diff --git a/lam-packaging/debian/copyright b/lam-packaging/debian/copyright index f8876244..548ed39e 100644 --- a/lam-packaging/debian/copyright +++ b/lam-packaging/debian/copyright @@ -87,7 +87,6 @@ The complete license can be found in the file COPYING or in Some parts of this package have other, compatible licences. These are: A: - DejaVu Fonts — License Fonts are © Bitstream (see below). DejaVu changes are in public domain. Explanation @@ -178,6 +177,7 @@ A: Software without prior written authorization from Tavmjong Bah. For further information, contact: tavmjong @ free . fr. + B: MIT License @@ -200,6 +200,7 @@ B: OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + C: New BSD License @@ -224,8 +225,8 @@ C: OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -D: +D: GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -392,6 +393,7 @@ D: permanent authorization for you to choose that version for the Library. + E: Duo @@ -418,6 +420,7 @@ E: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + F: 3-Clause BSD License @@ -446,6 +449,7 @@ F: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + G: 2-Clause BSD License @@ -471,42 +475,518 @@ G: POSSIBILITY OF SUCH DAMAGE. +H: + 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. + + + Programs and licenses with other licenses and/or authors than the main license and authors: -lib/3rdParty/composer/beberlei G 2013 Benjamin Eberlei -lib/3rdParty/composer/composer B Nils Adermann, Jordi Boggiano -lib/3rdParty/composer/fgrosse B 2015 Friedrich Große -lib/3rdParty/composer/nyholm B 2016 Tobias Nyholm -lib/3rdParty/composer/paragonie B 2015 Paragon Initiative Enterprises -lib/3rdParty/composer/php-http B 2015 PHP HTTP Team -lib/3rdParty/composer/psr B 2018 PHP Framework Interoperability Group -lib/3rdParty/composer/ramsey B 2018 Ben Ramsey -lib/3rdParty/composer/spomky-labs B 2018 Spomky-Labs -lib/3rdParty/composer/symfony B 2019 Fabien Potencier -lib/3rdParty/composer/web-auth B 2018 Spomky-Labs -lib/3rdParty/tcpdf D 2018 Nicola Asuni - Tecnick.com LTD -lib/3rdParty/tcpdf/fonts/DejaVu*.ttf A Public Domain, Bitstream, Inc., Tavmjong Bah -lib/3rdParty/tcpdf/fonts/DejaVu*.z A Public Domain, Bitstream, Inc., Tavmjong Bah -lib/3rdParty/phpseclib B 2019 TerraFrost and other contributors -lib/3rdParty/Monolog B 2011 Jordi Boggiano -lib/3rdParty/Psr B 2012 PHP Framework Interoperability Group -lib/3rdParty/yubico/Yubico.php C 2015 Yubico AB -templates/lib/*jquery*.js B 2018 jQuery Foundation and other contributors -style/120_jquery-ui*.css B 2016 jQuery Foundation and other contributors -templates/lib/*jquery-dropmenu-*.js B 2010 Fred Heusschen -style/150_jquery-dropmenu*.css B 2010 Fred Heusschen -templates/lib/*jquery-fineuploader-*.js B 2010 Andrew Valums -style/150_jquery-fineuploader*.css B 2010 Andrew Valums -templates/lib/*jquery-validationEngine-*.js B 2010 Cedric Dugas and Olivier Refalo -style/150_jquery-validationEngine*.css B 2010 Cedric Dugas and Olivier Refalo -templates/lib/extra/cropperjs B 2018 Chen Fengyuan -style/600_cropper*.css B 2018 Chen Fengyuan -templates/lib/extra/duo/*.js E 2019 Duo Security -lib/3rdParty/duo/*.php E 2019 Duo Security -graphics/webauthn.svg F 2017 Duo Security, Inc. -templates/lib/600_jquery.magnific-popup.js B 2016 Dmitry Semenov -style/610_magnific-popup.css B 2016 Dmitry Semenov -style/responsive/105_normalize.css B Nicolas Gallagher and Jonathan Neal -style/responsive/110_grid.css B +lib/3rdParty/composer/beberlei G 2013 Benjamin Eberlei +lib/3rdParty/composer/composer B Nils Adermann, Jordi Boggiano +lib/3rdParty/composer/fgrosse B 2015 Friedrich Große +lib/3rdParty/composer/nyholm B 2016 Tobias Nyholm +lib/3rdParty/composer/paragonie B 2015 Paragon Initiative Enterprises +lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna G +lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client H +lib/3rdParty/composer/pear-pear.horde.org/Horde_ListHeaders H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Mail G +lib/3rdParty/composer/pear-pear.horde.org/Horde_Mime H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Secret H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Socket_Client H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Stream H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Stream_Filter H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Stream_Wrapper G +lib/3rdParty/composer/pear-pear.horde.org/Horde_Support G +lib/3rdParty/composer/pear-pear.horde.org/Horde_Text_Flowed H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Translation H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Util H +lib/3rdParty/composer/php-http B 2015 PHP HTTP Team +lib/3rdParty/composer/psr B 2018 PHP Framework Interoperability Group +lib/3rdParty/composer/ramsey B 2018 Ben Ramsey +lib/3rdParty/composer/spomky-labs B 2018 Spomky-Labs +lib/3rdParty/composer/symfony B 2019 Fabien Potencier +lib/3rdParty/composer/web-auth B 2018 Spomky-Labs +lib/3rdParty/tcpdf D 2018 Nicola Asuni - Tecnick.com LTD +lib/3rdParty/tcpdf/fonts/DejaVu*.ttf A Public Domain, Bitstream, Inc., Tavmjong Bah +lib/3rdParty/tcpdf/fonts/DejaVu*.z A Public Domain, Bitstream, Inc., Tavmjong Bah +lib/3rdParty/phpseclib B 2019 TerraFrost and other contributors +lib/3rdParty/Monolog B 2011 Jordi Boggiano +lib/3rdParty/Psr B 2012 PHP Framework Interoperability Group +lib/3rdParty/yubico/Yubico.php C 2015 Yubico AB +templates/lib/*jquery*.js B 2018 jQuery Foundation and other contributors +style/120_jquery-ui*.css B 2016 jQuery Foundation and other contributors +templates/lib/*jquery-dropmenu-*.js B 2010 Fred Heusschen +style/150_jquery-dropmenu*.css B 2010 Fred Heusschen +templates/lib/*jquery-fineuploader-*.js B 2010 Andrew Valums +style/150_jquery-fineuploader*.css B 2010 Andrew Valums +templates/lib/*jquery-validationEngine-*.js B 2010 Cedric Dugas and Olivier Refalo +style/150_jquery-validationEngine*.css B 2010 Cedric Dugas and Olivier Refalo +templates/lib/extra/cropperjs B 2018 Chen Fengyuan +style/600_cropper*.css B 2018 Chen Fengyuan +templates/lib/extra/duo/*.js E 2019 Duo Security +lib/3rdParty/duo/*.php E 2019 Duo Security +graphics/webauthn.svg F 2017 Duo Security, Inc. +templates/lib/600_jquery.magnific-popup.js B 2016 Dmitry Semenov +style/610_magnific-popup.css B 2016 Dmitry Semenov +style/responsive/105_normalize.css B Nicolas Gallagher and Jonathan Neal +style/responsive/110_grid.css B diff --git a/lam/composer.json b/lam/composer.json index 68a77fea..fdfdceca 100644 --- a/lam/composer.json +++ b/lam/composer.json @@ -2,9 +2,16 @@ "config": { "vendor-dir": "lib/3rdParty/composer" }, + "repositories": [ + { + "type": "pear", + "url": "https://pear.horde.org" + } + ], "require" : { "web-auth/webauthn-lib" : "2.1.7", "symfony/http-foundation" : "5.0.0", - "symfony/psr-http-message-bridge" : "1.3.0" + "symfony/psr-http-message-bridge" : "1.3.0", + "pear-pear.horde.org/Horde_Imap_Client" : "2.30.1" } } \ No newline at end of file diff --git a/lam/composer.lock b/lam/composer.lock index 93f7d6d8..6d13eec2 100644 --- a/lam/composer.lock +++ b/lam/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ef5f7241f5ed768a1c63843aadbb54aa", + "content-hash": "faf0719c09b7ff85ee6e4adcc038afb7", "packages": [ { "name": "beberlei/assert", - "version": "v3.2.6", + "version": "v3.2.7", "source": { "type": "git", "url": "https://github.com/beberlei/assert.git", - "reference": "99508be011753690fe108ded450f5caaae180cfa" + "reference": "d63a6943fc4fd1a2aedb65994e3548715105abcf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/beberlei/assert/zipball/99508be011753690fe108ded450f5caaae180cfa", - "reference": "99508be011753690fe108ded450f5caaae180cfa", + "url": "https://api.github.com/repos/beberlei/assert/zipball/d63a6943fc4fd1a2aedb65994e3548715105abcf", + "reference": "d63a6943fc4fd1a2aedb65994e3548715105abcf", "shasum": "" }, "require": { @@ -66,7 +66,7 @@ "assertion", "validation" ], - "time": "2019-10-10T10:33:57+00:00" + "time": "2019-12-19T17:51:41+00:00" }, { "name": "fgrosse/phpasn1", @@ -244,6 +244,483 @@ ], "time": "2018-07-02T15:55:56+00:00" }, + { + "name": "pear-pear.horde.org/Horde_Crypt_Blowfish", + "version": "1.1.3", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Crypt_Blowfish-1.1.3.tgz" + }, + "require": { + "pear-pear.horde.org/horde_exception": "<3.0.0.0", + "pear-pear.horde.org/horde_support": "<3.0.0.0", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_crypt_blowfish": "== 1.1.3.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "LGPL-2.1" + ], + "description": "A library that provides blowfish encryption/decryption for PHP string data." + }, + { + "name": "pear-pear.horde.org/Horde_Exception", + "version": "2.0.8", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Exception-2.0.8.tgz" + }, + "require": { + "pear-pear.horde.org/horde_translation": "<3.0.0.0", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_exception": "== 2.0.8.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "LGPL-2.1" + ], + "description": "This class provides the default exception handlers for the Horde Application Framework." + }, + { + "name": "pear-pear.horde.org/Horde_Idna", + "version": "1.1.2", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Idna-1.1.2.tgz" + }, + "require": { + "pear-pear.horde.org/horde_exception": "<3.0.0.0", + "pear-pear.horde.org/horde_util": "<3.0.0.0", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_idna": "== 1.1.2.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "BSD-2-Clause" + ], + "description": "A library that wraps various backends providing IDNA (Internationalized Domain Names in Applications) support." + }, + { + "name": "pear-pear.horde.org/Horde_Imap_Client", + "version": "2.30.1", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Imap_Client-2.30.1.tgz" + }, + "require": { + "ext-hash": "*", + "ext-json": "*", + "pear-pear.horde.org/horde_exception": "<3.0.0.0", + "pear-pear.horde.org/horde_mail": "<3.0.0.0", + "pear-pear.horde.org/horde_mime": "<3.0.0.0", + "pear-pear.horde.org/horde_secret": "<3.0.0.0", + "pear-pear.horde.org/horde_socket_client": "<3.0.0.0", + "pear-pear.horde.org/horde_stream": "<2.0.0.0", + "pear-pear.horde.org/horde_stream_filter": "<3.0.0.0", + "pear-pear.horde.org/horde_translation": "<3.0.0.0", + "pear-pear.horde.org/horde_util": "<3.0.0.0", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_imap_client": "== 2.30.1.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "LGPL-2.1" + ], + "description": "A library to access IMAP4rev1 (RFC 3501) mail servers. Also supports connections to POP3 (STD 53/RFC 1939)." + }, + { + "name": "pear-pear.horde.org/Horde_ListHeaders", + "version": "1.2.5", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_ListHeaders-1.2.5.tgz" + }, + "require": { + "pear-pear.horde.org/horde_mail": "<3.0.0.0", + "pear-pear.horde.org/horde_translation": "<3.0.0.0", + "pear-pear.horde.org/horde_util": "<3.0.0.0", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_listheaders": "== 1.2.5.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "LGPL-2.1" + ], + "description": "The Horde_ListHeaders library parses Mailing List Headers as defined in RFC 2369 & RFC 2919." + }, + { + "name": "pear-pear.horde.org/Horde_Mail", + "version": "2.6.5", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Mail-2.6.5.tgz" + }, + "require": { + "pear-pear.horde.org/horde_exception": "<3.0.0.0", + "pear-pear.horde.org/horde_idna": "<2.0.0.0", + "pear-pear.horde.org/horde_mime": "<3.0.0.0", + "pear-pear.horde.org/horde_stream_filter": "<3.0.0.0", + "pear-pear.horde.org/horde_translation": "<3.0.0.0", + "pear-pear.horde.org/horde_util": "<3.0.0.0", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_mail": "== 2.6.5.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "BSD-2-Clause" + ], + "description": "Provides interfaces for sending e-mail messages and parsing e-mail addresses." + }, + { + "name": "pear-pear.horde.org/Horde_Mime", + "version": "2.11.0", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Mime-2.11.0.tgz" + }, + "require": { + "pear-pear.horde.org/horde_exception": "<3.0.0.0", + "pear-pear.horde.org/horde_listheaders": "<2.0.0.0", + "pear-pear.horde.org/horde_mail": "<3.0.0.0", + "pear-pear.horde.org/horde_stream": "<2.0.0.0", + "pear-pear.horde.org/horde_stream_filter": "<3.0.0.0", + "pear-pear.horde.org/horde_support": "<3.0.0.0", + "pear-pear.horde.org/horde_text_flowed": "<3.0.0.0", + "pear-pear.horde.org/horde_translation": "<3.0.0.0", + "pear-pear.horde.org/horde_util": "<3.0.0.0", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_mime": "== 2.11.0.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "LGPL-2.1" + ], + "description": "Provides methods for dealing with Multipurpose Internet Mail Extensions (MIME) features (RFC 2045/2046/2047)." + }, + { + "name": "pear-pear.horde.org/Horde_Secret", + "version": "2.0.6", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Secret-2.0.6.tgz" + }, + "require": { + "ext-hash": "*", + "pear-pear.horde.org/horde_crypt_blowfish": "<2.0.0.0", + "pear-pear.horde.org/horde_exception": "<3.0.0.0", + "pear-pear.horde.org/horde_support": "<3.0.0.0", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_secret": "== 2.0.6.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "LGPL-2.1" + ], + "description": "An API for encrypting and decrypting small pieces of data with the use of a shared key." + }, + { + "name": "pear-pear.horde.org/Horde_Socket_Client", + "version": "2.1.2", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Socket_Client-2.1.2.tgz" + }, + "require": { + "pear-pear.horde.org/horde_exception": "<3.0.0.0", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_socket_client": "== 2.1.2.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "LGPL-2.1" + ], + "description": "Provides abstract class for use in creating PHP network socket clients." + }, + { + "name": "pear-pear.horde.org/Horde_Stream", + "version": "1.6.3", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Stream-1.6.3.tgz" + }, + "require": { + "pear-pear.horde.org/horde_exception": "<3.0.0.0", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_stream": "== 1.6.3.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "LGPL-2.1" + ], + "description": "An object-oriented interface to assist in creating and storing PHP stream resources, and to provide utility methods to access and manipulate the stream contents." + }, + { + "name": "pear-pear.horde.org/Horde_Stream_Filter", + "version": "2.0.4", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Stream_Filter-2.0.4.tgz" + }, + "require": { + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_stream_filter": "== 2.0.4.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "LGPL-2.1" + ], + "description": "A collection of various stream filters." + }, + { + "name": "pear-pear.horde.org/Horde_Stream_Wrapper", + "version": "2.1.4", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Stream_Wrapper-2.1.4.tgz" + }, + "require": { + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_stream_wrapper": "== 2.1.4.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "BSD-2-Clause" + ], + "description": "A collection of stream wrappers." + }, + { + "name": "pear-pear.horde.org/Horde_Support", + "version": "2.2.0", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Support-2.2.0.tgz" + }, + "require": { + "pear-pear.horde.org/horde_exception": "<3.0.0.0", + "pear-pear.horde.org/horde_stream_wrapper": "<3.0.0.0", + "pear-pear.horde.org/horde_util": "<3.0.0.0", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_support": "== 2.2.0.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "BSD-2-Clause" + ], + "description": "Support classes not tied to Horde but is used by it. These classes can be used outside of Horde as well." + }, + { + "name": "pear-pear.horde.org/Horde_Text_Flowed", + "version": "2.0.4", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Text_Flowed-2.0.4.tgz" + }, + "require": { + "pear-pear.horde.org/horde_util": "<3.0.0.0", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_text_flowed": "== 2.0.4.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "LGPL-2.1" + ], + "description": "A library that provides common methods for manipulating text using the encoding described in RFC 3676 ('flowed' text)." + }, + { + "name": "pear-pear.horde.org/Horde_Translation", + "version": "2.2.2", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Translation-2.2.2.tgz" + }, + "require": { + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_translation": "== 2.2.2.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "LGPL-2.1" + ], + "description": "Translation wrappers." + }, + { + "name": "pear-pear.horde.org/Horde_Util", + "version": "2.5.9", + "dist": { + "type": "file", + "url": "https://pear.horde.org/get/Horde_Util-2.5.9.tgz" + }, + "require": { + "ext-dom": "*", + "php": "<8.0.0.0" + }, + "replace": { + "pear-horde/horde_util": "== 2.5.9.0" + }, + "type": "pear-library", + "autoload": { + "classmap": [ + "" + ] + }, + "include-path": [ + "/" + ], + "license": [ + "LGPL-2.1" + ], + "description": "A library that provides functionality useful for all kind of applications." + }, { "name": "php-http/message-factory", "version": "v1.0.2", @@ -447,44 +924,46 @@ }, { "name": "ramsey/uuid", - "version": "3.8.0", + "version": "3.9.2", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "d09ea80159c1929d75b3f9c60504d613aeb4a1e3" + "reference": "7779489a47d443f845271badbdcedfe4df8e06fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/d09ea80159c1929d75b3f9c60504d613aeb4a1e3", - "reference": "d09ea80159c1929d75b3f9c60504d613aeb4a1e3", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/7779489a47d443f845271badbdcedfe4df8e06fb", + "reference": "7779489a47d443f845271badbdcedfe4df8e06fb", "shasum": "" }, "require": { - "paragonie/random_compat": "^1.0|^2.0|9.99.99", - "php": "^5.4 || ^7.0", + "ext-json": "*", + "paragonie/random_compat": "^1 | ^2 | 9.99.99", + "php": "^5.4 | ^7 | ^8", "symfony/polyfill-ctype": "^1.8" }, "replace": { "rhumsaa/uuid": "self.version" }, "require-dev": { - "codeception/aspect-mock": "^1.0 | ~2.0.0", - "doctrine/annotations": "~1.2.0", - "goaop/framework": "1.0.0-alpha.2 | ^1.0 | ~2.1.0", - "ircmaxell/random-lib": "^1.1", - "jakub-onderka/php-parallel-lint": "^0.9.0", - "mockery/mockery": "^0.9.9", + "codeception/aspect-mock": "^1 | ^2", + "doctrine/annotations": "^1.2", + "goaop/framework": "1.0.0-alpha.2 | ^1 | ^2.1", + "jakub-onderka/php-parallel-lint": "^1", + "mockery/mockery": "^0.9.11 | ^1", "moontoast/math": "^1.1", - "php-mock/php-mock-phpunit": "^0.3|^1.1", - "phpunit/phpunit": "^4.7|^5.0|^6.5", - "squizlabs/php_codesniffer": "^2.3" + "paragonie/random-lib": "^2", + "php-mock/php-mock-phpunit": "^0.3 | ^1.1", + "phpunit/phpunit": "^4.8 | ^5.4 | ^6.5", + "squizlabs/php_codesniffer": "^3.5" }, "suggest": { "ext-ctype": "Provides support for PHP Ctype functions", "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator", + "ext-openssl": "Provides the OpenSSL extension for use with the OpenSslGenerator", "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator", - "ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter", "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid", "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." }, @@ -497,13 +976,21 @@ "autoload": { "psr-4": { "Ramsey\\Uuid\\": "src/" - } + }, + "files": [ + "src/functions.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + }, { "name": "Marijn Huizendveld", "email": "marijn.huizendveld@gmail.com" @@ -511,11 +998,6 @@ { "name": "Thibaud Fabre", "email": "thibaud@aztech.io" - }, - { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" } ], "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", @@ -525,7 +1007,7 @@ "identifier", "uuid" ], - "time": "2018-07-19T23:38:55+00:00" + "time": "2019-12-17T08:18:51+00:00" }, { "name": "spomky-labs/base64url", @@ -702,16 +1184,16 @@ }, { "name": "symfony/mime", - "version": "v5.0.0", + "version": "v5.0.4", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "76f3c09b7382bf979af7bcd8e6f8033f1324285e" + "reference": "2a3c7fee1f1a0961fa9cf360d5da553d05095e59" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/76f3c09b7382bf979af7bcd8e6f8033f1324285e", - "reference": "76f3c09b7382bf979af7bcd8e6f8033f1324285e", + "url": "https://api.github.com/repos/symfony/mime/zipball/2a3c7fee1f1a0961fa9cf360d5da553d05095e59", + "reference": "2a3c7fee1f1a0961fa9cf360d5da553d05095e59", "shasum": "" }, "require": { @@ -760,7 +1242,7 @@ "mime", "mime-type" ], - "time": "2019-11-18T17:27:11+00:00" + "time": "2020-01-04T14:08:26+00:00" }, { "name": "symfony/polyfill-ctype", diff --git a/lam/copyright b/lam/copyright index 9679a9f8..42b75396 100644 --- a/lam/copyright +++ b/lam/copyright @@ -86,7 +86,6 @@ The complete license can be found in the file COPYING. Some parts of this package have other, compatible licences. These are: A: - DejaVu Fonts — License Fonts are © Bitstream (see below). DejaVu changes are in public domain. Explanation @@ -177,6 +176,7 @@ A: Software without prior written authorization from Tavmjong Bah. For further information, contact: tavmjong @ free . fr. + B: MIT License @@ -199,6 +199,7 @@ B: OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + C: New BSD License @@ -223,8 +224,8 @@ C: OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -D: +D: GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -391,6 +392,7 @@ D: permanent authorization for you to choose that version for the Library. + E: Duo @@ -417,6 +419,7 @@ E: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + F: 3-Clause BSD License @@ -445,6 +448,7 @@ F: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + G: 2-Clause BSD License @@ -470,42 +474,518 @@ G: POSSIBILITY OF SUCH DAMAGE. +H: + 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. + + + Programs and licenses with other licenses and/or authors than the main license and authors: -lib/3rdParty/composer/beberlei G 2013 Benjamin Eberlei -lib/3rdParty/composer/composer B Nils Adermann, Jordi Boggiano -lib/3rdParty/composer/fgrosse B 2015 Friedrich Große -lib/3rdParty/composer/nyholm B 2016 Tobias Nyholm -lib/3rdParty/composer/paragonie B 2015 Paragon Initiative Enterprises -lib/3rdParty/composer/php-http B 2015 PHP HTTP Team -lib/3rdParty/composer/psr B 2018 PHP Framework Interoperability Group -lib/3rdParty/composer/ramsey B 2018 Ben Ramsey -lib/3rdParty/composer/spomky-labs B 2018 Spomky-Labs -lib/3rdParty/composer/symfony B 2019 Fabien Potencier -lib/3rdParty/composer/web-auth B 2018 Spomky-Labs -lib/3rdParty/tcpdf D 2018 Nicola Asuni - Tecnick.com LTD -lib/3rdParty/tcpdf/fonts/DejaVu*.ttf A Public Domain, Bitstream, Inc., Tavmjong Bah -lib/3rdParty/tcpdf/fonts/DejaVu*.z A Public Domain, Bitstream, Inc., Tavmjong Bah -lib/3rdParty/phpseclib B 2019 TerraFrost and other contributors -lib/3rdParty/Monolog B 2011 Jordi Boggiano -lib/3rdParty/Psr B 2012 PHP Framework Interoperability Group -lib/3rdParty/yubico/Yubico.php C 2015 Yubico AB -templates/lib/*jquery*.js B 2018 jQuery Foundation and other contributors -style/120_jquery-ui*.css B 2016 jQuery Foundation and other contributors -templates/lib/*jquery-dropmenu-*.js B 2010 Fred Heusschen -style/150_jquery-dropmenu*.css B 2010 Fred Heusschen -templates/lib/*jquery-fineuploader-*.js B 2010 Andrew Valums -style/150_jquery-fineuploader*.css B 2010 Andrew Valums -templates/lib/*jquery-validationEngine-*.js B 2010 Cedric Dugas and Olivier Refalo -style/150_jquery-validationEngine*.css B 2010 Cedric Dugas and Olivier Refalo -templates/lib/extra/cropperjs B 2018 Chen Fengyuan -style/600_cropper*.css B 2018 Chen Fengyuan -templates/lib/extra/duo/*.js E 2019 Duo Security -lib/3rdParty/duo/*.php E 2019 Duo Security -graphics/webauthn.svg F 2017 Duo Security, Inc. -templates/lib/600_jquery.magnific-popup.js B 2016 Dmitry Semenov -style/610_magnific-popup.css B 2016 Dmitry Semenov -style/responsive/105_normalize.css B Nicolas Gallagher and Jonathan Neal -style/responsive/110_grid.css B +lib/3rdParty/composer/beberlei G 2013 Benjamin Eberlei +lib/3rdParty/composer/composer B Nils Adermann, Jordi Boggiano +lib/3rdParty/composer/fgrosse B 2015 Friedrich Große +lib/3rdParty/composer/nyholm B 2016 Tobias Nyholm +lib/3rdParty/composer/paragonie B 2015 Paragon Initiative Enterprises +lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna G +lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client H +lib/3rdParty/composer/pear-pear.horde.org/Horde_ListHeaders H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Mail G +lib/3rdParty/composer/pear-pear.horde.org/Horde_Mime H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Secret H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Socket_Client H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Stream H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Stream_Filter H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Stream_Wrapper G +lib/3rdParty/composer/pear-pear.horde.org/Horde_Support G +lib/3rdParty/composer/pear-pear.horde.org/Horde_Text_Flowed H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Translation H +lib/3rdParty/composer/pear-pear.horde.org/Horde_Util H +lib/3rdParty/composer/php-http B 2015 PHP HTTP Team +lib/3rdParty/composer/psr B 2018 PHP Framework Interoperability Group +lib/3rdParty/composer/ramsey B 2018 Ben Ramsey +lib/3rdParty/composer/spomky-labs B 2018 Spomky-Labs +lib/3rdParty/composer/symfony B 2019 Fabien Potencier +lib/3rdParty/composer/web-auth B 2018 Spomky-Labs +lib/3rdParty/tcpdf D 2018 Nicola Asuni - Tecnick.com LTD +lib/3rdParty/tcpdf/fonts/DejaVu*.ttf A Public Domain, Bitstream, Inc., Tavmjong Bah +lib/3rdParty/tcpdf/fonts/DejaVu*.z A Public Domain, Bitstream, Inc., Tavmjong Bah +lib/3rdParty/phpseclib B 2019 TerraFrost and other contributors +lib/3rdParty/Monolog B 2011 Jordi Boggiano +lib/3rdParty/Psr B 2012 PHP Framework Interoperability Group +lib/3rdParty/yubico/Yubico.php C 2015 Yubico AB +templates/lib/*jquery*.js B 2018 jQuery Foundation and other contributors +style/120_jquery-ui*.css B 2016 jQuery Foundation and other contributors +templates/lib/*jquery-dropmenu-*.js B 2010 Fred Heusschen +style/150_jquery-dropmenu*.css B 2010 Fred Heusschen +templates/lib/*jquery-fineuploader-*.js B 2010 Andrew Valums +style/150_jquery-fineuploader*.css B 2010 Andrew Valums +templates/lib/*jquery-validationEngine-*.js B 2010 Cedric Dugas and Olivier Refalo +style/150_jquery-validationEngine*.css B 2010 Cedric Dugas and Olivier Refalo +templates/lib/extra/cropperjs B 2018 Chen Fengyuan +style/600_cropper*.css B 2018 Chen Fengyuan +templates/lib/extra/duo/*.js E 2019 Duo Security +lib/3rdParty/duo/*.php E 2019 Duo Security +graphics/webauthn.svg F 2017 Duo Security, Inc. +templates/lib/600_jquery.magnific-popup.js B 2016 Dmitry Semenov +style/610_magnific-popup.css B 2016 Dmitry Semenov +style/responsive/105_normalize.css B Nicolas Gallagher and Jonathan Neal +style/responsive/110_grid.css B diff --git a/lam/lib/3rdParty/composer/beberlei/assert/lib/Assert/LazyAssertion.php b/lam/lib/3rdParty/composer/beberlei/assert/lib/Assert/LazyAssertion.php index c032911a..6ccd6423 100644 --- a/lam/lib/3rdParty/composer/beberlei/assert/lib/Assert/LazyAssertion.php +++ b/lam/lib/3rdParty/composer/beberlei/assert/lib/Assert/LazyAssertion.php @@ -21,96 +21,96 @@ use LogicException; * * @author Benjamin Eberlei * - * @method static static alnum(string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric. - * @method static static base64(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined. - * @method static static between(mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit. - * @method static static betweenExclusive(mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit. - * @method static static betweenLength(int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths. - * @method static static boolean(string|callable $message = null, string $propertyPath = null) Assert that value is php boolean. - * @method static static choice(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. - * @method static static choicesNotEmpty(array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content. - * @method static static classExists(string|callable $message = null, string $propertyPath = null) Assert that the class exists. - * @method static static contains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars. - * @method static static count(int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count. - * @method static static date(string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format. - * @method static static defined(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined. - * @method static static digit(string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit. - * @method static static directory(string|callable $message = null, string $propertyPath = null) Assert that a directory exists. - * @method static static e164(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number. - * @method static static email(string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL). - * @method static static endsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars. - * @method static static eq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using ==). - * @method static static eqArraySubset(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that the array contains the subset. - * @method static static extensionLoaded(string|callable $message = null, string $propertyPath = null) Assert that extension is loaded. - * @method static static extensionVersion(string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed. - * @method static static false(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False. - * @method static static file(string|callable $message = null, string $propertyPath = null) Assert that a file exists. - * @method static static float(string|callable $message = null, string $propertyPath = null) Assert that value is a php float. - * @method static static greaterOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit. - * @method static static greaterThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit. - * @method static static implementsInterface(string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface. - * @method static static inArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice(). - * @method static static integer(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer. - * @method static static integerish(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish. - * @method static static interfaceExists(string|callable $message = null, string $propertyPath = null) Assert that the interface exists. - * @method static static ip(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address. - * @method static static ipv4(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address. - * @method static static ipv6(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address. - * @method static static isArray(string|callable $message = null, string $propertyPath = null) Assert that value is an array. - * @method static static isArrayAccessible(string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object. - * @method static static isCallable(string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable. - * @method static static isCountable(string|callable $message = null, string $propertyPath = null) Assert that value is countable. - * @method static static isInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name. - * @method static static isJsonString(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string. - * @method static static isObject(string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object. - * @method static static isResource(string|callable $message = null, string $propertyPath = null) Assert that value is a resource. - * @method static static isTraversable(string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object. - * @method static static keyExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array. - * @method static static keyIsset(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset(). - * @method static static keyNotExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array. - * @method static static length(int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length. - * @method static static lessOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit. - * @method static static lessThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit. - * @method static static max(mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit. - * @method static static maxCount(int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at most $count elements. - * @method static static maxLength(int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars. - * @method static static methodExists(mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object. - * @method static static min(mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit. - * @method static static minCount(int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at least $count elements. - * @method static static minLength(int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long. - * @method static static noContent(string|callable $message = null, string $propertyPath = null) Assert that value is empty. - * @method static static notBlank(string|callable $message = null, string $propertyPath = null) Assert that value is not blank. - * @method static static notContains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string does not contains a sequence of chars. - * @method static static notEmpty(string|callable $message = null, string $propertyPath = null) Assert that value is not empty. - * @method static static notEmptyKey(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty. - * @method static static notEq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using ==). - * @method static static notInArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices. - * @method static static notIsInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name. - * @method static static notNull(string|callable $message = null, string $propertyPath = null) Assert that value is not null. - * @method static static notRegex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value does not match a regex. - * @method static static notSame(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using ===). - * @method static static null(string|callable $message = null, string $propertyPath = null) Assert that value is null. - * @method static static numeric(string|callable $message = null, string $propertyPath = null) Assert that value is numeric. - * @method static static objectOrClass(string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists. - * @method static static phpVersion(mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version. - * @method static static propertiesExist(array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist. - * @method static static propertyExists(string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists. - * @method static static range(mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers. - * @method static static readable(string|callable $message = null, string $propertyPath = null) Assert that the value is something readable. - * @method static static regex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex. - * @method static static same(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===). - * @method static static satisfy(callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback. - * @method static static scalar(string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar. - * @method static static startsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars. - * @method static static string(string|callable $message = null, string $propertyPath = null) Assert that value is a string. - * @method static static subclassOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name. - * @method static static true(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True. - * @method static static url(string|callable $message = null, string $propertyPath = null) Assert that value is an URL. - * @method static static uuid(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID. - * @method static static version(string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions. - * @method static static writeable(string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable. - * @method static static all() Switch chain into validation mode for an array of values. - * @method static static nullOr() Switch chain into mode allowing nulls, ignoring further assertions. + * @method LazyAssertion alnum(string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric. + * @method LazyAssertion base64(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined. + * @method LazyAssertion between(mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit. + * @method LazyAssertion betweenExclusive(mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit. + * @method LazyAssertion betweenLength(int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths. + * @method LazyAssertion boolean(string|callable $message = null, string $propertyPath = null) Assert that value is php boolean. + * @method LazyAssertion choice(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. + * @method LazyAssertion choicesNotEmpty(array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content. + * @method LazyAssertion classExists(string|callable $message = null, string $propertyPath = null) Assert that the class exists. + * @method LazyAssertion contains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars. + * @method LazyAssertion count(int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count. + * @method LazyAssertion date(string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format. + * @method LazyAssertion defined(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined. + * @method LazyAssertion digit(string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit. + * @method LazyAssertion directory(string|callable $message = null, string $propertyPath = null) Assert that a directory exists. + * @method LazyAssertion e164(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number. + * @method LazyAssertion email(string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL). + * @method LazyAssertion endsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars. + * @method LazyAssertion eq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using ==). + * @method LazyAssertion eqArraySubset(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that the array contains the subset. + * @method LazyAssertion extensionLoaded(string|callable $message = null, string $propertyPath = null) Assert that extension is loaded. + * @method LazyAssertion extensionVersion(string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed. + * @method LazyAssertion false(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False. + * @method LazyAssertion file(string|callable $message = null, string $propertyPath = null) Assert that a file exists. + * @method LazyAssertion float(string|callable $message = null, string $propertyPath = null) Assert that value is a php float. + * @method LazyAssertion greaterOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit. + * @method LazyAssertion greaterThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit. + * @method LazyAssertion implementsInterface(string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface. + * @method LazyAssertion inArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice(). + * @method LazyAssertion integer(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer. + * @method LazyAssertion integerish(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish. + * @method LazyAssertion interfaceExists(string|callable $message = null, string $propertyPath = null) Assert that the interface exists. + * @method LazyAssertion ip(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address. + * @method LazyAssertion ipv4(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address. + * @method LazyAssertion ipv6(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address. + * @method LazyAssertion isArray(string|callable $message = null, string $propertyPath = null) Assert that value is an array. + * @method LazyAssertion isArrayAccessible(string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object. + * @method LazyAssertion isCallable(string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable. + * @method LazyAssertion isCountable(string|callable $message = null, string $propertyPath = null) Assert that value is countable. + * @method LazyAssertion isInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name. + * @method LazyAssertion isJsonString(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string. + * @method LazyAssertion isObject(string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object. + * @method LazyAssertion isResource(string|callable $message = null, string $propertyPath = null) Assert that value is a resource. + * @method LazyAssertion isTraversable(string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object. + * @method LazyAssertion keyExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array. + * @method LazyAssertion keyIsset(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset(). + * @method LazyAssertion keyNotExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array. + * @method LazyAssertion length(int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length. + * @method LazyAssertion lessOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit. + * @method LazyAssertion lessThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit. + * @method LazyAssertion max(mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit. + * @method LazyAssertion maxCount(int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at most $count elements. + * @method LazyAssertion maxLength(int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars. + * @method LazyAssertion methodExists(mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object. + * @method LazyAssertion min(mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit. + * @method LazyAssertion minCount(int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at least $count elements. + * @method LazyAssertion minLength(int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long. + * @method LazyAssertion noContent(string|callable $message = null, string $propertyPath = null) Assert that value is empty. + * @method LazyAssertion notBlank(string|callable $message = null, string $propertyPath = null) Assert that value is not blank. + * @method LazyAssertion notContains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string does not contains a sequence of chars. + * @method LazyAssertion notEmpty(string|callable $message = null, string $propertyPath = null) Assert that value is not empty. + * @method LazyAssertion notEmptyKey(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty. + * @method LazyAssertion notEq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using ==). + * @method LazyAssertion notInArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices. + * @method LazyAssertion notIsInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name. + * @method LazyAssertion notNull(string|callable $message = null, string $propertyPath = null) Assert that value is not null. + * @method LazyAssertion notRegex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value does not match a regex. + * @method LazyAssertion notSame(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using ===). + * @method LazyAssertion null(string|callable $message = null, string $propertyPath = null) Assert that value is null. + * @method LazyAssertion numeric(string|callable $message = null, string $propertyPath = null) Assert that value is numeric. + * @method LazyAssertion objectOrClass(string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists. + * @method LazyAssertion phpVersion(mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version. + * @method LazyAssertion propertiesExist(array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist. + * @method LazyAssertion propertyExists(string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists. + * @method LazyAssertion range(mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers. + * @method LazyAssertion readable(string|callable $message = null, string $propertyPath = null) Assert that the value is something readable. + * @method LazyAssertion regex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex. + * @method LazyAssertion same(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===). + * @method LazyAssertion satisfy(callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback. + * @method LazyAssertion scalar(string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar. + * @method LazyAssertion startsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars. + * @method LazyAssertion string(string|callable $message = null, string $propertyPath = null) Assert that value is a string. + * @method LazyAssertion subclassOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name. + * @method LazyAssertion true(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True. + * @method LazyAssertion url(string|callable $message = null, string $propertyPath = null) Assert that value is an URL. + * @method LazyAssertion uuid(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID. + * @method LazyAssertion version(string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions. + * @method LazyAssertion writeable(string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable. + * @method LazyAssertion all() Switch chain into validation mode for an array of values. + * @method LazyAssertion nullOr() Switch chain into mode allowing nulls, ignoring further assertions. */ class LazyAssertion { diff --git a/lam/lib/3rdParty/composer/composer/autoload_classmap.php b/lam/lib/3rdParty/composer/composer/autoload_classmap.php index 024622f7..af12d2d6 100644 --- a/lam/lib/3rdParty/composer/composer/autoload_classmap.php +++ b/lam/lib/3rdParty/composer/composer/autoload_classmap.php @@ -6,4 +6,234 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname(dirname(dirname($vendorDir))); return array( + 'HordeImapClientBaseTables' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/data/migration/1_horde_imap_client_base_tables.php', + 'HordeImapClientChangeColumnName' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/data/migration/2_horde_imap_client_change_column_name.php', + 'Horde\\Socket\\Client' => $vendorDir . '/pear-pear.horde.org/Horde_Socket_Client/Horde/Socket/Client.php', + 'Horde\\Socket\\Client\\Exception' => $vendorDir . '/pear-pear.horde.org/Horde_Socket_Client/Horde/Socket/Client/Exception.php', + 'Horde_Array' => $vendorDir . '/pear-pear.horde.org/Horde_Util/Horde/Array.php', + 'Horde_Array_Sort_Helper' => $vendorDir . '/pear-pear.horde.org/Horde_Util/Horde/Array/Sort/Helper.php', + 'Horde_Crypt_Blowfish' => $vendorDir . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish.php', + 'Horde_Crypt_Blowfish_Base' => $vendorDir . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Base.php', + 'Horde_Crypt_Blowfish_Exception' => $vendorDir . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Exception.php', + 'Horde_Crypt_Blowfish_Mcrypt' => $vendorDir . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Mcrypt.php', + 'Horde_Crypt_Blowfish_Openssl' => $vendorDir . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Openssl.php', + 'Horde_Crypt_Blowfish_Pbkdf2' => $vendorDir . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Pbkdf2.php', + 'Horde_Crypt_Blowfish_Php' => $vendorDir . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php.php', + 'Horde_Crypt_Blowfish_Php_Base' => $vendorDir . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Base.php', + 'Horde_Crypt_Blowfish_Php_Cbc' => $vendorDir . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Cbc.php', + 'Horde_Crypt_Blowfish_Php_Ecb' => $vendorDir . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Ecb.php', + 'Horde_Domhtml' => $vendorDir . '/pear-pear.horde.org/Horde_Util/Horde/Domhtml.php', + 'Horde_Exception' => $vendorDir . '/pear-pear.horde.org/Horde_Exception/Horde/Exception.php', + 'Horde_Exception_LastError' => $vendorDir . '/pear-pear.horde.org/Horde_Exception/Horde/Exception/LastError.php', + 'Horde_Exception_NotFound' => $vendorDir . '/pear-pear.horde.org/Horde_Exception/Horde/Exception/NotFound.php', + 'Horde_Exception_Pear' => $vendorDir . '/pear-pear.horde.org/Horde_Exception/Horde/Exception/Pear.php', + 'Horde_Exception_PermissionDenied' => $vendorDir . '/pear-pear.horde.org/Horde_Exception/Horde/Exception/PermissionDenied.php', + 'Horde_Exception_Translation' => $vendorDir . '/pear-pear.horde.org/Horde_Exception/Horde/Exception/Translation.php', + 'Horde_Exception_Wrapped' => $vendorDir . '/pear-pear.horde.org/Horde_Exception/Horde/Exception/Wrapped.php', + 'Horde_Idna' => $vendorDir . '/pear-pear.horde.org/Horde_Idna/Horde/Idna.php', + 'Horde_Idna_Exception' => $vendorDir . '/pear-pear.horde.org/Horde_Idna/Horde/Idna/Exception.php', + 'Horde_Idna_Punycode' => $vendorDir . '/pear-pear.horde.org/Horde_Idna/Horde/Idna/Punycode.php', + 'Horde_Idna_Translation' => $vendorDir . '/pear-pear.horde.org/Horde_Idna/Horde/Idna/Translation.php', + 'Horde_Imap_Client' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client.php', + 'Horde_Imap_Client_Auth_DigestMD5' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Auth/DigestMD5.php', + 'Horde_Imap_Client_Auth_Scram' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Auth/Scram.php', + 'Horde_Imap_Client_Base' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base.php', + 'Horde_Imap_Client_Base_Alerts' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Alerts.php', + 'Horde_Imap_Client_Base_Debug' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Debug.php', + 'Horde_Imap_Client_Base_Deprecated' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Deprecated.php', + 'Horde_Imap_Client_Base_Mailbox' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Mailbox.php', + 'Horde_Imap_Client_Base_Password' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Password.php', + 'Horde_Imap_Client_Cache' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache.php', + 'Horde_Imap_Client_Cache_Backend' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend.php', + 'Horde_Imap_Client_Cache_Backend_Cache' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Cache.php', + 'Horde_Imap_Client_Cache_Backend_Db' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Db.php', + 'Horde_Imap_Client_Cache_Backend_Hashtable' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Hashtable.php', + 'Horde_Imap_Client_Cache_Backend_Mongo' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Mongo.php', + 'Horde_Imap_Client_Cache_Backend_Null' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Null.php', + 'Horde_Imap_Client_Data_Acl' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Acl.php', + 'Horde_Imap_Client_Data_AclCommon' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclCommon.php', + 'Horde_Imap_Client_Data_AclNegative' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclNegative.php', + 'Horde_Imap_Client_Data_AclRights' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclRights.php', + 'Horde_Imap_Client_Data_BaseSubject' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/BaseSubject.php', + 'Horde_Imap_Client_Data_Capability' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Capability.php', + 'Horde_Imap_Client_Data_Capability_Imap' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Capability/Imap.php', + 'Horde_Imap_Client_Data_Envelope' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Envelope.php', + 'Horde_Imap_Client_Data_Fetch' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Fetch.php', + 'Horde_Imap_Client_Data_Fetch_Pop3' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Fetch/Pop3.php', + 'Horde_Imap_Client_Data_Format' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format.php', + 'Horde_Imap_Client_Data_Format_Astring' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Astring.php', + 'Horde_Imap_Client_Data_Format_Astring_Nonascii' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Astring/Nonascii.php', + 'Horde_Imap_Client_Data_Format_Atom' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Atom.php', + 'Horde_Imap_Client_Data_Format_Date' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Date.php', + 'Horde_Imap_Client_Data_Format_DateTime' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/DateTime.php', + 'Horde_Imap_Client_Data_Format_Exception' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Exception.php', + 'Horde_Imap_Client_Data_Format_Filter_Quote' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Filter/Quote.php', + 'Horde_Imap_Client_Data_Format_Filter_String' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Filter/String.php', + 'Horde_Imap_Client_Data_Format_List' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/List.php', + 'Horde_Imap_Client_Data_Format_ListMailbox' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/ListMailbox.php', + 'Horde_Imap_Client_Data_Format_ListMailbox_Utf8' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/ListMailbox/Utf8.php', + 'Horde_Imap_Client_Data_Format_Mailbox' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Mailbox.php', + 'Horde_Imap_Client_Data_Format_Mailbox_Utf8' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Mailbox/Utf8.php', + 'Horde_Imap_Client_Data_Format_Nil' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nil.php', + 'Horde_Imap_Client_Data_Format_Nstring' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nstring.php', + 'Horde_Imap_Client_Data_Format_Nstring_Nonascii' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nstring/Nonascii.php', + 'Horde_Imap_Client_Data_Format_Number' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Number.php', + 'Horde_Imap_Client_Data_Format_String' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String.php', + 'Horde_Imap_Client_Data_Format_String_Nonascii' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String/Nonascii.php', + 'Horde_Imap_Client_Data_Format_String_Support_Nonascii' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String/Support/Nonascii.php', + 'Horde_Imap_Client_Data_Namespace' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Namespace.php', + 'Horde_Imap_Client_Data_SearchCharset' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/SearchCharset.php', + 'Horde_Imap_Client_Data_SearchCharset_Utf8' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/SearchCharset/Utf8.php', + 'Horde_Imap_Client_Data_Sync' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Sync.php', + 'Horde_Imap_Client_Data_Thread' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Thread.php', + 'Horde_Imap_Client_DateTime' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/DateTime.php', + 'Horde_Imap_Client_Exception' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception.php', + 'Horde_Imap_Client_Exception_NoSupportExtension' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/NoSupportExtension.php', + 'Horde_Imap_Client_Exception_NoSupportPop3' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/NoSupportPop3.php', + 'Horde_Imap_Client_Exception_SearchCharset' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/SearchCharset.php', + 'Horde_Imap_Client_Exception_ServerResponse' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/ServerResponse.php', + 'Horde_Imap_Client_Exception_Sync' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/Sync.php', + 'Horde_Imap_Client_Fetch_Query' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Fetch/Query.php', + 'Horde_Imap_Client_Fetch_Results' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Fetch/Results.php', + 'Horde_Imap_Client_Ids' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids.php', + 'Horde_Imap_Client_Ids_Map' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids/Map.php', + 'Horde_Imap_Client_Ids_Pop3' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids/Pop3.php', + 'Horde_Imap_Client_Interaction_Client' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Client.php', + 'Horde_Imap_Client_Interaction_Command' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Command.php', + 'Horde_Imap_Client_Interaction_Command_Continuation' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Command/Continuation.php', + 'Horde_Imap_Client_Interaction_Pipeline' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Pipeline.php', + 'Horde_Imap_Client_Interaction_Server' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server.php', + 'Horde_Imap_Client_Interaction_Server_Continuation' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Continuation.php', + 'Horde_Imap_Client_Interaction_Server_Tagged' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Tagged.php', + 'Horde_Imap_Client_Interaction_Server_Untagged' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Untagged.php', + 'Horde_Imap_Client_Mailbox' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Mailbox.php', + 'Horde_Imap_Client_Mailbox_List' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Mailbox/List.php', + 'Horde_Imap_Client_Namespace_List' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Namespace/List.php', + 'Horde_Imap_Client_Password_Xoauth2' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Password/Xoauth2.php', + 'Horde_Imap_Client_Search_Query' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Search/Query.php', + 'Horde_Imap_Client_Socket' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket.php', + 'Horde_Imap_Client_Socket_Catenate' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/Catenate.php', + 'Horde_Imap_Client_Socket_ClientSort' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/ClientSort.php', + 'Horde_Imap_Client_Socket_Connection_Base' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/Connection/Base.php', + 'Horde_Imap_Client_Socket_Connection_Pop3' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/Connection/Pop3.php', + 'Horde_Imap_Client_Socket_Connection_Socket' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/Connection/Socket.php', + 'Horde_Imap_Client_Socket_Pop3' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/Pop3.php', + 'Horde_Imap_Client_Tokenize' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Tokenize.php', + 'Horde_Imap_Client_Translation' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Translation.php', + 'Horde_Imap_Client_Url' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Url.php', + 'Horde_Imap_Client_Url_Base' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Url/Base.php', + 'Horde_Imap_Client_Url_Imap' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Url/Imap.php', + 'Horde_Imap_Client_Url_Imap_Relative' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Url/Imap/Relative.php', + 'Horde_Imap_Client_Url_Pop3' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Url/Pop3.php', + 'Horde_Imap_Client_Utf7imap' => $vendorDir . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Utf7imap.php', + 'Horde_ListHeaders' => $vendorDir . '/pear-pear.horde.org/Horde_ListHeaders/Horde/ListHeaders.php', + 'Horde_ListHeaders_Base' => $vendorDir . '/pear-pear.horde.org/Horde_ListHeaders/Horde/ListHeaders/Base.php', + 'Horde_ListHeaders_Id' => $vendorDir . '/pear-pear.horde.org/Horde_ListHeaders/Horde/ListHeaders/Id.php', + 'Horde_ListHeaders_NoPost' => $vendorDir . '/pear-pear.horde.org/Horde_ListHeaders/Horde/ListHeaders/NoPost.php', + 'Horde_ListHeaders_Object' => $vendorDir . '/pear-pear.horde.org/Horde_ListHeaders/Horde/ListHeaders/Object.php', + 'Horde_ListHeaders_Translation' => $vendorDir . '/pear-pear.horde.org/Horde_ListHeaders/Horde/ListHeaders/Translation.php', + 'Horde_Mail_Exception' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Exception.php', + 'Horde_Mail_Mbox_Parse' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Mbox/Parse.php', + 'Horde_Mail_Rfc822' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822.php', + 'Horde_Mail_Rfc822_Address' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822/Address.php', + 'Horde_Mail_Rfc822_Group' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822/Group.php', + 'Horde_Mail_Rfc822_GroupList' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822/GroupList.php', + 'Horde_Mail_Rfc822_Identification' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822/Identification.php', + 'Horde_Mail_Rfc822_List' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822/List.php', + 'Horde_Mail_Rfc822_Object' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822/Object.php', + 'Horde_Mail_Translation' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Translation.php', + 'Horde_Mail_Transport' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport.php', + 'Horde_Mail_Transport_Lmtphorde' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Lmtphorde.php', + 'Horde_Mail_Transport_Mail' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Mail.php', + 'Horde_Mail_Transport_Mock' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Mock.php', + 'Horde_Mail_Transport_Null' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Null.php', + 'Horde_Mail_Transport_Sendmail' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Sendmail.php', + 'Horde_Mail_Transport_Smtp' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Smtp.php', + 'Horde_Mail_Transport_Smtphorde' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Smtphorde.php', + 'Horde_Mail_Transport_Smtpmx' => $vendorDir . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Smtpmx.php', + 'Horde_Mime' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime.php', + 'Horde_Mime_ContentParam_Decode' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/ContentParam/Decode.php', + 'Horde_Mime_Exception' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Exception.php', + 'Horde_Mime_Filter_Encoding' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Filter/Encoding.php', + 'Horde_Mime_Headers' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers.php', + 'Horde_Mime_Headers_Addresses' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Addresses.php', + 'Horde_Mime_Headers_AddressesMulti' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/AddressesMulti.php', + 'Horde_Mime_Headers_ContentDescription' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentDescription.php', + 'Horde_Mime_Headers_ContentId' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentId.php', + 'Horde_Mime_Headers_ContentLanguage' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentLanguage.php', + 'Horde_Mime_Headers_ContentParam' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentParam.php', + 'Horde_Mime_Headers_ContentParam_ContentDisposition' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentParam/ContentDisposition.php', + 'Horde_Mime_Headers_ContentParam_ContentType' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentParam/ContentType.php', + 'Horde_Mime_Headers_ContentTransferEncoding' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentTransferEncoding.php', + 'Horde_Mime_Headers_Date' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Date.php', + 'Horde_Mime_Headers_Deprecated' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Deprecated.php', + 'Horde_Mime_Headers_Element' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Element.php', + 'Horde_Mime_Headers_Element_Address' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Element/Address.php', + 'Horde_Mime_Headers_Element_Multiple' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Element/Multiple.php', + 'Horde_Mime_Headers_Element_Single' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Element/Single.php', + 'Horde_Mime_Headers_Extension_Mime' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Extension/Mime.php', + 'Horde_Mime_Headers_Identification' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Identification.php', + 'Horde_Mime_Headers_MessageId' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/MessageId.php', + 'Horde_Mime_Headers_Mime' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Mime.php', + 'Horde_Mime_Headers_MimeVersion' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/MimeVersion.php', + 'Horde_Mime_Headers_Received' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Received.php', + 'Horde_Mime_Headers_Subject' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Subject.php', + 'Horde_Mime_Headers_UserAgent' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/UserAgent.php', + 'Horde_Mime_Id' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Id.php', + 'Horde_Mime_Magic' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Magic.php', + 'Horde_Mime_Mail' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Mail.php', + 'Horde_Mime_Mdn' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Mdn.php', + 'Horde_Mime_Part' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Part.php', + 'Horde_Mime_Part_Iterator' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Part/Iterator.php', + 'Horde_Mime_Part_Upgrade_V1' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Part/Upgrade/V1.php', + 'Horde_Mime_QuotedPrintable' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/QuotedPrintable.php', + 'Horde_Mime_Related' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Related.php', + 'Horde_Mime_Translation' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Translation.php', + 'Horde_Mime_Uudecode' => $vendorDir . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Uudecode.php', + 'Horde_Secret' => $vendorDir . '/pear-pear.horde.org/Horde_Secret/Horde/Secret.php', + 'Horde_Secret_Exception' => $vendorDir . '/pear-pear.horde.org/Horde_Secret/Horde/Secret/Exception.php', + 'Horde_Stream' => $vendorDir . '/pear-pear.horde.org/Horde_Stream/Horde/Stream.php', + 'Horde_Stream_Exception' => $vendorDir . '/pear-pear.horde.org/Horde_Stream/Horde/Stream/Exception.php', + 'Horde_Stream_Existing' => $vendorDir . '/pear-pear.horde.org/Horde_Stream/Horde/Stream/Existing.php', + 'Horde_Stream_Filter_Bin2hex' => $vendorDir . '/pear-pear.horde.org/Horde_Stream_Filter/Horde/Stream/Filter/Bin2hex.php', + 'Horde_Stream_Filter_Crc32' => $vendorDir . '/pear-pear.horde.org/Horde_Stream_Filter/Horde/Stream/Filter/Crc32.php', + 'Horde_Stream_Filter_Eol' => $vendorDir . '/pear-pear.horde.org/Horde_Stream_Filter/Horde/Stream/Filter/Eol.php', + 'Horde_Stream_Filter_Htmlspecialchars' => $vendorDir . '/pear-pear.horde.org/Horde_Stream_Filter/Horde/Stream/Filter/Htmlspecialchars.php', + 'Horde_Stream_Filter_Null' => $vendorDir . '/pear-pear.horde.org/Horde_Stream_Filter/Horde/Stream/Filter/Null.php', + 'Horde_Stream_String' => $vendorDir . '/pear-pear.horde.org/Horde_Stream/Horde/Stream/String.php', + 'Horde_Stream_Temp' => $vendorDir . '/pear-pear.horde.org/Horde_Stream/Horde/Stream/Temp.php', + 'Horde_Stream_TempString' => $vendorDir . '/pear-pear.horde.org/Horde_Stream/Horde/Stream/TempString.php', + 'Horde_Stream_Wrapper_Combine' => $vendorDir . '/pear-pear.horde.org/Horde_Stream_Wrapper/Horde/Stream/Wrapper/Combine.php', + 'Horde_Stream_Wrapper_CombineStream' => $vendorDir . '/pear-pear.horde.org/Horde_Stream_Wrapper/Horde/Stream/Wrapper/CombineStream.php', + 'Horde_Stream_Wrapper_String' => $vendorDir . '/pear-pear.horde.org/Horde_Stream_Wrapper/Horde/Stream/Wrapper/String.php', + 'Horde_Stream_Wrapper_StringStream' => $vendorDir . '/pear-pear.horde.org/Horde_Stream_Wrapper/Horde/Stream/Wrapper/StringStream.php', + 'Horde_String' => $vendorDir . '/pear-pear.horde.org/Horde_Util/Horde/String.php', + 'Horde_String_Transliterate' => $vendorDir . '/pear-pear.horde.org/Horde_Util/Horde/String/Transliterate.php', + 'Horde_Support_Array' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Array.php', + 'Horde_Support_Backtrace' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Backtrace.php', + 'Horde_Support_CaseInsensitiveArray' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/CaseInsensitiveArray.php', + 'Horde_Support_CombineStream' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/CombineStream.php', + 'Horde_Support_ConsistentHash' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/ConsistentHash.php', + 'Horde_Support_Guid' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Guid.php', + 'Horde_Support_Inflector' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Inflector.php', + 'Horde_Support_Memory' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Memory.php', + 'Horde_Support_Numerizer' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Numerizer.php', + 'Horde_Support_Numerizer_Locale_Base' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Numerizer/Locale/Base.php', + 'Horde_Support_Numerizer_Locale_De' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Numerizer/Locale/De.php', + 'Horde_Support_Numerizer_Locale_Pt' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Numerizer/Locale/Pt.php', + 'Horde_Support_ObjectStub' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/ObjectStub.php', + 'Horde_Support_Randomid' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Randomid.php', + 'Horde_Support_Stack' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Stack.php', + 'Horde_Support_StringStream' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/StringStream.php', + 'Horde_Support_Stub' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Stub.php', + 'Horde_Support_Timer' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Timer.php', + 'Horde_Support_Uuid' => $vendorDir . '/pear-pear.horde.org/Horde_Support/Horde/Support/Uuid.php', + 'Horde_Text_Flowed' => $vendorDir . '/pear-pear.horde.org/Horde_Text_Flowed/Horde/Text/Flowed.php', + 'Horde_Translation' => $vendorDir . '/pear-pear.horde.org/Horde_Translation/Horde/Translation.php', + 'Horde_Translation_Autodetect' => $vendorDir . '/pear-pear.horde.org/Horde_Translation/Horde/Translation/Autodetect.php', + 'Horde_Translation_Exception' => $vendorDir . '/pear-pear.horde.org/Horde_Translation/Horde/Translation/Exception.php', + 'Horde_Translation_Handler' => $vendorDir . '/pear-pear.horde.org/Horde_Translation/Horde/Translation/Handler.php', + 'Horde_Translation_Handler_Gettext' => $vendorDir . '/pear-pear.horde.org/Horde_Translation/Horde/Translation/Handler/Gettext.php', + 'Horde_Util' => $vendorDir . '/pear-pear.horde.org/Horde_Util/Horde/Util.php', + 'Horde_Variables' => $vendorDir . '/pear-pear.horde.org/Horde_Util/Horde/Variables.php', ); diff --git a/lam/lib/3rdParty/composer/composer/autoload_files.php b/lam/lib/3rdParty/composer/composer/autoload_files.php index ada90386..1df9a325 100644 --- a/lam/lib/3rdParty/composer/composer/autoload_files.php +++ b/lam/lib/3rdParty/composer/composer/autoload_files.php @@ -11,4 +11,5 @@ return array( '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php', 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', + 'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php', ); diff --git a/lam/lib/3rdParty/composer/composer/autoload_real.php b/lam/lib/3rdParty/composer/composer/autoload_real.php index 9fc69849..5f1ebb26 100644 --- a/lam/lib/3rdParty/composer/composer/autoload_real.php +++ b/lam/lib/3rdParty/composer/composer/autoload_real.php @@ -23,6 +23,10 @@ class ComposerAutoloaderInited73ceb9c1bdec18b7c6d09764d1bce5 self::$loader = $loader = new \Composer\Autoload\ClassLoader(); spl_autoload_unregister(array('ComposerAutoloaderInited73ceb9c1bdec18b7c6d09764d1bce5', 'loadClassLoader')); + $includePaths = require __DIR__ . '/include_paths.php'; + $includePaths[] = get_include_path(); + set_include_path(implode(PATH_SEPARATOR, $includePaths)); + $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { require_once __DIR__ . '/autoload_static.php'; diff --git a/lam/lib/3rdParty/composer/composer/autoload_static.php b/lam/lib/3rdParty/composer/composer/autoload_static.php index 30a44942..131f5c98 100644 --- a/lam/lib/3rdParty/composer/composer/autoload_static.php +++ b/lam/lib/3rdParty/composer/composer/autoload_static.php @@ -12,6 +12,7 @@ class ComposerStaticInited73ceb9c1bdec18b7c6d09764d1bce5 '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php', 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', + 'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php', ); public static $prefixLengthsPsr4 = array ( @@ -146,11 +147,245 @@ class ComposerStaticInited73ceb9c1bdec18b7c6d09764d1bce5 ), ); + public static $classMap = array ( + 'HordeImapClientBaseTables' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/data/migration/1_horde_imap_client_base_tables.php', + 'HordeImapClientChangeColumnName' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/data/migration/2_horde_imap_client_change_column_name.php', + 'Horde\\Socket\\Client' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Socket_Client/Horde/Socket/Client.php', + 'Horde\\Socket\\Client\\Exception' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Socket_Client/Horde/Socket/Client/Exception.php', + 'Horde_Array' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Util/Horde/Array.php', + 'Horde_Array_Sort_Helper' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Util/Horde/Array/Sort/Helper.php', + 'Horde_Crypt_Blowfish' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish.php', + 'Horde_Crypt_Blowfish_Base' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Base.php', + 'Horde_Crypt_Blowfish_Exception' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Exception.php', + 'Horde_Crypt_Blowfish_Mcrypt' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Mcrypt.php', + 'Horde_Crypt_Blowfish_Openssl' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Openssl.php', + 'Horde_Crypt_Blowfish_Pbkdf2' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Pbkdf2.php', + 'Horde_Crypt_Blowfish_Php' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php.php', + 'Horde_Crypt_Blowfish_Php_Base' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Base.php', + 'Horde_Crypt_Blowfish_Php_Cbc' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Cbc.php', + 'Horde_Crypt_Blowfish_Php_Ecb' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Ecb.php', + 'Horde_Domhtml' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Util/Horde/Domhtml.php', + 'Horde_Exception' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Exception/Horde/Exception.php', + 'Horde_Exception_LastError' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Exception/Horde/Exception/LastError.php', + 'Horde_Exception_NotFound' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Exception/Horde/Exception/NotFound.php', + 'Horde_Exception_Pear' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Exception/Horde/Exception/Pear.php', + 'Horde_Exception_PermissionDenied' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Exception/Horde/Exception/PermissionDenied.php', + 'Horde_Exception_Translation' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Exception/Horde/Exception/Translation.php', + 'Horde_Exception_Wrapped' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Exception/Horde/Exception/Wrapped.php', + 'Horde_Idna' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Idna/Horde/Idna.php', + 'Horde_Idna_Exception' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Idna/Horde/Idna/Exception.php', + 'Horde_Idna_Punycode' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Idna/Horde/Idna/Punycode.php', + 'Horde_Idna_Translation' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Idna/Horde/Idna/Translation.php', + 'Horde_Imap_Client' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client.php', + 'Horde_Imap_Client_Auth_DigestMD5' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Auth/DigestMD5.php', + 'Horde_Imap_Client_Auth_Scram' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Auth/Scram.php', + 'Horde_Imap_Client_Base' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base.php', + 'Horde_Imap_Client_Base_Alerts' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Alerts.php', + 'Horde_Imap_Client_Base_Debug' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Debug.php', + 'Horde_Imap_Client_Base_Deprecated' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Deprecated.php', + 'Horde_Imap_Client_Base_Mailbox' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Mailbox.php', + 'Horde_Imap_Client_Base_Password' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Password.php', + 'Horde_Imap_Client_Cache' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache.php', + 'Horde_Imap_Client_Cache_Backend' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend.php', + 'Horde_Imap_Client_Cache_Backend_Cache' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Cache.php', + 'Horde_Imap_Client_Cache_Backend_Db' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Db.php', + 'Horde_Imap_Client_Cache_Backend_Hashtable' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Hashtable.php', + 'Horde_Imap_Client_Cache_Backend_Mongo' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Mongo.php', + 'Horde_Imap_Client_Cache_Backend_Null' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Null.php', + 'Horde_Imap_Client_Data_Acl' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Acl.php', + 'Horde_Imap_Client_Data_AclCommon' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclCommon.php', + 'Horde_Imap_Client_Data_AclNegative' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclNegative.php', + 'Horde_Imap_Client_Data_AclRights' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclRights.php', + 'Horde_Imap_Client_Data_BaseSubject' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/BaseSubject.php', + 'Horde_Imap_Client_Data_Capability' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Capability.php', + 'Horde_Imap_Client_Data_Capability_Imap' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Capability/Imap.php', + 'Horde_Imap_Client_Data_Envelope' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Envelope.php', + 'Horde_Imap_Client_Data_Fetch' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Fetch.php', + 'Horde_Imap_Client_Data_Fetch_Pop3' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Fetch/Pop3.php', + 'Horde_Imap_Client_Data_Format' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format.php', + 'Horde_Imap_Client_Data_Format_Astring' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Astring.php', + 'Horde_Imap_Client_Data_Format_Astring_Nonascii' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Astring/Nonascii.php', + 'Horde_Imap_Client_Data_Format_Atom' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Atom.php', + 'Horde_Imap_Client_Data_Format_Date' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Date.php', + 'Horde_Imap_Client_Data_Format_DateTime' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/DateTime.php', + 'Horde_Imap_Client_Data_Format_Exception' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Exception.php', + 'Horde_Imap_Client_Data_Format_Filter_Quote' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Filter/Quote.php', + 'Horde_Imap_Client_Data_Format_Filter_String' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Filter/String.php', + 'Horde_Imap_Client_Data_Format_List' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/List.php', + 'Horde_Imap_Client_Data_Format_ListMailbox' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/ListMailbox.php', + 'Horde_Imap_Client_Data_Format_ListMailbox_Utf8' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/ListMailbox/Utf8.php', + 'Horde_Imap_Client_Data_Format_Mailbox' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Mailbox.php', + 'Horde_Imap_Client_Data_Format_Mailbox_Utf8' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Mailbox/Utf8.php', + 'Horde_Imap_Client_Data_Format_Nil' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nil.php', + 'Horde_Imap_Client_Data_Format_Nstring' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nstring.php', + 'Horde_Imap_Client_Data_Format_Nstring_Nonascii' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nstring/Nonascii.php', + 'Horde_Imap_Client_Data_Format_Number' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Number.php', + 'Horde_Imap_Client_Data_Format_String' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String.php', + 'Horde_Imap_Client_Data_Format_String_Nonascii' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String/Nonascii.php', + 'Horde_Imap_Client_Data_Format_String_Support_Nonascii' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String/Support/Nonascii.php', + 'Horde_Imap_Client_Data_Namespace' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Namespace.php', + 'Horde_Imap_Client_Data_SearchCharset' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/SearchCharset.php', + 'Horde_Imap_Client_Data_SearchCharset_Utf8' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/SearchCharset/Utf8.php', + 'Horde_Imap_Client_Data_Sync' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Sync.php', + 'Horde_Imap_Client_Data_Thread' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Thread.php', + 'Horde_Imap_Client_DateTime' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/DateTime.php', + 'Horde_Imap_Client_Exception' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception.php', + 'Horde_Imap_Client_Exception_NoSupportExtension' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/NoSupportExtension.php', + 'Horde_Imap_Client_Exception_NoSupportPop3' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/NoSupportPop3.php', + 'Horde_Imap_Client_Exception_SearchCharset' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/SearchCharset.php', + 'Horde_Imap_Client_Exception_ServerResponse' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/ServerResponse.php', + 'Horde_Imap_Client_Exception_Sync' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/Sync.php', + 'Horde_Imap_Client_Fetch_Query' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Fetch/Query.php', + 'Horde_Imap_Client_Fetch_Results' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Fetch/Results.php', + 'Horde_Imap_Client_Ids' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids.php', + 'Horde_Imap_Client_Ids_Map' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids/Map.php', + 'Horde_Imap_Client_Ids_Pop3' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids/Pop3.php', + 'Horde_Imap_Client_Interaction_Client' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Client.php', + 'Horde_Imap_Client_Interaction_Command' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Command.php', + 'Horde_Imap_Client_Interaction_Command_Continuation' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Command/Continuation.php', + 'Horde_Imap_Client_Interaction_Pipeline' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Pipeline.php', + 'Horde_Imap_Client_Interaction_Server' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server.php', + 'Horde_Imap_Client_Interaction_Server_Continuation' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Continuation.php', + 'Horde_Imap_Client_Interaction_Server_Tagged' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Tagged.php', + 'Horde_Imap_Client_Interaction_Server_Untagged' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Untagged.php', + 'Horde_Imap_Client_Mailbox' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Mailbox.php', + 'Horde_Imap_Client_Mailbox_List' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Mailbox/List.php', + 'Horde_Imap_Client_Namespace_List' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Namespace/List.php', + 'Horde_Imap_Client_Password_Xoauth2' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Password/Xoauth2.php', + 'Horde_Imap_Client_Search_Query' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Search/Query.php', + 'Horde_Imap_Client_Socket' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket.php', + 'Horde_Imap_Client_Socket_Catenate' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/Catenate.php', + 'Horde_Imap_Client_Socket_ClientSort' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/ClientSort.php', + 'Horde_Imap_Client_Socket_Connection_Base' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/Connection/Base.php', + 'Horde_Imap_Client_Socket_Connection_Pop3' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/Connection/Pop3.php', + 'Horde_Imap_Client_Socket_Connection_Socket' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/Connection/Socket.php', + 'Horde_Imap_Client_Socket_Pop3' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket/Pop3.php', + 'Horde_Imap_Client_Tokenize' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Tokenize.php', + 'Horde_Imap_Client_Translation' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Translation.php', + 'Horde_Imap_Client_Url' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Url.php', + 'Horde_Imap_Client_Url_Base' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Url/Base.php', + 'Horde_Imap_Client_Url_Imap' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Url/Imap.php', + 'Horde_Imap_Client_Url_Imap_Relative' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Url/Imap/Relative.php', + 'Horde_Imap_Client_Url_Pop3' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Url/Pop3.php', + 'Horde_Imap_Client_Utf7imap' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Utf7imap.php', + 'Horde_ListHeaders' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_ListHeaders/Horde/ListHeaders.php', + 'Horde_ListHeaders_Base' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_ListHeaders/Horde/ListHeaders/Base.php', + 'Horde_ListHeaders_Id' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_ListHeaders/Horde/ListHeaders/Id.php', + 'Horde_ListHeaders_NoPost' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_ListHeaders/Horde/ListHeaders/NoPost.php', + 'Horde_ListHeaders_Object' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_ListHeaders/Horde/ListHeaders/Object.php', + 'Horde_ListHeaders_Translation' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_ListHeaders/Horde/ListHeaders/Translation.php', + 'Horde_Mail_Exception' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Exception.php', + 'Horde_Mail_Mbox_Parse' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Mbox/Parse.php', + 'Horde_Mail_Rfc822' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822.php', + 'Horde_Mail_Rfc822_Address' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822/Address.php', + 'Horde_Mail_Rfc822_Group' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822/Group.php', + 'Horde_Mail_Rfc822_GroupList' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822/GroupList.php', + 'Horde_Mail_Rfc822_Identification' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822/Identification.php', + 'Horde_Mail_Rfc822_List' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822/List.php', + 'Horde_Mail_Rfc822_Object' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Rfc822/Object.php', + 'Horde_Mail_Translation' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Translation.php', + 'Horde_Mail_Transport' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport.php', + 'Horde_Mail_Transport_Lmtphorde' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Lmtphorde.php', + 'Horde_Mail_Transport_Mail' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Mail.php', + 'Horde_Mail_Transport_Mock' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Mock.php', + 'Horde_Mail_Transport_Null' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Null.php', + 'Horde_Mail_Transport_Sendmail' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Sendmail.php', + 'Horde_Mail_Transport_Smtp' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Smtp.php', + 'Horde_Mail_Transport_Smtphorde' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Smtphorde.php', + 'Horde_Mail_Transport_Smtpmx' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mail/Horde/Mail/Transport/Smtpmx.php', + 'Horde_Mime' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime.php', + 'Horde_Mime_ContentParam_Decode' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/ContentParam/Decode.php', + 'Horde_Mime_Exception' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Exception.php', + 'Horde_Mime_Filter_Encoding' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Filter/Encoding.php', + 'Horde_Mime_Headers' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers.php', + 'Horde_Mime_Headers_Addresses' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Addresses.php', + 'Horde_Mime_Headers_AddressesMulti' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/AddressesMulti.php', + 'Horde_Mime_Headers_ContentDescription' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentDescription.php', + 'Horde_Mime_Headers_ContentId' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentId.php', + 'Horde_Mime_Headers_ContentLanguage' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentLanguage.php', + 'Horde_Mime_Headers_ContentParam' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentParam.php', + 'Horde_Mime_Headers_ContentParam_ContentDisposition' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentParam/ContentDisposition.php', + 'Horde_Mime_Headers_ContentParam_ContentType' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentParam/ContentType.php', + 'Horde_Mime_Headers_ContentTransferEncoding' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/ContentTransferEncoding.php', + 'Horde_Mime_Headers_Date' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Date.php', + 'Horde_Mime_Headers_Deprecated' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Deprecated.php', + 'Horde_Mime_Headers_Element' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Element.php', + 'Horde_Mime_Headers_Element_Address' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Element/Address.php', + 'Horde_Mime_Headers_Element_Multiple' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Element/Multiple.php', + 'Horde_Mime_Headers_Element_Single' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Element/Single.php', + 'Horde_Mime_Headers_Extension_Mime' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Extension/Mime.php', + 'Horde_Mime_Headers_Identification' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Identification.php', + 'Horde_Mime_Headers_MessageId' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/MessageId.php', + 'Horde_Mime_Headers_Mime' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Mime.php', + 'Horde_Mime_Headers_MimeVersion' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/MimeVersion.php', + 'Horde_Mime_Headers_Received' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Received.php', + 'Horde_Mime_Headers_Subject' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/Subject.php', + 'Horde_Mime_Headers_UserAgent' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Headers/UserAgent.php', + 'Horde_Mime_Id' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Id.php', + 'Horde_Mime_Magic' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Magic.php', + 'Horde_Mime_Mail' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Mail.php', + 'Horde_Mime_Mdn' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Mdn.php', + 'Horde_Mime_Part' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Part.php', + 'Horde_Mime_Part_Iterator' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Part/Iterator.php', + 'Horde_Mime_Part_Upgrade_V1' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Part/Upgrade/V1.php', + 'Horde_Mime_QuotedPrintable' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/QuotedPrintable.php', + 'Horde_Mime_Related' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Related.php', + 'Horde_Mime_Translation' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Translation.php', + 'Horde_Mime_Uudecode' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Mime/Horde/Mime/Uudecode.php', + 'Horde_Secret' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Secret/Horde/Secret.php', + 'Horde_Secret_Exception' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Secret/Horde/Secret/Exception.php', + 'Horde_Stream' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream/Horde/Stream.php', + 'Horde_Stream_Exception' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream/Horde/Stream/Exception.php', + 'Horde_Stream_Existing' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream/Horde/Stream/Existing.php', + 'Horde_Stream_Filter_Bin2hex' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream_Filter/Horde/Stream/Filter/Bin2hex.php', + 'Horde_Stream_Filter_Crc32' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream_Filter/Horde/Stream/Filter/Crc32.php', + 'Horde_Stream_Filter_Eol' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream_Filter/Horde/Stream/Filter/Eol.php', + 'Horde_Stream_Filter_Htmlspecialchars' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream_Filter/Horde/Stream/Filter/Htmlspecialchars.php', + 'Horde_Stream_Filter_Null' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream_Filter/Horde/Stream/Filter/Null.php', + 'Horde_Stream_String' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream/Horde/Stream/String.php', + 'Horde_Stream_Temp' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream/Horde/Stream/Temp.php', + 'Horde_Stream_TempString' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream/Horde/Stream/TempString.php', + 'Horde_Stream_Wrapper_Combine' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream_Wrapper/Horde/Stream/Wrapper/Combine.php', + 'Horde_Stream_Wrapper_CombineStream' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream_Wrapper/Horde/Stream/Wrapper/CombineStream.php', + 'Horde_Stream_Wrapper_String' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream_Wrapper/Horde/Stream/Wrapper/String.php', + 'Horde_Stream_Wrapper_StringStream' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Stream_Wrapper/Horde/Stream/Wrapper/StringStream.php', + 'Horde_String' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Util/Horde/String.php', + 'Horde_String_Transliterate' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Util/Horde/String/Transliterate.php', + 'Horde_Support_Array' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Array.php', + 'Horde_Support_Backtrace' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Backtrace.php', + 'Horde_Support_CaseInsensitiveArray' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/CaseInsensitiveArray.php', + 'Horde_Support_CombineStream' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/CombineStream.php', + 'Horde_Support_ConsistentHash' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/ConsistentHash.php', + 'Horde_Support_Guid' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Guid.php', + 'Horde_Support_Inflector' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Inflector.php', + 'Horde_Support_Memory' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Memory.php', + 'Horde_Support_Numerizer' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Numerizer.php', + 'Horde_Support_Numerizer_Locale_Base' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Numerizer/Locale/Base.php', + 'Horde_Support_Numerizer_Locale_De' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Numerizer/Locale/De.php', + 'Horde_Support_Numerizer_Locale_Pt' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Numerizer/Locale/Pt.php', + 'Horde_Support_ObjectStub' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/ObjectStub.php', + 'Horde_Support_Randomid' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Randomid.php', + 'Horde_Support_Stack' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Stack.php', + 'Horde_Support_StringStream' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/StringStream.php', + 'Horde_Support_Stub' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Stub.php', + 'Horde_Support_Timer' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Timer.php', + 'Horde_Support_Uuid' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Support/Horde/Support/Uuid.php', + 'Horde_Text_Flowed' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Text_Flowed/Horde/Text/Flowed.php', + 'Horde_Translation' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Translation/Horde/Translation.php', + 'Horde_Translation_Autodetect' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Translation/Horde/Translation/Autodetect.php', + 'Horde_Translation_Exception' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Translation/Horde/Translation/Exception.php', + 'Horde_Translation_Handler' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Translation/Horde/Translation/Handler.php', + 'Horde_Translation_Handler_Gettext' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Translation/Horde/Translation/Handler/Gettext.php', + 'Horde_Util' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Util/Horde/Util.php', + 'Horde_Variables' => __DIR__ . '/..' . '/pear-pear.horde.org/Horde_Util/Horde/Variables.php', + ); + public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { $loader->prefixLengthsPsr4 = ComposerStaticInited73ceb9c1bdec18b7c6d09764d1bce5::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInited73ceb9c1bdec18b7c6d09764d1bce5::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInited73ceb9c1bdec18b7c6d09764d1bce5::$classMap; }, null, ClassLoader::class); } diff --git a/lam/lib/3rdParty/composer/composer/include_paths.php b/lam/lib/3rdParty/composer/composer/include_paths.php new file mode 100644 index 00000000..41c63635 --- /dev/null +++ b/lam/lib/3rdParty/composer/composer/include_paths.php @@ -0,0 +1,25 @@ + + * Copyright 2012-2017 Horde LLC (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.horde.org/licenses/lgpl21. + * + * @author Matthew Fonda + * @author Michael Slusarz + * @category Horde + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ + +/** + * Provides blowfish encryption/decryption, with or without a secret key, + * for PHP strings. + * + * @author Matthew Fonda + * @author Michael Slusarz + * @category Horde + * @copyright 2005-2008 Matthew Fonda + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + * + * @property string $cipher The cipher block mode ('ecb' or 'cbc'). + * @property string $key The encryption key in use. + * @property mixed $iv The initialization vector (false if using 'ecb'). + */ +class Horde_Crypt_Blowfish +{ + // Constants for 'ignore' parameter of constructor. + const IGNORE_OPENSSL = 1; + const IGNORE_MCRYPT = 2; + + // Block size for Blowfish + const BLOCKSIZE = 8; + + // Maximum key size for Blowfish + const MAXKEYSIZE = 56; + + // IV Length for CBC + const IV_LENGTH = 8; + + /** + * Blowfish crypt driver. + * + * @var Horde_Crypt_Blowfish_Base + */ + protected $_crypt; + + /** + * Constructor. + * + * @param string $key Encryption key. + * @param array $opts Additional options: + * - cipher: (string) Either 'ecb' or 'cbc'. + * - ignore: (integer) A mask of drivers to ignore (IGNORE_* constants). + * - iv: (string) IV to use. + */ + public function __construct($key, array $opts = array()) + { + $opts = array_merge(array( + 'cipher' => 'ecb', + 'ignore' => 0, + 'iv' => null + ), $opts); + + if (!($opts['ignore'] & self::IGNORE_OPENSSL) && + Horde_Crypt_Blowfish_Openssl::supported()) { + $this->_crypt = new Horde_Crypt_Blowfish_Openssl($opts['cipher']); + } elseif (!($opts['ignore'] & self::IGNORE_MCRYPT) && + Horde_Crypt_Blowfish_Mcrypt::supported()) { + $this->_crypt = new Horde_Crypt_Blowfish_Mcrypt($opts['cipher']); + } else { + $this->_crypt = new Horde_Crypt_Blowfish_Php($opts['cipher']); + } + + $this->setKey($key, $opts['iv']); + } + + /** + */ + public function __get($name) + { + switch ($name) { + case 'cipher': + case 'key': + case 'iv': + return $this->_crypt->$name; + } + } + + /** + * Encrypts a string. + * + * @param string $text The string to encrypt. + * + * @return string The ciphertext. + * @throws Horde_Crypt_Blowfish_Exception + */ + public function encrypt($text) + { + if (!is_string($text)) { + throw new Horde_Crypt_Blowfish_Exception('Data to encrypt must be a string.'); + } + + return $this->_crypt->encrypt($text); + } + + /** + * Decrypts a string. + * + * @param string $text The string to decrypt. + * + * @return string The plaintext. + * @throws Horde_Crypt_Blowfish_Exception + */ + public function decrypt($text) + { + if (!is_string($text)) { + throw new Horde_Crypt_Blowfish_Exception('Data to decrypt must be a string.'); + } + + return $this->_crypt->decrypt($text); + } + + /** + * Sets the secret key. + * + * The key must be non-zero, and less than or equal to MAXKEYSIZE + * characters (bytes) in length. + * + * @param string $key Key must be non-empty and less than MAXKEYSIZE + * bytes in length. + * @param string $iv The initialization vector to use. Only needed for + * 'cbc' cipher. If null, an IV is automatically + * generated. + * + * @throws Horde_Crypt_Blowfish_Exception + */ + public function setKey($key, $iv = null) + { + if (!is_string($key)) { + throw new Horde_Crypt_Blowfish_Exception('Encryption key must be a string.'); + } + + $len = strlen($key); + if (($len > self::MAXKEYSIZE) || ($len == 0)) { + throw new Horde_Crypt_Blowfish_Exception(sprintf('Encryption key must be less than %d characters (bytes) and non-zero. Supplied key length: %d', self::MAXKEYSIZE, $len)); + } + + $this->_crypt->key = $key; + + switch ($this->_crypt->cipher) { + case 'cbc': + if (is_null($iv)) { + if (is_null($this->iv)) { + $this->_crypt->setIv(); + } + } else { + $iv = substr($iv, 0, self::IV_LENGTH); + if (($len = strlen($iv)) < self::IV_LENGTH) { + $iv .= str_repeat(chr(0), self::IV_LENGTH - $len); + } + $this->_crypt->setIv($iv); + } + break; + + case 'ecb': + $this->iv = false; + break; + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Base.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Base.php new file mode 100644 index 00000000..8036d11f --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Base.php @@ -0,0 +1,128 @@ + + * @category Horde + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ + +/** + * Abstract base driver class for blowfish encryption. + * + * @author Michael Slusarz + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ +abstract class Horde_Crypt_Blowfish_Base +{ + /** + * Cipher method. + * + * @var string + */ + public $cipher; + + /** + * Initialization vector. + * + * @var string + */ + public $iv = null; + + /** + * Encryption key. + * + * @var string + */ + public $key; + + /** + * Is this driver supported on this system? + * + * @return boolean True if supported. + */ + public static function supported() + { + return true; + } + + /** + * Constructor. + * + * @param string $cipher Either 'ecb' or 'cbc'. + */ + public function __construct($cipher) + { + $this->cipher = $cipher; + } + + /** + * Encrypts a string. + * + * @param string $text The string to encrypt. + * + * @return string The ciphertext. + * @throws Horde_Crypt_Blowfish_Exception + */ + abstract public function encrypt($text); + + /** + * Decrypts a string. + * + * @param string $text The string to encrypt. + * + * @return string The ciphertext. + * @throws Horde_Crypt_Blowfish_Exception + */ + abstract public function decrypt($text); + + /** + * Sets the initialization vector (required for CBC mode). + * + * @param string $iv Initialization vector. + */ + public function setIv($iv = null) + { + $this->iv = is_null($iv) + ? substr(new Horde_Support_Randomid(), 0, 8) + : $iv; + } + + /** + * Pad text to match blocksize length. + * + * @param string $text Unpadded text. + * @param boolean $ignore Don't pad if already at blocksize length. + * + * @return string Padded text. + */ + protected function _pad($text, $ignore = false) + { + $blocksize = Horde_Crypt_Blowfish::BLOCKSIZE; + $padding = $blocksize - (strlen($text) % $blocksize); + + return ($ignore && ($padding == $blocksize)) + ? $text + : $text . str_repeat(chr($padding), $padding); + } + + /** + * Unpad text from blocksize boundary. + * + * @param string $text Padded text. + * + * @return string Unpadded text. + */ + protected function _unpad($text) + { + return substr($text, 0, ord(substr($text, -1)) * -1); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Exception.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Exception.php new file mode 100644 index 00000000..64485766 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Exception.php @@ -0,0 +1,25 @@ + + * @category Horde + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ + +/** + * Exception object for the Horde_Crypt_Blowfish package. + * + * @author Michael Slusarz + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ +class Horde_Crypt_Blowfish_Exception extends Horde_Exception_Wrapped +{ +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Mcrypt.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Mcrypt.php new file mode 100644 index 00000000..429001bf --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Mcrypt.php @@ -0,0 +1,87 @@ + + * Copyright 2008 Philippe Jausions + * Copyright 2012-2017 Horde LLC (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.horde.org/licenses/lgpl21. + * + * @author Matthew Fonda + * @author Philippe Jausions + * @author Michael Slusarz + * @category Horde + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ + +/** + * Mcrypt driver for blowfish encryption. + * + * @author Matthew Fonda + * @author Philippe Jausions + * @author Michael Slusarz + * @category Horde + * @copyright 2005-2008 Matthew Fonda + * @copyright 2008 Philippe Jausions + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ +class Horde_Crypt_Blowfish_Mcrypt extends Horde_Crypt_Blowfish_Base +{ + /** + * Mcrypt resource. + * + * @var resource + */ + private $_mcrypt; + + /** + */ + public static function supported() + { + return PHP_VERSION_ID < 70100 && extension_loaded('mcrypt'); + } + + /** + */ + public function __construct($cipher) + { + parent::__construct($cipher); + + $this->_mcrypt = mcrypt_module_open(MCRYPT_BLOWFISH, '', $cipher, ''); + } + + /** + */ + public function encrypt($text) + { + mcrypt_generic_init($this->_mcrypt, $this->key, empty($this->iv) ? str_repeat('0', Horde_Crypt_Blowfish::IV_LENGTH) : $this->iv); + $out = mcrypt_generic($this->_mcrypt, $this->_pad($text)); + mcrypt_generic_deinit($this->_mcrypt); + + return $out; + } + + /** + */ + public function decrypt($text) + { + mcrypt_generic_init($this->_mcrypt, $this->key, empty($this->iv) ? str_repeat('0', Horde_Crypt_Blowfish::IV_LENGTH) : $this->iv); + $out = mdecrypt_generic($this->_mcrypt, $this->_pad($text, true)); + mcrypt_generic_deinit($this->_mcrypt); + + return $this->_unpad($out); + } + + /** + */ + public function setIv($iv = null) + { + $this->iv = is_null($iv) + ? mcrypt_create_iv(Horde_Crypt_Blowfish::IV_LENGTH, MCRYPT_RAND) + : $iv; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Openssl.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Openssl.php new file mode 100644 index 00000000..a23bfa8b --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Openssl.php @@ -0,0 +1,56 @@ + + * @category Horde + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ + +/** + * Openssl driver for blowfish encryption. + * + * @author Michael Slusarz + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ +class Horde_Crypt_Blowfish_Openssl extends Horde_Crypt_Blowfish_Base +{ + /** + */ + public static function supported() + { + return extension_loaded('openssl'); + } + + /** + */ + public function encrypt($text) + { + if (PHP_VERSION_ID <= 50302) { + return @openssl_encrypt($text, 'bf-' . $this->cipher, $this->key, true); + } elseif (PHP_VERSION_ID == 50303) { + // Need to mask error output, since an invalid warning message was + // issued prior to 5.3.4 for empty IVs in ECB mode. + return @openssl_encrypt($text, 'bf-' . $this->cipher, $this->key, true, strval($this->iv)); + } + + return openssl_encrypt($text, 'bf-' . $this->cipher, $this->key, true, strval($this->iv)); + } + + /** + */ + public function decrypt($text) + { + return (PHP_VERSION_ID <= 50302) + ? openssl_decrypt($text, 'bf-' . $this->cipher, $this->key, true) + : openssl_decrypt($text, 'bf-' . $this->cipher, $this->key, true, strval($this->iv)); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Pbkdf2.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Pbkdf2.php new file mode 100644 index 00000000..adacfd0c --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Pbkdf2.php @@ -0,0 +1,128 @@ + + * @category Horde + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ + +/** + * PBKDF2 (Password-Based Key Derivation Function 2) implementation (RFC + * 2898; PKCS #5 v2.0). + * + * @author Michael Slusarz + * @category Horde + * @copyright 2015-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + * @link https://defuse.ca/php-pbkdf2.htm pbkdf2 code released to the + * public domain. + */ +class Horde_Crypt_Blowfish_Pbkdf2 +{ + /** + * Hash algorithm used to create key. + * + * @var string + */ + public $hashAlgo; + + /** + * Number of iterations to use. + * + * @var integer + */ + public $iterations; + + /** + * Salt. + * + * @var string + */ + public $salt; + + /** + * The derived key. + * + * @var string + */ + protected $_key; + + /** + * Constructor. + * + * @param string $pass The password. + * @param string $key_length Length of the derived key (in bytes). + * @param array $opts Additional options: + * - algo: (string) Hash algorithm. + * - i_count: (integer) Iteration count. + * - salt: (string) The salt to use. + */ + public function __construct($pass, $key_length, array $opts = array()) + { + $this->iterations = isset($opts['i_count']) + ? $opts['i_count'] + : 16384; + + if (($key_length <= 0) || ($this->iterations <= 0)) { + throw new InvalidArgumentException('Invalid arguments'); + } + + $this->hashAlgo = isset($opts['algo']) + ? $opts['algo'] + : 'SHA256'; + + /* Nice to have, but salt does not need to be cryptographically + * secure random value. */ + $this->salt = isset($opts['salt']) + ? $opts['salt'] + : (function_exists('openssl_random_pseudo_bytes') + ? openssl_random_pseudo_bytes($key_length) + : substr(hash('sha512', new Horde_Support_Randomid(), true), 0, $key_length)); + + if (function_exists('hash_pbkdf2')) { + $this->_key = hash_pbkdf2( + $this->hashAlgo, + $pass, + $this->salt, + $this->iterations, + $key_length, + true + ); + return; + } + + $hash_length = strlen(hash($this->hashAlgo, '', true)); + $block_count = ceil($key_length / $hash_length); + + $hash = ''; + for ($i = 1; $i <= $block_count; ++$i) { + // $i encoded as 4 bytes, big endian. + $last = $this->salt . pack('N', $i); + for ($j = 0; $j < $this->iterations; $j++) { + $last = hash_hmac($this->hashAlgo, $last, $pass, true); + if ($j) { + $xorsum ^= $last; + } else { + $xorsum = $last; + } + } + $hash .= $xorsum; + } + + $this->_key = substr($hash, 0, $key_length); + } + + /** + */ + public function __toString() + { + return $this->_key; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php.php new file mode 100644 index 00000000..3b164140 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php.php @@ -0,0 +1,75 @@ + + * Copyright 2008 Philippe Jausions + * Copyright 2012-2017 Horde LLC (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.horde.org/licenses/lgpl21. + * + * @author Matthew Fonda + * @author Philippe Jausions + * @author Michael Slusarz + * @category Horde + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ + +/** + * Native PHP driver for blowfish encryption. + * + * @author Matthew Fonda + * @author Philippe Jausions + * @author Michael Slusarz + * @category Horde + * @copyright 2005-2008 Matthew Fonda + * @copyright 2008 Philippe Jausions + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ +class Horde_Crypt_Blowfish_Php extends Horde_Crypt_Blowfish_Base +{ + /** + * Subclass object. + * + * @var Horde_Crypt_Blowfish_Php_Base + */ + protected $_ob; + + /** + */ + public function encrypt($text) + { + $this->_init(); + return $this->_ob->encrypt($this->_pad($text), $this->iv); + } + + /** + */ + public function decrypt($text) + { + $this->_init(); + return $this->_unpad($this->_ob->decrypt($this->_pad($text, true), $this->iv)); + } + + /** + * Initialize the subclass. + */ + protected function _init() + { + if (!isset($this->_ob) || + ($this->_ob->md5 != hash('md5', $this->key))) { + switch ($this->cipher) { + case 'cbc': + $this->_ob = new Horde_Crypt_Blowfish_Php_Cbc($this->key); + break; + + case 'ecb': + $this->_ob = new Horde_Crypt_Blowfish_Php_Ecb($this->key); + break; + } + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Base.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Base.php new file mode 100644 index 00000000..65820b5c --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Base.php @@ -0,0 +1,459 @@ + + * Copyright 2012-2017 Horde LLC (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.horde.org/licenses/lgpl21. + * + * @author Matthew Fonda + * @author Michael Slusarz + * @category Horde + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ + +/** + * Base subclass for the PHP driver. + * + * @author Matthew Fonda + * @author Michael Slusarz + * @category Horde + * @copyright 2005-2008 Matthew Fonda + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ +abstract class Horde_Crypt_Blowfish_Php_Base +{ + /** + * MD5 sum of the key used. + * + * @var string + */ + public $md5; + + /** + * P-Array contains 18 32-bit subkeys. + * + * @var array + */ + protected $_P = array( + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, + 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, + 0x9216D5D9, 0x8979FB1B + ); + + /** + * Array of four S-Blocks each containing 256 32-bit entries. + * + * @var array + */ + protected $_S = array( + array( + 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, + 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, + 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, + 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, + 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, + 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, + 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, + 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, + 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, + 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, + 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, + 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, + 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, + 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, + 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, + 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, + 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, + 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, + 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, + 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, + 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, + 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, + 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, + 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, + 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, + 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, + 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, + 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, + 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, + 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, + 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, + 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, + 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, + 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, + 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, + 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, + 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, + 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, + 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, + 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, + 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, + 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, + 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, + 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, + 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, + 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, + 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, + 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, + 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, + 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, + 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, + 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, + 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, + 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, + 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, + 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, + 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, + 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, + 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, + 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, + 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, + 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, + 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A + ), array( + 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, + 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, + 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, + 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, + 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, + 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, + 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, + 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, + 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, + 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, + 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, + 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, + 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, + 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, + 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, + 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, + 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, + 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, + 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, + 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, + 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, + 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, + 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, + 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, + 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, + 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, + 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, + 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, + 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, + 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, + 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, + 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, + 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, + 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, + 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, + 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, + 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, + 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, + 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, + 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, + 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, + 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, + 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, + 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, + 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, + 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, + 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, + 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, + 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, + 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, + 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, + 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, + 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, + 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, + 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, + 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, + 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, + 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, + 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, + 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, + 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, + 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, + 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 + ), array( + 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, + 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, + 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, + 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, + 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, + 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, + 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, + 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, + 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, + 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, + 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, + 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, + 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, + 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, + 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, + 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, + 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, + 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, + 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, + 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, + 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, + 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, + 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, + 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, + 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, + 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, + 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, + 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, + 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, + 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, + 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, + 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, + 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, + 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, + 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, + 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, + 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, + 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, + 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, + 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, + 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, + 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, + 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, + 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, + 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, + 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, + 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, + 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, + 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, + 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, + 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, + 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, + 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, + 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, + 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, + 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, + 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, + 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, + 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, + 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, + 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, + 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, + 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 + ), array( + 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, + 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, + 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, + 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, + 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, + 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, + 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, + 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, + 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, + 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, + 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, + 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, + 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, + 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, + 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, + 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, + 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, + 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, + 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, + 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, + 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, + 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, + 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, + 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, + 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, + 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, + 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, + 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, + 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, + 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, + 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, + 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, + 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, + 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, + 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, + 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, + 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, + 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, + 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, + 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, + 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, + 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, + 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, + 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, + 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, + 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, + 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, + 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, + 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, + 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, + 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, + 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, + 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, + 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, + 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, + 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, + 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, + 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, + 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, + 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, + 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, + 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, + 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 + ) + ); + + /** + * Constructor. + * + * @param string $key Encrpytion key. + */ + public function __construct($key) + { + $data = $datal = $datar = $k = 0; + $len = strlen($key); + + for ($i = 0; $i < 18; ++$i) { + $data = 0; + for ($j = 4; $j > 0; --$j) { + $data = $data << 8 | ord($key[$k]); + $k = ($k + 1) % $len; + } + $this->_P[$i] ^= $data; + } + + for ($i = 0; $i <= 16; $i += 2) { + $this->_encipher($datal, $datar); + $this->_P[$i] = $datal; + $this->_P[$i+1] = $datar; + } + + for ($i = 0; $i < 256; $i += 2) { + $this->_encipher($datal, $datar); + $this->_S[0][$i] = $datal; + $this->_S[0][$i+1] = $datar; + } + + for ($i = 0; $i < 256; $i += 2) { + $this->_encipher($datal, $datar); + $this->_S[1][$i] = $datal; + $this->_S[1][$i+1] = $datar; + } + + for ($i = 0; $i < 256; $i += 2) { + $this->_encipher($datal, $datar); + $this->_S[2][$i] = $datal; + $this->_S[2][$i+1] = $datar; + } + + for ($i = 0; $i < 256; $i += 2) { + $this->_encipher($datal, $datar); + $this->_S[3][$i] = $datal; + $this->_S[3][$i+1] = $datar; + } + + $this->md5 = hash('md5', $key); + } + + /** + */ + abstract public function encrypt($text, $iv); + + /** + */ + abstract public function decrypt($text, $iv); + + /** + * Workaround for XOR on certain systems. + * + * @param integer|float $l + * @param integer|float $r + * + * @return float + */ + protected function _binxor($l, $r) + { + $x = (($l < 0) ? (float)($l + 4294967296) : (float)$l) + ^ (($r < 0) ? (float)($r + 4294967296) : (float)$r); + + return (float)(($x < 0) ? $x + 4294967296 : $x); + } + + /** + * Enciphers a single 64-bit block. + * + * @param int &$Xl + * @param int &$Xr + */ + protected function _encipher(&$Xl, &$Xr) + { + if ($Xl < 0) { + $Xl += 4294967296; + } + + if ($Xr < 0) { + $Xr += 4294967296; + } + + for ($i = 0; $i < 16; ++$i) { + $temp = $Xl ^ $this->_P[$i]; + if ($temp < 0) { + $temp += 4294967296; + } + + $Xl = fmod((fmod($this->_S[0][($temp >> 24) & 255] + + $this->_S[1][($temp >> 16) & 255], 4294967296) + ^ $this->_S[2][($temp >> 8) & 255]) + + $this->_S[3][$temp & 255], 4294967296) ^ $Xr; + $Xr = $temp; + } + + $Xr = $this->_binxor($Xl, $this->_P[16]); + $Xl = $this->_binxor($temp, $this->_P[17]); + } + + /** + * Deciphers a single 64-bit block. + * + * @param int &$Xl + * @param int &$Xr + */ + protected function _decipher(&$Xl, &$Xr) + { + if ($Xl < 0) { + $Xl += 4294967296; + } + if ($Xr < 0) { + $Xr += 4294967296; + } + + for ($i = 17; $i > 1; --$i) { + $temp = $Xl ^ $this->_P[$i]; + if ($temp < 0) { + $temp += 4294967296; + } + + $Xl = fmod((fmod($this->_S[0][($temp >> 24) & 255] + + $this->_S[1][($temp >> 16) & 255], 4294967296) + ^ $this->_S[2][($temp >> 8) & 255]) + + $this->_S[3][$temp & 255], 4294967296) ^ $Xr; + $Xr = $temp; + } + + $Xr = $this->_binxor($Xl, $this->_P[1]); + $Xl = $this->_binxor($temp, $this->_P[0]); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Cbc.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Cbc.php new file mode 100644 index 00000000..28443529 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Cbc.php @@ -0,0 +1,73 @@ + + * Copyright 2008 Philippe Jausions + * Copyright 2012-2017 Horde LLC (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.horde.org/licenses/lgpl21. + * + * @author Matthew Fonda + * @author Philippe Jausions + * @author Michael Slusarz + * @category Horde + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ + +/** + * PHP implementation of the Blowfish algorithm in CBC mode. + * + * @author Matthew Fonda + * @author Philippe Jausions + * @author Michael Slusarz + * @category Horde + * @copyright 2005-2008 Matthew Fonda + * @copyright 2008 Philippe Jausions + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ +class Horde_Crypt_Blowfish_Php_Cbc extends Horde_Crypt_Blowfish_Php_Base +{ + /** + */ + public function encrypt($text, $iv) + { + $cipherText = ''; + $len = strlen($text); + + list(, $Xl, $Xr) = unpack('N2', substr($text, 0, 8) ^ $iv); + $this->_encipher($Xl, $Xr); + $cipherText .= pack('N2', $Xl, $Xr); + + for ($i = 8; $i < $len; $i += 8) { + list(, $Xl, $Xr) = unpack('N2', substr($text, $i, 8) ^ substr($cipherText, $i - 8, 8)); + $this->_encipher($Xl, $Xr); + $cipherText .= pack('N2', $Xl, $Xr); + } + + return $cipherText; + } + + /** + */ + public function decrypt($text, $iv) + { + $plainText = ''; + $len = strlen($text); + + list(, $Xl, $Xr) = unpack('N2', substr($text, 0, 8)); + $this->_decipher($Xl, $Xr); + $plainText .= (pack('N2', $Xl, $Xr) ^ $iv); + + for ($i = 8; $i < $len; $i += 8) { + list(, $Xl, $Xr) = unpack('N2', substr($text, $i, 8)); + $this->_decipher($Xl, $Xr); + $plainText .= (pack('N2', $Xl, $Xr) ^ substr($text, $i - 8, 8)); + } + + return $plainText; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Ecb.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Ecb.php new file mode 100644 index 00000000..35c708db --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Crypt_Blowfish/Horde/Crypt/Blowfish/Php/Ecb.php @@ -0,0 +1,65 @@ + + * Copyright 2008 Philippe Jausions + * Copyright 2012-2017 Horde LLC (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.horde.org/licenses/lgpl21. + * + * @author Matthew Fonda + * @author Philippe Jausions + * @author Michael Slusarz + * @category Horde + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ + +/** + * PHP implementation of the Blowfish algorithm in ECB mode. + * + * @author Matthew Fonda + * @author Philippe Jausions + * @author Michael Slusarz + * @category Horde + * @copyright 2005-2008 Matthew Fonda + * @copyright 2008 Philippe Jausions + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Crypt_Blowfish + */ +class Horde_Crypt_Blowfish_Php_Ecb extends Horde_Crypt_Blowfish_Php_Base +{ + /** + */ + public function encrypt($text, $iv) + { + $cipherText = ''; + $len = strlen($text); + + for ($i = 0; $i < $len; $i += 8) { + list(, $Xl, $Xr) = unpack('N2', substr($text, $i, 8)); + $this->_encipher($Xl, $Xr); + $cipherText .= pack('N2', $Xl, $Xr); + } + + return $cipherText; + } + + /** + */ + public function decrypt($text, $iv) + { + $plainText = ''; + $len = strlen($text); + + for ($i = 0; $i < $len; $i += 8) { + list(, $Xl, $Xr) = unpack('N2', substr($text, $i, 8)); + $this->_decipher($Xl, $Xr); + $plainText .= pack('N2', $Xl, $Xr); + } + + return $plainText; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception.php new file mode 100644 index 00000000..f8f60c2d --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception.php @@ -0,0 +1,64 @@ +_logLevel; + } + + /** + * Sets the log level. + * + * @param mixed $level The log level. + */ + public function setLogLevel($level = 0) + { + if (is_string($level)) { + $level = defined('Horde_Log::' . $level) + ? constant('Horde_Log::' . $level) + : 0; + } + + $this->_logLevel = $level; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception/LastError.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception/LastError.php new file mode 100644 index 00000000..aab84f0e --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception/LastError.php @@ -0,0 +1,45 @@ +file = $code_or_lasterror['file']; + $this->line = $code_or_lasterror['line']; + } else { + parent::__construct($message, $code_or_lasterror); + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception/NotFound.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception/NotFound.php new file mode 100644 index 00000000..cee88cfa --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception/NotFound.php @@ -0,0 +1,31 @@ +getMessage(), $error->getCode()); + $this->details = $this->_getPearTrace($error); + } + + /** + * Return a trace for the PEAR error. + * + * @param PEAR_Error $error The PEAR error. + * + * @return string The backtrace as a string. + */ + private function _getPearTrace(PEAR_Error $error) + { + $pear_error = ''; + $backtrace = $error->getBacktrace(); + if (!empty($backtrace)) { + $pear_error .= 'PEAR backtrace:' . "\n\n"; + foreach ($backtrace as $frame) { + $pear_error .= + (isset($frame['class']) ? $frame['class'] : '') + . (isset($frame['type']) ? $frame['type'] : '') + . (isset($frame['function']) ? $frame['function'] : 'unkown') . ' ' + . (isset($frame['file']) ? $frame['file'] : 'unkown') . ':' + . (isset($frame['line']) ? $frame['line'] : 'unkown') . "\n"; + } + } + $userinfo = $error->getUserInfo(); + if (!empty($userinfo)) { + $pear_error .= "\n" . 'PEAR user info:' . "\n\n"; + if (is_string($userinfo)) { + $pear_error .= $userinfo; + } else { + $pear_error .= print_r($userinfo, true); + } + } + return $pear_error; + } + + /** + * Exception handling. + * + * @param mixed $result The result to be checked for a PEAR_Error. + * + * @return mixed Returns the original result if it was no PEAR_Error. + * + * @throws Horde_Exception_Pear In case the result was a PEAR_Error. + */ + public static function catchError($result) + { + if ($result instanceof PEAR_Error) { + throw new self::$_class($result); + } + return $result; + } +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception/PermissionDenied.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception/PermissionDenied.php new file mode 100644 index 00000000..2f5b0416 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception/PermissionDenied.php @@ -0,0 +1,31 @@ + + * @package Exception + */ +class Horde_Exception_Translation extends Horde_Translation_Autodetect +{ + /** + * The translation domain + * + * @var string + */ + protected static $_domain = 'Horde_Exception'; + + /** + * The absolute PEAR path to the translations for the default gettext handler. + * + * @var string + */ + protected static $_pearDirectory = '/daten/dev/lam/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data'; +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception/Wrapped.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception/Wrapped.php new file mode 100644 index 00000000..7143c8f9 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/Horde/Exception/Wrapped.php @@ -0,0 +1,46 @@ +getCode(); + } + if ($message instanceof Exception) { + $previous = $message; + } + if (method_exists($message, 'getUserinfo') && + $details = $message->getUserinfo()) { + $this->details = $details; + } elseif (!empty($message->details)) { + $this->details = $message->details; + } + $message = (string)$message->getMessage(); + } + + parent::__construct($message, $code, $previous); + } +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/Horde_Exception.pot b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/Horde_Exception.pot new file mode 100644 index 00000000..901041dc --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/Horde_Exception.pot @@ -0,0 +1,26 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception \n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2012-01-17 12:38+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ar/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ar/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..71938c49 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ar/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ar/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ar/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..4988b5c7 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ar/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,25 @@ +# Arabic translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "غير موجود" + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/bg/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/bg/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..71938c49 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/bg/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/bg/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/bg/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..1e487e2e --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/bg/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Bulgarian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "не беше намерен" + +#: lib/Horde/Exception/PermissionDenied.php:32 +#, fuzzy +msgid "Permission Denied" +msgstr "Права" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/bs/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/bs/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..71938c49 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/bs/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/bs/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/bs/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..c76a5325 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/bs/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Bosnian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "%s nije pronađen." + +#: lib/Horde/Exception/PermissionDenied.php:32 +#, fuzzy +msgid "Permission Denied" +msgstr "Dozvole" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ca/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ca/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..92e00ad4 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ca/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ca/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ca/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..8c19682e --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ca/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,25 @@ +# Catalan translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "No s'ha trobat." + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "Permis denegat" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/cs/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/cs/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..a2d7d9f6 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/cs/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/cs/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/cs/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..9650a891 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/cs/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Czech translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "Nenalezeno." + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "Přístup odepřen" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/da/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/da/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..2c7c2099 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/da/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/da/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/da/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..5c6c14e2 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/da/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Danish translations for Horde_Exception package. +# Copyright (C) 2014 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception package. +# Erling Preben Hansen , 2013-2014. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2012-01-17 12:38+0100\n" +"PO-Revision-Date: 2014-03-19 21:04+0100\n" +"Last-Translator: Erling Preben Hansen \n" +"Language-Team: i18n@lists.horde.org\n" +"Language: da\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Ikke fundet" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Tilladelse nægtet" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/de/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/de/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..8001cefb Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/de/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/de/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/de/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..22bd92d7 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/de/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# German translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2011-02-02 16:17+0100\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Nicht gefunden" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Zugriff verweigert" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/el/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/el/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..3649388d Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/el/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/el/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/el/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..66893ed7 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/el/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,27 @@ +# Greek translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2015-10-02 12:08+0200\n" +"Last-Translator: Antonis Limperis \n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Language: el\n" +"X-Generator: Poedit 1.7.1\n" + +#: lib/Horde/Exception/NotFound.php:32 +msgid "Not Found" +msgstr "Δεν Υπάρχει" + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "Δεν υπάρχουν δικαιώματα" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/es/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/es/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..b43eaf61 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/es/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/es/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/es/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..93f76a6d --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/es/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,27 @@ +# Spanish translations for Horde_Exception package. +# Copyright (C) 2013 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception package. +# Automatically generated, 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception \n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2012-01-17 12:38+0100\n" +"PO-Revision-Date: 2013-06-11 20:26+0200\n" +"Last-Translator: Manuel P. Ayala , Juan C. Blanco " +"\n" +"Language-Team: i18n@lists.horde.org\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "No encontrado" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Permiso denegado" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/et/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/et/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..2efb015d Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/et/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/et/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/et/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..a205f9d6 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/et/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Estonian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2011-02-02 16:17+0100\n" +"PO-Revision-Date: 2010-11-09 01:27+0200\n" +"Last-Translator: Alar Sing \n" +"Language-Team: i18n@lists.horde.org\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Ei Leitud" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Juurdepääs keelatud" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/eu/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/eu/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..2fc67250 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/eu/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/eu/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/eu/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..d2900baa --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/eu/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,27 @@ +# Basque translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2012-01-17 12:38+0100\n" +"PO-Revision-Date: 2013-01-16 10:17+0100\n" +"Last-Translator: Ibon Igartua \n" +"Language-Team: Euskal Herriko Unibertsitatea \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-Language: Basque\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Ez da aurkitu" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Baimena ukatu da" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fa/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fa/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..71938c49 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fa/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fa/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fa/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..db60103f --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fa/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Persian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "%s پیدا نشد" + +#: lib/Horde/Exception/PermissionDenied.php:32 +#, fuzzy +msgid "Permission Denied" +msgstr "مجوز" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fi/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fi/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..9467d0b6 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fi/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fi/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fi/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..75427a8c --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fi/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Finnish translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Leena Heino , 2010-2012. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2011-02-02 16:17+0100\n" +"PO-Revision-Date: 2012-03-07 15:05:44+0200\n" +"Last-Translator: Leena Heino \n" +"Language-Team: Finnish \n" +"Language: fi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Ei löytynyt" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Käyttö kielletty" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fr/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fr/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..a9766164 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fr/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fr/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fr/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..13b4f42a --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/fr/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,28 @@ +# French translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# Paul De Vlieger , 2013 +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception \n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2012-01-17 12:38+0100\n" +"PO-Revision-Date: 2013-01-14 11:54+0100\n" +"Last-Translator: Paul De Vlieger \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Lokalize 1.4\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Non trouvé" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Autorisation rejetée" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/gl/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/gl/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..71938c49 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/gl/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/gl/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/gl/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..59f9c9b0 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/gl/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,24 @@ +# Galician translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:32 +msgid "Not Found" +msgstr "" + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/he/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/he/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..b8d61640 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/he/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/he/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/he/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..3f5e3f18 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/he/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,25 @@ +# Hebrew translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Exception/NotFound.php:32 +msgid "Not Found" +msgstr "" + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/hr/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/hr/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..5339aa0e Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/hr/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/hr/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/hr/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..f7f66538 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/hr/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,27 @@ +# Croatian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Valentin Vidic , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2011-02-02 16:17+0100\n" +"PO-Revision-Date: 2011-11-08 16:49+0200\n" +"Last-Translator: Valentin Vidic \n" +"Language-Team: i18n@lists.horde.org\n" +"Language: hr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Nije pronađeno" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Pristup odbijen" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/hu/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/hu/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..be2e4faa Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/hu/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/hu/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/hu/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..a70e67be --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/hu/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,25 @@ +# Hungarian translations for Horde_Exception module. +# Copyright 2010-2013 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception \n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2012-01-17 12:38+0100\n" +"PO-Revision-Date: 2014-07-14 11:35+0200\n" +"Last-Translator: Andras Galos \n" +"Language-Team: i18n@lists.horde.org\n" +"Language: hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Nem található" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Hozzáférés megtagadva" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/id/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/id/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..70543261 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/id/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/id/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/id/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..49f6c34a --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/id/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,25 @@ +# Indonesian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ASCII\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:32 +msgid "Not Found" +msgstr "" + +#: lib/Horde/Exception/PermissionDenied.php:32 +#, fuzzy +msgid "Permission Denied" +msgstr "Izin" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/is/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/is/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..71938c49 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/is/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/is/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/is/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..9da93dd9 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/is/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,25 @@ +# Icelandic translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:32 +msgid "Not Found" +msgstr "" + +#: lib/Horde/Exception/PermissionDenied.php:32 +#, fuzzy +msgid "Permission Denied" +msgstr "Persónulegt" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/it/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/it/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..8056dfab Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/it/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/it/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/it/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..ad8c82ff --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/it/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Italian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "Nessun suono" + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "Permessi negati" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ja/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ja/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..2c15ac80 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ja/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ja/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ja/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..dcf26a72 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ja/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,27 @@ +# Japanese translation for Horde. +# Copyright 2004-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde package. +# Hiromi Kimura +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2012-01-17 12:38+0100\n" +"PO-Revision-Date: 2012-10-14 11:19+0900\n" +"Last-Translator: Hiromi Kimura \n" +"Language-Team: i18n@lists.horde.org\n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Poedit 1.5.4\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "見つかりません" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "アクセスは拒否されました" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/km/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/km/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..71938c49 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/km/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/km/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/km/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..f8d1aa8a --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/km/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,25 @@ +# Khmer translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:32 +msgid "Not Found" +msgstr "" + +#: lib/Horde/Exception/PermissionDenied.php:32 +#, fuzzy +msgid "Permission Denied" +msgstr "សិទ្ធិ​ត្រូវ​បាន​បដិសេធ" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ko/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ko/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..9cea0a32 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ko/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ko/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ko/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..b2c25c84 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ko/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Korean translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: lib/Horde/Exception/NotFound.php:32 +msgid "Not Found" +msgstr "" + +#: lib/Horde/Exception/PermissionDenied.php:32 +#, fuzzy +msgid "Permission Denied" +msgstr "개인 메일" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/lt/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/lt/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..2797485d Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/lt/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/lt/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/lt/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..68892672 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/lt/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Lithuanian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Vilius Šumskas , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2011-05-28 01:09+0300\n" +"PO-Revision-Date: 2011-06-27 23:04+0300\n" +"Last-Translator: Vilius Šumskas \n" +"Language-Team: Lithuanian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" +"%100<10 || n%100>=20) ? 1 : 2);\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Nerasta" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Neužtenka teisių" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/lv/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/lv/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..9a0e2f35 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/lv/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/lv/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/lv/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..a9c5dea1 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/lv/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,41 @@ +# Latvian translations for Horde_Exception package. +# Copyright 2011-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception package. +# Automatically generated, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2011-02-02 16:17+0100\n" +"PO-Revision-Date: 2011-10-16 15:21+0300\n" +"Last-Translator: Jānis Eisaks \n" +"Language-Team: i18n@lists.horde.org\n" +"Language: lv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" +"X-Poedit-Language: Latvian\n" +"X-Poedit-Country: LATVIA\n" +"X-Poedit-SourceCharset: utf-8\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Nav atrasts" + +# #-#-#-#-# horde.po (Horde 2.1) #-#-#-#-# +# #-#-#-#-# lv_LV.po (Mnemo 2.1.2) #-#-#-#-# +# +# #-#-#-#-# lv_LV.po (Ingo H3 (1.1.5)) #-#-#-#-# +# #-#-#-#-# lv_LV.po (Mnemo 2.1.2) #-#-#-#-# +# +# #-#-#-#-# mnemo.po (Mnemo 2.1.2) #-#-#-#-# +# +# #-#-#-#-# ingo.po (Ingo H3 (1.1.5)) #-#-#-#-# +# #-#-#-#-# lv_LV.po (Mnemo 2.1.2) #-#-#-#-# +# +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Pieeja liegta" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/mk/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/mk/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..71938c49 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/mk/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/mk/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/mk/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..20131a42 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/mk/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,24 @@ +# Macedonian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:32 +msgid "Not Found" +msgstr "" + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nb/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nb/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..b8d61640 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nb/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nb/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nb/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..e6b5cff4 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nb/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,27 @@ +# Norwegian Bokmal translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "ikke funnet" + +#: lib/Horde/Exception/PermissionDenied.php:32 +#, fuzzy +msgid "Permission Denied" +msgstr "Rettighet" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nl/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nl/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..cc8c1054 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nl/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nl/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nl/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..ad85c91f --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nl/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,27 @@ +# Dutch translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# +# Arjen de Korte , 2012. +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2012-01-17 12:38+0100\n" +"PO-Revision-Date: 2012-11-03 12:17+0100\n" +"Last-Translator: Arjen de Korte \n" +"Language-Team: Dutch \n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 1.4\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Niet gevonden" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Toegang geweigerd" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nn/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nn/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..b8d61640 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nn/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nn/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nn/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..243ac478 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/nn/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Norwegian Nynorsk translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Exception/NotFound.php:32 +msgid "Not Found" +msgstr "" + +#: lib/Horde/Exception/PermissionDenied.php:32 +#, fuzzy +msgid "Permission Denied" +msgstr "Tilgang" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pl/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pl/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..ed9a15d9 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pl/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pl/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pl/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..6391ca25 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pl/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,28 @@ +# Polish translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "%s nieznaleziony." + +#: lib/Horde/Exception/PermissionDenied.php:32 +#, fuzzy +msgid "Permission Denied" +msgstr "Uprawnienie" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pt/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pt/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..39337a35 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pt/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pt/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pt/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..5e93300a --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pt/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Portuguese translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "Não encontrado." + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "Permissão Negada" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pt_BR/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pt_BR/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..1984fc52 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pt_BR/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pt_BR/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pt_BR/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..2768a105 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/pt_BR/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Portuguese translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2012-01-17 12:38+0100\n" +"PO-Revision-Date: 2012-03-27 22:56-0300\n" +"Last-Translator: Luis Felipe Marzagao \n" +"Language-Team: i18n@lists.horde.org\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Não Encontrado" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Permissão Negada" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ro/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ro/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..212e6882 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ro/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ro/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ro/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..c57b456d --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ro/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Romanian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ASCII\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " +"20)) ? 1 : 2;\n" + +#: lib/Horde/Exception/NotFound.php:32 +msgid "Not Found" +msgstr "" + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ru/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ru/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..0aa090c6 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ru/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ru/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ru/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..2656e174 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/ru/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,30 @@ +# Russian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" +"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "Отменить изменения" + +# #-#-#-#-# ru_RU.po (Mnemo H3 2.2) #-#-#-#-# +# fuzzy +#: lib/Horde/Exception/PermissionDenied.php:32 +#, fuzzy +msgid "Permission Denied" +msgstr "Изменить права доступа" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sk/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sk/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..e01418ea Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sk/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sk/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sk/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..dd8ff96d --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sk/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Slovak translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2011-02-02 16:17+0100\n" +"PO-Revision-Date: 2011-05-18 16:10+0100\n" +"Last-Translator: Martin Matuška \n" +"Language-Team: i18n@lists.horde.org\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#: lib/Horde/Exception/NotFound.php:27 +msgid "Not Found" +msgstr "Nenájdené" + +#: lib/Horde/Exception/PermissionDenied.php:27 +msgid "Permission Denied" +msgstr "Prístup odmietnutý" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sl/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sl/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..8705e01d Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sl/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sl/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sl/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..c4bd1ae3 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sl/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,27 @@ +# Slovenian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "Ni najden." + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "Dovoljenje je zavrnjeno." diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sv/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sv/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..b8d61640 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sv/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sv/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sv/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..fdb96635 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/sv/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,27 @@ +# Swedish translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "%s saknas." + +#: lib/Horde/Exception/PermissionDenied.php:32 +#, fuzzy +msgid "Permission Denied" +msgstr "Behörighet" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/tr/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/tr/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..fd7b8273 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/tr/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/tr/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/tr/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..c75c2626 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/tr/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,26 @@ +# Turkish translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "Ses Yok" + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "İzin Yok" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/uk/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/uk/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..235eba11 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/uk/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/uk/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/uk/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..ca6dc35d --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/uk/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,25 @@ +# Ukrainian translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2013-04-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: lib/Horde/Exception/NotFound.php:32 +msgid "Not Found" +msgstr "Не знайдено" + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "Доступ заборонений" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/zh_CN/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/zh_CN/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..cfa09fd1 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/zh_CN/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/zh_CN/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/zh_CN/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..98a6ec86 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/zh_CN/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,25 @@ +# Chinese translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "未找到。" + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "权限不足" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/zh_TW/LC_MESSAGES/Horde_Exception.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/zh_TW/LC_MESSAGES/Horde_Exception.mo new file mode 100644 index 00000000..5062a7c6 Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/zh_TW/LC_MESSAGES/Horde_Exception.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/zh_TW/LC_MESSAGES/Horde_Exception.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/zh_TW/LC_MESSAGES/Horde_Exception.po new file mode 100644 index 00000000..367c479c --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Exception/data/locale/zh_TW/LC_MESSAGES/Horde_Exception.po @@ -0,0 +1,25 @@ +# Chinese translations for Horde_Exception module. +# Copyright 2010-2016 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Exception module. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Exception\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2010-10-13 01:27+0200\n" +"PO-Revision-Date: 2010-10-13 01:27+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Exception/NotFound.php:32 +#, fuzzy +msgid "Not Found" +msgstr "靜音" + +#: lib/Horde/Exception/PermissionDenied.php:32 +msgid "Permission Denied" +msgstr "存取遭拒" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/Horde/Idna.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/Horde/Idna.php new file mode 100644 index 00000000..4eb1f3ca --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/Horde/Idna.php @@ -0,0 +1,172 @@ + + * @category Horde + * @license http://www.horde.org/licenses/bsd BSD + * @package Idna + */ + +/** + * Provide normalized encoding/decoding support for IDNA strings. + * + * @author Michael Slusarz + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/bsd BSD + * @package Idna + */ +class Horde_Idna +{ + /** + * The backend to use. + * + * @var mixed + */ + protected static $_backend; + + /** + * @throws Horde_Idna_Exception + */ + public static function encode($data) + { + switch ($backend = static::_getBackend()) { + case 'INTL': + return idn_to_ascii($data); + + case 'INTL_UTS46': + $result = idn_to_ascii($data, 0, INTL_IDNA_VARIANT_UTS46, $info); + self::_checkForError($info); + return $result; + + default: + return $backend->encode($data); + } + } + + /** + * @throws Horde_Idna_Exception + */ + public static function decode($data) + { + switch ($backend = static::_getBackend()) { + case 'INTL': + case 'INTL_UTS46': + $parts = explode('.', $data); + foreach ($parts as &$part) { + if (strpos($part, 'xn--') === 0) { + switch ($backend) { + case 'INTL': + $part = idn_to_utf8($part); + break; + + case 'INTL_UTS46': + $part = idn_to_utf8($part, 0, INTL_IDNA_VARIANT_UTS46, $info); + self::_checkForError($info); + break; + } + } + } + return implode('.', $parts); + + default: + return $backend->decode($data); + } + } + + /** + * Checks if the $idna_info parameter of idn_to_ascii() or idn_to_utf8() + * contains errors. + * + * @param array $info Fourth parameter to idn_to_ascii() or idn_to_utf8(). + * + * @throws Horde_Idna_Exception + */ + protected static function _checkForError($info) + { + if (!isset($info['errors'])) { + return; + } + switch (true) { + case $info['errors'] & IDNA_ERROR_EMPTY_LABEL: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "Domain name is empty" + )); + case $info['errors'] & IDNA_ERROR_LABEL_TOO_LONG: + case $info['errors'] & IDNA_ERROR_DOMAIN_NAME_TOO_LONG: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "Domain name is too long" + )); + case $info['errors'] & IDNA_ERROR_LEADING_HYPHEN: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "Starts with a hyphen" + )); + case $info['errors'] & IDNA_ERROR_TRAILING_HYPHEN: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "Ends with a hyphen" + )); + case $info['errors'] & IDNA_ERROR_HYPHEN_3_4: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "Contains hyphen in the third and fourth positions" + )); + case $info['errors'] & IDNA_ERROR_LEADING_COMBINING_MARK: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "Starts with a combining mark" + )); + case $info['errors'] & IDNA_ERROR_DISALLOWED: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "Contains disallowed characters" + )); + case $info['errors'] & IDNA_ERROR_PUNYCODE: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "Starts with \"xn--\" but does not contain valid Punycode" + )); + case $info['errors'] & IDNA_ERROR_LABEL_HAS_DOT: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "Contains a dot" + )); + case $info['errors'] & IDNA_ERROR_INVALID_ACE_LABEL: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "ACE label does not contain a valid label string" + )); + case $info['errors'] & IDNA_ERROR_BIDI: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "Does not meet the IDNA BiDi requirements (for right-to-left characters)" + )); + case $info['errors'] & IDNA_ERROR_CONTEXTJ: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "Does not meet the IDNA CONTEXTJ requirements" + )); + case $info['errors']: + throw new Horde_Idna_Exception(Horde_Idna_Translation::t( + "Unknown error" + )); + } + } + + /** + * Return the IDNA backend. + * + * @return mixed IDNA backend (false if none available). + */ + protected static function _getBackend() + { + if (!isset(self::$_backend)) { + if (extension_loaded('intl')) { + /* Only available in PHP > 5.4.0 */ + self::$_backend = defined('INTL_IDNA_VARIANT_UTS46') + ? 'INTL_UTS46' + : 'INTL'; + } else { + self::$_backend = new Horde_Idna_Punycode(); + } + } + + return self::$_backend; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/Horde/Idna/Exception.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/Horde/Idna/Exception.php new file mode 100644 index 00000000..b3f57cbe --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/Horde/Idna/Exception.php @@ -0,0 +1,24 @@ + + * @category Horde + * @license http://www.horde.org/licenses/bsd BSD + * @package Idna + */ + +/** + * Exception class for the Horde_Idna package. + * + * @author Michael Slusarz + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/bsd BSD + * @package Idna + */ +class Horde_Idna_Exception extends Horde_Exception +{} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/Horde/Idna/Punycode.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/Horde/Idna/Punycode.php new file mode 100644 index 00000000..d940ed31 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/Horde/Idna/Punycode.php @@ -0,0 +1,354 @@ + + * @author Michael Slusarz + * @category Horde + * @license http://www.horde.org/licenses/bsd BSD + * @package Idna + */ + +/** + * Punycode implementation as described in RFC 3492. + * + * Original code (v1.0.1; released under the MIT License): + * https://github.com/true/php-punycode/ + * + * @author Renan Gonçalves + * @author Michael Slusarz + * @category Horde + * @copyright 2014 TrueServer B.V. + * @copyright 2015-2017 Horde LLC + * @license http://www.horde.org/licenses/bsd BSD + * @package Idna + * @link http://tools.ietf.org/html/rfc3492 + */ +class Horde_Idna_Punycode +{ + /** + * Bootstring parameter values. + */ + const BASE = 36; + const TMIN = 1; + const TMAX = 26; + const SKEW = 38; + const DAMP = 700; + const INITIAL_BIAS = 72; + const INITIAL_N = 128; + const PREFIX = 'xn--'; + const DELIMITER = '-'; + + /** + * Encode table. + * + * @param array + */ + protected static $_encodeTable = array( + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + ); + + /** + * Decode table. + * + * @param array + */ + protected static $_decodeTable = array( + 'a' => 0, 'b' => 1, 'c' => 2, 'd' => 3, 'e' => 4, 'f' => 5, + 'g' => 6, 'h' => 7, 'i' => 8, 'j' => 9, 'k' => 10, 'l' => 11, + 'm' => 12, 'n' => 13, 'o' => 14, 'p' => 15, 'q' => 16, 'r' => 17, + 's' => 18, 't' => 19, 'u' => 20, 'v' => 21, 'w' => 22, 'x' => 23, + 'y' => 24, 'z' => 25, '0' => 26, '1' => 27, '2' => 28, '3' => 29, + '4' => 30, '5' => 31, '6' => 32, '7' => 33, '8' => 34, '9' => 35 + ); + + /** + * Encode a domain to its Punycode version. + * + * @param string $input Domain name in Unicde to be encoded. + * + * @return string Punycode representation in ASCII. + */ + public function encode($input) + { + $parts = explode('.', $input); + + foreach ($parts as &$part) { + $part = $this->_encodePart($part); + } + + return implode('.', $parts); + } + + /** + * Encode a part of a domain name, such as tld, to its Punycode version. + * + * @param string $input Part of a domain name. + * + * @return string Punycode representation of a domain part. + */ + protected function _encodePart($input) + { + $codePoints = $this->_codePoints($input); + + $n = static::INITIAL_N; + $bias = static::INITIAL_BIAS; + $delta = 0; + $h = $b = count($codePoints['basic']); + + $output = ''; + foreach ($codePoints['basic'] as $code) { + $output .= $this->_codePointToChar($code); + } + if ($input === $output) { + return $output; + } + if ($b > 0) { + $output .= static::DELIMITER; + } + + $codePoints['nonBasic'] = array_unique($codePoints['nonBasic']); + sort($codePoints['nonBasic']); + + $i = 0; + $length = Horde_String::length($input, 'UTF-8'); + + while ($h < $length) { + $m = $codePoints['nonBasic'][$i++]; + $delta = $delta + ($m - $n) * ($h + 1); + $n = $m; + + foreach ($codePoints['all'] as $c) { + if (($c < $n) || ($c < static::INITIAL_N)) { + ++$delta; + } + + if ($c === $n) { + $q = $delta; + for ($k = static::BASE; ; $k += static::BASE) { + $t = $this->_calculateThreshold($k, $bias); + if ($q < $t) { + break; + } + + $code = $t + (($q - $t) % (static::BASE - $t)); + $output .= static::$_encodeTable[$code]; + + $q = ($q - $t) / (static::BASE - $t); + } + + $output .= static::$_encodeTable[$q]; + $bias = $this->_adapt($delta, $h + 1, ($h === $b)); + $delta = 0; + ++$h; + } + } + + ++$delta; + ++$n; + } + + return static::PREFIX . $output; + } + + /** + * Decode a Punycode domain name to its Unicode counterpart. + * + * @param string $input Domain name in Punycode + * + * @return string Unicode domain name. + */ + public function decode($input) + { + $parts = explode('.', $input); + + foreach ($parts as &$part) { + if (strpos($part, static::PREFIX) === 0) { + $part = $this->_decodePart( + substr($part, strlen(static::PREFIX)) + ); + } + } + + return implode('.', $parts); + } + + /** + * Decode a part of domain name, such as tld. + * + * @param string $input Part of a domain name. + * + * @return string Unicode domain part. + */ + protected function _decodePart($input) + { + $n = static::INITIAL_N; + $i = 0; + $bias = static::INITIAL_BIAS; + $output = ''; + + $pos = strrpos($input, static::DELIMITER); + if ($pos !== false) { + $output = substr($input, 0, $pos++); + } else { + $pos = 0; + } + + $outputLength = strlen($output); + $inputLength = strlen($input); + + /* Punycode lookup is case-insensitive. */ + $input = Horde_String::lower($input); + + while ($pos < $inputLength) { + $oldi = $i; + $w = 1; + + for ($k = static::BASE; ; $k += static::BASE) { + $digit = static::$_decodeTable[$input[$pos++]]; + $i = $i + ($digit * $w); + $t = $this->_calculateThreshold($k, $bias); + + if ($digit < $t) { + break; + } + + $w = $w * (static::BASE - $t); + } + + $bias = $this->_adapt($i - $oldi, ++$outputLength, ($oldi === 0)); + $n = $n + (int) ($i / $outputLength); + $i = $i % ($outputLength); + + $output = Horde_String::substr($output, 0, $i, 'UTF-8') . + $this->_codePointToChar($n) . + Horde_String::substr($output, $i, $outputLength - 1, 'UTF-8'); + + ++$i; + } + + return $output; + } + + /** + * Calculate the bias threshold to fall between TMIN and TMAX. + * + * @param integer $k + * @param integer $bias + * + * @return integer + */ + protected function _calculateThreshold($k, $bias) + { + if ($k <= ($bias + static::TMIN)) { + return static::TMIN; + } elseif ($k >= ($bias + static::TMAX)) { + return static::TMAX; + } + return $k - $bias; + } + + /** + * Bias adaptation. + * + * @param integer $delta + * @param integer $numPoints + * @param boolean $firstTime + * + * @return integer + */ + protected function _adapt($delta, $numPoints, $firstTime) + { + $delta = (int) ( + ($firstTime) + ? $delta / static::DAMP + : $delta / 2 + ); + $delta += (int) ($delta / $numPoints); + + $k = 0; + while ($delta > ((static::BASE - static::TMIN) * static::TMAX) / 2) { + $delta = (int) ($delta / (static::BASE - static::TMIN)); + $k = $k + static::BASE; + } + $k = $k + (int) (((static::BASE - static::TMIN + 1) * $delta) / ($delta + static::SKEW)); + + return $k; + } + + /** + * List code points for a given input. + * + * @param string $input + * + * @return array Multi-dimension array with basic, non-basic and + * aggregated code points. + */ + protected function _codePoints($input) + { + $codePoints = array( + 'all' => array(), + 'basic' => array(), + 'nonBasic' => array() + ); + + $len = Horde_String::length($input, 'UTF-8'); + for ($i = 0; $i < $len; ++$i) { + $char = Horde_String::substr($input, $i, 1, 'UTF-8'); + $code = $this->_charToCodePoint($char); + if ($code < 128) { + $codePoints['all'][] = $codePoints['basic'][] = $code; + } else { + $codePoints['all'][] = $codePoints['nonBasic'][] = $code; + } + } + + return $codePoints; + } + + /** + * Convert a single or multi-byte character to its code point. + * + * @param string $char + * + * @return integer + */ + protected function _charToCodePoint($char) + { + $code = ord($char[0]); + if ($code < 128) { + return $code; + } elseif ($code < 224) { + return (($code - 192) * 64) + (ord($char[1]) - 128); + } elseif ($code < 240) { + return (($code - 224) * 4096) + ((ord($char[1]) - 128) * 64) + (ord($char[2]) - 128); + } + return (($code - 240) * 262144) + ((ord($char[1]) - 128) * 4096) + ((ord($char[2]) - 128) * 64) + (ord($char[3]) - 128); + } + + /** + * Convert a code point to its single or multi-byte character + * + * @param integer $code + * + * @return string + */ + protected function _codePointToChar($code) + { + if ($code <= 0x7F) { + return chr($code); + } elseif ($code <= 0x7FF) { + return chr(($code >> 6) + 192) . chr(($code & 63) + 128); + } elseif ($code <= 0xFFFF) { + return chr(($code >> 12) + 224) . chr((($code >> 6) & 63) + 128) . chr(($code & 63) + 128); + } + return chr(($code >> 18) + 240) . chr((($code >> 12) & 63) + 128) . chr((($code >> 6) & 63) + 128) . chr(($code & 63) + 128); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/Horde/Idna/Translation.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/Horde/Idna/Translation.php new file mode 100644 index 00000000..e4820f22 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/Horde/Idna/Translation.php @@ -0,0 +1,40 @@ + + * @category Horde + * @license http://www.horde.org/licenses/bsd BSD + * @package Idna + */ + +/** + * Horde_Idna_Translation is the translation wrapper class for + * Horde_Idna. + * + * @author Jan Schneider + * @category Horde + * @copyright 2017 Horde LLC + * @license http://www.horde.org/licenses/bsd BSD + * @package Idna + * @since Horde_Idna 1.1.0 + */ +class Horde_Idna_Translation extends Horde_Translation_Autodetect +{ + /** + * The translation domain + * + * @var string + */ + protected static $_domain = 'Horde_Idna'; + + /** + * The absolute PEAR path to the translations for the default gettext handler. + * + * @var string + */ + protected static $_pearDirectory = '/daten/dev/lam/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data'; +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/Horde_Idna.pot b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/Horde_Idna.pot new file mode 100644 index 00000000..89a4a026 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/Horde_Idna.pot @@ -0,0 +1,70 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Idna package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Horde_Idna\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2017-07-26 12:13+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/Horde/Idna.php:131 +msgid "ACE label does not contain a valid label string" +msgstr "" + +#: lib/Horde/Idna.php:127 +msgid "Contains a dot" +msgstr "" + +#: lib/Horde/Idna.php:119 +msgid "Contains disallowed characters" +msgstr "" + +#: lib/Horde/Idna.php:111 +msgid "Contains hyphen in the third and fourth positions" +msgstr "" + +#: lib/Horde/Idna.php:135 +msgid "Does not meet the IDNA BiDi requirements (for right-to-left characters)" +msgstr "" + +#: lib/Horde/Idna.php:139 +msgid "Does not meet the IDNA CONTEXTJ requirements" +msgstr "" + +#: lib/Horde/Idna.php:94 +msgid "Domain name is empty" +msgstr "" + +#: lib/Horde/Idna.php:99 +msgid "Domain name is too long" +msgstr "" + +#: lib/Horde/Idna.php:107 +msgid "Ends with a hyphen" +msgstr "" + +#: lib/Horde/Idna.php:123 +msgid "Starts with \"xn--\" but does not contain valid Punycode" +msgstr "" + +#: lib/Horde/Idna.php:115 +msgid "Starts with a combining mark" +msgstr "" + +#: lib/Horde/Idna.php:103 +msgid "Starts with a hyphen" +msgstr "" + +#: lib/Horde/Idna.php:143 +msgid "Unknown error" +msgstr "" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/de/LC_MESSAGES/Horde_Idna.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/de/LC_MESSAGES/Horde_Idna.mo new file mode 100644 index 00000000..8d922e4d Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/de/LC_MESSAGES/Horde_Idna.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/de/LC_MESSAGES/Horde_Idna.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/de/LC_MESSAGES/Horde_Idna.po new file mode 100644 index 00000000..f1708261 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/de/LC_MESSAGES/Horde_Idna.po @@ -0,0 +1,71 @@ +# German translations for Horde_Idna package. +# Copyright (C) 2017 Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Idna package. +# Jan Schneider , 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Idna\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2017-07-26 12:13+0200\n" +"PO-Revision-Date: 2017-01-24 11:33+0100\n" +"Last-Translator: Automatically generated\n" +"Language-Team: i18n@lists.horde.org\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: lib/Horde/Idna.php:131 +msgid "ACE label does not contain a valid label string" +msgstr "ACE-Label enthält keinen gültigen Labeltext" + +#: lib/Horde/Idna.php:127 +msgid "Contains a dot" +msgstr "Enthält einen Punkt" + +#: lib/Horde/Idna.php:119 +msgid "Contains disallowed characters" +msgstr "Enthält ungültige Zeichen" + +#: lib/Horde/Idna.php:111 +msgid "Contains hyphen in the third and fourth positions" +msgstr "Enthält Bindestrich an der dritten und vierten Stelle" + +#: lib/Horde/Idna.php:135 +msgid "Does not meet the IDNA BiDi requirements (for right-to-left characters)" +msgstr "" +"Entspricht nicht den IDNA-BiDi-Anforderungen (für rechts-nach-links Zeichen)" + +#: lib/Horde/Idna.php:139 +msgid "Does not meet the IDNA CONTEXTJ requirements" +msgstr "Entspricht nicht den IDNA-CONTEXTJ-Anforderungen" + +#: lib/Horde/Idna.php:94 +msgid "Domain name is empty" +msgstr "Domainname ist leer" + +#: lib/Horde/Idna.php:99 +msgid "Domain name is too long" +msgstr "Domainname ist zu lang" + +#: lib/Horde/Idna.php:107 +msgid "Ends with a hyphen" +msgstr "Endet mit einem Bindestrich" + +#: lib/Horde/Idna.php:123 +msgid "Starts with \"xn--\" but does not contain valid Punycode" +msgstr "Beginnt mit \"xn--\" aber enthält keinen gültigen Punycode" + +#: lib/Horde/Idna.php:115 +msgid "Starts with a combining mark" +msgstr "Beginnt mit einem Kombinationszeichen" + +#: lib/Horde/Idna.php:103 +msgid "Starts with a hyphen" +msgstr "Beginnt mit einem Bindestrich" + +#: lib/Horde/Idna.php:143 +msgid "Unknown error" +msgstr "Unbekannter Fehler" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/tr/LC_MESSAGES/Horde_Idna.mo b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/tr/LC_MESSAGES/Horde_Idna.mo new file mode 100644 index 00000000..4d6f96ee Binary files /dev/null and b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/tr/LC_MESSAGES/Horde_Idna.mo differ diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/tr/LC_MESSAGES/Horde_Idna.po b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/tr/LC_MESSAGES/Horde_Idna.po new file mode 100644 index 00000000..6dd1766a --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Idna/data/locale/tr/LC_MESSAGES/Horde_Idna.po @@ -0,0 +1,71 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Horde LLC (http://www.horde.org/) +# This file is distributed under the same license as the Horde_Idna package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Horde_Idna\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2017-06-09 15:53+0300\n" +"PO-Revision-Date: 2017-06-09 16:18+0300\n" +"Language-Team: İTÜ BİDB \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.12\n" +"Last-Translator: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Language: tr\n" + +#: lib/Horde/Idna.php:83 +msgid "ACE label does not contain a valid label string" +msgstr "ACE etiketi geçerli bir etiket dizesi içermiyor" + +#: lib/Horde/Idna.php:79 +msgid "Contains a dot" +msgstr "Bir nokta içeriyor" + +#: lib/Horde/Idna.php:71 +msgid "Contains disallowed characters" +msgstr "İzin verilmeyen karakterler içeriyor" + +#: lib/Horde/Idna.php:63 +msgid "Contains hyphen in the third and fourth positions" +msgstr "Üçüncü ve dördüncü konumda tire içeriyor" + +#: lib/Horde/Idna.php:87 +msgid "Does not meet the IDNA BiDi requirements (for right-to-left characters)" +msgstr "IDNA BiDi gereksinimlerini karşılamıyor (sağdan sola karakterler için)" + +#: lib/Horde/Idna.php:91 +msgid "Does not meet the IDNA CONTEXTJ requirements" +msgstr "IDNA CONTEXTJ gereksinimlerini karşılamıyor" + +#: lib/Horde/Idna.php:46 +msgid "Domain name is empty" +msgstr "Alan adı boş" + +#: lib/Horde/Idna.php:51 +msgid "Domain name is too long" +msgstr "Alan adı çok uzun" + +#: lib/Horde/Idna.php:59 +msgid "Ends with a hyphen" +msgstr "Tire ile bitiyor" + +#: lib/Horde/Idna.php:75 +msgid "Starts with \"xn--\" but does not contain valid Punycode" +msgstr "\"Xn--\" ile başlıyor ancak geçerli Punycode içermiyor" + +#: lib/Horde/Idna.php:67 +msgid "Starts with a combining mark" +msgstr "Birleştirme işaretiyle başlıyor" + +#: lib/Horde/Idna.php:55 +msgid "Starts with a hyphen" +msgstr "Tire ile başlıyor" + +#: lib/Horde/Idna.php:95 +msgid "Unknown error" +msgstr "Bilinmeyen hata" diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client.php new file mode 100644 index 00000000..36064b85 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client.php @@ -0,0 +1,203 @@ + + * @category Horde + * @copyright 2008-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client +{ + /* Constants for openMailbox() */ + const OPEN_READONLY = 1; + const OPEN_READWRITE = 2; + const OPEN_AUTO = 3; + + /* Constants for listMailboxes() */ + const MBOX_SUBSCRIBED = 1; + const MBOX_SUBSCRIBED_EXISTS = 2; + const MBOX_UNSUBSCRIBED = 3; + const MBOX_ALL = 4; + /* @since 2.23.0 */ + const MBOX_ALL_SUBSCRIBED = 5; + + /* Constants for status() */ + const STATUS_MESSAGES = 1; + const STATUS_RECENT = 2; + const STATUS_UIDNEXT = 4; + const STATUS_UIDVALIDITY = 8; + const STATUS_UNSEEN = 16; + const STATUS_ALL = 32; + const STATUS_FIRSTUNSEEN = 64; + const STATUS_FLAGS = 128; + const STATUS_PERMFLAGS = 256; + const STATUS_HIGHESTMODSEQ = 512; + const STATUS_SYNCMODSEQ = 1024; + const STATUS_SYNCFLAGUIDS = 2048; + const STATUS_UIDNOTSTICKY = 4096; + const STATUS_UIDNEXT_FORCE = 8192; + const STATUS_SYNCVANISHED = 16384; + /* @since 2.12.0 */ + const STATUS_RECENT_TOTAL = 32768; + /* @since 2.14.0 */ + const STATUS_FORCE_REFRESH = 65536; + + /* Constants for search() */ + const SORT_ARRIVAL = 1; + const SORT_CC = 2; + const SORT_DATE = 3; + const SORT_FROM = 4; + const SORT_REVERSE = 5; + const SORT_SIZE = 6; + const SORT_SUBJECT = 7; + const SORT_TO = 8; + /* SORT_THREAD provided for completeness - it is not a valid sort criteria + * for search() (use thread() instead). */ + const SORT_THREAD = 9; + /* Sort criteria defined in RFC 5957 */ + const SORT_DISPLAYFROM = 10; + const SORT_DISPLAYTO = 11; + /* SORT_SEQUENCE does a simple numerical sort on the returned + * UIDs/sequence numbers. */ + const SORT_SEQUENCE = 12; + /* Fuzzy sort criteria defined in RFC 6203 */ + const SORT_RELEVANCY = 13; + /* @since 2.4.0 */ + const SORT_DISPLAYFROM_FALLBACK = 14; + /* @since 2.4.0 */ + const SORT_DISPLAYTO_FALLBACK = 15; + + /* Search results constants */ + const SEARCH_RESULTS_COUNT = 1; + const SEARCH_RESULTS_MATCH = 2; + const SEARCH_RESULTS_MAX = 3; + const SEARCH_RESULTS_MIN = 4; + const SEARCH_RESULTS_SAVE = 5; + /* Fuzzy sort criteria defined in RFC 6203 */ + const SEARCH_RESULTS_RELEVANCY = 6; + + /* Constants for thread() */ + const THREAD_ORDEREDSUBJECT = 1; + const THREAD_REFERENCES = 2; + const THREAD_REFS = 3; + + /* Fetch criteria constants. */ + const FETCH_STRUCTURE = 1; + const FETCH_FULLMSG = 2; + const FETCH_HEADERTEXT = 3; + const FETCH_BODYTEXT = 4; + const FETCH_MIMEHEADER = 5; + const FETCH_BODYPART = 6; + const FETCH_BODYPARTSIZE = 7; + const FETCH_HEADERS = 8; + const FETCH_ENVELOPE = 9; + const FETCH_FLAGS = 10; + const FETCH_IMAPDATE = 11; + const FETCH_SIZE = 12; + const FETCH_UID = 13; + const FETCH_SEQ = 14; + const FETCH_MODSEQ = 15; + /* @since 2.11.0 */ + const FETCH_DOWNGRADED = 16; + + /* Namespace constants. @deprecated */ + const NS_PERSONAL = 1; + const NS_OTHER = 2; + const NS_SHARED = 3; + + /* ACL constants (RFC 4314 [2.1]). */ + const ACL_LOOKUP = 'l'; + const ACL_READ = 'r'; + const ACL_SEEN = 's'; + const ACL_WRITE = 'w'; + const ACL_INSERT = 'i'; + const ACL_POST = 'p'; + const ACL_CREATEMBOX = 'k'; + const ACL_DELETEMBOX = 'x'; + const ACL_DELETEMSGS = 't'; + const ACL_EXPUNGE = 'e'; + const ACL_ADMINISTER = 'a'; + // Old constants (RFC 2086 [3]; RFC 4314 [2.1.1]) + const ACL_CREATE = 'c'; + const ACL_DELETE = 'd'; + + /* System flags. */ + // RFC 3501 [2.3.2] + const FLAG_ANSWERED = '\\answered'; + const FLAG_DELETED = '\\deleted'; + const FLAG_DRAFT = '\\draft'; + const FLAG_FLAGGED = '\\flagged'; + const FLAG_RECENT = '\\recent'; + const FLAG_SEEN = '\\seen'; + // RFC 3503 [3.3] + const FLAG_MDNSENT = '$mdnsent'; + // RFC 5550 [2.8] + const FLAG_FORWARDED = '$forwarded'; + // RFC 5788 registered keywords: + // http://www.ietf.org/mail-archive/web/morg/current/msg00441.html + const FLAG_JUNK = '$junk'; + const FLAG_NOTJUNK = '$notjunk'; + + /* Special-use mailbox attributes (RFC 6154 [2]). */ + const SPECIALUSE_ALL = '\\All'; + const SPECIALUSE_ARCHIVE = '\\Archive'; + const SPECIALUSE_DRAFTS = '\\Drafts'; + const SPECIALUSE_FLAGGED = '\\Flagged'; + const SPECIALUSE_JUNK = '\\Junk'; + const SPECIALUSE_SENT = '\\Sent'; + const SPECIALUSE_TRASH = '\\Trash'; + + /* Constants for sync(). */ + const SYNC_UIDVALIDITY = 0; + const SYNC_FLAGS = 1; + const SYNC_FLAGSUIDS = 2; + const SYNC_NEWMSGS = 4; + const SYNC_NEWMSGSUIDS = 8; + const SYNC_VANISHED = 16; + const SYNC_VANISHEDUIDS = 32; + const SYNC_ALL = 64; + + /** + * Capability dependencies. + * + * @deprecated + * + * @var array + */ + public static $capability_deps = array( + // RFC 7162 [3.2] + 'QRESYNC' => array( + // QRESYNC requires CONDSTORE, but the latter is implied and is + // not required to be listed. + 'ENABLE' + ), + // RFC 5182 [2.1] + 'SEARCHRES' => array( + 'ESEARCH' + ), + // RFC 5255 [3.1] + 'LANGUAGE' => array( + 'NAMESPACE' + ), + // RFC 5957 [1] + 'SORT=DISPLAY' => array( + 'SORT' + ) + ); + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Auth/DigestMD5.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Auth/DigestMD5.php new file mode 100644 index 00000000..bbeeb4ec --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Auth/DigestMD5.php @@ -0,0 +1,189 @@ + + * @author Michael Slusarz + * @copyright 2002-2003 Richard Heyes + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Auth_DigestMD5 +{ + /** + * Digest response components. + * + * @var string + */ + protected $_response; + + /** + * Generate the Digest-MD5 response. + * + * @param string $id Authentication id (username). + * @param string $pass Password. + * @param string $challenge The digest challenge sent by the server. + * @param string $hostname The hostname of the machine connecting to. + * @param string $service The service name (e.g. 'imap', 'pop3'). + * + * @throws Horde_Imap_Client_Exception + */ + public function __construct($id, $pass, $challenge, $hostname, $service) + { + $challenge = $this->_parseChallenge($challenge); + $cnonce = $this->_getCnonce(); + $digest_uri = sprintf('%s/%s', $service, $hostname); + + /* Get response value. */ + $A1 = sprintf('%s:%s:%s', pack('H32', hash('md5', sprintf('%s:%s:%s', $id, $challenge['realm'], $pass))), $challenge['nonce'], $cnonce); + $A2 = 'AUTHENTICATE:' . $digest_uri; + $response_value = hash('md5', sprintf('%s:%s:00000001:%s:auth:%s', hash('md5', $A1), $challenge['nonce'], $cnonce, hash('md5', $A2))); + + $this->_response = array( + 'cnonce' => '"' . $cnonce . '"', + 'digest-uri' => '"' . $digest_uri . '"', + 'maxbuf' => $challenge['maxbuf'], + 'nc' => '00000001', + 'nonce' => '"' . $challenge['nonce'] . '"', + 'qop' => 'auth', + 'response' => $response_value, + 'username' => '"' . $id . '"' + ); + + if (strlen($challenge['realm'])) { + $this->_response['realm'] = '"' . $challenge['realm'] . '"'; + } + } + + /** + * Cooerce to string. + * + * @return string The digest response (not base64 encoded). + */ + public function __toString() + { + $out = array(); + foreach ($this->_response as $key => $val) { + $out[] = $key . '=' . $val; + } + return implode(',', $out); + } + + /** + * Return specific digest response directive. + * + * @return mixed Requested directive, or null if it does not exist. + */ + public function __get($name) + { + return isset($this->_response[$name]) + ? $this->_response[$name] + : null; + } + + /** + * Parses and verifies the digest challenge. + * + * @param string $challenge The digest challenge + * + * @return array The parsed challenge as an array with directives as keys. + * + * @throws Horde_Imap_Client_Exception + */ + protected function _parseChallenge($challenge) + { + $tokens = array( + 'maxbuf' => 65536, + 'realm' => '' + ); + + preg_match_all('/([a-z-]+)=("[^"]+(? + * @category Horde + * @copyright 2015-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.29.0 + */ +class Horde_Imap_Client_Auth_Scram +{ + /** + * AuthMessage (RFC 5802 [3]). + * + * @var string + */ + protected $_authmsg; + + /** + * Hash name. + * + * @var string + */ + protected $_hash; + + /** + * Number of Hi iterations (RFC 5802 [2]). + * + * @var integer + */ + protected $_iterations; + + /** + * Nonce. + * + * @var string + */ + protected $_nonce; + + /** + * Password. + * + * @var string + */ + protected $_pass; + + /** + * Server salt. + * + * @var string + */ + protected $_salt; + + /** + * Calculated server signature value. + * + * @var string + */ + protected $_serversig; + + /** + * Username. + * + * @var string + */ + protected $_user; + + /** + * Constructor. + * + * @param string $user Username. + * @param string $pass Password. + * @param string $hash Hash name. + * + * @throws Horde_Imap_Client_Exception + */ + public function __construct($user, $pass, $hash = 'SHA1') + { + $error = false; + + $this->_hash = $hash; + + try { + if (!class_exists('Horde_Stringprep') || + !class_exists('Horde_Crypt_Blowfish_Pbkdf2')) { + throw new Exception(); + } + + Horde_Stringprep::autoload(); + $saslprep = new Znerol\Component\Stringprep\Profile\SASLprep(); + + $this->_user = $saslprep->apply( + $user, + 'UTF-8', + Znerol\Component\Stringprep\Profile::MODE_QUERY + ); + $this->_pass = $saslprep->apply( + $pass, + 'UTF-8', + Znerol\Component\Stringprep\Profile::MODE_STORE + ); + } catch (Znerol\Component\Stringprep\ProfileException $e) { + $error = true; + } catch (Exception $e) { + $error = true; + } + + if ($error) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Authentication failure."), + Horde_Imap_Client_Exception::LOGIN_AUTHORIZATIONFAILED + ); + } + + /* Generate nonce. (Done here so this can be overwritten for + * testing purposes.) */ + $this->_nonce = strval(new Horde_Support_Randomid()); + } + + /** + * Return the initial client message. + * + * @return string Initial client message. + */ + public function getClientFirstMessage() + { + /* n: client doesn't support channel binding, + * , + * n=: SASLprepped username with "," and "=" escaped, + * r=: Random nonce */ + $this->_authmsg = 'n=' . str_replace( + array(',', '='), + array('=2C', '=3D'), + $this->_user + ) . ',r=' . $this->_nonce; + + return 'n,,' . $this->_authmsg; + } + + /** + * Process the initial server message response. + * + * @param string $msg Initial server response. + * + * @return boolean False if authentication failed at this stage. + */ + public function parseServerFirstMessage($msg) + { + $i = $r = $s = false; + + foreach (explode(',', $msg) as $val) { + list($attr, $aval) = array_map('trim', explode('=', $val, 2)); + + switch ($attr) { + case 'i': + $this->_iterations = intval($aval); + $i = true; + break; + + case 'r': + /* Beginning of server-provided nonce MUST be the same as the + * nonce we provided. */ + if (strpos($aval, $this->_nonce) !== 0) { + return false; + } + $this->_nonce = $aval; + $r = true; + break; + + case 's': + $this->_salt = base64_decode($aval); + $s = true; + break; + } + } + + if ($i && $r && $s) { + $this->_authmsg .= ',' . $msg; + return true; + } + + return false; + } + + /** + * Return the final client message. + * + * @return string Final client message. + */ + public function getClientFinalMessage() + { + $final_msg = 'c=biws,r=' . $this->_nonce; + + /* Salted password. */ + $s_pass = strval(new Horde_Crypt_Blowfish_Pbkdf2( + $this->_pass, + strlen(hash($this->_hash, '', true)), + array( + 'algo' => $this->_hash, + 'i_count' => $this->_iterations, + 'salt' => $this->_salt + ) + )); + + /* Client key. */ + $c_key = hash_hmac($this->_hash, 'Client Key', $s_pass, true); + + /* Stored key. */ + $s_key = hash($this->_hash, $c_key, true); + + /* Client signature. */ + $auth_msg = $this->_authmsg . ',' . $final_msg; + $c_sig = hash_hmac($this->_hash, $auth_msg, $s_key, true); + + /* Proof. */ + $proof = $c_key ^ $c_sig; + + /* Server signature. */ + $this->_serversig = hash_hmac( + $this->_hash, + $auth_msg, + hash_hmac($this->_hash, 'Server Key', $s_pass, true), + true + ); + + /* c=biws: channel-binding ("biws" = base64('n,,')), + * p=: base64 encoded ClientProof, + * r=: Nonce as returned from the server. */ + return $final_msg . ',p=' . base64_encode($proof); + } + + /** + * Process the final server message response. + * + * @param string $msg Final server response. + * + * @return boolean False if authentication failed. + */ + public function parseServerFinalMessage($msg) + { + foreach (explode(',', $msg) as $val) { + list($attr, $aval) = array_map('trim', explode('=', $val, 2)); + + switch ($attr) { + case 'e': + return false; + + case 'v': + return (base64_decode($aval) === $this->_serversig); + } + } + + return false; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base.php new file mode 100644 index 00000000..1a2f53cd --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base.php @@ -0,0 +1,4082 @@ + + * @category Horde + * @copyright 2008-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * + * @property-read Horde_Imap_Client_Base_Alert $alerts_ob + The alert reporting object (@since 2.26.0) + * @property-read Horde_Imap_Client_Data_Capability $capability + * A capability object. (@since 2.24.0) + * @property-read Horde_Imap_Client_Data_SearchCharset $search_charset + * A search charset object. (@since 2.24.0) + * @property-read Horde_Imap_Client_Url $url The URL object for the current + * connection parameters (@since 2.24.0) + */ +abstract class Horde_Imap_Client_Base +implements Serializable, SplObserver +{ + /** Serialized version. */ + const VERSION = 3; + + /** Cache names for miscellaneous data. */ + const CACHE_MODSEQ = '_m'; + const CACHE_SEARCH = '_s'; + /* @since 2.9.0 */ + const CACHE_SEARCHID = '_i'; + + /** Cache names used exclusively within this class. @since 2.11.0 */ + const CACHE_DOWNGRADED = 'HICdg'; + + /** + * The list of fetch fields that can be cached, and their cache names. + * + * @var array + */ + public $cacheFields = array( + Horde_Imap_Client::FETCH_ENVELOPE => 'HICenv', + Horde_Imap_Client::FETCH_FLAGS => 'HICflags', + Horde_Imap_Client::FETCH_HEADERS => 'HIChdrs', + Horde_Imap_Client::FETCH_IMAPDATE => 'HICdate', + Horde_Imap_Client::FETCH_SIZE => 'HICsize', + Horde_Imap_Client::FETCH_STRUCTURE => 'HICstruct' + ); + + /** + * Has the internal configuration changed? + * + * @var boolean + */ + public $changed = false; + + /** + * Horde_Imap_Client is optimized for short (i.e. 1 seconds) scripts. It + * makes heavy use of mailbox caching to save on server accesses. This + * property should be set to false for long-running scripts, or else + * status() data may not reflect the current state of the mailbox on the + * server. + * + * @since 2.14.0 + * + * @var boolean + */ + public $statuscache = true; + + /** + * Alerts reporting object. + * + * @var Horde_Imap_Client_Base_Alerts + */ + protected $_alerts; + + /** + * The Horde_Imap_Client_Cache object. + * + * @var Horde_Imap_Client_Cache + */ + protected $_cache = null; + + /** + * Connection to the IMAP server. + * + * @var Horde\Socket\Client + */ + protected $_connection = null; + + /** + * The debug object. + * + * @var Horde_Imap_Client_Base_Debug + */ + protected $_debug = null; + + /** + * The default ports to use for a connection. + * First element is non-secure, second is SSL. + * + * @var array + */ + protected $_defaultPorts = array(); + + /** + * The fetch data object type to return. + * + * @var string + */ + protected $_fetchDataClass = 'Horde_Imap_Client_Data_Fetch'; + + /** + * Cached server data. + * + * @var array + */ + protected $_init; + + /** + * Is there an active authenticated connection to the IMAP Server? + * + * @var boolean + */ + protected $_isAuthenticated = false; + + /** + * The current mailbox selection mode. + * + * @var integer + */ + protected $_mode = 0; + + /** + * Hash containing connection parameters. + * This hash never changes. + * + * @var array + */ + protected $_params = array(); + + /** + * The currently selected mailbox. + * + * @var Horde_Imap_Client_Mailbox + */ + protected $_selected = null; + + /** + * Temp array (destroyed at end of process). + * + * @var array + */ + protected $_temp = array(); + + /** + * Constructor. + * + * @param array $params Configuration parameters: + *
+     * - cache: (array) If set, caches data from fetch(), search(), and
+     *          thread() calls. Requires the horde/Cache package to be
+     *          installed. The array can contain the following keys (see
+     *          Horde_Imap_Client_Cache for default values):
+     *   - backend: [REQUIRED (or cacheob)] (Horde_Imap_Client_Cache_Backend)
+     *              Backend cache driver [@since 2.9.0].
+     *   - fetch_ignore: (array) A list of mailboxes to ignore when storing
+     *                   fetch data.
+     *   - fields: (array) The fetch criteria to cache. If not defined, all
+     *             cacheable data is cached. The following is a list of
+     *             criteria that can be cached:
+     *     - Horde_Imap_Client::FETCH_ENVELOPE
+     *     - Horde_Imap_Client::FETCH_FLAGS
+     *       Only if server supports CONDSTORE extension
+     *     - Horde_Imap_Client::FETCH_HEADERS
+     *       Only for queries that specifically request caching
+     *     - Horde_Imap_Client::FETCH_IMAPDATE
+     *     - Horde_Imap_Client::FETCH_SIZE
+     *     - Horde_Imap_Client::FETCH_STRUCTURE
+     * - capability_ignore: (array) A list of IMAP capabilites to ignore, even
+     *                      if they are supported on the server.
+     *                      DEFAULT: No supported capabilities are ignored.
+     * - comparator: (string) The search comparator to use instead of the
+     *               default server comparator. See setComparator() for
+     *               format.
+     *               DEFAULT: Use the server default
+     * - context: (array) Any context parameters passed to
+     *            stream_create_context(). @since 2.27.0
+     * - debug: (string) If set, will output debug information to the stream
+     *          provided. The value can be any PHP supported wrapper that can
+     *          be opened via PHP's fopen() function.
+     *          DEFAULT: No debug output
+     * - hostspec: (string) The hostname or IP address of the server.
+     *             DEFAULT: 'localhost'
+     * - id: (array) Send ID information to the server (only if server
+     *       supports the ID extension). An array with the keys as the fields
+     *       to send and the values being the associated values. See RFC 2971
+     *       [3.3] for a list of standard field values.
+     *       DEFAULT: No info sent to server
+     * - lang: (array) A list of languages (in priority order) to be used to
+     *         display human readable messages.
+     *         DEFAULT: Messages output in IMAP server default language
+     * - password: (mixed) The user password. Either a string or a
+     *             Horde_Imap_Client_Base_Password object [@since 2.14.0].
+     * - port: (integer) The server port to which we will connect.
+     *         DEFAULT: 143 (imap or imap w/TLS) or 993 (imaps)
+     * - secure: (string) Use SSL or TLS to connect. Values:
+     *   - false (No encryption)
+     *   - 'ssl' (Auto-detect SSL version)
+     *   - 'sslv2' (Force SSL version 3)
+     *   - 'sslv3' (Force SSL version 2)
+     *   - 'tls' (TLS; started via protocol-level negotation over
+     *     unencrypted channel; RECOMMENDED way of initiating secure
+     *     connection)
+     *   - 'tlsv1' (TLS direct version 1.x connection to server) [@since
+     *     2.16.0]
+     *   - true (TLS if available/necessary) [@since 2.15.0]
+     *     DEFAULT: false
+     * - timeout: (integer)  Connection timeout, in seconds.
+     *            DEFAULT: 30 seconds
+     * - username: (string) [REQUIRED] The username.
+     * - authusername (string) The username used for SASL authentication.
+     * 	 If specified this is the user name whose password is used 
+     * 	 (e.g. administrator).
+     * 	 Only valid for RFC 2595/4616 - PLAIN SASL mechanism.
+     * 	 DEFAULT: the same value provided in the username parameter.
+     * 
+ */ + public function __construct(array $params = array()) + { + if (!isset($params['username'])) { + throw new InvalidArgumentException('Horde_Imap_Client requires a username.'); + } + + $this->_setInit(); + + // Default values. + $params = array_merge(array( + 'context' => array(), + 'hostspec' => 'localhost', + 'secure' => false, + 'timeout' => 30 + ), array_filter($params)); + + if (!isset($params['port']) && strpos($params['hostspec'], 'unix://') !== 0) { + $params['port'] = (!empty($params['secure']) && in_array($params['secure'], array('ssl', 'sslv2', 'sslv3'), true)) + ? $this->_defaultPorts[1] + : $this->_defaultPorts[0]; + } + + if (empty($params['cache'])) { + $params['cache'] = array('fields' => array()); + } elseif (empty($params['cache']['fields'])) { + $params['cache']['fields'] = $this->cacheFields; + } else { + $params['cache']['fields'] = array_flip($params['cache']['fields']); + } + + if (empty($params['cache']['fetch_ignore'])) { + $params['cache']['fetch_ignore'] = array(); + } + + $this->_params = $params; + if (isset($params['password'])) { + $this->setParam('password', $params['password']); + } + + $this->changed = true; + $this->_initOb(); + } + + /** + * Get encryption key. + * + * @deprecated Pass callable into 'password' parameter instead. + * + * @return string The encryption key. + */ + protected function _getEncryptKey() + { + if (is_callable($ekey = $this->getParam('encryptKey'))) { + return call_user_func($ekey); + } + + throw new InvalidArgumentException('encryptKey parameter is not a valid callback.'); + } + + /** + * Do initialization tasks. + */ + protected function _initOb() + { + register_shutdown_function(array($this, 'shutdown')); + + $this->_alerts = new Horde_Imap_Client_Base_Alerts(); + // @todo: Remove (BC) + $this->_alerts->attach($this); + + $this->_debug = ($debug = $this->getParam('debug')) + ? new Horde_Imap_Client_Base_Debug($debug) + : new Horde_Support_Stub(); + + // @todo: Remove (BC purposes) + if (isset($this->_init['capability']) && + !is_object($this->_init['capability'])) { + $this->_setInit('capability'); + } + + foreach (array('capability', 'search_charset') as $val) { + if (isset($this->_init[$val])) { + $this->_init[$val]->attach($this); + } + } + } + + /** + * Shutdown actions. + */ + public function shutdown() + { + try { + $this->logout(); + } catch (Horde_Imap_Client_Exception $e) { + } + } + + /** + * This object can not be cloned. + */ + public function __clone() + { + throw new LogicException('Object cannot be cloned.'); + } + + /** + */ + public function update(SplSubject $subject) + { + if (($subject instanceof Horde_Imap_Client_Data_Capability) || + ($subject instanceof Horde_Imap_Client_Data_SearchCharset)) { + $this->changed = true; + } + + /* @todo: BC - remove */ + if ($subject instanceof Horde_Imap_Client_Base_Alerts) { + $this->_temp['alerts'][] = $subject->getLast()->alert; + } + } + + /** + */ + public function serialize() + { + return serialize(array( + 'i' => $this->_init, + 'p' => $this->_params, + 'v' => self::VERSION + )); + } + + /** + */ + public function unserialize($data) + { + $data = @unserialize($data); + if (!is_array($data) || + !isset($data['v']) || + ($data['v'] != self::VERSION)) { + throw new Exception('Cache version change'); + } + + $this->_init = $data['i']; + $this->_params = $data['p']; + + $this->_initOb(); + } + + /** + */ + public function __get($name) + { + switch ($name) { + case 'alerts_ob': + return $this->_alerts; + + case 'capability': + return $this->_capability(); + + case 'search_charset': + if (!isset($this->_init['search_charset'])) { + $this->_init['search_charset'] = new Horde_Imap_Client_Data_SearchCharset(); + $this->_init['search_charset']->attach($this); + } + $this->_init['search_charset']->setBaseOb($this); + return $this->_init['search_charset']; + + case 'url': + $url = new Horde_Imap_Client_Url(); + $url->hostspec = $this->getParam('hostspec'); + $url->port = $this->getParam('port'); + $url->protocol = 'imap'; + return $url; + } + } + + /** + * Set an initialization value. + * + * @param string $key The initialization key. If null, resets all keys. + * @param mixed $val The cached value. If null, removes the key. + */ + public function _setInit($key = null, $val = null) + { + if (is_null($key)) { + $this->_init = array(); + } elseif (is_null($val)) { + unset($this->_init[$key]); + } else { + switch ($key) { + case 'capability': + if ($ci = $this->getParam('capability_ignore')) { + $ignored = array(); + + foreach ($ci as $val2) { + $c = explode('=', $val2); + + if ($val->query($c[0], isset($c[1]) ? $c[1] : null)) { + $ignored[] = $val2; + $val->remove($c[0], isset($c[1]) ? $c[1] : null); + } + } + + if ($this->_debug->debug && !empty($ignored)) { + $this->_debug->info(sprintf( + 'CONFIG: IGNORING these IMAP capabilities: %s', + implode(', ', $ignored) + )); + } + } + + $val->attach($this); + break; + } + + /* Nothing has changed. */ + if (isset($this->_init[$key]) && ($this->_init[$key] === $val)) { + return; + } + + $this->_init[$key] = $val; + } + + $this->changed = true; + } + + /** + * Initialize the Horde_Imap_Client_Cache object, if necessary. + * + * @param boolean $current If true, we are going to update the currently + * selected mailbox. Add an additional check to + * see if caching is available in current + * mailbox. + * + * @return boolean Returns true if caching is enabled. + */ + protected function _initCache($current = false) + { + $c = $this->getParam('cache'); + + if (empty($c['fields'])) { + return false; + } + + if (is_null($this->_cache)) { + if (isset($c['backend'])) { + $backend = $c['backend']; + } elseif (isset($c['cacheob'])) { + /* Deprecated */ + $backend = new Horde_Imap_Client_Cache_Backend_Cache($c); + } else { + return false; + } + + $this->_cache = new Horde_Imap_Client_Cache(array( + 'backend' => $backend, + 'baseob' => $this, + 'debug' => $this->_debug + )); + } + + return $current + /* If UIDs are labeled as not sticky, don't cache since UIDs will + * change on every access. */ + ? !($this->_mailboxOb()->getStatus(Horde_Imap_Client::STATUS_UIDNOTSTICKY)) + : true; + } + + /** + * Returns a value from the internal params array. + * + * @param string $key The param key. + * + * @return mixed The param value, or null if not found. + */ + public function getParam($key) + { + /* Passwords may be stored encrypted. */ + switch ($key) { + case 'password': + if (isset($this->_params[$key]) && + ($this->_params[$key] instanceof Horde_Imap_Client_Base_Password)) { + return $this->_params[$key]->getPassword(); + } + + // DEPRECATED + if (!empty($this->_params['_passencrypt'])) { + try { + $secret = new Horde_Secret(); + return $secret->read($this->_getEncryptKey(), $this->_params['password']); + } catch (Exception $e) { + return null; + } + } + break; + } + + return isset($this->_params[$key]) + ? $this->_params[$key] + : null; + } + + /** + * Sets a configuration parameter value. + * + * @param string $key The param key. + * @param mixed $val The param value. + */ + public function setParam($key, $val) + { + switch ($key) { + case 'password': + if ($val instanceof Horde_Imap_Client_Base_Password) { + break; + } + + // DEPRECATED: Encrypt password. + try { + $encrypt_key = $this->_getEncryptKey(); + if (strlen($encrypt_key)) { + $secret = new Horde_Secret(); + $val = $secret->write($encrypt_key, $val); + $this->_params['_passencrypt'] = true; + } + } catch (Exception $e) {} + break; + } + + $this->_params[$key] = $val; + $this->changed = true; + } + + /** + * Returns the Horde_Imap_Client_Cache object used, if available. + * + * @return mixed Either the cache object or null. + */ + public function getCache() + { + $this->_initCache(); + return $this->_cache; + } + + /** + * Returns the correct IDs object for use with this driver. + * + * @param mixed $ids Either self::ALL, self::SEARCH_RES, self::LARGEST, + * Horde_Imap_Client_Ids object, array, or sequence + * string. + * @param boolean $sequence Are $ids message sequence numbers? + * + * @return Horde_Imap_Client_Ids The IDs object. + */ + public function getIdsOb($ids = null, $sequence = false) + { + return new Horde_Imap_Client_Ids($ids, $sequence); + } + + /** + * Returns whether the IMAP server supports the given capability + * (See RFC 3501 [6.1.1]). + * + * @deprecated Use $capability property instead. + * + * @param string $capability The capability string to query. + * + * @return mixed True if the server supports the queried capability, + * false if it doesn't, or an array if the capability can + * contain multiple values. + */ + public function queryCapability($capability) + { + try { + $c = $this->_capability(); + return ($out = $c->getParams($capability)) + ? $out + : $c->query($capability); + } catch (Horde_Imap_Client_Exception $e) { + return false; + } + } + + /** + * Get CAPABILITY information from the IMAP server. + * + * @deprecated Use $capability property instead. + * + * @return array The capability array. + * + * @throws Horde_Imap_Client_Exception + */ + public function capability() + { + return $this->_capability()->toArray(); + } + + /** + * Query server capability. + * + * Required because internal code can't call capability via magic method + * directly - it may not exist yet, the creation code may call capability + * recursively, and __get() doesn't allow recursive calls to the same + * property (chicken/egg issue). + * + * @return mixed The capability object if no arguments provided. If + * arguments are provided, they are passed to the query() + * method and this value is returned. + * @throws Horde_Imap_Client_Exception + */ + protected function _capability() + { + if (!isset($this->_init['capability'])) { + $this->_initCapability(); + } + + return ($args = func_num_args()) + ? $this->_init['capability']->query(func_get_arg(0), ($args > 1) ? func_get_arg(1) : null) + : $this->_init['capability']; + } + + /** + * Retrieve capability information from the IMAP server. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _initCapability(); + + /** + * Send a NOOP command (RFC 3501 [6.1.2]). + * + * @throws Horde_Imap_Client_Exception + */ + public function noop() + { + if (!$this->_connection) { + // NOOP can be called in the unauthenticated state. + $this->_connect(); + } + $this->_noop(); + } + + /** + * Send a NOOP command. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _noop(); + + /** + * Get the NAMESPACE information from the IMAP server (RFC 2342). + * + * @param array $additional If the server supports namespaces, any + * additional namespaces to add to the + * namespace list that are not broadcast by + * the server. The namespaces must be UTF-8 + * strings. + * @param array $opts Additional options: + * - ob_return: (boolean) If true, returns a + * Horde_Imap_Client_Namespace_List object instead of an + * array. + * + * @return mixed A Horde_Imap_Client_Namespace_List object if + * 'ob_return', is true. Otherwise, an array of namespace + * objects (@deprecated) with the name as the key (UTF-8) + * and the following values: + *
+     *  - delimiter: (string) The namespace delimiter.
+     *  - hidden: (boolean) Is this a hidden namespace?
+     *  - name: (string) The namespace name (UTF-8).
+     *  - translation: (string) Returns the translated name of the namespace
+     *                 (UTF-8). Requires RFC 5255 and a previous call to
+     *                 setLanguage().
+     *  - type: (integer) The namespace type. Either:
+     *    - Horde_Imap_Client::NS_PERSONAL
+     *    - Horde_Imap_Client::NS_OTHER
+     *    - Horde_Imap_Client::NS_SHARED
+     * 
+ * + * @throws Horde_Imap_Client_Exception + */ + public function getNamespaces( + array $additional = array(), array $opts = array() + ) + { + $additional = array_map('strval', $additional); + $sig = hash( + 'md5', + json_encode($additional) . intval(empty($opts['ob_return'])) + ); + + if (isset($this->_init['namespace'][$sig])) { + $ns = $this->_init['namespace'][$sig]; + } else { + $this->login(); + + $ns = $this->_getNamespaces(); + + /* Skip namespaces if we have already auto-detected them. Also, + * hidden namespaces cannot be empty. */ + $to_process = array_diff(array_filter($additional, 'strlen'), array_map('strlen', iterator_to_array($ns))); + if (!empty($to_process)) { + foreach ($this->listMailboxes($to_process, Horde_Imap_Client::MBOX_ALL, array('delimiter' => true)) as $key => $val) { + $ob = new Horde_Imap_Client_Data_Namespace(); + $ob->delimiter = $val['delimiter']; + $ob->hidden = true; + $ob->name = $key; + $ob->type = $ob::NS_SHARED; + $ns[$val] = $ob; + } + } + + if (!count($ns)) { + /* This accurately determines the namespace information of the + * base namespace if the NAMESPACE command is not supported. + * See: RFC 3501 [6.3.8] */ + $mbox = $this->listMailboxes('', Horde_Imap_Client::MBOX_ALL, array('delimiter' => true)); + $first = reset($mbox); + + $ob = new Horde_Imap_Client_Data_Namespace(); + $ob->delimiter = $first['delimiter']; + $ns[''] = $ob; + } + + $this->_init['namespace'][$sig] = $ns; + $this->_setInit('namespace', $this->_init['namespace']); + } + + if (!empty($opts['ob_return'])) { + return $ns; + } + + /* @todo Remove for 3.0 */ + $out = array(); + foreach ($ns as $key => $val) { + $out[$key] = array( + 'delimiter' => $val->delimiter, + 'hidden' => $val->hidden, + 'name' => $val->name, + 'translation' => $val->translation, + 'type' => $val->type + ); + } + + return $out; + } + + /** + * Get the NAMESPACE information from the IMAP server. + * + * @return Horde_Imap_Client_Namespace_List Namespace list object. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _getNamespaces(); + + /** + * Display if connection to the server has been secured via TLS or SSL. + * + * @return boolean True if the IMAP connection is secured. + */ + public function isSecureConnection() + { + return ($this->_connection && $this->_connection->secure); + } + + /** + * Connect to the remote server. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _connect(); + + /** + * Return a list of alerts that MUST be presented to the user (RFC 3501 + * [7.1]). + * + * @deprecated Add an observer to the $alerts_ob property instead. + * + * @return array An array of alert messages. + */ + public function alerts() + { + $alerts = isset($this->_temp['alerts']) + ? $this->_temp['alerts'] + : array(); + unset($this->_temp['alerts']); + return $alerts; + } + + /** + * Login to the IMAP server. + * + * @throws Horde_Imap_Client_Exception + */ + public function login() + { + if (!$this->_isAuthenticated && $this->_login()) { + if ($this->getParam('id')) { + try { + $this->sendID(); + /* ID is queued - force sending the queued command. */ + $this->_sendCmd($this->_pipeline()); + } catch (Horde_Imap_Client_Exception_NoSupportExtension $e) { + // Ignore if server doesn't support ID extension. + } + } + + if ($this->getParam('comparator')) { + try { + $this->setComparator(); + } catch (Horde_Imap_Client_Exception_NoSupportExtension $e) { + // Ignore if server doesn't support I18NLEVEL=2 + } + } + } + + $this->_isAuthenticated = true; + } + + /** + * Login to the IMAP server. + * + * @return boolean Return true if global login tasks should be run. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _login(); + + /** + * Logout from the IMAP server (see RFC 3501 [6.1.3]). + */ + public function logout() + { + if ($this->_isAuthenticated && $this->_connection->connected) { + $this->_logout(); + $this->_connection->close(); + } + + $this->_connection = $this->_selected = null; + $this->_isAuthenticated = false; + $this->_mode = 0; + } + + /** + * Logout from the IMAP server (see RFC 3501 [6.1.3]). + */ + abstract protected function _logout(); + + /** + * Send ID information to the IMAP server (RFC 2971). + * + * @param array $info Overrides the value of the 'id' param and sends + * this information instead. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function sendID($info = null) + { + if (!$this->_capability('ID')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('ID'); + } + + $this->_sendID(is_null($info) ? ($this->getParam('id') ?: array()) : $info); + } + + /** + * Send ID information to the IMAP server (RFC 2971). + * + * @param array $info The information to send to the server. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _sendID($info); + + /** + * Return ID information from the IMAP server (RFC 2971). + * + * @return array An array of information returned, with the keys as the + * 'field' and the values as the 'value'. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function getID() + { + if (!$this->_capability('ID')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('ID'); + } + + return $this->_getID(); + } + + /** + * Return ID information from the IMAP server (RFC 2971). + * + * @return array An array of information returned, with the keys as the + * 'field' and the values as the 'value'. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _getID(); + + /** + * Sets the preferred language for server response messages (RFC 5255). + * + * @param array $langs Overrides the value of the 'lang' param and sends + * this list of preferred languages instead. The + * special string 'i-default' can be used to restore + * the language to the server default. + * + * @return string The language accepted by the server, or null if the + * default language is used. + * + * @throws Horde_Imap_Client_Exception + */ + public function setLanguage($langs = null) + { + $lang = null; + + if ($this->_capability('LANGUAGE')) { + $lang = is_null($langs) + ? $this->getParam('lang') + : $langs; + } + + return is_null($lang) + ? null + : $this->_setLanguage($lang); + } + + /** + * Sets the preferred language for server response messages (RFC 5255). + * + * @param array $langs The preferred list of languages. + * + * @return string The language accepted by the server, or null if the + * default language is used. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _setLanguage($langs); + + /** + * Gets the preferred language for server response messages (RFC 5255). + * + * @param array $list If true, return the list of available languages. + * + * @return mixed If $list is true, the list of languages available on the + * server (may be empty). If false, the language used by + * the server, or null if the default language is used. + * + * @throws Horde_Imap_Client_Exception + */ + public function getLanguage($list = false) + { + if (!$this->_capability('LANGUAGE')) { + return $list ? array() : null; + } + + return $this->_getLanguage($list); + } + + /** + * Gets the preferred language for server response messages (RFC 5255). + * + * @param array $list If true, return the list of available languages. + * + * @return mixed If $list is true, the list of languages available on the + * server (may be empty). If false, the language used by + * the server, or null if the default language is used. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _getLanguage($list); + + /** + * Open a mailbox. + * + * @param mixed $mailbox The mailbox to open. Either a + * Horde_Imap_Client_Mailbox object or a string + * (UTF-8). + * @param integer $mode The access mode. Either + * - Horde_Imap_Client::OPEN_READONLY + * - Horde_Imap_Client::OPEN_READWRITE + * - Horde_Imap_Client::OPEN_AUTO + * + * @throws Horde_Imap_Client_Exception + */ + public function openMailbox($mailbox, $mode = Horde_Imap_Client::OPEN_AUTO) + { + $this->login(); + + $change = false; + $mailbox = Horde_Imap_Client_Mailbox::get($mailbox); + + if ($mode == Horde_Imap_Client::OPEN_AUTO) { + if (is_null($this->_selected) || + !$mailbox->equals($this->_selected)) { + $mode = Horde_Imap_Client::OPEN_READONLY; + $change = true; + } + } else { + $change = (is_null($this->_selected) || + !$mailbox->equals($this->_selected) || + ($mode != $this->_mode)); + } + + if ($change) { + $this->_openMailbox($mailbox, $mode); + $this->_mailboxOb()->open = true; + if ($this->_initCache(true)) { + $this->_condstoreSync(); + } + } + } + + /** + * Open a mailbox. + * + * @param Horde_Imap_Client_Mailbox $mailbox The mailbox to open. + * @param integer $mode The access mode. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _openMailbox(Horde_Imap_Client_Mailbox $mailbox, + $mode); + + /** + * Called when the selected mailbox is changed. + * + * @param mixed $mailbox The selected mailbox or null. + * @param integer $mode The access mode. + */ + protected function _changeSelected($mailbox = null, $mode = null) + { + $this->_mode = $mode; + if (is_null($mailbox)) { + $this->_selected = null; + } else { + $this->_selected = clone $mailbox; + $this->_mailboxOb()->reset(); + } + } + + /** + * Return the Horde_Imap_Client_Base_Mailbox object. + * + * @param string $mailbox The mailbox name. Defaults to currently + * selected mailbox. + * + * @return Horde_Imap_Client_Base_Mailbox Mailbox object. + */ + protected function _mailboxOb($mailbox = null) + { + $name = is_null($mailbox) + ? strval($this->_selected) + : strval($mailbox); + + if (!isset($this->_temp['mailbox_ob'][$name])) { + $this->_temp['mailbox_ob'][$name] = new Horde_Imap_Client_Base_Mailbox(); + } + + return $this->_temp['mailbox_ob'][$name]; + } + + /** + * Return the currently opened mailbox and access mode. + * + * @return mixed Null if no mailbox selected, or an array with two + * elements: + * - mailbox: (Horde_Imap_Client_Mailbox) The mailbox object. + * - mode: (integer) Current mode. + * + * @throws Horde_Imap_Client_Exception + */ + public function currentMailbox() + { + return is_null($this->_selected) + ? null + : array( + 'mailbox' => clone $this->_selected, + 'mode' => $this->_mode + ); + } + + /** + * Create a mailbox. + * + * @param mixed $mailbox The mailbox to create. Either a + * Horde_Imap_Client_Mailbox object or a string + * (UTF-8). + * @param array $opts Additional options: + * - special_use: (array) An array of special-use flags to mark the + * mailbox with. The server MUST support RFC 6154. + * + * @throws Horde_Imap_Client_Exception + */ + public function createMailbox($mailbox, array $opts = array()) + { + $this->login(); + + if (!$this->_capability('CREATE-SPECIAL-USE')) { + unset($opts['special_use']); + } + + $this->_createMailbox(Horde_Imap_Client_Mailbox::get($mailbox), $opts); + } + + /** + * Create a mailbox. + * + * @param Horde_Imap_Client_Mailbox $mailbox The mailbox to create. + * @param array $opts Additional options. See + * createMailbox(). + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _createMailbox(Horde_Imap_Client_Mailbox $mailbox, + $opts); + + /** + * Delete a mailbox. + * + * @param mixed $mailbox The mailbox to delete. Either a + * Horde_Imap_Client_Mailbox object or a string + * (UTF-8). + * + * @throws Horde_Imap_Client_Exception + */ + public function deleteMailbox($mailbox) + { + $this->login(); + + $mailbox = Horde_Imap_Client_Mailbox::get($mailbox); + + $this->_deleteMailbox($mailbox); + $this->_deleteMailboxPost($mailbox); + } + + /** + * Delete a mailbox. + * + * @param Horde_Imap_Client_Mailbox $mailbox The mailbox to delete. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _deleteMailbox(Horde_Imap_Client_Mailbox $mailbox); + + /** + * Actions to perform after a mailbox delete. + * + * @param Horde_Imap_Client_Mailbox $mailbox The deleted mailbox. + */ + protected function _deleteMailboxPost(Horde_Imap_Client_Mailbox $mailbox) + { + /* Delete mailbox caches. */ + if ($this->_initCache()) { + $this->_cache->deleteMailbox($mailbox); + } + unset($this->_temp['mailbox_ob'][strval($mailbox)]); + + /* Unsubscribe from mailbox. */ + try { + $this->subscribeMailbox($mailbox, false); + } catch (Horde_Imap_Client_Exception $e) { + // Ignore failed unsubscribe request + } + } + + /** + * Rename a mailbox. + * + * @param mixed $old The old mailbox name. Either a + * Horde_Imap_Client_Mailbox object or a string (UTF-8). + * @param mixed $new The new mailbox name. Either a + * Horde_Imap_Client_Mailbox object or a string (UTF-8). + * + * @throws Horde_Imap_Client_Exception + */ + public function renameMailbox($old, $new) + { + // Login will be handled by first listMailboxes() call. + + $old = Horde_Imap_Client_Mailbox::get($old); + $new = Horde_Imap_Client_Mailbox::get($new); + + /* Check if old mailbox(es) were subscribed to. */ + $base = $this->listMailboxes($old, Horde_Imap_Client::MBOX_SUBSCRIBED, array('delimiter' => true)); + if (empty($base)) { + $base = $this->listMailboxes($old, Horde_Imap_Client::MBOX_ALL, array('delimiter' => true)); + $base = reset($base); + $subscribed = array(); + } else { + $base = reset($base); + $subscribed = array($base['mailbox']); + } + + $all_mboxes = array($base['mailbox']); + if (strlen($base['delimiter'])) { + $search = $old->list_escape . $base['delimiter'] . '*'; + $all_mboxes = array_merge($all_mboxes, $this->listMailboxes($search, Horde_Imap_Client::MBOX_ALL, array('flat' => true))); + $subscribed = array_merge($subscribed, $this->listMailboxes($search, Horde_Imap_Client::MBOX_SUBSCRIBED, array('flat' => true))); + } + + $this->_renameMailbox($old, $new); + + /* Delete mailbox actions. */ + foreach ($all_mboxes as $val) { + $this->_deleteMailboxPost($val); + } + + foreach ($subscribed as $val) { + try { + $this->subscribeMailbox(new Horde_Imap_Client_Mailbox(substr_replace($val, $new, 0, strlen($old)))); + } catch (Horde_Imap_Client_Exception $e) { + // Ignore failed subscription requests + } + } + } + + /** + * Rename a mailbox. + * + * @param Horde_Imap_Client_Mailbox $old The old mailbox name. + * @param Horde_Imap_Client_Mailbox $new The new mailbox name. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _renameMailbox(Horde_Imap_Client_Mailbox $old, + Horde_Imap_Client_Mailbox $new); + + /** + * Manage subscription status for a mailbox. + * + * @param mixed $mailbox The mailbox to [un]subscribe to. Either a + * Horde_Imap_Client_Mailbox object or a string + * (UTF-8). + * @param boolean $subscribe True to subscribe, false to unsubscribe. + * + * @throws Horde_Imap_Client_Exception + */ + public function subscribeMailbox($mailbox, $subscribe = true) + { + $this->login(); + $this->_subscribeMailbox(Horde_Imap_Client_Mailbox::get($mailbox), (bool)$subscribe); + } + + /** + * Manage subscription status for a mailbox. + * + * @param Horde_Imap_Client_Mailbox $mailbox The mailbox to [un]subscribe + * to. + * @param boolean $subscribe True to subscribe, false to + * unsubscribe. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _subscribeMailbox(Horde_Imap_Client_Mailbox $mailbox, + $subscribe); + + /** + * Obtain a list of mailboxes matching a pattern. + * + * @param mixed $pattern The mailbox search pattern(s) (see RFC 3501 + * [6.3.8] for the format). A UTF-8 string or an + * array of strings. If a Horde_Imap_Client_Mailbox + * object is given, it is escaped (i.e. wildcard + * patterns are converted to return the miminal + * number of matches possible). + * @param integer $mode Which mailboxes to return. Either: + * - Horde_Imap_Client::MBOX_SUBSCRIBED + * Return subscribed mailboxes. + * - Horde_Imap_Client::MBOX_SUBSCRIBED_EXISTS + * Return subscribed mailboxes that exist on the server. + * - Horde_Imap_Client::MBOX_UNSUBSCRIBED + * Return unsubscribed mailboxes. + * - Horde_Imap_Client::MBOX_ALL + * Return all mailboxes regardless of subscription status. + * - Horde_Imap_Client::MBOX_ALL_SUBSCRIBED (@since 2.23.0) + * Return all mailboxes regardless of subscription status, and ensure + * the '\subscribed' attribute is set if mailbox is subscribed + * (implies 'attributes' option is true). + * @param array $options Additional options: + *
+     *   - attributes: (boolean) If true, return attribute information under
+     *                 the 'attributes' key.
+     *                 DEFAULT: Do not return this information.
+     *   - children: (boolean) Tell server to return children attribute
+     *               information (\HasChildren, \HasNoChildren). Requires the
+     *               LIST-EXTENDED extension to guarantee this information is
+     *               returned. Server MAY return this attribute without this
+     *               option, or if the CHILDREN extension is available, but it
+     *               is not guaranteed.
+     *               DEFAULT: false
+     *   - flat: (boolean) If true, return a flat list of mailbox names only.
+     *           Overrides the 'attributes' option.
+     *           DEFAULT: Do not return flat list.
+     *   - recursivematch: (boolean) Force the server to return information
+     *                     about parent mailboxes that don't match other
+     *                     selection options, but have some sub-mailboxes that
+     *                     do. Information about children is returned in the
+     *                     CHILDINFO extended data item ('extended'). Requires
+     *                     the LIST-EXTENDED extension.
+     *                     DEFAULT: false
+     *   - remote: (boolean) Tell server to return mailboxes that reside on
+     *             another server. Requires the LIST-EXTENDED extension.
+     *             DEFAULT: false
+     *   - special_use: (boolean) Tell server to return special-use attribute
+     *                  information (see Horde_Imap_Client SPECIALUSE_*
+     *                  constants). Server must support the SPECIAL-USE return
+     *                  option for this setting to have any effect.
+     *                  DEFAULT: false
+     *   - status: (integer) Tell server to return status information. The
+     *             value is a bitmask that may contain any of:
+     *     - Horde_Imap_Client::STATUS_MESSAGES
+     *     - Horde_Imap_Client::STATUS_RECENT
+     *     - Horde_Imap_Client::STATUS_UIDNEXT
+     *     - Horde_Imap_Client::STATUS_UIDVALIDITY
+     *     - Horde_Imap_Client::STATUS_UNSEEN
+     *     - Horde_Imap_Client::STATUS_HIGHESTMODSEQ
+     *     DEFAULT: 0
+     *   - sort: (boolean) If true, return a sorted list of mailboxes?
+     *           DEFAULT: Do not sort the list.
+     *   - sort_delimiter: (string) If 'sort' is true, this is the delimiter
+     *                     used to sort the mailboxes.
+     *                     DEFAULT: '.'
+     * 
+ * + * @return array If 'flat' option is true, the array values are a list + * of Horde_Imap_Client_Mailbox objects. Otherwise, the + * keys are UTF-8 mailbox names and the values are arrays + * with these keys: + * - attributes: (array) List of lower-cased attributes [only if + * 'attributes' option is true]. + * - delimiter: (string) The delimiter for the mailbox. + * - extended: (TODO) TODO [only if 'recursivematch' option is true and + * LIST-EXTENDED extension is supported on the server]. + * - mailbox: (Horde_Imap_Client_Mailbox) The mailbox object. + * - status: (array) See status() [only if 'status' option is true]. + * + * @throws Horde_Imap_Client_Exception + */ + public function listMailboxes($pattern, + $mode = Horde_Imap_Client::MBOX_ALL, + array $options = array()) + { + $this->login(); + + $pattern = is_array($pattern) + ? array_unique($pattern) + : array($pattern); + + /* Prepare patterns. */ + $plist = array(); + foreach ($pattern as $val) { + if ($val instanceof Horde_Imap_Client_Mailbox) { + $val = $val->list_escape; + } + $plist[] = Horde_Imap_Client_Mailbox::get(preg_replace( + array("/\*{2,}/", "/\%{2,}/"), + array('*', '%'), + Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($val) + ), true); + } + + if (isset($options['special_use']) && + !$this->_capability('SPECIAL-USE')) { + unset($options['special_use']); + } + + $ret = $this->_listMailboxes($plist, $mode, $options); + + if (!empty($options['status']) && + !$this->_capability('LIST-STATUS')) { + foreach ($this->status(array_keys($ret), $options['status']) as $key => $val) { + $ret[$key]['status'] = $val; + } + } + + if (empty($options['sort'])) { + return $ret; + } + + $list_ob = new Horde_Imap_Client_Mailbox_List(empty($options['flat']) ? array_keys($ret) : $ret); + $sorted = $list_ob->sort(array( + 'delimiter' => empty($options['sort_delimiter']) ? '.' : $options['sort_delimiter'] + )); + + if (!empty($options['flat'])) { + return $sorted; + } + + $out = array(); + foreach ($sorted as $val) { + $out[$val] = $ret[$val]; + } + + return $out; + } + + /** + * Obtain a list of mailboxes matching a pattern. + * + * @param array $pattern The mailbox search patterns + * (Horde_Imap_Client_Mailbox objects). + * @param integer $mode Which mailboxes to return. + * @param array $options Additional options. + * + * @return array See listMailboxes(). + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _listMailboxes($pattern, $mode, $options); + + /** + * Obtain status information for a mailbox. + * + * @param mixed $mailbox The mailbox(es) to query. Either a + * Horde_Imap_Client_Mailbox object, a string + * (UTF-8), or an array of objects/strings (since + * 2.10.0). + * @param integer $flags A bitmask of information requested from the + * server. Allowed flags: + *
+     *   - Horde_Imap_Client::STATUS_MESSAGES
+     *     Return key: messages
+     *     Return format: (integer) The number of messages in the mailbox.
+     *
+     *   - Horde_Imap_Client::STATUS_RECENT
+     *     Return key: recent
+     *     Return format: (integer) The number of messages with the \Recent
+     *                    flag set as currently reported in the mailbox
+     *
+     *   - Horde_Imap_Client::STATUS_RECENT_TOTAL
+     *     Return key: recent_total
+     *     Return format: (integer) The number of messages with the \Recent
+     *                    flag set. This returns the total number of messages
+     *                    that have been marked as recent in this mailbox
+     *                    since the PHP process began. (since 2.12.0)
+     *
+     *   - Horde_Imap_Client::STATUS_UIDNEXT
+     *     Return key: uidnext
+     *     Return format: (integer) The next UID to be assigned in the
+     *                    mailbox. Only returned if the server automatically
+     *                    provides the data.
+     *
+     *   - Horde_Imap_Client::STATUS_UIDNEXT_FORCE
+     *     Return key: uidnext
+     *     Return format: (integer) The next UID to be assigned in the
+     *                    mailbox. This option will always determine this
+     *                    value, even if the server does not automatically
+     *                    provide this data.
+     *
+     *   - Horde_Imap_Client::STATUS_UIDVALIDITY
+     *     Return key: uidvalidity
+     *     Return format: (integer) The unique identifier validity of the
+     *                    mailbox.
+     *
+     *   - Horde_Imap_Client::STATUS_UNSEEN
+     *     Return key: unseen
+     *     Return format: (integer) The number of messages which do not have
+     *                    the \Seen flag set.
+     *
+     *   - Horde_Imap_Client::STATUS_FIRSTUNSEEN
+     *     Return key: firstunseen
+     *     Return format: (integer) The sequence number of the first unseen
+     *                    message in the mailbox.
+     *
+     *   - Horde_Imap_Client::STATUS_FLAGS
+     *     Return key: flags
+     *     Return format: (array) The list of defined flags in the mailbox
+     *                    (all flags are in lowercase).
+     *
+     *   - Horde_Imap_Client::STATUS_PERMFLAGS
+     *     Return key: permflags
+     *     Return format: (array) The list of flags that a client can change
+     *                    permanently (all flags are in lowercase).
+     *
+     *   - Horde_Imap_Client::STATUS_HIGHESTMODSEQ
+     *     Return key: highestmodseq
+     *     Return format: (integer) If the server supports the CONDSTORE
+     *                    IMAP extension, this will be the highest
+     *                    mod-sequence value of all messages in the mailbox.
+     *                    Else 0 if CONDSTORE not available or the mailbox
+     *                    does not support mod-sequences.
+     *
+     *   - Horde_Imap_Client::STATUS_SYNCMODSEQ
+     *     Return key: syncmodseq
+     *     Return format: (integer) If caching, and the server supports the
+     *                    CONDSTORE IMAP extension, this is the cached
+     *                    mod-sequence value of the mailbox when it was opened
+     *                    for the first time in this access. Will be null if
+     *                    not caching, CONDSTORE not available, or the mailbox
+     *                    does not support mod-sequences.
+     *
+     *   - Horde_Imap_Client::STATUS_SYNCFLAGUIDS
+     *     Return key: syncflaguids
+     *     Return format: (Horde_Imap_Client_Ids) If caching, the server
+     *                    supports the CONDSTORE IMAP extension, and the
+     *                    mailbox contained cached data when opened for the
+     *                    first time in this access, this is the list of UIDs
+     *                    in which flags have changed since STATUS_SYNCMODSEQ.
+     *
+     *   - Horde_Imap_Client::STATUS_SYNCVANISHED
+     *     Return key: syncvanished
+     *     Return format: (Horde_Imap_Client_Ids) If caching, the server
+     *                    supports the CONDSTORE IMAP extension, and the
+     *                    mailbox contained cached data when opened for the
+     *                    first time in this access, this is the list of UIDs
+     *                    which have been deleted since STATUS_SYNCMODSEQ.
+     *
+     *   - Horde_Imap_Client::STATUS_UIDNOTSTICKY
+     *     Return key: uidnotsticky
+     *     Return format: (boolean) If the server supports the UIDPLUS IMAP
+     *                    extension, and the queried mailbox does not support
+     *                    persistent UIDs, this value will be true. In all
+     *                    other cases, this value will be false.
+     *
+     *   - Horde_Imap_Client::STATUS_FORCE_REFRESH
+     *     Normally, the status information will be cached for a given
+     *     mailbox. Since most PHP requests are generally less than a second,
+     *     this is fine. However, if your script is long running, the status
+     *     information may not be up-to-date. Specifying this flag will ensure
+     *     that the server is always polled for the current mailbox status
+     *     before results are returned. (since 2.14.0)
+     *
+     *   - Horde_Imap_Client::STATUS_ALL (DEFAULT)
+     *     Shortcut to return 'messages', 'recent', 'uidnext', 'uidvalidity',
+     *     and 'unseen' values.
+     * 
+     * @param array $opts     Additional options:
+     * 
+     *   - sort: (boolean) If true, sort the list of mailboxes? (since 2.10.0)
+     *           DEFAULT: Do not sort the list.
+     *   - sort_delimiter: (string) If 'sort' is true, this is the delimiter
+     *                     used to sort the mailboxes. (since 2.10.0)
+     *                     DEFAULT: '.'
+     * 
+ * + * @return array If $mailbox contains multiple mailboxes, an array with + * keys being the UTF-8 mailbox name and values as arrays + * containing the requested keys (see above). + * Otherwise, an array with keys as the requested keys (see + * above) and values as the key data. + * + * @throws Horde_Imap_Client_Exception + */ + public function status($mailbox, $flags = Horde_Imap_Client::STATUS_ALL, + array $opts = array()) + { + $opts = array_merge(array( + 'sort' => false, + 'sort_delimiter' => '.' + ), $opts); + + $this->login(); + + if (is_array($mailbox)) { + if (empty($mailbox)) { + return array(); + } + $ret_array = true; + } else { + $mailbox = array($mailbox); + $ret_array = false; + } + + $mlist = array_map(array('Horde_Imap_Client_Mailbox', 'get'), $mailbox); + + $unselected_flags = array( + 'messages' => Horde_Imap_Client::STATUS_MESSAGES, + 'recent' => Horde_Imap_Client::STATUS_RECENT, + 'uidnext' => Horde_Imap_Client::STATUS_UIDNEXT, + 'uidvalidity' => Horde_Imap_Client::STATUS_UIDVALIDITY, + 'unseen' => Horde_Imap_Client::STATUS_UNSEEN + ); + + if (!$this->statuscache) { + $flags |= Horde_Imap_Client::STATUS_FORCE_REFRESH; + } + + if ($flags & Horde_Imap_Client::STATUS_ALL) { + foreach ($unselected_flags as $val) { + $flags |= $val; + } + } + + $master = $ret = array(); + + /* Catch flags that are not supported. */ + if (($flags & Horde_Imap_Client::STATUS_HIGHESTMODSEQ) && + !$this->_capability()->isEnabled('CONDSTORE')) { + $master['highestmodseq'] = 0; + $flags &= ~Horde_Imap_Client::STATUS_HIGHESTMODSEQ; + } + + if (($flags & Horde_Imap_Client::STATUS_UIDNOTSTICKY) && + !$this->_capability('UIDPLUS')) { + $master['uidnotsticky'] = false; + $flags &= ~Horde_Imap_Client::STATUS_UIDNOTSTICKY; + } + + /* UIDNEXT return options. */ + if ($flags & Horde_Imap_Client::STATUS_UIDNEXT_FORCE) { + $flags |= Horde_Imap_Client::STATUS_UIDNEXT; + } + + foreach ($mlist as $val) { + $name = strval($val); + $tmp_flags = $flags; + + if ($val->equals($this->_selected)) { + /* Check if already in mailbox. */ + $opened = true; + + if ($flags & Horde_Imap_Client::STATUS_FORCE_REFRESH) { + $this->noop(); + } + } else { + /* A list of STATUS options (other than those handled directly + * below) that require the mailbox to be explicitly opened. */ + $opened = ($flags & Horde_Imap_Client::STATUS_FIRSTUNSEEN) || + ($flags & Horde_Imap_Client::STATUS_FLAGS) || + ($flags & Horde_Imap_Client::STATUS_PERMFLAGS) || + ($flags & Horde_Imap_Client::STATUS_UIDNOTSTICKY) || + /* Force mailboxes containing wildcards to be accessed via + * STATUS so that wildcards do not return a bunch of + * mailboxes in the LIST-STATUS response. */ + (strpbrk($name, '*%') !== false); + } + + $ret[$name] = $master; + $ptr = &$ret[$name]; + + /* STATUS_PERMFLAGS requires a read/write mailbox. */ + if ($flags & Horde_Imap_Client::STATUS_PERMFLAGS) { + $this->openMailbox($val, Horde_Imap_Client::OPEN_READWRITE); + $opened = true; + } + + /* Handle SYNC related return options. These require the mailbox + * to be opened at least once. */ + if ($flags & Horde_Imap_Client::STATUS_SYNCMODSEQ) { + $this->openMailbox($val); + $ptr['syncmodseq'] = $this->_mailboxOb($val)->getStatus(Horde_Imap_Client::STATUS_SYNCMODSEQ); + $tmp_flags &= ~Horde_Imap_Client::STATUS_SYNCMODSEQ; + $opened = true; + } + + if ($flags & Horde_Imap_Client::STATUS_SYNCFLAGUIDS) { + $this->openMailbox($val); + $ptr['syncflaguids'] = $this->getIdsOb($this->_mailboxOb($val)->getStatus(Horde_Imap_Client::STATUS_SYNCFLAGUIDS)); + $tmp_flags &= ~Horde_Imap_Client::STATUS_SYNCFLAGUIDS; + $opened = true; + } + + if ($flags & Horde_Imap_Client::STATUS_SYNCVANISHED) { + $this->openMailbox($val); + $ptr['syncvanished'] = $this->getIdsOb($this->_mailboxOb($val)->getStatus(Horde_Imap_Client::STATUS_SYNCVANISHED)); + $tmp_flags &= ~Horde_Imap_Client::STATUS_SYNCVANISHED; + $opened = true; + } + + /* Handle RECENT_TOTAL option. */ + if ($flags & Horde_Imap_Client::STATUS_RECENT_TOTAL) { + $this->openMailbox($val); + $ptr['recent_total'] = $this->_mailboxOb($val)->getStatus(Horde_Imap_Client::STATUS_RECENT_TOTAL); + $tmp_flags &= ~Horde_Imap_Client::STATUS_RECENT_TOTAL; + $opened = true; + } + + if ($opened) { + if ($tmp_flags) { + $tmp = $this->_status(array($val), $tmp_flags); + $ptr += reset($tmp); + } + } else { + $to_process[] = $val; + } + } + + if ($flags && !empty($to_process)) { + if ((count($to_process) > 1) && + $this->_capability('LIST-STATUS')) { + foreach ($this->listMailboxes($to_process, Horde_Imap_Client::MBOX_ALL, array('status' => $flags)) as $key => $val) { + if (isset($val['status'])) { + $ret[$key] += $val['status']; + } + } + } else { + foreach ($this->_status($to_process, $flags) as $key => $val) { + $ret[$key] += $val; + } + } + } + + if (!$opts['sort'] || (count($ret) === 1)) { + return $ret_array + ? $ret + : reset($ret); + } + + $list_ob = new Horde_Imap_Client_Mailbox_List(array_keys($ret)); + $sorted = $list_ob->sort(array( + 'delimiter' => $opts['sort_delimiter'] + )); + + $out = array(); + foreach ($sorted as $val) { + $out[$val] = $ret[$val]; + } + + return $out; + } + + /** + * Obtain status information for mailboxes. + * + * @param array $mboxes The list of mailbox objects to query. + * @param integer $flags A bitmask of information requested from the + * server. + * + * @return array See array return for status(). + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _status($mboxes, $flags); + + /** + * Perform a STATUS call on multiple mailboxes at the same time. + * + * This method leverages the LIST-EXTENDED and LIST-STATUS extensions on + * the IMAP server to improve the efficiency of this operation. + * + * @deprecated Use status() instead. + * + * @param array $mailboxes The mailboxes to query. Either + * Horde_Imap_Client_Mailbox objects, strings + * (UTF-8), or a combination of the two. + * @param integer $flags See status(). + * @param array $opts Additional options: + * - sort: (boolean) If true, sort the list of mailboxes? + * DEFAULT: Do not sort the list. + * - sort_delimiter: (string) If 'sort' is true, this is the delimiter + * used to sort the mailboxes. + * DEFAULT: '.' + * + * @return array An array with the keys as the mailbox names (UTF-8) and + * the values as arrays with the requested keys (from the + * mask given in $flags). + */ + public function statusMultiple($mailboxes, + $flags = Horde_Imap_Client::STATUS_ALL, + array $opts = array()) + { + return $this->status($mailboxes, $flags, $opts); + } + + /** + * Append message(s) to a mailbox. + * + * @param mixed $mailbox The mailbox to append the message(s) to. Either + * a Horde_Imap_Client_Mailbox object or a string + * (UTF-8). + * @param array $data The message data to append, along with + * additional options. An array of arrays with + * each embedded array having the following + * entries: + *
+     *   - data: (mixed) The data to append. If a string or a stream resource,
+     *           this will be used as the entire contents of a single message.
+     *           If an array, will catenate all given parts into a single
+     *           message. This array contains one or more arrays with
+     *           two keys:
+     *     - t: (string) Either 'url' or 'text'.
+     *     - v: (mixed) If 't' is 'url', this is the IMAP URL to the message
+     *          part to append. If 't' is 'text', this is either a string or
+     *          resource representation of the message part data.
+     *     DEFAULT: NONE (entry is MANDATORY)
+     *   - flags: (array) An array of flags/keywords to set on the appended
+     *            message.
+     *            DEFAULT: Only the \Recent flag is set.
+     *   - internaldate: (DateTime) The internaldate to set for the appended
+     *                   message.
+     *                   DEFAULT: internaldate will be the same date as when
+     *                   the message was appended.
+     * 
+ * @param array $options Additonal options: + *
+     *   - create: (boolean) Try to create $mailbox if it does not exist?
+     *             DEFAULT: No.
+     * 
+ * + * @return Horde_Imap_Client_Ids The UIDs of the appended messages. + * + * @throws Horde_Imap_Client_Exception + */ + public function append($mailbox, $data, array $options = array()) + { + $this->login(); + + $mailbox = Horde_Imap_Client_Mailbox::get($mailbox); + + $ret = $this->_append($mailbox, $data, $options); + + if ($ret instanceof Horde_Imap_Client_Ids) { + return $ret; + } + + $uids = $this->getIdsOb(); + + foreach ($data as $val) { + if (is_resource($val['data'])) { + rewind($val['data']); + } + + $uids->add($this->_getUidByMessageId( + $mailbox, + Horde_Mime_Headers::parseHeaders($val['data'])->getHeader('Message-ID') + )); + } + + return $uids; + } + + /** + * Append message(s) to a mailbox. + * + * @param Horde_Imap_Client_Mailbox $mailbox The mailbox to append the + * message(s) to. + * @param array $data The message data. + * @param array $options Additional options. + * + * @return mixed A Horde_Imap_Client_Ids object containing the UIDs of + * the appended messages (if server supports UIDPLUS + * extension) or true. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _append(Horde_Imap_Client_Mailbox $mailbox, + $data, $options); + + /** + * Request a checkpoint of the currently selected mailbox (RFC 3501 + * [6.4.1]). + * + * @throws Horde_Imap_Client_Exception + */ + public function check() + { + // CHECK only useful if we are already authenticated. + if ($this->_isAuthenticated) { + $this->_check(); + } + } + + /** + * Request a checkpoint of the currently selected mailbox. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _check(); + + /** + * Close the connection to the currently selected mailbox, optionally + * expunging all deleted messages (RFC 3501 [6.4.2]). + * + * @param array $options Additional options: + * - expunge: (boolean) Expunge all messages flagged as deleted? + * DEFAULT: No + * + * @throws Horde_Imap_Client_Exception + */ + public function close(array $options = array()) + { + // This check catches the non-logged in case. + if (is_null($this->_selected)) { + return; + } + + /* If we are caching, search for deleted messages. */ + if (!empty($options['expunge']) && $this->_initCache(true)) { + /* Make sure mailbox is read-write to expunge. */ + $this->openMailbox($this->_selected, Horde_Imap_Client::OPEN_READWRITE); + if ($this->_mode == Horde_Imap_Client::OPEN_READONLY) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Cannot expunge read-only mailbox."), + Horde_Imap_Client_Exception::MAILBOX_READONLY + ); + } + + $search_query = new Horde_Imap_Client_Search_Query(); + $search_query->flag(Horde_Imap_Client::FLAG_DELETED, true); + $search_res = $this->search($this->_selected, $search_query); + $mbox = $this->_selected; + } else { + $search_res = null; + } + + $this->_close($options); + $this->_selected = null; + $this->_mode = 0; + + if (!is_null($search_res)) { + $this->_deleteMsgs($mbox, $search_res['match']); + } + } + + /** + * Close the connection to the currently selected mailbox, optionally + * expunging all deleted messages (RFC 3501 [6.4.2]). + * + * @param array $options Additional options. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _close($options); + + /** + * Expunge deleted messages from the given mailbox. + * + * @param mixed $mailbox The mailbox to expunge. Either a + * Horde_Imap_Client_Mailbox object or a string + * (UTF-8). + * @param array $options Additional options: + * - delete: (boolean) If true, will flag all messages in 'ids' as + * deleted (since 2.10.0). + * DEFAULT: false + * - ids: (Horde_Imap_Client_Ids) A list of messages to expunge. These + * messages must already be flagged as deleted (unless 'delete' + * is true). + * DEFAULT: All messages marked as deleted will be expunged. + * - list: (boolean) If true, returns the list of expunged messages + * (UIDs only). + * DEFAULT: false + * + * @return Horde_Imap_Client_Ids If 'list' option is true, returns the + * UID list of expunged messages. + * + * @throws Horde_Imap_Client_Exception + */ + public function expunge($mailbox, array $options = array()) + { + // Open mailbox call will handle the login. + $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_READWRITE); + + /* Don't expunge if the mailbox is readonly. */ + if ($this->_mode == Horde_Imap_Client::OPEN_READONLY) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Cannot expunge read-only mailbox."), + Horde_Imap_Client_Exception::MAILBOX_READONLY + ); + } + + if (empty($options['ids'])) { + $options['ids'] = $this->getIdsOb(Horde_Imap_Client_Ids::ALL); + } elseif ($options['ids']->isEmpty()) { + return $this->getIdsOb(); + } + + return $this->_expunge($options); + } + + /** + * Expunge all deleted messages from the given mailbox. + * + * @param array $options Additional options. + * + * @return Horde_Imap_Client_Ids If 'list' option is true, returns the + * list of expunged messages. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _expunge($options); + + /** + * Search a mailbox. + * + * @param mixed $mailbox The mailbox to search. + * Either a + * Horde_Imap_Client_Mailbox + * object or a string + * (UTF-8). + * @param Horde_Imap_Client_Search_Query $query The search query. + * Defaults to an ALL + * search. + * @param array $options Additional options: + *
+     *   - nocache: (boolean) Don't cache the results.
+     *              DEFAULT: false (results cached, if possible)
+     *   - partial: (mixed) The range of results to return (message sequence
+     *              numbers) Only a single range is supported (represented by
+     *              the minimum and maximum values contained in the range
+     *              given).
+     *              DEFAULT: All messages are returned.
+     *   - results: (array) The data to return. Consists of zero or more of
+     *              the following flags:
+     *     - Horde_Imap_Client::SEARCH_RESULTS_COUNT
+     *     - Horde_Imap_Client::SEARCH_RESULTS_MATCH (DEFAULT)
+     *     - Horde_Imap_Client::SEARCH_RESULTS_MAX
+     *     - Horde_Imap_Client::SEARCH_RESULTS_MIN
+     *     - Horde_Imap_Client::SEARCH_RESULTS_SAVE
+     *     - Horde_Imap_Client::SEARCH_RESULTS_RELEVANCY
+     *   - sequence: (boolean) If true, returns an array of sequence numbers.
+     *               DEFAULT: Returns an array of UIDs
+     *   - sort: (array) Sort the returned list of messages. Multiple sort
+     *           criteria can be specified. Any sort criteria can be sorted in
+     *           reverse order (instead of the default ascending order) by
+     *           adding a Horde_Imap_Client::SORT_REVERSE element to the array
+     *           directly before adding the sort element. The following sort
+     *           criteria are available:
+     *     - Horde_Imap_Client::SORT_ARRIVAL
+     *     - Horde_Imap_Client::SORT_CC
+     *     - Horde_Imap_Client::SORT_DATE
+     *     - Horde_Imap_Client::SORT_DISPLAYFROM
+     *       On servers that don't support SORT=DISPLAY, this criteria will
+     *       fallback to doing client-side sorting.
+     *     - Horde_Imap_Client::SORT_DISPLAYFROM_FALLBACK
+     *       On servers that don't support SORT=DISPLAY, this criteria will
+     *       fallback to Horde_Imap_Client::SORT_FROM [since 2.4.0].
+     *     - Horde_Imap_Client::SORT_DISPLAYTO
+     *       On servers that don't support SORT=DISPLAY, this criteria will
+     *       fallback to doing client-side sorting.
+     *     - Horde_Imap_Client::SORT_DISPLAYTO_FALLBACK
+     *       On servers that don't support SORT=DISPLAY, this criteria will
+     *       fallback to Horde_Imap_Client::SORT_TO [since 2.4.0].
+     *     - Horde_Imap_Client::SORT_FROM
+     *     - Horde_Imap_Client::SORT_SEQUENCE
+     *     - Horde_Imap_Client::SORT_SIZE
+     *     - Horde_Imap_Client::SORT_SUBJECT
+     *     - Horde_Imap_Client::SORT_TO
+     *
+     *     [On servers that support SEARCH=FUZZY, this criteria is also
+     *     available:]
+     *     - Horde_Imap_Client::SORT_RELEVANCY
+     * 
+ * + * @return array An array with the following keys: + *
+     *   - count: (integer) The number of messages that match the search
+     *            criteria. Always returned.
+     *   - match: (Horde_Imap_Client_Ids) The IDs that match $criteria, sorted
+     *            if the 'sort' modifier was set. Returned if
+     *            Horde_Imap_Client::SEARCH_RESULTS_MATCH is set.
+     *   - max: (integer) The UID (default) or message sequence number (if
+     *          'sequence' is true) of the highest message that satisifies
+     *          $criteria. Returns null if no matches found. Returned if
+     *          Horde_Imap_Client::SEARCH_RESULTS_MAX is set.
+     *   - min: (integer) The UID (default) or message sequence number (if
+     *          'sequence' is true) of the lowest message that satisifies
+     *          $criteria. Returns null if no matches found. Returned if
+     *          Horde_Imap_Client::SEARCH_RESULTS_MIN is set.
+     *   - modseq: (integer) The highest mod-sequence for all messages being
+     *            returned. Returned if 'sort' is false, the search query
+     *            includes a MODSEQ command, and the server supports the
+     *            CONDSTORE IMAP extension.
+     *   - relevancy: (array) The list of relevancy scores. Returned if
+     *                Horde_Imap_Client::SEARCH_RESULTS_RELEVANCY is set and
+     *                the server supports FUZZY search matching.
+     *   - save: (boolean) Whether the search results were saved. Returned if
+     *           Horde_Imap_Client::SEARCH_RESULTS_SAVE is set.
+     * 
+ * + * @throws Horde_Imap_Client_Exception + */ + public function search($mailbox, $query = null, array $options = array()) + { + $this->login(); + + if (empty($options['results'])) { + $options['results'] = array( + Horde_Imap_Client::SEARCH_RESULTS_MATCH, + Horde_Imap_Client::SEARCH_RESULTS_COUNT + ); + } elseif (!in_array(Horde_Imap_Client::SEARCH_RESULTS_COUNT, $options['results'])) { + $options['results'][] = Horde_Imap_Client::SEARCH_RESULTS_COUNT; + } + + // Default to an ALL search. + if (is_null($query)) { + $query = new Horde_Imap_Client_Search_Query(); + } + + // Check for SEARCHRES support. + if ((($pos = array_search(Horde_Imap_Client::SEARCH_RESULTS_SAVE, $options['results'])) !== false) && + !$this->_capability('SEARCHRES')) { + unset($options['results'][$pos]); + } + + // Check for SORT-related options. + if (!empty($options['sort'])) { + foreach ($options['sort'] as $key => $val) { + switch ($val) { + case Horde_Imap_Client::SORT_DISPLAYFROM_FALLBACK: + $options['sort'][$key] = $this->_capability('SORT', 'DISPLAY') + ? Horde_Imap_Client::SORT_DISPLAYFROM + : Horde_Imap_Client::SORT_FROM; + break; + + case Horde_Imap_Client::SORT_DISPLAYTO_FALLBACK: + $options['sort'][$key] = $this->_capability('SORT', 'DISPLAY') + ? Horde_Imap_Client::SORT_DISPLAYTO + : Horde_Imap_Client::SORT_TO; + break; + } + } + } + + /* Default search results. */ + $default_ret = array( + 'count' => 0, + 'match' => $this->getIdsOb(), + 'max' => null, + 'min' => null, + 'relevancy' => array() + ); + + /* Build search query. */ + $squery = $query->build($this); + + /* Check for query contents. If empty, this means that the query + * object has identified that this query can NEVER return any results. + * Immediately return now. */ + if (!count($squery['query'])) { + return $default_ret; + } + + // Check for supported charset. + if (!is_null($squery['charset']) && + ($this->search_charset->query($squery['charset'], true) === false)) { + foreach ($this->search_charset->charsets as $val) { + try { + $new_query = clone $query; + $new_query->charset($val); + break; + } catch (Horde_Imap_Client_Exception_SearchCharset $e) { + unset($new_query); + } + } + + if (!isset($new_query)) { + throw $e; + } + + $query = $new_query; + $squery = $query->build($this); + } + + // Store query in $options array to pass to child method. + $options['_query'] = $squery; + + /* RFC 6203: MUST NOT request relevancy results if we are not using + * FUZZY searching. */ + if (in_array(Horde_Imap_Client::SEARCH_RESULTS_RELEVANCY, $options['results']) && + !in_array('SEARCH=FUZZY', $squery['exts_used'])) { + throw new InvalidArgumentException('Cannot specify RELEVANCY results if not doing a FUZZY search.'); + } + + /* Check for partial matching. */ + if (!empty($options['partial'])) { + $pids = $this->getIdsOb($options['partial'], true)->range_string; + if (!strlen($pids)) { + throw new InvalidArgumentException('Cannot specify empty sequence range for a PARTIAL search.'); + } + + if (strpos($pids, ':') === false) { + $pids .= ':' . $pids; + } + + $options['partial'] = $pids; + } + + /* Optimization - if query is just for a count of either RECENT or + * ALL messages, we can send status information instead. Can't + * optimize with unseen queries because we may cause an infinite loop + * between here and the status() call. */ + if ((count($options['results']) === 1) && + (reset($options['results']) == Horde_Imap_Client::SEARCH_RESULTS_COUNT)) { + switch ($squery['query']) { + case 'ALL': + $ret = $this->status($mailbox, Horde_Imap_Client::STATUS_MESSAGES); + return array('count' => $ret['messages']); + + case 'RECENT': + $ret = $this->status($mailbox, Horde_Imap_Client::STATUS_RECENT); + return array('count' => $ret['recent']); + } + } + + $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_AUTO); + + /* Take advantage of search result caching. If CONDSTORE available, + * we can cache all queries and invalidate the cache when the MODSEQ + * changes. If CONDSTORE not available, we can only store queries + * that don't involve flags. We store results by hashing the options + * array. */ + $cache = null; + if (empty($options['nocache']) && + $this->_initCache(true) && + ($this->_capability()->isEnabled('CONDSTORE') || + !$query->flagSearch())) { + $cache = $this->_getSearchCache('search', $options); + if (isset($cache['data'])) { + if (isset($cache['data']['match'])) { + $cache['data']['match'] = $this->getIdsOb($cache['data']['match']); + } + return $cache['data']; + } + } + + /* Optimization: Catch when there are no messages in a mailbox. */ + $status_res = $this->status($this->_selected, Horde_Imap_Client::STATUS_MESSAGES | Horde_Imap_Client::STATUS_HIGHESTMODSEQ); + if ($status_res['messages'] || + in_array(Horde_Imap_Client::SEARCH_RESULTS_SAVE, $options['results'])) { + /* RFC 7162 [3.1.2.2] - trying to do a MODSEQ SEARCH on a mailbox + * that doesn't support it will return BAD. */ + if (in_array('CONDSTORE', $squery['exts']) && + !$this->_mailboxOb()->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ)) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Mailbox does not support mod-sequences."), + Horde_Imap_Client_Exception::MBOXNOMODSEQ + ); + } + + $ret = $this->_search($query, $options); + } else { + $ret = $default_ret; + if (isset($status_res['highestmodseq'])) { + $ret['modseq'] = $status_res['highestmodseq']; + } + } + + if ($cache) { + $save = $ret; + if (isset($save['match'])) { + $save['match'] = strval($ret['match']); + } + $this->_setSearchCache($save, $cache); + } + + return $ret; + } + + /** + * Search a mailbox. + * + * @param object $query The search query. + * @param array $options Additional options. The '_query' key contains + * the value of $query->build(). + * + * @return Horde_Imap_Client_Ids An array of IDs. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _search($query, $options); + + /** + * Set the comparator to use for searching/sorting (RFC 5255). + * + * @param string $comparator The comparator string (see RFC 4790 [3.1] - + * "collation-id" - for format). The reserved + * string 'default' can be used to select + * the default comparator. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function setComparator($comparator = null) + { + $comp = is_null($comparator) + ? $this->getParam('comparator') + : $comparator; + if (is_null($comp)) { + return; + } + + $this->login(); + + if (!$this->_capability('I18NLEVEL', '2')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension( + 'I18NLEVEL', + 'The IMAP server does not support changing SEARCH/SORT comparators.' + ); + } + + $this->_setComparator($comp); + } + + /** + * Set the comparator to use for searching/sorting (RFC 5255). + * + * @param string $comparator The comparator string (see RFC 4790 [3.1] - + * "collation-id" - for format). The reserved + * string 'default' can be used to select + * the default comparator. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _setComparator($comparator); + + /** + * Get the comparator used for searching/sorting (RFC 5255). + * + * @return mixed Null if the default comparator is being used, or an + * array of comparator information (see RFC 5255 [4.8]). + * + * @throws Horde_Imap_Client_Exception + */ + public function getComparator() + { + $this->login(); + + return $this->_capability('I18NLEVEL', '2') + ? $this->_getComparator() + : null; + } + + /** + * Get the comparator used for searching/sorting (RFC 5255). + * + * @return mixed Null if the default comparator is being used, or an + * array of comparator information (see RFC 5255 [4.8]). + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _getComparator(); + + /** + * Thread sort a given list of messages (RFC 5256). + * + * @param mixed $mailbox The mailbox to query. Either a + * Horde_Imap_Client_Mailbox object or a string + * (UTF-8). + * @param array $options Additional options: + *
+     *   - criteria: (mixed) The following thread criteria are available:
+     *     - Horde_Imap_Client::THREAD_ORDEREDSUBJECT
+     *     - Horde_Imap_Client::THREAD_REFERENCES
+     *     - Horde_Imap_Client::THREAD_REFS
+     *       Other algorithms can be explicitly specified by passing the IMAP
+     *       thread algorithm in as a string value.
+     *     DEFAULT: Horde_Imap_Client::THREAD_ORDEREDSUBJECT
+     *   - search: (Horde_Imap_Client_Search_Query) The search query.
+     *             DEFAULT: All messages in mailbox included in thread sort.
+     *   - sequence: (boolean) If true, each message is stored and referred to
+     *               by its message sequence number.
+     *               DEFAULT: Stored/referred to by UID.
+     * 
+ * + * @return Horde_Imap_Client_Data_Thread A thread data object. + * + * @throws Horde_Imap_Client_Exception + */ + public function thread($mailbox, array $options = array()) + { + // Open mailbox call will handle the login. + $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_AUTO); + + /* Take advantage of search result caching. If CONDSTORE available, + * we can cache all queries and invalidate the cache when the MODSEQ + * changes. If CONDSTORE not available, we can only store queries + * that don't involve flags. See search() for similar caching. */ + $cache = null; + if ($this->_initCache(true) && + ($this->_capability()->isEnabled('CONDSTORE') || + empty($options['search']) || + !$options['search']->flagSearch())) { + $cache = $this->_getSearchCache('thread', $options); + if (isset($cache['data']) && + ($cache['data'] instanceof Horde_Imap_Client_Data_Thread)) { + return $cache['data']; + } + } + + $status_res = $this->status($this->_selected, Horde_Imap_Client::STATUS_MESSAGES); + + $ob = $status_res['messages'] + ? $this->_thread($options) + : new Horde_Imap_Client_Data_Thread(array(), empty($options['sequence']) ? 'uid' : 'sequence'); + + if ($cache) { + $this->_setSearchCache($ob, $cache); + } + + return $ob; + } + + /** + * Thread sort a given list of messages (RFC 5256). + * + * @param array $options Additional options. See thread(). + * + * @return Horde_Imap_Client_Data_Thread A thread data object. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _thread($options); + + /** + * Fetch message data (see RFC 3501 [6.4.5]). + * + * @param mixed $mailbox The mailbox to search. + * Either a + * Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * @param Horde_Imap_Client_Fetch_Query $query Fetch query object. + * @param array $options Additional options: + * - changedsince: (integer) Only return messages that have a + * mod-sequence larger than this value. This option + * requires the CONDSTORE IMAP extension (if not present, + * this value is ignored). Additionally, the mailbox + * must support mod-sequences or an exception will be + * thrown. If valid, this option implicity adds the + * mod-sequence fetch criteria to the fetch command. + * DEFAULT: Mod-sequence values are ignored. + * - exists: (boolean) Ensure that all ids returned exist on the server. + * If false, the list of ids returned in the results object + * is not guaranteed to reflect the current state of the + * remote mailbox. + * DEFAULT: false + * - ids: (Horde_Imap_Client_Ids) A list of messages to fetch data from. + * DEFAULT: All messages in $mailbox will be fetched. + * - nocache: (boolean) If true, will not cache the results (previously + * cached data will still be used to generate results) [since + * 2.8.0]. + * DEFAULT: false + * + * @return Horde_Imap_Client_Fetch_Results A results object. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function fetch($mailbox, $query, array $options = array()) + { + try { + $ret = $this->_fetchWrapper($mailbox, $query, $options); + unset($this->_temp['fetch_nocache']); + return $ret; + } catch (Exception $e) { + unset($this->_temp['fetch_nocache']); + throw $e; + } + } + + /** + * Wrapper for fetch() to allow internal state to be reset on exception. + * + * @internal + * @see fetch() + */ + private function _fetchWrapper($mailbox, $query, $options) + { + $this->login(); + + $query = clone $query; + + $cache_array = $header_cache = $new_query = array(); + + if (empty($options['ids'])) { + $options['ids'] = $this->getIdsOb(Horde_Imap_Client_Ids::ALL); + } elseif ($options['ids']->isEmpty()) { + return new Horde_Imap_Client_Fetch_Results($this->_fetchDataClass); + } elseif ($options['ids']->search_res && + !$this->_capability('SEARCHRES')) { + /* SEARCHRES requires server support. */ + throw new Horde_Imap_Client_Exception_NoSupportExtension('SEARCHRES'); + } + + $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_AUTO); + $mbox_ob = $this->_mailboxOb(); + + if (!empty($options['nocache'])) { + $this->_temp['fetch_nocache'] = true; + } + + $cf = $this->_initCache(true) + ? $this->_cacheFields() + : array(); + + if (!empty($cf)) { + /* If using cache, we store by UID so we need to return UIDs. */ + $query->uid(); + } + + $modseq_check = !empty($options['changedsince']); + if ($query->contains(Horde_Imap_Client::FETCH_MODSEQ)) { + if (!$this->_capability()->isEnabled('CONDSTORE')) { + unset($query[Horde_Imap_Client::FETCH_MODSEQ]); + } elseif (empty($options['changedsince'])) { + $modseq_check = true; + } + } + + if ($modseq_check && + !$mbox_ob->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ)) { + /* RFC 7162 [3.1.2.2] - trying to do a MODSEQ FETCH on a mailbox + * that doesn't support it will return BAD. */ + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Mailbox does not support mod-sequences."), + Horde_Imap_Client_Exception::MBOXNOMODSEQ + ); + } + + /* Determine if caching is available and if anything in $query is + * cacheable. */ + foreach ($cf as $k => $v) { + if (isset($query[$k])) { + switch ($k) { + case Horde_Imap_Client::FETCH_ENVELOPE: + case Horde_Imap_Client::FETCH_FLAGS: + case Horde_Imap_Client::FETCH_IMAPDATE: + case Horde_Imap_Client::FETCH_SIZE: + case Horde_Imap_Client::FETCH_STRUCTURE: + $cache_array[$k] = $v; + break; + + case Horde_Imap_Client::FETCH_HEADERS: + $this->_temp['headers_caching'] = array(); + + foreach ($query[$k] as $key => $val) { + /* Only cache if directly requested. Iterate through + * requests to ensure at least one can be cached. */ + if (!empty($val['cache']) && !empty($val['peek'])) { + $cache_array[$k] = $v; + ksort($val); + $header_cache[$key] = hash('md5', serialize($val)); + } + } + break; + } + } + } + + $ret = new Horde_Imap_Client_Fetch_Results( + $this->_fetchDataClass, + $options['ids']->sequence ? Horde_Imap_Client_Fetch_Results::SEQUENCE : Horde_Imap_Client_Fetch_Results::UID + ); + + /* If nothing is cacheable, we can do a straight search. */ + if (empty($cache_array)) { + $options['_query'] = $query; + $this->_fetch($ret, array($options)); + return $ret; + } + + $cs_ret = empty($options['changedsince']) + ? null + : clone $ret; + + /* Convert special searches to UID lists and create mapping. */ + $ids = $this->resolveIds( + $this->_selected, + $options['ids'], + empty($options['exists']) ? 1 : 2 + ); + + /* Add non-user settable cache fields. */ + $cache_array[Horde_Imap_Client::FETCH_DOWNGRADED] = self::CACHE_DOWNGRADED; + + /* Get the cached values. */ + $data = $this->_cache->get( + $this->_selected, + $ids->ids, + array_values($cache_array), + $mbox_ob->getStatus(Horde_Imap_Client::STATUS_UIDVALIDITY) + ); + + /* Build a list of what we still need. */ + $map = array_flip($mbox_ob->map->map); + $sequence = $options['ids']->sequence; + foreach ($ids as $uid) { + $crit = clone $query; + + if ($sequence) { + if (!isset($map[$uid])) { + continue; + } + $entry_idx = $map[$uid]; + } else { + $entry_idx = $uid; + unset($crit[Horde_Imap_Client::FETCH_UID]); + } + + $entry = $ret->get($entry_idx); + + if (isset($map[$uid])) { + $entry->setSeq($map[$uid]); + unset($crit[Horde_Imap_Client::FETCH_SEQ]); + } + + $entry->setUid($uid); + + foreach ($cache_array as $key => $cid) { + switch ($key) { + case Horde_Imap_Client::FETCH_DOWNGRADED: + if (!empty($data[$uid][$cid])) { + $entry->setDowngraded(true); + } + break; + + case Horde_Imap_Client::FETCH_ENVELOPE: + if (isset($data[$uid][$cid]) && + ($data[$uid][$cid] instanceof Horde_Imap_Client_Data_Envelope)) { + $entry->setEnvelope($data[$uid][$cid]); + unset($crit[$key]); + } + break; + + case Horde_Imap_Client::FETCH_FLAGS: + if (isset($data[$uid][$cid]) && + is_array($data[$uid][$cid])) { + $entry->setFlags($data[$uid][$cid]); + unset($crit[$key]); + } + break; + + case Horde_Imap_Client::FETCH_HEADERS: + foreach ($header_cache as $hkey => $hval) { + if (isset($data[$uid][$cid][$hval])) { + /* We have found a cached entry with the same + * MD5 sum. */ + $entry->setHeaders($hkey, $data[$uid][$cid][$hval]); + $crit->remove($key, $hkey); + } else { + $this->_temp['headers_caching'][$hkey] = $hval; + } + } + break; + + case Horde_Imap_Client::FETCH_IMAPDATE: + if (isset($data[$uid][$cid]) && + ($data[$uid][$cid] instanceof Horde_Imap_Client_DateTime)) { + $entry->setImapDate($data[$uid][$cid]); + unset($crit[$key]); + } + break; + + case Horde_Imap_Client::FETCH_SIZE: + if (isset($data[$uid][$cid])) { + $entry->setSize($data[$uid][$cid]); + unset($crit[$key]); + } + break; + + case Horde_Imap_Client::FETCH_STRUCTURE: + if (isset($data[$uid][$cid]) && + ($data[$uid][$cid] instanceof Horde_Mime_Part)) { + $entry->setStructure($data[$uid][$cid]); + unset($crit[$key]); + } + break; + } + } + + if (count($crit)) { + $sig = $crit->hash(); + if (isset($new_query[$sig])) { + $new_query[$sig]['i'][] = $entry_idx; + } else { + $new_query[$sig] = array( + 'c' => $crit, + 'i' => array($entry_idx) + ); + } + } + } + + $to_fetch = array(); + foreach ($new_query as $val) { + $ids_ob = $this->getIdsOb(null, $sequence); + $ids_ob->duplicates = true; + $ids_ob->add($val['i']); + $to_fetch[] = array_merge($options, array( + '_query' => $val['c'], + 'ids' => $ids_ob + )); + } + + if (!empty($to_fetch)) { + $this->_fetch(is_null($cs_ret) ? $ret : $cs_ret, $to_fetch); + } + + if (is_null($cs_ret)) { + return $ret; + } + + /* If doing changedsince query, and all other data is cached, we still + * need to hit IMAP server to determine proper results set. */ + if (empty($new_query)) { + $squery = new Horde_Imap_Client_Search_Query(); + $squery->modseq($options['changedsince'] + 1); + $squery->ids($options['ids']); + + $cs = $this->search($this->_selected, $squery, array( + 'sequence' => $sequence + )); + + foreach ($cs['match'] as $val) { + $entry = $ret->get($val); + if ($sequence) { + $entry->setSeq($val); + } else { + $entry->setUid($val); + } + $cs_ret[$val] = $entry; + } + } else { + foreach ($cs_ret as $key => $val) { + $val->merge($ret->get($key)); + } + } + + return $cs_ret; + } + + /** + * Fetch message data. + * + * Fetch queries should be grouped in the $queries argument. Each value + * is an array of fetch options, with the fetch query stored in the + * '_query' parameter. IMPORTANT: All queries must have the same ID + * type (either sequence or UID). + * + * @param Horde_Imap_Client_Fetch_Results $results Fetch results. + * @param array $queries The list of queries. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _fetch(Horde_Imap_Client_Fetch_Results $results, + $queries); + + /** + * Get the list of vanished messages (UIDs that have been expunged since a + * given mod-sequence value). + * + * @param mixed $mailbox The mailbox to query. Either a + * Horde_Imap_Client_Mailbox object or a string + * (UTF-8). + * @param integer $modseq Search for expunged messages after this + * mod-sequence value. + * @param array $opts Additional options: + * - ids: (Horde_Imap_Client_Ids) Restrict to these UIDs. + * DEFAULT: Returns full list of UIDs vanished (QRESYNC only). + * This option is REQUIRED for non-QRESYNC servers or + * else an empty list will be returned. + * + * @return Horde_Imap_Client_Ids List of UIDs that have vanished. + * + * @throws Horde_Imap_Client_NoSupportExtension + */ + public function vanished($mailbox, $modseq, array $opts = array()) + { + $this->login(); + + if (empty($opts['ids'])) { + if (!$this->_capability()->isEnabled('QRESYNC')) { + return $this->getIdsOb(); + } + $opts['ids'] = $this->getIdsOb(Horde_Imap_Client_Ids::ALL); + } elseif ($opts['ids']->isEmpty()) { + return $this->getIdsOb(); + } elseif ($opts['ids']->sequence) { + throw new InvalidArgumentException('Vanished requires UIDs.'); + } + + $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_AUTO); + + if ($this->_capability()->isEnabled('QRESYNC')) { + if (!$this->_mailboxOb()->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ)) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Mailbox does not support mod-sequences."), + Horde_Imap_Client_Exception::MBOXNOMODSEQ + ); + } + + return $this->_vanished(max(1, $modseq), $opts['ids']); + } + + $ids = $this->resolveIds($mailbox, $opts['ids']); + + $squery = new Horde_Imap_Client_Search_Query(); + $squery->ids($ids); + $search = $this->search($mailbox, $squery, array( + 'nocache' => true + )); + + return $this->getIdsOb(array_diff($ids->ids, $search['match']->ids)); + } + + /** + * Get the list of vanished messages. + * + * @param integer $modseq Mod-sequence value. + * @param Horde_Imap_Client_Ids $ids UIDs. + * + * @return Horde_Imap_Client_Ids List of UIDs that have vanished. + */ + abstract protected function _vanished($modseq, Horde_Imap_Client_Ids $ids); + + /** + * Store message flag data (see RFC 3501 [6.4.6]). + * + * @param mixed $mailbox The mailbox containing the messages to modify. + * Either a Horde_Imap_Client_Mailbox object or a + * string (UTF-8). + * @param array $options Additional options: + * - add: (array) An array of flags to add. + * DEFAULT: No flags added. + * - ids: (Horde_Imap_Client_Ids) The list of messages to modify. + * DEFAULT: All messages in $mailbox will be modified. + * - remove: (array) An array of flags to remove. + * DEFAULT: No flags removed. + * - replace: (array) Replace the current flags with this set + * of flags. Overrides both the 'add' and 'remove' options. + * DEFAULT: No replace is performed. + * - unchangedsince: (integer) Only changes flags if the mod-sequence ID + * of the message is equal or less than this value. + * Requires the CONDSTORE IMAP extension on the server. + * Also requires the mailbox to support mod-sequences. + * Will throw an exception if either condition is not + * met. + * DEFAULT: mod-sequence is ignored when applying + * changes + * + * @return Horde_Imap_Client_Ids A Horde_Imap_Client_Ids object + * containing the list of IDs that failed + * the 'unchangedsince' test. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function store($mailbox, array $options = array()) + { + // Open mailbox call will handle the login. + $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_READWRITE); + + /* SEARCHRES requires server support. */ + if (empty($options['ids'])) { + $options['ids'] = $this->getIdsOb(Horde_Imap_Client_Ids::ALL); + } elseif ($options['ids']->isEmpty()) { + return $this->getIdsOb(); + } elseif ($options['ids']->search_res && + !$this->_capability('SEARCHRES')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('SEARCHRES'); + } + + if (!empty($options['unchangedsince'])) { + if (!$this->_capability()->isEnabled('CONDSTORE')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('CONDSTORE'); + } + + /* RFC 7162 [3.1.2.2] - trying to do a UNCHANGEDSINCE STORE on a + * mailbox that doesn't support it will return BAD. */ + if (!$this->_mailboxOb()->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ)) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Mailbox does not support mod-sequences."), + Horde_Imap_Client_Exception::MBOXNOMODSEQ + ); + } + } + + return $this->_store($options); + } + + /** + * Store message flag data. + * + * @param array $options Additional options. + * + * @return Horde_Imap_Client_Ids A Horde_Imap_Client_Ids object + * containing the list of IDs that failed + * the 'unchangedsince' test. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _store($options); + + /** + * Copy messages to another mailbox. + * + * @param mixed $source The source mailbox. Either a + * Horde_Imap_Client_Mailbox object or a string + * (UTF-8). + * @param mixed $dest The destination mailbox. Either a + * Horde_Imap_Client_Mailbox object or a string + * (UTF-8). + * @param array $options Additional options: + * - create: (boolean) Try to create $dest if it does not exist? + * DEFAULT: No. + * - force_map: (boolean) Forces the array mapping to always be + * returned. [@since 2.19.0] + * - ids: (Horde_Imap_Client_Ids) The list of messages to copy. + * DEFAULT: All messages in $mailbox will be copied. + * - move: (boolean) If true, delete the original messages. + * DEFAULT: Original messages are not deleted. + * + * @return mixed An array mapping old UIDs (keys) to new UIDs (values) on + * success (only guaranteed if 'force_map' is true) or + * true. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function copy($source, $dest, array $options = array()) + { + // Open mailbox call will handle the login. + $this->openMailbox($source, empty($options['move']) ? Horde_Imap_Client::OPEN_AUTO : Horde_Imap_Client::OPEN_READWRITE); + + /* SEARCHRES requires server support. */ + if (empty($options['ids'])) { + $options['ids'] = $this->getIdsOb(Horde_Imap_Client_Ids::ALL); + } elseif ($options['ids']->isEmpty()) { + return array(); + } elseif ($options['ids']->search_res && + !$this->_capability('SEARCHRES')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('SEARCHRES'); + } + + $dest = Horde_Imap_Client_Mailbox::get($dest); + $res = $this->_copy($dest, $options); + + if (($res === true) && !empty($options['force_map'])) { + /* Need to manually create mapping from Message-ID data. */ + $query = new Horde_Imap_Client_Fetch_Query(); + $query->envelope(); + $fetch = $this->fetch($source, $query, array( + 'ids' => $options['ids'] + )); + + $res = array(); + foreach ($fetch as $val) { + if ($uid = $this->_getUidByMessageId($dest, $val->getEnvelope()->message_id)) { + $res[$val->getUid()] = $uid; + } + } + } + + return $res; + } + + /** + * Copy messages to another mailbox. + * + * @param Horde_Imap_Client_Mailbox $dest The destination mailbox. + * @param array $options Additional options. + * + * @return mixed An array mapping old UIDs (keys) to new UIDs (values) on + * success (if the IMAP server and/or driver support the + * UIDPLUS extension) or true. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _copy(Horde_Imap_Client_Mailbox $dest, + $options); + + /** + * Set quota limits. The server must support the IMAP QUOTA extension + * (RFC 2087). + * + * @param mixed $root The quota root. Either a + * Horde_Imap_Client_Mailbox object or a string + * (UTF-8). + * @param array $resources The resource values to set. Keys are the + * resource atom name; value is the resource + * value. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function setQuota($root, array $resources = array()) + { + $this->login(); + + if (!$this->_capability('QUOTA')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('QUOTA'); + } + + if (!empty($resources)) { + $this->_setQuota(Horde_Imap_Client_Mailbox::get($root), $resources); + } + } + + /** + * Set quota limits. + * + * @param Horde_Imap_Client_Mailbox $root The quota root. + * @param array $resources The resource values to set. + * + * @return boolean True on success. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _setQuota(Horde_Imap_Client_Mailbox $root, + $resources); + + /** + * Get quota limits. The server must support the IMAP QUOTA extension + * (RFC 2087). + * + * @param mixed $root The quota root. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * + * @return mixed An array with resource keys. Each key holds an array + * with 2 values: 'limit' and 'usage'. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function getQuota($root) + { + $this->login(); + + if (!$this->_capability('QUOTA')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('QUOTA'); + } + + return $this->_getQuota(Horde_Imap_Client_Mailbox::get($root)); + } + + /** + * Get quota limits. + * + * @param Horde_Imap_Client_Mailbox $root The quota root. + * + * @return mixed An array with resource keys. Each key holds an array + * with 2 values: 'limit' and 'usage'. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _getQuota(Horde_Imap_Client_Mailbox $root); + + /** + * Get quota limits for a mailbox. The server must support the IMAP QUOTA + * extension (RFC 2087). + * + * @param mixed $mailbox A mailbox. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * + * @return mixed An array with the keys being the quota roots. Each key + * holds an array with resource keys: each of these keys + * holds an array with 2 values: 'limit' and 'usage'. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function getQuotaRoot($mailbox) + { + $this->login(); + + if (!$this->_capability('QUOTA')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('QUOTA'); + } + + return $this->_getQuotaRoot(Horde_Imap_Client_Mailbox::get($mailbox)); + } + + /** + * Get quota limits for a mailbox. + * + * @param Horde_Imap_Client_Mailbox $mailbox A mailbox. + * + * @return mixed An array with the keys being the quota roots. Each key + * holds an array with resource keys: each of these keys + * holds an array with 2 values: 'limit' and 'usage'. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _getQuotaRoot(Horde_Imap_Client_Mailbox $mailbox); + + /** + * Get the ACL rights for a given mailbox. The server must support the + * IMAP ACL extension (RFC 2086/4314). + * + * @param mixed $mailbox A mailbox. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * + * @return array An array with identifiers as the keys and + * Horde_Imap_Client_Data_Acl objects as the values. + * + * @throws Horde_Imap_Client_Exception + */ + public function getACL($mailbox) + { + $this->login(); + return $this->_getACL(Horde_Imap_Client_Mailbox::get($mailbox)); + } + + /** + * Get ACL rights for a given mailbox. + * + * @param Horde_Imap_Client_Mailbox $mailbox A mailbox. + * + * @return array An array with identifiers as the keys and + * Horde_Imap_Client_Data_Acl objects as the values. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _getACL(Horde_Imap_Client_Mailbox $mailbox); + + /** + * Set ACL rights for a given mailbox/identifier. + * + * @param mixed $mailbox A mailbox. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * @param string $identifier The identifier to alter (UTF-8). + * @param array $options Additional options: + * - rights: (string) The rights to alter or set. + * - action: (string, optional) If 'add' or 'remove', adds or removes the + * specified rights. Sets the rights otherwise. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function setACL($mailbox, $identifier, $options) + { + $this->login(); + + if (!$this->_capability('ACL')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('ACL'); + } + + if (empty($options['rights'])) { + if (!isset($options['action']) || + (($options['action'] != 'add') && + $options['action'] != 'remove')) { + $this->_deleteACL( + Horde_Imap_Client_Mailbox::get($mailbox), + Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($identifier) + ); + } + return; + } + + $acl = ($options['rights'] instanceof Horde_Imap_Client_Data_Acl) + ? $options['rights'] + : new Horde_Imap_Client_Data_Acl(strval($options['rights'])); + + $options['rights'] = $acl->getString( + $this->_capability('RIGHTS') + ? Horde_Imap_Client_Data_AclCommon::RFC_4314 + : Horde_Imap_Client_Data_AclCommon::RFC_2086 + ); + if (isset($options['action'])) { + switch ($options['action']) { + case 'add': + $options['rights'] = '+' . $options['rights']; + break; + case 'remove': + $options['rights'] = '-' . $options['rights']; + break; + } + } + + $this->_setACL( + Horde_Imap_Client_Mailbox::get($mailbox), + Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($identifier), + $options + ); + } + + /** + * Set ACL rights for a given mailbox/identifier. + * + * @param Horde_Imap_Client_Mailbox $mailbox A mailbox. + * @param string $identifier The identifier to alter + * (UTF7-IMAP). + * @param array $options Additional options. 'rights' + * contains the string of + * rights to set on the server. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _setACL(Horde_Imap_Client_Mailbox $mailbox, + $identifier, $options); + + /** + * Deletes ACL rights for a given mailbox/identifier. + * + * @param mixed $mailbox A mailbox. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * @param string $identifier The identifier to delete (UTF-8). + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function deleteACL($mailbox, $identifier) + { + $this->login(); + + if (!$this->_capability('ACL')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('ACL'); + } + + $this->_deleteACL( + Horde_Imap_Client_Mailbox::get($mailbox), + Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($identifier) + ); + } + + /** + * Deletes ACL rights for a given mailbox/identifier. + * + * @param Horde_Imap_Client_Mailbox $mailbox A mailbox. + * @param string $identifier The identifier to delete + * (UTF7-IMAP). + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _deleteACL(Horde_Imap_Client_Mailbox $mailbox, + $identifier); + + /** + * List the ACL rights for a given mailbox/identifier. The server must + * support the IMAP ACL extension (RFC 2086/4314). + * + * @param mixed $mailbox A mailbox. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * @param string $identifier The identifier to query (UTF-8). + * + * @return Horde_Imap_Client_Data_AclRights An ACL data rights object. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function listACLRights($mailbox, $identifier) + { + $this->login(); + + if (!$this->_capability('ACL')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('ACL'); + } + + return $this->_listACLRights( + Horde_Imap_Client_Mailbox::get($mailbox), + Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($identifier) + ); + } + + /** + * Get ACL rights for a given mailbox/identifier. + * + * @param Horde_Imap_Client_Mailbox $mailbox A mailbox. + * @param string $identifier The identifier to query + * (UTF7-IMAP). + * + * @return Horde_Imap_Client_Data_AclRights An ACL data rights object. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _listACLRights(Horde_Imap_Client_Mailbox $mailbox, + $identifier); + + /** + * Get the ACL rights for the current user for a given mailbox. The + * server must support the IMAP ACL extension (RFC 2086/4314). + * + * @param mixed $mailbox A mailbox. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * + * @return Horde_Imap_Client_Data_Acl An ACL data object. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function getMyACLRights($mailbox) + { + $this->login(); + + if (!$this->_capability('ACL')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('ACL'); + } + + return $this->_getMyACLRights(Horde_Imap_Client_Mailbox::get($mailbox)); + } + + /** + * Get the ACL rights for the current user for a given mailbox. + * + * @param Horde_Imap_Client_Mailbox $mailbox A mailbox. + * + * @return Horde_Imap_Client_Data_Acl An ACL data object. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _getMyACLRights(Horde_Imap_Client_Mailbox $mailbox); + + /** + * Return master list of ACL rights available on the server. + * + * @return array A list of ACL rights. + */ + public function allAclRights() + { + $this->login(); + + $rights = array( + Horde_Imap_Client::ACL_LOOKUP, + Horde_Imap_Client::ACL_READ, + Horde_Imap_Client::ACL_SEEN, + Horde_Imap_Client::ACL_WRITE, + Horde_Imap_Client::ACL_INSERT, + Horde_Imap_Client::ACL_POST, + Horde_Imap_Client::ACL_ADMINISTER + ); + + if ($capability = $this->_capability()->getParams('RIGHTS')) { + // Add rights defined in CAPABILITY string (RFC 4314). + return array_merge($rights, str_split(reset($capability))); + } + + // Add RFC 2086 rights (deprecated by RFC 4314, but need to keep for + // compatibility with old servers). + return array_merge($rights, array( + Horde_Imap_Client::ACL_CREATE, + Horde_Imap_Client::ACL_DELETE + )); + } + + /** + * Get metadata for a given mailbox. The server must support either the + * IMAP METADATA extension (RFC 5464) or the ANNOTATEMORE extension + * (http://ietfreport.isoc.org/idref/draft-daboo-imap-annotatemore/). + * + * @param mixed $mailbox A mailbox. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * @param array $entries The entries to fetch (UTF-8 strings). + * @param array $options Additional options: + * - depth: (string) Either "0", "1" or "infinity". Returns only the + * given value (0), only values one level below the specified + * value (1) or all entries below the specified value + * (infinity). + * - maxsize: (integer) The maximal size the returned values may have. + * DEFAULT: No maximal size. + * + * @return array An array with metadata names as the keys and metadata + * values as the values. If 'maxsize' is set, and entries + * exist on the server larger than this size, the size will + * be returned in the key '*longentries'. + * + * @throws Horde_Imap_Client_Exception + */ + public function getMetadata($mailbox, $entries, array $options = array()) + { + $this->login(); + + if (!is_array($entries)) { + $entries = array($entries); + } + + return $this->_getMetadata(Horde_Imap_Client_Mailbox::get($mailbox), array_map(array('Horde_Imap_Client_Utf7imap', 'Utf8ToUtf7Imap'), $entries), $options); + } + + /** + * Get metadata for a given mailbox. + * + * @param Horde_Imap_Client_Mailbox $mailbox A mailbox. + * @param array $entries The entries to fetch + * (UTF7-IMAP strings). + * @param array $options Additional options. + * + * @return array An array with metadata names as the keys and metadata + * values as the values. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _getMetadata(Horde_Imap_Client_Mailbox $mailbox, + $entries, $options); + + /** + * Set metadata for a given mailbox/identifier. + * + * @param mixed $mailbox A mailbox. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). If empty, sets a + * server annotation. + * @param array $data A set of data values. The metadata values + * corresponding to the keys of the array will + * be set to the values in the array. + * + * @throws Horde_Imap_Client_Exception + */ + public function setMetadata($mailbox, $data) + { + $this->login(); + $this->_setMetadata(Horde_Imap_Client_Mailbox::get($mailbox), $data); + } + + /** + * Set metadata for a given mailbox/identifier. + * + * @param Horde_Imap_Client_Mailbox $mailbox A mailbox. + * @param array $data A set of data values. See + * setMetadata() for format. + * + * @throws Horde_Imap_Client_Exception + */ + abstract protected function _setMetadata(Horde_Imap_Client_Mailbox $mailbox, + $data); + + /* Public utility functions. */ + + /** + * Returns a unique identifier for the current mailbox status. + * + * @deprecated + * + * @param mixed $mailbox A mailbox. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * @param array $addl Additional cache info to add to the cache ID + * string. + * + * @return string The cache ID string, which will change when the + * composition of the mailbox changes. The uidvalidity + * will always be the first element, and will be delimited + * by the '|' character. + * + * @throws Horde_Imap_Client_Exception + */ + public function getCacheId($mailbox, array $addl = array()) + { + return Horde_Imap_Client_Base_Deprecated::getCacheId($this, $mailbox, $this->_capability()->isEnabled('CONDSTORE'), $addl); + } + + /** + * Parses a cacheID created by getCacheId(). + * + * @deprecated + * + * @param string $id The cache ID. + * + * @return array An array with the following information: + * - highestmodseq: (integer) + * - messages: (integer) + * - uidnext: (integer) + * - uidvalidity: (integer) Always present + */ + public function parseCacheId($id) + { + return Horde_Imap_Client_Base_Deprecated::parseCacheId($id); + } + + /** + * Resolves an IDs object into a list of IDs. + * + * @param Horde_Imap_Client_Mailbox $mailbox The mailbox. + * @param Horde_Imap_Client_Ids $ids The Ids object. + * @param integer $convert Convert to UIDs? + * - 0: No + * - 1: Only if $ids is not already a UIDs object + * - 2: Always + * + * @return Horde_Imap_Client_Ids The list of IDs. + */ + public function resolveIds(Horde_Imap_Client_Mailbox $mailbox, + Horde_Imap_Client_Ids $ids, $convert = 0) + { + $map = $this->_mailboxOb($mailbox)->map; + + if ($ids->special) { + /* Optimization for ALL sequence searches. */ + if (!$convert && $ids->all && $ids->sequence) { + $res = $this->status($mailbox, Horde_Imap_Client::STATUS_MESSAGES); + return $this->getIdsOb($res['messages'] ? ('1:' . $res['messages']) : array(), true); + } + + $convert = 2; + } elseif (!$convert || + (!$ids->sequence && ($convert == 1)) || + $ids->isEmpty()) { + return clone $ids; + } else { + /* Do an all or nothing: either we have all the numbers/UIDs in + * memory and can return, or just send the whole ID query to the + * server. Any advantage we would get by a partial search are + * outweighed by the complexities needed to make the search and + * then merge back into the original results. */ + $lookup = $map->lookup($ids); + if (count($lookup) === count($ids)) { + return $this->getIdsOb(array_values($lookup)); + } + } + + $query = new Horde_Imap_Client_Search_Query(); + $query->ids($ids); + + $res = $this->search($mailbox, $query, array( + 'results' => array( + Horde_Imap_Client::SEARCH_RESULTS_MATCH, + Horde_Imap_Client::SEARCH_RESULTS_SAVE + ), + 'sequence' => (!$convert && $ids->sequence), + 'sort' => array(Horde_Imap_Client::SORT_SEQUENCE) + )); + + /* Update mapping. */ + if ($convert) { + if ($ids->all) { + $ids = $this->getIdsOb('1:' . count($res['match'])); + } elseif ($ids->special) { + return $res['match']; + } + + /* Sanity checking (Bug #12911). */ + $list1 = array_slice($ids->ids, 0, count($res['match'])); + $list2 = $res['match']->ids; + if (!empty($list1) && + !empty($list2) && + (count($list1) === count($list2))) { + $map->update(array_combine($list1, $list2)); + } + } + + return $res['match']; + } + + /** + * Determines if the given charset is valid for search-related queries. + * This check pertains just to the basic IMAP SEARCH command. + * + * @deprecated Use $search_charset property instead. + * + * @param string $charset The query charset. + * + * @return boolean True if server supports this charset. + */ + public function validSearchCharset($charset) + { + return $this->search_charset->query($charset); + } + + /* Mailbox syncing functions. */ + + /** + * Returns a unique token for the current mailbox synchronization status. + * + * @since 2.2.0 + * + * @param mixed $mailbox A mailbox. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * + * @return string The sync token. + * + * @throws Horde_Imap_Client_Exception + */ + public function getSyncToken($mailbox) + { + $out = array(); + + foreach ($this->_syncStatus($mailbox) as $key => $val) { + $out[] = $key . $val; + } + + return base64_encode(implode(',', $out)); + } + + /** + * Synchronize a mailbox from a sync token. + * + * @since 2.2.0 + * + * @param mixed $mailbox A mailbox. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * @param string $token A sync token generated by getSyncToken(). + * @param array $opts Additional options: + * - criteria: (integer) Mask of Horde_Imap_Client::SYNC_* criteria to + * return. Defaults to SYNC_ALL. + * - ids: (Horde_Imap_Client_Ids) A cached list of UIDs. Unless QRESYNC + * is available on the server, failure to specify this option + * means SYNC_VANISHEDUIDS information cannot be returned. + * + * @return Horde_Imap_Client_Data_Sync A sync object. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_Sync + */ + public function sync($mailbox, $token, array $opts = array()) + { + if (($token = base64_decode($token, true)) === false) { + throw new Horde_Imap_Client_Exception_Sync('Bad token.', Horde_Imap_Client_Exception_Sync::BAD_TOKEN); + } + + $sync = array(); + foreach (explode(',', $token) as $val) { + $sync[substr($val, 0, 1)] = substr($val, 1); + } + + return new Horde_Imap_Client_Data_Sync( + $this, + $mailbox, + $sync, + $this->_syncStatus($mailbox), + (isset($opts['criteria']) ? $opts['criteria'] : Horde_Imap_Client::SYNC_ALL), + (isset($opts['ids']) ? $opts['ids'] : null) + ); + } + + /* Private utility functions. */ + + /** + * Store FETCH data in cache. + * + * @param Horde_Imap_Client_Fetch_Results $data The fetch results. + * + * @throws Horde_Imap_Client_Exception + */ + protected function _updateCache(Horde_Imap_Client_Fetch_Results $data) + { + if (!empty($this->_temp['fetch_nocache']) || + empty($this->_selected) || + !count($data) || + !$this->_initCache(true)) { + return; + } + + $c = $this->getParam('cache'); + if (in_array(strval($this->_selected), $c['fetch_ignore'])) { + $this->_debug->info(sprintf( + 'CACHE: Ignoring FETCH data [%s]', + $this->_selected + )); + return; + } + + /* Optimization: we can directly use getStatus() here since we know + * these values are initialized. */ + $mbox_ob = $this->_mailboxOb(); + $highestmodseq = $mbox_ob->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ); + $uidvalidity = $mbox_ob->getStatus(Horde_Imap_Client::STATUS_UIDVALIDITY); + + $mapping = $modseq = $tocache = array(); + if (count($data)) { + $cf = $this->_cacheFields(); + } + + foreach ($data as $v) { + /* It is possible that we received FETCH information that doesn't + * contain UID data. This is uncacheable so don't process. */ + if (!($uid = $v->getUid())) { + return; + } + + $tmp = array(); + + if ($v->isDowngraded()) { + $tmp[self::CACHE_DOWNGRADED] = true; + } + + foreach ($cf as $key => $val) { + if ($v->exists($key)) { + switch ($key) { + case Horde_Imap_Client::FETCH_ENVELOPE: + $tmp[$val] = $v->getEnvelope(); + break; + + case Horde_Imap_Client::FETCH_FLAGS: + if ($highestmodseq) { + $modseq[$uid] = $v->getModSeq(); + $tmp[$val] = $v->getFlags(); + } + break; + + case Horde_Imap_Client::FETCH_HEADERS: + foreach ($this->_temp['headers_caching'] as $label => $hash) { + if ($hdr = $v->getHeaders($label)) { + $tmp[$val][$hash] = $hdr; + } + } + break; + + case Horde_Imap_Client::FETCH_IMAPDATE: + $tmp[$val] = $v->getImapDate(); + break; + + case Horde_Imap_Client::FETCH_SIZE: + $tmp[$val] = $v->getSize(); + break; + + case Horde_Imap_Client::FETCH_STRUCTURE: + $tmp[$val] = clone $v->getStructure(); + break; + } + } + } + + if (!empty($tmp)) { + $tocache[$uid] = $tmp; + } + + $mapping[$v->getSeq()] = $uid; + } + + if (!empty($mapping)) { + if (!empty($tocache)) { + $this->_cache->set($this->_selected, $tocache, $uidvalidity); + } + + $this->_mailboxOb()->map->update($mapping); + } + + if (!empty($modseq)) { + $this->_updateModSeq(max(array_merge($modseq, array($highestmodseq)))); + $mbox_ob->setStatus(Horde_Imap_Client::STATUS_SYNCFLAGUIDS, array_keys($modseq)); + } + } + + /** + * Moves cache entries from the current mailbox to another mailbox. + * + * @param Horde_Imap_Client_Mailbox $to The destination mailbox. + * @param array $map Mapping of source UIDs (keys) to + * destination UIDs (values). + * @param string $uidvalid UIDVALIDITY of destination + * mailbox. + * + * @throws Horde_Imap_Client_Exception + */ + protected function _moveCache(Horde_Imap_Client_Mailbox $to, $map, + $uidvalid) + { + if (!$this->_initCache()) { + return; + } + + $c = $this->getParam('cache'); + if (in_array(strval($to), $c['fetch_ignore'])) { + $this->_debug->info(sprintf( + 'CACHE: Ignoring moving FETCH data (%s => %s)', + $this->_selected, + $to + )); + return; + } + + $old = $this->_cache->get($this->_selected, array_keys($map), null); + $new = array(); + + foreach ($map as $key => $val) { + if (!empty($old[$key])) { + $new[$val] = $old[$key]; + } + } + + if (!empty($new)) { + $this->_cache->set($to, $new, $uidvalid); + } + } + + /** + * Delete messages in the cache. + * + * @param Horde_Imap_Client_Mailbox $mailbox The mailbox. + * @param Horde_Imap_Client_Ids $ids The list of IDs to delete in + * $mailbox. + * @param array $opts Additional options (not used + * in base class). + * + * @return Horde_Imap_Client_Ids UIDs that were deleted. + * @throws Horde_Imap_Client_Exception + */ + protected function _deleteMsgs(Horde_Imap_Client_Mailbox $mailbox, + Horde_Imap_Client_Ids $ids, + array $opts = array()) + { + if (!$this->_initCache()) { + return $ids; + } + + $mbox_ob = $this->_mailboxOb(); + $ids_ob = $ids->sequence + ? $this->getIdsOb($mbox_ob->map->lookup($ids)) + : $ids; + + $this->_cache->deleteMsgs($mailbox, $ids_ob->ids); + $mbox_ob->setStatus(Horde_Imap_Client::STATUS_SYNCVANISHED, $ids_ob->ids); + $mbox_ob->map->remove($ids); + + return $ids_ob; + } + + /** + * Retrieve data from the search cache. + * + * @param string $type The cache type ('search' or 'thread'). + * @param array $options The options array of the calling function. + * + * @return mixed Returns search cache metadata. If search was retrieved, + * data is in key 'data'. + * Returns null if caching is not available. + */ + protected function _getSearchCache($type, $options) + { + $status = $this->status($this->_selected, Horde_Imap_Client::STATUS_HIGHESTMODSEQ | Horde_Imap_Client::STATUS_UIDVALIDITY); + + /* Search caching requires MODSEQ, which may not be active for a + * mailbox. */ + if (empty($status['highestmodseq'])) { + return null; + } + + ksort($options); + $cache = hash('md5', $type . serialize($options)); + $cacheid = $this->getSyncToken($this->_selected); + $ret = array(); + + $md = $this->_cache->getMetaData( + $this->_selected, + $status['uidvalidity'], + array(self::CACHE_SEARCH, self::CACHE_SEARCHID) + ); + + if (!isset($md[self::CACHE_SEARCHID]) || + ($md[self::CACHE_SEARCHID] != $cacheid)) { + $md[self::CACHE_SEARCH] = array(); + $md[self::CACHE_SEARCHID] = $cacheid; + if ($this->_debug->debug && + !isset($this->_temp['searchcacheexpire'][strval($this->_selected)])) { + $this->_debug->info(sprintf( + 'SEARCH: Expired from cache [%s]', + $this->_selected + )); + $this->_temp['searchcacheexpire'][strval($this->_selected)] = true; + } + } elseif (isset($md[self::CACHE_SEARCH][$cache])) { + $this->_debug->info(sprintf( + 'SEARCH: Retrieved %s from cache (%s [%s])', + $type, + $cache, + $this->_selected + )); + $ret['data'] = $md[self::CACHE_SEARCH][$cache]; + unset($md[self::CACHE_SEARCHID]); + } + + return array_merge($ret, array( + 'id' => $cache, + 'metadata' => $md, + 'type' => $type + )); + } + + /** + * Set data in the search cache. + * + * @param mixed $data The cache data to store. + * @param string $sdata The search data returned from _getSearchCache(). + */ + protected function _setSearchCache($data, $sdata) + { + $sdata['metadata'][self::CACHE_SEARCH][$sdata['id']] = $data; + + $this->_cache->setMetaData($this->_selected, null, $sdata['metadata']); + + if ($this->_debug->debug) { + $this->_debug->info(sprintf( + 'SEARCH: Saved %s to cache (%s [%s])', + $sdata['type'], + $sdata['id'], + $this->_selected + )); + unset($this->_temp['searchcacheexpire'][strval($this->_selected)]); + } + } + + /** + * Updates the cached MODSEQ value. + * + * @param integer $modseq MODSEQ value to store. + * + * @return mixed The MODSEQ of the old value if it was replaced (or false + * if it didn't exist or is the same). + */ + protected function _updateModSeq($modseq) + { + if (!$this->_initCache(true)) { + return false; + } + + $mbox_ob = $this->_mailboxOb(); + $uidvalid = $mbox_ob->getStatus(Horde_Imap_Client::STATUS_UIDVALIDITY); + $md = $this->_cache->getMetaData($this->_selected, $uidvalid, array(self::CACHE_MODSEQ)); + + if (isset($md[self::CACHE_MODSEQ])) { + if ($md[self::CACHE_MODSEQ] < $modseq) { + $set = true; + $sync = $md[self::CACHE_MODSEQ]; + } else { + $set = false; + $sync = 0; + } + $mbox_ob->setStatus(Horde_Imap_Client::STATUS_SYNCMODSEQ, $md[self::CACHE_MODSEQ]); + } else { + $set = true; + $sync = 0; + } + + /* $modseq can be 0 - NOMODSEQ - so don't store in that case. */ + if ($set && $modseq) { + $this->_cache->setMetaData($this->_selected, $uidvalid, array( + self::CACHE_MODSEQ => $modseq + )); + } + + return $sync; + } + + /** + * Synchronizes the current mailbox cache with the server (using CONDSTORE + * or QRESYNC). + */ + protected function _condstoreSync() + { + $mbox_ob = $this->_mailboxOb(); + + /* Check that modseqs are available in mailbox. */ + if (!($highestmodseq = $mbox_ob->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ)) || + !($modseq = $this->_updateModSeq($highestmodseq))) { + $mbox_ob->sync = true; + } + + if ($mbox_ob->sync) { + return; + } + + $uids_ob = $this->getIdsOb($this->_cache->get( + $this->_selected, + array(), + array(), + $mbox_ob->getStatus(Horde_Imap_Client::STATUS_UIDVALIDITY) + )); + + if (!count($uids_ob)) { + $mbox_ob->sync = true; + return; + } + + /* Are we caching flags? */ + if (array_key_exists(Horde_Imap_Client::FETCH_FLAGS, $this->_cacheFields())) { + $fquery = new Horde_Imap_Client_Fetch_Query(); + $fquery->flags(); + + /* Update flags in cache. Cache will be updated in _fetch(). */ + $this->_fetch(new Horde_Imap_Client_Fetch_Results(), array( + array( + '_query' => $fquery, + 'changedsince' => $modseq, + 'ids' => $uids_ob + ) + )); + } + + /* Search for deleted messages, and remove from cache. */ + $vanished = $this->vanished($this->_selected, $modseq, array( + 'ids' => $uids_ob + )); + $disappear = array_diff($uids_ob->ids, $vanished->ids); + if (!empty($disappear)) { + $this->_deleteMsgs($this->_selected, $this->getIdsOb($disappear)); + } + + $mbox_ob->sync = true; + } + + /** + * Provide the list of available caching fields. + * + * @return array The list of available caching fields (fields are in the + * key). + */ + protected function _cacheFields() + { + $c = $this->getParam('cache'); + $out = $c['fields']; + + if (!$this->_capability()->isEnabled('CONDSTORE')) { + unset($out[Horde_Imap_Client::FETCH_FLAGS]); + } + + return $out; + } + + /** + * Return the current mailbox synchronization status. + * + * @param mixed $mailbox A mailbox. Either a Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * + * @return array An array with status data. (This data is not guaranteed + * to have any specific format). + */ + protected function _syncStatus($mailbox) + { + $status = $this->status( + $mailbox, + Horde_Imap_Client::STATUS_HIGHESTMODSEQ | + Horde_Imap_Client::STATUS_MESSAGES | + Horde_Imap_Client::STATUS_UIDNEXT_FORCE | + Horde_Imap_Client::STATUS_UIDVALIDITY + ); + + $fields = array('uidnext', 'uidvalidity'); + if (empty($status['highestmodseq'])) { + $fields[] = 'messages'; + } else { + $fields[] = 'highestmodseq'; + } + + $out = array(); + $sync_map = array_flip(Horde_Imap_Client_Data_Sync::$map); + + foreach ($fields as $val) { + $out[$sync_map[$val]] = $status[$val]; + } + + return array_filter($out); + } + + /** + * Get a message UID by the Message-ID. Returns the last message in a + * mailbox that matches. + * + * @param Horde_Imap_Client_Mailbox $mailbox The mailbox to search + * @param string $msgid Message-ID. + * + * @return string UID (null if not found). + */ + protected function _getUidByMessageId($mailbox, $msgid) + { + if (!$msgid) { + return null; + } + + $query = new Horde_Imap_Client_Search_Query(); + $query->headerText('Message-ID', $msgid); + $res = $this->search($mailbox, $query, array( + 'results' => array(Horde_Imap_Client::SEARCH_RESULTS_MAX) + )); + + return $res['max']; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Alerts.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Alerts.php new file mode 100644 index 00000000..5d820ddb --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Alerts.php @@ -0,0 +1,102 @@ + + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.24.0 + */ +class Horde_Imap_Client_Base_Alerts +implements SplSubject +{ + /** + * Alert data. + * + * @var object + */ + protected $_alert; + + /** + * Observers. + * + * @var array + */ + protected $_observers = array(); + + /** + * Add an alert. + * + * @param string $alert The alert string. + * @param string $type The alert type. + */ + public function add($alert, $type = null) + { + $this->_alert = new stdClass; + $this->_alert->alert = $alert; + if (!is_null($type)) { + $this->_alert->type = $type; + } + + $this->notify(); + } + + /** + * Returns the last alert received. + * + * @return object Alert information. Object with these properties: + *
+     *   - alert: (string) Alert string.
+     *   - type: (string) [OPTIONAL] Alert type.
+     * 
+ */ + public function getLast() + { + return $this->_alert; + } + + /* SplSubject methods. */ + + /** + */ + public function attach(SplObserver $observer) + { + $this->detach($observer); + $this->_observers[] = $observer; + } + + /** + */ + public function detach(SplObserver $observer) + { + if (($key = array_search($observer, $this->_observers, true)) !== false) { + unset($this->_observers[$key]); + } + } + + /** + * Notification is triggered internally whenever the object's internal + * data storage is altered. + */ + public function notify() + { + foreach ($this->_observers as $val) { + $val->update($this); + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Debug.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Debug.php new file mode 100644 index 00000000..13559696 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Debug.php @@ -0,0 +1,152 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @internal + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Base_Debug +{ + /** Time, in seconds, to be labeled a slow command. */ + const SLOW_CMD = 5; + + /** + * Is debugging active? + * + * @var boolean + */ + public $debug = true; + + /** + * The debug stream. + * + * @var resource + */ + protected $_stream; + + /** + * Timestamp of last command. + * + * @var integer + */ + protected $_time = null; + + /** + * Constructor. + * + * @param mixed $debug The debug target. + */ + public function __construct($debug) + { + $this->_stream = is_resource($debug) + ? $debug + : @fopen($debug, 'a'); + register_shutdown_function(array($this, 'shutdown')); + } + + /** + * Shutdown function. + */ + public function shutdown() + { + if (is_resource($this->_stream)) { + fflush($this->_stream); + fclose($this->_stream); + $this->_stream = null; + } + } + + /** + * Write client output to debug log. + * + * @param string $msg Debug message. + */ + public function client($msg) + { + $this->_write($msg . "\n", 'C: '); + } + + /** + * Write informational message to debug log. + * + * @param string $msg Debug message. + */ + public function info($msg) + { + $this->_write($msg . "\n", '>> '); + } + + /** + * Write server output to debug log. + * + * @param string $msg Debug message. + */ + public function raw($msg) + { + $this->_write($msg); + } + + /** + * Write server output to debug log. + * + * @param string $msg Debug message. + */ + public function server($msg) + { + $this->_write($msg . "\n", 'S: '); + } + + /** + * Write debug information to the output stream. + * + * @param string $msg Debug data. + */ + protected function _write($msg, $pre = null) + { + if (!$this->debug || !$this->_stream) { + return; + } + + if (!is_null($pre)) { + $new_time = microtime(true); + + if (is_null($this->_time)) { + fwrite( + $this->_stream, + str_repeat('-', 30) . "\n" . '>> ' . date('r') . "\n" + ); + } elseif (($diff = ($new_time - $this->_time)) > self::SLOW_CMD) { + fwrite( + $this->_stream, + '>> Slow Command: ' . round($diff, 3) . " seconds\n" + ); + } + + $this->_time = $new_time; + } + + fwrite($this->_stream, $pre . $msg); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Deprecated.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Deprecated.php new file mode 100644 index 00000000..288d6f89 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Deprecated.php @@ -0,0 +1,109 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @internal + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Base_Deprecated +{ + /** + * Returns a unique identifier for the current mailbox status. + * + * @param Horde_Imap_Client_Base $base_ob The base driver object. + * @param mixed $mailbox A mailbox. Either a + * Horde_Imap_Client_Mailbox + * object or a string (UTF-8). + * @param boolean $condstore Is CONDSTORE enabled? + * @param array $addl Additional cache info to add to + * the cache ID string. + * + * @return string The cache ID string, which will change when the + * composition of the mailbox changes. The uidvalidity + * will always be the first element, and will be delimited + * by the '|' character. + * + * @throws Horde_Imap_Client_Exception + */ + public static function getCacheId($base_ob, $mailbox, $condstore, + array $addl = array()) + { + $query = Horde_Imap_Client::STATUS_UIDVALIDITY | Horde_Imap_Client::STATUS_MESSAGES | Horde_Imap_Client::STATUS_UIDNEXT; + + /* Use MODSEQ as cache ID if CONDSTORE extension is available. */ + if ($condstore) { + $query |= Horde_Imap_Client::STATUS_HIGHESTMODSEQ; + } else { + $query |= Horde_Imap_Client::STATUS_UIDNEXT_FORCE; + } + + $status = $base_ob->status($mailbox, $query); + + if (empty($status['highestmodseq'])) { + $parts = array( + 'V' . $status['uidvalidity'], + 'U' . $status['uidnext'], + 'M' . $status['messages'] + ); + } else { + $parts = array( + 'V' . $status['uidvalidity'], + 'H' . $status['highestmodseq'] + ); + } + + return implode('|', array_merge($parts, $addl)); + } + + /** + * Parses a cacheID created by getCacheId(). + * + * @param string $id The cache ID. + * + * @return array An array with the following information: + * - highestmodseq: (integer) + * - messages: (integer) + * - uidnext: (integer) + * - uidvalidity: (integer) Always present + */ + public static function parseCacheId($id) + { + $data = array( + 'H' => 'highestmodseq', + 'M' => 'messages', + 'U' => 'uidnext', + 'V' => 'uidvalidity' + ); + $info = array(); + + foreach (explode('|', $id) as $part) { + if (isset($data[$part[0]])) { + $info[$data[$part[0]]] = intval(substr($part, 1)); + } + } + + return $info; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Mailbox.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Mailbox.php new file mode 100644 index 00000000..0125a22f --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Mailbox.php @@ -0,0 +1,187 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @internal + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Base_Mailbox +{ + /** + * Mapping object. + * + * @var Horde_Imap_Client_Ids_Map + */ + public $map; + + /** + * Is mailbox opened? + * + * @var boolean + */ + public $open; + + /** + * Is mailbox sync'd with remote server (via CONDSTORE/QRESYNC)? + * + * @var boolean + */ + public $sync; + + /** + * Status information. + * + * @var array + */ + protected $_status = array(); + + /** + * Constructor. + */ + public function __construct() + { + $this->reset(); + } + + /** + * Get status information for the mailbox. + * + * @param integer $entry STATUS_* constant. + * + * @return mixed Status information. + */ + public function getStatus($entry) + { + if (isset($this->_status[$entry])) { + return $this->_status[$entry]; + } + + switch ($entry) { + case Horde_Imap_Client::STATUS_FLAGS: + case Horde_Imap_Client::STATUS_SYNCFLAGUIDS: + case Horde_Imap_Client::STATUS_SYNCVANISHED: + return array(); + + case Horde_Imap_Client::STATUS_FIRSTUNSEEN: + /* If we know there are no messages in the current mailbox, we + * know there are no unseen messages. */ + return empty($this->_status[Horde_Imap_Client::STATUS_MESSAGES]) + ? false + : null; + + case Horde_Imap_Client::STATUS_RECENT_TOTAL: + case Horde_Imap_Client::STATUS_SYNCMODSEQ: + return 0; + + case Horde_Imap_Client::STATUS_PERMFLAGS: + /* If PERMFLAGS is not returned by server, must assume that all + * flags can be changed permanently (RFC 3501 [6.3.1]). */ + $flags = isset($this->_status[Horde_Imap_Client::STATUS_FLAGS]) + ? $this->_status[Horde_Imap_Client::STATUS_FLAGS] + : array(); + $flags[] = "\\*"; + return $flags; + + case Horde_Imap_Client::STATUS_UIDNOTSTICKY: + /* In the absence of explicit uidnotsticky identification, assume + * that UIDs are sticky. */ + return false; + + case Horde_Imap_Client::STATUS_UNSEEN: + /* If we know there are no messages in the current mailbox, we + * know there are no unseen messages . */ + return empty($this->_status[Horde_Imap_Client::STATUS_MESSAGES]) + ? 0 + : null; + + default: + return null; + } + } + + /** + * Set status information for the mailbox. + * + * @param integer $entry STATUS_* constant. + * @param mixed $value Status information. + */ + public function setStatus($entry, $value) + { + switch ($entry) { + case Horde_Imap_Client::STATUS_FIRSTUNSEEN: + case Horde_Imap_Client::STATUS_HIGHESTMODSEQ: + case Horde_Imap_Client::STATUS_MESSAGES: + case Horde_Imap_Client::STATUS_UNSEEN: + case Horde_Imap_Client::STATUS_UIDNEXT: + case Horde_Imap_Client::STATUS_UIDVALIDITY: + $value = intval($value); + break; + + case Horde_Imap_Client::STATUS_RECENT: + /* Keep track of RECENT_TOTAL information. */ + $this->_status[Horde_Imap_Client::STATUS_RECENT_TOTAL] = isset($this->_status[Horde_Imap_Client::STATUS_RECENT_TOTAL]) + ? ($this->_status[Horde_Imap_Client::STATUS_RECENT_TOTAL] + $value) + : intval($value); + break; + + case Horde_Imap_Client::STATUS_SYNCMODSEQ: + /* This is only set once per access. */ + if (isset($this->_status[$entry])) { + return; + } + $value = intval($value); + break; + + case Horde_Imap_Client::STATUS_SYNCFLAGUIDS: + case Horde_Imap_Client::STATUS_SYNCVANISHED: + if (!isset($this->_status[$entry])) { + $this->_status[$entry] = array(); + } + $this->_status[$entry] = array_merge($this->_status[$entry], $value); + return; + } + + $this->_status[$entry] = $value; + } + + /** + * Reset the mailbox information. + */ + public function reset() + { + $keep = array( + Horde_Imap_Client::STATUS_SYNCFLAGUIDS, + Horde_Imap_Client::STATUS_SYNCMODSEQ, + Horde_Imap_Client::STATUS_SYNCVANISHED + ); + + foreach (array_diff(array_keys($this->_status), $keep) as $val) { + unset($this->_status[$val]); + } + + $this->map = new Horde_Imap_Client_Ids_Map(); + $this->open = $this->sync = false; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Password.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Password.php new file mode 100644 index 00000000..2895618d --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Base/Password.php @@ -0,0 +1,33 @@ + + * @category Horde + * @copyright 2013-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.14.0 + */ +interface Horde_Imap_Client_Base_Password +{ + /** + * Return the password to use for the server connection. + * + * @return string The password. + */ + public function getPassword(); + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache.php new file mode 100644 index 00000000..d858fe4f --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache.php @@ -0,0 +1,263 @@ + + * @category Horde + * @copyright 2005-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Cache +{ + /** + * Base client object. + * + * @var Horde_Imap_Client_Base + */ + protected $_baseob; + + /** + * Storage backend. + * + * @var Horde_Imap_Client_Cache_Backend + */ + protected $_backend; + + /** + * Debug output. + * + * @var Horde_Imap_Client_Base_Debug + */ + protected $_debug = false; + + /** + * The configuration params. + * + * @var array + */ + protected $_params = array(); + + /** + * Constructor. + * + * @param array $params Configuration parameters: + *
+     *   - REQUIRED Parameters:
+     *     - backend: (Horde_Imap_Client_Cache_Backend) The cache backend.
+     *     - baseob: (Horde_Imap_Client_Base) The base client object.
+     *
+     *   - Optional Parameters:
+     *     - debug: (Horde_Imap_Client_Base_Debug) Debug object.
+     *              DEFAULT: No debug output
+     * 
+ */ + public function __construct(array $params = array()) + { + $this->_backend = $params['backend']; + $this->_baseob = $params['baseob']; + + $this->_backend->setParams(array( + 'hostspec' => $this->_baseob->getParam('hostspec'), + 'port' => $this->_baseob->getParam('port'), + 'username' => $this->_baseob->getParam('username') + )); + + if (isset($params['debug']) && + ($params['debug'] instanceof Horde_Imap_Client_Base_Debug)) { + $this->_debug = $params['debug']; + $this->_debug->info(sprintf( + 'CACHE: Using the %s storage driver.', + get_class($this->_backend) + )); + } + } + + /** + * Get information from the cache. + * + * @param string $mailbox An IMAP mailbox string. + * @param array $uids The list of message UIDs to retrieve + * information for. If empty, returns the list + * of cached UIDs. + * @param array $fields An array of fields to retrieve. If empty, + * returns all cached fields. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + * + * @return array An array of arrays with the UID of the message as the + * key (if found) and the fields as values (will be + * undefined if not found). If $uids is empty, returns the + * full (unsorted) list of cached UIDs. + */ + public function get($mailbox, array $uids = array(), $fields = array(), + $uidvalid = null) + { + $mailbox = strval($mailbox); + + if (empty($uids)) { + $ret = $this->_backend->getCachedUids($mailbox, $uidvalid); + } else { + $ret = $this->_backend->get($mailbox, $uids, $fields, $uidvalid); + + if ($this->_debug && !empty($ret)) { + $this->_debug->info(sprintf( + 'CACHE: Retrieved messages (%s [%s; %s])', + empty($fields) ? 'ALL' : implode(',', $fields), + $mailbox, + $this->_baseob->getIdsOb(array_keys($ret))->tostring_sort + )); + } + } + + return $ret; + } + + /** + * Store information in cache. + * + * @param string $mailbox An IMAP mailbox string. + * @param array $data The list of data to save. The keys are the + * UIDs, the values are an array of information + * to save. If empty, do a check to make sure + * the uidvalidity is still valid. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + */ + public function set($mailbox, $data, $uidvalid) + { + $mailbox = strval($mailbox); + + if (empty($data)) { + $this->_backend->getMetaData($mailbox, $uidvalid, array('uidvalid')); + } else { + $this->_backend->set($mailbox, $data, $uidvalid); + + if ($this->_debug) { + $this->_debug->info(sprintf( + 'CACHE: Stored messages [%s; %s]', + $mailbox, + $this->_baseob->getIdsOb(array_keys($data))->tostring_sort + )); + } + } + } + + /** + * Get metadata information for a mailbox. + * + * @param string $mailbox An IMAP mailbox string. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + * @param array $entries An array of entries to return. If empty, + * returns all metadata. + * + * @return array The requested metadata. Requested entries that do not + * exist will be undefined. The following entries are + * defaults and always present: + * - uidvalid: (integer) The UIDVALIDITY of the mailbox. + */ + public function getMetaData($mailbox, $uidvalid = null, + array $entries = array()) + { + return $this->_backend->getMetaData(strval($mailbox), $uidvalid, $entries); + } + + /** + * Set metadata information for a mailbox. + * + * @param string $mailbox An IMAP mailbox string. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + * @param array $data The list of data to save. The keys are the + * metadata IDs, the values are the associated + * data. The following labels are reserved: + * 'uidvalid'. + */ + public function setMetaData($mailbox, $uidvalid, array $data = array()) + { + unset($data['uidvalid']); + + if (!empty($data)) { + if (!empty($uidvalid)) { + $data['uidvalid'] = $uidvalid; + } + $mailbox = strval($mailbox); + + $this->_backend->setMetaData($mailbox, $data); + + if ($this->_debug) { + $this->_debug->info(sprintf( + 'CACHE: Stored metadata (%s [%s])', + implode(',', array_keys($data)), + $mailbox + )); + } + } + } + + /** + * Delete messages in the cache. + * + * @param string $mailbox An IMAP mailbox string. + * @param array $uids The list of message UIDs to delete. + */ + public function deleteMsgs($mailbox, $uids) + { + if (empty($uids)) { + return; + } + + $mailbox = strval($mailbox); + + $this->_backend->deleteMsgs($mailbox, $uids); + + if ($this->_debug) { + $this->_debug->info(sprintf( + 'CACHE: Deleted messages [%s; %s]', + $mailbox, + $this->_baseob->getIdsOb($uids)->tostring_sort + )); + } + } + + /** + * Delete a mailbox from the cache. + * + * @param string $mbox The mailbox to delete. + */ + public function deleteMailbox($mbox) + { + $mbox = strval($mbox); + $this->_backend->deleteMailbox($mbox); + + if ($this->_debug) { + $this->_debug->info(sprintf( + 'CACHE: Deleted mailbox [%s]', + $mbox + )); + } + } + + /** + * Clear the cache. + * + * @since 2.9.0 + * + * @param integer $lifetime Only delete entries older than this (in + * seconds). If null, deletes all entries. + */ + public function clear($lifetime = null) + { + $this->_backend->clear($lifetime); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend.php new file mode 100644 index 00000000..75ed98c7 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend.php @@ -0,0 +1,165 @@ + + * @category Horde + * @copyright 2013-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +abstract class Horde_Imap_Client_Cache_Backend implements Serializable +{ + /** + * Configuration paramters. + * Values set by the base Cache object: hostspec, port, username + * + * @var array + */ + protected $_params = array(); + + /** + * Constructor. + * + * @param array $params Configuration parameters. + */ + public function __construct(array $params = array()) + { + $this->setParams($params); + $this->_initOb(); + } + + /** + * Initialization tasks. + */ + protected function _initOb() + { + } + + /** + * Add configuration parameters. + * + * @param array $params Configuration parameters. + */ + public function setParams(array $params = array()) + { + $this->_params = array_merge($this->_params, $params); + } + + /** + * Get information from the cache for a set of UIDs. + * + * @param string $mailbox An IMAP mailbox string. + * @param array $uids The list of message UIDs to retrieve + * information for. + * @param array $fields An array of fields to retrieve. If empty, + * returns all cached fields. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + * + * @return array An array of arrays with the UID of the message as the + * key (if found) and the fields as values (will be + * undefined if not found). + */ + abstract public function get($mailbox, $uids, $fields, $uidvalid); + + /** + * Get the list of cached UIDs. + * + * @param string $mailbox An IMAP mailbox string. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + * + * @return array The (unsorted) list of cached UIDs. + */ + abstract public function getCachedUids($mailbox, $uidvalid); + + /** + * Store data in cache. + * + * @param string $mailbox An IMAP mailbox string. + * @param array $data The list of data to save. The keys are the + * UIDs, the values are an array of information + * to save. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + */ + abstract public function set($mailbox, $data, $uidvalid); + + /** + * Get metadata information for a mailbox. + * + * @param string $mailbox An IMAP mailbox string. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + * @param array $entries An array of entries to return. If empty, + * returns all metadata. + * + * @return array The requested metadata. Requested entries that do not + * exist will be undefined. The following entries are + * defaults and always present: + * - uidvalid: (integer) The UIDVALIDITY of the mailbox. + */ + abstract public function getMetaData($mailbox, $uidvalid, $entries); + + /** + * Set metadata information for a mailbox. + * + * @param string $mailbox An IMAP mailbox string. + * @param array $data The list of data to save. The keys are the + * metadata IDs, the values are the associated + * data. (If present, uidvalidity appears as + * the 'uidvalid' key in $data.) + */ + abstract public function setMetaData($mailbox, $data); + + /** + * Delete messages in the cache. + * + * @param string $mailbox An IMAP mailbox string. + * @param array $uids The list of message UIDs to delete. + */ + abstract public function deleteMsgs($mailbox, $uids); + + /** + * Delete a mailbox from the cache. + * + * @param string $mailbox The mailbox to delete. + */ + abstract public function deleteMailbox($mailbox); + + /** + * Clear the cache. + * + * @param integer $lifetime Only delete entries older than this (in + * seconds). If null, deletes all entries. + */ + abstract public function clear($lifetime); + + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + return serialize($this->_params); + } + + /** + */ + public function unserialize($data) + { + $this->_params = unserialize($data); + $this->_initOb(); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Cache.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Cache.php new file mode 100644 index 00000000..cea22c5f --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Cache.php @@ -0,0 +1,506 @@ + + * @category Horde + * @copyright 2005-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Cache_Backend_Cache +extends Horde_Imap_Client_Cache_Backend +{ + /** Cache structure version. */ + const VERSION = 3; + + /** + * The cache object. + * + * @var Horde_Cache + */ + protected $_cache; + + /** + * The working data for the current pageload. All changes take place to + * this data. + * + * @var array + */ + protected $_data = array(); + + /** + * The list of cache slices loaded. + * + * @var array + */ + protected $_loaded = array(); + + /** + * The mapping of UIDs to slices. + * + * @var array + */ + protected $_slicemap = array(); + + /** + * The list of items to update: + * - add: (array) List of IDs that were added. + * - slice: (array) List of slices that were modified. + * - slicemap: (boolean) Was slicemap info changed? + * + * @var array + */ + protected $_update = array(); + + /** + * Constructor. + * + * @param array $params Configuration parameters: + *
+     *   - REQUIRED Parameters:
+     *     - cacheob: (Horde_Cache) The cache object to use.
+     *
+     *   - Optional Parameters:
+     *     - lifetime: (integer) The lifetime of the cache data (in seconds).
+     *                 DEFAULT: 1 week (604800 seconds)
+     *     - slicesize: (integer) The slicesize to use.
+     *                  DEFAULT: 50
+     * 
+ */ + public function __construct(array $params = array()) + { + // Default parameters. + $params = array_merge(array( + 'lifetime' => 604800, + 'slicesize' => 50 + ), array_filter($params)); + + if (!isset($params['cacheob'])) { + throw new InvalidArgumentException('Missing cacheob parameter.'); + } + + foreach (array('lifetime', 'slicesize') as $val) { + $params[$val] = intval($params[$val]); + } + + parent::__construct($params); + } + + /** + * Initialization tasks. + */ + protected function _initOb() + { + $this->_cache = $this->_params['cacheob']; + register_shutdown_function(array($this, 'save')); + } + + /** + * Updates the cache. + */ + public function save() + { + $lifetime = $this->_params['lifetime']; + + foreach ($this->_update as $mbox => $val) { + $s = &$this->_slicemap[$mbox]; + + try { + if (!empty($val['add'])) { + if ($s['c'] <= $this->_params['slicesize']) { + $val['slice'][] = $s['i']; + $this->_loadSlice($mbox, $s['i']); + } + $val['slicemap'] = true; + + foreach (array_keys(array_flip($val['add'])) as $uid) { + if ($s['c']++ > $this->_params['slicesize']) { + $s['c'] = 0; + $val['slice'][] = ++$s['i']; + $this->_loadSlice($mbox, $s['i']); + } + $s['s'][$uid] = $s['i']; + } + } + + if (!empty($val['slice'])) { + $d = &$this->_data[$mbox]; + $val['slicemap'] = true; + + foreach (array_keys(array_flip($val['slice'])) as $slice) { + $data = array(); + foreach (array_keys($s['s'], $slice) as $uid) { + $data[$uid] = is_array($d[$uid]) + ? serialize($d[$uid]) + : $d[$uid]; + } + $this->_cache->set($this->_getCid($mbox, $slice), serialize($data), $lifetime); + } + } + + if (!empty($val['slicemap'])) { + $this->_cache->set($this->_getCid($mbox, 'slicemap'), serialize($s), $lifetime); + } + } catch (Horde_Exception $e) { + } + } + + $this->_update = array(); + } + + /** + */ + public function get($mailbox, $uids, $fields, $uidvalid) + { + $ret = array(); + $this->_loadUids($mailbox, $uids, $uidvalid); + + if (empty($this->_data[$mailbox])) { + return $ret; + } + + if (!empty($fields)) { + $fields = array_flip($fields); + } + $ptr = &$this->_data[$mailbox]; + + foreach (array_intersect($uids, array_keys($ptr)) as $val) { + if (is_string($ptr[$val])) { + try { + $ptr[$val] = @unserialize($ptr[$val]); + } catch (Exception $e) {} + } + + $ret[$val] = (empty($fields) || empty($ptr[$val])) + ? $ptr[$val] + : array_intersect_key($ptr[$val], $fields); + } + + return $ret; + } + + /** + */ + public function getCachedUids($mailbox, $uidvalid) + { + $this->_loadSliceMap($mailbox, $uidvalid); + return array_unique(array_merge( + array_keys($this->_slicemap[$mailbox]['s']), + (isset($this->_update[$mailbox]) ? $this->_update[$mailbox]['add'] : array()) + )); + } + + /** + */ + public function set($mailbox, $data, $uidvalid) + { + $update = array_keys($data); + + try { + $this->_loadUids($mailbox, $update, $uidvalid); + } catch (Horde_Imap_Client_Exception $e) { + // Ignore invalidity - just start building the new cache + } + + $d = &$this->_data[$mailbox]; + $s = &$this->_slicemap[$mailbox]['s']; + $add = $updated = array(); + + foreach ($data as $k => $v) { + if (isset($d[$k])) { + if (is_string($d[$k])) { + try { + $d[$k] = @unserialize($d[$k]); + } catch (Exception $e) {} + } + $d[$k] = is_array($d[$k]) + ? array_merge($d[$k], $v) + : $v; + if (isset($s[$k])) { + $updated[$s[$k]] = true; + } + } else { + $d[$k] = $v; + $add[] = $k; + } + } + + $this->_toUpdate($mailbox, 'add', $add); + $this->_toUpdate($mailbox, 'slice', array_keys($updated)); + } + + /** + */ + public function getMetaData($mailbox, $uidvalid, $entries) + { + $this->_loadSliceMap($mailbox, $uidvalid); + + return empty($entries) + ? $this->_slicemap[$mailbox]['d'] + : array_intersect_key($this->_slicemap[$mailbox]['d'], array_flip($entries)); + } + + /** + */ + public function setMetaData($mailbox, $data) + { + $this->_loadSliceMap($mailbox, isset($data['uidvalid']) ? $data['uidvalid'] : null); + $this->_slicemap[$mailbox]['d'] = array_merge($this->_slicemap[$mailbox]['d'], $data); + $this->_toUpdate($mailbox, 'slicemap', true); + } + + /** + */ + public function deleteMsgs($mailbox, $uids) + { + if (empty($uids)) { + return; + } + + $this->_loadSliceMap($mailbox); + + $slicemap = &$this->_slicemap[$mailbox]; + $deleted = array_intersect_key($slicemap['s'], array_flip($uids)); + + if (isset($this->_update[$mailbox])) { + $this->_update[$mailbox]['add'] = array_diff( + $this->_update[$mailbox]['add'], + $uids + ); + } + + if (empty($deleted)) { + return; + } + + $this->_loadUids($mailbox, array_keys($deleted)); + $d = &$this->_data[$mailbox]; + + foreach (array_keys($deleted) as $id) { + unset($d[$id], $slicemap['s'][$id]); + } + + foreach (array_unique($deleted) as $slice) { + /* Get rid of slice if less than 10% of capacity. */ + if (($slice != $slicemap['i']) && + ($slice_uids = array_keys($slicemap['s'], $slice)) && + ($this->_params['slicesize'] * 0.1) > count($slice_uids)) { + $this->_toUpdate($mailbox, 'add', $slice_uids); + $this->_cache->expire($this->_getCid($mailbox, $slice)); + foreach ($slice_uids as $val) { + unset($slicemap['s'][$val]); + } + } else { + $this->_toUpdate($mailbox, 'slice', array($slice)); + } + } + } + + /** + */ + public function deleteMailbox($mailbox) + { + $this->_loadSliceMap($mailbox); + $this->_deleteMailbox($mailbox); + } + + /** + */ + public function clear($lifetime) + { + $this->_cache->clear(); + $this->_data = $this->_loaded = $this->_slicemap = $this->_update = array(); + } + + /** + * Create the unique ID used to store the data in the cache. + * + * @param string $mailbox The mailbox to cache. + * @param string $slice The cache slice. + * + * @return string The cache ID. + */ + protected function _getCid($mailbox, $slice) + { + return implode('|', array( + 'horde_imap_client', + $this->_params['username'], + $mailbox, + $this->_params['hostspec'], + $this->_params['port'], + $slice, + self::VERSION + )); + } + + /** + * Delete a mailbox from the cache. + * + * @param string $mbox The mailbox to delete. + */ + protected function _deleteMailbox($mbox) + { + foreach (array_merge(array_keys(array_flip($this->_slicemap[$mbox]['s'])), array('slicemap')) as $slice) { + $cid = $this->_getCid($mbox, $slice); + $this->_cache->expire($cid); + unset($this->_loaded[$cid]); + } + + unset( + $this->_data[$mbox], + $this->_slicemap[$mbox], + $this->_update[$mbox] + ); + } + + /** + * Load UIDs by regenerating from the cache. + * + * @param string $mailbox The mailbox to load. + * @param array $uids The UIDs to load. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + */ + protected function _loadUids($mailbox, $uids, $uidvalid = null) + { + if (!isset($this->_data[$mailbox])) { + $this->_data[$mailbox] = array(); + } + + $this->_loadSliceMap($mailbox, $uidvalid); + + if (!empty($uids)) { + foreach (array_unique(array_intersect_key($this->_slicemap[$mailbox]['s'], array_flip($uids))) as $slice) { + $this->_loadSlice($mailbox, $slice); + } + } + } + + /** + * Load UIDs from a cache slice. + * + * @param string $mailbox The mailbox to load. + * @param integer $slice The slice to load. + */ + protected function _loadSlice($mailbox, $slice) + { + $cache_id = $this->_getCid($mailbox, $slice); + + if (!empty($this->_loaded[$cache_id])) { + return; + } + + if (($data = $this->_cache->get($cache_id, 0)) !== false) { + try { + $data = @unserialize($data); + } catch (Exception $e) {} + } + + if (($data !== false) && is_array($data)) { + $this->_data[$mailbox] += $data; + $this->_loaded[$cache_id] = true; + } else { + $ptr = &$this->_slicemap[$mailbox]; + + // Slice data is corrupt; remove from slicemap. + foreach (array_keys($ptr['s'], $slice) as $val) { + unset($ptr['s'][$val]); + } + + if ($slice == $ptr['i']) { + $ptr['c'] = 0; + } + } + } + + /** + * Load the slicemap for a given mailbox. The slicemap contains + * the uidvalidity information, the UIDs->slice lookup table, and any + * metadata that needs to be saved for the mailbox. + * + * @param string $mailbox The mailbox. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + */ + protected function _loadSliceMap($mailbox, $uidvalid = null) + { + if (!isset($this->_slicemap[$mailbox]) && + (($data = $this->_cache->get($this->_getCid($mailbox, 'slicemap'), 0)) !== false)) { + try { + if (($slice = @unserialize($data)) && + is_array($slice)) { + $this->_slicemap[$mailbox] = $slice; + } + } catch (Exception $e) {} + } + + if (isset($this->_slicemap[$mailbox])) { + $ptr = &$this->_slicemap[$mailbox]; + if (is_null($ptr['d']['uidvalid'])) { + $ptr['d']['uidvalid'] = $uidvalid; + return; + } elseif (!is_null($uidvalid) && + ($ptr['d']['uidvalid'] != $uidvalid)) { + $this->_deleteMailbox($mailbox); + } else { + return; + } + } + + $this->_slicemap[$mailbox] = array( + // Tracking count for purposes of determining slices + 'c' => 0, + // Metadata storage + // By default includes UIDVALIDITY of mailbox. + 'd' => array('uidvalid' => $uidvalid), + // The ID of the last slice. + 'i' => 0, + // The slice list. + 's' => array() + ); + } + + /** + * Add update entry for a mailbox. + * + * @param string $mailbox The mailbox. + * @param string $type 'add', 'slice', or 'slicemap'. + * @param mixed $data The data to update. + */ + protected function _toUpdate($mailbox, $type, $data) + { + if (!isset($this->_update[$mailbox])) { + $this->_update[$mailbox] = array( + 'add' => array(), + 'slice' => array() + ); + } + + $this->_update[$mailbox][$type] = ($type == 'slicemap') + ? $data + : array_merge($this->_update[$mailbox][$type], $data); + } + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + $this->save(); + return parent::serialize(); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Db.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Db.php new file mode 100644 index 00000000..98d8a0d7 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Db.php @@ -0,0 +1,407 @@ + + * @category Horde + * @copyright 2013-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Cache_Backend_Db +extends Horde_Imap_Client_Cache_Backend +{ + /** SQL table names. */ + const BASE_TABLE = 'horde_imap_client_data'; + const MD_TABLE = 'horde_imap_client_metadata'; + const MSG_TABLE = 'horde_imap_client_message'; + + /** + * Handle for the database connection. + * + * @var Horde_Db_Adapter + */ + protected $_db; + + /** + * Constructor. + * + * @param array $params Configuration parameters: + *
+     *   - REQUIRED Parameters:
+     *     - db: (Horde_Db_Adapter) DB object.
+     * 
+ */ + public function __construct(array $params = array()) + { + if (!isset($params['db'])) { + throw new InvalidArgumentException('Missing db parameter.'); + } + + parent::__construct($params); + } + + /** + */ + protected function _initOb() + { + $this->_db = $this->_params['db']; + } + + /** + */ + public function get($mailbox, $uids, $fields, $uidvalid) + { + $this->getMetaData($mailbox, $uidvalid, array('uidvalid')); + + $query = $this->_baseSql($mailbox, self::MSG_TABLE); + $query[0] = 'SELECT t.data, t.msguid ' . $query[0]; + + $uid_query = array(); + foreach ($uids as $val) { + $uid_query[] = 't.msguid = ?'; + $query[1][] = strval($val); + } + $query[0] .= ' AND (' . implode(' OR ', $uid_query) . ')'; + + $compress = new Horde_Compress_Fast(); + $out = array(); + + try { + $columns = $this->_db->columns(self::MSG_TABLE); + $res = $this->_db->select($query[0], $query[1]); + + foreach ($res as $row) { + try { + $out[$row['msguid']] = @unserialize($compress->decompress( + $columns['data']->binaryToString($row['data']) + )); + } catch (Exception $e) {} + } + } catch (Horde_Db_Exception $e) {} + + return $out; + } + + /** + */ + public function getCachedUids($mailbox, $uidvalid) + { + $this->getMetaData($mailbox, $uidvalid, array('uidvalid')); + + $query = $this->_baseSql($mailbox, self::MSG_TABLE); + $query[0] = 'SELECT DISTINCT t.msguid ' . $query[0]; + + try { + return $this->_db->selectValues($query[0], $query[1]); + } catch (Horde_Db_Exception $e) { + return array(); + } + } + + /** + */ + public function set($mailbox, $data, $uidvalid) + { + if ($uid = $this->_getUid($mailbox)) { + $res = $this->get($mailbox, array_keys($data), array(), $uidvalid); + } else { + $res = array(); + $uid = $this->_createUid($mailbox); + } + + $compress = new Horde_Compress_Fast(); + + foreach ($data as $key => $val) { + if (isset($res[$key])) { + try { + /* Update */ + $this->_db->updateBlob( + self::MSG_TABLE, + array('data' => new Horde_Db_Value_Binary($compress->compress(serialize(array_merge($res[$key], $val))))), + array( + 'messageid = ? AND msguid = ?', + array($uid, strval($key)) + ) + ); + } catch (Horde_Db_Exception $e) {} + } else { + /* Insert */ + try { + $this->_db->insertBlob( + self::MSG_TABLE, + array( + 'data' => new Horde_Db_Value_Binary($compress->compress(serialize($val))), + 'msguid' => strval($key), + 'messageid' => $uid + ) + ); + } catch (Horde_Db_Exception $e) {} + } + } + + /* Update modified time. */ + try { + $this->_db->update( + sprintf( + 'UPDATE %s SET modified = ? WHERE messageid = ?', + self::BASE_TABLE + ), + array(time(), $uid) + ); + } catch (Horde_Db_Exception $e) {} + + /* Update uidvalidity. */ + $this->setMetaData($mailbox, array('uidvalid' => $uidvalid)); + } + + /** + */ + public function getMetaData($mailbox, $uidvalid, $entries) + { + $query = $this->_baseSql($mailbox, self::MD_TABLE); + $query[0] = 'SELECT t.field, t.data ' . $query[0]; + + if (!empty($entries)) { + $entries[] = 'uidvalid'; + $entry_query = array(); + + foreach (array_unique($entries) as $val) { + $entry_query[] = 't.field = ?'; + $query[1][] = $val; + } + $query[0] .= ' AND (' . implode(' OR ', $entry_query) . ')'; + } + + try { + if ($res = $this->_db->selectAssoc($query[0], $query[1])) { + $columns = $this->_db->columns(self::MD_TABLE); + foreach ($res as $key => $val) { + switch ($key) { + case 'uidvalid': + $res[$key] = $columns['data']->binaryToString($val); + break; + + default: + try { + $res[$key] = @unserialize( + $columns['data']->binaryToString($val) + ); + } catch (Exception $e) {} + break; + } + } + + if (is_null($uidvalid) || + !isset($res['uidvalid']) || + ($res['uidvalid'] == $uidvalid)) { + return $res; + } + + $this->deleteMailbox($mailbox); + } + } catch (Horde_Db_Exception $e) {} + + return array(); + } + + /** + */ + public function setMetaData($mailbox, $data) + { + if (!($uid = $this->_getUid($mailbox))) { + $uid = $this->_createUid($mailbox); + } + + $query = sprintf('SELECT field FROM %s where messageid = ?', self::MD_TABLE); + $values = array($uid); + + try { + $fields = $this->_db->selectValues($query, $values); + } catch (Horde_Db_Exception $e) { + return; + } + + foreach ($data as $key => $val) { + $val = new Horde_Db_Value_Binary(($key == 'uidvalid') ? $val : serialize($val)); + + if (in_array($key, $fields)) { + /* Update */ + try { + $this->_db->updateBlob( + self::MD_TABLE, + array('data' => $val), + array('field = ? AND messageid = ?', array($key, $uid)) + ); + } catch (Horde_Db_Exception $e) {} + } else { + /* Insert */ + try { + $this->_db->insertBlob( + self::MD_TABLE, + array('data' => $val, 'field' => $key, 'messageid' => $uid) + ); + } catch (Horde_Db_Exception $e) {} + } + } + } + + /** + */ + public function deleteMsgs($mailbox, $uids) + { + if (empty($uids)) { + return; + } + + $query = $this->_baseSql($mailbox); + $query[0] = sprintf( + 'DELETE FROM %s WHERE messageid IN (SELECT messageid ' . $query[0] . ')', + self::MSG_TABLE + ); + + $uid_query = array(); + foreach ($uids as $val) { + $uid_query[] = 'msguid = ?'; + $query[1][] = strval($val); + } + $query[0] .= ' AND (' . implode(' OR ', $uid_query) . ')'; + + try { + $this->_db->delete($query[0], $query[1]); + } catch (Horde_Db_Exception $e) {} + } + + /** + */ + public function deleteMailbox($mailbox) + { + if (is_null($uid = $this->_getUid($mailbox))) { + return; + } + + foreach (array(self::BASE_TABLE, self::MD_TABLE, self::MSG_TABLE) as $val) { + try { + $this->_db->delete( + sprintf('DELETE FROM %s WHERE messageid = ?', $val), + array($uid) + ); + } catch (Horde_Db_Exception $e) {} + } + } + + /** + */ + public function clear($lifetime) + { + if (is_null($lifetime)) { + try { + $this->_db->delete(sprintf('DELETE FROM %s', self::BASE_TABLE)); + $this->_db->delete(sprintf('DELETE FROM %s', self::MD_TABLE)); + $this->_db->delete(sprintf('DELETE FROM %s', self::MSG_TABLE)); + } catch (Horde_Db_Exception $e) {} + return; + } + + $purge = time() - $lifetime; + $sql = 'DELETE FROM %s WHERE messageid IN (SELECT messageid FROM %s WHERE modified < ?)'; + + foreach (array(self::MD_TABLE, self::MSG_TABLE) as $val) { + try { + $this->_db->delete( + sprintf($sql, $val, self::BASE_TABLE), + array($purge) + ); + } catch (Horde_Db_Exception $e) { + } + } + + try { + $this->_db->delete( + sprintf('DELETE FROM %s WHERE modified < ?', self::BASE_TABLE), + array($purge) + ); + } catch (Horde_Db_Exception $e) { + } + } + + /** + * Prepare the base SQL query. + * + * @param string $mailbox The mailbox. + * @param string $join The table to join with the base table. + * + * @return array SQL query and bound parameters. + */ + protected function _baseSql($mailbox, $join = null) + { + $sql = sprintf('FROM %s d', self::BASE_TABLE); + + if (!is_null($join)) { + $sql .= sprintf(' INNER JOIN %s t ON d.messageid = t.messageid', $join); + } + + return array( + $sql . ' WHERE d.hostspec = ? AND d.port = ? AND d.username = ? AND d.mailbox = ?', + array( + $this->_params['hostspec'], + $this->_params['port'], + $this->_params['username'], + $mailbox + ) + ); + } + + /** + * @param string $mailbox + * + * @return string UID from base table. + */ + protected function _getUid($mailbox) + { + $query = $this->_baseSql($mailbox); + $query[0] = 'SELECT d.messageid ' . $query[0]; + + try { + return $this->_db->selectValue($query[0], $query[1]); + } catch (Horde_Db_Exception $e) { + return null; + } + } + + /** + * @param string $mailbox + * + * @return string UID from base table. + */ + protected function _createUid($mailbox) + { + return $this->_db->insert( + sprintf( + 'INSERT INTO %s (hostspec, mailbox, port, username) ' . + 'VALUES (?, ?, ?, ?)', + self::BASE_TABLE + ), + array( + $this->_params['hostspec'], + $mailbox, + $this->_params['port'], + $this->_params['username'] + ) + ); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Hashtable.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Hashtable.php new file mode 100644 index 00000000..d4fa67d3 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Hashtable.php @@ -0,0 +1,421 @@ + + * @category Horde + * @copyright 2013-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.17.0 + */ +class Horde_Imap_Client_Cache_Backend_Hashtable +extends Horde_Imap_Client_Cache_Backend +{ + /** Separator for CID between mailbox and UID. */ + const CID_SEPARATOR = '|'; + + /** + * The working data for the current pageload. All changes take place to + * this data. + * + * @var array + */ + protected $_data = array(); + + /** + * HashTable object. + * + * @var Horde_HashTable + */ + protected $_hash; + + /** + * Mailbox level data. + * + * @var array + */ + protected $_mbox = array(); + + /** + * Horde_Pack singleton object. + * + * @var Horde_Pack + */ + protected $_pack; + + /** + * List of mailbox/UIDs to update. + * Keys are mailboxes. Values are arrays with three possible keys: + *
+     *   - d: UIDs to delete
+     *   - m: Was metadata updated?
+     *   - u: UIDs to update
+     * 
+ * + * @var array + */ + protected $_update = array(); + + /** + * Constructor. + * + * @param array $params Configuration parameters: + *
+     *   - REQUIRED parameters:
+     *     - hashtable: (Horde_HashTable) A HashTable object.
+     *
+     *   - Optional Parameters:
+     *     - lifetime: (integer) The lifetime of the cache data (in seconds).
+     *                 DEFAULT: 604800 seconds (1 week) [@since 2.19.0]
+     * 
+ */ + public function __construct(array $params = array()) + { + if (!isset($params['hashtable'])) { + throw new InvalidArgumentException('Missing hashtable parameter.'); + } + + parent::__construct(array_merge(array( + 'lifetime' => 604800 + ), $params)); + } + + /** + */ + protected function _initOb() + { + $this->_hash = $this->_params['hashtable']; + $this->_pack = new Horde_Pack(); + register_shutdown_function(array($this, 'save')); + } + + /** + */ + public function get($mailbox, $uids, $fields, $uidvalid) + { + $ret = array(); + + if (empty($uids)) { + return $ret; + } + + $this->_loadUids($mailbox, $uids, $uidvalid); + + if (empty($this->_data[$mailbox])) { + return $ret; + } + + if (!empty($fields)) { + $fields = array_flip($fields); + } + $ptr = &$this->_data[$mailbox]; + $to_delete = array(); + + foreach ($uids as $val) { + if (isset($ptr[$val])) { + if (is_string($ptr[$val])) { + try { + $ptr[$val] = $this->_pack->unpack($ptr[$val]); + } catch (Horde_Pack_Exception $e) { + $to_delete[] = $val; + continue; + } + } + + $ret[$val] = (empty($fields) || empty($ptr[$val])) + ? $ptr[$val] + : array_intersect_key($ptr[$val], $fields); + } else { + $to_delete[] = $val; + } + } + + $this->deleteMsgs($mailbox, $to_delete); + + return $ret; + } + + /** + */ + public function getCachedUids($mailbox, $uidvalid) + { + $this->_loadMailbox($mailbox, $uidvalid); + return $this->_mbox[$mailbox]['u']->ids; + } + + /** + */ + public function set($mailbox, $data, $uidvalid) + { + $this->_loadUids($mailbox, array_keys($data), $uidvalid); + + $d = &$this->_data[$mailbox]; + $to_add = array(); + + foreach ($data as $k => $v) { + if (isset($d[$k]) && is_string($d[$k])) { + try { + $d[$k] = $this->_pack->unpack($d[$k]); + } catch (Horde_Pack_Exception $e) { + continue; + } + } + + $d[$k] = (isset($d[$k]) && is_array($d[$k])) + ? array_merge($d[$k], $v) + : $v; + $this->_update[$mailbox]['u'][$k] = true; + unset($this->_update[$mailbox]['d'][$k]); + $to_add[] = $k; + } + + if (!empty($to_add)) { + $this->_mbox[$mailbox]['u']->add($to_add); + $this->_update[$mailbox]['m'] = true; + } + } + + /** + */ + public function getMetaData($mailbox, $uidvalid, $entries) + { + $this->_loadMailbox($mailbox, $uidvalid); + + return empty($entries) + ? $this->_mbox[$mailbox]['d'] + : array_intersect_key($this->_mbox[$mailbox]['d'], array_flip($entries)); + } + + /** + */ + public function setMetaData($mailbox, $data) + { + $this->_loadMailbox($mailbox, isset($data['uidvalid']) ? $data['uidvalid'] : null); + + $this->_mbox[$mailbox]['d'] = array_merge( + $this->_mbox[$mailbox]['d'], + $data + ); + $this->_update[$mailbox]['m'] = true; + } + + /** + */ + public function deleteMsgs($mailbox, $uids) + { + if (empty($uids)) { + return; + } + + $this->_loadMailbox($mailbox); + + foreach ($uids as $val) { + unset( + $this->_data[$mailbox][$val], + $this->_update[$mailbox]['u'][$val] + ); + $this->_update[$mailbox]['d'][$val] = true; + } + + $this->_mbox[$mailbox]['u']->remove($uids); + $this->_update[$mailbox]['m'] = true; + } + + /** + */ + public function deleteMailbox($mailbox) + { + /* Do this action immediately, instead of at shutdown. Makes coding + * simpler. */ + $this->_loadMailbox($mailbox); + + $this->_hash->delete(array_merge( + array($this->_getCid($mailbox)), + array_values($this->_getMsgCids($mailbox, $this->_mbox[$mailbox]['u'])) + )); + + unset( + $this->_data[$mailbox], + $this->_mbox[$mailbox], + $this->_update[$mailbox] + ); + } + + /** + */ + public function clear($lifetime) + { + /* Only can clear mailboxes we know about. */ + foreach (array_keys($this->_mbox) as $val) { + $this->deleteMailbox($val); + } + + $this->_data = $this->_mbox = $this->_update = array(); + } + + /** + * Updates the cache. + */ + public function save() + { + foreach ($this->_update as $mbox => $val) { + try { + if (!empty($val['u'])) { + $ptr = &$this->_data[$mbox]; + foreach ($this->_getMsgCids($mbox, array_keys($val['u'])) as $k2 => $v2) { + try { + $this->_hash->set( + $v2, + $this->_pack->pack($ptr[$k2]), + array('expire' => $this->_params['lifetime']) + ); + } catch (Horde_Pack_Exception $e) { + $this->deleteMsgs($mbox, array($v2)); + $val['d'][] = $v2; + } + } + } + + if (!empty($val['d'])) { + $this->_hash->delete(array_values( + $this->_getMsgCids($mbox, $val['d']) + )); + } + + if (!empty($val['m'])) { + try { + $this->_hash->set( + $this->_getCid($mbox), + $this->_pack->pack($this->_mbox[$mbox]), + array('expire' => $this->_params['lifetime']) + ); + } catch (Horde_Pack_Exception $e) {} + } + } catch (Horde_Exception $e) { + } + } + + $this->_update = array(); + } + + /** + * Loads basic mailbox information. + * + * @param string $mailbox The mailbox to load. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + */ + protected function _loadMailbox($mailbox, $uidvalid = null) + { + if (!isset($this->_mbox[$mailbox]) && + ($ob = $this->_hash->get($this->_getCid($mailbox)))) { + try { + $this->_mbox[$mailbox] = $this->_pack->unpack($ob); + } catch (Horde_Pack_Exception $e) {} + } + + if (isset($this->_mbox[$mailbox])) { + if (is_null($uidvalid) || + ($uidvalid == $this->_mbox[$mailbox]['d']['uidvalid'])) { + return; + } + $this->deleteMailbox($mailbox); + } + + $this->_mbox[$mailbox] = array( + // Metadata storage + // By default includes UIDVALIDITY of mailbox. + 'd' => array('uidvalid' => $uidvalid), + // List of UIDs + 'u' => new Horde_Imap_Client_Ids() + ); + } + + /** + * Load UIDs by regenerating from the cache. + * + * @param string $mailbox The mailbox to load. + * @param array $uids The UIDs to load. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + */ + protected function _loadUids($mailbox, $uids, $uidvalid = null) + { + if (!isset($this->_data[$mailbox])) { + $this->_data[$mailbox] = array(); + } + + $this->_loadMailbox($mailbox, $uidvalid); + + if (empty($uids)) { + return; + } + + $ptr = &$this->_data[$mailbox]; + + $load = array_flip( + array_diff_key( + $this->_getMsgCids( + $mailbox, + array_unique(array_intersect($this->_mbox[$mailbox]['u']->ids, $uids)) + ), + $this->_data[$mailbox] + ) + ); + + foreach (array_filter($this->_hash->get(array_keys($load))) as $key => $val) { + $ptr[$load[$key]] = $val; + } + } + + /** + * Create the unique ID used to store the mailbox data in the cache. + * + * @param string $mailbox The mailbox to cache. + * + * @return string The cache ID. + */ + protected function _getCid($mailbox) + { + return implode(self::CID_SEPARATOR, array( + 'horde_imap_client', + $this->_params['username'], + $mailbox, + $this->_params['hostspec'], + $this->_params['port'] + )); + } + + /** + * Return a list of cache IDs for mailbox/UID pairs. + * + * @param string $mailbox The mailbox to cache. + * @param array $ids The UID list. + * + * @return array List of UIDs => cache IDs. + */ + protected function _getMsgCids($mailbox, $ids) + { + $cid = $this->_getCid($mailbox); + $out = array(); + + foreach ($ids as $val) { + $out[$val] = $cid . self::CID_SEPARATOR . $val; + } + + return $out; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Mongo.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Mongo.php new file mode 100644 index 00000000..9fb6511e --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Mongo.php @@ -0,0 +1,440 @@ + + * @category Horde + * @copyright 2013-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Cache_Backend_Mongo +extends Horde_Imap_Client_Cache_Backend +implements Horde_Mongo_Collection_Index +{ + /** Mongo collection names. */ + const BASE = 'horde_imap_client_cache_data'; + const MD = 'horde_imap_client_cache_metadata'; + const MSG = 'horde_imap_client_cache_message'; + + /** Mongo field names: BASE collection. */ + const BASE_HOSTSPEC = 'hostspec'; + const BASE_MAILBOX = 'mailbox'; + const BASE_MODIFIED = 'modified'; + const BASE_PORT = 'port'; + const BASE_UID = 'data'; + const BASE_USERNAME = 'username'; + + /** Mongo field names: MD collection. */ + const MD_DATA = 'data'; + const MD_FIELD = 'field'; + const MD_UID = 'uid'; + + /** Mongo field names: MSG collection. */ + const MSG_DATA = 'data'; + const MSG_MSGUID = 'msguid'; + const MSG_UID = 'uid'; + + /** + * The MongoDB object for the cache data. + * + * @var MongoDB + */ + protected $_db; + + /** + * The list of indices. + * + * @var array + */ + protected $_indices = array( + self::BASE => array( + 'base_index_1' => array( + self::BASE_HOSTSPEC => 1, + self::BASE_MAILBOX => 1, + self::BASE_PORT => 1, + self::BASE_USERNAME => 1, + ) + ), + self::MSG => array( + 'msg_index_1' => array( + self::MSG_MSGUID => 1, + self::MSG_UID => 1 + ) + ) + ); + + /** + * Constructor. + * + * @param array $params Configuration parameters: + *
+     *   - REQUIRED parameters:
+     *     - mongo_db: (Horde_Mongo_Client) A MongoDB client object.
+     * 
+ */ + public function __construct(array $params = array()) + { + if (!isset($params['mongo_db'])) { + throw new InvalidArgumentException('Missing mongo_db parameter.'); + } + + parent::__construct($params); + } + + /** + */ + protected function _initOb() + { + $this->_db = $this->_params['mongo_db']->selectDB(null); + } + + /** + */ + public function get($mailbox, $uids, $fields, $uidvalid) + { + $this->getMetaData($mailbox, $uidvalid, array('uidvalid')); + + if (!($uid = $this->_getUid($mailbox))) { + return array(); + } + + $out = array(); + $query = array( + self::MSG_MSGUID => array('$in' => array_map('strval', $uids)), + self::MSG_UID => $uid + ); + + try { + $cursor = $this->_db->selectCollection(self::MSG)->find( + $query, + array(self::MSG_DATA => true, self::MSG_MSGUID => true) + ); + foreach ($cursor as $val) { + try { + $out[$val[self::MSG_MSGUID]] = $this->_value($val[self::MSG_DATA]); + } catch (Exception $e) {} + } + } catch (MongoException $e) {} + + return $out; + } + + /** + */ + public function getCachedUids($mailbox, $uidvalid) + { + $this->getMetaData($mailbox, $uidvalid, array('uidvalid')); + + if (!($uid = $this->_getUid($mailbox))) { + return array(); + } + + $out = array(); + $query = array( + self::MSG_UID => $uid + ); + + try { + $cursor = $this->_db->selectCollection(self::MSG)->find( + $query, array(self::MSG_MSGUID => true) + ); + foreach ($cursor as $val) { + $out[] = $val[self::MSG_MSGUID]; + } + } catch (MongoException $e) {} + + return $out; + } + + /** + */ + public function set($mailbox, $data, $uidvalid) + { + if ($uid = $this->_getUid($mailbox)) { + $res = $this->get($mailbox, array_keys($data), array(), $uidvalid); + } else { + $res = array(); + $uid = $this->_createUid($mailbox); + } + + $coll = $this->_db->selectCollection(self::MSG); + + foreach ($data as $key => $val) { + try { + if (isset($res[$key])) { + $coll->update(array( + self::MSG_MSGUID => strval($key), + self::MSG_UID => $uid + ), array( + self::MSG_DATA => $this->_value(array_merge($res[$key], $val)), + self::MSG_MSGUID => strval($key), + self::MSG_UID => $uid + )); + } else { + $doc = array( + self::MSG_DATA => $this->_value($val), + self::MSG_MSGUID => strval($key), + self::MSG_UID => $uid + ); + $coll->insert($doc); + } + } catch (MongoException $e) {} + } + + /* Update modified time. */ + try { + $this->_db->selectCollection(self::BASE)->update( + array(self::BASE_UID => $uid), + array(self::BASE_MODIFIED => time()) + ); + } catch (MongoException $e) {} + + /* Update uidvalidity. */ + $this->setMetaData($mailbox, array('uidvalid' => $uidvalid)); + } + + /** + */ + public function getMetaData($mailbox, $uidvalid, $entries) + { + if (!($uid = $this->_getUid($mailbox))) { + return array(); + } + + $out = array(); + $query = array( + self::MD_UID => $uid + ); + + if (!empty($entries)) { + $entries[] = 'uidvalid'; + $query[self::MD_FIELD] = array( + '$in' => array_unique($entries) + ); + } + + try { + $cursor = $this->_db->selectCollection(self::MD)->find( + $query, + array(self::MD_DATA => true, self::MD_FIELD => true) + ); + foreach ($cursor as $val) { + try { + $out[$val[self::MD_FIELD]] = $this->_value($val[self::MD_DATA]); + } catch (Exception $e) {} + } + + if (is_null($uidvalid) || + !isset($out['uidvalid']) || + ($out['uidvalid'] == $uidvalid)) { + return $out; + } + + $this->deleteMailbox($mailbox); + } catch (MongoException $e) {} + + return array(); + } + + /** + */ + public function setMetaData($mailbox, $data) + { + if (!($uid = $this->_getUid($mailbox))) { + $uid = $this->_createUid($mailbox); + } + + $coll = $this->_db->selectCollection(self::MD); + + foreach ($data as $key => $val) { + try { + $coll->update( + array( + self::MD_FIELD => $key, + self::MD_UID => $uid + ), + array( + self::MD_DATA => $this->_value($val), + self::MD_FIELD => $key, + self::MD_UID => $uid + ), + array('upsert' => true) + ); + } catch (MongoException $e) {} + } + } + + /** + */ + public function deleteMsgs($mailbox, $uids) + { + if (!empty($uids) && ($uid = $this->_getUid($mailbox))) { + try { + $this->_db->selectCollection(self::MSG)->remove(array( + self::MSG_MSGUID => array( + '$in' => array_map('strval', $uids) + ), + self::MSG_UID => $uid + )); + } catch (MongoException $e) {} + } + } + + /** + */ + public function deleteMailbox($mailbox) + { + if (!($uid = $this->_getUid($mailbox))) { + return; + } + + foreach (array(self::BASE, self::MD, self::MSG) as $val) { + try { + $this->_db->selectCollection($val) + ->remove(array('uid' => $uid)); + } catch (MongoException $e) {} + } + } + + /** + */ + public function clear($lifetime) + { + if (is_null($lifetime)) { + foreach (array(self::BASE, self::MD, self::MSG) as $val) { + $this->_db->selectCollection($val)->drop(); + } + return; + } + + $query = array( + self::BASE_MODIFIED => array('$lt' => (time() - $lifetime)) + ); + $uids = array(); + + try { + $cursor = $this->_db->selectCollection(self::BASE)->find($query); + foreach ($cursor as $val) { + $uids[] = strval($val['_id']); + } + } catch (MongoException $e) {} + + if (empty($uids)) { + return; + } + + foreach (array(self::BASE, self::MD, self::MSG) as $val) { + try { + $this->_db->selectCollection($val) + ->remove(array('uid' => array('$in' => $uids))); + } catch (MongoException $e) {} + } + } + + /** + * Return the UID for a mailbox/user/server combo. + * + * @param string $mailbox Mailbox name. + * + * @return string UID from base table. + */ + protected function _getUid($mailbox) + { + $query = array( + self::BASE_HOSTSPEC => $this->_params['hostspec'], + self::BASE_MAILBOX => $mailbox, + self::BASE_PORT => $this->_params['port'], + self::BASE_USERNAME => $this->_params['username'] + ); + + try { + if ($result = $this->_db->selectCollection(self::BASE)->findOne($query)) { + return strval($result['_id']); + } + } catch (MongoException $e) {} + + return null; + } + + /** + * Create and return the UID for a mailbox/user/server combo. + * + * @param string $mailbox Mailbox name. + * + * @return string UID from base table. + */ + protected function _createUid($mailbox) + { + $doc = array( + self::BASE_HOSTSPEC => $this->_params['hostspec'], + self::BASE_MAILBOX => $mailbox, + self::BASE_PORT => $this->_params['port'], + self::BASE_USERNAME => $this->_params['username'] + ); + $this->_db->selectCollection(self::BASE)->insert($doc); + + return $this->_getUid($mailbox); + } + + /** + * Convert data from/to storage format. + * + * @param mixed|MongoBinData $data The data object. + * + * @return mixed|MongoBinData The converted data. + */ + protected function _value($data) + { + static $compress; + + if (!isset($compress)) { + $compress = new Horde_Compress_Fast(); + } + + return ($data instanceof MongoBinData) + ? @unserialize($compress->decompress($data->bin)) + : new MongoBinData( + $compress->compress(serialize($data)), MongoBinData::BYTE_ARRAY + ); + } + + /* Horde_Mongo_Collection_Index methods. */ + + /** + */ + public function checkMongoIndices() + { + foreach ($this->_indices as $key => $val) { + if (!$this->_params['mongo_db']->checkIndices($key, $val)) { + return false; + } + } + + return true; + } + + /** + */ + public function createMongoIndices() + { + foreach ($this->_indices as $key => $val) { + $this->_params['mongo_db']->createIndices($key, $val); + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Null.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Null.php new file mode 100644 index 00000000..ca4fe8bc --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Cache/Backend/Null.php @@ -0,0 +1,79 @@ + + * @category Horde + * @copyright 2013-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Cache_Backend_Null +extends Horde_Imap_Client_Cache_Backend +{ + /** + */ + public function get($mailbox, $uids, $fields, $uidvalid) + { + return array(); + } + + /** + */ + public function getCachedUids($mailbox, $uidvalid) + { + return array(); + } + + /** + */ + public function set($mailbox, $data, $uidvalid) + { + } + + /** + */ + public function getMetaData($mailbox, $uidvalid, $entries) + { + return array( + 'uidvalid' => 0 + ); + } + + /** + */ + public function setMetaData($mailbox, $data) + { + } + + /** + */ + public function deleteMsgs($mailbox, $uids) + { + } + + /** + */ + public function deleteMailbox($mailbox) + { + } + + /** + */ + public function clear($lifetime) + { + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Acl.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Acl.php new file mode 100644 index 00000000..1f0461c9 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Acl.php @@ -0,0 +1,164 @@ + + * @category Horde + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Acl extends Horde_Imap_Client_Data_AclCommon implements ArrayAccess, IteratorAggregate, Serializable +{ + /** + * ACL rights. + * + * @var array + */ + protected $_rights; + + /** + * Constructor. + * + * @param string $rights The rights (see RFC 4314 [2.1]). + */ + public function __construct($rights = '') + { + $this->_rights = str_split($rights); + $this->_normalize(); + } + + /** + * String representation of the ACL. + * + * @return string String representation (RFC 4314 compliant). + */ + public function __toString() + { + return implode('', $this->_rights); + } + + /** + * Computes the difference to another rights string. + * Virtual rights are ignored. + * + * @param string $rights The rights to compute against. + * + * @return array Two element array: added and removed. + */ + public function diff($rights) + { + $rlist = array_diff(str_split($rights), array_keys($this->_virtual)); + + return array( + 'added' => implode('', array_diff($rlist, $this->_rights)), + 'removed' => implode('', array_diff($this->_rights, $rlist)) + ); + } + + /** + * Normalize virtual rights (see RFC 4314 [2.1.1]). + */ + protected function _normalize() + { + /* Clients conforming to RFC 4314 MUST ignore the virtual ACL_CREATE + * and ACL_DELETE rights. See RFC 4314 [2.1]. However, we still need + * to handle these rights when dealing with RFC 2086 servers since + * we are abstracting out use of ACL_CREATE/ACL_DELETE to their + * component RFC 4314 rights. */ + foreach ($this->_virtual as $key => $val) { + foreach ($val as $right) { + if ($this[$right]) { + foreach (array_keys($this->_virtual) as $virtual) { + unset($this[$virtual]); + } + return; + } + } + } + foreach ($this->_virtual as $key => $val) { + if ($this[$key]) { + unset($this[$key]); + $this->_rights = array_unique(array_merge($this->_rights, $val)); + } + } + } + + /* ArrayAccess methods. */ + + /** + */ + public function offsetExists($offset) + { + return $this[$offset]; + } + + /** + */ + public function offsetGet($offset) + { + return in_array($offset, $this->_rights); + } + + /** + */ + public function offsetSet($offset, $value) + { + if ($value) { + if (!$this[$offset]) { + $this->_rights[] = $offset; + $this->_normalize(); + } + } elseif ($this[$offset]) { + if (isset($this->_virtual[$offset])) { + foreach ($this->_virtual[$offset] as $val) { + unset($this[$val]); + } + } + unset($this[$offset]); + } + } + + /** + */ + public function offsetUnset($offset) + { + $this->_rights = array_values(array_diff($this->_rights, array($offset))); + } + + /* IteratorAggregate method. */ + + public function getIterator() + { + return new ArrayIterator($this->_rights); + } + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + return json_encode($this->_rights); + } + + /** + */ + public function unserialize($data) + { + $this->_rights = json_decode($data); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclCommon.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclCommon.php new file mode 100644 index 00000000..7b5e3cfd --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclCommon.php @@ -0,0 +1,72 @@ + + * @category Horde + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_AclCommon +{ + /** Constants for getString(). */ + const RFC_2086 = 1; + const RFC_4314 = 2; + + /** + * List of virtual rights (RFC 4314 [2.1.1]). + * + * @var array + */ + protected $_virtual = array( + Horde_Imap_Client::ACL_CREATE => array( + Horde_Imap_Client::ACL_CREATEMBOX, + Horde_Imap_Client::ACL_DELETEMBOX + ), + Horde_Imap_Client::ACL_DELETE => array( + Horde_Imap_Client::ACL_DELETEMSGS, + // Don't put this first - we do checks on the existence of the + // first element in this array to determine the RFC type, and this + // is duplicate of right contained in ACL_CREATE. + Horde_Imap_Client::ACL_DELETEMBOX, + Horde_Imap_Client::ACL_EXPUNGE + ) + ); + + /** + * Returns the raw string to use in IMAP server calls. + * + * @param integer $type The RFC type to use (RFC_* constant). + * + * @return string The string representation of the ACL. + */ + public function getString($type = self::RFC_4314) + { + $acl = strval($this); + + if ($type == self::RFC_2086) { + foreach ($this->_virtual as $key => $val) { + $acl = str_replace($val, '', $acl, $count); + if ($count) { + $acl .= $key; + } + } + } + + return $acl; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclNegative.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclNegative.php new file mode 100644 index 00000000..4ef352bd --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclNegative.php @@ -0,0 +1,25 @@ + + * @category Horde + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_AclNegative extends Horde_Imap_Client_Data_Acl +{ +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclRights.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclRights.php new file mode 100644 index 00000000..5b21468d --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/AclRights.php @@ -0,0 +1,208 @@ + + * @category Horde + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_AclRights extends Horde_Imap_Client_Data_AclCommon implements ArrayAccess, Iterator, Serializable +{ + /** + * ACL optional rights. + * + * @var array + */ + protected $_optional = array(); + + /** + * ACL required rights. + * + * @var array + */ + protected $_required = array(); + + /** + * Constructor. + * + * @param array $required The required rights (see RFC 4314 [2.1]). + * @param array $optional The optional rights (see RFC 4314 [2.1]). + */ + public function __construct(array $required = array(), + array $optional = array()) + { + $this->_required = $required; + + foreach ($optional as $val) { + foreach (str_split($val) as $right) { + $this->_optional[$right] = $val; + } + } + + $this->_normalize(); + } + + /** + * String representation of the ACL. + * + * @return string String representation (RFC 4314 compliant). + * + */ + public function __toString() + { + return implode('', array_keys(array_flip(array_merge(array_values($this->_required), array_keys($this->_optional))))); + } + + /** + * Normalize virtual rights (see RFC 4314 [2.1.1]). + */ + protected function _normalize() + { + /* Clients conforming to RFC 4314 MUST ignore the virtual ACL_CREATE + * and ACL_DELETE rights. See RFC 4314 [2.1]. However, we still need + * to handle these rights when dealing with RFC 2086 servers since + * we are abstracting out use of ACL_CREATE/ACL_DELETE to their + * component RFC 4314 rights. */ + foreach ($this->_virtual as $key => $val) { + if (isset($this->_optional[$key])) { + unset($this->_optional[$key]); + foreach ($val as $val2) { + $this->_optional[$val2] = implode('', $val); + } + } elseif (($pos = array_search($key, $this->_required)) !== false) { + unset($this->_required[$pos]); + $this->_required = array_unique(array_merge($this->_required, $val)); + } + } + } + + /* ArrayAccess methods. */ + + /** + */ + public function offsetExists($offset) + { + return (bool)$this[$offset]; + } + + /** + */ + public function offsetGet($offset) + { + if (isset($this->_optional[$offset])) { + return $this->_optional[$offset]; + } + + $pos = array_search($offset, $this->_required); + + return ($pos === false) + ? null + : $this->_required[$pos]; + } + + /** + */ + public function offsetSet($offset, $value) + { + $this->_optional[$offset] = $value; + $this->_normalize(); + } + + /** + */ + public function offsetUnset($offset) + { + unset($this->_optional[$offset]); + $this->_required = array_values(array_diff($this->_required, array($offset))); + + if (isset($this->_virtual[$offset])) { + foreach ($this->_virtual[$offset] as $val) { + unset($this[$val]); + } + } + } + + /* Iterator methods. */ + + /** + */ + public function current() + { + $val = current($this->_required); + return is_null($val) + ? current($this->_optional) + : $val; + } + + /** + */ + public function key() + { + $key = key($this->_required); + return is_null($key) + ? key($this->_optional) + : $key; + } + + /** + */ + public function next() + { + if (key($this->_required) === null) { + next($this->_optional); + } else { + next($this->_required); + } + } + + /** + */ + public function rewind() + { + reset($this->_required); + reset($this->_optional); + } + + /** + */ + public function valid() + { + return ((key($this->_required) !== null) || + (key($this->_optional) !== null)); + + } + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + return json_encode(array( + $this->_required, + $this->_optional + )); + } + + /** + */ + public function unserialize($data) + { + list($this->_required, $this->_optional) = json_decode($data); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/BaseSubject.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/BaseSubject.php new file mode 100644 index 00000000..615d7164 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/BaseSubject.php @@ -0,0 +1,231 @@ + + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.horde.org/licenses/lgpl21. + * + * @category Horde + * @copyright 2002-2008 Timo Sirainen + * @copyright 2008-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ + +/** + * Determines the "base subject" of a string (RFC 5256 [2.1]). + * + * @author Timo Sirainen + * @author Michael Slusarz + * @category Horde + * @copyright 2002-2008 Timo Sirainen + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_BaseSubject +{ + /** + * The base subject. + * + * @var string + */ + protected $_subject; + + /** + * Constructor. + * + * @param string $str The subject string. + * @param array $opts Additional options: + * - keepblob: (boolean) Don't remove any "blob" information (i.e. text + * leading text between square brackets) from string. + * + * @return string The cleaned up subject string. + */ + public function __construct($str, array $opts = array()) + { + // Rule 1a: MIME decode. + $str = Horde_Mime::decode($str); + + // Rule 1b: Remove superfluous whitespace. + $str = preg_replace("/[\t\r\n ]+/", ' ', $str); + + do { + /* (2) Remove all trailing text of the subject that matches the + * the subj-trailer ABNF, repeat until no more matches are + * possible. */ + $str = preg_replace("/(?:\s*\(fwd\)\s*)+$/i", '', $str); + + do { + /* (3) Remove all prefix text of the subject that matches the + * subj-leader ABNF. */ + $found = $this->_removeSubjLeader($str, !empty($opts['keepblob'])); + + /* (4) If there is prefix text of the subject that matches + * the subj-blob ABNF, and removing that prefix leaves a + * non-empty subj-base, then remove the prefix text. */ + $found = (empty($opts['keepblob']) && $this->_removeBlobWhenNonempty($str)) || $found; + + /* (5) Repeat (3) and (4) until no matches remain. */ + } while ($found); + + /* (6) If the resulting text begins with the subj-fwd-hdr ABNF and + * ends with the subj-fwd-trl ABNF, remove the subj-fwd-hdr and + * subj-fwd-trl and repeat from step (2). */ + } while ($this->_removeSubjFwdHdr($str)); + + $this->_subject = strval($str); + } + + /** + * Return the "base subject" defined in RFC 5256 [2.1]. + * + * @return string The base subject. + */ + public function __toString() + { + return $this->_subject; + } + + /** + * Remove all prefix text of the subject that matches the subj-leader + * ABNF. + * + * @param string &$str The subject string. + * @param boolean $keepblob Remove blob information? + * + * @return boolean True if string was altered. + */ + protected function _removeSubjLeader(&$str, $keepblob = false) + { + $ret = false; + + if (!strlen($str)) { + return $ret; + } + + if ($len = strspn($str, " \t")) { + $str = substr($str, $len); + $ret = true; + } + + $i = 0; + + if (!$keepblob) { + while (isset($str[$i]) && ($str[$i] === '[')) { + if (($i = $this->_removeBlob($str, $i)) === false) { + return $ret; + } + } + } + + if (stripos($str, 're', $i) === 0) { + $i += 2; + } elseif (stripos($str, 'fw', $i) === 0) { + $i += (stripos($str, 'fwd', $i) === 0) ? 3 : 2; + } else { + return $ret; + } + + $i += strspn($str, " \t", $i); + + if (!$keepblob) { + while (isset($str[$i]) && ($str[$i] === '[')) { + if (($i = $this->_removeBlob($str, $i)) === false) { + return $ret; + } + } + } + + if (!isset($str[$i]) || ($str[$i] !== ':')) { + return $ret; + } + + $str = substr($str, ++$i); + + return true; + } + + /** + * Remove "[...]" text. + * + * @param string $str The subject string. + * @param integer $i Current position. + * + * @return boolean|integer False if blob was not found, otherwise the + * string position of the first non-blob char. + */ + protected function _removeBlob($str, $i) + { + if ($str[$i] !== '[') { + return false; + } + + ++$i; + + for ($cnt = strlen($str); $i < $cnt; ++$i) { + if ($str[$i] === ']') { + break; + } + + if ($str[$i] === '[') { + return false; + } + } + + if ($i === ($cnt - 1)) { + return false; + } + + ++$i; + + if ($str[$i] === ' ') { + ++$i; + } + + return $i; + } + + /** + * Remove "[...]" text if it doesn't result in the subject becoming + * empty. + * + * @param string &$str The subject string. + * + * @return boolean True if string was altered. + */ + protected function _removeBlobWhenNonempty(&$str) + { + if ($str && + ($str[0] === '[') && + (($i = $this->_removeBlob($str, 0)) !== false) && + ($i !== strlen($str))) { + $str = substr($str, $i); + return true; + } + + return false; + } + + /** + * Remove a "[fwd: ... ]" string. + * + * @param string &$str The subject string. + * + * @return boolean True if string was altered. + */ + protected function _removeSubjFwdHdr(&$str) + { + if ((stripos($str, '[fwd:') !== 0) || (substr($str, -1) !== ']')) { + return false; + } + + $str = substr($str, 5, -1); + return true; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Capability.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Capability.php new file mode 100644 index 00000000..98c25135 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Capability.php @@ -0,0 +1,214 @@ + + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.24.0 + */ +class Horde_Imap_Client_Data_Capability +implements Serializable, SplSubject +{ + /** + * Capability data. + * + * @var array + */ + protected $_data = array(); + + /** + * Observers. + * + * @var array + */ + protected $_observers = array(); + + /** + * Add a capability (and optional parameters). + * + * @param string $capability The capability to add. + * @param mixed $params A parameter (or array of parameters) to add. + */ + public function add($capability, $params = null) + { + $capability = Horde_String::upper($capability); + + if (is_null($params)) { + if (isset($this->_data[$capability])) { + return; + } + $params = true; + } else { + if (!is_array($params)) { + $params = array($params); + } + $params = array_map('Horde_String::upper', $params); + + if (isset($this->_data[$capability]) && + is_array($this->_data[$capability])) { + $params = array_merge($this->_data[$capability], $params); + } + } + + $this->_data[$capability] = $params; + $this->notify(); + } + + /** + * Remove a capability. + * + * @param string $capability The capability to remove. + * @param string $params A parameter (or array of parameters) to + * remove from the capability. + */ + public function remove($capability, $params = null) + { + $capability = Horde_String::upper($capability); + + if (is_null($params)) { + unset($this->_data[$capability]); + } elseif (isset($this->_data[$capability])) { + if (!is_array($params)) { + $params = array($params); + } + $params = array_map('Horde_String::upper', $params); + + $this->_data[$capability] = is_array($this->_data[$capability]) + ? array_diff($this->_data[$capability], $params) + : array(); + + if (empty($this->_data[$capability])) { + unset($this->_data[$capability]); + } + } + + $this->notify(); + } + + /** + * Returns whether the server supports the given capability. + * + * @param string $capability The capability string to query. + * @param string $parameter If set, require the parameter to exist. + * + * @return boolean True if the capability (and parameter) exist. + */ + public function query($capability, $parameter = null) + { + $capability = Horde_String::upper($capability); + + if (!isset($this->_data[$capability])) { + return false; + } + + return is_null($parameter) ?: + (is_array($this->_data[$capability]) && + in_array(Horde_String::upper($parameter), $this->_data[$capability])); + } + + /** + * Return the list of parameters for an extension. + * + * @param string $capability The capability string to query. + * + * @return array An array of parameters if the extension exists and + * supports parameters. Otherwise, an empty array. + */ + public function getParams($capability) + { + return ($this->query($capability) && is_array($out = $this->_data[Horde_String::upper($capability)])) + ? $out + : array(); + } + + /** + * Is the extension enabled? + * + * @param string $capability The extension (+ parameter) to query. If + * null, returns all enabled extensions. + * + * @return mixed If $capability is null, return all enabled extensions. + * Otherwise, true if the extension (+ parameter) is + * enabled. + */ + public function isEnabled($capability = null) + { + return is_null($capability) + ? array() + : false; + } + + /** + * Returns the raw data. + * + * @deprecated + * + * @return array Capability data. + */ + public function toArray() + { + return $this->_data; + } + + /* SplSubject methods. */ + + /** + */ + public function attach(SplObserver $observer) + { + $this->detach($observer); + $this->_observers[] = $observer; + } + + /** + */ + public function detach(SplObserver $observer) + { + if (($key = array_search($observer, $this->_observers, true)) !== false) { + unset($this->_observers[$key]); + } + } + + /** + * Notification is triggered internally whenever the object's internal + * data storage is altered. + */ + public function notify() + { + foreach ($this->_observers as $val) { + $val->update($this); + } + } + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + return json_encode($this->_data); + } + + /** + */ + public function unserialize($data) + { + $this->_data = json_decode($data, true); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Capability/Imap.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Capability/Imap.php new file mode 100644 index 00000000..96a058a5 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Capability/Imap.php @@ -0,0 +1,117 @@ + + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.24.0 + * + * @property-read integer $cmdlength Allowable command length (in octets). + */ +class Horde_Imap_Client_Data_Capability_Imap +extends Horde_Imap_Client_Data_Capability +{ + /** + * The list of enabled extensions. + * + * @var array + */ + protected $_enabled = array(); + + /** + */ + public function __get($name) + { + switch ($name) { + case 'cmdlength': + /* RFC 2683 [3.2.1.5] originally recommended that lines should + * be limited to "approximately 1000 octets". However, servers + * should allow a command line of at least "8000 octets". + * RFC 7162 [4] updates the recommendation to 8192 octets. + * As a compromise, assume all modern IMAP servers handle + * ~2000 octets and, if CONDSTORE/QRESYNC is supported, assume + * they can handle ~8000 octets. (Don't need dependency support + * checks here - the simple presence of CONDSTORE/QRESYNC is + * enough to trigger.) */ + return (isset($this->_data['CONDSTORE']) || isset($this->_data['QRESYNC'])) + ? 8000 + : 2000; + } + } + + /** + */ + public function query($capability, $parameter = null) + { + if (parent::query($capability, $parameter)) { + return true; + } + + switch (Horde_String::upper($capability)) { + case 'CONDSTORE': + case 'ENABLE': + /* RFC 7162 [3.2.3] - QRESYNC implies CONDSTORE and ENABLE. */ + return (is_null($parameter) && $this->query('QRESYNC')); + + case 'UTF8': + /* RFC 6855 [3] - UTF8=ONLY implies UTF8=ACCEPT. */ + return ((Horde_String::upper($parameter) === 'ACCEPT') && + $this->query('UTF8', 'ONLY')); + } + + return false; + } + + /** + */ + public function isEnabled($capability = null) + { + return is_null($capability) + ? $this->_enabled + : in_array(Horde_String::upper($capability), $this->_enabled); + } + + /** + * Set a capability as enabled/disabled. + * + * @param array $capability A capability (+ parameter). + * @param boolean $enable If true, enables the capability. + */ + public function enable($capability, $enable = true) + { + $capability = Horde_String::upper($capability); + $enabled = $this->isEnabled($capability); + + if ($enable && !$enabled) { + switch ($capability) { + case 'QRESYNC': + /* RFC 7162 [3.2.3] - Enabling QRESYNC also implies enabling + * of CONDSTORE. */ + $this->enable('CONDSTORE'); + break; + } + + $this->_enabled[] = $capability; + $this->notify(); + } elseif (!$enable && $enabled) { + $this->_enabled = array_diff($this->_enabled, array($capability)); + $this->notify(); + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Envelope.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Envelope.php new file mode 100644 index 00000000..5903e89d --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Envelope.php @@ -0,0 +1,226 @@ + + * @category Horde + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * + * @todo $date should return null if it doesn't exist. + * + * @property Horde_Mail_Rfc822_List $bcc Bcc address(es). + * @property Horde_Mail_Rfc822_List $cc Cc address(es). + * @property Horde_Imap_Client_DateTime $date Message date. + * @property Horde_Mail_Rfc822_List $from From address(es). + * @property string $in_reply_to Message-ID of the message replied to. + * @property string $message_id Message-ID of the message. + * @property Horde_Mail_Rfc822_List $reply_to Reply-to address(es). + * @property Horde_Mail_Rfc822_List $sender Sender address. + * @property string $subject Subject. + * @property Horde_Mail_Rfc822_List $to To address(es). + */ +class Horde_Imap_Client_Data_Envelope implements Serializable +{ + /* Serializable version. */ + const VERSION = 3; + + /** + * Data object. + * + * @var Horde_Mime_Headers + */ + protected $_data; + + /** + * Constructor. + * + * @var array $data An array of property names (keys) and values to set + * in this object. + */ + public function __construct(array $data = array()) + { + $this->_data = new Horde_Mime_Headers(); + + foreach ($data as $key => $val) { + $this->$key = $val; + } + } + + /** + */ + public function __get($name) + { + $name = $this->_normalizeProperty($name); + + switch ($name) { + case 'bcc': + case 'cc': + case 'from': + case 'reply-to': + case 'sender': + case 'to': + if ($h = $this->_data[$name]) { + return $h->getAddressList(true); + } + + if (in_array($name, array('sender', 'reply-to'))) { + return $this->from; + } + break; + + case 'date': + if ($val = $this->_data['date']) { + return new Horde_Imap_Client_DateTime($val->value); + } + break; + + case 'in-reply-to': + case 'message-id': + case 'subject': + if ($val = $this->_data[$name]) { + return $val->value; + } + break; + } + + // Default values. + switch ($name) { + case 'bcc': + case 'cc': + case 'from': + case 'to': + return new Horde_Mail_Rfc822_List(); + + case 'date': + return new Horde_Imap_Client_DateTime(); + + case 'in-reply-to': + case 'message-id': + case 'subject': + return ''; + } + + return null; + } + + /** + */ + public function __set($name, $value) + { + if (!strlen($value)) { + return; + } + + $name = $this->_normalizeProperty($name); + + switch ($name) { + case 'bcc': + case 'cc': + case 'date': + case 'from': + case 'in-reply-to': + case 'message-id': + case 'reply-to': + case 'sender': + case 'subject': + case 'to': + switch ($name) { + case 'from': + if ($this->reply_to->match($value)) { + unset($this->_data['reply-to']); + } + if ($this->sender->match($value)) { + unset($this->_data['sender']); + } + break; + + case 'reply-to': + case 'sender': + if ($this->from->match($value)) { + unset($this->_data[$name]); + return; + } + break; + } + + $this->_data->addHeader($name, $value); + break; + } + } + + /** + */ + public function __isset($name) + { + $name = $this->_normalizeProperty($name); + + switch ($name) { + case 'reply-to': + case 'sender': + if (isset($this->_data[$name])) { + return true; + } + $name = 'from'; + break; + } + + return isset($this->_data[$name]); + } + + /** + */ + protected function _normalizeProperty($name) + { + switch ($name) { + case 'in_reply_to': + return 'in-reply-to'; + + case 'message_id': + return 'message-id'; + + case 'reply_to': + return 'reply-to'; + } + + return $name; + } + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + return serialize(array( + 'd' => $this->_data, + 'v' => self::VERSION + )); + } + + /** + */ + public function unserialize($data) + { + $data = @unserialize($data); + if (empty($data['v']) || ($data['v'] != self::VERSION)) { + throw new Exception('Cache version change'); + } + + $this->_data = $data['d']; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Fetch.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Fetch.php new file mode 100644 index 00000000..0dba67de --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Fetch.php @@ -0,0 +1,666 @@ + + * @category Horde + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Fetch +{ + /** Header formatting constants. */ + const HEADER_PARSE = 1; + const HEADER_STREAM = 2; + + /** + * Internal data array. + * + * @var array + */ + protected $_data = array(); + + /** + */ + public function __clone() + { + $this->_data = unserialize(serialize($this->_data)); + } + + /** + * Set the full message property. + * + * @param mixed $msg The full message text, as either a string or stream + * resource. + */ + public function setFullMsg($msg) + { + $this->_data[Horde_Imap_Client::FETCH_FULLMSG] = $this->_setMixed($msg); + } + + /** + * Returns the full message. + * + * @param boolean $stream Return as a stream? + * + * @return mixed The full text of the entire message. + */ + public function getFullMsg($stream = false) + { + return $this->_msgText( + $stream, + isset($this->_data[Horde_Imap_Client::FETCH_FULLMSG]) + ? $this->_data[Horde_Imap_Client::FETCH_FULLMSG] + : null + ); + } + + /** + * Set the message structure. + * + * @param Horde_Mime_Part $structure The base MIME part of the message. + */ + public function setStructure(Horde_Mime_Part $structure) + { + $this->_data[Horde_Imap_Client::FETCH_STRUCTURE] = $structure; + } + + /** + * Get the message structure. + * + * @return Horde_Mime_Part $structure The base MIME part of the message. + */ + public function getStructure() + { + return isset($this->_data[Horde_Imap_Client::FETCH_STRUCTURE]) + ? clone $this->_data[Horde_Imap_Client::FETCH_STRUCTURE] + : new Horde_Mime_Part(); + } + + /** + * Set a header entry. + * + * @param string $label The search label. + * @param mixed $data Either a Horde_Mime_Headers object or the raw + * header text. + */ + public function setHeaders($label, $data) + { + if ($data instanceof Horde_Stream) { + $data = $data->stream; + } + $this->_data[Horde_Imap_Client::FETCH_HEADERS][$label] = $data; + } + + /** + * Get a header entry. + * + * @param string $label The search label. + * @param integer $format The return format. If self::HEADER_PARSE, + * returns a Horde_Mime_Headers object. If + * self::HEADER_STREAM, returns a stream. + * Otherwise, returns header text. + * + * @return mixed See $format. + */ + public function getHeaders($label, $format = 0) + { + return $this->_getHeaders( + $label, + $format, + Horde_Imap_Client::FETCH_HEADERS + ); + } + + /** + * Set a header text entry. + * + * @param string $id The MIME ID. + * @param mixed $text The header text, as either a string or stream + * resource. + */ + public function setHeaderText($id, $text) + { + $this->_data[Horde_Imap_Client::FETCH_HEADERTEXT][$id] = $this->_setMixed($text); + } + + /** + * Get a header text entry. + * + * @param string $id The MIME ID. + * @param integer $format The return format. If self::HEADER_PARSE, + * returns a Horde_Mime_Headers object. If + * self::HEADER_STREAM, returns a stream. + * Otherwise, returns header text. + * + * @return mixed See $format. + */ + public function getHeaderText($id = 0, $format = 0) + { + return $this->_getHeaders( + $id, + $format, + Horde_Imap_Client::FETCH_HEADERTEXT + ); + } + + /** + * Set a MIME header entry. + * + * @param string $id The MIME ID. + * @param mixed $text The header text, as either a string or stream + * resource. + */ + public function setMimeHeader($id, $text) + { + $this->_data[Horde_Imap_Client::FETCH_MIMEHEADER][$id] = $this->_setMixed($text); + } + + /** + * Get a MIME header entry. + * + * @param string $id The MIME ID. + * @param integer $format The return format. If self::HEADER_PARSE, + * returns a Horde_Mime_Headers object. If + * self::HEADER_STREAM, returns a stream. + * Otherwise, returns header text. + * + * @return mixed See $format. + */ + public function getMimeHeader($id, $format = 0) + { + return $this->_getHeaders( + $id, + $format, + Horde_Imap_Client::FETCH_MIMEHEADER + ); + } + + /** + * Set a body part entry. + * + * @param string $id The MIME ID. + * @param mixed $text The body part text, as either a string or stream + * resource. + * @param string $decode Either '8bit', 'binary', or null. + */ + public function setBodyPart($id, $text, $decode = null) + { + $this->_data[Horde_Imap_Client::FETCH_BODYPART][$id] = array( + 'd' => $decode, + 't' => $this->_setMixed($text) + ); + } + + /** + * Get a body part entry. + * + * @param string $id The MIME ID. + * @param boolean $stream Return as a stream? + * + * @return mixed The full text of the body part. + */ + public function getBodyPart($id, $stream = false) + { + return $this->_msgText( + $stream, + isset($this->_data[Horde_Imap_Client::FETCH_BODYPART][$id]) + ? $this->_data[Horde_Imap_Client::FETCH_BODYPART][$id]['t'] + : null + ); + } + + /** + * Determines if/how a body part was MIME decoded on the server. + * + * @param string $id The MIME ID. + * + * @return string Either '8bit', 'binary', or null. + */ + public function getBodyPartDecode($id) + { + return isset($this->_data[Horde_Imap_Client::FETCH_BODYPART][$id]) + ? $this->_data[Horde_Imap_Client::FETCH_BODYPART][$id]['d'] + : null; + } + + /** + * Set the body part size for a body part. + * + * @param string $id The MIME ID. + * @param integer $size The size (in bytes). + */ + public function setBodyPartSize($id, $size) + { + $this->_data[Horde_Imap_Client::FETCH_BODYPARTSIZE][$id] = intval($size); + } + + /** + * Returns the body part size, if returned by the server. + * + * @param string $id The MIME ID. + * + * @return integer The body part size, in bytes. + */ + public function getBodyPartSize($id) + { + return isset($this->_data[Horde_Imap_Client::FETCH_BODYPARTSIZE][$id]) + ? $this->_data[Horde_Imap_Client::FETCH_BODYPARTSIZE][$id] + : null; + } + + /** + * Set a body text entry. + * + * @param string $id The MIME ID. + * @param mixed $text The body part text, as either a string or stream + * resource. + */ + public function setBodyText($id, $text) + { + $this->_data[Horde_Imap_Client::FETCH_BODYTEXT][$id] = $this->_setMixed($text); + } + + /** + * Get a body text entry. + * + * @param string $id The MIME ID. + * @param boolean $stream Return as a stream? + * + * @return mixed The full text of the body text. + */ + public function getBodyText($id = 0, $stream = false) + { + return $this->_msgText( + $stream, + isset($this->_data[Horde_Imap_Client::FETCH_BODYTEXT][$id]) + ? $this->_data[Horde_Imap_Client::FETCH_BODYTEXT][$id] + : null + ); + } + + /** + * Set envelope data. + * + * @param array $data The envelope data to pass to the Envelope object + * constructor, or an Envelope object. + */ + public function setEnvelope($data) + { + $this->_data[Horde_Imap_Client::FETCH_ENVELOPE] = is_array($data) + ? new Horde_Imap_Client_Data_Envelope($data) + : $data; + } + + /** + * Get envelope data. + * + * @return Horde_Imap_Client_Data_Envelope An envelope object. + */ + public function getEnvelope() + { + return isset($this->_data[Horde_Imap_Client::FETCH_ENVELOPE]) + ? clone $this->_data[Horde_Imap_Client::FETCH_ENVELOPE] + : new Horde_Imap_Client_Data_Envelope(); + } + + /** + * Set IMAP flags. + * + * @param array $flags An array of IMAP flags. + */ + public function setFlags(array $flags) + { + $this->_data[Horde_Imap_Client::FETCH_FLAGS] = array_map( + 'Horde_String::lower', + array_map('trim', $flags) + ); + } + + /** + * Get IMAP flags. + * + * @return array An array of IMAP flags (all flags in lowercase). + */ + public function getFlags() + { + return isset($this->_data[Horde_Imap_Client::FETCH_FLAGS]) + ? $this->_data[Horde_Imap_Client::FETCH_FLAGS] + : array(); + } + + /** + * Set IMAP internal date. + * + * @param mixed $date Either a Horde_Imap_Client_DateTime object or a + * date string. + */ + public function setImapDate($date) + { + $this->_data[Horde_Imap_Client::FETCH_IMAPDATE] = is_object($date) + ? $date + : new Horde_Imap_Client_DateTime($date); + } + + /** + * Get internal IMAP date. + * + * @return Horde_Imap_Client_DateTime A date object. + */ + public function getImapDate() + { + return isset($this->_data[Horde_Imap_Client::FETCH_IMAPDATE]) + ? clone $this->_data[Horde_Imap_Client::FETCH_IMAPDATE] + : new Horde_Imap_Client_DateTime(); + } + + /** + * Set message size. + * + * @param integer $size The size of the message, in bytes. + */ + public function setSize($size) + { + $this->_data[Horde_Imap_Client::FETCH_SIZE] = intval($size); + } + + /** + * Get message size. + * + * @return integer The size of the message, in bytes. + */ + public function getSize() + { + return isset($this->_data[Horde_Imap_Client::FETCH_SIZE]) + ? $this->_data[Horde_Imap_Client::FETCH_SIZE] + : 0; + } + + /** + * Set UID. + * + * @param integer $uid The message UID. + */ + public function setUid($uid) + { + $this->_data[Horde_Imap_Client::FETCH_UID] = intval($uid); + } + + /** + * Get UID. + * + * @return integer The message UID. + */ + public function getUid() + { + return isset($this->_data[Horde_Imap_Client::FETCH_UID]) + ? $this->_data[Horde_Imap_Client::FETCH_UID] + : null; + } + + /** + * Set message sequence number. + * + * @param integer $seq The message sequence number. + */ + public function setSeq($seq) + { + $this->_data[Horde_Imap_Client::FETCH_SEQ] = intval($seq); + } + + /** + * Get message sequence number. + * + * @return integer The message sequence number. + */ + public function getSeq() + { + return isset($this->_data[Horde_Imap_Client::FETCH_SEQ]) + ? $this->_data[Horde_Imap_Client::FETCH_SEQ] + : null; + } + + /** + * Set the modified sequence value for the message. + * + * @param integer $modseq The modseq value. + */ + public function setModSeq($modseq) + { + $this->_data[Horde_Imap_Client::FETCH_MODSEQ] = intval($modseq); + } + + /** + * Get the modified sequence value for the message. + * + * @return integer The modseq value. + */ + public function getModSeq() + { + return isset($this->_data[Horde_Imap_Client::FETCH_MODSEQ]) + ? $this->_data[Horde_Imap_Client::FETCH_MODSEQ] + : null; + } + + /** + * Set the internationalized downgraded status for the message. + * + * @since 2.11.0 + * + * @param boolean $downgraded True if at least one message component has + * been downgraded. + */ + public function setDowngraded($downgraded) + { + if ($downgraded) { + $this->_data[Horde_Imap_Client::FETCH_DOWNGRADED] = true; + } else { + unset($this->_data[Horde_Imap_Client::FETCH_DOWNGRADED]); + } + } + + /** + * Does the message contain internationalized downgraded data (i.e. it + * is a "surrogate" message)? + * + * @since 2.11.0 + * + * @return boolean True if at least one message components has been + * downgraded. + */ + public function isDowngraded() + { + return !empty($this->_data[Horde_Imap_Client::FETCH_DOWNGRADED]); + } + + /** + * Return the internal representation of the data. + * + * @return array The data array. + */ + public function getRawData() + { + return $this->_data; + } + + /** + * Merge a fetch object into this one. + * + * @param Horde_Imap_Client_Data_Fetch $data A fetch object. + */ + public function merge(Horde_Imap_Client_Data_Fetch $data) + { + $this->_data = array_replace_recursive( + $this->_data, + $data->getRawData() + ); + } + + /** + * Does this object containing cacheable data of the given type? + * + * @param integer $type The type to query. + * + * @return boolean True if the type is cacheable. + */ + public function exists($type) + { + return isset($this->_data[$type]); + } + + /** + * Does this object contain only default values for all fields? + * + * @return boolean True if object contains default data. + */ + public function isDefault() + { + return empty($this->_data); + } + + /** + * Return text representation of a field. + * + * @param boolean $stream Return as a stream? + * @param mixed $data The field data (string or resource) or null if + * field does not exist. + * + * @return mixed Requested text representation. + */ + protected function _msgText($stream, $data) + { + if ($data instanceof Horde_Stream) { + if ($stream) { + $data->rewind(); + return $data->stream; + } + return strval($data); + } + + if (is_resource($data)) { + rewind($data); + return $stream + ? $data + : stream_get_contents($data); + } + + if (!$stream) { + return strval($data); + } + + $tmp = fopen('php://temp', 'w+'); + + if (!is_null($data)) { + fwrite($tmp, $data); + rewind($tmp); + } + + return $tmp; + } + + /** + * Return representation of a header field. + * + * @param string $id The header id. + * @param integer $format The return format. If self::HEADER_PARSE, + * returns a Horde_Mime_Headers object. If + * self::HEADER_STREAM, returns a stream. + * Otherwise, returns header text. + * @param integer $key The array key where the data is stored in the + * internal array. + * + * @return mixed The data in the format specified by $format. + */ + protected function _getHeaders($id, $format, $key) + { + switch ($format) { + case self::HEADER_STREAM: + if (!isset($this->_data[$key][$id])) { + $data = null; + } elseif (is_object($this->_data[$key][$id])) { + switch ($key) { + case Horde_Imap_Client::FETCH_HEADERS: + $data = $this->_getHeaders($id, 0, $key); + break; + + case Horde_Imap_Client::FETCH_HEADERTEXT: + case Horde_Imap_Client::FETCH_MIMEHEADER: + $data = $this->_data[$key][$id]; + break; + } + } else { + $data = $this->_data[$key][$id]; + } + + return $this->_msgText(true, $data); + + case self::HEADER_PARSE: + if (!isset($this->_data[$key][$id])) { + return new Horde_Mime_Headers(); + } elseif (is_object($this->_data[$key][$id])) { + switch ($key) { + case Horde_Imap_Client::FETCH_HEADERS: + return clone $this->_data[$key][$id]; + + case Horde_Imap_Client::FETCH_HEADERTEXT: + case Horde_Imap_Client::FETCH_MIMEHEADER: + $hdrs = $this->_data[$key][$id]; + break; + } + } else { + $hdrs = $this->_getHeaders($id, self::HEADER_STREAM, $key); + } + + return Horde_Mime_Headers::parseHeaders($hdrs); + } + + if (!isset($this->_data[$key][$id])) { + return ''; + } + + if (is_object($this->_data[$key][$id])) { + switch ($key) { + case Horde_Imap_Client::FETCH_HEADERS: + return $this->_data[$key][$id]->toString( + array('nowrap' => true) + ); + + case Horde_Imap_Client::FETCH_HEADERTEXT: + case Horde_Imap_Client::FETCH_MIMEHEADER: + return strval($this->_data[$key][$id]); + } + } + + return $this->_msgText(false, $this->_data[$key][$id]); + } + + /** + * Converts mixed input (string or resource) to the correct internal + * representation. + * + * @param mixed $data Mixed data (string, resource, Horde_Stream object). + * + * @return mixed The internal representation of that data. + */ + protected function _setMixed($data) + { + return is_resource($data) + ? new Horde_Stream_Existing(array('stream' => $data)) + : $data; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Fetch/Pop3.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Fetch/Pop3.php new file mode 100644 index 00000000..500de384 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Fetch/Pop3.php @@ -0,0 +1,36 @@ + + * @category Horde + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Fetch_Pop3 extends Horde_Imap_Client_Data_Fetch +{ + /** + * Set UID. + * + * @param string $uid The message UID. Unlike IMAP, this UID does not + * have to be an integer. + */ + public function setUid($uid) + { + $this->_data[Horde_Imap_Client::FETCH_UID] = strval($uid); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format.php new file mode 100644 index 00000000..e3cf3123 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format.php @@ -0,0 +1,83 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format +{ + /** + * Data. + * + * @var mixed + */ + protected $_data; + + /** + * Constructor. + * + * @param mixed $data Data. + */ + public function __construct($data) + { + $this->_data = is_resource($data) + ? stream_get_contents($data, -1, 0) + : $data; + } + + /** + * Returns the string value of the raw data. + * + * @return string String value. + */ + public function __toString() + { + return strval($this->_data); + } + + /** + * Returns the raw data. + * + * @return mixed Raw data. + */ + public function getData() + { + return $this->_data; + } + + /** + * Returns the data formatted for output to the IMAP server. + * + * @return string IMAP escaped string. + */ + public function escape() + { + return strval($this); + } + + /** + * Verify the data. + * + * @throws Horde_Imap_Client_Data_Format_Exception + */ + public function verify() + { + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Astring.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Astring.php new file mode 100644 index 00000000..5695c7cd --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Astring.php @@ -0,0 +1,32 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_Astring extends Horde_Imap_Client_Data_Format_String +{ + /** + */ + public function quoted() + { + return $this->_filter->quoted || !$this->_data->length(); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Astring/Nonascii.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Astring/Nonascii.php new file mode 100644 index 00000000..7741b42c --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Astring/Nonascii.php @@ -0,0 +1,28 @@ + + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.25.0 + */ +class Horde_Imap_Client_Data_Format_Astring_Nonascii +extends Horde_Imap_Client_Data_Format_Astring +implements Horde_Imap_Client_Data_Format_String_Support_Nonascii +{ +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Atom.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Atom.php new file mode 100644 index 00000000..2575a7e6 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Atom.php @@ -0,0 +1,57 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_Atom extends Horde_Imap_Client_Data_Format +{ + /** + */ + public function escape() + { + return strlen($this->_data) + ? parent::escape() + : '""'; + } + + /** + */ + public function verify() + { + if (strlen($this->_data) !== strlen($this->stripNonAtomCharacters())) { + throw new Horde_Imap_Client_Data_Format_Exception('Illegal character in IMAP atom.'); + } + } + + /** + * Strip out any characters that are not allowed in an IMAP atom. + * + * @return string The atom data disallowed characters removed. + */ + public function stripNonAtomCharacters() + { + return str_replace( + array('(', ')', '{', ' ', '%', '*', '"', '\\', ']'), + '', + preg_replace('/[^\x20-\x7e]/', '', $this->_data) + ); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Date.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Date.php new file mode 100644 index 00000000..ee223877 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Date.php @@ -0,0 +1,49 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_Date extends Horde_Imap_Client_Data_Format +{ + /** + * Constructor. + * + * @param mixed $data Either a DateTime object, or a date format that + * can be converted to a DateTime object. + * + * @throws Exception + */ + public function __construct($data) + { + if (!($data instanceof DateTime)) { + $data = new Horde_Imap_Client_DateTime($data); + } + + parent::__construct($data); + } + + /** + */ + public function __toString() + { + return $this->_data->format('j-M-Y'); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/DateTime.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/DateTime.php new file mode 100644 index 00000000..5553f01a --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/DateTime.php @@ -0,0 +1,39 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_DateTime extends Horde_Imap_Client_Data_Format_Date +{ + /** + */ + public function __toString() + { + return $this->_data->format('j-M-Y H:i:s O'); + } + + /** + */ + public function escape() + { + return '"' . strval($this) . '"'; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Exception.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Exception.php new file mode 100644 index 00000000..1bc89fcb --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Exception.php @@ -0,0 +1,25 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_Exception extends Horde_Exception_Wrapped +{ +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Filter/Quote.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Filter/Quote.php new file mode 100644 index 00000000..7b0026eb --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Filter/Quote.php @@ -0,0 +1,64 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_Filter_Quote extends php_user_filter +{ + /** + * Has the initial quote been prepended? + * + * @var boolean + */ + protected $_prepend; + + /** + */ + public function onCreate() + { + $this->_prepend = false; + } + + /** + * @see stream_filter_register() + */ + public function filter($in, $out, &$consumed, $closing) + { + if (!$this->_prepend) { + stream_bucket_append($out, stream_bucket_new($this->stream, '"')); + $this->_prepend = true; + } + + while ($bucket = stream_bucket_make_writeable($in)) { + $consumed += $bucket->datalen; + $bucket->data = addcslashes($bucket->data, '"\\'); + stream_bucket_append($out, $bucket); + } + + /* feof() call needed due to: + * http://news.php.net/php.internals/80363 */ + if ($closing || feof($this->stream)) { + stream_bucket_append($out, stream_bucket_new($this->stream, '"')); + } + + return PSFS_PASS_ON; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Filter/String.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Filter/String.php new file mode 100644 index 00000000..e608343e --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Filter/String.php @@ -0,0 +1,120 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_Filter_String extends php_user_filter +{ + /** + * Skip status. + * + * @var boolean + */ + protected $_skip = false; + + /** + * @see stream_filter_register() + */ + public function onCreate() + { + $this->params->binary = false; + $this->params->literal = false; + $this->params->nonascii = false; + // no_quote_list is used below as a config option + $this->params->quoted = false; + + return true; + } + + /** + * @see stream_filter_register() + */ + public function filter($in, $out, &$consumed, $closing) + { + $p = $this->params; + + while ($bucket = stream_bucket_make_writeable($in)) { + if (!$this->_skip) { + $len = $bucket->datalen; + $str = $bucket->data; + + for ($i = 0; $i < $len; ++$i) { + $chr = ord($str[$i]); + + switch ($chr) { + case 0: // null + $p->binary = true; + $p->literal = true; + + // No need to scan input anymore. + $this->_skip = true; + break 2; + + case 10: // LF + case 13: // CR + $p->literal = true; + break; + + case 32: // SPACE + case 34: // " + case 40: // ( + case 41: // ) + case 92: // \ + case 123: // { + case 127: // DEL + // These are all invalid ATOM characters. + $p->quoted = true; + break; + + case 37: // % + case 42: // * + // These are not quoted if being used as wildcards. + if (empty($p->no_quote_list)) { + $p->quoted = true; + } + break; + + default: + if ($chr < 32) { + // CTL characters must be, at a minimum, quoted. + $p->quoted = true; + } elseif ($chr > 127) { + $p->nonascii = true; + // 8-bit chars must be in a literal. + $p->literal = true; + } + break; + } + } + } + + $consumed += $bucket->datalen; + stream_bucket_append($out, $bucket); + } + + if ($p->literal) { + $p->quoted = false; + } + + return PSFS_PASS_ON; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/List.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/List.php new file mode 100644 index 00000000..e0326f5e --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/List.php @@ -0,0 +1,106 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_List extends Horde_Imap_Client_Data_Format implements Countable, IteratorAggregate +{ + /** + * @see add() + */ + public function __construct($data = null) + { + parent::__construct(array()); + + if (!is_null($data)) { + $this->add($data); + } + } + + /** + * Add an element to the list. + * + * @param mixed $data The data element(s) to add. Either a + * Horde_Imap_Client_Data_Format object, a string + * value that will be treated as an IMAP atom, or + * an array (or iterable object) of objects to add. + * @param boolean $merge Merge the contents of any container objects, + * instead of adding the objects themselves? + * + * @return Horde_Imap_Client_Data_Format_List This object to allow for + * chainable calls (since + * 2.10.0). + */ + public function add($data, $merge = false) + { + if (is_array($data) || ($merge && ($data instanceof Traversable))) { + foreach ($data as $val) { + $this->add($val); + } + } elseif (is_object($data)) { + $this->_data[] = $data; + } elseif (!is_null($data)) { + $this->_data[] = new Horde_Imap_Client_Data_Format_Atom($data); + } + + return $this; + } + + /** + */ + public function __toString() + { + $out = ''; + + foreach ($this as $val) { + if ($val instanceof $this) { + $out .= '(' . $val->escape() . ') '; + } elseif (($val instanceof Horde_Imap_Client_Data_Format_String) && + $val->literal()) { + /* ERROR: Requires literal output. */ + return ''; + } else { + $out .= $val->escape() . ' '; + } + } + + return rtrim($out); + } + + /* Countable methods. */ + + /** + */ + public function count() + { + return count($this->_data); + } + + /* IteratorAggregate method. */ + + /** + * Iterator loops through the data elements contained in this list. + */ + public function getIterator() + { + return new ArrayIterator($this->_data); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/ListMailbox.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/ListMailbox.php new file mode 100644 index 00000000..3f186bea --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/ListMailbox.php @@ -0,0 +1,38 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_ListMailbox +extends Horde_Imap_Client_Data_Format_Mailbox +{ + /** + */ + protected function _filterParams() + { + $ob = parent::_filterParams(); + + /* Don't quote % or * characters. */ + $ob->no_quote_list = true; + + return $ob; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/ListMailbox/Utf8.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/ListMailbox/Utf8.php new file mode 100644 index 00000000..69cca6cc --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/ListMailbox/Utf8.php @@ -0,0 +1,39 @@ + + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_ListMailbox_Utf8 +extends Horde_Imap_Client_Data_Format_Mailbox_Utf8 +{ + /** + */ + protected function _filterParams() + { + $ob = parent::_filterParams(); + + /* Don't quote % or * characters. */ + $ob->no_quote_list = true; + + return $ob; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Mailbox.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Mailbox.php new file mode 100644 index 00000000..1b0620f3 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Mailbox.php @@ -0,0 +1,99 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_Mailbox +extends Horde_Imap_Client_Data_Format_Astring +{ + /** + * Mailbox encoding. + * + * @var string + */ + protected $_encoding = 'utf7imap'; + + /** + * Mailbox object. + * + * @var Horde_Imap_Client_Mailbox + */ + protected $_mailbox; + + /** + * @param mixed $data Either a mailbox object or a UTF-8 mailbox name. + */ + public function __construct($data) + { + $this->_mailbox = Horde_Imap_Client_Mailbox::get($data); + + parent::__construct($this->_mailbox->{$this->_encoding}); + } + + /** + */ + public function __toString() + { + return strval($this->_mailbox); + } + + /** + */ + public function getData() + { + return $this->_mailbox; + } + + /** + * @throws Horde_Imap_Client_Exception + */ + public function binary() + { + if (parent::binary()) { + // Mailbox data can NEVER be sent as binary. + /* @todo: Disable until Horde_Imap_Client 3.0 */ + // throw new Horde_Imap_Client_Exception( + // 'Client error: can not send mailbox to IMAP server as binary data.' + // ); + + // Temporary fix: send a blank mailbox string. + $this->_mailbox = Horde_Imap_Client_Mailbox::get(''); + } + + return false; + } + + /** + */ + public function length() + { + return strlen($this->_mailbox->{$this->_encoding}); + } + + /** + */ + public function getStream() + { + $stream = new Horde_Stream_Temp(); + $stream->add($this->_mailbox->{$this->_encoding}); + return $stream; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Mailbox/Utf8.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Mailbox/Utf8.php new file mode 100644 index 00000000..9b8c95b6 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Mailbox/Utf8.php @@ -0,0 +1,57 @@ + + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_Mailbox_Utf8 +extends Horde_Imap_Client_Data_Format_Mailbox +implements Horde_Imap_Client_Data_Format_String_Support_Nonascii +{ + /** + */ + protected $_encoding = 'utf8'; + + /** + */ + public function __construct($data) + { + parent::__construct($data); + + /* RFC 3501 allows any US-ASCII character, except null (\0), in + * mailbox data. + * RFC 6855 [3] institutes additional limitations on valid mailbox + * characters, to comply with RFC 5198 [2] (Net-Unicode Definition): + * "MUST NOT contain control characters (U+0000-U+001F and + * U+0080-U+009F), a delete character (U+007F), a line separator + * (U+2028), or a paragraph separator (U+2029)." */ + if ($this->quoted() && + preg_match('/[\x00-\x1f\x7f\x80-\x9f\x{2028}\x{2029}]/u', strval($this))) { + throw new Horde_Imap_Client_Data_Format_Exception( + 'Invalid character found in mailbox data.' + ); + } + + if ($this->literal()) { + $this->forceQuoted(); + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nil.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nil.php new file mode 100644 index 00000000..4a69d8aa --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nil.php @@ -0,0 +1,46 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_Nil extends Horde_Imap_Client_Data_Format +{ + /** + */ + public function __construct($data = null) + { + // Don't store any data in object. + } + + /** + */ + public function __toString() + { + return ''; + } + + /** + */ + public function escape() + { + return 'NIL'; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nstring.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nstring.php new file mode 100644 index 00000000..58048bca --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nstring.php @@ -0,0 +1,93 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_Nstring extends Horde_Imap_Client_Data_Format_String +{ + /** + */ + public function __construct($data = null) + { + /* Data can be null (NIL) here. */ + if (is_null($data)) { + $this->_data = null; + } else { + parent::__construct($data); + } + } + + /** + */ + public function __toString() + { + return is_null($this->_data) + ? '' + : parent::__toString(); + } + + /** + */ + public function escape() + { + return is_null($this->_data) + ? 'NIL' + : parent::escape(); + } + + public function escapeStream() + { + if (is_null($this->_data)) { + $stream = new Horde_Stream_Temp(); + $stream->add('NIL', true); + return $stream->stream; + } + + return parent::escapeStream(); + } + + /** + */ + public function quoted() + { + return is_null($this->_data) + ? false + : parent::quoted(); + } + + /** + */ + public function length() + { + return is_null($this->_data) + ? 0 + : parent::length(); + } + + /** + */ + public function getStream() + { + return is_null($this->_data) + ? new Horde_Stream_Temp() + : parent::getStream(); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nstring/Nonascii.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nstring/Nonascii.php new file mode 100644 index 00000000..1d47f0f5 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Nstring/Nonascii.php @@ -0,0 +1,28 @@ + + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.25.0 + */ +class Horde_Imap_Client_Data_Format_Nstring_Nonascii +extends Horde_Imap_Client_Data_Format_Nstring +implements Horde_Imap_Client_Data_Format_String_Support_Nonascii +{ +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Number.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Number.php new file mode 100644 index 00000000..dc33f4be --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/Number.php @@ -0,0 +1,41 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_Number extends Horde_Imap_Client_Data_Format +{ + /** + */ + public function __toString() + { + return strval(intval($this->_data)); + } + + /** + */ + public function verify() + { + if (!is_numeric($this->_data)) { + throw new Horde_Imap_Client_Data_Format_Exception('Illegal character in IMAP number.'); + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String.php new file mode 100644 index 00000000..927a3944 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String.php @@ -0,0 +1,219 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Format_String +extends Horde_Imap_Client_Data_Format +{ + /** + * String filter parameters. + * + * @var string + */ + protected $_filter; + + /** + * @param array $opts Additional options: + * - eol: (boolean) If true, normalize EOLs in input. @since 2.2.0 + * - skipscan: (boolean) If true, don't scan input for + * binary/literal/quoted data. @since 2.2.0 + * + * @throws Horde_Imap_Client_Data_Format_Exception + */ + public function __construct($data, array $opts = array()) + { + /* String data is stored in a stream. */ + $this->_data = new Horde_Stream_Temp(); + + if (empty($opts['skipscan'])) { + $this->_filter = $this->_filterParams(); + stream_filter_register('horde_imap_client_string', 'Horde_Imap_Client_Data_Format_Filter_String'); + $res = stream_filter_append($this->_data->stream, 'horde_imap_client_string', STREAM_FILTER_WRITE, $this->_filter); + } else { + $res = null; + } + + if (empty($opts['eol'])) { + $res2 = null; + } else { + stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol'); + $res2 = stream_filter_append($this->_data->stream, 'horde_eol', STREAM_FILTER_WRITE); + } + + $this->_data->add($data); + + if (!is_null($res)) { + stream_filter_remove($res); + } + if (!is_null($res2)) { + stream_filter_remove($res2); + } + + if (isset($this->_filter) && + $this->_filter->nonascii && + !($this instanceof Horde_Imap_Client_Data_Format_String_Support_Nonascii)) { + throw new Horde_Imap_Client_Data_Format_Exception( + 'String contains non-ASCII characters.' + ); + } + } + + /** + * Return the base string filter parameters. + * + * @return object Filter parameters. + */ + protected function _filterParams() + { + return new stdClass; + } + + /** + */ + public function __toString() + { + return $this->_data->getString(0); + } + + /** + */ + public function escape() + { + if ($this->literal()) { + throw new Horde_Imap_Client_Data_Format_Exception('String requires literal to output.'); + } + + return $this->quoted() + ? stream_get_contents($this->escapeStream()) + : $this->_data->getString(0); + } + + /** + * Return the escaped string as a stream. + * + * @return resource The IMAP escaped stream. + */ + public function escapeStream() + { + if ($this->literal()) { + throw new Horde_Imap_Client_Data_Format_Exception('String requires literal to output.'); + } + + rewind($this->_data->stream); + + $stream = new Horde_Stream_Temp(); + $stream->add($this->_data, true); + + stream_filter_register('horde_imap_client_string_quote', 'Horde_Imap_Client_Data_Format_Filter_Quote'); + stream_filter_append($stream->stream, 'horde_imap_client_string_quote', STREAM_FILTER_READ); + + return $stream->stream; + } + + /** + * Does this data item require quoted string output? + * + * @return boolean True if quoted output is required. + */ + public function quoted() + { + /* IMAP strings MUST be quoted if they are not a literal. */ + return (!isset($this->_filter) || !$this->_filter->literal); + } + + /** + * Force item to be output quoted. + */ + public function forceQuoted() + { + $this->_filter = $this->_filterParams(); + $this->_filter->binary = false; + $this->_filter->literal = false; + $this->_filter->quoted = true; + } + + /** + * Does this data item require literal string output? + * + * @return boolean True if literal output is required. + */ + public function literal() + { + return (isset($this->_filter) && $this->_filter->literal); + } + + /** + * Force item to be output as a literal. + */ + public function forceLiteral() + { + $this->_filter = $this->_filterParams(); + // Keep binary status, if set + $this->_filter->literal = true; + $this->_filter->quoted = false; + } + + /** + * If literal output, is the data binary? + * + * @return boolean True if the literal output is binary. + */ + public function binary() + { + return (isset($this->_filter) && !empty($this->_filter->binary)); + } + + /** + * Force item to be output as a binary literal. + */ + public function forceBinary() + { + $this->_filter = $this->_filterParams(); + $this->_filter->binary = true; + $this->_filter->literal = true; + $this->_filter->quoted = false; + } + + /** + * Return the length of the data. + * + * @since 2.2.0 + * + * @return integer Data length. + */ + public function length() + { + return $this->_data->length(); + } + + /** + * Return the contents of the string as a stream object. + * + * @since 2.3.0 + * + * @return Horde_Stream The stream object. + */ + public function getStream() + { + return $this->_data; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String/Nonascii.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String/Nonascii.php new file mode 100644 index 00000000..1150b648 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String/Nonascii.php @@ -0,0 +1,28 @@ + + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.25.0 + */ +class Horde_Imap_Client_Data_Format_String_Nonascii +extends Horde_Imap_Client_Data_Format_String +implements Horde_Imap_Client_Data_Format_String_Support_Nonascii +{ +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String/Support/Nonascii.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String/Support/Nonascii.php new file mode 100644 index 00000000..0db89bae --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Format/String/Support/Nonascii.php @@ -0,0 +1,27 @@ + + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.25.0 + */ +interface Horde_Imap_Client_Data_Format_String_Support_Nonascii +{ +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Namespace.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Namespace.php new file mode 100644 index 00000000..242293d8 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Namespace.php @@ -0,0 +1,143 @@ + + * @category Horde + * @copyright 2013-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.21.0 + * + * @property-read string $base The namespace base ($name without trailing + * delimiter) (UTF-8). + * @property string $delimiter The namespace delimiter. + * @property boolean $hidden Is this a hidden namespace? + * @property string $name The namespace name (UTF-8). + * @property string $translation Returns the translated name of the namespace + * (UTF-8). + * @property integer $type The namespace type. Either self::NS_PERSONAL, + * self::NS_OTHER, or self::NS_SHARED. + */ +class Horde_Imap_Client_Data_Namespace implements Serializable +{ + /* Namespace type constants. */ + const NS_PERSONAL = 1; + const NS_OTHER = 2; + const NS_SHARED = 3; + + /** + * Data object. + * + * @var array + */ + protected $_data = array(); + + /** + * Strips namespace information from the given mailbox name. + * + * @param string $mbox Mailbox name. + * + * @return string Mailbox name with namespace prefix stripped. + */ + public function stripNamespace($mbox) + { + $mbox = strval($mbox); + $name = $this->name; + + return (strlen($name) && (strpos($mbox, $name) === 0)) + ? substr($mbox, strlen($name)) + : $mbox; + } + + /** + */ + public function __get($name) + { + if (isset($this->_data[$name])) { + return $this->_data[$name]; + } + + switch ($name) { + case 'base': + return rtrim($this->name, $this->delimiter); + + case 'delimiter': + case 'name': + case 'translation': + return ''; + + case 'hidden': + return false; + + case 'type': + return self::NS_PERSONAL; + } + + return null; + } + + /** + */ + public function __set($name, $value) + { + switch ($name) { + case 'delimiter': + case 'name': + case 'translation': + $this->_data[$name] = strval($value); + break; + + case 'hidden': + $this->_data[$name] = (bool)$value; + break; + + case 'type': + $this->_data[$name] = intval($value); + break; + } + } + + /** + */ + public function __isset($name) + { + return isset($this->_data[$name]); + } + + /** + */ + public function __toString() + { + return $this->name; + } + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + return json_encode($this->_data); + } + + /** + */ + public function unserialize($data) + { + $this->_data = json_decode($data, true); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/SearchCharset.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/SearchCharset.php new file mode 100644 index 00000000..554284b6 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/SearchCharset.php @@ -0,0 +1,178 @@ + + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.24.0 + * + * @property-read array $charsets The list of valid charsets that have been + * discovered on the server. + */ +class Horde_Imap_Client_Data_SearchCharset +implements Serializable, SplSubject +{ + /** + * Base client object. + * + * @var Horde_Imap_Client_Base + */ + protected $_baseob; + + /** + * Charset data. + * + * @var array + */ + protected $_charsets = array( + 'US-ASCII' => true + ); + + /** + * Observers. + * + * @var array + */ + protected $_observers = array(); + + /** + */ + public function __get($name) + { + switch ($name) { + case 'charsets': + return array_keys(array_filter($this->_charsets)); + } + } + + /** + */ + public function setBaseOb(Horde_Imap_Client_Base $ob) + { + $this->_baseob = $ob; + } + + /** + * Query the validity of a charset. + * + * @param string $charset The charset to query. + * @param boolean $cached If true, only query cached values. + * + * @return boolean True if the charset is valid for searching. + */ + public function query($charset, $cached = false) + { + $charset = Horde_String::upper($charset); + + if (isset($this->_charsets[$charset])) { + return $this->_charsets[$charset]; + } elseif ($cached) { + return null; + } + + if (!$this->_baseob) { + throw new RuntimeException( + 'Base object needs to be defined to query for charset.' + ); + } + + /* Use a dummy search query and search for BADCHARSET response. */ + $query = new Horde_Imap_Client_Search_Query(); + $query->charset($charset, false); + $query->ids($this->_baseob->getIdsOb(1, true)); + $query->text('a'); + try { + $this->_baseob->search('INBOX', $query, array( + 'nocache' => true, + 'sequence' => true + )); + $this->_charsets[$charset] = true; + } catch (Horde_Imap_Client_Exception $e) { + $this->_charsets[$charset] = ($e->getCode() !== Horde_Imap_Client_Exception::BADCHARSET); + } + + $this->notify(); + + return $this->_charsets[$charset]; + } + + /** + * Set the validity of a given charset. + * + * @param string $charset The charset. + * @param boolean $valid Is charset valid? + */ + public function setValid($charset, $valid = true) + { + $charset = Horde_String::upper($charset); + $valid = (bool)$valid; + + if (!isset($this->_charsets[$charset]) || + ($this->_charsets[$charset] !== $valid)) { + $this->_charsets[$charset] = $valid; + $this->notify(); + } + } + + /* SplSubject methods. */ + + /** + */ + public function attach(SplObserver $observer) + { + $this->detach($observer); + $this->_observers[] = $observer; + } + + /** + */ + public function detach(SplObserver $observer) + { + if (($key = array_search($observer, $this->_observers, true)) !== false) { + unset($this->_observers[$key]); + } + } + + /** + * Notification is triggered internally whenever the object's internal + * data storage is altered. + */ + public function notify() + { + foreach ($this->_observers as $val) { + $val->update($this); + } + } + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + return json_encode($this->_charsets); + } + + /** + */ + public function unserialize($data) + { + $this->_charsets = json_decode($data, true); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/SearchCharset/Utf8.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/SearchCharset/Utf8.php new file mode 100644 index 00000000..a6851c0f --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/SearchCharset/Utf8.php @@ -0,0 +1,66 @@ + + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.24.0 + */ +class Horde_Imap_Client_Data_SearchCharset_Utf8 +extends Horde_Imap_Client_Data_SearchCharset +{ + /** + * Charset data. + * + * @var array + */ + protected $_charsets = array( + 'US-ASCII' => true, + 'UTF-8' => true + ); + + /** + */ + public function query($charset, $cached = false) + { + return isset($this->_charsets[Horde_String::upper($charset)]); + } + + /** + */ + public function setValid($charset, $valid = true) + { + } + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + return ''; + } + + /** + */ + public function unserialize($data) + { + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Sync.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Sync.php new file mode 100644 index 00000000..701ab71c --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Sync.php @@ -0,0 +1,267 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.2.0 + * + * @property-read Horde_Imap_Client_Ids $flagsuids List of messages with flag + * changes. + * @property-read Horde_Imap_Client_Ids $newmsgsuids List of new messages. + * @property-read Horde_Imap_Client_Ids $vanisheduids List of messages that + * have vanished. + */ +class Horde_Imap_Client_Data_Sync +{ + /** + * Mappings of status() values to sync keys. + * + * @since 2.8.0 + * + * @var array + */ + public static $map = array( + 'H' => 'highestmodseq', + 'M' => 'messages', + 'U' => 'uidnext', + 'V' => 'uidvalidity' + ); + + /** + * Are there messages that have had flag changes? + * + * @var boolean + */ + public $flags = null; + + /** + * The previous value of HIGHESTMODSEQ. + * + * @since 2.8.0 + * + * @var integer + */ + public $highestmodseq = null; + + /** + * The synchronized mailbox. + * + * @var Horde_Imap_Client_Mailbox + */ + public $mailbox; + + /** + * The previous number of messages in the mailbox. + * + * @since 2.8.0 + * + * @var integer + */ + public $messages = null; + + /** + * Are there new messages? + * + * @var boolean + */ + public $newmsgs = null; + + /** + * The previous value of UIDNEXT. + * + * @since 2.8.0 + * + * @var integer + */ + public $uidnext = null; + + /** + * The previous value of UIDVALIDITY. + * + * @since 2.8.0 + * + * @var integer + */ + public $uidvalidity = null; + + /** + * The UIDs of messages that are guaranteed to have vanished. This list is + * only guaranteed to be available if the server supports QRESYNC or a + * list of known UIDs is passed to the sync() method. + * + * @var Horde_Imap_Client_Ids + */ + public $vanished = null; + + /** + * UIDs of messages that have had flag changes. + * + * @var Horde_Imap_Client_Ids + */ + protected $_flagsuids; + + /** + * UIDs of new messages. + * + * @var Horde_Imap_Client_Ids + */ + protected $_newmsgsuids; + + /** + * UIDs of messages that have vanished. + * + * @var Horde_Imap_Client_Ids + */ + protected $_vanisheduids; + + /** + * Constructor. + * + * @param Horde_Imap_Client_Base $base_ob Base driver object. + * @param mixed $mailbox Mailbox to sync. + * @param array $sync Token sync data. + * @param array $curr Current sync data. + * @param integer $criteria Mask of criteria to return. + * @param Horde_Imap_Client_Ids $ids List of known UIDs. + * + * @throws Horde_Imap_Client_Exception + * @throws Horde_Imap_Client_Exception_Sync + */ + public function __construct(Horde_Imap_Client_Base $base_ob, $mailbox, + $sync, $curr, $criteria, $ids) + { + foreach (self::$map as $key => $val) { + if (isset($sync[$key])) { + $this->$val = $sync[$key]; + } + } + + /* Check uidvalidity. */ + if (!$this->uidvalidity || ($curr['V'] != $this->uidvalidity)) { + throw new Horde_Imap_Client_Exception_Sync('UIDs in cached mailbox have changed.', Horde_Imap_Client_Exception_Sync::UIDVALIDITY_CHANGED); + } + + $this->mailbox = $mailbox; + + /* This was a UIDVALIDITY check only. */ + if (!$criteria) { + return; + } + + $sync_all = ($criteria & Horde_Imap_Client::SYNC_ALL); + + /* New messages. */ + if ($sync_all || + ($criteria & Horde_Imap_Client::SYNC_NEWMSGS) || + ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS)) { + $this->newmsgs = empty($this->uidnext) + ? !empty($curr['U']) + : (!empty($curr['U']) && ($curr['U'] > $this->uidnext)); + + if ($this->newmsgs && + ($sync_all || + ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS))) { + $new_ids = empty($this->uidnext) + ? Horde_Imap_Client_Ids::ALL + : ($this->uidnext . ':' . $curr['U']); + + $squery = new Horde_Imap_Client_Search_Query(); + $squery->ids(new Horde_Imap_Client_Ids($new_ids)); + $sres = $base_ob->search($mailbox, $squery); + + $this->_newmsgsuids = $sres['match']; + } + } + + /* Do single status call to get all necessary data. */ + if ($this->highestmodseq && + ($sync_all || + ($criteria & Horde_Imap_Client::SYNC_FLAGS) || + ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS) || + ($criteria & Horde_Imap_Client::SYNC_VANISHED) || + ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS))) { + $status_sync = $base_ob->status($mailbox, Horde_Imap_Client::STATUS_SYNCMODSEQ | Horde_Imap_Client::STATUS_SYNCFLAGUIDS | Horde_Imap_Client::STATUS_SYNCVANISHED); + + if (!is_null($ids)) { + $ids = $base_ob->resolveIds($mailbox, $ids); + } + } + + /* Flag changes. */ + if ($sync_all || ($criteria & Horde_Imap_Client::SYNC_FLAGS)) { + $this->flags = $this->highestmodseq + ? ($this->highestmodseq != $curr['H']) + : true; + } + + if ($sync_all || ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS)) { + if ($this->highestmodseq) { + if ($this->highestmodseq == $status_sync['syncmodseq']) { + $this->_flagsuids = is_null($ids) + ? $status_sync['syncflaguids'] + : $base_ob->getIdsOb(array_intersect($ids->ids, $status_sync['syncflaguids']->ids)); + } else { + $squery = new Horde_Imap_Client_Search_Query(); + $squery->modseq($this->highestmodseq + 1); + $sres = $base_ob->search($mailbox, $squery, array( + 'ids' => $ids + )); + $this->_flagsuids = $sres['match']; + } + } else { + /* Without MODSEQ, need to mark all FLAGS as changed. */ + $this->_flagsuids = $base_ob->resolveIds($mailbox, is_null($ids) ? $base_ob->getIdsOb(Horde_Imap_Client_Ids::ALL) : $ids); + } + } + + /* Vanished messages. */ + if ($sync_all || + ($criteria & Horde_Imap_Client::SYNC_VANISHED) || + ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS)) { + if ($this->highestmodseq && + ($this->highestmodseq == $status_sync['syncmodseq'])) { + $vanished = is_null($ids) + ? $status_sync['syncvanished'] + : $base_ob->getIdsOb(array_intersect($ids->ids, $status_sync['syncvanished']->ids)); + } else { + $vanished = $base_ob->vanished($mailbox, $this->highestmodseq ? $this->highestmodseq : 1, array( + 'ids' => $ids + )); + } + + $this->vanished = (bool)count($vanished); + $this->_vanisheduids = $vanished; + } + } + + /** + */ + public function __get($name) + { + switch ($name) { + case 'flagsuids': + case 'newmsgsuids': + case 'vanisheduids': + return empty($this->{'_' . $name}) + ? new Horde_Imap_Client_Ids() + : $this->{'_' . $name}; + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Thread.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Thread.php new file mode 100644 index 00000000..b487f6fc --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Data/Thread.php @@ -0,0 +1,216 @@ + + * @category Horde + * @copyright 2008-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Data_Thread implements Countable, Serializable +{ + /** + * Internal thread data structure. Keys are base values, values are arrays + * with keys as the ID and values as the level. + * + * @var array + */ + protected $_thread = array(); + + /** + * The index type. + * + * @var string + */ + protected $_type; + + /** + * Constructor. + * + * @param array $data See $_thread. + * @param string $type Either 'sequence' or 'uid'. + */ + public function __construct($data, $type) + { + $this->_thread = $data; + $this->_type = $type; + } + + /** + * Return the ID type. + * + * @return string Either 'sequence' or 'uid'. + */ + public function getType() + { + return $this->_type; + } + + /** + * Return the sorted list of messages indices. + * + * @return Horde_Imap_Client_Ids The sorted list of messages. + */ + public function messageList() + { + return new Horde_Imap_Client_Ids($this->_getAllIndices(), $this->getType() == 'sequence'); + } + + /** + * Returns the list of messages in a thread. + * + * @param integer $index An index contained in the thread. + * + * @return array Keys are indices, values are objects with the following + * properties: + * - base: (integer) Base ID of the thread. If null, thread is a single + * message. + * - last: (boolean) If true, this is the last index in the sublevel. + * - level: (integer) The sublevel of the index. + */ + public function getThread($index) + { + foreach ($this->_thread as $v) { + if (isset($v[$index])) { + reset($v); + + $ob = new stdClass; + $ob->base = (count($v) > 1) ? key($v) : null; + $ob->last = false; + + $levels = $out = array(); + $last = 0; + + while (($v2 = current($v)) !== false) { + $k2 = key($v); + $ob2 = clone $ob; + $ob2->level = $v2; + $out[$k2] = $ob2; + + if (($last < $v2) && isset($levels[$v2])) { + $out[$levels[$v2]]->last = true; + } + $levels[$v2] = $k2; + $last = $v2; + next($v); + } + + foreach ($levels as $v) { + $out[$v]->last = true; + } + + return $out; + } + } + + return array(); + } + + /** + * Returns array of all threads. + * + * @return array Keys of thread arrays are indices, values are objects with the following + * properties: + * - base: (integer) Base ID of the thread. If null, thread is a single + * message. + * - last: (boolean) If true, this is the last index in the sublevel. + * - level: (integer) The sublevel of the index. + */ + public function getThreads() + { + $data = array(); + foreach ($this->_thread as $v) { + reset($v); + + $ob = new stdClass; + $ob->base = (count($v) > 1) ? key($v) : null; + $ob->last = false; + + $levels = $out = array(); + $last = 0; + + while (($v2 = current($v)) !== false) { + $k2 = key($v); + $ob2 = clone $ob; + $ob2->level = $v2; + $out[$k2] = $ob2; + + if (($last < $v2) && isset($levels[$v2])) { + $out[$levels[$v2]]->last = true; + } + $levels[$v2] = $k2; + $last = $v2; + next($v); + } + + foreach ($levels as $v) { + $out[$v]->last = true; + } + + $data[] = $out; + } + + return $data; + } + + /* Countable methods. */ + + /** + */ + public function count() + { + return count($this->_getAllIndices()); + } + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + return json_encode(array( + $this->_thread, + $this->_type + )); + } + + /** + */ + public function unserialize($data) + { + list($this->_thread, $this->_type) = json_decode($data, true); + } + + /* Protected methods. */ + + /** + * Return all indices. + * + * @return array An array of indices. + */ + protected function _getAllIndices() + { + $out = array(); + + foreach ($this->_thread as $val) { + $out += $val; + } + + return array_keys($out); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/DateTime.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/DateTime.php new file mode 100644 index 00000000..bc167f28 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/DateTime.php @@ -0,0 +1,119 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_DateTime extends DateTime +{ + /** + */ + public function __construct($time = null, $tz = null) + { + /* See https://bugs.php.net/bug.php?id=67118 */ + $bug_67118 = (version_compare(PHP_VERSION, '5.6', '>=')) || + in_array(PHP_VERSION, array('5.4.29', '5.5.13')); + $tz = new DateTimeZone('UTC'); + + /* Bug #14381 Catch malformed offset - which doesn't cause + DateTime to throw exception. */ + if (substr(rtrim($time), -5) === ' 0000') { + $time = substr(trim($time), 0, strlen(trim($time)) - 5) . ' +0000'; + try { + if ($bug_67118) { + new DateTime($time, $tz); + } + parent::__construct($time, $tz); + return; + } catch (Exception $e) {} + } + + try { + if ($bug_67118) { + new DateTime($time, $tz); + } + parent::__construct($time, $tz); + return; + } catch (Exception $e) {} + + /* Check for malformed day-of-week parts, usually incorrectly + * localized. E.g. Fr, 15 Apr 2016 15:15:09 +0000 */ + if (!preg_match("/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun),/", $time)) { + $time = preg_replace("/^(\S*,)/", '', $time, 1, $i); + if ($i) { + try { + if ($bug_67118) { + new DateTime($time, $tz); + } + parent::__construct($time, $tz); + return; + } catch (Exception $e) {} + } + } + + /* Bug #5717 - Check for UT vs. UTC. */ + if (substr(rtrim($time), -3) === ' UT') { + try { + if ($bug_67118) { + new DateTime($time . 'C', $tz); + } + parent::__construct($time . 'C', $tz); + return; + } catch (Exception $e) {} + } + + /* Bug #9847 - Catch paranthesized timezone information at end of date + * string. */ + $date = preg_replace("/\s*\([^\)]+\)\s*$/", '', $time, -1, $i); + if ($i) { + try { + if ($bug_67118) { + new DateTime($date, $tz); + } + parent::__construct($date, $tz); + return; + } catch (Exception $e) {} + } + + parent::__construct('@-1', $tz); + } + + /** + * String representation: UNIX timestamp. + */ + public function __toString() + { + return $this->error() + ? '0' + : strval($this->getTimestamp()); + } + + /** + * Was this an unparseable date? + * + * @return boolean True if unparseable. + */ + public function error() + { + return ($this->getTimestamp() === -1); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception.php new file mode 100644 index 00000000..024de04b --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception.php @@ -0,0 +1,303 @@ + + * @category Horde + * @copyright 2008-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Exception extends Horde_Exception_Wrapped +{ + /* Error message codes. */ + + /** + * Unspecified error (DEFAULT). + */ + const UNSPECIFIED = 0; + + /** + * There was an unrecoverable error in UTF7IMAP -> UTF8 conversion. + */ + const UTF7IMAP_CONVERSION = 3; + + /** + * The server ended the connection. + */ + const DISCONNECT = 4; + + /** + * The charset used in the search query is not supported on the + * server. */ + const BADCHARSET = 5; + + /** + * There were errors parsing the MIME/RFC 2822 header of the part. + */ + const PARSEERROR = 6; + + /** + * The server could not decode the MIME part (see RFC 3516). + */ + const UNKNOWNCTE = 7; + + /** + * The comparator specified by setComparator() was not recognized by the + * IMAP server + */ + const BADCOMPARATOR = 9; + + /** + * RFC 7162 [3.1.2.2] - All mailboxes are not required to support + * mod-sequences. + */ + const MBOXNOMODSEQ = 10; + + /** + * Thrown if server denies the network connection. + */ + const SERVER_CONNECT = 11; + + /** + * Thrown if read error for server response. + */ + const SERVER_READERROR = 12; + + /** + * Thrown if write error in server interaction. + */ + const SERVER_WRITEERROR = 16; + + /** + * Thrown on CATENATE if the URL is invalid. + */ + const CATENATE_BADURL = 13; + + /** + * Thrown on CATENATE if the message was too big. + */ + const CATENATE_TOOBIG = 14; + + /** + * Thrown on CREATE if special-use attribute is not supported. + */ + const USEATTR = 15; + + /** + * The user did not have permissions to carry out the operation. + */ + const NOPERM = 17; + + /** + * The operation was not successful because another user is holding + * a necessary resource. The operation may succeed if attempted later. + */ + const INUSE = 18; + + /** + * The operation failed because data on the server was corrupt. + */ + const CORRUPTION = 19; + + /** + * The operation failed because it exceeded some limit on the server. + */ + const LIMIT = 20; + + /** + * The operation failed because the user is over their quota. + */ + const OVERQUOTA = 21; + + /** + * The operation failed because the requested creation object already + * exists. + */ + const ALREADYEXISTS = 22; + + /** + * The operation failed because the requested deletion object did not + * exist. + */ + const NONEXISTENT = 23; + + /** + * Setting metadata failed because the size of its value is too large. + * The maximum octet count the server is willing to accept will be + * in the exception message string. + */ + const METADATA_MAXSIZE = 24; + + /** + * Setting metadata failed because the maximum number of allowed + * annotations has already been reached. + */ + const METADATA_TOOMANY = 25; + + /** + * Setting metadata failed because the server does not support private + * annotations on one of the specified mailboxes. + */ + const METADATA_NOPRIVATE = 26; + + /** + * Invalid metadata entry. + */ + const METADATA_INVALID = 27; + + + // Login failures + + /** + * Could not start mandatory TLS connection. + */ + const LOGIN_TLSFAILURE = 100; + + /** + * Could not find an available authentication method. + */ + const LOGIN_NOAUTHMETHOD = 101; + + /** + * Generic authentication failure. + */ + const LOGIN_AUTHENTICATIONFAILED = 102; + + /** + * Remote server is unavailable. + */ + const LOGIN_UNAVAILABLE = 103; + + /** + * Authentication succeeded, but authorization failed. + */ + const LOGIN_AUTHORIZATIONFAILED = 104; + + /** + * Authentication is no longer permitted with this passphrase. + */ + const LOGIN_EXPIRED = 105; + + /** + * Login requires privacy. + */ + const LOGIN_PRIVACYREQUIRED = 106; + + /** + * Server verification failed (SCRAM authentication). + */ + const LOGIN_SERVER_VERIFICATION_FAILED = 107; + + + // Mailbox access failures + + /** + * Could not open/access mailbox + */ + const MAILBOX_NOOPEN = 200; + + /** + * Could not complete the command because the mailbox is read-only + */ + const MAILBOX_READONLY = 201; + + + // POP3 specific error codes + + /** + * Temporary issue. Generally, there is no need to alarm the user for + * errors of this type. + */ + const POP3_TEMP_ERROR = 300; + + /** + * Permanent error indicated by server. + */ + const POP3_PERM_ERROR = 301; + + + // Unsupported feature error codes + + /** + * Function/feature is not supported on this server. + */ + const NOT_SUPPORTED = 400; + + + /** + * Raw error message (in English). + * + * @since 2.18.0 + * + * @var string + */ + public $raw_msg = ''; + + /** + * Constructor. + * + * @param string $message Error message (non-translated). + * @param code $code Error code. + */ + public function __construct($message = null, $code = null) + { + parent::__construct($message, $code); + + $this->raw_msg = $this->message; + try { + $this->message = Horde_Imap_Client_Translation::t($this->message); + } catch (Horde_Translation_Exception $e) {} + } + + /** + * Allow the error message to be altered. + * + * @param string $msg Error message. + */ + public function setMessage($msg) + { + $this->message = strval($msg); + } + + /** + * Allow the error code to be altered. + * + * @param integer $code Error code. + */ + public function setCode($code) + { + $this->code = intval($code); + } + + /** + * Perform substitution of variables in the error message. + * + * Needed to allow for correct translation of error message. + * + * @since 2.22.0 + * + * @param array $args Arguments used for substitution. + */ + public function messagePrintf(array $args = array()) + { + $this->raw_msg = vsprintf($this->raw_msg, $args); + $this->message = vsprintf($this->message, $args); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/NoSupportExtension.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/NoSupportExtension.php new file mode 100644 index 00000000..dc76b42f --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/NoSupportExtension.php @@ -0,0 +1,54 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Exception_NoSupportExtension +extends Horde_Imap_Client_Exception +{ + /** + * The extension not supported on the server. + * + * @var string + */ + public $extension; + + /** + * Constructor. + * + * @param string $extension The extension not supported on the server. + * @param string $msg A non-standard error message to use instead + * of the default. + */ + public function __construct($extension, $msg = null) + { + $this->extension = $extension; + + if (is_null($msg)) { + $msg = sprintf( + Horde_Imap_Client_Translation::r("The server does not support the %s extension."), + $extension + ); + } + + parent::__construct($msg, self::NOT_SUPPORTED); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/NoSupportPop3.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/NoSupportPop3.php new file mode 100644 index 00000000..a76c4a5c --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/NoSupportPop3.php @@ -0,0 +1,40 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Exception_NoSupportPop3 +extends Horde_Imap_Client_Exception +{ + /** + * Constructor. + * + * @param string $feature The feature not supported in POP3. + */ + public function __construct($feature) + { + parent::__construct( + Horde_Imap_Client_Translation::r("%s not supported on POP3 servers."), + self::NOT_SUPPORTED + ); + $this->messagePrintf(array($feature)); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/SearchCharset.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/SearchCharset.php new file mode 100644 index 00000000..50bdb8ce --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/SearchCharset.php @@ -0,0 +1,50 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Exception_SearchCharset +extends Horde_Imap_Client_Exception +{ + /** + * Charset that was attempted to be converted to. + * + * @var string + */ + public $charset; + + /** + * Constructor. + * + * @param string $charset The charset that was attempted to be converted + * to. + */ + public function __construct($charset) + { + $this->charset = $charset; + + parent::__construct( + Horde_Imap_Client_Translation::r("Cannot convert search query text to new charset"), + self::BADCHARSET + ); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/ServerResponse.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/ServerResponse.php new file mode 100644 index 00000000..7d154949 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/ServerResponse.php @@ -0,0 +1,88 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * + * @property-read string $command The command that caused the BAD/NO error + * status. + * @property-read array $resp_data The response data array. + * @property-read integer $status Server error status. + */ +class Horde_Imap_Client_Exception_ServerResponse extends Horde_Imap_Client_Exception +{ + /** + * Pipeline object. + * + * @var Horde_Imap_Client_Interaction_Pipeline + */ + protected $_pipeline; + + /** + * Server response object. + * + * @var Horde_Imap_Client_Interaction_Server + */ + protected $_server; + + /** + * Constructor. + * + * @param string $msg Error message. + * @param integer $code Error code. + * @param Horde_Imap_Client_Interaction_Server $server Server ob. + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline ob. + */ + public function __construct( + $msg = null, + $code = 0, + Horde_Imap_Client_Interaction_Server $server, + Horde_Imap_Client_Interaction_Pipeline $pipeline + ) + { + $this->details = strval($server->token); + + $this->_pipeline = $pipeline; + $this->_server = $server; + + parent::__construct($msg, $code); + } + + /** + */ + public function __get($name) + { + switch ($name) { + case 'command': + return ($this->_server instanceof Horde_Imap_Client_Interaction_Server_Tagged) + ? $this->_pipeline->getCmd($this->_server->tag)->getCommand() + : null; + + case 'resp_data': + return $this->_pipeline->data; + + case 'status': + return $this->_server->status; + + default: + return parent::__get($name); + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/Sync.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/Sync.php new file mode 100644 index 00000000..cc3af5ad --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Exception/Sync.php @@ -0,0 +1,37 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Exception_Sync extends Horde_Exception_Wrapped +{ + /* Error message codes. */ + + /** + * Token could not be parsed. + */ + const BAD_TOKEN = 1; + + /** + * UIDVALIDITY of the mailbox changed. + */ + const UIDVALIDITY_CHANGED = 2; + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Fetch/Query.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Fetch/Query.php new file mode 100644 index 00000000..1c777a1b --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Fetch/Query.php @@ -0,0 +1,383 @@ + + * @category Horde + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Fetch_Query implements ArrayAccess, Countable, Iterator +{ + /** + * Internal data array. + * + * @var array + */ + protected $_data = array(); + + /** + * Get the full text of the message. + * + * @param array $opts The following options are available: + * - length: (integer) The length of the substring to return. + * DEFAULT: The entire text is returned. + * - peek: (boolean) If set, does not set the '\Seen' flag on the + * message. + * DEFAULT: The seen flag is set. + * - start: (integer) If a portion of the full text is desired to be + * returned, the starting position is identified here. + * DEFAULT: The entire text is returned. + */ + public function fullText(array $opts = array()) + { + $this->_data[Horde_Imap_Client::FETCH_FULLMSG] = $opts; + } + + /** + * Return header text. + * + * Header text is defined only for the base RFC 2822 message or + * message/rfc822 parts. + * + * @param array $opts The following options are available: + * - id: (string) The MIME ID to obtain the header text for. + * DEFAULT: The header text for the base message will be + * returned. + * - length: (integer) The length of the substring to return. + * DEFAULT: The entire text is returned. + * - peek: (boolean) If set, does not set the '\Seen' flag on the + * message. + * DEFAULT: The seen flag is set. + * - start: (integer) If a portion of the full text is desired to be + * returned, the starting position is identified here. + * DEFAULT: The entire text is returned. + */ + public function headerText(array $opts = array()) + { + $id = isset($opts['id']) + ? $opts['id'] + : 0; + $this->_data[Horde_Imap_Client::FETCH_HEADERTEXT][$id] = $opts; + } + + /** + * Return body text. + * + * Body text is defined only for the base RFC 2822 message or + * message/rfc822 parts. + * + * @param array $opts The following options are available: + * - id: (string) The MIME ID to obtain the body text for. + * DEFAULT: The body text for the entire message will be + * returned. + * - length: (integer) The length of the substring to return. + * DEFAULT: The entire text is returned. + * - peek: (boolean) If set, does not set the '\Seen' flag on the + * message. + * DEFAULT: The seen flag is set. + * - start: (integer) If a portion of the full text is desired to be + * returned, the starting position is identified here. + * DEFAULT: The entire text is returned. + */ + public function bodyText(array $opts = array()) + { + $id = isset($opts['id']) + ? $opts['id'] + : 0; + $this->_data[Horde_Imap_Client::FETCH_BODYTEXT][$id] = $opts; + } + + /** + * Return MIME header text. + * + * MIME header text is defined only for non-RFC 2822 messages and + * non-message/rfc822 parts. + * + * @param string $id The MIME ID to obtain the MIME header text for. + * @param array $opts The following options are available: + * - length: (integer) The length of the substring to return. + * DEFAULT: The entire text is returned. + * - peek: (boolean) If set, does not set the '\Seen' flag on the + * message. + * DEFAULT: The seen flag is set. + * - start: (integer) If a portion of the full text is desired to be + * returned, the starting position is identified here. + * DEFAULT: The entire text is returned. + */ + public function mimeHeader($id, array $opts = array()) + { + $this->_data[Horde_Imap_Client::FETCH_MIMEHEADER][$id] = $opts; + } + + /** + * Return the body part data for a MIME ID. + * + * @param string $id The MIME ID to obtain the body part text for. + * @param array $opts The following options are available: + * - decode: (boolean) Attempt to server-side decode the bodypart data + * if it is MIME transfer encoded. + * DEFAULT: false + * - length: (integer) The length of the substring to return. + * DEFAULT: The entire text is returned. + * - peek: (boolean) If set, does not set the '\Seen' flag on the + * message. + * DEFAULT: The seen flag is set. + * - start: (integer) If a portion of the full text is desired to be + * returned, the starting position is identified here. + * DEFAULT: The entire text is returned. + */ + public function bodyPart($id, array $opts = array()) + { + $this->_data[Horde_Imap_Client::FETCH_BODYPART][$id] = $opts; + } + + /** + * Returns the decoded body part size for a MIME ID. + * + * @param string $id The MIME ID to obtain the decoded body part size + * for. + */ + public function bodyPartSize($id) + { + $this->_data[Horde_Imap_Client::FETCH_BODYPARTSIZE][$id] = true; + } + + /** + * Returns RFC 2822 header text that matches a search string. + * + * This header search work only with the base RFC 2822 message or + * message/rfc822 parts. + * + * @param string $label A unique label associated with this particular + * search. This is how the results are stored. + * @param array $search The search string(s) (case-insensitive). + * @param array $opts The following options are available: + * - cache: (boolean) If true, and 'peek' is also true, will cache + * the result of this call. + * DEFAULT: false + * - id: (string) The MIME ID to search. + * DEFAULT: The base message part + * - length: (integer) The length of the substring to return. + * DEFAULT: The entire text is returned. + * - notsearch: (boolean) Do a 'NOT' search on the headers. + * DEFAULT: false + * - peek: (boolean) If set, does not set the '\Seen' flag on the + * message. + * DEFAULT: The seen flag is set. + * - start: (integer) If a portion of the full text is desired to be + * returned, the starting position is identified here. + * DEFAULT: The entire text is returned. + */ + public function headers($label, $search, array $opts = array()) + { + $this->_data[Horde_Imap_Client::FETCH_HEADERS][$label] = array_merge( + $opts, + array( + 'headers' => array_map('strval', $search) + ) + ); + } + + /** + * Return MIME structure information. + */ + public function structure() + { + $this->_data[Horde_Imap_Client::FETCH_STRUCTURE] = true; + } + + /** + * Return envelope header data. + */ + public function envelope() + { + $this->_data[Horde_Imap_Client::FETCH_ENVELOPE] = true; + } + + /** + * Return flags set for the message. + */ + public function flags() + { + $this->_data[Horde_Imap_Client::FETCH_FLAGS] = true; + } + + /** + * Return the internal (IMAP) date of the message. + */ + public function imapDate() + { + $this->_data[Horde_Imap_Client::FETCH_IMAPDATE] = true; + } + + /** + * Return the size (in bytes) of the message. + */ + public function size() + { + $this->_data[Horde_Imap_Client::FETCH_SIZE] = true; + } + + /** + * Return the unique ID of the message. + */ + public function uid() + { + $this->_data[Horde_Imap_Client::FETCH_UID] = true; + } + + /** + * Return the sequence number of the message. + */ + public function seq() + { + $this->_data[Horde_Imap_Client::FETCH_SEQ] = true; + } + + /** + * Return the mod-sequence value for the message. + * + * The server must support the CONDSTORE IMAP extension, and the mailbox + * must support mod-sequences. + */ + public function modseq() + { + $this->_data[Horde_Imap_Client::FETCH_MODSEQ] = true; + } + + /** + * Does the query contain the given criteria? + * + * @param integer $criteria The criteria to remove. + * + * @return boolean True if the query contains the given criteria. + */ + public function contains($criteria) + { + return isset($this->_data[$criteria]); + } + + /** + * Remove an entry under a given criteria. + * + * @param integer $criteria Criteria ID. + * @param string $key The key to remove. + */ + public function remove($criteria, $key) + { + if (isset($this->_data[$criteria]) && + is_array($this->_data[$criteria])) { + unset($this->_data[$criteria][$key]); + if (empty($this->_data[$criteria])) { + unset($this->_data[$criteria]); + } + } + } + + /** + * Returns a hash of the current query object. + * + * @return string Hash. + */ + public function hash() + { + return hash('md5', serialize($this)); + } + + /* ArrayAccess methods. */ + + /** + */ + public function offsetExists($offset) + { + return isset($this->_data[$offset]); + } + + /** + */ + public function offsetGet($offset) + { + return isset($this->_data[$offset]) + ? $this->_data[$offset] + : null; + } + + /** + */ + public function offsetSet($offset, $value) + { + $this->_data[$offset] = $value; + } + + /** + */ + public function offsetUnset($offset) + { + unset($this->_data[$offset]); + } + + /* Countable methods. */ + + /** + */ + public function count() + { + return count($this->_data); + } + + /* Iterator methods. */ + + /** + */ + public function current() + { + $opts = current($this->_data); + + return (!empty($opts) && ($this->key() == Horde_Imap_Client::FETCH_BODYPARTSIZE)) + ? array_keys($opts) + : $opts; + } + + /** + */ + public function key() + { + return key($this->_data); + } + + /** + */ + public function next() + { + next($this->_data); + } + + /** + */ + public function rewind() + { + reset($this->_data); + } + + /** + */ + public function valid() + { + return !is_null($this->key()); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Fetch/Results.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Fetch/Results.php new file mode 100644 index 00000000..a39246b0 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Fetch/Results.php @@ -0,0 +1,182 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * + * @property-read integer $key_type The key type (sequence or UID). + */ +class Horde_Imap_Client_Fetch_Results +implements ArrayAccess, Countable, IteratorAggregate +{ + /** + * Key type constants. + */ + const SEQUENCE = 1; + const UID = 2; + + /** + * Internal data array. + * + * @var array + */ + protected $_data = array(); + + /** + * Key type. + * + * @var integer + */ + protected $_keyType; + + /** + * Class to use when creating a new fetch object. + * + * @var string + */ + protected $_obClass; + + /** + * Constructor. + * + * @param string $ob_class Class to use when creating a new fetch + * object. + * @param integer $key_type Key type. + */ + public function __construct($ob_class = 'Horde_Imap_Client_Data_Fetch', + $key_type = self::UID) + { + $this->_obClass = $ob_class; + $this->_keyType = $key_type; + } + + /** + */ + public function __get($name) + { + switch ($name) { + case 'key_type': + return $this->_keyType; + } + } + + /** + * Return a fetch object, creating and storing an empty object in the + * results set if it doesn't currently exist. + * + * @param string $key The key to retrieve. + * + * @return Horde_Imap_Client_Data_Fetch The fetch object. + */ + public function get($key) + { + if (!isset($this->_data[$key])) { + $this->_data[$key] = new $this->_obClass(); + } + + return $this->_data[$key]; + } + + /** + * Return the list of IDs. + * + * @return array ID list. + */ + public function ids() + { + ksort($this->_data); + return array_keys($this->_data); + } + + /** + * Return the first fetch object in the results, if there is only one + * object. + * + * @return null|Horde_Imap_Client_Data_Fetch The fetch object if there is + * only one object, or null. + */ + public function first() + { + return (count($this->_data) === 1) + ? reset($this->_data) + : null; + } + + /** + * Clears all fetch results. + * + * @since 2.6.0 + */ + public function clear() + { + $this->_data = array(); + } + + /* ArrayAccess methods. */ + + /** + */ + public function offsetExists($offset) + { + return isset($this->_data[$offset]); + } + + /** + */ + public function offsetGet($offset) + { + return isset($this->_data[$offset]) + ? $this->_data[$offset] + : null; + } + + /** + */ + public function offsetSet($offset, $value) + { + $this->_data[$offset] = $value; + } + + /** + */ + public function offsetUnset($offset) + { + unset($this->_data[$offset]); + } + + /* Countable methods. */ + + /** + */ + public function count() + { + return count($this->_data); + } + + /* IteratorAggregate methods. */ + + /** + */ + public function getIterator() + { + ksort($this->_data); + return new ArrayIterator($this->_data); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids.php new file mode 100644 index 00000000..187b646c --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids.php @@ -0,0 +1,494 @@ + + * @category Horde + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * + * @property-read boolean $all Does this represent an ALL message set? + * @property-read array $ids The list of IDs. + * @property-read boolean $largest Does this represent the largest ID in use? + * @property-read string $max The largest ID (@since 2.20.0). + * @property-read string $min The smallest ID (@since 2.20.0). + * @property-read string $range_string Generates a range string consisting of + * all messages between begin and end of + * ID list. + * @property-read boolean $search_res Does this represent a search result? + * @property-read boolean $sequence Are these sequence IDs? If false, these + * are UIDs. + * @property-read boolean $special True if this is a "special" ID + * representation. + * @property-read string $tostring Return the non-sorted string + * representation. + * @property-read string $tostring_sort Return the sorted string + * representation. + */ +class Horde_Imap_Client_Ids implements Countable, Iterator, Serializable +{ + /** + * "Special" representation constants. + */ + const ALL = "\01"; + const SEARCH_RES = "\02"; + const LARGEST = "\03"; + + /** + * Allow duplicate IDs? + * + * @var boolean + */ + public $duplicates = false; + + /** + * List of IDs. + * + * @var mixed + */ + protected $_ids = array(); + + /** + * Are IDs message sequence numbers? + * + * @var boolean + */ + protected $_sequence = false; + + /** + * Are IDs sorted? + * + * @var boolean + */ + protected $_sorted = false; + + /** + * Constructor. + * + * @param mixed $ids See self::add(). + * @param boolean $sequence Are $ids message sequence numbers? + */ + public function __construct($ids = null, $sequence = false) + { + $this->add($ids); + $this->_sequence = $sequence; + } + + /** + */ + public function __get($name) + { + switch ($name) { + case 'all': + return ($this->_ids === self::ALL); + + case 'ids': + return is_array($this->_ids) + ? $this->_ids + : array(); + + case 'largest': + return ($this->_ids === self::LARGEST); + + case 'max': + $this->sort(); + return end($this->_ids); + + case 'min': + $this->sort(); + return reset($this->_ids); + + case 'range_string': + if (!count($this)) { + return ''; + } + + $min = $this->min; + $max = $this->max; + + return ($min == $max) + ? $min + : $min . ':' . $max; + + case 'search_res': + return ($this->_ids === self::SEARCH_RES); + + case 'sequence': + return (bool)$this->_sequence; + + case 'special': + return is_string($this->_ids); + + case 'tostring': + case 'tostring_sort': + if ($this->all) { + return '1:*'; + } elseif ($this->largest) { + return '*'; + } elseif ($this->search_res) { + return '$'; + } + return strval($this->_toSequenceString($name == 'tostring_sort')); + } + } + + /** + */ + public function __toString() + { + return $this->tostring; + } + + /** + * Add IDs to the current object. + * + * @param mixed $ids Either self::ALL, self::SEARCH_RES, self::LARGEST, + * Horde_Imap_Client_Ids object, array, or sequence + * string. + */ + public function add($ids) + { + if (!is_null($ids)) { + if (is_string($ids) && + in_array($ids, array(self::ALL, self::SEARCH_RES, self::LARGEST))) { + $this->_ids = $ids; + } elseif ($add = $this->_resolveIds($ids)) { + if (is_array($this->_ids) && !empty($this->_ids)) { + foreach ($add as $val) { + $this->_ids[] = $val; + } + } else { + $this->_ids = $add; + } + if (!$this->duplicates) { + $this->_ids = (count($this->_ids) > 25000) + ? array_unique($this->_ids) + : array_keys(array_flip($this->_ids)); + } + } + + $this->_sorted = is_array($this->_ids) && (count($this->_ids) === 1); + } + } + + /** + * Removed IDs from the current object. + * + * @since 2.17.0 + * + * @param mixed $ids Either Horde_Imap_Client_Ids object, array, or + * sequence string. + */ + public function remove($ids) + { + if (!$this->isEmpty() && + ($remove = $this->_resolveIds($ids))) { + $this->_ids = array_diff($this->_ids, array_unique($remove)); + } + } + + /** + * Is this object empty (i.e. does not contain IDs)? + * + * @return boolean True if object is empty. + */ + public function isEmpty() + { + return (is_array($this->_ids) && !count($this->_ids)); + } + + /** + * Reverses the order of the IDs. + */ + public function reverse() + { + if (is_array($this->_ids)) { + $this->_ids = array_reverse($this->_ids); + } + } + + /** + * Sorts the IDs. + */ + public function sort() + { + if (!$this->_sorted && is_array($this->_ids)) { + $this->_sort($this->_ids); + $this->_sorted = true; + } + } + + /** + * Sorts the IDs numerically. + * + * @param array $ids The array list. + */ + protected function _sort(&$ids) + { + sort($ids, SORT_NUMERIC); + } + + /** + * Split the sequence string at an approximate length. + * + * @since 2.7.0 + * + * @param integer $length Length to split. + * + * @return array A list containing individual sequence strings. + */ + public function split($length) + { + $id = new Horde_Stream_Temp(); + $id->add($this->tostring_sort, true); + + $out = array(); + + do { + $out[] = $id->substring(0, $length) . $id->getToChar(','); + } while (!$id->eof()); + + return $out; + } + + /** + * Resolve the $ids input to add() and remove(). + * + * @param mixed $ids Either Horde_Imap_Client_Ids object, array, or + * sequence string. + * + * @return array An array of IDs. + */ + protected function _resolveIds($ids) + { + if ($ids instanceof Horde_Imap_Client_Ids) { + return $ids->ids; + } elseif (is_array($ids)) { + return $ids; + } elseif (is_string($ids) || is_integer($ids)) { + return is_numeric($ids) + ? array($ids) + : $this->_fromSequenceString($ids); + } + + return array(); + } + + /** + * Create an IMAP message sequence string from a list of indices. + * + * Index Format: range_start:range_end,uid,uid2,... + * + * @param boolean $sort Numerically sort the IDs before creating the + * range? + * + * @return string The IMAP message sequence string. + */ + protected function _toSequenceString($sort = true) + { + if (empty($this->_ids)) { + return ''; + } + + $in = $this->_ids; + + if ($sort && !$this->_sorted) { + $this->_sort($in); + } + + $first = $last = array_shift($in); + $i = count($in) - 1; + $out = array(); + + foreach ($in as $key => $val) { + if (($last + 1) == $val) { + $last = $val; + } + + if (($i == $key) || ($last != $val)) { + if ($last == $first) { + $out[] = $first; + if ($i == $key) { + $out[] = $val; + } + } else { + $out[] = $first . ':' . $last; + if (($i == $key) && ($last != $val)) { + $out[] = $val; + } + } + $first = $last = $val; + } + } + + return empty($out) + ? $first + : implode(',', $out); + } + + /** + * Parse an IMAP message sequence string into a list of indices. + * + * @see _toSequenceString() + * + * @param string $str The IMAP message sequence string. + * + * @return array An array of indices. + */ + protected function _fromSequenceString($str) + { + $ids = array(); + $str = trim($str); + + if (!strlen($str)) { + return $ids; + } + + $idarray = explode(',', $str); + + foreach ($idarray as $val) { + $range = explode(':', $val); + if (isset($range[1])) { + for ($i = min($range), $j = max($range); $i <= $j; ++$i) { + $ids[] = $i; + } + } else { + $ids[] = $val; + } + } + + return $ids; + } + + /* Countable methods. */ + + /** + */ + public function count() + { + return is_array($this->_ids) + ? count($this->_ids) + : 0; + } + + /* Iterator methods. */ + + /** + */ + public function current() + { + return is_array($this->_ids) + ? current($this->_ids) + : null; + } + + /** + */ + public function key() + { + return is_array($this->_ids) + ? key($this->_ids) + : null; + } + + /** + */ + public function next() + { + if (is_array($this->_ids)) { + next($this->_ids); + } + } + + /** + */ + public function rewind() + { + if (is_array($this->_ids)) { + reset($this->_ids); + } + } + + /** + */ + public function valid() + { + return !is_null($this->key()); + } + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + $save = array(); + + if ($this->duplicates) { + $save['d'] = 1; + } + + if ($this->_sequence) { + $save['s'] = 1; + } + + if ($this->_sorted) { + $save['is'] = 1; + } + + switch ($this->_ids) { + case self::ALL: + $save['a'] = true; + break; + + case self::LARGEST: + $save['l'] = true; + break; + + case self::SEARCH_RES: + $save['sr'] = true; + break; + + default: + $save['i'] = strval($this); + break; + } + + return serialize($save); + } + + /** + */ + public function unserialize($data) + { + $save = @unserialize($data); + + $this->duplicates = !empty($save['d']); + $this->_sequence = !empty($save['s']); + $this->_sorted = !empty($save['is']); + + if (isset($save['a'])) { + $this->_ids = self::ALL; + } elseif (isset($save['l'])) { + $this->_ids = self::LARGEST; + } elseif (isset($save['sr'])) { + $this->_ids = self::SEARCH_RES; + } elseif (isset($save['i'])) { + $this->add($save['i']); + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids/Map.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids/Map.php new file mode 100644 index 00000000..85a2ec07 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids/Map.php @@ -0,0 +1,242 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.1.0 + * + * @property-read array $map The raw ID mapping data. + * @property-read Horde_Imap_Client_Ids $seq The sorted sequence values. + * @property-read Horde_Imap_Client_Ids $uids The sorted UIDs. + */ +class Horde_Imap_Client_Ids_Map implements Countable, IteratorAggregate, Serializable +{ + /** + * Sequence -> UID mapping. + * + * @var array + */ + protected $_ids = array(); + + /** + * Is the array sorted? + * + * @var boolean + */ + protected $_sorted = true; + + /** + * Constructor. + * + * @param array $ids Array of sequence -> UID mapping. + */ + public function __construct(array $ids = array()) + { + $this->update($ids); + } + + /** + */ + public function __get($name) + { + switch ($name) { + case 'map': + return $this->_ids; + + case 'seq': + $this->sort(); + return new Horde_Imap_Client_Ids(array_keys($this->_ids), true); + + case 'uids': + $this->sort(); + return new Horde_Imap_Client_Ids($this->_ids); + } + } + + /** + * Updates the mapping. + * + * @param array $ids Array of sequence -> UID mapping. + * + * @return boolean True if the mapping changed. + */ + public function update($ids) + { + if (empty($ids)) { + return false; + } elseif (empty($this->_ids)) { + $this->_ids = $ids; + $change = true; + } else { + $change = false; + foreach ($ids as $k => $v) { + if (!isset($this->_ids[$k]) || ($this->_ids[$k] != $v)) { + $this->_ids[$k] = $v; + $change = true; + } + } + } + + if ($change) { + $this->_sorted = false; + } + + return $change; + } + + /** + * Create a Sequence <-> UID lookup table. + * + * @param Horde_Imap_Client_Ids $ids IDs to lookup. + * + * @return array Keys are sequence numbers, values are UIDs. + */ + public function lookup(Horde_Imap_Client_Ids $ids) + { + if ($ids->all) { + return $this->_ids; + } elseif ($ids->sequence) { + return array_intersect_key($this->_ids, array_flip($ids->ids)); + } + + return array_intersect($this->_ids, $ids->ids); + } + + /** + * Removes messages from the ID mapping. + * + * @param Horde_Imap_Client_Ids $ids IDs to remove. + */ + public function remove(Horde_Imap_Client_Ids $ids) + { + /* For sequence numbers, we need to reindex anytime we have an index + * that appears equal to or after a previously seen index. If an IMAP + * server is smart, it will expunge in reverse order instead. */ + if ($ids->sequence) { + $remove = $ids->ids; + } else { + $ids->sort(); + $remove = array_reverse(array_keys($this->lookup($ids))); + } + + if (empty($remove)) { + return; + } + + $this->sort(); + + if (count($remove) == count($this->_ids) && + !array_diff($remove, array_keys($this->_ids))) { + $this->_ids = array(); + return; + } + + /* Find the minimum sequence number to remove. We know entries before + * this are untouched so no need to process them multiple times. */ + $first = min($remove); + $edit = $newids = array(); + foreach (array_keys($this->_ids) as $i => $seq) { + if ($seq >= $first) { + $i += (($seq == $first) ? 0 : 1); + $newids = array_slice($this->_ids, 0, $i, true); + $edit = array_slice($this->_ids, $i + (($seq == $first) ? 0 : 1), null, true); + break; + } + } + + if (!empty($edit)) { + foreach ($remove as $val) { + $found = false; + $tmp = array(); + + foreach (array_keys($edit) as $i => $seq) { + if ($found) { + $tmp[$seq - 1] = $edit[$seq]; + } elseif ($seq >= $val) { + $tmp = array_slice($edit, 0, ($seq == $val) ? $i : $i + 1, true); + $found = true; + } + } + + $edit = $tmp; + } + } + + $this->_ids = $newids + $edit; + } + + /** + * Sort the map. + */ + public function sort() + { + if (!$this->_sorted) { + ksort($this->_ids, SORT_NUMERIC); + $this->_sorted = true; + } + } + + /* Countable methods. */ + + /** + */ + public function count() + { + return count($this->_ids); + } + + /* IteratorAggregate method. */ + + /** + */ + public function getIterator() + { + return new ArrayIterator($this->_ids); + } + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + /* Sort before storing; provides more compressible representation. */ + $this->sort(); + + return json_encode(array( + strval(new Horde_Imap_Client_Ids(array_keys($this->_ids))), + strval(new Horde_Imap_Client_Ids(array_values($this->_ids))) + )); + } + + /** + */ + public function unserialize($data) + { + $data = json_decode($data, true); + + $keys = new Horde_Imap_Client_Ids($data[0]); + $vals = new Horde_Imap_Client_Ids($data[1]); + $this->_ids = array_combine($keys->ids, $vals->ids); + + /* Guaranteed to be sorted if unserializing. */ + $this->_sorted = true; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids/Pop3.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids/Pop3.php new file mode 100644 index 00000000..a3ff9cb1 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids/Pop3.php @@ -0,0 +1,64 @@ + + * @category Horde + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Ids_Pop3 extends Horde_Imap_Client_Ids +{ + /** + */ + protected function _sort(&$ids) + { + /* There is no guarantee of POP3 UIDL order - IDs need to be unique, + * but there is no requirement they need be incrementing. RFC + * 1939[7] */ + } + + /** + * Create a POP3 message sequence string. + * + * Index Format: UID1[SPACE]UID2... + * + * @param boolean $sort Not used in this class. + * + * @return string The POP3 message sequence string. + */ + protected function _toSequenceString($sort = true) + { + /* $sort is ignored - see _sort(). */ + + /* Use space as delimiter as it is the only printable ASCII character + * that is not allowed as part of the UID (RFC 1939 [7]). */ + return implode(' ', count($this->_ids) > 25000 ? array_unique($this->_ids) : array_keys(array_flip($this->_ids))); + } + + /** + * Parse a POP3 message sequence string into a list of indices. + * + * @param string $str The POP3 message sequence string. + * + * @return array An array of UIDs. + */ + protected function _fromSequenceString($str) + { + return explode(' ', trim($str)); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Client.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Client.php new file mode 100644 index 00000000..8a585ada --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Client.php @@ -0,0 +1,61 @@ + + * @category Horde + * @copyright 2012-2016 Horde LLC + * @deprecated + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Interaction_Client extends Horde_Imap_Client_Data_Format_List +{ + /** + * The command tag. + * + * @var string + */ + public $tag; + + /** + * Constructor. + * + * @param string $tag The tag to use. If not set, will be automatically + * generated. + */ + public function __construct($tag = null) + { + $this->tag = is_null($tag) + ? substr(strval(new Horde_Support_Randomid()), 0, 10) + : strval($tag); + + parent::__construct($this->tag); + } + + /** + * Get the command. + * + * @return string The command. + */ + public function getCommand() + { + return isset($this->_data[1]) + ? $this->_data[1] + : null; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Command.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Command.php new file mode 100644 index 00000000..93628d36 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Command.php @@ -0,0 +1,184 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.10.0 + * + * @property-read boolean $continuation True if the command requires a server + * continuation response. + */ +class Horde_Imap_Client_Interaction_Command +extends Horde_Imap_Client_Data_Format_List +{ + /** + * Debug string(s) to use instead of command text. + * + * Multiple entries refer to the various steps in a continuation command. + * + * @var array + */ + public $debug = array(); + + /** + * Use LITERAL+ if available + * + * @var boolean + */ + public $literalplus = true; + + /** + * Are literal8's available? + * + * @var boolean + */ + public $literal8 = false; + + /** + * A callback to run on error. + * + * If callback returns true, the command will be treated as successful. + * + * @since 2.24.0 + * + * @var callback + */ + public $on_error = null; + + /** + * A callback to run on success. + * + * @since 2.28.0 + * + * @var callback + */ + public $on_success = null; + + /** + * Pipeline object associated with this command. + * + * @since 2.28.0 + * + * @var Horde_Imap_Client_Interaction_Pipeline + */ + public $pipeline; + + /** + * Server response. + * + * @var Horde_Imap_Client_Interaction_Server + */ + public $response; + + /** + * The command tag. + * + * @var string + */ + public $tag; + + /** + * Command timer. + * + * @var Horde_Support_Timer + */ + protected $_timer; + + /** + * Constructor. + * + * @param string $cmd The IMAP command. + * @param string $tag The tag to use. If not set, will be automatically + * generated. + */ + public function __construct($cmd, $tag = null) + { + $this->tag = is_null($tag) + ? substr(new Horde_Support_Randomid(), 0, 10) + : strval($tag); + + parent::__construct($this->tag); + + $this->add($cmd); + } + + /** + */ + public function __get($name) + { + switch ($name) { + case 'continuation': + return $this->_continuationCheck($this); + } + } + + /** + * Get the command. + * + * @return string The command. + */ + public function getCommand() + { + return $this->_data[1]; + } + + /** + * Start the command timer. + */ + public function startTimer() + { + $this->_timer = new Horde_Support_Timer(); + $this->_timer->push(); + } + + /** + * Return the timer data. + * + * @return mixed Null if timer wasn't started, or a float containing + * elapsed command time. + */ + public function getTimer() + { + return $this->_timer + ? round($this->_timer->pop(), 4) + : null; + } + + /** + * Recursive check for continuation functions. + */ + protected function _continuationCheck($list) + { + foreach ($list as $val) { + if (($val instanceof Horde_Imap_Client_Interaction_Command_Continuation) || + (($val instanceof Horde_Imap_Client_Data_Format_String) && + $val->literal())) { + return true; + } + + if (($val instanceof Horde_Imap_Client_Data_Format_List) && + $this->_continuationCheck($val)) { + return true; + } + } + + return false; + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Command/Continuation.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Command/Continuation.php new file mode 100644 index 00000000..061834ed --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Command/Continuation.php @@ -0,0 +1,74 @@ + + * @category Horde + * @copyright 2013-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.10.0 + */ +class Horde_Imap_Client_Interaction_Command_Continuation +{ + /** + * Is this an optional continuation request? + * + * @since 2.13.0 + * @var boolean + */ + public $optional = false; + + /** + * Closure function to run after continuation response. + * + * @var Closure + */ + protected $_closure; + + /** + * Constructor. + * + * @param Closure $closure A function to run after the continuation + * response is received. It receives one + * argument - a Continuation object - and should + * return a list of arguments to send to the + * server (via a + * Horde_Imap_Client_Data_Format_List object). + */ + public function __construct($closure) + { + $this->_closure = $closure; + } + + /** + * Calls the closure object. + * + * @param Horde_Imap_Client_Interaction_Server_Continuation $ob Continuation + * object. + * + * @return Horde_Imap_Client_Data_Format_List Further commands to issue + * to the server. + */ + public function getCommands( + Horde_Imap_Client_Interaction_Server_Continuation $ob + ) + { + $closure = $this->_closure; + return $closure($ob); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Pipeline.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Pipeline.php new file mode 100644 index 00000000..50d2e038 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Pipeline.php @@ -0,0 +1,160 @@ + + * @category Horde + * @copyright 2013-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.10.0 + * + * @property-read boolean $finished True if all commands have finished. + */ +class Horde_Imap_Client_Interaction_Pipeline implements Countable, IteratorAggregate +{ + /** + * Data storage from server responses. + * + * @var array + */ + public $data = array( + 'modseqs' => array(), + 'modseqs_nouid' => array() + ); + + /** + * Fetch results. + * + * @var Horde_Imap_Client_Fetch_Results + */ + public $fetch; + + /** + * The list of commands. + * + * @var array + */ + protected $_commands = array(); + + /** + * The list of commands to complete. + * + * @var array + */ + protected $_todo = array(); + + /** + * Constructor. + * + * @param Horde_Imap_Client_Fetch_Results $fetch Fetch results object. + */ + public function __construct(Horde_Imap_Client_Fetch_Results $fetch) + { + $this->fetch = $fetch; + } + + /** + */ + public function __get($name) + { + switch ($name) { + case 'finished': + return empty($this->_todo); + } + } + + /** + * Add a command to the pipeline. + * + * @param Horde_Imap_Client_Interaction_Command $cmd Command object. + * @param boolean $top Add command to top + * of queue? + */ + public function add(Horde_Imap_Client_Interaction_Command $cmd, + $top = false) + { + if ($top) { + // This won't re-index keys, which may be numerical. + $this->_commands = array($cmd->tag => $cmd) + $this->_commands; + } else { + $this->_commands[$cmd->tag] = $cmd; + } + $this->_todo[$cmd->tag] = true; + } + + /** + * Mark a command as completed. + * + * @param Horde_Imap_Client_Interaction_Server_Tagged $resp Tagged server + * response. + * + * @return Horde_Imap_Client_Interaction_Command Command that was + * completed. Returns null + * if tagged response + * is not contained in this + * pipeline object. + */ + public function complete(Horde_Imap_Client_Interaction_Server_Tagged $resp) + { + if (isset($this->_commands[$resp->tag])) { + $cmd = $this->_commands[$resp->tag]; + $cmd->response = $resp; + unset($this->_todo[$resp->tag]); + } else { + /* This can be reached if a previous pipeline action was aborted, + * e.g. via an Exception. */ + $cmd = null; + } + + return $cmd; + } + + /** + * Return the command for a given tag. + * + * @param string $tag The command tag. + * + * @return Horde_Imap_Client_Interaction_Command A command object (or + * null if the tag does + * not exist). + */ + public function getCmd($tag) + { + return isset($this->_commands[$tag]) + ? $this->_commands[$tag] + : null; + } + + /* Countable methods. */ + + /** + */ + public function count() + { + return count($this->_commands); + } + + /* IteratorAggregate methods. */ + + /** + */ + public function getIterator() + { + return new ArrayIterator($this->_commands); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server.php new file mode 100644 index 00000000..28962a6b --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server.php @@ -0,0 +1,144 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Interaction_Server +{ + /** + * Response codes (RFC 3501 [7.1]). + */ + const BAD = 1; + const BYE = 2; + const NO = 3; + const OK = 4; + const PREAUTH = 5; + + /** + * Check for status response? + * + * @var boolean + */ + protected $_checkStatus = true; + + /** + * Response code (RFC 3501 [7.1]). Properties: + * - code: (string) Response code. + * - data: (array) Data associated with response. + * + * @var object + */ + public $responseCode = null; + + /** + * Status response from the server. + * + * @var string + */ + public $status = null; + + /** + * IMAP server data. + * + * @var Horde_Imap_Client_Tokenize + */ + public $token; + + /** + * Auto-scan an incoming line to determine the response type. + * + * @param Horde_Imap_Client_Tokenize $t Tokenized data returned from the + * server. + * + * @return Horde_Imap_Client_Interaction_Server A server response object. + */ + public static function create(Horde_Imap_Client_Tokenize $t) + { + $t->rewind(); + $tag = $t->next(); + $t->next(); + + switch ($tag) { + case '+': + return new Horde_Imap_Client_Interaction_Server_Continuation($t); + + case '*': + return new Horde_Imap_Client_Interaction_Server_Untagged($t); + + default: + return new Horde_Imap_Client_Interaction_Server_Tagged($t, $tag); + } + } + + /** + * Constructor. + * + * @param Horde_Imap_Client_Tokenize $token Tokenized data returned from + * the server. + */ + public function __construct(Horde_Imap_Client_Tokenize $token) + { + $this->token = $token; + + /* Check for response status. */ + $status = $token->current(); + $valid = array('BAD', 'BYE', 'NO', 'OK', 'PREAUTH'); + + if (in_array($status, $valid)) { + $this->status = constant(__CLASS__ . '::' . $status); + $resp_text = $token->next(); + + /* Check for response code. Only occurs if there is a response + * status. */ + if (is_string($resp_text) && ($resp_text[0] === '[')) { + $resp = new stdClass; + $resp->data = array(); + + if ($resp_text[strlen($resp_text) - 1] === ']') { + $resp->code = substr($resp_text, 1, -1); + } else { + $resp->code = substr($resp_text, 1); + + while (($elt = $token->next()) !== false) { + if (is_string($elt) && $elt[strlen($elt) - 1] === ']') { + $resp->data[] = substr($elt, 0, -1); + break; + } + $resp->data[] = is_string($elt) + ? $elt + : $token->flushIterator(); + } + } + + $token->next(); + $this->responseCode = $resp; + } + } + } + + /** + */ + public function __toString() + { + return strval($this->token); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Continuation.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Continuation.php new file mode 100644 index 00000000..1f27dabd --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Continuation.php @@ -0,0 +1,25 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Interaction_Server_Continuation extends Horde_Imap_Client_Interaction_Server +{ +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Tagged.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Tagged.php new file mode 100644 index 00000000..ef90fc2f --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Tagged.php @@ -0,0 +1,49 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Interaction_Server_Tagged +extends Horde_Imap_Client_Interaction_Server +{ + /** + * Tag. + * + * @var string + */ + public $tag; + + /** + * @param string $tag Response tag. + */ + public function __construct(Horde_Imap_Client_Tokenize $token, $tag) + { + $this->tag = $tag; + + parent::__construct($token); + + if (is_null($this->status)) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Bad tagged response.") + ); + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Untagged.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Untagged.php new file mode 100644 index 00000000..91d51882 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Interaction/Server/Untagged.php @@ -0,0 +1,25 @@ + + * @category Horde + * @copyright 2012-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Interaction_Server_Untagged extends Horde_Imap_Client_Interaction_Server +{ +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Mailbox.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Mailbox.php new file mode 100644 index 00000000..2d10e141 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Mailbox.php @@ -0,0 +1,147 @@ + + * @category Horde + * @copyright 2011-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * + * @property-read string $list_escape Escapes mailbox for use in LIST + * command (UTF-8). + * @property-read string $utf7imap Mailbox in UTF7-IMAP. + * @property-read string $utf8 Mailbox in UTF-8. + */ +class Horde_Imap_Client_Mailbox implements Serializable +{ + /** + * UTF7-IMAP representation of mailbox. + * If boolean true, it is identical to UTF-8 representation. + * + * @var mixed + */ + protected $_utf7imap; + + /** + * UTF8 representation of mailbox. + * + * @var string + */ + protected $_utf8; + + /** + * Shortcut to obtaining mailbox object. + * + * @param string $mbox The mailbox name. + * @param boolean $utf7imap Is mailbox UTF7-IMAP encoded? Otherwise, + * mailbox is assumed to be UTF-8. + * + * @return Horde_Imap_Client_Mailbox A mailbox object. + */ + public static function get($mbox, $utf7imap = false) + { + return ($mbox instanceof Horde_Imap_Client_Mailbox) + ? $mbox + : new Horde_Imap_Client_Mailbox($mbox, $utf7imap); + } + + /** + * Constructor. + * + * @param string $mbox The mailbox name. + * @param boolean $utf7imap Is mailbox UTF7-IMAP encoded (true). + * Otherwise, mailbox is assumed to be UTF-8 + * encoded. + */ + public function __construct($mbox, $utf7imap = false) + { + if (strcasecmp($mbox, 'INBOX') === 0) { + $mbox = 'INBOX'; + } + + if ($utf7imap) { + $this->_utf7imap = $mbox; + } else { + $this->_utf8 = $mbox; + } + } + + /** + */ + public function __get($name) + { + switch ($name) { + case 'list_escape': + return preg_replace("/\*+/", '%', $this->utf8); + + case 'utf7imap': + if (!isset($this->_utf7imap)) { + $n = Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($this->_utf8); + $this->_utf7imap = ($n == $this->_utf8) + ? true + : $n; + } + + return ($this->_utf7imap === true) + ? $this->_utf8 + : $this->_utf7imap; + + case 'utf8': + if (!isset($this->_utf8)) { + $this->_utf8 = Horde_Imap_Client_Utf7imap::Utf7ImapToUtf8($this->_utf7imap); + if ($this->_utf8 == $this->_utf7imap) { + $this->_utf7imap = true; + } + } + return (string)$this->_utf8; + } + } + + /** + */ + public function __toString() + { + return $this->utf8; + } + + /** + * Compares this mailbox to another mailbox string. + * + * @return boolean True if the items are equal. + */ + public function equals($mbox) + { + return ($this->utf8 == $mbox); + } + + /* Serializable methods. */ + + /** + */ + public function serialize() + { + return json_encode(array($this->_utf7imap, $this->_utf8)); + } + + /** + */ + public function unserialize($data) + { + list($this->_utf7imap, $this->_utf8) = json_decode($data, true); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Mailbox/List.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Mailbox/List.php new file mode 100644 index 00000000..2df2357d --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Mailbox/List.php @@ -0,0 +1,158 @@ + + * @category Horde + * @copyright 2004-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Mailbox_List implements Countable, IteratorAggregate +{ + /** + * The delimiter character to use. + * + * @var string + */ + protected $_delimiter; + + /** + * Mailbox list. + * + * @var array + */ + protected $_mboxes = array(); + + /** + * Should we sort with INBOX at the front of the list? + * + * @var boolean + */ + protected $_sortinbox; + + /** + * Constructor. + * + * @param mixed $mboxes A mailbox or list of mailboxes. + */ + public function __construct($mboxes) + { + $this->_mboxes = is_array($mboxes) + ? $mboxes + : array($mboxes); + } + + /** + * Sort the list of mailboxes. + * + * @param array $opts Options: + * - delimiter: (string) The delimiter to use. + * DEFAULT: '.' + * - inbox: (boolean) Always put INBOX at the head of the list? + * DEFAULT: Yes + * - noupdate: (boolean) Do not update the object's mailbox list? + * DEFAULT: true + * + * @return array List of sorted mailboxes (index association is kept). + */ + public function sort(array $opts = array()) + { + $this->_delimiter = isset($opts['delimiter']) + ? $opts['delimiter'] + : '.'; + $this->_sortinbox = (!isset($opts['inbox']) || !empty($opts['inbox'])); + + if (empty($opts['noupdate'])) { + $mboxes = &$this->_mboxes; + } else { + $mboxes = $this->_mboxes; + } + + uasort($mboxes, array($this, '_mboxCompare')); + + return $mboxes; + } + + /** + * Hierarchical folder sorting function (used with usort()). + * + * @param string $a Comparison item 1. + * @param string $b Comparison item 2. + * + * @return integer See usort(). + */ + final protected function _mboxCompare($a, $b) + { + /* Always return INBOX as "smaller". */ + if ($this->_sortinbox) { + if (strcasecmp($a, 'INBOX') === 0) { + return -1; + } elseif (strcasecmp($b, 'INBOX') === 0) { + return 1; + } + } + + $a_parts = explode($this->_delimiter, $a); + $b_parts = explode($this->_delimiter, $b); + + $a_count = count($a_parts); + $b_count = count($b_parts); + + for ($i = 0, $iMax = min($a_count, $b_count); $i < $iMax; ++$i) { + if ($a_parts[$i] != $b_parts[$i]) { + /* If only one of the folders is under INBOX, return it as + * "smaller". */ + if ($this->_sortinbox && ($i === 0)) { + $a_base = (strcasecmp($a_parts[0], 'INBOX') === 0); + $b_base = (strcasecmp($b_parts[0], 'INBOX') === 0); + if ($a_base && !$b_base) { + return -1; + } elseif (!$a_base && $b_base) { + return 1; + } + } + + $cmp = strnatcasecmp($a_parts[$i], $b_parts[$i]); + return ($cmp === 0) + ? strcmp($a_parts[$i], $b_parts[$i]) + : $cmp; + } elseif ($a_parts[$i] !== $b_parts[$i]) { + return strlen($a_parts[$i]) - strlen($b_parts[$i]); + } + } + + return ($a_count - $b_count); + } + + /* Countable methods. */ + + /** + */ + public function count() + { + return count($this->_mboxes); + } + + /* IteratorAggregate methods. */ + + /** + */ + public function getIterator() + { + return new ArrayIterator($this->_mboxes); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Namespace/List.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Namespace/List.php new file mode 100644 index 00000000..4ace338e --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Namespace/List.php @@ -0,0 +1,130 @@ + + * @category Horde + * @copyright 2014-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.21.0 + */ +class Horde_Imap_Client_Namespace_List +implements ArrayAccess, Countable, IteratorAggregate +{ + /** + * The list of namespace objects. + * + * @var array + */ + protected $_ns = array(); + + /** + * Constructor. + * + * @param array $ns The list of namespace objects. + */ + public function __construct($ns = array()) + { + foreach ($ns as $val) { + $this->_ns[strval($val)] = $val; + } + } + + /** + * Get namespace info for a full mailbox path. + * + * @param string $mbox The mailbox path. + * @param boolean $personal If true, will return the empty namespace only + * if it is a personal namespace. + * + * @return mixed The Horde_Imap_Client_Data_Namespace object for the + * mailbox path, or null if the path doesn't exist. + */ + public function getNamespace($mbox, $personal = false) + { + $mbox = strval($mbox); + + if ($ns = $this[$mbox]) { + return $ns; + } + + foreach ($this->_ns as $val) { + $mbox = $mbox . $val->delimiter; + if (strlen($val->name) && (strpos($mbox, $val->name) === 0)) { + return $val; + } + } + + return (($ns = $this['']) && (!$personal || ($ns->type === $ns::NS_PERSONAL))) + ? $ns + : null; + } + + /* ArrayAccess methods. */ + + /** + */ + public function offsetExists($offset) + { + return isset($this->_ns[strval($offset)]); + } + + /** + */ + public function offsetGet($offset) + { + $offset = strval($offset); + + return isset($this->_ns[$offset]) + ? $this->_ns[$offset] + : null; + } + + /** + */ + public function offsetSet($offset, $value) + { + if ($value instanceof Horde_Imap_Client_Data_Namespace) { + $this->_ns[strval($value)] = $value; + } + } + + /** + */ + public function offsetUnset($offset) + { + unset($this->_ns[strval($offset)]); + } + + /* Countable methods. */ + + /** + */ + public function count() + { + return count($this->_ns); + } + + /* IteratorAggregate methods. */ + + /** + */ + public function getIterator() + { + return new ArrayIterator($this->_ns); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Password/Xoauth2.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Password/Xoauth2.php new file mode 100644 index 00000000..f608e208 --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Password/Xoauth2.php @@ -0,0 +1,71 @@ + + * @category Horde + * @copyright 2013-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + * @since 2.16.0 + */ +class Horde_Imap_Client_Password_Xoauth2 +implements Horde_Imap_Client_Base_Password +{ + /** + * Access token. + * + * @var string + */ + public $access_token; + + /** + * Username. + * + * @var string + */ + public $username; + + /** + * Constructor. + * + * @param string $username The username. + * @param string $access_token The access token. + */ + public function __construct($username, $access_token) + { + $this->username = $username; + $this->access_token = $access_token; + } + + /** + * Return the password to use for the server connection. + * + * @return string The password. + */ + public function getPassword() + { + // base64("user=" {User} "^Aauth=Bearer " {Access Token} "^A^A") + // ^A represents a Control+A (\001) + return base64_encode( + 'user=' . $this->username . "\1" . + 'auth=Bearer ' . $this->access_token . "\1\1" + ); + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Search/Query.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Search/Query.php new file mode 100644 index 00000000..c0474f1c --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Search/Query.php @@ -0,0 +1,904 @@ + + * @category Horde + * @copyright 2008-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Search_Query implements Serializable +{ + /** + * Serialized version. + */ + const VERSION = 3; + + /** + * Constants for dateSearch() + */ + const DATE_BEFORE = 'BEFORE'; + const DATE_ON = 'ON'; + const DATE_SINCE = 'SINCE'; + + /** + * Constants for intervalSearch() + */ + const INTERVAL_OLDER = 'OLDER'; + const INTERVAL_YOUNGER = 'YOUNGER'; + + /** + * The charset of the search strings. All text strings must be in + * this charset. By default, this is 'US-ASCII' (see RFC 3501 [6.4.4]). + * + * @var string + */ + protected $_charset = null; + + /** + * The list of search params. + * + * @var array + */ + protected $_search = array(); + + /** + * String representation: The IMAP search string. + */ + public function __toString() + { + try { + $res = $this->build(null); + return $res['query']->escape(); + } catch (Exception $e) { + return ''; + } + } + + /** + * Sets the charset of the search text. + * + * @param string $charset The charset to use for the search. + * @param boolean $convert Convert existing text values? + * + * @throws Horde_Imap_Client_Exception_SearchCharset + */ + public function charset($charset, $convert = true) + { + $oldcharset = $this->_charset; + $this->_charset = Horde_String::upper($charset); + + if (!$convert || ($oldcharset == $this->_charset)) { + return; + } + + foreach (array('and', 'or') as $item) { + if (isset($this->_search[$item])) { + foreach ($this->_search[$item] as &$val) { + $val->charset($charset, $convert); + } + } + } + + // Unset the reference to avoid corrupting $this->_search below. + unset($val); + + foreach (array('header', 'text') as $item) { + if (isset($this->_search[$item])) { + foreach ($this->_search[$item] as $key => $val) { + $new_val = Horde_String::convertCharset($val['text'], $oldcharset, $this->_charset); + if (Horde_String::convertCharset($new_val, $this->_charset, $oldcharset) != $val['text']) { + throw new Horde_Imap_Client_Exception_SearchCharset($this->_charset); + } + $this->_search[$item][$key]['text'] = $new_val; + } + } + } + } + + /** + * Builds an IMAP4rev1 compliant search string. + * + * @todo Change default of $exts to null. + * + * @param Horde_Imap_Client_Base $exts The server object this query will + * be run on (@since 2.24.0), a + * Horde_Imap_Client_Data_Capability + * object (@since 2.24.0), or the + * list of extensions present + * on the server (@deprecated). + * If null, all extensions are + * assumed to be available. + * + * @return array An array with these elements: + * - charset: (string) The charset of the search string. If null, no + * text strings appear in query. + * - exts: (array) The list of IMAP extensions used to create the + * string. + * - query: (Horde_Imap_Client_Data_Format_List) The IMAP search + * command. + * + * @throws Horde_Imap_Client_Data_Format_Exception + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + public function build($exts = array()) + { + /* @todo: BC */ + if (is_array($exts)) { + $tmp = new Horde_Imap_Client_Data_Capability_Imap(); + foreach ($exts as $key => $val) { + $tmp->add($key, is_array($val) ? $val : null); + } + $exts = $tmp; + } elseif (!is_null($exts)) { + if ($exts instanceof Horde_Imap_Client_Base) { + $exts = $exts->capability; + } elseif (!($exts instanceof Horde_Imap_Client_Data_Capability)) { + throw new InvalidArgumentException('Incorrect $exts parameter'); + } + } + + $temp = array( + 'cmds' => new Horde_Imap_Client_Data_Format_List(), + 'exts' => $exts, + 'exts_used' => array() + ); + $cmds = &$temp['cmds']; + $charset = $charset_cname = null; + $default_search = true; + $exts_used = &$temp['exts_used']; + $ptr = &$this->_search; + + $charset_get = function ($c) use (&$charset, &$charset_cname) { + $charset = is_null($c) + ? 'US-ASCII' + : strval($c); + $charset_cname = ($charset === 'US-ASCII') + ? 'Horde_Imap_Client_Data_Format_Astring' + : 'Horde_Imap_Client_Data_Format_Astring_Nonascii'; + }; + $create_return = function ($charset, $exts_used, $cmds) { + return array( + 'charset' => $charset, + 'exts' => array_keys(array_flip($exts_used)), + 'query' => $cmds + ); + }; + + /* Do IDs check first. If there is an empty ID query (without a NOT + * qualifier), the rest of this query is irrelevant since we already + * know the search will return no results. */ + if (isset($ptr['ids'])) { + if (!count($ptr['ids']['ids']) && !$ptr['ids']['ids']->special) { + if (empty($ptr['ids']['not'])) { + /* This is a match on an empty list of IDs. We do need to + * process any OR queries that may exist, since they are + * independent of this result. */ + if (isset($ptr['or'])) { + $this->_buildAndOr( + 'OR', $ptr['or'], $charset, $exts_used, $cmds + ); + } + return $create_return($charset, $exts_used, $cmds); + } + + /* If reached here, this a NOT search of an empty list. We can + * safely discard this from the output. */ + } else { + $this->_addFuzzy(!empty($ptr['ids']['fuzzy']), $temp); + if (!empty($ptr['ids']['not'])) { + $cmds->add('NOT'); + } + if (!$ptr['ids']['ids']->sequence) { + $cmds->add('UID'); + } + $cmds->add(strval($ptr['ids']['ids'])); + } + } + + if (isset($ptr['new'])) { + $this->_addFuzzy(!empty($ptr['newfuzzy']), $temp); + if ($ptr['new']) { + $cmds->add('NEW'); + unset($ptr['flag']['UNSEEN']); + } else { + $cmds->add('OLD'); + } + unset($ptr['flag']['RECENT']); + } + + if (!empty($ptr['flag'])) { + foreach ($ptr['flag'] as $key => $val) { + $this->_addFuzzy(!empty($val['fuzzy']), $temp); + + $tmp = ''; + if (empty($val['set'])) { + // This is a 'NOT' search. All system flags but \Recent + // have 'UN' equivalents. + if ($key == 'RECENT') { + $cmds->add('NOT'); + } else { + $tmp = 'UN'; + } + } + + if ($val['type'] == 'keyword') { + $cmds->add(array( + $tmp . 'KEYWORD', + $key + )); + } else { + $cmds->add($tmp . $key); + } + } + } + + if (!empty($ptr['header'])) { + /* The list of 'system' headers that have a specific search + * query. */ + $systemheaders = array( + 'BCC', 'CC', 'FROM', 'SUBJECT', 'TO' + ); + + foreach ($ptr['header'] as $val) { + $this->_addFuzzy(!empty($val['fuzzy']), $temp); + + if (!empty($val['not'])) { + $cmds->add('NOT'); + } + + if (in_array($val['header'], $systemheaders)) { + $cmds->add($val['header']); + } else { + $cmds->add(array( + 'HEADER', + new Horde_Imap_Client_Data_Format_Astring($val['header']) + )); + } + + $charset_get($this->_charset); + $cmds->add( + new $charset_cname(isset($val['text']) ? $val['text'] : '') + ); + } + } + + if (!empty($ptr['text'])) { + foreach ($ptr['text'] as $val) { + $this->_addFuzzy(!empty($val['fuzzy']), $temp); + + if (!empty($val['not'])) { + $cmds->add('NOT'); + } + + $charset_get($this->_charset); + $cmds->add(array( + $val['type'], + new $charset_cname($val['text']) + )); + } + } + + if (!empty($ptr['size'])) { + foreach ($ptr['size'] as $key => $val) { + $this->_addFuzzy(!empty($val['fuzzy']), $temp); + if (!empty($val['not'])) { + $cmds->add('NOT'); + } + $cmds->add(array( + $key, + new Horde_Imap_Client_Data_Format_Number( + empty($val['size']) ? 0 : $val['size'] + ) + )); + } + } + + if (!empty($ptr['date'])) { + foreach ($ptr['date'] as $val) { + $this->_addFuzzy(!empty($val['fuzzy']), $temp); + + if (!empty($val['not'])) { + $cmds->add('NOT'); + } + + if (empty($val['header'])) { + $cmds->add($val['range']); + } else { + $cmds->add('SENT' . $val['range']); + } + $cmds->add($val['date']); + } + } + + if (!empty($ptr['within'])) { + if (is_null($exts) || $exts->query('WITHIN')) { + $exts_used[] = 'WITHIN'; + } + + foreach ($ptr['within'] as $key => $val) { + $this->_addFuzzy(!empty($val['fuzzy']), $temp); + if (!empty($val['not'])) { + $cmds->add('NOT'); + } + + if (is_null($exts) || $exts->query('WITHIN')) { + $cmds->add(array( + $key, + new Horde_Imap_Client_Data_Format_Number($val['interval']) + )); + } else { + // This workaround is only accurate to within 1 day, due + // to limitations with the IMAP4rev1 search commands. + $cmds->add(array( + ($key == self::INTERVAL_OLDER) ? self::DATE_BEFORE : self::DATE_SINCE, + new Horde_Imap_Client_Data_Format_Date('now -' . $val['interval'] . ' seconds') + )); + } + } + } + + if (!empty($ptr['modseq'])) { + if (!is_null($exts) && !$exts->query('CONDSTORE')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('CONDSTORE'); + } + + $exts_used[] = 'CONDSTORE'; + + $this->_addFuzzy(!empty($ptr['modseq']['fuzzy']), $temp); + + if (!empty($ptr['modseq']['not'])) { + $cmds->add('NOT'); + } + $cmds->add('MODSEQ'); + if (isset($ptr['modseq']['name'])) { + $cmds->add(array( + new Horde_Imap_Client_Data_Format_String($ptr['modseq']['name']), + $ptr['modseq']['type'] + )); + } + $cmds->add(new Horde_Imap_Client_Data_Format_Number($ptr['modseq']['value'])); + } + + if (isset($ptr['prevsearch'])) { + if (!is_null($exts) && !$exts->query('SEARCHRES')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('SEARCHRES'); + } + + $exts_used[] = 'SEARCHRES'; + + $this->_addFuzzy(!empty($ptr['prevsearchfuzzy']), $temp); + + if (!$ptr['prevsearch']) { + $cmds->add('NOT'); + } + $cmds->add('$'); + } + + // Add AND'ed queries + if (!empty($ptr['and'])) { + $default_search = $this->_buildAndOr( + 'AND', $ptr['and'], $charset, $exts_used, $cmds + ); + } + + // Add OR'ed queries + if (!empty($ptr['or'])) { + $default_search = $this->_buildAndOr( + 'OR', $ptr['or'], $charset, $exts_used, $cmds + ); + } + + // Default search is 'ALL' + if ($default_search && !count($cmds)) { + $cmds->add('ALL'); + } + + return $create_return($charset, $exts_used, $cmds); + } + + /** + * Builds the AND/OR query. + * + * @param string $type 'AND' or 'OR'. + * @param array $data Query data. + * @param string &$charset Search charset. + * @param array &$exts_used IMAP extensions used. + * @param Horde_Imap_Client_Data_Format_List &$cmds Command list. + * + * @return boolean True if query might return results. + */ + protected function _buildAndOr($type, $data, &$charset, &$exts_used, + &$cmds) + { + $results = false; + + foreach ($data as $val) { + $ret = $val->build(); + + /* Empty sub-query. */ + if (!count($ret['query'])) { + switch ($type) { + case 'AND': + /* Any empty sub-query means that the query MUST return + * no results. */ + $cmds = new Horde_Imap_Client_Data_Format_List(); + $exts_used = array(); + return false; + + case 'OR': + /* Skip this query. */ + continue 2; + } + } + + $results = true; + + if (!is_null($ret['charset']) && ($ret['charset'] != 'US-ASCII')) { + if (!is_null($charset) && + ($charset != 'US-ASCII') && + ($charset != $ret['charset'])) { + throw new InvalidArgumentException( + 'AND/OR queries must all have the same charset.' + ); + } + $charset = $ret['charset']; + } + + $exts_used = array_merge($exts_used, $ret['exts']); + + switch ($type) { + case 'AND': + $cmds->add($ret['query'], true); + break; + + case 'OR': + // First OR'd query + if (count($cmds)) { + $new_cmds = new Horde_Imap_Client_Data_Format_List(); + $new_cmds->add(array( + 'OR', + $ret['query'], + $cmds + )); + $cmds = $new_cmds; + } else { + $cmds = $ret['query']; + } + break; + } + } + + return $results; + } + + /** + * Adds fuzzy modifier to search keys. + * + * @param boolean $add Add the fuzzy modifier? + * @param array $temp Temporary build data. + * + * @throws Horde_Imap_Client_Exception_NoSupport_Extension + */ + protected function _addFuzzy($add, &$temp) + { + if ($add) { + if (!$temp['exts']->query('SEARCH', 'FUZZY')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('SEARCH=FUZZY'); + } + $temp['cmds']->add('FUZZY'); + $temp['exts_used'][] = 'SEARCH=FUZZY'; + } + } + + /** + * Search for a flag/keywords. + * + * @param string $name The flag or keyword name. + * @param boolean $set If true, search for messages that have the flag + * set. If false, search for messages that do not + * have the flag set. + * @param array $opts Additional options: + * - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server + * MUST support RFC 6203. + */ + public function flag($name, $set = true, array $opts = array()) + { + $name = Horde_String::upper(ltrim($name, '\\')); + if (!isset($this->_search['flag'])) { + $this->_search['flag'] = array(); + } + + /* The list of defined system flags (see RFC 3501 [2.3.2]). */ + $systemflags = array( + 'ANSWERED', 'DELETED', 'DRAFT', 'FLAGGED', 'RECENT', 'SEEN' + ); + + $this->_search['flag'][$name] = array_filter(array( + 'fuzzy' => !empty($opts['fuzzy']), + 'set' => $set, + 'type' => in_array($name, $systemflags) ? 'flag' : 'keyword' + )); + } + + /** + * Determines if flags are a part of the search. + * + * @return boolean True if search query involves flags. + */ + public function flagSearch() + { + return !empty($this->_search['flag']); + } + + /** + * Search for either new messages (messages that have the '\Recent' flag + * but not the '\Seen' flag) or old messages (messages that do not have + * the '\Recent' flag). If new messages are searched, this will clear + * any '\Recent' or '\Unseen' flag searches. If old messages are searched, + * this will clear any '\Recent' flag search. + * + * @param boolean $newmsgs If true, searches for new messages. Else, + * search for old messages. + * @param array $opts Additional options: + * - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server + * MUST support RFC 6203. + */ + public function newMsgs($newmsgs = true, array $opts = array()) + { + $this->_search['new'] = $newmsgs; + if (!empty($opts['fuzzy'])) { + $this->_search['newfuzzy'] = true; + } + } + + /** + * Search for text in the header of a message. + * + * @param string $header The header field. + * @param string $text The search text. + * @param boolean $not If true, do a 'NOT' search of $text. + * @param array $opts Additional options: + * - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server + * MUST support RFC 6203. + */ + public function headerText($header, $text, $not = false, + array $opts = array()) + { + if (!isset($this->_search['header'])) { + $this->_search['header'] = array(); + } + $this->_search['header'][] = array_filter(array( + 'fuzzy' => !empty($opts['fuzzy']), + 'header' => Horde_String::upper($header), + 'text' => $text, + 'not' => $not + )); + } + + /** + * Search for text in either the entire message, or just the body. + * + * @param string $text The search text. + * @param string $bodyonly If true, only search in the body of the + * message. If false, also search in the headers. + * @param boolean $not If true, do a 'NOT' search of $text. + * @param array $opts Additional options: + * - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server + * MUST support RFC 6203. + */ + public function text($text, $bodyonly = true, $not = false, + array $opts = array()) + { + if (!isset($this->_search['text'])) { + $this->_search['text'] = array(); + } + + $this->_search['text'][] = array_filter(array( + 'fuzzy' => !empty($opts['fuzzy']), + 'not' => $not, + 'text' => $text, + 'type' => $bodyonly ? 'BODY' : 'TEXT' + )); + } + + /** + * Search for messages smaller/larger than a certain size. + * + * @todo: Remove $not for 3.0 + * + * @param integer $size The size (in bytes). + * @param boolean $larger Search for messages larger than $size? + * @param boolean $not If true, do a 'NOT' search of $text. + * @param array $opts Additional options: + * - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server + * MUST support RFC 6203. + */ + public function size($size, $larger = false, $not = false, + array $opts = array()) + { + if (!isset($this->_search['size'])) { + $this->_search['size'] = array(); + } + $this->_search['size'][$larger ? 'LARGER' : 'SMALLER'] = array_filter(array( + 'fuzzy' => !empty($opts['fuzzy']), + 'not' => $not, + 'size' => (float)$size + )); + } + + /** + * Search for messages within a given UID range. Only one message range + * can be specified per query. + * + * @param Horde_Imap_Client_Ids $ids The list of UIDs to search. + * @param boolean $not If true, do a 'NOT' search of the + * UIDs. + * @param array $opts Additional options: + * - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server + * MUST support RFC 6203. + */ + public function ids(Horde_Imap_Client_Ids $ids, $not = false, + array $opts = array()) + { + $this->_search['ids'] = array_filter(array( + 'fuzzy' => !empty($opts['fuzzy']), + 'ids' => $ids, + 'not' => $not + )); + } + + /** + * Search for messages within a date range. + * + * @param mixed $date DateTime or Horde_Date object. + * @param string $range Either: + * - Horde_Imap_Client_Search_Query::DATE_BEFORE + * - Horde_Imap_Client_Search_Query::DATE_ON + * - Horde_Imap_Client_Search_Query::DATE_SINCE + * @param boolean $header If true, search using the date in the message + * headers. If false, search using the internal + * IMAP date (usually arrival time). + * @param boolean $not If true, do a 'NOT' search of the range. + * @param array $opts Additional options: + * - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server + * MUST support RFC 6203. + */ + public function dateSearch($date, $range, $header = true, $not = false, + array $opts = array()) + { + if (!isset($this->_search['date'])) { + $this->_search['date'] = array(); + } + + // We should really be storing the raw DateTime object as data, + // but all versions of the query object have converted at this stage. + $ob = new Horde_Imap_Client_Data_Format_Date($date); + + $this->_search['date'][] = array_filter(array( + 'date' => $ob->escape(), + 'fuzzy' => !empty($opts['fuzzy']), + 'header' => $header, + 'range' => $range, + 'not' => $not + )); + } + + /** + * Search for messages within a date and time range. + * + * @param mixed $date DateTime or Horde_Date object. + * @param string $range Either: + * - Horde_Imap_Client_Search_Query::DATE_BEFORE + * - Horde_Imap_Client_Search_Query::DATE_ON + * - Horde_Imap_Client_Search_Query::DATE_SINCE + * @param boolean $header If true, search using the date in the message + * headers. If false, search using the internal + * IMAP date (usually arrival time). + * @param boolean $not If true, do a 'NOT' search of the range. + * @param array $opts Additional options: + * - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server + * MUST support RFC 6203. + */ + public function dateTimeSearch($date, $range, $header = true, $not = false, + array $opts = array()) + { + if (!isset($this->_search['date'])) { + $this->_search['date'] = array(); + } + + // We should really be storing the raw DateTime object as data, + // but all versions of the query object have converted at this stage. + $ob = new Horde_Imap_Client_Data_Format_DateTime($date); + + $this->_search['date'][] = array_filter(array( + 'date' => $ob->escape(), + 'fuzzy' => !empty($opts['fuzzy']), + 'header' => $header, + 'range' => $range, + 'not' => $not + )); + } + + /** + * Search for messages within a given interval. Only one interval of each + * type can be specified per search query. If the IMAP server supports + * the WITHIN extension (RFC 5032), it will be used. Otherwise, the + * search query will be dynamically created using IMAP4rev1 search + * terms. + * + * @param integer $interval Seconds from the present. + * @param string $range Either: + * - Horde_Imap_Client_Search_Query::INTERVAL_OLDER + * - Horde_Imap_Client_Search_Query::INTERVAL_YOUNGER + * @param boolean $not If true, do a 'NOT' search. + * @param array $opts Additional options: + * - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server + * MUST support RFC 6203. + */ + public function intervalSearch($interval, $range, $not = false, + array $opts = array()) + { + if (!isset($this->_search['within'])) { + $this->_search['within'] = array(); + } + $this->_search['within'][$range] = array( + 'fuzzy' => !empty($opts['fuzzy']), + 'interval' => $interval, + 'not' => $not + ); + } + + /** + * AND queries - the contents of this query will be AND'ed (in its + * entirety) with the contents of EACH of the queries passed in. All + * AND'd queries must share the same charset as this query. + * + * @param mixed $queries A query, or an array of queries, to AND with the + * current query. + */ + public function andSearch($queries) + { + if (!isset($this->_search['and'])) { + $this->_search['and'] = array(); + } + + if ($queries instanceof Horde_Imap_Client_Search_Query) { + $queries = array($queries); + } + + $this->_search['and'] = array_merge($this->_search['and'], $queries); + } + + /** + * OR a query - the contents of this query will be OR'ed (in its entirety) + * with the contents of EACH of the queries passed in. All OR'd queries + * must share the same charset as this query. All contents of any single + * query will be AND'ed together. + * + * @param mixed $queries A query, or an array of queries, to OR with the + * current query. + */ + public function orSearch($queries) + { + if (!isset($this->_search['or'])) { + $this->_search['or'] = array(); + } + + if ($queries instanceof Horde_Imap_Client_Search_Query) { + $queries = array($queries); + } + + $this->_search['or'] = array_merge($this->_search['or'], $queries); + } + + /** + * Search for messages modified since a specific moment. The IMAP server + * must support the CONDSTORE extension (RFC 7162) for this query to be + * used. + * + * @param integer $value The mod-sequence value. + * @param string $name The entry-name string. + * @param string $type Either 'shared', 'priv', or 'all'. Defaults to + * 'all' + * @param boolean $not If true, do a 'NOT' search. + * @param array $opts Additional options: + * - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server + * MUST support RFC 6203. + */ + public function modseq($value, $name = null, $type = null, $not = false, + array $opts = array()) + { + if (!is_null($type)) { + $type = Horde_String::lower($type); + if (!in_array($type, array('shared', 'priv', 'all'))) { + $type = 'all'; + } + } + + $this->_search['modseq'] = array_filter(array( + 'fuzzy' => !empty($opts['fuzzy']), + 'name' => $name, + 'not' => $not, + 'type' => (!is_null($name) && is_null($type)) ? 'all' : $type, + 'value' => $value + )); + } + + /** + * Use the results from the previous SEARCH command. The IMAP server must + * support the SEARCHRES extension (RFC 5182) for this query to be used. + * + * @param boolean $not If true, don't match the previous query. + * @param array $opts Additional options: + * - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server + * MUST support RFC 6203. + */ + public function previousSearch($not = false, array $opts = array()) + { + $this->_search['prevsearch'] = $not; + if (!empty($opts['fuzzy'])) { + $this->_search['prevsearchfuzzy'] = true; + } + } + + /* Serializable methods. */ + + /** + * Serialization. + * + * @return string Serialized data. + */ + public function serialize() + { + $data = array( + // Serialized data ID. + self::VERSION, + $this->_search + ); + + if (!is_null($this->_charset)) { + $data[] = $this->_charset; + } + + return serialize($data); + } + + /** + * Unserialization. + * + * @param string $data Serialized data. + * + * @throws Exception + */ + public function unserialize($data) + { + $data = @unserialize($data); + if (!is_array($data) || + !isset($data[0]) || + ($data[0] != self::VERSION)) { + throw new Exception('Cache version change'); + } + + $this->_search = $data[1]; + if (isset($data[2])) { + $this->_charset = $data[2]; + } + } + +} diff --git a/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket.php b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket.php new file mode 100644 index 00000000..12d6dfae --- /dev/null +++ b/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Socket.php @@ -0,0 +1,5167 @@ + + * - RFC 2086/4314: ACL + * - RFC 2087: QUOTA + * - RFC 2088: LITERAL+ + * - RFC 2195: AUTH=CRAM-MD5 + * - RFC 2221: LOGIN-REFERRALS + * - RFC 2342: NAMESPACE + * - RFC 2595/4616: TLS & AUTH=PLAIN + * - RFC 2831: DIGEST-MD5 authentication mechanism (obsoleted by RFC 6331) + * - RFC 2971: ID + * - RFC 3348: CHILDREN + * - RFC 3501: IMAP4rev1 specification + * - RFC 3502: MULTIAPPEND + * - RFC 3516: BINARY + * - RFC 3691: UNSELECT + * - RFC 4315: UIDPLUS + * - RFC 4422: SASL Authentication (for DIGEST-MD5) + * - RFC 4466: Collected extensions (updates RFCs 2088, 3501, 3502, 3516) + * - RFC 4469/5550: CATENATE + * - RFC 4731: ESEARCH + * - RFC 4959: SASL-IR + * - RFC 5032: WITHIN + * - RFC 5161: ENABLE + * - RFC 5182: SEARCHRES + * - RFC 5255: LANGUAGE/I18NLEVEL + * - RFC 5256: THREAD/SORT + * - RFC 5258: LIST-EXTENDED + * - RFC 5267: ESORT; PARTIAL search return option + * - RFC 5464: METADATA + * - RFC 5530: IMAP Response Codes + * - RFC 5802: AUTH=SCRAM-SHA-1 + * - RFC 5819: LIST-STATUS + * - RFC 5957: SORT=DISPLAY + * - RFC 6154: SPECIAL-USE/CREATE-SPECIAL-USE + * - RFC 6203: SEARCH=FUZZY + * - RFC 6851: MOVE + * - RFC 6855: UTF8=ACCEPT/UTF8=ONLY + * - RFC 6858: DOWNGRADED response code + * - RFC 7162: CONDSTORE/QRESYNC + *
+ * + * Implements the following non-RFC extensions: + *
+ *   - draft-ietf-morg-inthread-01: THREAD=REFS
+ *   - draft-daboo-imap-annotatemore-07: ANNOTATEMORE
+ *   - draft-daboo-imap-annotatemore-08: ANNOTATEMORE2
+ *   - XIMAPPROXY
+ *     Requires imapproxy v1.2.7-rc1 or later
+ *     See https://squirrelmail.svn.sourceforge.net/svnroot/squirrelmail/trunk/imap_proxy/README
+ *   - AUTH=XOAUTH2
+ *     https://developers.google.com/gmail/xoauth2_protocol
+ * 
+ * + * TODO (or not necessary?): + *
+ *   - RFC 2177: IDLE
+ *   - RFC 2193: MAILBOX-REFERRALS
+ *   - RFC 4467/5092/5524/5550/5593: URLAUTH, URLAUTH=BINARY, URL-PARTIAL
+ *   - RFC 4978: COMPRESS=DEFLATE
+ *     See: http://bugs.php.net/bug.php?id=48725
+ *   - RFC 5257: ANNOTATE (Experimental)
+ *   - RFC 5259: CONVERT
+ *   - RFC 5267: CONTEXT=SEARCH; CONTEXT=SORT
+ *   - RFC 5465: NOTIFY
+ *   - RFC 5466: FILTERS
+ *   - RFC 6785: IMAPSIEVE
+ *   - RFC 7377: MULTISEARCH
+ * 
+ * + * @author Michael Slusarz + * @category Horde + * @copyright 1999-2007 The SquirrelMail Project Team + * @copyright 2005-2017 Horde LLC + * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 + * @package Imap_Client + */ +class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base +{ + /** + * Cache names used exclusively within this class. + */ + const CACHE_FLAGS = 'HICflags'; + + /** + * Queued commands to send to the server. + * + * @var array + */ + protected $_cmdQueue = array(); + + /** + * The default ports to use for a connection. + * + * @var array + */ + protected $_defaultPorts = array(143, 993); + + /** + * Mapping of status fields to IMAP names. + * + * @var array + */ + protected $_statusFields = array( + 'messages' => Horde_Imap_Client::STATUS_MESSAGES, + 'recent' => Horde_Imap_Client::STATUS_RECENT, + 'uidnext' => Horde_Imap_Client::STATUS_UIDNEXT, + 'uidvalidity' => Horde_Imap_Client::STATUS_UIDVALIDITY, + 'unseen' => Horde_Imap_Client::STATUS_UNSEEN, + 'firstunseen' => Horde_Imap_Client::STATUS_FIRSTUNSEEN, + 'flags' => Horde_Imap_Client::STATUS_FLAGS, + 'permflags' => Horde_Imap_Client::STATUS_PERMFLAGS, + 'uidnotsticky' => Horde_Imap_Client::STATUS_UIDNOTSTICKY, + 'highestmodseq' => Horde_Imap_Client::STATUS_HIGHESTMODSEQ + ); + + /** + * The unique tag to use when making an IMAP query. + * + * @var integer + */ + protected $_tag = 0; + + /** + * @param array $params A hash containing configuration parameters. + * Additional parameters to base driver: + * - debug_literal: (boolean) If true, will output the raw text of + * literal responses to the debug stream. Otherwise, + * outputs a summary of the literal response. + * - envelope_addrs: (integer) The maximum number of address entries to + * read for FETCH ENVELOPE address fields. + * DEFAULT: 1000 + * - envelope_string: (integer) The maximum length of string fields + * returned by the FETCH ENVELOPE command. + * DEFAULT: 2048 + * - xoauth2_token: (mixed) If set, will authenticate via the XOAUTH2 + * mechanism (if available) with this token. Either a + * string (since 2.13.0) or a + * Horde_Imap_Client_Base_Password object (since + * 2.14.0). + */ + public function __construct(array $params = array()) + { + parent::__construct(array_merge(array( + 'debug_literal' => false, + 'envelope_addrs' => 1000, + 'envelope_string' => 2048 + ), $params)); + } + + /** + */ + public function __get($name) + { + switch ($name) { + case 'search_charset': + if (!isset($this->_init['search_charset']) && + $this->_capability()->isEnabled('UTF8=ACCEPT')) { + $this->_init['search_charset'] = new Horde_Imap_Client_Data_SearchCharset_Utf8(); + } + break; + } + + return parent::__get($name); + } + + /** + */ + public function getParam($key) + { + switch ($key) { + case 'xoauth2_token': + if (isset($this->_params[$key]) && + ($this->_params[$key] instanceof Horde_Imap_Client_Base_Password)) { + return $this->_params[$key]->getPassword(); + } + break; + } + + return parent::getParam($key); + } + + /** + */ + public function update(SplSubject $subject) + { + if (!empty($this->_init['imapproxy']) && + ($subject instanceof Horde_Imap_Client_Data_Capability_Imap)) { + $this->_setInit('enabled', $subject->isEnabled()); + } + + return parent::update($subject); + } + + /** + */ + protected function _initCapability() + { + // Need to use connect call here or else we run into loop issues + // because _connect() can generate the capability object internally. + $this->_connect(); + + // It is possible the server provided capability information on + // connect, so check for it now. + if (!isset($this->_init['capability'])) { + $this->_sendCmd($this->_command('CAPABILITY')); + } + } + + /** + * Parse a CAPABILITY Response (RFC 3501 [7.2.1]). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param array $data An array of CAPABILITY strings. + */ + protected function _parseCapability( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + $data + ) + { + if (!empty($this->_temp['no_cap'])) { + return; + } + + $pipeline->data['capability_set'] = true; + + $c = new Horde_Imap_Client_Data_Capability_Imap(); + + foreach ($data as $val) { + $cap_list = explode('=', $val); + $c->add( + $cap_list[0], + isset($cap_list[1]) ? array($cap_list[1]) : null + ); + } + + $this->_setInit('capability', $c); + } + + /** + */ + protected function _noop() + { + // NOOP doesn't return any specific response + $this->_sendCmd($this->_command('NOOP')); + } + + /** + */ + protected function _getNamespaces() + { + if ($this->_capability('NAMESPACE')) { + $data = $this->_sendCmd($this->_command('NAMESPACE'))->data; + if (isset($data['namespace'])) { + return $data['namespace']; + } + } + + return new Horde_Imap_Client_Namespace_List(); + } + + /** + * Parse a NAMESPACE response (RFC 2342 [5] & RFC 5255 [3.4]). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data The NAMESPACE data. + */ + protected function _parseNamespace( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + Horde_Imap_Client_Tokenize $data + ) + { + $namespace_array = array( + Horde_Imap_Client_Data_Namespace::NS_PERSONAL, + Horde_Imap_Client_Data_Namespace::NS_OTHER, + Horde_Imap_Client_Data_Namespace::NS_SHARED + ); + + $c = array(); + + // Per RFC 2342, response from NAMESPACE command is: + // (PERSONAL NAMESPACES) (OTHER_USERS NAMESPACE) (SHARED NAMESPACES) + foreach ($namespace_array as $val) { + $entry = $data->next(); + + if (is_null($entry)) { + continue; + } + + while ($data->next() !== false) { + $ob = Horde_Imap_Client_Mailbox::get($data->next(), true); + + $ns = new Horde_Imap_Client_Data_Namespace(); + $ns->delimiter = $data->next(); + $ns->name = strval($ob); + $ns->type = $val; + $c[strval($ob)] = $ns; + + // RFC 4466: NAMESPACE extensions + while (($ext = $data->next()) !== false) { + switch (Horde_String::upper($ext)) { + case 'TRANSLATION': + // RFC 5255 [3.4] - TRANSLATION extension + $data->next(); + $ns->translation = $data->next(); + $data->next(); + break; + } + } + } + } + + $pipeline->data['namespace'] = new Horde_Imap_Client_Namespace_List($c); + } + + /** + */ + protected function _login() + { + $secure = $this->getParam('secure'); + + if (!empty($this->_temp['preauth'])) { + unset($this->_temp['preauth']); + + /* Don't allow PREAUTH if we are requring secure access, since + * PREAUTH cannot provide secure access. */ + if (!$this->isSecureConnection() && ($secure !== false)) { + $this->logout(); + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Could not open secure TLS connection to the IMAP server."), + Horde_Imap_Client_Exception::LOGIN_TLSFAILURE + ); + } + + return $this->_loginTasks(); + } + + /* Blank passwords are not allowed, so no need to even try + * authentication to determine this. */ + if (!strlen($this->getParam('password'))) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("No password provided."), + Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED + ); + } + + $this->_connect(); + + $first_login = empty($this->_init['authmethod']); + + // Switch to secure channel if using TLS. + if (!$this->isSecureConnection() && + (($secure === 'tls') || + (($secure === true) && + $this->_capability('LOGINDISABLED')))) { + if ($first_login && !$this->_capability('STARTTLS')) { + /* We should never hit this - STARTTLS is required pursuant to + * RFC 3501 [6.2.1]. */ + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Server does not support TLS connections."), + Horde_Imap_Client_Exception::LOGIN_TLSFAILURE + ); + } + + // Switch over to a TLS connection. + // STARTTLS returns no untagged response. + $this->_sendCmd($this->_command('STARTTLS')); + + if (!$this->_connection->startTls()) { + $this->logout(); + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Could not open secure TLS connection to the IMAP server."), + Horde_Imap_Client_Exception::LOGIN_TLSFAILURE + ); + } + + $this->_debug->info('Successfully completed TLS negotiation.'); + + $this->setParam('secure', 'tls'); + $secure = 'tls'; + + if ($first_login) { + // Expire cached CAPABILITY information (RFC 3501 [6.2.1]) + $this->_setInit('capability'); + + // Reset language (RFC 5255 [3.1]) + $this->_setInit('lang'); + } + + // Set language if using imapproxy + if (!empty($this->_init['imapproxy'])) { + $this->setLanguage(); + } + } + + /* If we reached this point and don't have a secure connection, then + * a secure connections is not available. */ + if (($secure === true) && !$this->isSecureConnection()) { + $this->setParam('secure', false); + $secure = false; + } + + if ($first_login) { + // Add authentication methods. + $auth_mech = array(); + $auth = array_flip($this->_capability()->getParams('AUTH')); + + // XOAUTH2 + if (isset($auth['XOAUTH2']) && $this->getParam('xoauth2_token')) { + $auth_mech[] = 'XOAUTH2'; + } + unset($auth['XOAUTH2']); + + /* 'AUTH=PLAIN' authentication always exists if under TLS (RFC 3501 + * [7.2.1]; RFC 2595), even though we might get here with a + * non-TLS secure connection too. Use it over all other + * authentication methods, although we need to do sanity checking + * since broken IMAP servers may not support as required - + * fallback to LOGIN instead, if not explicitly disabled. */ + if ($secure) { + if (isset($auth['PLAIN'])) { + $auth_mech[] = 'PLAIN'; + unset($auth['PLAIN']); + } elseif (!$this->_capability('LOGINDISABLED')) { + $auth_mech[] = 'LOGIN'; + } + } + + // Check for supported SCRAM AUTH mechanisms. Preferred because it + // provides verification of server authenticity. + foreach (array_keys($auth) as $key) { + switch ($key) { + case 'SCRAM-SHA-1': + $auth_mech[] = $key; + unset($auth[$key]); + break; + } + } + + // Check for supported CRAM AUTH mechanisms. + foreach (array_keys($auth) as $key) { + switch ($key) { + case 'CRAM-SHA1': + case 'CRAM-SHA256': + $auth_mech[] = $key; + unset($auth[$key]); + break; + } + } + + // Prefer CRAM-MD5 over DIGEST-MD5, as the latter has been + // obsoleted (RFC 6331). + if (isset($auth['CRAM-MD5'])) { + $auth_mech[] = 'CRAM-MD5'; + } elseif (isset($auth['DIGEST-MD5'])) { + $auth_mech[] = 'DIGEST-MD5'; + } + unset($auth['CRAM-MD5'], $auth['DIGEST-MD5']); + + // Add other auth mechanisms. + $auth_mech = array_merge($auth_mech, array_keys($auth)); + + // Fall back to 'LOGIN' if available. + if (!$secure && !$this->_capability('LOGINDISABLED')) { + $auth_mech[] = 'LOGIN'; + } + + if (empty($auth_mech)) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("No supported IMAP authentication method could be found."), + Horde_Imap_Client_Exception::LOGIN_NOAUTHMETHOD + ); + } + + $auth_mech = array_unique($auth_mech); + } else { + $auth_mech = array($this->_init['authmethod']); + } + + $login_err = null; + + foreach ($auth_mech as $method) { + try { + $resp = $this->_tryLogin($method); + $data = $resp->data; + $this->_setInit('authmethod', $method); + unset($this->_temp['referralcount']); + } catch (Horde_Imap_Client_Exception_ServerResponse $e) { + $data = $e->resp_data; + if (isset($data['loginerr'])) { + $login_err = $data['loginerr']; + } + $resp = false; + } catch (Horde_Imap_Client_Exception $e) { + $resp = false; + } + + // Check for login referral (RFC 2221) response - can happen for + // an OK, NO, or BYE response. + if (isset($data['referral'])) { + foreach (array('host', 'port', 'username') as $val) { + if (!is_null($data['referral']->$val)) { + $this->setParam($val, $data['referral']->$val); + } + } + + if (!is_null($data['referral']->auth)) { + $this->_setInit('authmethod', $data['referral']->auth); + } + + if (!isset($this->_temp['referralcount'])) { + $this->_temp['referralcount'] = 0; + } + + // RFC 2221 [3] - Don't follow more than 10 levels of referral + // without consulting the user. + if (++$this->_temp['referralcount'] < 10) { + $this->logout(); + $this->_setInit('capability'); + $this->_setInit('namespace'); + return $this->login(); + } + + unset($this->_temp['referralcount']); + } + + if ($resp) { + return $this->_loginTasks($first_login, $resp->data); + } + } + + /* Try again from scratch if authentication failed in an established, + * previously-authenticated object. */ + if (!empty($this->_init['authmethod'])) { + $this->_setInit(); + unset($this->_temp['no_cap']); + try { + return $this->_login(); + } catch (Horde_Imap_Client_Exception $e) {} + } + + /* Default to AUTHENTICATIONFAILED error (see RFC 5530[3]). */ + if (is_null($login_err)) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Mail server denied authentication."), + Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED + ); + } + + throw $login_err; + } + + /** + * Connects to the IMAP server. + * + * @throws Horde_Imap_Client_Exception + */ + protected function _connect() + { + if (!is_null($this->_connection)) { + return; + } + + try { + $this->_connection = new Horde_Imap_Client_Socket_Connection_Socket( + $this->getParam('hostspec'), + $this->getParam('port'), + $this->getParam('timeout'), + $this->getParam('secure'), + $this->getParam('context'), + array( + 'debug' => $this->_debug, + 'debugliteral' => $this->getParam('debug_literal') + ) + ); + } catch (Horde\Socket\Client\Exception $e) { + $e2 = new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Error connecting to mail server."), + Horde_Imap_Client_Exception::SERVER_CONNECT + ); + $e2->details = $e->details; + throw $e2; + } + + // If we already have capability information, don't re-set with + // (possibly) limited information sent in the initial banner. + if (isset($this->_init['capability'])) { + $this->_temp['no_cap'] = true; + } + + /* Get greeting information (untagged response). */ + try { + $this->_getLine($this->_pipeline()); + } catch (Horde_Imap_Client_Exception_ServerResponse $e) { + if ($e->status === Horde_Imap_Client_Interaction_Server::BYE) { + /* Server is explicitly rejecting our connection (RFC 3501 + * [7.1.5]). */ + $e->setMessage(Horde_Imap_Client_Translation::r("Server rejected connection.")); + $e->setCode(Horde_Imap_Client_Exception::SERVER_CONNECT); + } + throw $e; + } + + // Check for IMAP4rev1 support + if (!$this->_capability('IMAP4REV1')) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("The mail server does not support IMAP4rev1 (RFC 3501)."), + Horde_Imap_Client_Exception::SERVER_CONNECT + ); + } + + // Set language if NOT using imapproxy + if (empty($this->_init['imapproxy'])) { + if ($this->_capability('XIMAPPROXY')) { + $this->_setInit('imapproxy', true); + } else { + $this->setLanguage(); + } + } + + // If pre-authenticated, we need to do all login tasks now. + if (!empty($this->_temp['preauth'])) { + $this->login(); + } + } + + /** + * Authenticate to the IMAP server. + * + * @param string $method IMAP login method. + * + * @return Horde_Imap_Client_Interaction_Pipeline Pipeline object. + * + * @throws Horde_Imap_Client_Exception + */ + protected function _tryLogin($method) + { + $username = $this->getParam('username'); + if (is_null($authusername = $this->getParam('authusername'))) { + $authusername = $username; + } + $password = $this->getParam('password'); + + switch ($method) { + case 'CRAM-MD5': + case 'CRAM-SHA1': + case 'CRAM-SHA256': + // RFC 2195: CRAM-MD5 + // CRAM-SHA1 & CRAM-SHA256 supported by Courier SASL library + + $args = array( + $username, + Horde_String::lower(substr($method, 5)), + $password + ); + + $cmd = $this->_command('AUTHENTICATE')->add(array( + $method, + new Horde_Imap_Client_Interaction_Command_Continuation(function($ob) use ($args) { + return new Horde_Imap_Client_Data_Format_List( + base64_encode($args[0] . ' ' . hash_hmac($args[1], base64_decode($ob->token->current()), $args[2], false)) + ); + }) + )); + $cmd->debug = array( + null, + sprintf('[AUTHENTICATE response (username: %s)]', $username) + ); + break; + + case 'DIGEST-MD5': + // RFC 2831/4422; obsoleted by RFC 6331 + + // Need $args because PHP 5.3 doesn't allow access to $this in + // anonymous functions. + $args = array( + $username, + $password, + $this->getParam('hostspec') + ); + + $cmd = $this->_command('AUTHENTICATE')->add(array( + $method, + new Horde_Imap_Client_Interaction_Command_Continuation(function($ob) use ($args) { + return new Horde_Imap_Client_Data_Format_List( + base64_encode(new Horde_Imap_Client_Auth_DigestMD5( + $args[0], + $args[1], + base64_decode($ob->token->current()), + $args[2], + 'imap' + )) + ); + }), + new Horde_Imap_Client_Interaction_Command_Continuation(function($ob) { + if (strpos(base64_decode($ob->token->current()), 'rspauth=') === false) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Unexpected response from server when authenticating."), + Horde_Imap_Client_Exception::SERVER_CONNECT + ); + } + + return new Horde_Imap_Client_Data_Format_List(); + }) + )); + $cmd->debug = array( + null, + sprintf('[AUTHENTICATE Response (username: %s)]', $username), + null + ); + break; + + case 'LOGIN': + /* See, e.g., RFC 6855 [5] - LOGIN command does not support + * non-ASCII characters. If we reach this point, treat as an + * authentication failure. */ + try { + $username = new Horde_Imap_Client_Data_Format_Astring($username); + $password = new Horde_Imap_Client_Data_Format_Astring($password); + } catch (Horde_Imap_Client_Data_Format_Exception $e) { + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Authentication failed."), + Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED + ); + } + + $cmd = $this->_command('LOGIN')->add(array( + $username, + $password + )); + $cmd->debug = array( + sprintf('LOGIN %s [PASSWORD]', $username) + ); + break; + + case 'PLAIN': + // RFC 2595/4616 - PLAIN SASL mechanism + $cmd = $this->_authInitialResponse( + $method, + base64_encode(implode("\0", array( + $username, + $authusername, + $password + ))), + $username + ); + break; + + case 'SCRAM-SHA-1': + $scram = new Horde_Imap_Client_Auth_Scram( + $username, + $password, + 'SHA1' + ); + + $cmd = $this->_authInitialResponse( + $method, + base64_encode($scram->getClientFirstMessage()) + ); + + $cmd->add( + new Horde_Imap_Client_Interaction_Command_Continuation(function($ob) use ($scram) { + $sr1 = base64_decode($ob->token->current()); + return new Horde_Imap_Client_Data_Format_List( + $scram->parseServerFirstMessage($sr1) + ? base64_encode($scram->getClientFinalMessage()) + : '*' + ); + }) + ); + + $self = $this; + $cmd->add( + new Horde_Imap_Client_Interaction_Command_Continuation(function($ob) use ($scram, $self) { + $sr2 = base64_decode($ob->token->current()); + if (!$scram->parseServerFinalMessage($sr2)) { + /* This means authentication passed, according to the + * server, but the server signature is incorrect. + * This indicates that server verification has failed. + * Immediately disconnect from the server, since this + * is a possible security issue. */ + $self->logout(); + throw new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Server failed verification check."), + Horde_Imap_Client_Exception::LOGIN_SERVER_VERIFICATION_FAILED + ); + } + + return new Horde_Imap_Client_Data_Format_List(); + }) + ); + break; + + case 'XOAUTH2': + // Google XOAUTH2 + $cmd = $this->_authInitialResponse( + $method, + $this->getParam('xoauth2_token') + ); + + /* This is an optional command continuation. XOAUTH2 will return + * error information in continuation response. */ + $error_continuation = new Horde_Imap_Client_Interaction_Command_Continuation( + function($ob) { + return new Horde_Imap_Client_Data_Format_List(); + } + ); + $error_continuation->optional = true; + $cmd->add($error_continuation); + break; + + default: + $e = new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Unknown authentication method: %s"), + Horde_Imap_Client_Exception::SERVER_CONNECT + ); + $e->messagePrintf(array($method)); + throw $e; + } + + return $this->_sendCmd($this->_pipeline($cmd)); + } + + /** + * Create the AUTHENTICATE command for the initial client response. + * + * @param string $method AUTHENTICATE SASL method. + * @param string $ir Initial client response. + * @param string $username If set, log a username message in debug log + * instead of raw data. + * + * @return Horde_Imap_Client_Interaction_Command A command object. + */ + protected function _authInitialResponse($method, $ir, $username = null) + { + $cmd = $this->_command('AUTHENTICATE')->add($method); + + if ($this->_capability('SASL-IR')) { + // IMAP Extension for SASL Initial Client Response (RFC 4959) + $cmd->add($ir); + if ($username) { + $cmd->debug = array( + sprintf('AUTHENTICATE %s [INITIAL CLIENT RESPONSE (username: %s)]', $method, $username) + ); + } + } else { + $cmd->add( + new Horde_Imap_Client_Interaction_Command_Continuation(function($ob) use ($ir) { + return new Horde_Imap_Client_Data_Format_List($ir); + }) + ); + if ($username) { + $cmd->debug = array( + null, + sprintf('[INITIAL CLIENT RESPONSE (username: %s)]', $username) + ); + } + } + + return $cmd; + } + + /** + * Perform login tasks. + * + * @param boolean $firstlogin Is this the first login? + * @param array $resp The data response from the login command. + * May include: + * - capability_set: (boolean) True if CAPABILITY was set after login. + * - proxyreuse: (boolean) True if re-used connection via imapproxy. + * + * @return boolean True if global login tasks should be performed. + */ + protected function _loginTasks($firstlogin = true, array $resp = array()) + { + /* If reusing an imapproxy connection, no need to do any of these + * login tasks again. */ + if (!$firstlogin && !empty($resp['proxyreuse'])) { + if (isset($this->_init['enabled'])) { + foreach ($this->_init['enabled'] as $val) { + $this->_capability()->enable($val); + } + } + + // If we have not yet set the language, set it now. + if (!isset($this->_init['lang'])) { + $this->_temp['lang_queue'] = true; + $this->setLanguage(); + unset($this->_temp['lang_queue']); + } + return false; + } + + /* If we logged in for first time, and server did not return + * capability information, we need to mark for retrieval. */ + if ($firstlogin && empty($resp['capability_set'])) { + $this->_setInit('capability'); + } + + $this->_temp['lang_queue'] = true; + $this->setLanguage(); + unset($this->_temp['lang_queue']); + + /* Only active QRESYNC/CONDSTORE if caching is enabled. */ + $enable = array(); + if ($this->_initCache()) { + if ($this->_capability('QRESYNC')) { + $enable[] = 'QRESYNC'; + } elseif ($this->_capability('CONDSTORE')) { + $enable[] = 'CONDSTORE'; + } + } + + /* Use UTF8=ACCEPT, if available. */ + if ($this->_capability('UTF8', 'ACCEPT')) { + $enable[] = 'UTF8=ACCEPT'; + } + + $this->_enable($enable); + + return true; + } + + /** + */ + protected function _logout() + { + if (empty($this->_temp['logout'])) { + /* If using imapproxy, force sending these commands, since they + * may not be sent again if they are (likely) initialization + * commands. */ + if (!empty($this->_cmdQueue) && + !empty($this->_init['imapproxy'])) { + $this->_sendCmd($this->_pipeline()); + } + + $this->_temp['logout'] = true; + try { + $this->_sendCmd($this->_command('LOGOUT')); + } catch (Horde_Imap_Client_Exception_ServerResponse $e) { + // Ignore server errors + } + unset($this->_temp['logout']); + } + } + + /** + */ + protected function _sendID($info) + { + $cmd = $this->_command('ID'); + + if (empty($info)) { + $cmd->add(new Horde_Imap_Client_Data_Format_Nil()); + } else { + $tmp = new Horde_Imap_Client_Data_Format_List(); + foreach ($info as $key => $val) { + $tmp->add(array( + new Horde_Imap_Client_Data_Format_String(Horde_String::lower($key)), + new Horde_Imap_Client_Data_Format_Nstring($val) + )); + } + $cmd->add($tmp); + } + + $temp = &$this->_temp; + + /* Add to queue - this doesn't need to be sent immediately. */ + $cmd->on_error = function() use (&$temp) { + /* Ignore server errors. E.g. Cyrus returns this: + * 001 NO Only one Id allowed in non-authenticated state + * even though NO is not allowed in RFC 2971[3.1]. */ + $temp['id'] = array(); + return true; + }; + $cmd->on_success = function() use ($cmd, &$temp) { + $temp['id'] = $cmd->pipeline->data['id']; + }; + $this->_cmdQueue[] = $cmd; + } + + /** + * Parse an ID response (RFC 2971 [3.2]). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data The server response. + */ + protected function _parseID( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + Horde_Imap_Client_Tokenize $data + ) + { + if (!isset($pipeline->data['id'])) { + $pipeline->data['id'] = array(); + } + + if (!is_null($data->next())) { + while (($curr = $data->next()) !== false) { + if (!is_null($id = $data->next())) { + $pipeline->data['id'][$curr] = $id; + } + } + } + } + + /** + */ + protected function _getID() + { + if (!isset($this->_temp['id'])) { + $this->sendID(); + /* ID is queued - force sending the queued command. */ + $this->_sendCmd($this->_pipeline()); + } + + return $this->_temp['id']; + } + + /** + */ + protected function _setLanguage($langs) + { + $cmd = $this->_command('LANGUAGE'); + foreach ($langs as $lang) { + $cmd->add(new Horde_Imap_Client_Data_Format_Astring($lang)); + } + + if (!empty($this->_temp['lang_queue'])) { + $this->_cmdQueue[] = $cmd; + return array(); + } + + try { + $this->_sendCmd($cmd); + } catch (Horde_Imap_Client_Exception $e) { + $this->_setInit('lang', false); + return null; + } + + return $this->_init['lang']; + } + + /** + */ + protected function _getLanguage($list) + { + if (!$list) { + return empty($this->_init['lang']) + ? null + : $this->_init['lang']; + } + + if (!isset($this->_init['langavail'])) { + try { + $this->_sendCmd($this->_command('LANGUAGE')); + } catch (Horde_Imap_Client_Exception $e) { + $this->_setInit('langavail', array()); + } + } + + return $this->_init['langavail']; + } + + /** + * Parse a LANGUAGE response (RFC 5255 [3.3]). + * + * @param Horde_Imap_Client_Tokenize $data The server response. + */ + protected function _parseLanguage(Horde_Imap_Client_Tokenize $data) + { + $lang_list = $data->flushIterator(); + + if (count($lang_list) === 1) { + // This is the language that was set. + $this->_setInit('lang', reset($lang_list)); + } else { + // These are the languages that are available. + $this->_setInit('langavail', $lang_list); + } + } + + /** + * Enable an IMAP extension (see RFC 5161). + * + * @param array $exts The extensions to enable. + * + * @throws Horde_Imap_Client_Exception + */ + protected function _enable($exts) + { + if (!empty($exts) && $this->_capability('ENABLE')) { + $c = $this->_capability(); + $todo = array(); + + // Only enable non-enabled extensions. + foreach ($exts as $val) { + if (!$c->isEnabled($val)) { + $c->enable($val); + $todo[] = $val; + } + } + + if (!empty($todo)) { + $cmd = $this->_command('ENABLE')->add($todo); + $cmd->on_error = function() use ($todo, $c) { + /* Something went wrong... disable the extensions. */ + foreach ($todo as $val) { + $c->enable($val, false); + } + }; + $this->_cmdQueue[] = $cmd; + } + } + } + + /** + * Parse an ENABLED response (RFC 5161 [3.2]). + * + * @param Horde_Imap_Client_Tokenize $data The server response. + */ + protected function _parseEnabled(Horde_Imap_Client_Tokenize $data) + { + $c = $this->_capability(); + + foreach ($data->flushIterator() as $val) { + $c->enable($val); + } + } + + /** + */ + protected function _openMailbox(Horde_Imap_Client_Mailbox $mailbox, $mode) + { + $c = $this->_capability(); + $qresync = $c->isEnabled('QRESYNC'); + + $cmd = $this->_command( + ($mode == Horde_Imap_Client::OPEN_READONLY) ? 'EXAMINE' : 'SELECT' + )->add( + $this->_getMboxFormatOb($mailbox) + ); + $pipeline = $this->_pipeline($cmd); + + /* If QRESYNC is available, synchronize the mailbox. */ + if ($qresync) { + $this->_initCache(); + $md = $this->_cache->getMetaData($mailbox, null, array(self::CACHE_MODSEQ, 'uidvalid')); + + /* CACHE_MODSEQ can be set but 0 (NOMODSEQ was returned). */ + if (!empty($md[self::CACHE_MODSEQ])) { + if ($uids = $this->_cache->get($mailbox)) { + $uids = $this->getIdsOb($uids); + + /* Check for extra long UID string. Assume that any + * server that can handle QRESYNC can also handle long + * input strings (at least 8 KB), so 7 KB is as good as + * any guess as to an upper limit. If this occurs, provide + * a range string (min -> max) instead. */ + if (strlen($uid_str = $uids->tostring_sort) > 7000) { + $uid_str = $uids->range_string; + } + } else { + $uid_str = null; + } + + /* Several things can happen with a QRESYNC: + * 1. UIDVALIDITY may have changed. If so, we need to expire + * the cache immediately (done below). + * 2. NOMODSEQ may have been returned. We can keep current + * message cache data but won't be able to do flag caching. + * 3. VANISHED/FETCH information was returned. These responses + * will have already been handled by those response handlers. + * 4. We are already synced with the local server in which + * case it acts like a normal EXAMINE/SELECT. */ + $cmd->add(new Horde_Imap_Client_Data_Format_List(array( + 'QRESYNC', + new Horde_Imap_Client_Data_Format_List(array_filter(array( + $md['uidvalid'], + $md[self::CACHE_MODSEQ], + $uid_str + ))) + ))); + } + + /* Let the 'CLOSED' response code handle mailbox switching if + * QRESYNC is active. */ + if ($this->_selected) { + $pipeline->data['qresyncmbox'] = array($mailbox, $mode); + } else { + $this->_changeSelected($mailbox, $mode); + } + } else { + if (!$c->isEnabled('CONDSTORE') && + $this->_initCache() && + $c->query('CONDSTORE')) { + /* Activate CONDSTORE now if ENABLE is not available. */ + $cmd->add(new Horde_Imap_Client_Data_Format_List('CONDSTORE')); + $c->enable('CONDSTORE'); + } + + $this->_changeSelected($mailbox, $mode); + } + + try { + $this->_sendCmd($pipeline); + } catch (Horde_Imap_Client_Exception_ServerResponse $e) { + // An EXAMINE/SELECT failure with a return of 'NO' will cause the + // current mailbox to be unselected. + if ($e->status === Horde_Imap_Client_Interaction_Server::NO) { + $this->_changeSelected(null); + $this->_mode = 0; + if (!$e->getCode()) { + $e = new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Could not open mailbox \"%s\"."), + Horde_Imap_Client_Exception::MAILBOX_NOOPEN + ); + $e->messagePrintf(array($mailbox)); + } + } + throw $e; + } + + if ($qresync) { + /* Mailbox is fully sync'd. */ + $this->_mailboxOb()->sync = true; + } + } + + /** + */ + protected function _createMailbox(Horde_Imap_Client_Mailbox $mailbox, $opts) + { + $cmd = $this->_command('CREATE')->add( + $this->_getMboxFormatOb($mailbox) + ); + + // RFC 6154 Sec. 3 + if (!empty($opts['special_use'])) { + $use = new Horde_Imap_Client_Data_Format_List('USE'); + $use->add( + new Horde_Imap_Client_Data_Format_List($opts['special_use']) + ); + $cmd->add($use); + } + + // CREATE returns no untagged information (RFC 3501 [6.3.3]) + $this->_sendCmd($cmd); + } + + /** + */ + protected function _deleteMailbox(Horde_Imap_Client_Mailbox $mailbox) + { + // Some IMAP servers will not allow a delete of a currently open + // mailbox. + if ($mailbox->equals($this->_selected)) { + $this->close(); + } + + $cmd = $this->_command('DELETE')->add( + $this->_getMboxFormatOb($mailbox) + ); + + try { + // DELETE returns no untagged information (RFC 3501 [6.3.4]) + $this->_sendCmd($cmd); + } catch (Horde_Imap_Client_Exception $e) { + // Some IMAP servers won't allow a mailbox delete unless all + // messages in that mailbox are deleted. + $this->expunge($mailbox, array( + 'delete' => true + )); + $this->_sendCmd($cmd); + } + } + + /** + */ + protected function _renameMailbox(Horde_Imap_Client_Mailbox $old, + Horde_Imap_Client_Mailbox $new) + { + // Some IMAP servers will not allow a rename of a currently open + // mailbox. + if ($old->equals($this->_selected)) { + $this->close(); + } + + // RENAME returns no untagged information (RFC 3501 [6.3.5]) + $this->_sendCmd( + $this->_command('RENAME')->add(array( + $this->_getMboxFormatOb($old), + $this->_getMboxFormatOb($new) + )) + ); + } + + /** + */ + protected function _subscribeMailbox(Horde_Imap_Client_Mailbox $mailbox, + $subscribe) + { + // SUBSCRIBE/UNSUBSCRIBE returns no untagged information (RFC 3501 + // [6.3.6 & 6.3.7]) + $this->_sendCmd( + $this->_command( + $subscribe ? 'SUBSCRIBE' : 'UNSUBSCRIBE' + )->add( + $this->_getMboxFormatOb($mailbox) + ) + ); + } + + /** + */ + protected function _listMailboxes($pattern, $mode, $options) + { + // RFC 5258 [3.1]: Use LSUB for MBOX_SUBSCRIBED if no other server + // return options are specified. + if (($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) && + !array_intersect(array_keys($options), array('attributes', 'children', 'recursivematch', 'remote', 'special_use', 'status'))) { + return $this->_getMailboxList( + $pattern, + Horde_Imap_Client::MBOX_SUBSCRIBED, + array( + 'flat' => !empty($options['flat']), + 'no_listext' => true + ) + ); + } + + // Get the list of subscribed/unsubscribed mailboxes. Since LSUB is + // not guaranteed to have correct attributes, we must use LIST to + // ensure we receive the correct information. + if (($mode != Horde_Imap_Client::MBOX_ALL) && + !$this->_capability('LIST-EXTENDED')) { + $subscribed = $this->_getMailboxList( + $pattern, + Horde_Imap_Client::MBOX_SUBSCRIBED, + array('flat' => true) + ); + + // If mode is subscribed, and 'flat' option is true, we can + // return now. + if (($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) && + !empty($options['flat'])) { + return $subscribed; + } + } else { + $subscribed = null; + } + + return $this->_getMailboxList($pattern, $mode, $options, $subscribed); + } + + /** + * Obtain a list of mailboxes. + * + * @param array $pattern The mailbox search pattern(s). + * @param integer $mode Which mailboxes to return. + * @param array $options Additional options. 'no_listext' will skip + * using the LIST-EXTENDED capability. + * @param array $subscribed A list of subscribed mailboxes. + * + * @return array See listMailboxes((). + * + * @throws Horde_Imap_Client_Exception + */ + protected function _getMailboxList($pattern, $mode, $options, + $subscribed = null) + { + // Setup entry for use in _parseList(). + $pipeline = $this->_pipeline(); + $pipeline->data['mailboxlist'] = array( + 'ext' => false, + 'mode' => $mode, + 'opts' => $options, + /* Can't use array_merge here because it will destroy any mailbox + * name (key) that is "numeric". */ + 'sub' => (is_null($subscribed) ? null : array_flip(array_map('strval', $subscribed)) + array('INBOX' => true)) + ); + $pipeline->data['listresponse'] = array(); + + $cmds = array(); + $return_opts = new Horde_Imap_Client_Data_Format_List(); + + if ($this->_capability('LIST-EXTENDED') && + empty($options['no_listext'])) { + $cmd = $this->_command('LIST'); + $pipeline->data['mailboxlist']['ext'] = true; + + $select_opts = new Horde_Imap_Client_Data_Format_List(); + $subscribed = false; + + switch ($mode) { + case Horde_Imap_Client::MBOX_ALL_SUBSCRIBED: + case Horde_Imap_Client::MBOX_UNSUBSCRIBED: + $return_opts->add('SUBSCRIBED'); + break; + + case Horde_Imap_Client::MBOX_SUBSCRIBED: + case Horde_Imap_Client::MBOX_SUBSCRIBED_EXISTS: + $select_opts->add('SUBSCRIBED'); + $return_opts->add('SUBSCRIBED'); + $subscribed = true; + break; + } + + if (!empty($options['remote'])) { + $select_opts->add('REMOTE'); + } + + if (!empty($options['recursivematch'])) { + $select_opts->add('RECURSIVEMATCH'); + } + + if (!empty($select_opts)) { + $cmd->add($select_opts); + } + + $cmd->add(''); + + $tmp = new Horde_Imap_Client_Data_Format_List(); + foreach ($pattern as $val) { + if ($subscribed && (strcasecmp($val, 'INBOX') === 0)) { + $cmds[] = $this->_command('LIST')->add(array( + '', + 'INBOX' + )); + } else { + $tmp->add($this->_getMboxFormatOb($val, true)); + } + } + + if (count($tmp)) { + $cmd->add($tmp); + $cmds[] = $cmd; + } + + if (!empty($options['children'])) { + $return_opts->add('CHILDREN'); + } + + if (!empty($options['special_use'])) { + $return_opts->add('SPECIAL-USE'); + } + } else { + foreach ($pattern as $val) { + $cmds[] = $this->_command( + ($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) ? 'LSUB' : 'LIST' + )->add(array( + '', + $this->_getMboxFormatOb($val, true) + )); + } + } + + /* LIST-STATUS does NOT depend on LIST-EXTENDED. */ + if (!empty($options['status']) && + $this->_capability('LIST-STATUS')) { + $available_status = array( + Horde_Imap_Client::STATUS_MESSAGES, + Horde_Imap_Client::STATUS_RECENT, + Horde_Imap_Client::STATUS_UIDNEXT, + Horde_Imap_Client::STATUS_UIDVALIDITY, + Horde_Imap_Client::STATUS_UNSEEN, + Horde_Imap_Client::STATUS_HIGHESTMODSEQ + ); + + $status_opts = array(); + foreach (array_intersect($this->_statusFields, $available_status) as $key => $val) { + if ($options['status'] & $val) { + $status_opts[] = $key; + } + } + + if (count($status_opts)) { + $return_opts->add(array( + 'STATUS', + new Horde_Imap_Client_Data_Format_List( + array_map('Horde_String::upper', $status_opts) + ) + )); + } + } + + foreach ($cmds as $val) { + if (count($return_opts)) { + $val->add(array( + 'RETURN', + $return_opts + )); + } + + $pipeline->add($val); + } + + try { + $lr = $this->_sendCmd($pipeline)->data['listresponse']; + } catch (Horde_Imap_Client_Exception_ServerResponse $e) { + /* Archiveopteryx 3.1.3 can't process empty list-select-opts list. + * Retry using base IMAP4rev1 functionality. */ + if (($e->status === Horde_Imap_Client_Interaction_Server::BAD) && + $this->_capability('LIST-EXTENDED')) { + $this->_capability()->remove('LIST-EXTENDED'); + return $this->_listMailboxes($pattern, $mode, $options); + } + + throw $e; + } + + if (!empty($options['flat'])) { + return array_values($lr); + } + + /* Add in STATUS return, if needed. */ + if (!empty($options['status']) && $this->_capability('LIST-STATUS')) { + foreach($lr as $val_utf8 => $tmp) { + $lr[$val_utf8]['status'] = $this->_prepareStatusResponse($status_opts, $val_utf8); + } + } + + return $lr; + } + + /** + * Parse a LIST/LSUB response (RFC 3501 [7.2.2 & 7.2.3]). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data The server response (includes + * type as first token). + * + * @throws Horde_Imap_Client_Exception + */ + protected function _parseList( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + Horde_Imap_Client_Tokenize $data + ) + { + $data->next(); + $attr = null; + $attr_raw = $data->flushIterator(); + $delimiter = $data->next(); + $mbox = Horde_Imap_Client_Mailbox::get( + $data->next(), + !$this->_capability()->isEnabled('UTF8=ACCEPT') + ); + $ml = $pipeline->data['mailboxlist']; + + switch ($ml['mode']) { + case Horde_Imap_Client::MBOX_ALL_SUBSCRIBED: + case Horde_Imap_Client::MBOX_SUBSCRIBED_EXISTS: + case Horde_Imap_Client::MBOX_UNSUBSCRIBED: + $attr = array_flip(array_map('Horde_String::lower', $attr_raw)); + + /* Subscribed list is in UTF-8. */ + if (is_null($ml['sub']) && + !isset($attr['\\subscribed']) && + (strcasecmp($mbox, 'INBOX') === 0)) { + $attr['\\subscribed'] = 1; + } elseif (isset($ml['sub'][strval($mbox)])) { + $attr['\\subscribed'] = 1; + } + break; + } + + switch ($ml['mode']) { + case Horde_Imap_Client::MBOX_SUBSCRIBED_EXISTS: + if (isset($attr['\\nonexistent']) || + !isset($attr['\\subscribed'])) { + return; + } + break; + + case Horde_Imap_Client::MBOX_UNSUBSCRIBED: + if (isset($attr['\\subscribed'])) { + return; + } + break; + } + + if (!empty($ml['opts']['flat'])) { + $pipeline->data['listresponse'][] = $mbox; + return; + } + + $tmp = array( + 'delimiter' => $delimiter, + 'mailbox' => $mbox + ); + + if ($attr || !empty($ml['opts']['attributes'])) { + if (is_null($attr)) { + $attr = array_flip(array_map('Horde_String::lower', $attr_raw)); + } + + /* RFC 5258 [3.4]: inferred attributes. */ + if ($ml['ext']) { + if (isset($attr['\\noinferiors'])) { + $attr['\\hasnochildren'] = 1; + } + if (isset($attr['\\nonexistent'])) { + $attr['\\noselect'] = 1; + } + } + $tmp['attributes'] = array_keys($attr); + } + + if ($data->next() !== false) { + $tmp['extended'] = $data->flushIterator(); + } + + $pipeline->data['listresponse'][strval($mbox)] = $tmp; + } + + /** + */ + protected function _status($mboxes, $flags) + { + $on_error = null; + $out = $to_process = array(); + $pipeline = $this->_pipeline(); + $unseen_flags = array( + Horde_Imap_Client::STATUS_FIRSTUNSEEN, + Horde_Imap_Client::STATUS_UNSEEN + ); + + foreach ($mboxes as $mailbox) { + /* If FLAGS/PERMFLAGS/UIDNOTSTICKY/FIRSTUNSEEN are needed, we must + * do a SELECT/EXAMINE to get this information (data will be + * caught in the code below). */ + if (($flags & Horde_Imap_Client::STATUS_FIRSTUNSEEN) || + ($flags & Horde_Imap_Client::STATUS_FLAGS) || + ($flags & Horde_Imap_Client::STATUS_PERMFLAGS) || + ($flags & Horde_Imap_Client::STATUS_UIDNOTSTICKY)) { + $this->openMailbox($mailbox); + } + + $mbox_ob = $this->_mailboxOb($mailbox); + $data = $query = array(); + + foreach ($this->_statusFields as $key => $val) { + if (!($val & $flags)) { + continue; + } + + if ($val == Horde_Imap_Client::STATUS_HIGHESTMODSEQ) { + $c = $this->_capability(); + + /* Don't include modseq returns if server does not support + * it. */ + if (!$c->query('CONDSTORE')) { + continue; + } + + /* Even though CONDSTORE is available, it may not yet have + * been enabled. */ + $c->enable('CONDSTORE'); + $on_error = function() use ($c) { + $c->enable('CONDSTORE', false); + }; + } + + if ($mailbox->equals($this->_selected)) { + if (!is_null($tmp = $mbox_ob->getStatus($val))) { + $data[$key] = $tmp; + } elseif (($val == Horde_Imap_Client::STATUS_UIDNEXT) && + ($flags & Horde_Imap_Client::STATUS_UIDNEXT_FORCE)) { + /* UIDNEXT is not mandatory. */ + if ($mbox_ob->getStatus(Horde_Imap_Client::STATUS_MESSAGES) == 0) { + $data[$key] = 0; + } else { + $fquery = new Horde_Imap_Client_Fetch_Query(); + $fquery->uid(); + $fetch_res = $this->fetch($this->_selected, $fquery, array( + 'ids' => $this->getIdsOb(Horde_Imap_Client_Ids::LARGEST) + )); + $data[$key] = $fetch_res->first()->getUid() + 1; + } + } elseif (in_array($val, $unseen_flags)) { + /* RFC 3501 [6.3.1] - FIRSTUNSEEN information is not + * mandatory. If missing in EXAMINE/SELECT results, we + * need to do a search. An UNSEEN count also requires + * a search. */ + $squery = new Horde_Imap_Client_Search_Query(); + $squery->flag(Horde_Imap_Client::FLAG_SEEN, false); + $search = $this->search($mailbox, $squery, array( + 'results' => array( + Horde_Imap_Client::SEARCH_RESULTS_MIN, + Horde_Imap_Client::SEARCH_RESULTS_COUNT + ), + 'sequence' => true + )); + + $mbox_ob->setStatus(Horde_Imap_Client::STATUS_FIRSTUNSEEN, $search['min']); + $mbox_ob->setStatus(Horde_Imap_Client::STATUS_UNSEEN, $search['count']); + + $data[$key] = $mbox_ob->getStatus($val); + } + } else { + $query[] = $key; + } + } + + $out[strval($mailbox)] = $data; + + if (count($query)) { + $cmd = $this->_command('STATUS')->add(array( + $this->_getMboxFormatOb($mailbox), + new Horde_Imap_Client_Data_Format_List( + array_map('Horde_String::upper', $query) + ) + )); + $cmd->on_error = $on_error; + + $pipeline->add($cmd); + $to_process[] = array($query, $mailbox); + } + } + + if (count($pipeline)) { + $this->_sendCmd($pipeline); + + foreach ($to_process as $val) { + $out[strval($val[1])] += $this->_prepareStatusResponse($val[0], $val[1]); + } + } + + return $out; + } + + /** + * Parse a STATUS response (RFC 3501 [7.2.4]). + * + * @param Horde_Imap_Client_Tokenize $data Token data + */ + protected function _parseStatus(Horde_Imap_Client_Tokenize $data) + { + // Mailbox name is in UTF7-IMAP (unless UTF8 has been enabled). + $mbox_ob = $this->_mailboxOb( + Horde_Imap_Client_Mailbox::get( + $data->next(), + !$this->_capability()->isEnabled('UTF8=ACCEPT') + ) + ); + + $data->next(); + + while (($k = $data->next()) !== false) { + $mbox_ob->setStatus( + $this->_statusFields[Horde_String::lower($k)], + $data->next() + ); + } + } + + /** + * Prepares a status response for a mailbox. + * + * @param array $request The status keys to return. + * @param string $mailbox The mailbox to query. + */ + protected function _prepareStatusResponse($request, $mailbox) + { + $mbox_ob = $this->_mailboxOb($mailbox); + $out = array(); + + foreach ($request as $val) { + $out[$val] = $mbox_ob->getStatus($this->_statusFields[$val]); + } + + return $out; + } + + /** + */ + protected function _append(Horde_Imap_Client_Mailbox $mailbox, $data, + $options) + { + $c = $this->_capability(); + + // Check for MULTIAPPEND extension (RFC 3502) + if ((count($data) > 1) && !$c->query('MULTIAPPEND')) { + $result = $this->getIdsOb(); + foreach (array_keys($data) as $key) { + $res = $this->_append($mailbox, array($data[$key]), $options); + if (($res === true) || ($result === true)) { + $result = true; + } else { + $result->add($res); + } + } + return $result; + } + + // Check for extensions. + $binary = $c->query('BINARY'); + $catenate = $c->query('CATENATE'); + $utf8 = $c->isEnabled('UTF8=ACCEPT'); + + $asize = 0; + + $cmd = $this->_command('APPEND')->add( + $this->_getMboxFormatOb($mailbox) + ); + $cmd->literal8 = true; + + foreach (array_keys($data) as $key) { + if (!empty($data[$key]['flags'])) { + $tmp = new Horde_Imap_Client_Data_Format_List(); + foreach ($data[$key]['flags'] as $val) { + /* Ignore recent flag. RFC 3501 [9]: flag definition */ + if (strcasecmp($val, Horde_Imap_Client::FLAG_RECENT) !== 0) { + $tmp->add($val); + } + } + $cmd->add($tmp); + } + + if (!empty($data[$key]['internaldate'])) { + $cmd->add(new Horde_Imap_Client_Data_Format_DateTime($data[$key]['internaldate'])); + } + + $adata = null; + + if (is_array($data[$key]['data'])) { + if ($catenate) { + $cmd->add('CATENATE'); + $tmp = new Horde_Imap_Client_Data_Format_List(); + } else { + $data_stream = new Horde_Stream_Temp(); + } + + foreach ($data[$key]['data'] as $v) { + switch ($v['t']) { + case 'text': + if ($catenate) { + $tdata = $this->_appendData($v['v'], $asize); + if ($utf8) { + /* RFC 6855 [4]: CATENATE UTF8 extension. */ + $tdata->forceBinary(); + $tmp->add(array( + 'UTF8', + new Horde_Imap_Client_Data_Format_List($tdata) + )); + } else { + $tmp->add(array( + 'TEXT', + $tdata + )); + } + } else { + if (is_resource($v['v'])) { + rewind($v['v']); + } + $data_stream->add($v['v']); + } + break; + + case 'url': + if ($catenate) { + $tmp->add(array( + 'URL', + new Horde_Imap_Client_Data_Format_Astring($v['v']) + )); + } else { + $data_stream->add($this->_convertCatenateUrl($v['v'])); + } + break; + } + } + + if ($catenate) { + $cmd->add($tmp); + } else { + $adata = $this->_appendData($data_stream->stream, $asize); + } + } else { + $adata = $this->_appendData($data[$key]['data'], $asize); + } + + if (!is_null($adata)) { + if ($utf8) { + /* RFC 6855 [4]: APPEND UTF8 extension. */ + $adata->forceBinary(); + $cmd->add(array( + 'UTF8', + new Horde_Imap_Client_Data_Format_List($adata) + )); + } else { + $cmd->add($adata); + } + } + } + + /* Although it is normally more efficient to use LITERAL+, disable if + * payload is over 50 KB because it allows the server to throw error + * before we potentially push a lot of data to server that would + * otherwise be ignored (see RFC 4549 [4.2.2.3]). + * Additionally, since so many IMAP servers have issues with APPEND + * + BINARY, don't use LITERAL+ since servers may send BAD + * (incorrectly) after initial command. */ + $cmd->literalplus = (($asize < (1024 * 50)) && !$binary); + + // If the mailbox is currently selected read-only, we need to close + // because some IMAP implementations won't allow an append. And some + // implementations don't support append on ANY open mailbox. Be safe + // and always make sure we are in a non-selected state. + $this->close(); + + try { + $resp = $this->_sendCmd($cmd); + } catch (Horde_Imap_Client_Exception $e) { + switch ($e->getCode()) { + case $e::CATENATE_BADURL: + case $e::CATENATE_TOOBIG: + /* Cyrus 2.4 (at least as of .14) has a broken CATENATE (see + * Bug #11111). Regardless, if CATENATE is broken, we can try + * to fallback to APPEND. */ + $c->remove('CATENATE'); + return $this->_append($mailbox, $data, $options); + + case $e::DISCONNECT: + /* Workaround broken literal8 on Cyrus. */ + if ($binary) { + // Need to re-login first before removing capability. + $this->login(); + $c->remove('BINARY'); + return $this->_append($mailbox, $data, $options); + } + break; + } + + if (!empty($options['create']) && + !empty($e->resp_data['trycreate'])) { + $this->createMailbox($mailbox); + unset($options['create']); + return $this->_append($mailbox, $data, $options); + } + + /* RFC 3516/4466 says we should be able to append binary data + * using literal8 "~{#} format", but it doesn't seem to work on + * all servers tried (UW-IMAP/Cyrus). Do a last-ditch check for + * broken BINARY and attempt to fix here. */ + if ($c->query('BINARY') && + ($e instanceof Horde_Imap_Client_Exception_ServerResponse)) { + switch ($e->status) { + case Horde_Imap_Client_Interaction_Server::BAD: + case Horde_Imap_Client_Interaction_Server::NO: + $c->remove('BINARY'); + return $this->_append($mailbox, $data, $options); + } + } + + throw $e; + } + + /* If we reach this point and have data in 'appenduid', UIDPLUS (RFC + * 4315) has done the dirty work for us. */ + return isset($resp->data['appenduid']) + ? $resp->data['appenduid'] + : true; + } + + /** + * Prepares append message data for insertion into the IMAP command + * string. + * + * @param mixed $data Either a resource or a string. + * @param integer &$asize Total append size. + * + * @return Horde_Imap_Client_Data_Format_String_Nonascii The data object. + */ + protected function _appendData($data, &$asize) + { + if (is_resource($data)) { + rewind($data); + } + + /* Since this is body text, with possible embedded charset + * information, non-ASCII characters are supported. */ + $ob = new Horde_Imap_Client_Data_Format_String_Nonascii($data, array( + 'eol' => true, + 'skipscan' => true + )); + + // APPEND data MUST be sent in a literal (RFC 3501 [6.3.11]). + $ob->forceLiteral(); + + $asize += $ob->length(); + + return $ob; + } + + /** + * Converts a CATENATE URL to stream data. + * + * @param string $url The CATENATE URL. + * + * @return resource A stream containing the data. + */ + protected function _convertCatenateUrl($url) + { + $e = $part = null; + $url = new Horde_Imap_Client_Url_Imap($url); + + if (!is_null($url->mailbox) && !is_null($url->uid)) { + try { + $status_res = is_null($url->uidvalidity) + ? null + : $this->status($url->mailbox, Horde_Imap_Client::STATUS_UIDVALIDITY); + + if (is_null($status_res) || + ($status_res['uidvalidity'] == $url->uidvalidity)) { + if (!isset($this->_temp['catenate_ob'])) { + $this->_temp['catenate_ob'] = new Horde_Imap_Client_Socket_Catenate($this); + } + $part = $this->_temp['catenate_ob']->fetchFromUrl($url); + } + } catch (Horde_Imap_Client_Exception $e) {} + } + + if (is_null($part)) { + $message = 'Bad IMAP URL given in CATENATE data: ' . strval($url); + if ($e) { + $message .= ' ' . $e->getMessage(); + } + + throw new InvalidArgumentException($message); + } + + return $part; + } + + /** + */ + protected function _check() + { + // CHECK returns no untagged information (RFC 3501 [6.4.1]) + $this->_sendCmd($this->_command('CHECK')); + } + + /** + */ + protected function _close($options) + { + if (empty($options['expunge'])) { + if ($this->_capability('UNSELECT')) { + // RFC 3691 defines 'UNSELECT' for precisely this purpose + $this->_sendCmd($this->_command('UNSELECT')); + } else { + /* RFC 3501 [6.4.2]: to close a mailbox without expunge, + * select a non-existent mailbox. */ + try { + $this->_sendCmd($this->_command('EXAMINE')->add( + $this->_getMboxFormatOb("\24nonexist\24") + )); + + /* Not pipelining, since the odds that this CLOSE is even + * needed is tiny; and it returns BAD, which should be + * avoided, if possible. */ + $this->_sendCmd($this->_command('CLOSE')); + } catch (Horde_Imap_Client_Exception_ServerResponse $e) { + // Ignore error; it is expected. + } + } + } else { + // If caching, we need to know the UIDs being deleted, so call + // expunge() before calling close(). + if ($this->_initCache(true)) { + $this->expunge($this->_selected); + } + + // CLOSE returns no untagged information (RFC 3501 [6.4.2]) + $this->_sendCmd($this->_command('CLOSE')); + } + } + + /** + */ + protected function _expunge($options) + { + $expunged_ob = $modseq = null; + $ids = $options['ids']; + $list_msgs = !empty($options['list']); + $mailbox = $this->_selected; + $uidplus = $this->_capability('UIDPLUS'); + $unflag = array(); + $use_cache = $this->_initCache(true); + + if ($ids->all) { + if (!$uidplus || $list_msgs || $use_cache) { + $ids = $this->resolveIds($mailbox, $ids, 2); + } + } elseif ($uidplus) { + /* If QRESYNC is not available, and we are returning the list of + * expunged messages (or we are caching), we have to make sure we + * have a mapping of Sequence -> UIDs. If we have QRESYNC, the + * server SHOULD return a VANISHED response with UIDs. However, + * even if the server returns EXPUNGEs instead, we can use + * vanished() to grab the list. */ + unset($this->_temp['search_save']); + if ($this->_capability()->isEnabled('QRESYNC')) { + $ids = $this->resolveIds($mailbox, $ids, 1); + if ($list_msgs) { + $modseq = $this->_mailboxOb()->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ); + } + } else { + $ids = $this->resolveIds($mailbox, $ids, ($list_msgs || $use_cache) ? 2 : 1); + } + if (!empty($this->_temp['search_save'])) { + $ids = $this->getIdsOb(Horde_Imap_Client_Ids::SEARCH_RES); + } + } else { + /* Without UIDPLUS, need to temporarily unflag all messages marked + * as deleted but not a part of requested IDs to delete. Use NOT + * searches to accomplish this goal. */ + $squery = new Horde_Imap_Client_Search_Query(); + $squery->flag(Horde_Imap_Client::FLAG_DELETED, true); + $squery->ids($ids, true); + + $s_res = $this->search($mailbox, $squery, array( + 'results' => array( + Horde_Imap_Client::SEARCH_RESULTS_MATCH, + Horde_Imap_Client::SEARCH_RESULTS_SAVE + ) + )); + + $this->store($mailbox, array( + 'ids' => empty($s_res['save']) ? $s_res['match'] : $this->getIdsOb(Horde_Imap_Client_Ids::SEARCH_RES), + 'remove' => array(Horde_Imap_Client::FLAG_DELETED) + )); + + $unflag = $s_res['match']; + } + + if ($list_msgs) { + $expunged_ob = $this->getIdsOb(); + $this->_temp['expunged'] = $expunged_ob; + } + + /* Always use UID EXPUNGE if available. */ + if ($uidplus) { + /* We can only pipeline STORE w/ EXPUNGE if using UIDs and UIDPLUS + * is available. */ + if (empty($options['delete'])) { + $pipeline = $this->_pipeline(); + } else { + $pipeline = $this->_storeCmd(array( + 'add' => array( + Horde_Imap_Client::FLAG_DELETED + ), + 'ids' => $ids + )); + } + + foreach ($ids->split(2000) as $val) { + $pipeline->add( + $this->_command('UID EXPUNGE')->add($val) + ); + } + + $resp = $this->_sendCmd($pipeline); + } else { + if (!empty($options['delete'])) { + $this->store($mailbox, array( + 'add' => array(Horde_Imap_Client::FLAG_DELETED), + 'ids' => $ids + )); + } + + if ($use_cache || $list_msgs) { + $this->_sendCmd($this->_command('EXPUNGE')); + } else { + /* This is faster than an EXPUNGE because the server will not + * return untagged EXPUNGE responses. We can only do this if + * we are not updating cache information. */ + $this->close(array('expunge' => true)); + } + } + + unset($this->_temp['expunged']); + + if (!empty($unflag)) { + $this->store($mailbox, array( + 'add' => array(Horde_Imap_Client::FLAG_DELETED), + 'ids' => $unflag + )); + } + + if (!is_null($modseq) && !empty($resp->data['expunge_seen'])) { + /* There's a chance we actually did a full map of sequence -> UID, + * but this code should never be reached in the first place so + * be ultra-safe and just do a full VANISHED search. */ + $expunged_ob = $this->vanished($mailbox, $modseq, array( + 'ids' => $ids + )); + $this->_deleteMsgs($mailbox, $expunged_ob, array( + 'pipeline' => $resp + )); + } + + return $expunged_ob; + } + + /** + * Parse a VANISHED response (RFC 7162 [3.2.10]). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data The response data. + */ + protected function _parseVanished( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + Horde_Imap_Client_Tokenize $data + ) + { + /* There are two forms of VANISHED. VANISHED (EARLIER) will be sent + * in a FETCH (VANISHED) or SELECT/EXAMINE (QRESYNC) call. + * If this is the case, we can go ahead and update the cache + * immediately (we know we are caching or else QRESYNC would not be + * enabled). HIGHESTMODSEQ information will be updated via the tagged + * response. */ + if (($curr = $data->next()) === true) { + if (Horde_String::upper($data->next()) === 'EARLIER') { + /* Caching is guaranteed to be active if we are using + * QRESYNC. */ + $data->next(); + $vanished = $this->getIdsOb($data->next()); + if (isset($pipeline->data['vanished'])) { + $pipeline->data['vanished']->add($vanished); + } else { + $this->_deleteMsgs($this->_selected, $vanished, array( + 'pipeline' => $pipeline + )); + } + } + } else { + /* The second form is just VANISHED. This is analogous to EXPUNGE + * and requires the message count to decrement. */ + $this->_deleteMsgs($this->_selected, $this->getIdsOb($curr), array( + 'decrement' => true, + 'pipeline' => $pipeline + )); + } + } + + /** + * Search a mailbox. This driver supports all IMAP4rev1 search criteria + * as defined in RFC 3501. + */ + protected function _search($query, $options) + { + $sort_criteria = array( + Horde_Imap_Client::SORT_ARRIVAL => 'ARRIVAL', + Horde_Imap_Client::SORT_CC => 'CC', + Horde_Imap_Client::SORT_DATE => 'DATE', + Horde_Imap_Client::SORT_DISPLAYFROM => 'DISPLAYFROM', + Horde_Imap_Client::SORT_DISPLAYTO => 'DISPLAYTO', + Horde_Imap_Client::SORT_FROM => 'FROM', + Horde_Imap_Client::SORT_REVERSE => 'REVERSE', + Horde_Imap_Client::SORT_RELEVANCY => 'RELEVANCY', + // This is a bogus entry to allow the sort options check to + // correctly work below. + Horde_Imap_Client::SORT_SEQUENCE => 'SEQUENCE', + Horde_Imap_Client::SORT_SIZE => 'SIZE', + Horde_Imap_Client::SORT_SUBJECT => 'SUBJECT', + Horde_Imap_Client::SORT_TO => 'TO' + ); + + $results_criteria = array( + Horde_Imap_Client::SEARCH_RESULTS_COUNT => 'COUNT', + Horde_Imap_Client::SEARCH_RESULTS_MATCH => 'ALL', + Horde_Imap_Client::SEARCH_RESULTS_MAX => 'MAX', + Horde_Imap_Client::SEARCH_RESULTS_MIN => 'MIN', + Horde_Imap_Client::SEARCH_RESULTS_RELEVANCY => 'RELEVANCY', + Horde_Imap_Client::SEARCH_RESULTS_SAVE => 'SAVE' + ); + + // Check if the server supports sorting (RFC 5256). + $esearch = $return_sort = $server_seq_sort = $server_sort = false; + if (!empty($options['sort'])) { + /* Make sure sort options are correct. If not, default to no + * sort. */ + if (count(array_intersect($options['sort'], array_keys($sort_criteria))) === 0) { + unset($options['sort']); + } else { + $return_sort = true; + + if ($this->_capability('SORT')) { + /* Make sure server supports DISPLAYFROM & DISPLAYTO. */ + $server_sort = + !array_intersect($options['sort'], array(Horde_Imap_Client::SORT_DISPLAYFROM, Horde_Imap_Client::SORT_DISPLAYTO)) || + $this->_capability('SORT', 'DISPLAY'); + } + + /* If doing a sequence sort, need to do this on the client + * side. */ + if ($server_sort && + in_array(Horde_Imap_Client::SORT_SEQUENCE, $options['sort'])) { + $server_sort = false; + + /* Optimization: If doing only a sequence sort, just do a + * simple search and sort UIDs/sequences on client side. */ + switch (count($options['sort'])) { + case 1: + $server_seq_sort = true; + break; + + case 2: + $server_seq_sort = (reset($options['sort']) == Horde_Imap_Client::SORT_REVERSE); + break; + } + } + } + } + + $charset = is_null($options['_query']['charset']) + ? 'US-ASCII' + : $options['_query']['charset']; + $partial = false; + + if ($server_sort) { + $cmd = $this->_command( + empty($options['sequence']) ? 'UID SORT' : 'SORT' + ); + $results = array(); + + // Use ESEARCH (RFC 4466) response if server supports. + $esearch = false; + + // Check for ESORT capability (RFC 5267) + if ($this->_capability('ESORT')) { + foreach ($options['results'] as $val) { + if (isset($results_criteria[$val]) && + ($val != Horde_Imap_Client::SEARCH_RESULTS_SAVE)) { + $results[] = $results_criteria[$val]; + } + } + $esearch = true; + } + + // Add PARTIAL limiting (RFC 5267 [4.4]) + if ((!$esearch || !empty($options['partial'])) && + $this->_capability('CONTEXT', 'SORT')) { + /* RFC 5267 indicates RFC 4466 ESEARCH-like support, + * notwithstanding "real" RFC 4731 support. */ + $esearch = true; + + if (!empty($options['partial'])) { + /* Can't have both ALL and PARTIAL returns. */ + $results = array_diff($results, array('ALL')); + + $results[] = 'PARTIAL'; + $results[] = $options['partial']; + $partial = true; + } + } + + if ($esearch && empty($this->_init['noesearch'])) { + $cmd->add(array( + 'RETURN', + new Horde_Imap_Client_Data_Format_List($results) + )); + } + + $tmp = new Horde_Imap_Client_Data_Format_List(); + foreach ($options['sort'] as $val) { + if (isset($sort_criteria[$val])) { + $tmp->add($sort_criteria[$val]); + } + } + $cmd->add($tmp); + + /* Charset is mandatory for SORT (RFC 5256 [3]). + * If UTF-8 support is activated, a client MUST ONLY + * send the 'UTF-8' specification (RFC 6855 [3]; Errata 4029). */ + if (!$this->_capability()->isEnabled('UTF8=ACCEPT')) { + $cmd->add($charset); + } else { + $cmd->add('UTF-8'); + } + } else { + $cmd = $this->_command( + empty($options['sequence']) ? 'UID SEARCH' : 'SEARCH' + ); + $esearch = false; + $results = array(); + + // Check if the server supports ESEARCH (RFC 4731). + if ($this->_capability('ESEARCH')) { + foreach ($options['results'] as $val) { + if (isset($results_criteria[$val])) { + $results[] = $results_criteria[$val]; + } + } + $esearch = true; + } + + // Add PARTIAL limiting (RFC 5267 [4.4]). + if ((!$esearch || !empty($options['partial'])) && + $this->_capability('CONTEXT', 'SEARCH')) { + /* RFC 5267 indicates RFC 4466 ESEARCH-like support, + * notwithstanding "real" RFC 4731 support. */ + $esearch = true; + + if (!empty($options['partial'])) { + // Can't have both ALL and PARTIAL returns. + $results = array_diff($results, array('ALL')); + + $results[] = 'PARTIAL'; + $results[] = $options['partial']; + $partial = true; + } + } + + if ($esearch && empty($this->_init['noesearch'])) { + // Always use ESEARCH if available because it returns results + // in a more compact sequence-set list + $cmd->add(array( + 'RETURN', + new Horde_Imap_Client_Data_Format_List($results) + )); + } + + /* Charset is optional for SEARCH (RFC 3501 [6.4.4]). + * If UTF-8 support is activated, a client MUST NOT + * send the charset specification (RFC 6855 [3]; Errata 4029). */ + if (($charset != 'US-ASCII') && + !$this->_capability()->isEnabled('UTF8=ACCEPT')) { + $cmd->add(array( + 'CHARSET', + $options['_query']['charset'] + )); + } + } + + $cmd->add($options['_query']['query'], true); + + $pipeline = $this->_pipeline($cmd); + $pipeline->data['esearchresp'] = array(); + $er = &$pipeline->data['esearchresp']; + $pipeline->data['searchresp'] = $this->getIdsOb(array(), !empty($options['sequence'])); + $sr = &$pipeline->data['searchresp']; + + try { + $resp = $this->_sendCmd($pipeline); + } catch (Horde_Imap_Client_Exception $e) { + if (($e instanceof Horde_Imap_Client_Exception_ServerResponse) && + ($e->status === Horde_Imap_Client_Interaction_Server::NO) && + ($charset != 'US-ASCII')) { + /* RFC 3501 [6.4.4]: BADCHARSET response code is only a + * SHOULD return. If it doesn't exist, need to check for + * command status of 'NO'. List of supported charsets in + * the BADCHARSET response has already been parsed and stored + * at this point. */ + $this->search_charset->setValid($charset, false); + $e->setCode(Horde_Imap_Client_Exception::BADCHARSET); + } + + if (empty($this->_temp['search_retry'])) { + $this->_temp['search_retry'] = true; + + /* Bug #9842: Workaround broken Cyrus servers (as of + * 2.4.7). */ + if ($esearch && ($charset != 'US-ASCII')) { + $this->_capability()->remove('ESEARCH'); + $this->_setInit('noesearch', true); + + try { + return $this->_search($query, $options); + } catch (Horde_Imap_Client_Exception $e) {} + } + + /* Try to convert charset. */ + if (($e->getCode() === Horde_Imap_Client_Exception::BADCHARSET) && + ($charset != 'US-ASCII')) { + foreach ($this->search_charset->charsets as $val) { + $this->_temp['search_retry'] = 1; + $new_query = clone($query); + try { + $new_query->charset($val); + $options['_query'] = $new_query->build($this); + return $this->_search($new_query, $options); + } catch (Horde_Imap_Client_Exception $e) {} + } + } + + unset($this->_temp['search_retry']); + } + + throw $e; + } + + if ($return_sort && !$server_sort) { + if ($server_seq_sort) { + $sr->sort(); + if (reset($options['sort']) == Horde_Imap_Client::SORT_REVERSE) { + $sr->reverse(); + } + } else { + if (!isset($this->_temp['clientsort'])) { + $this->_temp['clientsort'] = new Horde_Imap_Client_Socket_ClientSort($this); + } + $sr = $this->getIdsOb($this->_temp['clientsort']->clientSort($sr, $options), !empty($options['sequence'])); + } + } + + if (!$partial && !empty($options['partial'])) { + $partial = $this->getIdsOb($options['partial'], true); + $min = $partial->min - 1; + + $sr = $this->getIdsOb( + array_slice($sr->ids, $min, $partial->max - $min), + !empty($options['sequence']) + ); + } + + $ret = array(); + foreach ($options['results'] as $val) { + switch ($val) { + case Horde_Imap_Client::SEARCH_RESULTS_COUNT: + $ret['count'] = ($esearch && !$partial) + ? $er['count'] + : count($sr); + break; + + case Horde_Imap_Client::SEARCH_RESULTS_MATCH: + $ret['match'] = $sr; + break; + + case Horde_Imap_Client::SEARCH_RESULTS_MAX: + $ret['max'] = $esearch + ? (!$partial && isset($er['max']) ? $er['max'] : null) + : (count($sr) ? max($sr->ids) : null); + break; + + case Horde_Imap_Client::SEARCH_RESULTS_MIN: + $ret['min'] = $esearch + ? (!$partial && isset($er['min']) ? $er['min'] : null) + : (count($sr) ? min($sr->ids) : null); + break; + + case Horde_Imap_Client::SEARCH_RESULTS_RELEVANCY: + $ret['relevancy'] = ($esearch && isset($er['relevancy'])) ? $er['relevancy'] : array(); + break; + + case Horde_Imap_Client::SEARCH_RESULTS_SAVE: + $this->_temp['search_save'] = $ret['save'] = $esearch ? empty($resp->data['searchnotsaved']) : false; + break; + } + } + + // Add modseq data, if needed. + if (!empty($er['modseq'])) { + $ret['modseq'] = $er['modseq']; + } + + unset($this->_temp['search_retry']); + + /* Check for EXPUNGEISSUED (RFC 2180 [4.3]/RFC 5530 [3]). */ + if (!empty($resp->data['expungeissued'])) { + $this->noop(); + } + + return $ret; + } + + /** + * Parse a SEARCH/SORT response (RFC 3501 [7.2.5]; RFC 4466 [3]; + * RFC 5256 [4]; RFC 5267 [3]). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param array $data A list of IDs (message sequence numbers or UIDs). + */ + protected function _parseSearch( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + $data + ) + { + /* More than one search response may be sent. */ + $pipeline->data['searchresp']->add($data); + } + + /** + * Parse an ESEARCH response (RFC 4466 [2.6.2]) + * Format: (TAG "a567") UID COUNT 5 ALL 4:19,21,28 + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data The server response. + */ + protected function _parseEsearch( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + Horde_Imap_Client_Tokenize $data + ) + { + // Ignore search correlator information + if ($data->next() === true) { + $data->flushIterator(false); + } + + // Ignore UID tag + $current = $data->next(); + if (Horde_String::upper($current) === 'UID') { + $current = $data->next(); + } + + do { + $val = $data->next(); + $tag = Horde_String::upper($current); + + switch ($tag) { + case 'ALL': + $this->_parseSearch($pipeline, $val); + break; + + case 'COUNT': + case 'MAX': + case 'MIN': + case 'MODSEQ': + case 'RELEVANCY': + $pipeline->data['esearchresp'][Horde_String::lower($tag)] = $val; + break; + + case 'PARTIAL': + // RFC 5267 [4.4] + $partial = $val->flushIterator(); + $this->_parseSearch($pipeline, end($partial)); + break; + } + } while (($current = $data->next()) !== false); + } + + /** + */ + protected function _setComparator($comparator) + { + $cmd = $this->_command('COMPARATOR'); + foreach ($comparator as $val) { + $cmd->add(new Horde_Imap_Client_Data_Format_Astring($val)); + } + $this->_sendCmd($cmd); + } + + /** + */ + protected function _getComparator() + { + $resp = $this->_sendCmd($this->_command('COMPARATOR')); + + return isset($resp->data['comparator']) + ? $resp->data['comparator'] + : null; + } + + /** + * Parse a COMPARATOR response (RFC 5255 [4.8]) + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data The server response. + */ + protected function _parseComparator( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + $data + ) + { + $pipeline->data['comparator'] = $data->next(); + // Ignore optional matching comparator list + } + + /** + * @throws Horde_Imap_Client_Exception_NoSupportExtension + */ + protected function _thread($options) + { + $thread_criteria = array( + Horde_Imap_Client::THREAD_ORDEREDSUBJECT => 'ORDEREDSUBJECT', + Horde_Imap_Client::THREAD_REFERENCES => 'REFERENCES', + Horde_Imap_Client::THREAD_REFS => 'REFS' + ); + + $tsort = (isset($options['criteria'])) + ? (is_string($options['criteria']) ? Horde_String::upper($options['criteria']) : $thread_criteria[$options['criteria']]) + : 'ORDEREDSUBJECT'; + + if (!$this->_capability('THREAD', $tsort)) { + switch ($tsort) { + case 'ORDEREDSUBJECT': + if (empty($options['search'])) { + $ids = $this->getIdsOb(Horde_Imap_Client_Ids::ALL, !empty($options['sequence'])); + } else { + $search_res = $this->search($this->_selected, $options['search'], array('sequence' => !empty($options['sequence']))); + $ids = $search_res['match']; + } + + /* Do client-side ORDEREDSUBJECT threading. */ + $query = new Horde_Imap_Client_Fetch_Query(); + $query->envelope(); + $query->imapDate(); + + $fetch_res = $this->fetch($this->_selected, $query, array( + 'ids' => $ids + )); + + if (!isset($this->_temp['clientsort'])) { + $this->_temp['clientsort'] = new Horde_Imap_Client_Socket_ClientSort($this); + } + return $this->_temp['clientsort']->threadOrderedSubject($fetch_res, empty($options['sequence'])); + + case 'REFERENCES': + case 'REFS': + throw new Horde_Imap_Client_Exception_NoSupportExtension( + 'THREAD', + sprintf('Server does not support "%s" thread sort.', $tsort) + ); + } + } + + $cmd = $this->_command( + empty($options['sequence']) ? 'UID THREAD' : 'THREAD' + )->add($tsort); + + /* If UTF-8 support is activated, a client MUST send the UTF-8 + * charset specification since charset is mandatory for this + * command (RFC 6855 [3]; Errata 4029). */ + if (empty($options['search'])) { + if (!$this->_capability()->isEnabled('UTF8=ACCEPT')) { + $cmd->add('US-ASCII'); + } else { + $cmd->add('UTF-8'); + } + $cmd->add('ALL'); + } else { + $search_query = $options['search']->build(); + if (!$this->_capability()->isEnabled('UTF8=ACCEPT')) { + $cmd->add(is_null($search_query['charset']) ? 'US-ASCII' : $search_query['charset']); + } + $cmd->add($search_query['query'], true); + } + + return new Horde_Imap_Client_Data_Thread( + $this->_sendCmd($cmd)->data['threadparse'], + empty($options['sequence']) ? 'uid' : 'sequence' + ); + } + + /** + * Parse a THREAD response (RFC 5256 [4]). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data Thread data. + */ + protected function _parseThread( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + Horde_Imap_Client_Tokenize $data + ) + { + $out = array(); + + while ($data->next() !== false) { + $thread = array(); + $this->_parseThreadLevel($thread, $data); + $out[] = $thread; + } + + $pipeline->data['threadparse'] = $out; + } + + /** + * Parse a level of a THREAD response (RFC 5256 [4]). + * + * @param array $thread Results. + * @param Horde_Imap_Client_Tokenize $data Thread data. + * @param integer $level The current tree level. + */ + protected function _parseThreadLevel(&$thread, + Horde_Imap_Client_Tokenize $data, + $level = 0) + { + while (($curr = $data->next()) !== false) { + if ($curr === true) { + $this->_parseThreadLevel($thread, $data, $level); + } elseif (!is_bool($curr)) { + $thread[$curr] = $level++; + } + } + } + + /** + */ + protected function _fetch(Horde_Imap_Client_Fetch_Results $results, + $queries) + { + $pipeline = $this->_pipeline(); + $pipeline->data['fetch_lookup'] = array(); + $pipeline->data['fetch_followup'] = array(); + + foreach ($queries as $options) { + $this->_fetchCmd($pipeline, $options); + $sequence = $options['ids']->sequence; + } + + try { + $resp = $this->_sendCmd($pipeline); + + /* Check for EXPUNGEISSUED (RFC 2180 [4.1]/RFC 5530 [3]). */ + if (!empty($resp->data['expungeissued'])) { + $this->noop(); + } + + foreach ($resp->fetch as $k => $v) { + $results->get($sequence ? $k : $v->getUid())->merge($v); + } + } catch (Horde_Imap_Client_Exception_ServerResponse $e) { + if ($e->status === Horde_Imap_Client_Interaction_Server::NO) { + if ($e->getCode() === $e::UNKNOWNCTE || + $e->getCode() === $e::PARSEERROR) { + /* UNKNOWN-CTE error. Redo the query without the BINARY + * elements. Also include PARSEERROR in this as + * Dovecot >= 2.2 binary fetch treats broken email as PARSE + * error and no longer UNKNOWN-CTE + */ + if (!empty($pipeline->data['binaryquery'])) { + foreach ($queries as $val) { + foreach ($pipeline->data['binaryquery'] as $key2 => $val2) { + unset($val2['decode']); + $val['_query']->bodyPart($key2, $val2); + $val['_query']->remove(Horde_Imap_Client::FETCH_BODYPARTSIZE, $key2); + } + $pipeline->data['fetch_followup'][] = $val; + } + $pipeline->data['fetch_followup'][] = $val; + } else { + $this->noop(); + } + } elseif ($sequence) { + /* A NO response, when coupled with a sequence FETCH, most + * likely means that messages were expunged. (RFC 2180 + * [4.1]) */ + $this->noop(); + } + } + } catch (Exception $e) { + // For any other error, ignore the Exception - fetch() is nice in + // that the return value explicitly handles missing data for any + // given message. + } + + if (!empty($pipeline->data['fetch_followup'])) { + $this->_fetch($results, $pipeline->data['fetch_followup']); + } + } + + /** + * Add a FETCH command to the given pipeline. + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param array $options Fetch query + * options + */ + protected function _fetchCmd( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + $options + ) + { + $fetch = new Horde_Imap_Client_Data_Format_List(); + $sequence = $options['ids']->sequence; + + /* Build an IMAP4rev1 compliant FETCH query. We handle the following + * criteria: + * BINARY[.PEEK][
]<> (RFC 3516) + * see BODY[] response + * BINARY.SIZE[
] (RFC 3516) + * BODY[.PEEK][
]<> + *
= HEADER, HEADER.FIELDS, HEADER.FIELDS.NOT, MIME, + * TEXT, empty + * <> = 0.# (# of bytes) + * BODYSTRUCTURE + * ENVELOPE + * FLAGS + * INTERNALDATE + * MODSEQ (RFC 7162) + * RFC822.SIZE + * UID + * + * No need to support these (can be built from other queries): + * =========================================================== + * ALL macro => (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) + * BODY => Use BODYSTRUCTURE instead + * FAST macro => (FLAGS INTERNALDATE RFC822.SIZE) + * FULL macro => (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY) + * RFC822 => BODY[] + * RFC822.HEADER => BODY[HEADER] + * RFC822.TEXT => BODY[TEXT] + */ + + foreach ($options['_query'] as $type => $c_val) { + switch ($type) { + case Horde_Imap_Client::FETCH_STRUCTURE: + $fetch->add('BODYSTRUCTURE'); + break; + + case Horde_Imap_Client::FETCH_FULLMSG: + if (empty($c_val['peek'])) { + $this->openMailbox($this->_selected, Horde_Imap_Client::OPEN_READWRITE); + } + $fetch->add( + 'BODY' . + (!empty($c_val['peek']) ? '.PEEK' : '') . + '[]' . + $this->_partialAtom($c_val) + ); + break; + + case Horde_Imap_Client::FETCH_HEADERTEXT: + case Horde_Imap_Client::FETCH_BODYTEXT: + case Horde_Imap_Client::FETCH_MIMEHEADER: + case Horde_Imap_Client::FETCH_BODYPART: + case Horde_Imap_Client::FETCH_HEADERS: + foreach ($c_val as $key => $val) { + $cmd = ($key == 0) + ? '' + : $key . '.'; + $main_cmd = 'BODY'; + + switch ($type) { + case Horde_Imap_Client::FETCH_HEADERTEXT: + $cmd .= 'HEADER'; + break; + + case Horde_Imap_Client::FETCH_BODYTEXT: + $cmd .= 'TEXT'; + break; + + case Horde_Imap_Client::FETCH_MIMEHEADER: + $cmd .= 'MIME'; + break; + + case Horde_Imap_Client::FETCH_BODYPART: + // Remove the last dot from the string. + $cmd = substr($cmd, 0, -1); + + if (!empty($val['decode']) && + $this->_capability('BINARY')) { + $main_cmd = 'BINARY'; + $pipeline->data['binaryquery'][$key] = $val; + } + break; + + case Horde_Imap_Client::FETCH_HEADERS: + $cmd .= 'HEADER.FIELDS'; + if (!empty($val['notsearch'])) { + $cmd .= '.NOT'; + } + $cmd .= ' (' . implode(' ', array_map('Horde_String::upper', $val['headers'])) . ')'; + + // Maintain a command -> label lookup so we can put + // the results in the proper location. + $pipeline->data['fetch_lookup'][$cmd] = $key; + } + + if (empty($val['peek'])) { + $this->openMailbox($this->_selected, Horde_Imap_Client::OPEN_READWRITE); + } + + $fetch->add( + $main_cmd . + (!empty($val['peek']) ? '.PEEK' : '') . + '[' . $cmd . ']' . + $this->_partialAtom($val) + ); + } + break; + + case Horde_Imap_Client::FETCH_BODYPARTSIZE: + if ($this->_capability('BINARY')) { + foreach ($c_val as $val) { + $fetch->add('BINARY.SIZE[' . $val . ']'); + } + } + break; + + case Horde_Imap_Client::FETCH_ENVELOPE: + $fetch->add('ENVELOPE'); + break; + + case Horde_Imap_Client::FETCH_FLAGS: + $fetch->add('FLAGS'); + break; + + case Horde_Imap_Client::FETCH_IMAPDATE: + $fetch->add('INTERNALDATE'); + break; + + case Horde_Imap_Client::FETCH_SIZE: + $fetch->add('RFC822.SIZE'); + break; + + case Horde_Imap_Client::FETCH_UID: + /* A UID FETCH will always return UID information (RFC 3501 + * [6.4.8]). Don't add to query as it just creates a longer + * FETCH command. */ + if ($sequence) { + $fetch->add('UID'); + } + break; + + case Horde_Imap_Client::FETCH_SEQ: + /* Nothing we need to add to fetch request unless sequence is + * the only criteria (see below). */ + break; + + case Horde_Imap_Client::FETCH_MODSEQ: + /* The 'changedsince' modifier implicitly adds the MODSEQ + * FETCH item (RFC 7162 [3.1.4.1]). Don't add to query as it + * just creates a longer FETCH command. */ + if (empty($options['changedsince'])) { + $fetch->add('MODSEQ'); + } + break; + } + } + + /* If empty fetch, add UID to make command valid. */ + if (!count($fetch)) { + $fetch->add('UID'); + } + + /* Add changedsince parameters. */ + if (empty($options['changedsince'])) { + $fetch_cmd = $fetch; + } else { + /* We might just want the list of UIDs changed since a given + * modseq. In that case, we don't have any other FETCH attributes, + * but RFC 3501 requires at least one specified attribute. */ + $fetch_cmd = array( + $fetch, + new Horde_Imap_Client_Data_Format_List(array( + 'CHANGEDSINCE', + new Horde_Imap_Client_Data_Format_Number($options['changedsince']) + )) + ); + } + + /* The FETCH command should be the only command issued by this library + * that should ever approach the command length limit. + * @todo Move this check to a more centralized location (_command()?). + * For simplification, assume that the UID list is the limiting factor + * and split this list at a sequence comma delimiter if it exceeds + * the character limit. */ + foreach ($options['ids']->split($this->_capability()->cmdlength) as $val) { + $cmd = $this->_command( + $sequence ? 'FETCH' : 'UID FETCH' + )->add(array( + $val, + $fetch_cmd + )); + $pipeline->add($cmd); + } + } + + /** + * Add a partial atom to an IMAP command based on the criteria options. + * + * @param array $opts Criteria options. + * + * @return string The partial atom. + */ + protected function _partialAtom($opts) + { + if (!empty($opts['length'])) { + return '<' . (empty($opts['start']) ? 0 : intval($opts['start'])) . '.' . intval($opts['length']) . '>'; + } + + return empty($opts['start']) + ? '' + : ('<' . intval($opts['start']) . '>'); + } + + /** + * Parse a FETCH response (RFC 3501 [7.4.2]). A FETCH response may occur + * due to a FETCH command, or due to a change in a message's state (i.e. + * the flags change). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param integer $id The message sequence number. + * @param Horde_Imap_Client_Tokenize $data The server response. + */ + protected function _parseFetch( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + $id, + Horde_Imap_Client_Tokenize $data + ) + { + if ($data->next() !== true) { + return; + } + + $ob = $pipeline->fetch->get($id); + $ob->setSeq($id); + + $flags = $modseq = $uid = false; + + while (($tag = $data->next()) !== false) { + $tag = Horde_String::upper($tag); + + /* Catch equivalent RFC822 tags, in case server returns them + * (in error, since we only use BODY in FETCH requests). */ + switch ($tag) { + case 'RFC822': + $tag = 'BODY[]'; + break; + + case 'RFC822.HEADER': + $tag = 'BODY[HEADER]'; + break; + + case 'RFC822.TEXT': + $tag = 'BODY[TEXT]'; + break; + } + + switch ($tag) { + case 'BODYSTRUCTURE': + $data->next(); + $structure = $this->_parseBodystructure($data); + $structure->buildMimeIds(); + $ob->setStructure($structure); + break; + + case 'ENVELOPE': + $data->next(); + $ob->setEnvelope($this->_parseEnvelope($data)); + break; + + case 'FLAGS': + $data->next(); + $ob->setFlags($data->flushIterator()); + $flags = true; + break; + + case 'INTERNALDATE': + $ob->setImapDate($data->next()); + break; + + case 'RFC822.SIZE': + $ob->setSize($data->next()); + break; + + case 'UID': + $ob->setUid($data->next()); + $uid = true; + break; + + case 'MODSEQ': + $data->next(); + $modseq = $data->next(); + $data->next(); + + /* MODSEQ must be greater than 0, so do sanity checking. */ + if ($modseq > 0) { + $ob->setModSeq($modseq); + + /* Store MODSEQ value. It may be used as the highestmodseq + * once a tagged response is received (RFC 7162 [6]). */ + $pipeline->data['modseqs'][] = $modseq; + } + break; + + default: + // Catch BODY[*]<#> responses + if (strpos($tag, 'BODY[') === 0) { + // Remove the beginning 'BODY[' + $tag = substr($tag, 5); + + // BODY[HEADER.FIELDS] request + if (!empty($pipeline->data['fetch_lookup']) && + (strpos($tag, 'HEADER.FIELDS') !== false)) { + $data->next(); + $sig = $tag . ' (' . implode(' ', array_map('Horde_String::upper', $data->flushIterator())) . ')'; + + // Ignore the trailing bracket + $data->next(); + + $ob->setHeaders($pipeline->data['fetch_lookup'][$sig], $data->next()); + } else { + // Remove trailing bracket and octet start info + $tag = substr($tag, 0, strrpos($tag, ']')); + + if (!strlen($tag)) { + // BODY[] request + if (!is_null($tmp = $data->nextStream())) { + $ob->setFullMsg($tmp); + } + } elseif (is_numeric(substr($tag, -1))) { + // BODY[MIMEID] request + if (!is_null($tmp = $data->nextStream())) { + $ob->setBodyPart($tag, $tmp); + } + } else { + // BODY[HEADER|TEXT|MIME] request + if (($last_dot = strrpos($tag, '.')) === false) { + $mime_id = 0; + } else { + $mime_id = substr($tag, 0, $last_dot); + $tag = substr($tag, $last_dot + 1); + } + + if (!is_null($tmp = $data->nextStream())) { + switch ($tag) { + case 'HEADER': + $ob->setHeaderText($mime_id, $tmp); + break; + + case 'TEXT': + $ob->setBodyText($mime_id, $tmp); + break; + + case 'MIME': + $ob->setMimeHeader($mime_id, $tmp); + break; + } + } + } + } + } elseif (strpos($tag, 'BINARY[') === 0) { + // Catch BINARY[*]<#> responses + // Remove the beginning 'BINARY[' and the trailing bracket + // and octet start info + $tag = substr($tag, 7, strrpos($tag, ']') - 7); + $body = $data->nextStream(); + + if (is_null($body)) { + /* Dovecot bug (as of 2.2.12): binary fetch of body + * part may fail with NIL return if decoding failed on + * server. Try again with non-decoded body. */ + $bq = $pipeline->data['binaryquery'][$tag]; + unset($bq['decode']); + + $query = new Horde_Imap_Client_Fetch_Query(); + $query->bodyPart($tag, $bq); + + $qids = ($quid = $ob->getUid()) + ? new Horde_Imap_Client_Ids($quid) + : new Horde_Imap_Client_Ids($id, true); + + $pipeline->data['fetch_followup'][] = array( + '_query' => $query, + 'ids' => $qids + ); + } else { + $ob->setBodyPart( + $tag, + $body, + empty($this->_temp['literal8']) ? '8bit' : 'binary' + ); + } + } elseif (strpos($tag, 'BINARY.SIZE[') === 0) { + // Catch BINARY.SIZE[*] responses + // Remove the beginning 'BINARY.SIZE[' and the trailing + // bracket and octet start info + $tag = substr($tag, 12, strrpos($tag, ']') - 12); + $ob->setBodyPartSize($tag, $data->next()); + } + break; + } + } + + /* MODSEQ issue: Oh joy. Per RFC 5162 (see Errata #1807), FETCH FLAGS + * responses are NOT required to provide UID information, even if + * QRESYNC is explicitly enabled. Caveat: the FLAGS information + * returned during a SELECT/EXAMINE MUST contain UIDs so we are OK + * there. + * The good news: all decent IMAP servers (Cyrus, Dovecot) will always + * provide UID information, so this is not normally an issue. + * The bad news: spec-wise, this behavior cannot be 100% guaranteed. + * Compromise: We will watch for a FLAGS response with a MODSEQ and + * check if a UID exists also. If not, put the sequence number in a + * queue - it is possible the UID information may appear later in an + * untagged response. When the command is over, double check to make + * sure there are none of these MODSEQ/FLAGS that are still UID-less. + * In the (rare) event that there is, don't cache anything and + * immediately close the mailbox: flags will be correctly sync'd next + * mailbox open so we only lose a bit of caching efficiency. + * Otherwise, we could end up with an inconsistent cached state. + * This Errata has been fixed in 7162 [3.2.4]. */ + if ($flags && $modseq && !$uid) { + $pipeline->data['modseqs_nouid'][] = $id; + } + } + + /** + * Recursively parse BODYSTRUCTURE data from a FETCH return (see + * RFC 3501 [7.4.2]). + * + * @param Horde_Imap_Client_Tokenize $data Data returned from the server. + * + * @return Horde_Mime_Part Mime part object. + */ + protected function _parseBodystructure(Horde_Imap_Client_Tokenize $data) + { + $ob = new Horde_Mime_Part(); + + // If index 0 is an array, this is a multipart part. + if (($entry = $data->next()) === true) { + do { + $ob->addPart($this->_parseBodystructure($data)); + } while (($entry = $data->next()) === true); + + // The subpart type. + $ob->setType('multipart/' . $entry); + + // After the subtype is further extension information. This + // information MAY appear for BODYSTRUCTURE requests. + + // This is parameter information. + if (($tmp = $data->next()) === false) { + return $ob; + } elseif ($tmp === true) { + foreach ($this->_parseStructureParams($data) as $key => $val) { + $ob->setContentTypeParameter($key, $val); + } + } + } else { + $ob->setType($entry . '/' . $data->next()); + + if ($data->next() === true) { + foreach ($this->_parseStructureParams($data) as $key => $val) { + $ob->setContentTypeParameter($key, $val); + } + } + + if (!is_null($tmp = $data->next())) { + $ob->setContentId($tmp); + } + + if (!is_null($tmp = $data->next())) { + $ob->setDescription(Horde_Mime::decode($tmp)); + } + + $te = $data->next(); + $bytes = $data->next(); + + if (!is_null($te)) { + $ob->setTransferEncoding($te); + + /* Base64 transfer encoding is approx. 33% larger than + * original data size (RFC 2045 [6.8]). Return from + * BODYSTRUCTURE is the size of the ENCODED data (RFC 3501 + * [7.4.2]). */ + if (strcasecmp($te, 'base64') === 0) { + $bytes *= 0.75; + } + } + + $ob->setBytes($bytes); + + // If the type is 'message/rfc822' or 'text/*', several extra + // fields are included + switch ($ob->getPrimaryType()) { + case 'message': + if ($ob->getSubType() == 'rfc822') { + if ($data->next() === true) { + // Ignore: envelope + $data->flushIterator(false); + } + if ($data->next() === true) { + $ob->addPart($this->_parseBodystructure($data)); + } + $data->next(); // Ignore: lines + } + break; + + case 'text': + $data->next(); // Ignore: lines + break; + } + + // After the subtype is further extension information. This + // information MAY appear for BODYSTRUCTURE requests. + + // Ignore: MD5 + if ($data->next() === false) { + return $ob; + } + } + + // This is disposition information + if (($tmp = $data->next()) === false) { + return $ob; + } elseif ($tmp === true) { + $ob->setDisposition($data->next()); + + if ($data->next() === true) { + foreach ($this->_parseStructureParams($data) as $key => $val) { + $ob->setDispositionParameter($key, $val); + } + } + $data->next(); + } + + // This is language information. It is either a single value or a list + // of values. + if (($tmp = $data->next()) === false) { + return $ob; + } elseif (!is_null($tmp)) { + $ob->setLanguage(($tmp === true) ? $data->flushIterator() : $tmp); + } + + // Ignore location (RFC 2557) and consume closing paren. + $data->flushIterator(false); + + return $ob; + } + + /** + * Helper function to parse a parameters-like tokenized array. + * + * @param mixed $data Message data. Either a Horde_Imap_Client_Tokenize + * object or null. + * + * @return array The parameter array. + */ + protected function _parseStructureParams($data) + { + $params = array(); + + if (is_null($data)) { + return $params; + } + + while (($name = $data->next()) !== false) { + $params[Horde_String::lower($name)] = $data->next(); + } + + $cp = new Horde_Mime_Headers_ContentParam('Unused', $params); + + return $cp->params; + } + + /** + * Parse ENVELOPE data from a FETCH return (see RFC 3501 [7.4.2]). + * + * @param Horde_Imap_Client_Tokenize $data Data returned from the server. + * + * @return Horde_Imap_Client_Data_Envelope An envelope object. + */ + protected function _parseEnvelope(Horde_Imap_Client_Tokenize $data) + { + // 'route', the 2nd element, is deprecated by RFC 2822. + $addr_structure = array( + 0 => 'personal', + 2 => 'mailbox', + 3 => 'host' + ); + $env_data = array( + 0 => 'date', + 1 => 'subject', + 2 => 'from', + 3 => 'sender', + 4 => 'reply_to', + 5 => 'to', + 6 => 'cc', + 7 => 'bcc', + 8 => 'in_reply_to', + 9 => 'message_id' + ); + + $addr_ob = new Horde_Mail_Rfc822_Address(); + $env_addrs = $this->getParam('envelope_addrs'); + $env_str = $this->getParam('envelope_string'); + $key = 0; + $ret = new Horde_Imap_Client_Data_Envelope(); + + while (($val = $data->next()) !== false) { + if (!isset($env_data[$key]) || is_null($val)) { + ++$key; + continue; + } + + if (is_string($val)) { + // These entries are text fields. + $ret->{$env_data[$key]} = substr($val, 0, $env_str); + } else { + // These entries are address structures. + $group = null; + $key2 = 0; + $tmp = new Horde_Mail_Rfc822_List(); + + while ($data->next() !== false) { + $a_val = $data->flushIterator(); + + // RFC 3501 [7.4.2]: Group entry when host is NIL. + // Group end when mailbox is NIL; otherwise, this is + // mailbox name. + if (is_null($a_val[3])) { + if (is_null($a_val[2])) { + $group = null; + } else { + $group = new Horde_Mail_Rfc822_Group($a_val[2]); + $tmp->add($group); + } + } else { + $addr = clone $addr_ob; + + foreach ($addr_structure as $add_key => $add_val) { + if (!is_null($a_val[$add_key])) { + $addr->$add_val = $a_val[$add_key]; + } + } + + if ($group) { + $group->addresses->add($addr); + } else { + $tmp->add($addr); + } + } + + if (++$key2 >= $env_addrs) { + $data->flushIterator(false); + break; + } + } + + $ret->{$env_data[$key]} = $tmp; + } + + ++$key; + } + + return $ret; + } + + /** + */ + protected function _vanished($modseq, Horde_Imap_Client_Ids $ids) + { + $pipeline = $this->_pipeline( + $this->_command('UID FETCH')->add(array( + strval($ids), + 'UID', + new Horde_Imap_Client_Data_Format_List(array( + 'VANISHED', + 'CHANGEDSINCE', + new Horde_Imap_Client_Data_Format_Number($modseq) + )) + )) + ); + $pipeline->data['vanished'] = $this->getIdsOb(); + + return $this->_sendCmd($pipeline)->data['vanished']; + } + + /** + */ + protected function _store($options) + { + $pipeline = $this->_storeCmd($options); + $pipeline->data['modified'] = $this->getIdsOb(); + + try { + $resp = $this->_sendCmd($pipeline); + + /* Check for EXPUNGEISSUED (RFC 2180 [4.2]/RFC 5530 [3]). */ + if (!empty($resp->data['expungeissued'])) { + $this->noop(); + } + + return $resp->data['modified']; + } catch (Horde_Imap_Client_Exception_ServerResponse $e) { + /* A NO response, when coupled with a sequence STORE and + * non-SILENT behavior, most likely means that messages were + * expunged. RFC 2180 [4.2] */ + if (empty($pipeline->data['store_silent']) && + !empty($options['sequence']) && + ($e->status === Horde_Imap_Client_Interaction_Server::NO)) { + $this->noop(); + } + + return $pipeline->data['modified']; + } + } + + /** + * Create a store command. + * + * @param array $options See Horde_Imap_Client_Base#_store(). + * + * @return Horde_Imap_Client_Interaction_Pipeline Pipeline object. + */ + protected function _storeCmd($options) + { + $cmds = array(); + $silent = empty($options['unchangedsince']) + ? !($this->_debug->debug || $this->_initCache(true)) + : false; + + if (!empty($options['replace'])) { + $cmds[] = array( + 'FLAGS' . ($silent ? '.SILENT' : ''), + $options['replace'] + ); + } else { + foreach (array('add' => '+', 'remove' => '-') as $k => $v) { + if (!empty($options[$k])) { + $cmds[] = array( + $v . 'FLAGS' . ($silent ? '.SILENT' : ''), + $options[$k] + ); + } + } + } + + $pipeline = $this->_pipeline(); + $pipeline->data['store_silent'] = $silent; + + foreach ($cmds as $val) { + $cmd = $this->_command( + empty($options['sequence']) ? 'UID STORE' : 'STORE' + )->add(strval($options['ids'])); + if (!empty($options['unchangedsince'])) { + $cmd->add(new Horde_Imap_Client_Data_Format_List(array( + 'UNCHANGEDSINCE', + new Horde_Imap_Client_Data_Format_Number(intval($options['unchangedsince'])) + ))); + } + $cmd->add($val); + + $pipeline->add($cmd); + } + + return $pipeline; + } + + /** + */ + protected function _copy(Horde_Imap_Client_Mailbox $dest, $options) + { + /* Check for MOVE command (RFC 6851). */ + $move_cmd = (!empty($options['move']) && + $this->_capability('MOVE')); + + $cmd = $this->_pipeline( + $this->_command( + ($options['ids']->sequence ? '' : 'UID ') . ($move_cmd ? 'MOVE' : 'COPY') + )->add(array( + strval($options['ids']), + $this->_getMboxFormatOb($dest) + )) + ); + $cmd->data['copydest'] = $dest; + + // COPY returns no untagged information (RFC 3501 [6.4.7]) + try { + $resp = $this->_sendCmd($cmd); + } catch (Horde_Imap_Client_Exception $e) { + if (!empty($options['create']) && + !empty($e->resp_data['trycreate'])) { + $this->createMailbox($dest); + unset($options['create']); + return $this->_copy($dest, $options); + } + throw $e; + } + + // If moving, delete the old messages now. Short-circuit if nothing + // was moved. + if (!$move_cmd && + !empty($options['move']) && + (isset($resp->data['copyuid']) || + !$this->_capability('UIDPLUS'))) { + $this->expunge($this->_selected, array( + 'delete' => true, + 'ids' => $options['ids'] + )); + } + + return isset($resp->data['copyuid']) + ? $resp->data['copyuid'] + : true; + } + + /** + */ + protected function _setQuota(Horde_Imap_Client_Mailbox $root, $resources) + { + $limits = new Horde_Imap_Client_Data_Format_List(); + + foreach ($resources as $key => $val) { + $limits->add(array( + Horde_String::upper($key), + new Horde_Imap_Client_Data_Format_Number($val) + )); + } + + $this->_sendCmd( + $this->_command('SETQUOTA')->add(array( + $this->_getMboxFormatOb($root), + $limits + )) + ); + } + + /** + */ + protected function _getQuota(Horde_Imap_Client_Mailbox $root) + { + $pipeline = $this->_pipeline( + $this->_command('GETQUOTA')->add( + $this->_getMboxFormatOb($root) + ) + ); + $pipeline->data['quotaresp'] = array(); + + return reset($this->_sendCmd($pipeline)->data['quotaresp']); + } + + /** + * Parse a QUOTA response (RFC 2087 [5.1]). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data The server response. + */ + protected function _parseQuota( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + Horde_Imap_Client_Tokenize $data + ) + { + $c = &$pipeline->data['quotaresp']; + + $root = $data->next(); + $c[$root] = array(); + + $data->next(); + + while (($curr = $data->next()) !== false) { + $c[$root][Horde_String::lower($curr)] = array( + 'usage' => $data->next(), + 'limit' => $data->next() + ); + } + } + + /** + */ + protected function _getQuotaRoot(Horde_Imap_Client_Mailbox $mailbox) + { + $pipeline = $this->_pipeline( + $this->_command('GETQUOTAROOT')->add( + $this->_getMboxFormatOb($mailbox) + ) + ); + $pipeline->data['quotaresp'] = array(); + + return $this->_sendCmd($pipeline)->data['quotaresp']; + } + + /** + */ + protected function _setACL(Horde_Imap_Client_Mailbox $mailbox, $identifier, + $options) + { + // SETACL returns no untagged information (RFC 4314 [3.1]). + $this->_sendCmd( + $this->_command('SETACL')->add(array( + $this->_getMboxFormatOb($mailbox), + new Horde_Imap_Client_Data_Format_Astring($identifier), + new Horde_Imap_Client_Data_Format_Astring($options['rights']) + )) + ); + } + + /** + */ + protected function _deleteACL(Horde_Imap_Client_Mailbox $mailbox, $identifier) + { + // DELETEACL returns no untagged information (RFC 4314 [3.2]). + $this->_sendCmd( + $this->_command('DELETEACL')->add(array( + $this->_getMboxFormatOb($mailbox), + new Horde_Imap_Client_Data_Format_Astring($identifier) + )) + ); + } + + /** + */ + protected function _getACL(Horde_Imap_Client_Mailbox $mailbox) + { + return $this->_sendCmd( + $this->_command('GETACL')->add( + $this->_getMboxFormatOb($mailbox) + ) + )->data['getacl']; + } + + /** + * Parse an ACL response (RFC 4314 [3.6]). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data The server response. + */ + protected function _parseACL( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + Horde_Imap_Client_Tokenize $data + ) + { + $acl = array(); + + // Ignore mailbox argument -> index 1 + $data->next(); + + while (($curr = $data->next()) !== false) { + $acl[$curr] = ($curr[0] === '-') + ? new Horde_Imap_Client_Data_AclNegative($data->next()) + : new Horde_Imap_Client_Data_Acl($data->next()); + } + + $pipeline->data['getacl'] = $acl; + } + + /** + */ + protected function _listACLRights(Horde_Imap_Client_Mailbox $mailbox, + $identifier) + { + $resp = $this->_sendCmd( + $this->_command('LISTRIGHTS')->add(array( + $this->_getMboxFormatOb($mailbox), + new Horde_Imap_Client_Data_Format_Astring($identifier) + )) + ); + + return isset($resp->data['listaclrights']) + ? $resp->data['listaclrights'] + : new Horde_Imap_Client_Data_AclRights(); + } + + /** + * Parse a LISTRIGHTS response (RFC 4314 [3.7]). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data The server response. + */ + protected function _parseListRights( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + Horde_Imap_Client_Tokenize $data + ) + { + // Ignore mailbox and identifier arguments + $data->next(); + $data->next(); + + $pipeline->data['listaclrights'] = new Horde_Imap_Client_Data_AclRights( + str_split($data->next()), + $data->flushIterator() + ); + } + + /** + */ + protected function _getMyACLRights(Horde_Imap_Client_Mailbox $mailbox) + { + $resp = $this->_sendCmd( + $this->_command('MYRIGHTS')->add( + $this->_getMboxFormatOb($mailbox) + ) + ); + + return isset($resp->data['myrights']) + ? $resp->data['myrights'] + : new Horde_Imap_Client_Data_Acl(); + } + + /** + * Parse a MYRIGHTS response (RFC 4314 [3.8]). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data The server response. + */ + protected function _parseMyRights( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + Horde_Imap_Client_Tokenize $data + ) + { + // Ignore 1st token (mailbox name) + $data->next(); + + $pipeline->data['myrights'] = new Horde_Imap_Client_Data_Acl($data->next()); + } + + /** + */ + protected function _getMetadata(Horde_Imap_Client_Mailbox $mailbox, + $entries, $options) + { + $pipeline = $this->_pipeline(); + $pipeline->data['metadata'] = array(); + + if ($this->_capability('METADATA') || + (strlen($mailbox) && $this->_capability('METADATA-SERVER'))) { + $cmd_options = new Horde_Imap_Client_Data_Format_List(); + + if (!empty($options['maxsize'])) { + $cmd_options->add(array( + 'MAXSIZE', + new Horde_Imap_Client_Data_Format_Number($options['maxsize']) + )); + } + if (!empty($options['depth'])) { + $cmd_options->add(array( + 'DEPTH', + new Horde_Imap_Client_Data_Format_Number($options['depth']) + )); + } + + $queries = new Horde_Imap_Client_Data_Format_List(); + foreach ($entries as $md_entry) { + $queries->add(new Horde_Imap_Client_Data_Format_Astring($md_entry)); + } + + $cmd = $this->_command('GETMETADATA')->add( + $this->_getMboxFormatOb($mailbox) + ); + if (count($cmd_options)) { + $cmd->add($cmd_options); + } + $cmd->add($queries); + + $pipeline->add($cmd); + } else { + if (!$this->_capability('ANNOTATEMORE') && + !$this->_capability('ANNOTATEMORE2')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('METADATA'); + } + + $queries = array(); + foreach ($entries as $md_entry) { + list($entry, $type) = $this->_getAnnotateMoreEntry($md_entry); + + if (!isset($queries[$type])) { + $queries[$type] = new Horde_Imap_Client_Data_Format_List(); + } + $queries[$type]->add(new Horde_Imap_Client_Data_Format_String($entry)); + } + + foreach ($queries as $key => $val) { + // TODO: Honor maxsize and depth options. + $pipeline->add( + $this->_command('GETANNOTATION')->add(array( + $this->_getMboxFormatOb($mailbox), + $val, + new Horde_Imap_Client_Data_Format_String($key) + )) + ); + } + } + + return $this->_sendCmd($pipeline)->data['metadata']; + } + + /** + * Split a name for the METADATA extension into the correct syntax for the + * older ANNOTATEMORE version. + * + * @param string $name A name for a metadata entry. + * + * @return array A list of two elements: The entry name and the value + * type. + * + * @throws Horde_Imap_Client_Exception + */ + protected function _getAnnotateMoreEntry($name) + { + if (substr($name, 0, 7) === '/shared') { + return array(substr($name, 7), 'value.shared'); + } else if (substr($name, 0, 8) === '/private') { + return array(substr($name, 8), 'value.priv'); + } + + $e = new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Invalid METADATA entry: \"%s\"."), + Horde_Imap_Client_Exception::METADATA_INVALID + ); + $e->messagePrintf(array($name)); + throw $e; + } + + /** + */ + protected function _setMetadata(Horde_Imap_Client_Mailbox $mailbox, $data) + { + if ($this->_capability('METADATA') || + (strlen($mailbox) && $this->_capability('METADATA-SERVER'))) { + $data_elts = new Horde_Imap_Client_Data_Format_List(); + + foreach ($data as $key => $value) { + $data_elts->add(array( + new Horde_Imap_Client_Data_Format_Astring($key), + /* METADATA supports literal8 - thus, it implicitly + * supports non-ASCII characters in the data. */ + new Horde_Imap_Client_Data_Format_Nstring_Nonascii($value) + )); + } + + $cmd = $this->_command('SETMETADATA')->add(array( + $this->_getMboxFormatOb($mailbox), + $data_elts + )); + } else { + if (!$this->_capability('ANNOTATEMORE') && + !$this->_capability('ANNOTATEMORE2')) { + throw new Horde_Imap_Client_Exception_NoSupportExtension('METADATA'); + } + + $cmd = $this->_pipeline(); + + foreach ($data as $md_entry => $value) { + list($entry, $type) = $this->_getAnnotateMoreEntry($md_entry); + + $cmd->add( + $this->_command('SETANNOTATION')->add(array( + $this->_getMboxFormatOb($mailbox), + new Horde_Imap_Client_Data_Format_String($entry), + new Horde_Imap_Client_Data_Format_List(array( + new Horde_Imap_Client_Data_Format_String($type), + /* ANNOTATEMORE supports literal8 - thus, it + * implicitly supports non-ASCII characters in the + * data. */ + new Horde_Imap_Client_Data_Format_Nstring_Nonascii($value) + )) + )) + ); + } + } + + $this->_sendCmd($cmd); + } + + /** + * Parse an ANNOTATION response (ANNOTATEMORE/ANNOTATEMORE2). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data The server response. + * + * @throws Horde_Imap_Client_Exception + */ + protected function _parseAnnotation( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + Horde_Imap_Client_Tokenize $data + ) + { + // Mailbox name is in UTF7-IMAP. + $mbox = Horde_Imap_Client_Mailbox::get($data->next(), true); + $entry = $data->next(); + + // Ignore unsolicited responses. + if ($data->next() !== true) { + return; + } + + while (($type = $data->next()) !== false) { + switch ($type) { + case 'value.priv': + $pipeline->data['metadata'][strval($mbox)]['/private' . $entry] = $data->next(); + break; + + case 'value.shared': + $pipeline->data['metadata'][strval($mbox)]['/shared' . $entry] = $data->next(); + break; + + default: + $e = new Horde_Imap_Client_Exception( + Horde_Imap_Client_Translation::r("Invalid METADATA value type \"%s\"."), + Horde_Imap_Client_Exception::METADATA_INVALID + ); + $e->messagePrintf(array($type)); + throw $e; + } + } + } + + /** + * Parse a METADATA response (RFC 5464 [4.4]). + * + * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline + * object. + * @param Horde_Imap_Client_Tokenize $data The server response. + * + * @throws Horde_Imap_Client_Exception + */ + protected function _parseMetadata( + Horde_Imap_Client_Interaction_Pipeline $pipeline, + Horde_Imap_Client_Tokenize $data + ) + { + // Mailbox name is in UTF7-IMAP. + $mbox = Horde_Imap_Client_Mailbox::get($data->next(), true); + + // Ignore unsolicited responses. + if ($data->next() === true) { + while (($entry = $data->next()) !== false) { + $pipeline->data['metadata'][strval($mbox)][$entry] = $data->next(); + } + } + } + + /* Overriden methods. */ + + /** + * @param array $opts Options: + * - decrement: (boolean) If true, decrement the message count. + * - pipeline: (Horde_Imap_Client_Interaction_Pipeline) Pipeline object. + */ + protected function _deleteMsgs(Horde_Imap_Client_Mailbox $mailbox, + Horde_Imap_Client_Ids $ids, + array $opts = array()) + { + /* If there are pending FETCH cache writes, we need to write them + * before the UID -> sequence number mapping changes. */ + if (isset($opts['pipeline'])) { + $this->_updateCache($opts['pipeline']->fetch); + } + + $res = parent::_deleteMsgs($mailbox, $ids); + + if (isset($this->_temp['expunged'])) { + $this->_temp['expunged']->add($res); + } + + if (!empty($opts['decrement'])) { + $mbox_ob = $this->_mailboxOb(); + $mbox_ob->setStatus( + Horde_Imap_Client::STATUS_MESSAGES, + $mbox_ob->getStatus(Horde_Imap_Client::STATUS_MESSAGES) - count($ids) + ); + } + } + + /* Internal functions. */ + + /** + * Return the proper mailbox format object based on the server's + * capabilities. + * + * @param string $mailbox The mailbox. + * @param boolean $list Is this object used in a LIST command? + * + * @return Horde_Imap_Client_Data_Format_Mailbox A mailbox format object. + */ + protected function _getMboxFormatOb($mailbox, $list = false) + { + if ($this->_capability()->isEnabled('UTF8=ACCEPT')) { + try { + return $list + ? new Horde_Imap_Client_Data_Format_ListMailbox_Utf8($mailbox) + : new Horde_Imap_Client_Data_Format_Mailbox_Utf8($mailbox); + } catch (Horde_Imap_Client_Data_Format_Exception $e) {} + } + + return $list + ? new Horde_Imap_Client_Data_Format_ListMailbox($mailbox) + : new Horde_Imap_Client_Data_Format_Mailbox($mailbox); + } + + /** + * Sends command(s) to the IMAP server. A connection to the server must + * have already been made. + * + * @param mixed $cmd Either a Command object or a Pipeline object. + * + * @return Horde_Imap_Client_Interaction_Pipeline A pipeline object. + * @throws Horde_Imap_Client_Exception + */ + protected function _sendCmd($cmd) + { + $pipeline = ($cmd instanceof Horde_Imap_Client_Interaction_Command) + ? $this->_pipeline($cmd) + : $cmd; + + if (!empty($this->_cmdQueue)) { + /* Add commands in reverse order. */ + foreach (arra