diff --git a/.gitignore b/.gitignore index 7b69a62d3..b9a13560a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,15 @@ /.idea +/api.php /error.log /nbproject /npm-debug.log /rainloop.sublime-project /rainloop.sublime-workspace +/rainloop/v/0.0.0/static/fonts/* +!/rainloop/v/0.0.0/static/fonts/.gitempty +/rainloop/v/0.0.0/static/svg/* +!/rainloop/v/0.0.0/static/svg/.gitempty /rainloop/v/0.0.0/static/css/*.css -/rainloop/v/0.0.0/static/js/*.js /rainloop/v/0.0.0/static/js/**/*.js /node_modules /build/local diff --git a/.jshintrc b/.jshintrc index 25fd75f03..969b1a4ad 100644 --- a/.jshintrc +++ b/.jshintrc @@ -51,6 +51,7 @@ "jquery" : true, "globals": { + "RL_COMMUNITY" : true, "module" : true, "require" : true, "ko" : true, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..4b6c3357f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,7 @@ +Thanks for contributing to RainLoop Webmail! + +1. Sign the CLA (individual or corporate) at . +2. Fork the repo, do work in a feature branch. +3. Issue a pull request. + +If you have any questions, open an issue or email [support@rainloop.net](mailto:support@rainloop.net). \ No newline at end of file diff --git a/LICENSE b/LICENSE index 70fc6a921..2def0e883 100644 --- a/LICENSE +++ b/LICENSE @@ -1,25 +1,661 @@ -Creative Commons — Attribution-NonCommercial-ShareAlike 3.0 Unported — CC BY-NC-SA 3.0 -(http://creativecommons.org/licenses/by-nc-sa/3.0/) + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 -You are free: + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. - to Share — to copy, distribute and transmit the work - to Remix — to adapt the work + Preamble -Under the following conditions: + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. - Attribution — You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work). - Noncommercial — You may not use this work for commercial purposes. - Share Alike — If you alter, transform, or build upon this work, you may distribute the resulting work only under the same or similar license to this one. + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. -With the understanding that: + When we speak of free software, we are referring to freedom, 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 +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. - Waiver — Any of the above conditions can be waived if you get permission from the copyright holder. - Public Domain — Where the work or any of its elements is in the public domain under applicable law, that status is in no way affected by the license. + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. -Other Rights — In no way are any of the following rights affected by the license: - Your fair dealing or fair use rights, or other applicable copyright exceptions and limitations; - The author's moral rights; - Rights other persons may have either in the work itself or in how the work is used, such as publicity or privacy rights. + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. -Notice — For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to this web page. \ No newline at end of file + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero 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 +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. \ No newline at end of file diff --git a/README.md b/README.md index 0d358d727..96b3c1c2e 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,13 @@ RainLoop Webmail ================== -[![Join the chat at https://gitter.im/RainLoop/rainloop-webmail](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/RainLoop/rainloop-webmail?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - Simple, modern & fast web-based email client. Modest system requirements, decent performance, simple installation and upgrade, no database required - all these make RainLoop Webmail a perfect choice for your email solution. -For more information about the product, check [http://rainloop.net](http://rainloop.net). +For more information about the product, check [rainloop.net](http://www.rainloop.net/). -Information about installing the product, check the [documentation page](http://rainloop.net/docs/installation/). +Information about installing the product, check the [documentation page](http://www.rainloop.net/docs/installation/). ## Attention @@ -18,7 +16,8 @@ It's not recommended to use in production environment. ## License -**Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)** -http://creativecommons.org/licenses/by-nc-sa/3.0/ +**RainLoop Webmail (Community edition)** is released under +**GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (AGPL)**. +http://www.gnu.org/licenses/agpl-3.0.html Copyright (c) 2015 Rainloop Team diff --git a/_include.php b/_include.php index eefd7e088..b615511b3 100644 --- a/_include.php +++ b/_include.php @@ -10,3 +10,12 @@ function __get_custom_data_full_path() return ''; return '/var/external-rainloop-data-folder/'; // custom data folder path } + +/** + * @return string + */ +function __get_additional_configuration_name() +{ + return ''; + return defined('APP_SITE') && 0 < strlen(APP_SITE) ? APP_SITE.'.ini' : ''; // additional configuration file name +} diff --git a/build/langs.php b/build/langs.php index 9d6248989..339c8bc88 100644 --- a/build/langs.php +++ b/build/langs.php @@ -48,7 +48,7 @@ function saveLangStructure($sLangFile, $aLang) } } - \file_put_contents(LANGS_PATH.'/'.$sLangFile, implode("\n", $aResultLines)); + \file_put_contents(LANGS_PATH.'/'.$sLangFile, implode("\n", $aResultLines)."\n"); } $sNL = "\n"; diff --git a/build/owncloud/rainloop-app/appinfo/info.xml b/build/owncloud/rainloop-app/appinfo/info.xml index 7ec7dbdd9..84b506124 100644 --- a/build/owncloud/rainloop-app/appinfo/info.xml +++ b/build/owncloud/rainloop-app/appinfo/info.xml @@ -4,7 +4,7 @@ RainLoop Simple, modern and fast web-based email client. 0.0 - CC BY-NC-SA 3.0 + RainLoop Team 6.0 diff --git a/build/test.php b/build/test.php new file mode 100644 index 000000000..e5e1422dd --- /dev/null +++ b/build/test.php @@ -0,0 +1,19 @@ + iMinWidth ? iWidth : iMinWidth); } }, + fResizeCreateFunction = function (oEvent) { + if (oEvent && oEvent.target) + { + var oResizableHandle = $(oEvent.target).find('.ui-resizable-handle'); - fResizeFunction = function (oEvent, oObject) { + oResizableHandle + .on('mousedown', function () { + Globals.$html.addClass('rl-resizer'); + }) + .on('mouseup', function () { + Globals.$html.removeClass('rl-resizer'); + }) + ; + } + }, + fResizeResizeFunction = _.debounce(function () { + Globals.$html.addClass('rl-resizer'); + }, 500, true), + fResizeStartFunction = function () { + Globals.$html.addClass('rl-resizer'); + }, + fResizeStopFunction = function (oEvent, oObject) { + Globals.$html.removeClass('rl-resizer'); if (oObject && oObject.size && oObject.size.width) { Local.set(sClientSideKeyName, oObject.size.width); @@ -1210,7 +1243,10 @@ 'minWidth': iMinWidth, 'maxWidth': 350, 'handles': 'e', - 'stop': fResizeFunction + 'create': fResizeCreateFunction, + 'resize': fResizeResizeFunction, + 'start': fResizeStartFunction, + 'stop': fResizeStopFunction }); Events.sub('left-panel.off', function () { @@ -1271,9 +1307,9 @@ { kn.hideLoading(); - if (SimplePace) + if (progressJs) { - SimplePace.set(100); + progressJs().end(); } }; @@ -1291,16 +1327,16 @@ self = this, $LAB = require('$LAB'), sJsHash = Settings.settingsGet('JsHash'), + sStartupUrl = Utils.pString(Settings.settingsGet('StartupUrl')), iContactsSyncInterval = Utils.pInt(Settings.settingsGet('ContactsSyncInterval')), bGoogle = Settings.settingsGet('AllowGoogleSocial'), bFacebook = Settings.settingsGet('AllowFacebookSocial'), bTwitter = Settings.settingsGet('AllowTwitterSocial') ; - if (SimplePace) + if (progressJs) { - SimplePace.set(70); - SimplePace.sleep(); + progressJs().set(70); } Globals.leftPanelDisabled.subscribe(function (bValue) { @@ -1332,10 +1368,26 @@ if (bValue) { + if ('' !== sStartupUrl) + { + kn.routeOff(); + kn.setHash(Links.root(sStartupUrl), true); + kn.routeOn(); + } + if ($LAB && window.crypto && window.crypto.getRandomValues && Settings.capa(Enums.Capa.OpenPGP)) { var fOpenpgpCallback = function (openpgp) { + PgpStore.openpgp = openpgp; + + if (window.Worker) + { + PgpStore.openpgp.initWorker(Links.openPgpWorkerJs()); + } + +// PgpStore.openpgp.config.useWebCrypto = false; + PgpStore.openpgpKeyring = new openpgp.Keyring(); PgpStore.capaOpenPGP(true); @@ -1365,8 +1417,8 @@ kn.startScreens([ require('Screen/User/MailBox'), - require('Screen/User/Settings'), - require('Screen/User/About') + Settings.capa(Enums.Capa.Settings) ? require('Screen/User/Settings') : null, + false ? require('Screen/User/About') : null ]); if (bGoogle || bFacebook || bTwitter) @@ -1386,7 +1438,7 @@ } }); - Events.sub('interval.5m-after5m', function () { + Events.sub('interval.2m-after5m', function () { self.folderInformationMultiply(); }); @@ -1445,7 +1497,9 @@ }, 1000); } - if (!!Settings.settingsGet('AccountSignMe') && window.navigator.registerProtocolHandler) + if (!!Settings.settingsGet('AccountSignMe') && + window.navigator.registerProtocolHandler && + Settings.capa(Enums.Capa.Composer)) { _.delay(function () { try { @@ -1467,7 +1521,7 @@ self.initVerticalLayoutResizer(Enums.ClientSideKeyName.FolderListSize); }); - if (Tinycon) + if (Tinycon && Settings.settingsGet('FaviconStatus') && !Settings.settingsGet('Filtered') ) { Tinycon.setOptions({ fallback: false @@ -1481,7 +1535,7 @@ } else { - this.bootstartLoginScreen(); + this.logout(); } }, self)); diff --git a/dev/Common/Audio.js b/dev/Common/Audio.js index 8e437fc88..13863510d 100644 --- a/dev/Common/Audio.js +++ b/dev/Common/Audio.js @@ -74,9 +74,7 @@ // Audio.prototype.record = function () // { // this.getUserMedia({audio:true}, function () { -// window.console.log(arguments); // }, function(oError) { -// window.console.log(arguments); // }); // }; diff --git a/dev/Common/Cache.js b/dev/Common/Cache.js index bacc24b80..86dc950e9 100644 --- a/dev/Common/Cache.js +++ b/dev/Common/Cache.js @@ -204,7 +204,10 @@ */ CacheUserStorage.prototype.setFolderHash = function (sFolderFullNameRaw, sFolderHash) { - this.oFolderHashCache[sFolderFullNameRaw] = sFolderHash; + if ('' !== sFolderFullNameRaw) + { + this.oFolderHashCache[sFolderFullNameRaw] = sFolderHash; + } }; /** diff --git a/dev/Common/Enums.js b/dev/Common/Enums.js index 36c56ad5e..7dd46a727 100644 --- a/dev/Common/Enums.js +++ b/dev/Common/Enums.js @@ -22,6 +22,7 @@ 'Sheet': 'sheet', 'Presentation': 'presentation', 'Certificate': 'certificate', + 'CertificateBin': 'certificate-bin', 'Archive': 'archive' }; @@ -71,6 +72,18 @@ 'OpenPGP': 'OPEN_PGP', 'Prefetch': 'PREFETCH', 'Gravatar': 'GRAVATAR', + 'Folders': 'FOLDERS', + 'Composer': 'COMPOSER', + 'Contacts': 'CONTACTS', + 'Reload': 'RELOAD', + 'Search': 'SEARCH', + 'SearchAdv': 'SEARCH_ADV', + 'MessageActions': 'MESSAGE_ACTIONS', + 'MessageListActions': 'MESSAGELIST_ACTIONS', + 'AttachmentsActions': 'ATTACHMENTS_ACTIONS', + 'DangerousActions': 'DANGEROUS_ACTIONS', + 'Settings': 'SETTINGS', + 'Help': 'HELP', 'Themes': 'THEMES', 'UserBackground': 'USER_BACKGROUND', 'Sieve': 'SIEVE', @@ -78,7 +91,8 @@ 'AttachmentThumbnails': 'ATTACHMENT_THUMBNAILS', 'Templates': 'TEMPLATES', 'AutoLogout': 'AUTOLOGOUT', - 'AdditionalAccounts': 'ADDITIONAL_ACCOUNTS' + 'AdditionalAccounts': 'ADDITIONAL_ACCOUNTS', + 'Identities': 'IDENTITIES' }; /** @@ -95,6 +109,7 @@ 'Settings': 'settings', 'Menu': 'menu', 'PopupComposeOpenPGP': 'compose-open-pgp', + 'PopupMessageOpenPGP': 'message-open-pgp', 'PopupKeyboardShortcutsHelp': 'popup-keyboard-shortcuts-help', 'PopupAsk': 'popup-ask' }; @@ -113,6 +128,21 @@ 'User': 99 }; + /** + * @enum {number} + */ + Enums.ServerFolderType = { + 'USER': 0, + 'INBOX': 1, + 'SENT': 2, + 'DRAFTS': 3, + 'JUNK': 4, + 'TRASH': 5, + 'IMPORTANT': 10, + 'FLAGGED': 11, + 'ALL': 12 + }; + /** * @enum {string} */ @@ -305,7 +335,9 @@ Enums.FilterConditionField = { 'From': 'From', 'Recipient': 'Recipient', - 'Subject': 'Subject' + 'Subject': 'Subject', + 'Header': 'Header', + 'Size': 'Size' }; /** @@ -315,7 +347,9 @@ 'Contains': 'Contains', 'NotContains': 'NotContains', 'EqualTo': 'EqualTo', - 'NotEqualTo': 'NotEqualTo' + 'NotEqualTo': 'NotEqualTo', + 'Over': 'Over', + 'Under': 'Under' }; /** diff --git a/dev/Common/Globals.js b/dev/Common/Globals.js index 3a4bfb5c1..acb582852 100644 --- a/dev/Common/Globals.js +++ b/dev/Common/Globals.js @@ -1,4 +1,6 @@ +/* global RL_COMMUNITY */ + (function () { 'use strict'; @@ -28,6 +30,11 @@ */ Globals.startMicrotime = (new window.Date()).getTime(); + /** + * @type {boolean} + */ + Globals.community = RL_COMMUNITY; + /** * @type {?} */ @@ -203,6 +210,7 @@ }; Globals.leftPanelDisabled = ko.observable(false); + Globals.leftPanelType = ko.observable(''); // popups Globals.popupVisibilityNames = ko.observableArray([]); @@ -249,7 +257,7 @@ sTagName = sTagName.toUpperCase(); return !(sTagName === 'INPUT' || sTagName === 'SELECT' || sTagName === 'TEXTAREA' || - (oElement && sTagName === 'DIV' && 'editorHtmlArea' === oElement.className && oElement.contentEditable) + (oElement && sTagName === 'DIV' && ('editorHtmlArea' === oElement.className || 'true' === '' + oElement.contentEditable)) ); } diff --git a/dev/Common/HtmlEditor.js b/dev/Common/HtmlEditor.js index 8e9f25c69..e607339df 100644 --- a/dev/Common/HtmlEditor.js +++ b/dev/Common/HtmlEditor.js @@ -32,7 +32,6 @@ this.resize = _.throttle(_.bind(this.resize, this), 100); this.__inited = false; - this.__initedData = null; this.init(); } @@ -104,7 +103,7 @@ */ HtmlEditor.prototype.clearSignatureSigns = function (sText) { - return sText.replace(/(\u0002|\u0003|\u200C|\u200D)/g, ''); + return sText.replace(/(\u200C|\u0002)/g, ''); }; /** @@ -197,6 +196,8 @@ { this.modeToggle(true); + sHtml = sHtml.replace(/]*><\/p>/ig, ''); + try { this.editor.setData(sHtml); } catch (e) {} @@ -206,10 +207,6 @@ this.focus(); } } - else - { - this.__initedData = [true, sHtml, bFocus]; - } }; HtmlEditor.prototype.setPlain = function (sPlain, bFocus) @@ -233,10 +230,6 @@ this.focus(); } } - else - { - this.__initedData = [false, sPlain, bFocus]; - } }; HtmlEditor.prototype.init = function () @@ -270,7 +263,7 @@ } oConfig.enterMode = window.CKEDITOR.ENTER_BR; - oConfig.shiftEnterMode = window.CKEDITOR.ENTER_BR; + oConfig.shiftEnterMode = window.CKEDITOR.ENTER_P; oConfig.language = Globals.oHtmlEditorLangsMap[sLanguage] || 'en'; if (window.CKEDITOR.env) @@ -278,19 +271,6 @@ window.CKEDITOR.env.isCompatible = true; } -// oConfig.allowedContent = { -// $1: { -// elements: window.CKEDITOR.dtd, -// attributes: true, -// styles: true, -// classes: true -// } -// }; -// -// oConfig.disallowedContent = 'script; style; iframe; frame; *[on*]'; - - window.CKEDITOR.dtd.$removeEmpty['p'] = 1; - self.editor = window.CKEDITOR.appendTo(self.$element[0], oConfig); self.editor.on('key', function(oEvent) { @@ -318,37 +298,26 @@ self.focusTrigger(); }); - if (self.fOnReady) - { - self.editor.on('instanceReady', function () { + self.editor.on('instanceReady', function () { - if (self.editor.removeMenuItem) - { - self.editor.removeMenuItem('cut'); - self.editor.removeMenuItem('copy'); - self.editor.removeMenuItem('paste'); - } + if (self.editor.removeMenuItem) + { + self.editor.removeMenuItem('cut'); + self.editor.removeMenuItem('copy'); + self.editor.removeMenuItem('paste'); + } - self.editor.setKeystroke(window.CKEDITOR.CTRL + 65 /* A */, 'selectAll'); + self.__resizable = true; + self.__inited = true; + self.resize(); + + if (self.fOnReady) + { self.fOnReady(); - self.__resizable = true; - self.__inited = true; - self.resize(); + } - if (self.__initedData) - { - if (self.__initedData[0]) - { - self.setHtml(self.__initedData[1], self.__initedData[2]); - } - else - { - self.setPlain(self.__initedData[1], self.__initedData[2]); - } - } - }); - } + }); } ; diff --git a/dev/Common/Links.js b/dev/Common/Links.js index da26296b0..62acbac17 100644 --- a/dev/Common/Links.js +++ b/dev/Common/Links.js @@ -19,12 +19,17 @@ this.sServer = './?'; this.sVersion = Settings.settingsGet('Version'); - this.sSpecSuffix = Settings.settingsGet('AuthAccountHash') || '0'; + this.sAuthSuffix = Settings.settingsGet('AuthAccountHash') || '0'; this.sWebPrefix = Settings.settingsGet('WebPath') || ''; this.sVersionPrefix = Settings.settingsGet('WebVersionPath') || 'rainloop/v/' + this.sVersion + '/'; this.sStaticPrefix = this.sVersionPrefix + 'static/'; } + Links.prototype.populateAuthSuffix = function () + { + this.sAuthSuffix = require('Storage/Settings').settingsGet('AuthAccountHash') || '0'; + }; + /** * @return {string} */ @@ -34,11 +39,12 @@ }; /** + * @param {string=} sStartupUrl * @return {string} */ - Links.prototype.root = function () + Links.prototype.root = function (sStartupUrl) { - return this.sBase; + return this.sBase + Utils.pString(sStartupUrl); }; /** @@ -59,47 +65,62 @@ /** * @param {string} sDownload + * @param {string=} sCustomSpecSuffix * @return {string} */ - Links.prototype.attachmentDownload = function (sDownload) + Links.prototype.attachmentDownload = function (sDownload, sCustomSpecSuffix) { - return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/Download/' + this.subQueryPrefix() + '/' + sDownload; + sCustomSpecSuffix = Utils.isUnd(sCustomSpecSuffix) ? this.sAuthSuffix : sCustomSpecSuffix; + return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + sCustomSpecSuffix + '/Download/' + + this.subQueryPrefix() + '/' + sDownload; }; /** * @param {string} sDownload + * @param {string=} sCustomSpecSuffix * @return {string} */ - Links.prototype.attachmentPreview = function (sDownload) + Links.prototype.attachmentPreview = function (sDownload, sCustomSpecSuffix) { - return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/View/' + this.subQueryPrefix() + '/' + sDownload; + sCustomSpecSuffix = Utils.isUnd(sCustomSpecSuffix) ? this.sAuthSuffix : sCustomSpecSuffix; + return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + sCustomSpecSuffix + '/View/' + + this.subQueryPrefix() + '/' + sDownload; }; /** * @param {string} sDownload + * @param {string=} sCustomSpecSuffix * @return {string} */ - Links.prototype.attachmentThumbnailPreview = function (sDownload) + Links.prototype.attachmentThumbnailPreview = function (sDownload, sCustomSpecSuffix) { - return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/ViewThumbnail/' + this.subQueryPrefix() + '/' + sDownload; + sCustomSpecSuffix = Utils.isUnd(sCustomSpecSuffix) ? this.sAuthSuffix : sCustomSpecSuffix; + return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + sCustomSpecSuffix + '/ViewThumbnail/' + + this.subQueryPrefix() + '/' + sDownload; }; /** * @param {string} sDownload + * @param {string=} sCustomSpecSuffix * @return {string} */ - Links.prototype.attachmentPreviewAsPlain = function (sDownload) + Links.prototype.attachmentPreviewAsPlain = function (sDownload, sCustomSpecSuffix) { - return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/ViewAsPlain/' + this.subQueryPrefix() + '/' + sDownload; + sCustomSpecSuffix = Utils.isUnd(sCustomSpecSuffix) ? this.sAuthSuffix : sCustomSpecSuffix; + return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + sCustomSpecSuffix + '/ViewAsPlain/' + + this.subQueryPrefix() + '/' + sDownload; }; /** * @param {string} sDownload + * @param {string=} sCustomSpecSuffix * @return {string} */ - Links.prototype.attachmentFramed = function (sDownload) + Links.prototype.attachmentFramed = function (sDownload, sCustomSpecSuffix) { - return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/FramedView/' + this.subQueryPrefix() + '/' + sDownload; + sCustomSpecSuffix = Utils.isUnd(sCustomSpecSuffix) ? this.sAuthSuffix : sCustomSpecSuffix; + return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + sCustomSpecSuffix + '/FramedView/' + + this.subQueryPrefix() + '/' + sDownload; }; /** @@ -107,7 +128,7 @@ */ Links.prototype.upload = function () { - return this.sServer + '/Upload/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/'; + return this.sServer + '/Upload/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/'; }; /** @@ -115,7 +136,7 @@ */ Links.prototype.uploadContacts = function () { - return this.sServer + '/UploadContacts/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/'; + return this.sServer + '/UploadContacts/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/'; }; /** @@ -123,7 +144,7 @@ */ Links.prototype.uploadBackground = function () { - return this.sServer + '/UploadBackground/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/'; + return this.sServer + '/UploadBackground/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/'; }; /** @@ -131,7 +152,7 @@ */ Links.prototype.append = function () { - return this.sServer + '/Append/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/'; + return this.sServer + '/Append/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/'; }; /** @@ -140,7 +161,7 @@ */ Links.prototype.change = function (sEmail) { - return this.sServer + '/Change/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/' + Utils.encodeURIComponent(sEmail) + '/'; + return this.sServer + '/Change/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/' + Utils.encodeURIComponent(sEmail) + '/'; }; /** @@ -149,7 +170,7 @@ */ Links.prototype.ajax = function (sAdd) { - return this.sServer + '/Ajax/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/' + sAdd; + return this.sServer + '/Ajax/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/' + sAdd; }; /** @@ -158,7 +179,7 @@ */ Links.prototype.messageViewLink = function (sRequestHash) { - return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/ViewAsPlain/' + this.subQueryPrefix() + '/' + sRequestHash; + return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/ViewAsPlain/' + this.subQueryPrefix() + '/' + sRequestHash; }; /** @@ -167,7 +188,7 @@ */ Links.prototype.messageDownloadLink = function (sRequestHash) { - return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/Download/' + this.subQueryPrefix() + '/' + sRequestHash; + return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/Download/' + this.subQueryPrefix() + '/' + sRequestHash; }; /** @@ -194,7 +215,7 @@ */ Links.prototype.userBackground = function (sHash) { - return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + + return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/UserBackground/' + this.subQueryPrefix() + '/' + sHash; }; @@ -257,23 +278,30 @@ * @param {string} sFolder * @param {number=} iPage = 1 * @param {string=} sSearch = '' + * @param {string=} sThreadUid = '' * @return {string} */ - Links.prototype.mailBox = function (sFolder, iPage, sSearch) + Links.prototype.mailBox = function (sFolder, iPage, sSearch, sThreadUid) { iPage = Utils.isNormal(iPage) ? Utils.pInt(iPage) : 1; sSearch = Utils.pString(sSearch); - var sResult = this.sBase + 'mailbox/'; + var + sResult = this.sBase + 'mailbox/', + iThreadUid = Utils.pInt(sThreadUid) + ; + if ('' !== sFolder) { - sResult += encodeURI(sFolder); + sResult += encodeURI(sFolder) + (0 < iThreadUid ? '~' + iThreadUid : ''); } + if (1 < iPage) { sResult = sResult.replace(/[\/]+$/, ''); sResult += '/p' + iPage; } + if ('' !== sSearch) { sResult = sResult.replace(/[\/]+$/, ''); @@ -305,7 +333,7 @@ */ Links.prototype.exportContactsVcf = function () { - return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/ContactsVcf/'; + return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/ContactsVcf/'; }; /** @@ -313,7 +341,7 @@ */ Links.prototype.exportContactsCsv = function () { - return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/ContactsCsv/'; + return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/ContactsCsv/'; }; /** @@ -362,15 +390,33 @@ */ Links.prototype.openPgpJs = function () { - return this.sStaticPrefix + 'js/min/openpgp.js'; + return this.sStaticPrefix + 'js/min/openpgp.min.js'; }; /** * @return {string} */ - Links.prototype.socialGoogle = function () + Links.prototype.openPgpWorkerJs = function () { - return this.sServer + 'SocialGoogle' + ('' !== this.sSpecSuffix ? '/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/' : ''); + return this.sStaticPrefix + 'js/min/openpgp.worker.min.js'; + }; + + /** + * @return {string} + */ + Links.prototype.openPgpWorkerPath = function () + { + return this.sStaticPrefix + 'js/min/'; + }; + + /** + * @param {boolean} bXAuth = false + * @return {string} + */ + Links.prototype.socialGoogle = function (bXAuth) + { + return this.sServer + 'SocialGoogle' + ('' !== this.sAuthSuffix ? '/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/' : '') + + (bXAuth ? '&xauth=1' : ''); }; /** @@ -378,7 +424,7 @@ */ Links.prototype.socialTwitter = function () { - return this.sServer + 'SocialTwitter' + ('' !== this.sSpecSuffix ? '/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/' : ''); + return this.sServer + 'SocialTwitter' + ('' !== this.sAuthSuffix ? '/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/' : ''); }; /** @@ -386,7 +432,7 @@ */ Links.prototype.socialFacebook = function () { - return this.sServer + 'SocialFacebook' + ('' !== this.sSpecSuffix ? '/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/' : ''); + return this.sServer + 'SocialFacebook' + ('' !== this.sAuthSuffix ? '/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/' : ''); }; module.exports = new Links(); diff --git a/dev/Common/Selector.js b/dev/Common/Selector.js index 0918e42b1..623da8d3f 100644 --- a/dev/Common/Selector.js +++ b/dev/Common/Selector.js @@ -633,13 +633,20 @@ var iOffset = 20, + aList = this.list(), oFocused = $(this.sItemFocusedSelector, this.oContentScrollable), oPos = oFocused.position(), iVisibleHeight = this.oContentVisible.height(), iFocusedHeight = oFocused.outerHeight() ; - if (oPos && (oPos.top < 0 || oPos.top + iFocusedHeight > iVisibleHeight)) + if (aList && aList[0] && aList[0].focused()) + { + this.oContentScrollable.scrollTop(0); + + return true; + } + else if (oPos && (oPos.top < 0 || oPos.top + iFocusedHeight > iVisibleHeight)) { if (oPos.top < 0) { @@ -771,10 +778,7 @@ if (bClick) { - this.focusedItem(oItem); - this.selectedItem(oItem); - - this.scrollToFocused(); + this.selectMessageItem(oItem); } } }; @@ -784,6 +788,14 @@ this.oCallbacks[sEventName] = fCallback; }; + Selector.prototype.selectMessageItem = function (oMessageItem) + { + this.focusedItem(oMessageItem); + this.selectedItem(oMessageItem); + + this.scrollToFocused(); + }; + module.exports = Selector; }()); \ No newline at end of file diff --git a/dev/Common/Translator.js b/dev/Common/Translator.js index b9fd187ea..5a5e9d87f 100644 --- a/dev/Common/Translator.js +++ b/dev/Common/Translator.js @@ -10,6 +10,7 @@ ko = require('ko'), Enums = require('Common/Enums'), + Utils = require('Common/Utils'), Globals = require('Common/Globals') ; @@ -24,6 +25,8 @@ this.trigger = ko.observable(false); this.i18n = _.bind(this.i18n, this); + + this.init(); } Translator.prototype.data = {}; @@ -293,29 +296,41 @@ { var self = this, - $html = $('html'), - fEmptyFunction = function () {}, iStart = (new Date()).getTime() ; - $html.addClass('rl-changing-language'); + Globals.$html.addClass('rl-changing-language'); $.ajax({ 'url': require('Common/Links').langLink(sLanguage, bAdmin), 'dataType': 'script', 'cache': true }) - .fail(fFail || fEmptyFunction) + .fail(fFail || Utils.emptyFunction) .done(function () { _.delay(function () { + self.reloadData(); - (fDone || fEmptyFunction)(); - $html.removeClass('rl-changing-language'); + + (fDone || Utils.emptyFunction)(); + + Globals.$html + .removeClass('rl-changing-language') + .removeClass('rl-rtl rl-ltr') + .addClass(-1 < Utils.inArray(sLanguage, ['ar', 'he', 'ur']) ? 'rl-rtl' : 'rl-ltr') +// .attr('dir', -1 < Utils.inArray(sLanguage, ['ar', 'he', 'ur']) ? 'rtl' : 'ltr') + ; + }, 500 < (new Date()).getTime() - iStart ? 1 : 500); }) ; }; + Translator.prototype.init = function () + { + Globals.$html.addClass('rl-' + (Globals.$html.attr('dir') || 'ltr')); + }; + module.exports = new Translator(); }()); diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index daf84d133..ed59539b0 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -150,6 +150,11 @@ { if (sMailToUrl && 'mailto:' === sMailToUrl.toString().substr(0, 7).toLowerCase()) { + if (!PopupComposeVoreModel) + { + return true; + } + sMailToUrl = sMailToUrl.toString().substr(7); var @@ -534,14 +539,14 @@ oEvent.preventDefault(); return; } - - if (oSender && oSender.tagName && oSender.tagName.match(/INPUT|TEXTAREA/i)) + else if (iKey === Enums.EventKeyCode.A) { - return; - } + if (oSender && ('true' === '' + oSender.contentEditable || + (oSender.tagName && oSender.tagName.match(/INPUT|TEXTAREA/i)))) + { + return; + } - if (iKey === Enums.EventKeyCode.A) - { if (window.getSelection) { window.getSelection().removeAllRanges(); @@ -847,7 +852,11 @@ }, convertPre = function () { - return (arguments && 1 < arguments.length) ? arguments[1].toString().replace(/[\n]/gm, '
') : ''; + return (arguments && 1 < arguments.length) ? + arguments[1].toString() + .replace(/[\n]/gm, '
') + .replace(/[\r]/gm, '') + : ''; }, fixAttibuteValue = function () { @@ -861,16 +870,17 @@ ; sText = sHtml - // specials for signature - .replace(/\u0002\u0002/g, '\u200C\u200C') - .replace(/\u0003\u0003/g, '\u200D\u200D') - - .replace(/]*>([\s\S\r\n]*)<\/pre>/gmi, convertPre) + .replace(/\u0002([\s\S]*)\u0002/gm, '\u200C$1\u200C') + .replace(/]*><\/p>/gi, '') + .replace(/]*>([\s\S\r\n\t]*)<\/pre>/gmi, convertPre) .replace(/[\s]+/gm, ' ') .replace(/((?:href|data)\s?=\s?)("[^"]+?"|'[^']+?')/gmi, fixAttibuteValue) .replace(/]*>/gmi, '\n') .replace(/<\/h[\d]>/gi, '\n') .replace(/<\/p>/gi, '\n\n') + .replace(/]*>/gmi, '\n') + .replace(/<\/ul>/gi, '\n') + .replace(/]*>/gmi, ' * ') .replace(/<\/li>/gi, '\n') .replace(/<\/td>/gi, '\n') .replace(/<\/tr>/gi, '\n') @@ -1012,16 +1022,12 @@ sPlain = aText.join("\n"); sPlain = sPlain - - // specials for signature - .replace(/\u200C\u200C/g, '\u0002\u0002') - .replace(/\u200D\u200D/g, '\u0003\u0003') - // .replace(/~~~\/blockquote~~~\n~~~blockquote~~~/g, '\n') .replace(/&/g, '&') .replace(/>/g, '>').replace(/') .replace(/[\s]*~~~\/blockquote~~~/g, '') + .replace(/\u200C([\s\S]*)\u200C/g, '\u0002$1\u0002') .replace(/\n/g, '
') ; diff --git a/dev/Component/AbstracCheckbox.js b/dev/Component/AbstracCheckbox.js index 7bb6533b5..de4696b92 100644 --- a/dev/Component/AbstracCheckbox.js +++ b/dev/Component/AbstracCheckbox.js @@ -48,11 +48,13 @@ this.inverted = Utils.isUnd(oParams.inverted) ? false : !!oParams.inverted; this.labeled = !Utils.isUnd(oParams.label); + this.labelAnimated = !!oParams.labelAnimated; } _.extend(AbstracCheckbox.prototype, AbstractComponent.prototype); - AbstracCheckbox.prototype.click = function() { + AbstracCheckbox.prototype.click = function() + { if (!this.readOnly && this.enable() && !this.disable()) { this.value(!this.value()); diff --git a/dev/Component/Select.js b/dev/Component/Select.js index a987e7669..046f7603a 100644 --- a/dev/Component/Select.js +++ b/dev/Component/Select.js @@ -7,6 +7,7 @@ _ = require('_'), Utils = require('Common/Utils'), + Translator = require('Common/Translator'), AbstractInput = require('Component/AbstractInput') ; @@ -26,6 +27,12 @@ this.optionsText = oParams.optionsText || null; this.optionsValue = oParams.optionsValue || null; + this.optionsCaption = oParams.optionsCaption || null; + + if (this.optionsCaption) + { + this.optionsCaption = Translator.i18n(this.optionsCaption); + } this.defautOptionsAfterRender = Utils.defautOptionsAfterRender; } diff --git a/dev/Component/SvgIcon.js b/dev/Component/SvgIcon.js new file mode 100644 index 000000000..710754c6f --- /dev/null +++ b/dev/Component/SvgIcon.js @@ -0,0 +1,35 @@ + +(function () { + + 'use strict'; + + var + $ = require('$'), + sUrl = null, + getUtl = function () { + if (!sUrl) + { + sUrl = 'rainloop/v/' + ($('#rlAppVersion').attr('content') || '0.0.0') + '/static/css/svg/icons.svg'; + } + + return sUrl; + } + ; + + module.exports = { + viewModel: { + createViewModel: function(oParams, oComponentInfo) { + var icon = oParams.icon || 'null'; + if (oComponentInfo.element && oComponentInfo.element) + { + $(oComponentInfo.element).replaceWith( +''); + } + } + }, + 'template': '' + }; + +}()); + + diff --git a/dev/External/ko.js b/dev/External/ko.js index b2e1e4712..dc8161007 100644 --- a/dev/External/ko.js +++ b/dev/External/ko.js @@ -7,6 +7,7 @@ window = require('window'), _ = require('_'), $ = require('$'), + JSON = require('JSON'), Opentip = require('Opentip'), fDisposalTooltipHelper = function (oElement) { @@ -24,36 +25,54 @@ 'init': function (oElement, fValueAccessor) { var - fValue = fValueAccessor(), oEditor = null, + fValue = fValueAccessor(), + fUpdateEditorValue = function () { - if (oEditor) + if (fValue && fValue.__editor) { - oEditor.setHtmlOrPlain(fValue()); + fValue.__editor.setHtmlOrPlain(fValue()); } }, + fUpdateKoValue = function () { - if (oEditor && oEditor.__inited) + if (fValue && fValue.__editor) { - fValue(oEditor.getDataWithHtmlMark()); + fValue(fValue.__editor.getDataWithHtmlMark()); } }, + + fOnReady = function () { + fValue.__editor = oEditor; + fUpdateEditorValue(); + }, + HtmlEditor = require('Common/HtmlEditor') ; - if (fValue) + if (ko.isObservable(fValue) && HtmlEditor) { - oEditor = new HtmlEditor(oElement, fUpdateKoValue, fUpdateEditorValue, fUpdateKoValue); - fValue.__editor = oEditor; + oEditor = new HtmlEditor(oElement, fUpdateKoValue, fOnReady, fUpdateKoValue); + fValue.__fetchEditorValue = fUpdateKoValue; - fValue.__updateEditorValue = fUpdateEditorValue; fValue.subscribe(fUpdateEditorValue); - fUpdateEditorValue(); + +// ko.utils.domNodeDisposal.addDisposeCallback(oElement, function () { +// }); } } }; + ko.bindingHandlers.json = { + 'init': function (oElement, fValueAccessor) { + $(oElement).text(JSON.stringify(ko.unwrap(fValueAccessor()))); + }, + 'update': function (oElement, fValueAccessor) { + $(oElement).text(JSON.stringify(ko.unwrap(fValueAccessor()))); + } + }; + ko.bindingHandlers.tooltip = { 'init': function (oElement, fValueAccessor) { @@ -266,8 +285,7 @@ ko.bindingHandlers.csstext = { 'init': function (oElement, fValueAccessor) { - var Utils = require('Common/Utils'); - if (oElement && oElement.styleSheet && !Utils.isUnd(oElement.styleSheet.cssText)) + if (oElement && oElement.styleSheet && undefined !== oElement.styleSheet.cssText) { oElement.styleSheet.cssText = ko.unwrap(fValueAccessor()); } @@ -277,8 +295,7 @@ } }, 'update': function (oElement, fValueAccessor) { - var Utils = require('Common/Utils'); - if (oElement && oElement.styleSheet && !Utils.isUnd(oElement.styleSheet.cssText)) + if (oElement && oElement.styleSheet && undefined !== oElement.styleSheet.cssText) { oElement.styleSheet.cssText = ko.unwrap(fValueAccessor()); } @@ -324,6 +341,36 @@ } }; + ko.bindingHandlers.onSpace = { + 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { + $(oElement).on('keyup.koOnSpace', function (oEvent) { + if (oEvent && 32 === window.parseInt(oEvent.keyCode, 10)) + { + fValueAccessor().call(oViewModel, oEvent); + } + }); + + ko.utils.domNodeDisposal.addDisposeCallback(oElement, function () { + $(oElement).off('keyup.koOnSpace'); + }); + } + }; + + ko.bindingHandlers.onTab = { + 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { + $(oElement).on('keydown.koOnTab', function (oEvent) { + if (oEvent && 9 === window.parseInt(oEvent.keyCode, 10)) + { + return fValueAccessor().call(oViewModel, !!oEvent.shiftKey); + } + }); + + ko.utils.domNodeDisposal.addDisposeCallback(oElement, function () { + $(oElement).off('keydown.koOnTab'); + }); + } + }; + ko.bindingHandlers.onEsc = { 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { $(oElement).on('keypress.koOnEsc', function (oEvent) { @@ -774,7 +821,7 @@ 'parseOnBlur': true, 'allowDragAndDrop': true, 'focusCallback': fFocusCallback, - 'inputDelimiters': [',', ';'], + 'inputDelimiters': [',', ';', "\n"], 'autoCompleteSource': fAutoCompleteSource, // 'elementHook': function (oEl, oItem) { // if (oEl && oItem) @@ -784,6 +831,7 @@ // } // }, 'parseHook': function (aInput) { + return _.map(aInput, function (sInputValue) { var @@ -801,6 +849,53 @@ return [sValue, null]; }); + +// var aResult = []; +// +// _.each(aInput, function (sInputValue) { +// +// var +// aM = null, +// aValues = [], +// sValue = Utils.trim(sInputValue), +// oEmail = null +// ; +// +// if ('' !== sValue) +// { +// aM = sValue.match(/[@]/g); +// if (aM && 0 < aM.length) +// { +// sValue = sValue.replace(/[\r\n]+/g, '; ').replace(/[\s]+/g, ' '); +// aValues = EmailModel.splitHelper(sValue, ';'); +// +// _.each(aValues, function (sV) { +// +// oEmail = new EmailModel(); +// oEmail.mailsoParse(sV); +// +// if (oEmail.email) +// { +// aResult.push([oEmail.toLine(false), oEmail]); +// } +// else +// { +// aResult.push(['', null]); +// } +// }); +// } +// else +// { +// aResult.push([sInputValue, null]); +// } +// } +// else +// { +// aResult.push([sInputValue, null]); +// } +// }); +// +// return aResult; }, 'change': _.bind(function (oEvent) { $oEl.data('EmailsTagsValue', oEvent.target.value); diff --git a/dev/Knoin/Knoin.js b/dev/Knoin/Knoin.js index c8052eda5..01808641c 100644 --- a/dev/Knoin/Knoin.js +++ b/dev/Knoin/Knoin.js @@ -170,8 +170,6 @@ Globals.popupVisibilityNames.push(this.viewModelName); oViewModel.viewModelDom.css('z-index', 3000 + Globals.popupVisibilityNames().length + 10); -// Utils.delegateRun(this, 'onShow'); // moved to showScreenPopup function (for parameters) - if (this.onShowTrigger) { this.onShowTrigger(!this.onShowTrigger()); @@ -257,6 +255,8 @@ if (ViewModelClassToShow.__vm && ViewModelClassToShow.__dom) { + Utils.delegateRun(ViewModelClassToShow.__vm, 'onBeforeShow', aParameters || []); + ViewModelClassToShow.__vm.modalVisibility(true); Utils.delegateRun(ViewModelClassToShow.__vm, 'onShow', aParameters || []); @@ -383,6 +383,8 @@ if (ViewModelClass.__vm && ViewModelClass.__dom && 'Popups' !== ViewModelClass.__vm.viewModelPosition()) { + Utils.delegateRun(ViewModelClass.__vm, 'onBeforeShow'); + ViewModelClass.__dom.show(); ViewModelClass.__vm.viewModelVisibility(true); @@ -425,19 +427,22 @@ _.each(aScreensClasses, function (CScreen) { - var - oScreen = new CScreen(), - sScreenName = oScreen ? oScreen.screenName() : '' - ; - - if (oScreen && '' !== sScreenName) + if (CScreen) { - if ('' === this.sDefaultScreenName) - { - this.sDefaultScreenName = sScreenName; - } + var + oScreen = new CScreen(), + sScreenName = oScreen ? oScreen.screenName() : '' + ; - this.oScreens[sScreenName] = oScreen; + if (oScreen && '' !== sScreenName) + { + if ('' === this.sDefaultScreenName) + { + this.sDefaultScreenName = sScreenName; + } + + this.oScreens[sScreenName] = oScreen; + } } }, this); diff --git a/dev/Model/Attachment.js b/dev/Model/Attachment.js index d4dc6911e..0534494c1 100644 --- a/dev/Model/Attachment.js +++ b/dev/Model/Attachment.js @@ -189,7 +189,8 @@ */ AttachmentModel.prototype.hasPreview = function () { - return this.isImage() || (this.isPdf() && Globals.bAllowPdfPreview) || this.isText() || this.isFramed(); + return this.isImage() || (this.isPdf() && Globals.bAllowPdfPreview) || + this.isText() || this.isFramed(); }; /** @@ -370,12 +371,17 @@ sResult = Enums.FileType.Pdf; break; case -1 < Utils.inArray(sMimeType, [ - 'application/pgp-signature', 'application/pkcs7-signature', 'application/pgp-keys' + 'application/pgp-signature', 'application/pgp-keys' ]) || -1 < Utils.inArray(sExt, [ 'asc', 'pem', 'ppk' ]): sResult = Enums.FileType.Certificate; break; + case -1 < Utils.inArray(sMimeType, ['application/pkcs7-signature']) || + -1 < Utils.inArray(sExt, ['p7s']): + + sResult = Enums.FileType.CertificateBin; + break; case -1 < Utils.inArray(aMimeTypeParts[1], [ 'rtf', 'msword', 'vnd.msword', 'vnd.openxmlformats-officedocument.wordprocessingml.document', 'vnd.openxmlformats-officedocument.wordprocessingml.template', @@ -447,6 +453,7 @@ sClass = 'icon-file-zip'; break; case Enums.FileType.Certificate: + case Enums.FileType.CertificateBin: sClass = 'icon-file-certificate'; break; case Enums.FileType.Sheet: @@ -509,6 +516,7 @@ sClass = 'icon-file-zip'; break; case Enums.FileType.Certificate: + case Enums.FileType.CertificateBin: sClass = 'icon-file-certificate'; break; case Enums.FileType.Sheet: diff --git a/dev/Model/Email.js b/dev/Model/Email.js index 173ed2a80..9304c7d22 100644 --- a/dev/Model/Email.js +++ b/dev/Model/Email.js @@ -36,6 +36,49 @@ return oEmailModel.initByJson(oJsonEmail) ? oEmailModel : null; }; + /** + * @static + * @param {string} sLine + * @param {string=} sDelimiter = ';' + * @return {Array} + */ + EmailModel.splitHelper = function (sLine, sDelimiter) + { + sDelimiter = sDelimiter || ';'; + + sLine = sLine.replace(/[\r\n]+/g, '; ').replace(/[\s]+/g, ' '); + + var + iIndex = 0, + iLen = sLine.length, + bAt = false, + sChar = '', + sResult = '' + ; + + for (; iIndex < iLen; iIndex++) + { + sChar = sLine.charAt(iIndex); + switch (sChar) + { + case '@': + bAt = true; + break; + case ' ': + if (bAt) + { + bAt = false; + sResult += sDelimiter; + } + break; + } + + sResult += sChar; + } + + return sResult.split(sDelimiter); + }; + /** * @type {string} */ diff --git a/dev/Model/Filter.js b/dev/Model/Filter.js index e919427d0..748f0c6c5 100644 --- a/dev/Model/Filter.js +++ b/dev/Model/Filter.js @@ -43,6 +43,9 @@ this.actionValueSecond = ko.observable(''); this.actionValueThird = ko.observable(''); + this.actionValueFourth = ko.observable(''); + this.actionValueFourth.error = ko.observable(false); + this.actionMarkAsRead = ko.observable(false); this.actionKeep = ko.observable(true); @@ -55,6 +58,8 @@ this.actionValue.error(false); this.actionValueSecond(''); this.actionValueThird(''); + this.actionValueFourth(''); + this.actionValueFourth.error(false); }, this); var fGetRealFolderName = function (sFolderFullNameRaw) { @@ -189,6 +194,14 @@ return false; } + if (Enums.FiltersAction.Vacation === this.actionType() && + '' !== this.actionValueFourth() && -1 === this.actionValueFourth().indexOf('@') + ) + { + this.actionValueFourth.error(true); + return false; + } + this.name.error(false); this.actionValue.error(false); @@ -209,6 +222,7 @@ 'ActionValue': this.actionValue(), 'ActionValueSecond': this.actionValueSecond(), 'ActionValueThird': this.actionValueThird(), + 'ActionValueFourth': this.actionValueFourth(), 'ActionType': this.actionType(), 'Stop': this.actionNoStop() ? '0' : '1', @@ -228,6 +242,11 @@ Utils.delegateRunOnDestroy(oConditionToDelete); }; + FilterModel.prototype.setRecipients = function () + { + this.actionValueFourth(require('Stores/User/Account').accountsEmails().join(', ')); + }; + FilterModel.prototype.parse = function (oItem) { var bResult = false; @@ -255,6 +274,7 @@ this.actionValue(Utils.pString(oItem['ActionValue'])); this.actionValueSecond(Utils.pString(oItem['ActionValueSecond'])); this.actionValueThird(Utils.pString(oItem['ActionValueThird'])); + this.actionValueFourth(Utils.pString(oItem['ActionValueFourth'])); this.actionNoStop(!oItem['Stop']); this.actionKeep(!!oItem['Keep']); @@ -288,6 +308,7 @@ oClone.actionValueSecond(this.actionValueSecond()); oClone.actionValueThird(this.actionValueThird()); + oClone.actionValueFourth(this.actionValueFourth()); oClone.actionKeep(this.actionKeep()); oClone.actionNoStop(this.actionNoStop()); diff --git a/dev/Model/FilterCondition.js b/dev/Model/FilterCondition.js index 9192ea059..e33ee9ade 100644 --- a/dev/Model/FilterCondition.js +++ b/dev/Model/FilterCondition.js @@ -25,11 +25,20 @@ this.value = ko.observable(''); this.value.error = ko.observable(false); + this.valueSecond = ko.observable(''); + this.valueSecond.error = ko.observable(false); + this.template = ko.computed(function () { var sTemplate = ''; - switch (this.type()) + switch (this.field()) { + case Enums.FilterConditionField.Size: + sTemplate = 'SettingsFiltersConditionSize'; + break; + case Enums.FilterConditionField.Header: + sTemplate = 'SettingsFiltersConditionMore'; + break; default: sTemplate = 'SettingsFiltersConditionDefault'; break; @@ -39,6 +48,11 @@ }, this); + this.field.subscribe(function () { + this.value(''); + this.valueSecond(''); + }, this); + this.regDisposables([this.template]); } @@ -52,6 +66,12 @@ return false; } + if (Enums.FilterConditionField.Header === this.field() && '' === this.valueSecond()) + { + this.valueSecond.error(true); + return false; + } + return true; }; @@ -62,6 +82,7 @@ this.field(Utils.pString(oItem['Field'])); this.type(Utils.pString(oItem['Type'])); this.value(Utils.pString(oItem['Value'])); + this.valueSecond(Utils.pString(oItem['ValueSecond'])); return true; } @@ -74,7 +95,8 @@ return { 'Field': this.field(), 'Type': this.type(), - 'Value': this.value() + 'Value': this.value(), + 'ValueSecond': this.valueSecond() }; }; @@ -85,6 +107,7 @@ oClone.field(this.field()); oClone.type(this.type()); oClone.value(this.value()); + oClone.valueSecond(this.valueSecond()); return oClone; }; diff --git a/dev/Model/Folder.js b/dev/Model/Folder.js index 668fec202..909645706 100644 --- a/dev/Model/Folder.js +++ b/dev/Model/Folder.js @@ -43,6 +43,7 @@ this.edited = ko.observable(false); this.collapsed = ko.observable(true); this.subScribed = ko.observable(true); + this.checkable = ko.observable(false); this.subFolders = ko.observableArray([]); this.deleteAccess = ko.observable(false); this.actionBlink = ko.observable(false).extend({'falseTimeout': 1000}); @@ -105,6 +106,7 @@ }, this); this.hidden = ko.computed(function () { + var bSystem = this.isSystemFolder(), bSubFolders = this.hasSubScribedSubfolders() @@ -182,6 +184,8 @@ return !this.isSystemFolder() && this.selectable && sInboxFolderName !== this.fullNameRaw; }, this); + this.canBeChecked = this.canBeSubScribed; + // this.visible.subscribe(function () { // Utils.timeOutAction('folder-list-folder-visibility-change', function () { // Globals.$win.trigger('folder-list-folder-visibility-change'); @@ -281,7 +285,7 @@ }); this.hasUnreadMessages = ko.computed(function () { - return 0 < this.messageCountUnread(); + return 0 < this.messageCountUnread() && '' !== this.printableUnreadCount(); }, this); this.hasSubScribedUnreadMessagesSubfolders = ko.computed(function () { @@ -352,6 +356,8 @@ this.existen = !!oJsonFolder.IsExists; this.subScribed(!!oJsonFolder.IsSubscribed); + this.checkable(!!oJsonFolder.Checkable); + this.type(sInboxFolderName === this.fullNameRaw ? Enums.FolderType.Inbox : Enums.FolderType.User); bResult = true; diff --git a/dev/Model/Message.js b/dev/Model/Message.js index 399e51912..32eda9cf1 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -14,8 +14,6 @@ Globals = require('Common/Globals'), Links = require('Common/Links'), - PgpStore = require('Stores/User/Pgp'), - AttachmentModel = require('Model/Attachment'), MessageHelper = require('Helper/Message'), @@ -82,7 +80,6 @@ }, this); this.body = null; - this.plainRaw = ''; this.isHtml = ko.observable(false); this.hasImages = ko.observable(false); @@ -784,47 +781,55 @@ */ MessageModel.prototype.populateByMessageListItem = function (oMessage) { - this.folderFullNameRaw = oMessage.folderFullNameRaw; - this.uid = oMessage.uid; - this.hash = oMessage.hash; - this.requestHash = oMessage.requestHash; - this.subject(oMessage.subject()); + if (oMessage) + { + this.folderFullNameRaw = oMessage.folderFullNameRaw; + this.uid = oMessage.uid; + this.hash = oMessage.hash; + this.requestHash = oMessage.requestHash; + this.subject(oMessage.subject()); + } + this.subjectPrefix(this.subjectPrefix()); this.subjectSuffix(this.subjectSuffix()); - this.size(oMessage.size()); - this.dateTimeStampInUTC(oMessage.dateTimeStampInUTC()); - this.priority(oMessage.priority()); + if (oMessage) + { - this.proxy = oMessage.proxy; + this.size(oMessage.size()); + this.dateTimeStampInUTC(oMessage.dateTimeStampInUTC()); + this.priority(oMessage.priority()); - this.fromEmailString(oMessage.fromEmailString()); - this.fromClearEmailString(oMessage.fromClearEmailString()); - this.toEmailsString(oMessage.toEmailsString()); - this.toClearEmailsString(oMessage.toClearEmailsString()); + this.proxy = oMessage.proxy; - this.emails = oMessage.emails; + this.fromEmailString(oMessage.fromEmailString()); + this.fromClearEmailString(oMessage.fromClearEmailString()); + this.toEmailsString(oMessage.toEmailsString()); + this.toClearEmailsString(oMessage.toClearEmailsString()); - this.from = oMessage.from; - this.to = oMessage.to; - this.cc = oMessage.cc; - this.bcc = oMessage.bcc; - this.replyTo = oMessage.replyTo; - this.deliveredTo = oMessage.deliveredTo; + this.emails = oMessage.emails; - this.unseen(oMessage.unseen()); - this.flagged(oMessage.flagged()); - this.answered(oMessage.answered()); - this.forwarded(oMessage.forwarded()); - this.isReadReceipt(oMessage.isReadReceipt()); - this.deletedMark(oMessage.deletedMark()); + this.from = oMessage.from; + this.to = oMessage.to; + this.cc = oMessage.cc; + this.bcc = oMessage.bcc; + this.replyTo = oMessage.replyTo; + this.deliveredTo = oMessage.deliveredTo; - this.priority(oMessage.priority()); + this.unseen(oMessage.unseen()); + this.flagged(oMessage.flagged()); + this.answered(oMessage.answered()); + this.forwarded(oMessage.forwarded()); + this.isReadReceipt(oMessage.isReadReceipt()); + this.deletedMark(oMessage.deletedMark()); - this.selected(oMessage.selected()); - this.checked(oMessage.checked()); - this.hasAttachments(oMessage.hasAttachments()); - this.attachmentsSpecData(oMessage.attachmentsSpecData()); + this.priority(oMessage.priority()); + + this.selected(oMessage.selected()); + this.checked(oMessage.checked()); + this.hasAttachments(oMessage.hasAttachments()); + this.attachmentsSpecData(oMessage.attachmentsSpecData()); + } this.body = null; @@ -833,7 +838,10 @@ this.sInReplyTo = ''; this.sReferences = ''; - this.threads(oMessage.threads()); + if (oMessage) + { + this.threads(oMessage.threads()); + } this.computeSenderEmail(); @@ -978,191 +986,21 @@ } }; - MessageModel.prototype.storeDataToDom = function () + MessageModel.prototype.storeDataInDom = function () { if (this.body) { this.body.data('rl-is-html', !!this.isHtml()); this.body.data('rl-has-images', !!this.hasImages()); - - this.body.data('rl-plain-raw', this.plainRaw); - - if (require('Stores/User/Pgp').capaOpenPGP()) - { - this.body.data('rl-plain-pgp-signed', !!this.isPgpSigned()); - this.body.data('rl-plain-pgp-encrypted', !!this.isPgpEncrypted()); - this.body.data('rl-pgp-verify-status', this.pgpSignedVerifyStatus()); - this.body.data('rl-pgp-verify-user', this.pgpSignedVerifyUser()); - } } }; - MessageModel.prototype.storePgpVerifyDataToDom = function () - { - if (this.body && require('Stores/User/Pgp').capaOpenPGP()) - { - this.body.data('rl-pgp-verify-status', this.pgpSignedVerifyStatus()); - this.body.data('rl-pgp-verify-user', this.pgpSignedVerifyUser()); - } - }; - - MessageModel.prototype.fetchDataToDom = function () + MessageModel.prototype.fetchDataFromDom = function () { if (this.body) { this.isHtml(!!this.body.data('rl-is-html')); this.hasImages(!!this.body.data('rl-has-images')); - - this.plainRaw = Utils.pString(this.body.data('rl-plain-raw')); - - if (require('Stores/User/Pgp').capaOpenPGP()) - { - this.isPgpSigned(!!this.body.data('rl-plain-pgp-signed')); - this.isPgpEncrypted(!!this.body.data('rl-plain-pgp-encrypted')); - this.pgpSignedVerifyStatus(this.body.data('rl-pgp-verify-status')); - this.pgpSignedVerifyUser(this.body.data('rl-pgp-verify-user')); - } - else - { - this.isPgpSigned(false); - this.isPgpEncrypted(false); - this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None); - this.pgpSignedVerifyUser(''); - } - } - }; - - MessageModel.prototype.verifyPgpSignedClearMessage = function () - { - if (this.isPgpSigned()) - { - var - aRes = [], - mPgpMessage = null, - sFrom = this.from && this.from[0] && this.from[0].email ? this.from[0].email : '', - aPublicKeys = PgpStore.findPublicKeysByEmail(sFrom), - oValidKey = null, - oValidSysKey = null, - sPlain = '' - ; - - this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Error); - this.pgpSignedVerifyUser(''); - - try - { - mPgpMessage = PgpStore.openpgp.cleartext.readArmored(this.plainRaw); - if (mPgpMessage && mPgpMessage.getText) - { - this.pgpSignedVerifyStatus( - aPublicKeys.length ? Enums.SignedVerifyStatus.Unverified : Enums.SignedVerifyStatus.UnknownPublicKeys); - - aRes = mPgpMessage.verify(aPublicKeys); - if (aRes && 0 < aRes.length) - { - oValidKey = _.find(aRes, function (oItem) { - return oItem && oItem.keyid && oItem.valid; - }); - - if (oValidKey) - { - oValidSysKey = PgpStore.findPublicKeyByHex(oValidKey.keyid.toHex()); - if (oValidSysKey) - { - sPlain = mPgpMessage.getText(); - - this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Success); - this.pgpSignedVerifyUser(oValidSysKey.user); - - sPlain = - Globals.$div.empty().append( - $('
').text(sPlain)
-									).html()
-									;
-
-								Globals.$div.empty();
-
-								this.replacePlaneTextBody(sPlain);
-							}
-						}
-					}
-				}
-			}
-			catch (oExc) {}
-
-			this.storePgpVerifyDataToDom();
-		}
-	};
-
-	MessageModel.prototype.decryptPgpEncryptedMessage = function (sPassword)
-	{
-		if (this.isPgpEncrypted())
-		{
-			var
-				aRes = [],
-				mPgpMessage = null,
-				mPgpMessageDecrypted = null,
-				sFrom = this.from && this.from[0] && this.from[0].email ? this.from[0].email : '',
-				aPublicKey = PgpStore.findPublicKeysByEmail(sFrom),
-				oPrivateKey = PgpStore.findSelfPrivateKey(sPassword),
-				oValidKey = null,
-				oValidSysKey = null,
-				sPlain = ''
-			;
-
-			this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Error);
-			this.pgpSignedVerifyUser('');
-
-			if (!oPrivateKey)
-			{
-				this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.UnknownPrivateKey);
-			}
-
-			try
-			{
-				mPgpMessage = PgpStore.openpgp.message.readArmored(this.plainRaw);
-				if (mPgpMessage && oPrivateKey && mPgpMessage.decrypt)
-				{
-					this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Unverified);
-
-					mPgpMessageDecrypted = mPgpMessage.decrypt(oPrivateKey);
-					if (mPgpMessageDecrypted)
-					{
-						aRes = mPgpMessageDecrypted.verify(aPublicKey);
-						if (aRes && 0 < aRes.length)
-						{
-							oValidKey = _.find(aRes, function (oItem) {
-								return oItem && oItem.keyid && oItem.valid;
-							});
-
-							if (oValidKey)
-							{
-								oValidSysKey = PgpStore.findPublicKeyByHex(oValidKey.keyid.toHex());
-								if (oValidSysKey)
-								{
-									this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Success);
-									this.pgpSignedVerifyUser(oValidSysKey.user);
-								}
-							}
-						}
-
-						sPlain = mPgpMessageDecrypted.getText();
-
-						sPlain =
-							Globals.$div.empty().append(
-							$('
').text(sPlain)
-							).html()
-							;
-
-						Globals.$div.empty();
-
-						this.replacePlaneTextBody(sPlain);
-					}
-				}
-			}
-			catch (oExc) {}
-
-			this.storePgpVerifyDataToDom();
 		}
 	};
 
diff --git a/dev/Model/OpenPgpKey.js b/dev/Model/OpenPgpKey.js
index 22c46bbbe..896bd056b 100644
--- a/dev/Model/OpenPgpKey.js
+++ b/dev/Model/OpenPgpKey.js
@@ -7,6 +7,8 @@
 		_ = require('_'),
 		ko = require('ko'),
 
+		PgpStore = require('Stores/User/Pgp'),
+
 		AbstractModel = require('Knoin/AbstractModel')
 	;
 
@@ -45,6 +47,22 @@
 	OpenPgpKeyModel.prototype.armor = '';
 	OpenPgpKeyModel.prototype.isPrivate = false;
 
+	OpenPgpKeyModel.prototype.getNativeKeys = function ()
+	{
+		var oKey = null;
+		try
+		{
+			oKey = PgpStore.openpgp.key.readArmored(this.armor);
+			if (oKey && !oKey.err && oKey.keys && oKey.keys[0])
+			{
+				return oKey.keys;
+			}
+		}
+		catch (e) {}
+
+		return null;
+	};
+
 	module.exports = OpenPgpKeyModel;
 
 }());
\ No newline at end of file
diff --git a/dev/Promises/AbstractAjax.js b/dev/Promises/AbstractAjax.js
index 0ef3faf62..20d51b54d 100644
--- a/dev/Promises/AbstractAjax.js
+++ b/dev/Promises/AbstractAjax.js
@@ -10,8 +10,10 @@
 
 		Consts = require('Common/Consts'),
 		Enums = require('Common/Enums'),
+		Globals = require('Common/Globals'),
 		Utils = require('Common/Utils'),
 		Links = require('Common/Links'),
+		Plugins = require('Common/Plugins'),
 
 		Settings = require('Storage/Settings'),
 
@@ -71,6 +73,8 @@
 			oParameters['XToken'] = Settings.settingsGet('Token');
 		}
 
+		Plugins.runHook('ajax-default-request', [sAction, oParameters, sAdditionalGetString]);
+
 		this.setTrigger(fTrigger, true);
 
 		oH = $.ajax({
@@ -83,12 +87,26 @@
 			'global': true
 		}).always(function (oData, sTextStatus) {
 
-			var bCached = false;
+			var bCached = false, oErrorData = null, sType = Enums.StorageResultType.Error;
 			if (oData && oData['Time'])
 			{
 				bCached = Utils.pInt(oData['Time']) > Utils.microtime() - iStart;
 			}
 
+			// backward capability
+			switch (true)
+			{
+				case 'success' === sTextStatus && oData && oData.Result && sAction === oData.Action:
+					sType = Enums.StorageResultType.Success;
+					break;
+				case 'abort' === sTextStatus && (!oData || !oData.__aborted__):
+					sType = Enums.StorageResultType.Abort;
+					break;
+			}
+
+			Plugins.runHook('ajax-default-response', [sAction,
+				Enums.StorageResultType.Success === sType ? oData : null, sType, bCached, oParameters]);
+
 			if ('success' === sTextStatus)
 			{
 				if (oData && oData.Result && sAction === oData.Action)
@@ -98,15 +116,18 @@
 				}
 				else if (oData && oData.Action)
 				{
+					oErrorData = oData;
 					oDeferred.reject(oData.ErrorCode ? oData.ErrorCode : Enums.Notification.AjaxFalse);
 				}
 				else
 				{
+					oErrorData = oData;
 					oDeferred.reject(Enums.Notification.AjaxParse);
 				}
 			}
 			else if ('timeout' === sTextStatus)
 			{
+				oErrorData = oData;
 				oDeferred.reject(Enums.Notification.AjaxTimeout);
 			}
 			else if ('abort' === sTextStatus)
@@ -118,6 +139,7 @@
 			}
 			else
 			{
+				oErrorData = oData;
 				oDeferred.reject(Enums.Notification.AjaxParse);
 			}
 
@@ -128,6 +150,45 @@
 			}
 
 			self.setTrigger(fTrigger, false);
+
+			if (oErrorData)
+			{
+				if (-1 < Utils.inArray(oErrorData.ErrorCode, [
+					Enums.Notification.AuthError, Enums.Notification.AccessError,
+					Enums.Notification.ConnectionError, Enums.Notification.DomainNotAllowed, Enums.Notification.AccountNotAllowed,
+					Enums.Notification.MailServerError,	Enums.Notification.UnknownNotification, Enums.Notification.UnknownError
+				]))
+				{
+					Globals.iAjaxErrorCount++;
+				}
+
+				if (Enums.Notification.InvalidToken === oErrorData.ErrorCode)
+				{
+					Globals.iTokenErrorCount++;
+				}
+
+				if (Consts.Values.TokenErrorLimit < Globals.iTokenErrorCount)
+				{
+					if (Globals.__APP__ && Globals.__APP__.loginAndLogoutReload)
+					{
+						 Globals.__APP__.loginAndLogoutReload(false, true);
+					}
+				}
+
+				if (oErrorData.ClearAuth || oErrorData.Logout || Consts.Values.AjaxErrorLimit < Globals.iAjaxErrorCount)
+				{
+					if (Globals.__APP__ && Globals.__APP__.clearClientSideToken)
+					{
+						Globals.__APP__.clearClientSideToken();
+					}
+
+					if (Globals.__APP__ && !oErrorData.ClearAuth && Globals.__APP__.loginAndLogoutReload)
+					{
+						Globals.__APP__.loginAndLogoutReload(false, true);
+					}
+				}
+			}
+
 		});
 
 		if (oH)
diff --git a/dev/Promises/User/Ajax.js b/dev/Promises/User/Ajax.js
index 6dec2b76f..6cc9de4ba 100644
--- a/dev/Promises/User/Ajax.js
+++ b/dev/Promises/User/Ajax.js
@@ -16,8 +16,6 @@
 //		AppStore = require('Stores/User/App'),
 //		SettingsStore = require('Stores/User/Settings'),
 
-		MessageSimpleModel = require('Model/MessageSimple'),
-
 		PromisesPopulator = require('Promises/User/Populator'),
 		AbstractAjaxPromises = require('Promises/AbstractAjax')
 	;
@@ -29,44 +27,10 @@
 	function UserAjaxUserPromises()
 	{
 		AbstractAjaxPromises.call(this);
-
-		this.messageListSimpleHash = '';
-		this.messageListSimpleCache = null;
 	}
 
 	_.extend(UserAjaxUserPromises.prototype, AbstractAjaxPromises.prototype);
 
-	UserAjaxUserPromises.prototype.messageListSimple = function (sFolder, aUids, fTrigger)
-	{
-		var self = this, sHash = sFolder + '~' + aUids.join('/');
-		if (sHash === this.messageListSimpleHash && this.messageListSimpleCache)
-		{
-			return this.fastResolve(this.messageListSimpleCache);
-		}
-
-		return this.abort('MessageListSimple')
-			.postRequest('MessageListSimple', fTrigger, {
-				'Folder': sFolder,
-				'Uids': aUids
-			}).then(function (oData) {
-
-				self.messageListSimpleHash = sHash;
-				self.messageListSimpleCache = _.compact(_.map(oData.Result, function (aItem) {
-					return MessageSimpleModel.newInstanceFromJson(aItem);
-				}));
-
-				return self.messageListSimpleCache;
-
-			}, function (iError) {
-
-				self.messageListSimpleHash = '';
-				self.messageListSimpleCache = null;
-
-				return self.fastReject(iError);
-			})
-		;
-	};
-
 	UserAjaxUserPromises.prototype.foldersReload = function (fTrigger)
 	{
 		return this.abort('Folders')
@@ -115,7 +79,7 @@
 	UserAjaxUserPromises.prototype.attachmentsActions = function (sAction, aHashes, fTrigger)
 	{
 		return this.postRequest('AttachmentsActions', fTrigger, {
-			'Action': sAction,
+			'Do': sAction,
 			'Hashes': aHashes
 		});
 	};
diff --git a/dev/Promises/User/Populator.js b/dev/Promises/User/Populator.js
index 623396bb0..87a41bcf9 100644
--- a/dev/Promises/User/Populator.js
+++ b/dev/Promises/User/Populator.js
@@ -90,6 +90,15 @@
 
 				if (oCacheFolder)
 				{
+					if (!FolderStore.displaySpecSetting())
+					{
+						oCacheFolder.checkable(true);
+					}
+					else
+					{
+						oCacheFolder.checkable(!!oFolder.Checkable);
+					}
+
 					oCacheFolder.collapsed(!self.isFolderExpanded(oCacheFolder.fullNameHash));
 
 					if (oFolder.Extended)
@@ -131,6 +140,14 @@
 		if (oData && 'Collection/FolderCollection' === oData['@Object'] &&
 			oData['@Collection'] && Utils.isArray(oData['@Collection']))
 		{
+			var
+				iLimit = Utils.pInt(Settings.settingsGet('FolderSpecLimit')),
+				iC = Utils.pInt(oData['CountRec'])
+			;
+
+			iLimit = 100 < iLimit ? 100 : (10 > iLimit ? 10 : iLimit);
+
+			FolderStore.displaySpecSetting(0 >= iC || iLimit < iC);
 			FolderStore.folderList(this.folderResponseParseRec(
 				Utils.isUnd(oData.Namespace) ? '' : oData.Namespace, oData['@Collection']));
 		}
@@ -162,12 +179,11 @@
 				Settings.settingsGet('ArchiveFolder') +
 				Settings.settingsGet('NullFolder'))
 			{
-				// TODO Magic Numbers
-				Settings.settingsSet('SentFolder', oData['SystemFolders'][2] || null);
-				Settings.settingsSet('DraftFolder', oData['SystemFolders'][3] || null);
-				Settings.settingsSet('SpamFolder', oData['SystemFolders'][4] || null);
-				Settings.settingsSet('TrashFolder', oData['SystemFolders'][5] || null);
-				Settings.settingsSet('ArchiveFolder', oData['SystemFolders'][12] || null);
+				Settings.settingsSet('SentFolder', oData['SystemFolders'][Enums.ServerFolderType.SENT] || null);
+				Settings.settingsSet('DraftFolder', oData['SystemFolders'][Enums.ServerFolderType.DRAFTS] || null);
+				Settings.settingsSet('SpamFolder', oData['SystemFolders'][Enums.ServerFolderType.JUNK] || null);
+				Settings.settingsSet('TrashFolder', oData['SystemFolders'][Enums.ServerFolderType.TRASH] || null);
+				Settings.settingsSet('ArchiveFolder', oData['SystemFolders'][Enums.ServerFolderType.ALL] || null);
 
 				bUpdate = true;
 			}
diff --git a/dev/Remote/User/Ajax.js b/dev/Remote/User/Ajax.js
index 20ee13045..b5a145b25 100644
--- a/dev/Remote/User/Ajax.js
+++ b/dev/Remote/User/Ajax.js
@@ -313,39 +313,30 @@
 		});
 	};
 
-	/**
-	 * @param {?Function} fCallback
-	 * @param {string} sFolderFullNameRaw
-	 * @param {Array} aUids
-	 */
-	RemoteUserAjax.prototype.messageListSimple = function (fCallback, sFolderFullNameRaw, aUids)
-	{
-		return this.defaultRequest(fCallback, 'MessageListSimple', {
-			'Folder': Utils.pString(sFolderFullNameRaw),
-			'Uids': aUids
-		}, Consts.Defaults.DefaultAjaxTimeout, '', ['MessageListSimple']);
-	};
-
 	/**
 	 * @param {?Function} fCallback
 	 * @param {string} sFolderFullNameRaw
 	 * @param {number=} iOffset = 0
 	 * @param {number=} iLimit = 20
 	 * @param {string=} sSearch = ''
+	 * @param {string=} sThreadUid = ''
 	 * @param {boolean=} bSilent = false
 	 */
-	RemoteUserAjax.prototype.messageList = function (fCallback, sFolderFullNameRaw, iOffset, iLimit, sSearch, bSilent)
+	RemoteUserAjax.prototype.messageList = function (fCallback, sFolderFullNameRaw, iOffset, iLimit, sSearch, sThreadUid, bSilent)
 	{
 		sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw);
 
 		var
-			sFolderHash = Cache.getFolderHash(sFolderFullNameRaw)
+			sFolderHash = Cache.getFolderHash(sFolderFullNameRaw),
+			bUseThreads = AppStore.threadsAllowed() && SettingsStore.useThreads(),
+			sInboxUidNext = Cache.getFolderInboxName() === sFolderFullNameRaw ? Cache.getFolderUidNext(sFolderFullNameRaw) : ''
 		;
 
 		bSilent = Utils.isUnd(bSilent) ? false : !!bSilent;
 		iOffset = Utils.isUnd(iOffset) ? 0 : Utils.pInt(iOffset);
 		iLimit = Utils.isUnd(iOffset) ? 20 : Utils.pInt(iLimit);
 		sSearch = Utils.pString(sSearch);
+		sThreadUid = Utils.pString(sThreadUid);
 
 		if ('' !== sFolderHash && ('' === sSearch || -1 === sSearch.indexOf('is:')))
 		{
@@ -358,9 +349,9 @@
 					sSearch,
 					AppStore.projectHash(),
 					sFolderHash,
-					Cache.getFolderInboxName() === sFolderFullNameRaw ? Cache.getFolderUidNext(sFolderFullNameRaw) : '',
-					AppStore.threadsAllowed() && SettingsStore.useThreads() ? '1' : '0',
-					''
+					sInboxUidNext,
+					bUseThreads ? '1' : '0',
+					bUseThreads ? sThreadUid : ''
 				].join(String.fromCharCode(0))), bSilent ? [] : ['MessageList']);
 		}
 		else
@@ -370,9 +361,11 @@
 				'Offset': iOffset,
 				'Limit': iLimit,
 				'Search': sSearch,
-				'UidNext': Cache.getFolderInboxName() === sFolderFullNameRaw ? Cache.getFolderUidNext(sFolderFullNameRaw) : '',
-				'UseThreads': AppStore.threadsAllowed() && SettingsStore.useThreads() ? '1' : '0'
-			}, '' === sSearch ? Consts.Defaults.DefaultAjaxTimeout : Consts.Defaults.SearchAjaxTimeout, '', bSilent ? [] : ['MessageList']);
+				'UidNext': sInboxUidNext,
+				'UseThreads': bUseThreads ? '1' : '0',
+				'ThreadUid': bUseThreads ? sThreadUid : ''
+			}, '' === sSearch ? Consts.Defaults.DefaultAjaxTimeout : Consts.Defaults.SearchAjaxTimeout,
+				'', bSilent ? [] : ['MessageList']);
 		}
 	};
 
@@ -414,35 +407,6 @@
 		return false;
 	};
 
-	/**
-	 * @param {?Function} fCallback
-	 * @param {string} sFolderFullNameRaw
-	 * @param {number} iUid
-	 * @return {boolean}
-	 */
-	RemoteUserAjax.prototype.messageThreadsFromCache = function (fCallback, sFolderFullNameRaw, iUid)
-	{
-		sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw);
-		iUid = Utils.pInt(iUid);
-
-		if (Cache.getFolderFromCacheList(sFolderFullNameRaw) && 0 < iUid)
-		{
-			var sFolderHash = Cache.getFolderHash(sFolderFullNameRaw);
-			if (sFolderHash)
-			{
-				this.defaultRequest(fCallback, 'MessageThreadsFromCache', {
-					'Folder': sFolderFullNameRaw,
-					'FolderHash': sFolderHash,
-					'Uid': iUid
-				});
-
-				return true;
-			}
-		}
-
-		return false;
-	};
-
 	/**
 	 * @param {?Function} fCallback
 	 * @param {Array} aExternals
@@ -744,19 +708,34 @@
 		});
 	};
 
+	/**
+	 * @param {?Function} fCallback
+	 * @param {string} sFolderFullNameRaw
+	 * @param {boolean} bCheckable
+	 */
+	RemoteUserAjax.prototype.folderSetCheckable = function (fCallback, sFolderFullNameRaw, bCheckable)
+	{
+		this.defaultRequest(fCallback, 'FolderCheckable', {
+			'Folder': sFolderFullNameRaw,
+			'Checkable': bCheckable ? '1' : '0'
+		});
+	};
+
 	/**
 	 * @param {?Function} fCallback
 	 * @param {string} sFolder
 	 * @param {string} sToFolder
 	 * @param {Array} aUids
 	 * @param {string=} sLearning
+	 * @param {boolean=} bMarkAsRead
 	 */
-	RemoteUserAjax.prototype.messagesMove = function (fCallback, sFolder, sToFolder, aUids, sLearning)
+	RemoteUserAjax.prototype.messagesMove = function (fCallback, sFolder, sToFolder, aUids, sLearning, bMarkAsRead)
 	{
 		this.defaultRequest(fCallback, 'MessageMove', {
 			'FromFolder': sFolder,
 			'ToFolder': sToFolder,
 			'Uids': aUids.join(','),
+			'MarkAsRead': bMarkAsRead ? '1' : '0',
 			'Learning': sLearning || ''
 		}, null, '', ['MessageList']);
 	};
diff --git a/dev/Screen/AbstractSettings.js b/dev/Screen/AbstractSettings.js
index 0727236f4..27d179cd2 100644
--- a/dev/Screen/AbstractSettings.js
+++ b/dev/Screen/AbstractSettings.js
@@ -131,6 +131,7 @@
 					// show
 					if (self.oCurrentSubScreen)
 					{
+						Utils.delegateRun(self.oCurrentSubScreen, 'onBeforeShow');
 						self.oCurrentSubScreen.viewModelDom.show();
 						Utils.delegateRun(self.oCurrentSubScreen, 'onShow');
 						Utils.delegateRun(self.oCurrentSubScreen, 'onShowWithDelay', [], 200);
diff --git a/dev/Screen/Admin/Settings.js b/dev/Screen/Admin/Settings.js
index 71267ca4c..bac2bedd5 100644
--- a/dev/Screen/Admin/Settings.js
+++ b/dev/Screen/Admin/Settings.js
@@ -38,8 +38,16 @@
 		kn.addSettingsViewModel(require('Settings/Admin/Login'),
 			'AdminSettingsLogin', 'TABS_LABELS/LABEL_LOGIN_NAME', 'login');
 
-		kn.addSettingsViewModel(require('Settings/Admin/Branding'),
-			'AdminSettingsBranding', 'TABS_LABELS/LABEL_BRANDING_NAME', 'branding');
+		if (RL_COMMUNITY)
+		{
+			kn.addSettingsViewModel(require('Settings/Admin/Branding'),
+				'AdminSettingsBranding', 'TABS_LABELS/LABEL_BRANDING_NAME', 'branding');
+		}
+		else
+		{
+			kn.addSettingsViewModel(require('Settings/Admin/Prem/Branding'),
+				'AdminSettingsBranding', 'TABS_LABELS/LABEL_BRANDING_NAME', 'branding');
+		}
 
 		kn.addSettingsViewModel(require('Settings/Admin/Contacts'),
 			'AdminSettingsContacts', 'TABS_LABELS/LABEL_CONTACTS_NAME', 'contacts');
@@ -59,8 +67,11 @@
 		kn.addSettingsViewModel(require('Settings/Admin/Packages'),
 			'AdminSettingsPackages', 'TABS_LABELS/LABEL_PACKAGES_NAME', 'packages');
 
-		kn.addSettingsViewModel(require('Settings/Admin/Licensing'),
-			'AdminSettingsLicensing', 'TABS_LABELS/LABEL_LICENSING_NAME', 'licensing');
+		if (!RL_COMMUNITY)
+		{
+			kn.addSettingsViewModel(require('Settings/Admin/Prem/Licensing'),
+				'AdminSettingsLicensing', 'TABS_LABELS/LABEL_LICENSING_NAME', 'licensing');
+		}
 
 		kn.addSettingsViewModel(require('Settings/Admin/About'),
 			'AdminSettingsAbout', 'TABS_LABELS/LABEL_ABOUT_NAME', 'about');
diff --git a/dev/Screen/User/MailBox.js b/dev/Screen/User/MailBox.js
index 64bb526cf..07a6da8c8 100644
--- a/dev/Screen/User/MailBox.js
+++ b/dev/Screen/User/MailBox.js
@@ -20,6 +20,8 @@
 		FolderStore = require('Stores/User/Folder'),
 		MessageStore = require('Stores/User/Message'),
 
+		Settings = require('Storage/Settings'),
+
 		AbstractScreen = require('Knoin/AbstractScreen')
 	;
 
@@ -53,6 +55,11 @@
 			nFoldersInboxUnreadCount = FolderStore.foldersInboxUnreadCount()
 		;
 
+		if (Settings.settingsGet('Filtered'))
+		{
+			nFoldersInboxUnreadCount = 0;
+		}
+
 		require('App/User').setWindowTitle(('' === sEmail ? '' : '' +
 			(0 < nFoldersInboxUnreadCount ? '(' + nFoldersInboxUnreadCount + ') ' : ' ') +
 				sEmail + ' - ') + Translator.i18n('TITLES/MAILBOX'));
@@ -64,26 +71,43 @@
 
 		AppStore.focusedState(Enums.Focused.None);
 		AppStore.focusedState(Enums.Focused.MessageList);
+
+		if (!Settings.capa(Enums.Capa.Folders))
+		{
+			Globals.leftPanelType(
+				Settings.capa(Enums.Capa.Composer) || Settings.capa(Enums.Capa.Contacts) ? 'short' : 'none');
+		}
+		else
+		{
+			Globals.leftPanelType('');
+		}
 	};
 
 	/**
 	 * @param {string} sFolderHash
 	 * @param {number} iPage
 	 * @param {string} sSearch
-	 * @param {boolean=} bPreview = false
 	 */
 	MailBoxUserScreen.prototype.onRoute = function (sFolderHash, iPage, sSearch)
 	{
 		var
-			sFolderFullNameRaw = Cache.getFolderFullNameRaw(sFolderHash),
-			oFolder = Cache.getFolderFromCacheList(sFolderFullNameRaw)
+			sThreadUid = sFolderHash.replace(/^(.+)~([\d]+)$/, '$2'),
+			oFolder = Cache.getFolderFromCacheList(Cache.getFolderFullNameRaw(
+				sFolderHash.replace(/~([\d]+)$/, '')))
 		;
 
 		if (oFolder)
 		{
+			if (sFolderHash === sThreadUid)
+			{
+				sThreadUid = '';
+			}
+
 			FolderStore.currentFolder(oFolder);
+
 			MessageStore.messageListPage(iPage);
 			MessageStore.messageListSearch(sSearch);
+			MessageStore.messageListThreadUid(sThreadUid);
 
 			require('App/User').reloadMessageList();
 		}
@@ -163,9 +187,9 @@
 		;
 
 		return [
-			[/^([a-zA-Z0-9]+)\/p([1-9][0-9]*)\/(.+)\/?$/, {'normalize_': fNormS}],
-			[/^([a-zA-Z0-9]+)\/p([1-9][0-9]*)$/, {'normalize_': fNormS}],
-			[/^([a-zA-Z0-9]+)\/(.+)\/?$/, {'normalize_': fNormD}],
+			[/^([a-zA-Z0-9~]+)\/p([1-9][0-9]*)\/(.+)\/?$/, {'normalize_': fNormS}],
+			[/^([a-zA-Z0-9~]+)\/p([1-9][0-9]*)$/, {'normalize_': fNormS}],
+			[/^([a-zA-Z0-9~]+)\/(.+)\/?$/, {'normalize_': fNormD}],
 			[/^([^\/]*)$/,  {'normalize_': fNormS}]
 		];
 	};
diff --git a/dev/Screen/User/Settings.js b/dev/Screen/User/Settings.js
index cb0ee5722..8ac11868f 100644
--- a/dev/Screen/User/Settings.js
+++ b/dev/Screen/User/Settings.js
@@ -47,6 +47,16 @@
 	 */
 	SettingsUserScreen.prototype.setupSettings = function (fCallback)
 	{
+		if (!Settings.capa(Enums.Capa.Settings))
+		{
+			if (fCallback)
+			{
+				fCallback();
+			}
+
+			return false;
+		}
+
 		kn.addSettingsViewModel(require('Settings/User/General'),
 			'SettingsGeneral', 'SETTINGS_LABELS/LABEL_GENERAL_NAME', 'general', true);
 
@@ -56,9 +66,12 @@
 				'SettingsContacts', 'SETTINGS_LABELS/LABEL_CONTACTS_NAME', 'contacts');
 		}
 
-		kn.addSettingsViewModel(require('Settings/User/Accounts'), 'SettingsAccounts',
-			Settings.capa(Enums.Capa.AdditionalAccounts) ?
-				'SETTINGS_LABELS/LABEL_ACCOUNTS_NAME' : 'SETTINGS_LABELS/LABEL_IDENTITIES_NAME', 'accounts');
+		if (Settings.capa(Enums.Capa.AdditionalAccounts) || Settings.capa(Enums.Capa.Identities))
+		{
+			kn.addSettingsViewModel(require('Settings/User/Accounts'), 'SettingsAccounts',
+				Settings.capa(Enums.Capa.AdditionalAccounts) ?
+					'SETTINGS_LABELS/LABEL_ACCOUNTS_NAME' : 'SETTINGS_LABELS/LABEL_IDENTITIES_NAME', 'accounts');
+		}
 
 		if (Settings.capa(Enums.Capa.Sieve))
 		{
@@ -72,10 +85,10 @@
 				'SettingsSecurity', 'SETTINGS_LABELS/LABEL_SECURITY_NAME', 'security');
 		}
 
-		if (AccountStore.isRootAccount() &&
+		if (AccountStore.isRootAccount() && (
 			(Settings.settingsGet('AllowGoogleSocial') && Settings.settingsGet('AllowGoogleSocialAuth')) ||
 			Settings.settingsGet('AllowFacebookSocial') ||
-			Settings.settingsGet('AllowTwitterSocial'))
+			Settings.settingsGet('AllowTwitterSocial')))
 		{
 			kn.addSettingsViewModel(require('Settings/User/Social'),
 				'SettingsSocial', 'SETTINGS_LABELS/LABEL_SOCIAL_NAME', 'social');
@@ -93,8 +106,11 @@
 				'SettingsTemplates', 'SETTINGS_LABELS/LABEL_TEMPLATES_NAME', 'templates');
 		}
 
-		kn.addSettingsViewModel(require('Settings/User/Folders'),
-			'SettingsFolders', 'SETTINGS_LABELS/LABEL_FOLDERS_NAME', 'folders');
+		if (Settings.capa(Enums.Capa.Folders))
+		{
+			kn.addSettingsViewModel(require('Settings/User/Folders'),
+				'SettingsFolders', 'SETTINGS_LABELS/LABEL_FOLDERS_NAME', 'folders');
+		}
 
 		if (Settings.capa(Enums.Capa.Themes))
 		{
@@ -114,12 +130,15 @@
 		{
 			fCallback();
 		}
+
+		return true;
 	};
 
 	SettingsUserScreen.prototype.onShow = function ()
 	{
 		this.setSettingsTitle();
 		Globals.keyScope(Enums.KeyState.Settings);
+		Globals.leftPanelType('');
 	};
 
 	SettingsUserScreen.prototype.setSettingsTitle = function ()
diff --git a/dev/Settings/.gitignore b/dev/Settings/.gitignore
new file mode 100644
index 000000000..d686bd062
--- /dev/null
+++ b/dev/Settings/.gitignore
@@ -0,0 +1,2 @@
+/Admin/Prem/**
+/Admin/_Prem/**
\ No newline at end of file
diff --git a/dev/Settings/Admin/About.js b/dev/Settings/Admin/About.js
index 0c8fb7a3e..2f65e6280 100644
--- a/dev/Settings/Admin/About.js
+++ b/dev/Settings/Admin/About.js
@@ -9,7 +9,8 @@
 		Translator = require('Common/Translator'),
 
 		Settings = require('Storage/Settings'),
-		CoreStore = require('Stores/Admin/Core')
+		CoreStore = require('Stores/Admin/Core'),
+		AppStore = require('Stores/Admin/App')
 	;
 
 	/**
@@ -34,7 +35,10 @@
 		this.coreRemoteRelease = CoreStore.coreRemoteRelease;
 		this.coreVersionCompare = CoreStore.coreVersionCompare;
 
+		this.community = RL_COMMUNITY || AppStore.community();
+
 		this.coreRemoteVersionHtmlDesc = ko.computed(function () {
+			Translator.trigger();
 			return Translator.i18n('TAB_ABOUT/HTML_NEW_VERSION', {'VERSION': this.coreRemoteVersion()});
 		}, this);
 
@@ -77,7 +81,7 @@
 
 	AboutAdminSettings.prototype.onBuild = function ()
 	{
-		if (this.access())
+		if (this.access() && !this.community)
 		{
 			require('App/Admin').reloadCoreData();
 		}
@@ -85,7 +89,7 @@
 
 	AboutAdminSettings.prototype.updateCoreData = function ()
 	{
-		if (!this.coreUpdating())
+		if (!this.coreUpdating() && !this.community)
 		{
 			require('App/Admin').updateCoreData();
 		}
diff --git a/dev/Settings/Admin/Branding.js b/dev/Settings/Admin/Branding.js
index 748a68d79..0ce884e59 100644
--- a/dev/Settings/Admin/Branding.js
+++ b/dev/Settings/Admin/Branding.js
@@ -39,6 +39,15 @@
 		this.userLogo = ko.observable(Settings.settingsGet('UserLogo') || '');
 		this.userLogo.trigger = ko.observable(Enums.SaveSettingsStep.Idle);
 
+		this.userLogoMessage = ko.observable(Settings.settingsGet('UserLogoMessage') || '');
+		this.userLogoMessage.trigger = ko.observable(Enums.SaveSettingsStep.Idle);
+
+		this.userIframeMessage = ko.observable(Settings.settingsGet('UserIframeMessage') || '');
+		this.userIframeMessage.trigger = ko.observable(Enums.SaveSettingsStep.Idle);
+
+		this.userLogoTitle = ko.observable(Settings.settingsGet('UserLogoTitle') || '');
+		this.userLogoTitle.trigger = ko.observable(Enums.SaveSettingsStep.Idle);
+
 		this.loginDescription = ko.observable(Settings.settingsGet('LoginDescription'));
 		this.loginDescription.trigger = ko.observable(Enums.SaveSettingsStep.Idle);
 
@@ -64,6 +73,8 @@
 		});
 
 		this.loginPowered = ko.observable(!!Settings.settingsGet('LoginPowered'));
+
+		this.community = RL_COMMUNITY || AppStore.community();
 	}
 
 	BrandingAdminSettings.prototype.onBuild = function ()
@@ -73,100 +84,26 @@
 			Remote = require('Remote/Admin/Ajax')
 		;
 
-		if (this.capa())
-		{
-			_.delay(function () {
+		_.delay(function () {
 
-				var
-					f3 = Utils.settingsSaveHelperSimpleFunction(self.loginLogo.trigger, self),
-					f4 = Utils.settingsSaveHelperSimpleFunction(self.loginDescription.trigger, self),
-					f5 = Utils.settingsSaveHelperSimpleFunction(self.loginCss.trigger, self),
-					f6 = Utils.settingsSaveHelperSimpleFunction(self.userLogo.trigger, self),
-					f7 = Utils.settingsSaveHelperSimpleFunction(self.loginBackground.trigger, self),
-					f8 = Utils.settingsSaveHelperSimpleFunction(self.userCss.trigger, self),
-					f9 = Utils.settingsSaveHelperSimpleFunction(self.welcomePageUrl.trigger, self),
-					f10 = Utils.settingsSaveHelperSimpleFunction(self.welcomePageDisplay.trigger, self)
-				;
+			var
+				f1 = Utils.settingsSaveHelperSimpleFunction(self.title.trigger, self),
+				f2 = Utils.settingsSaveHelperSimpleFunction(self.loadingDesc.trigger, self)
+			;
 
-				self.loginLogo.subscribe(function (sValue) {
-					Remote.saveAdminConfig(f3, {
-						'LoginLogo': Utils.trim(sValue)
-					});
+			self.title.subscribe(function (sValue) {
+				Remote.saveAdminConfig(f1, {
+					'Title': Utils.trim(sValue)
 				});
+			});
 
-				self.loginBackground.subscribe(function (sValue) {
-					Remote.saveAdminConfig(f7, {
-						'LoginBackground': Utils.trim(sValue)
-					});
+			self.loadingDesc.subscribe(function (sValue) {
+				Remote.saveAdminConfig(f2, {
+					'LoadingDescription': Utils.trim(sValue)
 				});
+			});
 
-				self.userLogo.subscribe(function (sValue) {
-					Remote.saveAdminConfig(f6, {
-						'UserLogo': Utils.trim(sValue)
-					});
-				});
-
-				self.loginDescription.subscribe(function (sValue) {
-					Remote.saveAdminConfig(f4, {
-						'LoginDescription': Utils.trim(sValue)
-					});
-				});
-
-				self.loginCss.subscribe(function (sValue) {
-					Remote.saveAdminConfig(f5, {
-						'LoginCss': Utils.trim(sValue)
-					});
-				});
-
-				self.userCss.subscribe(function (sValue) {
-					Remote.saveAdminConfig(f8, {
-						'UserCss': Utils.trim(sValue)
-					});
-				});
-
-				self.welcomePageUrl.subscribe(function (sValue) {
-					Remote.saveAdminConfig(f9, {
-						'WelcomePageUrl': Utils.trim(sValue)
-					});
-				});
-
-				self.welcomePageDisplay.subscribe(function (sValue) {
-					Remote.saveAdminConfig(f10, {
-						'WelcomePageDisplay': Utils.trim(sValue)
-					});
-				});
-
-				self.loginPowered.subscribe(function (bValue) {
-					Remote.saveAdminConfig(null, {
-						'LoginPowered': bValue ? '1' : '0'
-					});
-				});
-
-			}, 50);
-		}
-		else
-		{
-			_.delay(function () {
-
-				var
-					f1 = Utils.settingsSaveHelperSimpleFunction(self.title.trigger, self),
-					f2 = Utils.settingsSaveHelperSimpleFunction(self.loadingDesc.trigger, self)
-				;
-
-				self.title.subscribe(function (sValue) {
-					Remote.saveAdminConfig(f1, {
-						'Title': Utils.trim(sValue)
-					});
-				});
-
-				self.loadingDesc.subscribe(function (sValue) {
-					Remote.saveAdminConfig(f2, {
-						'LoadingDescription': Utils.trim(sValue)
-					});
-				});
-
-			}, 50);
-		}
+		}, 50);
 	};
 
 	module.exports = BrandingAdminSettings;
diff --git a/dev/Settings/Admin/General.js b/dev/Settings/Admin/General.js
index b56e2959c..ca000b854 100644
--- a/dev/Settings/Admin/General.js
+++ b/dev/Settings/Admin/General.js
@@ -37,6 +37,7 @@
 		this.capaUserBackground = CapaAdminStore.userBackground;
 		this.capaGravatar = CapaAdminStore.gravatar;
 		this.capaAdditionalAccounts = CapaAdminStore.additionalAccounts;
+		this.capaIdentities = CapaAdminStore.identities;
 		this.capaAttachmentThumbnails = CapaAdminStore.attachmentThumbnails;
 		this.capaTemplates = CapaAdminStore.templates;
 
@@ -136,6 +137,12 @@
 				});
 			});
 
+			self.capaIdentities.subscribe(function (bValue) {
+				Remote.saveAdminConfig(null, {
+					'CapaIdentities': bValue ? '1' : '0'
+				});
+			});
+
 			self.capaTemplates.subscribe(function (bValue) {
 				Remote.saveAdminConfig(null, {
 					'CapaTemplates': bValue ? '1' : '0'
diff --git a/dev/Settings/Admin/Licensing.js b/dev/Settings/Admin/Licensing.js
deleted file mode 100644
index 15bd709f5..000000000
--- a/dev/Settings/Admin/Licensing.js
+++ /dev/null
@@ -1,84 +0,0 @@
-
-(function () {
-
-	'use strict';
-
-	var
-		ko = require('ko'),
-
-		Settings = require('Storage/Settings'),
-		LicenseStore = require('Stores/Admin/License')
-	;
-
-	/**
-	 * @constructor
-	 */
-	function LicensingAdminSettings()
-	{
-		this.licensing = LicenseStore.licensing;
-		this.licensingProcess = LicenseStore.licensingProcess;
-		this.licenseValid = LicenseStore.licenseValid;
-		this.licenseExpired = LicenseStore.licenseExpired;
-		this.licenseError = LicenseStore.licenseError;
-		this.licenseTrigger = LicenseStore.licenseTrigger;
-
-		this.adminDomain = ko.observable('');
-		this.subscriptionEnabled = ko.observable(!!Settings.settingsGet('SubscriptionEnabled'));
-
-		this.licenseTrigger.subscribe(function () {
-			if (this.subscriptionEnabled())
-			{
-				require('App/Admin').reloadLicensing(true);
-			}
-		}, this);
-	}
-
-	LicensingAdminSettings.prototype.onBuild = function ()
-	{
-		if (this.subscriptionEnabled())
-		{
-			require('App/Admin').reloadLicensing(false);
-		}
-	};
-
-	LicensingAdminSettings.prototype.onShow = function ()
-	{
-		this.adminDomain(Settings.settingsGet('AdminDomain'));
-	};
-
-	LicensingAdminSettings.prototype.showActivationForm = function ()
-	{
-		require('Knoin/Knoin').showScreenPopup(require('View/Popup/Activate'));
-	};
-
-	LicensingAdminSettings.prototype.showTrialForm = function ()
-	{
-		require('Knoin/Knoin').showScreenPopup(require('View/Popup/Activate'), [true]);
-	};
-
-	/**
-	 * @return {boolean}
-	 */
-	LicensingAdminSettings.prototype.licenseIsUnlim = function ()
-	{
-		return 1898625600 === this.licenseExpired() || 1898625700 === this.licenseExpired();
-	};
-
-	/**
-	 * @return {string}
-	 */
-	LicensingAdminSettings.prototype.licenseExpiredMomentValue = function ()
-	{
-		var
-			moment = require('moment'),
-			iTime = this.licenseExpired(),
-			oM = moment.unix(iTime)
-		;
-
-		return this.licenseIsUnlim() ? 'Never' :
-			(iTime && (oM.format('LL') + ' (' + oM.from(moment()) + ')'));
-	};
-
-	module.exports = LicensingAdminSettings;
-
-}());
\ No newline at end of file
diff --git a/dev/Settings/Admin/Plugins.js b/dev/Settings/Admin/Plugins.js
index f15c7637c..c955eff04 100644
--- a/dev/Settings/Admin/Plugins.js
+++ b/dev/Settings/Admin/Plugins.js
@@ -12,7 +12,10 @@
 		Translator = require('Common/Translator'),
 
 		Settings = require('Storage/Settings'),
+
+		AppStore = require('Stores/Admin/App'),
 		PluginStore = require('Stores/Admin/Plugin'),
+		
 		Remote = require('Remote/Admin/Ajax')
 	;
 
@@ -26,6 +29,8 @@
 		this.plugins = PluginStore.plugins;
 		this.pluginsError = PluginStore.plugins.error;
 
+		this.community = RL_COMMUNITY || AppStore.community();
+
 		this.visibility = ko.computed(function () {
 			return PluginStore.plugins.loading() ? 'visible' : 'hidden';
 		}, this);
diff --git a/dev/Settings/Admin/Social.js b/dev/Settings/Admin/Social.js
index ca2d2ad84..8a6890cc5 100644
--- a/dev/Settings/Admin/Social.js
+++ b/dev/Settings/Admin/Social.js
@@ -20,6 +20,7 @@
 
 		this.googleEnable = SocialStore.google.enabled;
 		this.googleEnableAuth = SocialStore.google.capa.auth;
+		this.googleEnableAuthFast = SocialStore.google.capa.authFast;
 		this.googleEnableDrive = SocialStore.google.capa.drive;
 		this.googleEnablePreview = SocialStore.google.capa.preview;
 
diff --git a/dev/Settings/User/Accounts.js b/dev/Settings/User/Accounts.js
index 3b79644cd..8beb9e9f6 100644
--- a/dev/Settings/User/Accounts.js
+++ b/dev/Settings/User/Accounts.js
@@ -24,7 +24,7 @@
 	function AccountsUserSettings()
 	{
 		this.allowAdditionalAccount = Settings.capa(Enums.Capa.AdditionalAccounts);
-		this.allowIdentities = true;
+		this.allowIdentities = Settings.capa(Enums.Capa.Identities);
 
 		this.accounts = AccountStore.accounts;
 		this.identities = IdentityStore.identities;
@@ -33,10 +33,12 @@
 		this.identityForDeletion = ko.observable(null).deleteAccessHelper();
 	}
 
-	AccountsUserSettings.prototype.scrollableOptions = function ()
+	AccountsUserSettings.prototype.scrollableOptions = function (sWrapper)
 	{
 		return {
-			handle: '.drag-handle'
+			handle: '.drag-handle',
+			containment: sWrapper || 'parent',
+			axis: 'y'
 		};
 	};
 
diff --git a/dev/Settings/User/ChangePassword.js b/dev/Settings/User/ChangePassword.js
index 8a53619c4..b6fb723e6 100644
--- a/dev/Settings/User/ChangePassword.js
+++ b/dev/Settings/User/ChangePassword.js
@@ -103,6 +103,8 @@
 
 			this.passwordUpdateSuccess(true);
 			this.currentPassword.error(false);
+
+			require('App/User').setClientSideToken(oData.Result);
 		}
 		else
 		{
diff --git a/dev/Settings/User/Filters.js b/dev/Settings/User/Filters.js
index f5f133299..9ed24f23a 100644
--- a/dev/Settings/User/Filters.js
+++ b/dev/Settings/User/Filters.js
@@ -110,10 +110,12 @@
 		}, this);
 	}
 
-	FiltersUserSettings.prototype.scrollableOptions = function ()
+	FiltersUserSettings.prototype.scrollableOptions = function (sWrapper)
 	{
 		return {
-			handle: '.drag-handle'
+			handle: '.drag-handle',
+			containment: sWrapper || 'parent',
+			axis: 'y'
 		};
 	};
 
diff --git a/dev/Settings/User/Folders.js b/dev/Settings/User/Folders.js
index c5812c9ed..9d826f69b 100644
--- a/dev/Settings/User/Folders.js
+++ b/dev/Settings/User/Folders.js
@@ -26,8 +26,11 @@
 	 */
 	function FoldersUserSettings()
 	{
+		this.displaySpecSetting = FolderStore.displaySpecSetting;
 		this.folderList = FolderStore.folderList;
 
+		this.folderListHelp = ko.observable('').extend({'throttle': 100});
+
 		this.loading = ko.computed(function () {
 
 			var
@@ -95,6 +98,25 @@
 		FolderStore.folderList.error('');
 	};
 
+	FoldersUserSettings.prototype.onBuild = function (oDom)
+	{
+		var self = this;
+		oDom
+			.on('mouseover', '.delete-folder-parent', function () {
+				self.folderListHelp(Translator.i18n('SETTINGS_FOLDERS/HELP_DELETE_FOLDER'));
+			})
+			.on('mouseover', '.subscribe-folder-parent', function () {
+				self.folderListHelp(Translator.i18n('SETTINGS_FOLDERS/HELP_SHOW_HIDE_FOLDER'));
+			})
+			.on('mouseover', '.check-folder-parent', function () {
+				self.folderListHelp(Translator.i18n('SETTINGS_FOLDERS/HELP_CHECK_FOR_NEW_MESSAGES'));
+			})
+			.on('mouseout', '.subscribe-folder-parent, .check-folder-parent, .delete-folder-parent', function () {
+				self.folderListHelp('');
+			})
+		;
+	};
+
 	FoldersUserSettings.prototype.createFolder = function ()
 	{
 		require('Knoin/Knoin').showScreenPopup(require('View/Popup/FolderCreate'));
@@ -160,6 +182,20 @@
 		oFolder.subScribed(false);
 	};
 
+	FoldersUserSettings.prototype.checkableTrueFolder = function (oFolder)
+	{
+		Remote.folderSetCheckable(Utils.emptyFunction, oFolder.fullNameRaw, true);
+
+		oFolder.checkable(true);
+	};
+
+	FoldersUserSettings.prototype.checkableFalseFolder = function (oFolder)
+	{
+		Remote.folderSetCheckable(Utils.emptyFunction, oFolder.fullNameRaw, false);
+
+		oFolder.checkable(false);
+	};
+
 	module.exports = FoldersUserSettings;
 
 }());
\ No newline at end of file
diff --git a/dev/Settings/User/General.js b/dev/Settings/User/General.js
index 5d103bdad..7d4dc9d46 100644
--- a/dev/Settings/User/General.js
+++ b/dev/Settings/User/General.js
@@ -16,6 +16,7 @@
 		AppStore = require('Stores/User/App'),
 		LanguageStore = require('Stores/Language'),
 		SettingsStore = require('Stores/User/Settings'),
+		IdentityStore = require('Stores/User/Identity'),
 		NotificationStore = require('Stores/User/Notification'),
 		MessageStore = require('Stores/User/Message'),
 
@@ -62,6 +63,20 @@
 
 		this.isAnimationSupported = Globals.bAnimationSupported;
 
+		this.identities = IdentityStore.identities;
+
+		this.identityMain = ko.computed(function () {
+			var aList = this.identities();
+			return Utils.isArray(aList) ? _.find(aList, function (oItem) {
+				return oItem && '' === oItem.id() ? true : false;
+			}) : null;
+		}, this);
+
+		this.identityMainDesc = ko.computed(function () {
+			var oIdentity = this.identityMain();
+			return oIdentity ? oIdentity.formattedName() : '---';
+		}, this);
+
 		this.editorDefaultTypes = ko.computed(function () {
 			Translator.trigger();
 			return [
@@ -82,6 +97,15 @@
 		}, this);
 	}
 
+	GeneralUserSettings.prototype.editMainIdentity = function ()
+	{
+		var oIdentity = this.identityMain();
+		if (oIdentity)
+		{
+			require('Knoin/Knoin').showScreenPopup(require('View/Popup/Identity'), [oIdentity]);
+		}
+	};
+
 	GeneralUserSettings.prototype.testSoundNotification = function ()
 	{
 		NotificationStore.playSoundNotification(true);
diff --git a/dev/Settings/User/OpenPgp.js b/dev/Settings/User/OpenPgp.js
index e5c6ef6b9..c302d76ef 100644
--- a/dev/Settings/User/OpenPgp.js
+++ b/dev/Settings/User/OpenPgp.js
@@ -6,6 +6,7 @@
 	var
 		_ = require('_'),
 		ko = require('ko'),
+		window = require('window'),
 
 		Utils = require('Common/Utils'),
 
@@ -24,6 +25,8 @@
 		this.openpgpkeysPrivate = PgpStore.openpgpkeysPrivate;
 
 		this.openPgpKeyForDeletion = ko.observable(null).deleteAccessHelper();
+
+		this.isHttps = window.document && window.document.location ? 'https:' === window.document.location.protocol : false;
 	}
 
 	OpenPgpUserSettings.prototype.addOpenPgpKey = function ()
diff --git a/dev/Settings/User/Social.js b/dev/Settings/User/Social.js
index b5521a546..82bbe5d2f 100644
--- a/dev/Settings/User/Social.js
+++ b/dev/Settings/User/Social.js
@@ -15,6 +15,7 @@
 
 		this.googleEnable = SocialStore.google.enabled;
 		this.googleEnableAuth = SocialStore.google.capa.auth;
+		this.googleEnableAuthFast = SocialStore.google.capa.authFast;
 		this.googleEnableDrive = SocialStore.google.capa.drive;
 		this.googleEnablePreview = SocialStore.google.capa.preview;
 
diff --git a/dev/Settings/User/Templates.js b/dev/Settings/User/Templates.js
index db6991f7c..42f8baabb 100644
--- a/dev/Settings/User/Templates.js
+++ b/dev/Settings/User/Templates.js
@@ -31,10 +31,12 @@
 		this.templateForDeletion = ko.observable(null).deleteAccessHelper();
 	}
 
-	TemplatesUserSettings.prototype.scrollableOptions = function ()
+	TemplatesUserSettings.prototype.scrollableOptions = function (sWrapper)
 	{
 		return {
-			handle: '.drag-handle'
+			handle: '.drag-handle',
+			containment: sWrapper || 'parent',
+			axis: 'y'
 		};
 	};
 
diff --git a/dev/Storage/Settings.js b/dev/Storage/Settings.js
index ef12c2a8f..3fecebfc2 100644
--- a/dev/Storage/Settings.js
+++ b/dev/Storage/Settings.js
@@ -16,7 +16,6 @@
 	{
 		this.oSettings = window['rainloopAppData'] || {};
 		this.oSettings = Utils.isNormal(this.oSettings) ? this.oSettings : {};
-//		window.console.log(this.oSettings);
 	}
 
 	SettingsStorage.prototype.oSettings = null;
diff --git a/dev/Stores/Admin/Capa.js b/dev/Stores/Admin/Capa.js
index a2dfcf963..e7223103b 100644
--- a/dev/Stores/Admin/Capa.js
+++ b/dev/Stores/Admin/Capa.js
@@ -17,6 +17,7 @@
 	function CapaAdminStore()
 	{
 		this.additionalAccounts = ko.observable(false);
+		this.identities = ko.observable(false);
 		this.gravatar = ko.observable(false);
 		this.attachmentThumbnails = ko.observable(false);
 		this.sieve = ko.observable(false);
@@ -32,6 +33,7 @@
 	CapaAdminStore.prototype.populate = function()
 	{
 		this.additionalAccounts(Settings.capa(Enums.Capa.AdditionalAccounts));
+		this.identities(Settings.capa(Enums.Capa.Identities));
 		this.gravatar(Settings.capa(Enums.Capa.Gravatar));
 		this.attachmentThumbnails(Settings.capa(Enums.Capa.AttachmentThumbnails));
 		this.sieve(Settings.capa(Enums.Capa.Sieve));
diff --git a/dev/Stores/App.js b/dev/Stores/App.js
index 45b560689..28e70b1f8 100644
--- a/dev/Stores/App.js
+++ b/dev/Stores/App.js
@@ -29,6 +29,7 @@
 		this.interfaceAnimation.valueHasMutated();
 
 		this.prem = ko.observable(false);
+		this.community = ko.observable(true);
 	}
 
 	AppStore.prototype.populate = function()
@@ -39,6 +40,7 @@
 		this.interfaceAnimation(!!Settings.settingsGet('InterfaceAnimation'));
 
 		this.prem(!!Settings.settingsGet('PremType'));
+		this.community(!!Settings.settingsGet('Community'));
 	};
 
 	module.exports = AppStore;
diff --git a/dev/Stores/Language.js b/dev/Stores/Language.js
index 2659f42a0..4b3b1aa9b 100644
--- a/dev/Stores/Language.js
+++ b/dev/Stores/Language.js
@@ -22,14 +22,11 @@
 		this.language = ko.observable('')
 			.extend({'limitedList': this.languages});
 
-		this.userLanguage = ko.observable('')
-			.extend({'limitedList': this.languages});
-
 		this.languageAdmin = ko.observable('')
 			.extend({'limitedList': this.languagesAdmin});
 
-		this.userLanguageAdmin = ko.observable('')
-			.extend({'limitedList': this.languagesAdmin});
+		this.userLanguage = ko.observable('');
+		this.userLanguageAdmin = ko.observable('');
 	}
 
 	LanguageStore.prototype.populate = function ()
diff --git a/dev/Stores/Social.js b/dev/Stores/Social.js
index 0e870ce5b..ffeb0f6f9 100644
--- a/dev/Stores/Social.js
+++ b/dev/Stores/Social.js
@@ -33,6 +33,7 @@
 
 		this.google.capa = {};
 		this.google.capa.auth = ko.observable(false);
+		this.google.capa.authFast = ko.observable(false);
 		this.google.capa.drive = ko.observable(false);
 		this.google.capa.preview = ko.observable(false);
 
@@ -88,6 +89,7 @@
 		this.google.apiKey(Settings.settingsGet('GoogleApiKey'));
 
 		this.google.capa.auth(!!Settings.settingsGet('AllowGoogleSocialAuth'));
+		this.google.capa.authFast(!!Settings.settingsGet('AllowGoogleSocialAuthFast'));
 		this.google.capa.drive(!!Settings.settingsGet('AllowGoogleSocialDrive'));
 		this.google.capa.preview(!!Settings.settingsGet('AllowGoogleSocialPreview'));
 
diff --git a/dev/Stores/User/App.js b/dev/Stores/User/App.js
index e42fb074d..8e8a73695 100644
--- a/dev/Stores/User/App.js
+++ b/dev/Stores/User/App.js
@@ -8,6 +8,7 @@
 
 		Enums = require('Common/Enums'),
 		Globals = require('Common/Globals'),
+		Utils = require('Common/Utils'),
 
 		Settings = require('Storage/Settings'),
 
@@ -52,6 +53,8 @@
 
 		this.contactsIsAllowed = ko.observable(false);
 
+		this.attachmentsActions = ko.observableArray([]);
+
 		this.devEmail = '';
 		this.devPassword = '';
 	}
@@ -67,6 +70,9 @@
 
 		this.contactsIsAllowed(!!Settings.settingsGet('ContactsIsAllowed'));
 
+		var mAttachmentsActions = Settings.settingsGet('AttachmentsActions');
+		this.attachmentsActions(Utils.isNonEmptyArray(mAttachmentsActions) ? mAttachmentsActions : []);
+
 		this.devEmail = Settings.settingsGet('DevEmail');
 		this.devPassword = Settings.settingsGet('DevPassword');
 	};
diff --git a/dev/Stores/User/Folder.js b/dev/Stores/User/Folder.js
index 8b04773fe..57081f7b1 100644
--- a/dev/Stores/User/Folder.js
+++ b/dev/Stores/User/Folder.js
@@ -19,6 +19,8 @@
 	 */
 	function FolderUserStore()
 	{
+		this.displaySpecSetting = ko.observable(true);
+
 		this.sentFolder = ko.observable('');
 		this.draftFolder = ko.observable('');
 		this.spamFolder = ko.observable('');
@@ -181,13 +183,10 @@
 	};
 
 	/**
-	 * @param {boolean=} bBoot = false
 	 * @return {Array}
 	 */
-	FolderUserStore.prototype.getNextFolderNames = function (bBoot)
+	FolderUserStore.prototype.getNextFolderNames = function ()
 	{
-		bBoot = Utils.isUnd(bBoot) ? false : !!bBoot;
-
 		var
 			aResult = [],
 			iLimit = 5,
@@ -200,7 +199,8 @@
 					if (oFolder && sInboxFolderName !== oFolder.fullNameRaw &&
 						oFolder.selectable && oFolder.existen &&
 						iTimeout > oFolder.interval &&
-						(!bBoot || oFolder.subScribed()))
+						(oFolder.isSystemFolder() || (oFolder.subScribed() && oFolder.checkable()))
+					)
 					{
 						aTimeouts.push([oFolder.interval, oFolder.fullNameRaw]);
 					}
@@ -236,7 +236,9 @@
 			return iLimit <= aResult.length;
 		});
 
-		return _.uniq(aResult);
+		aResult = _.uniq(aResult);
+
+		return aResult;
 	};
 
 	module.exports = new FolderUserStore();
diff --git a/dev/Stores/User/Message.js b/dev/Stores/User/Message.js
index 55c503324..53b019820 100644
--- a/dev/Stores/User/Message.js
+++ b/dev/Stores/User/Message.js
@@ -22,6 +22,7 @@
 
 		AppStore = require('Stores/User/App'),
 		FolderStore = require('Stores/User/Folder'),
+		PgpStore = require('Stores/User/Pgp'),
 		SettingsStore = require('Stores/User/Settings'),
 
 		Remote = require('Remote/User/Ajax'),
@@ -41,11 +42,14 @@
 
 		this.messageListCount = ko.observable(0);
 		this.messageListSearch = ko.observable('');
+		this.messageListThreadUid = ko.observable('');
 		this.messageListPage = ko.observable(1);
+		this.messageListPageBeforeThread = ko.observable(1);
 		this.messageListError = ko.observable('');
 
 		this.messageListEndFolder = ko.observable('');
 		this.messageListEndSearch = ko.observable('');
+		this.messageListEndThreadUid = ko.observable('');
 		this.messageListEndPage = ko.observable(1);
 
 		this.messageListLoading = ko.observable(false);
@@ -63,17 +67,12 @@
 
 		this.message.viewTrigger = ko.observable(false);
 
-		this.messageThreadList = ko.observableArray([]);
-
-		this.messageLastThreadUidsData = ko.observable(null);
-
 		this.messageError = ko.observable('');
 
 		this.messageCurrentLoading = ko.observable(false);
-		this.messageThreadLoading = ko.observable(false);
 
 		this.messageLoading = ko.computed(function () {
-			return !!(this.messageCurrentLoading() || this.messageThreadLoading());
+			return this.messageCurrentLoading();
 		}, this);
 
 		this.messageLoadingThrottle = ko.observable(false).extend({'throttle': 50});
@@ -93,8 +92,12 @@
 
 	MessageUserStore.prototype.computers = function ()
 	{
+		var self = this;
+
 		this.messageListEndHash = ko.computed(function () {
-			return this.messageListEndFolder() + '|' + this.messageListEndSearch() + '|' + this.messageListEndPage();
+			return this.messageListEndFolder() + '|' + this.messageListEndSearch() +
+				'|' + this.messageListEndThreadUid() +
+				'|' + this.messageListEndPage();
 		}, this);
 
 		this.messageListPageCount = ko.computed(function () {
@@ -107,7 +110,8 @@
 			'read': this.messageListSearch,
 			'write': function (sValue) {
 				kn.setHash(Links.mailBox(
-					FolderStore.currentFolderFullNameHash(), 1, Utils.trim(sValue.toString())
+					FolderStore.currentFolderFullNameHash(), 1,
+					Utils.trim(sValue.toString()), self.messageListThreadUid()
 				));
 			},
 			'owner': this
@@ -222,16 +226,16 @@
 	{
 		var
 			iCount = 0,
-			oMessagesBodiesDom = null,
+			oMessagesDom = null,
 			iEnd = Globals.iMessageBodyCacheCount - Consts.Values.MessageBodyCacheLimit
 		;
 
 		if (0 < iEnd)
 		{
-			oMessagesBodiesDom = this.messagesBodiesDom();
-			if (oMessagesBodiesDom)
+			oMessagesDom = this.messagesBodiesDom();
+			if (oMessagesDom)
 			{
-				oMessagesBodiesDom.find('.rl-cache-class').each(function () {
+				oMessagesDom.find('.rl-cache-class').each(function () {
 					var oItem = $(this);
 					if (iEnd > oItem.data('rl-cache-count'))
 					{
@@ -243,7 +247,7 @@
 				if (0 < iCount)
 				{
 					_.delay(function () {
-						oMessagesBodiesDom.find('.rl-cache-purge').remove();
+						oMessagesDom.find('.rl-cache-purge').remove();
 					}, 300);
 				}
 			}
@@ -275,7 +279,8 @@
 						require('Stores/User/Account').email(),
 						Translator.i18n('MESSAGE_LIST/NEW_MESSAGE_NOTIFICATION', {
 							'COUNT': iLen
-						})
+						}),
+						{'Folder': '', 'Uid': ''}
 					);
 				}
 				else
@@ -286,7 +291,11 @@
 							Links.notificationMailIcon(),
 							MessageHelper.emailArrayToString(
 								MessageHelper.emailArrayFromJson(aNewMessages[iIndex].From), false),
-							aNewMessages[iIndex].Subject
+							aNewMessages[iIndex].Subject,
+							{
+								'Folder': aNewMessages[iIndex].Folder,
+								'Uid': aNewMessages[iIndex].Uid
+							}
 						);
 					}
 				}
@@ -298,10 +307,10 @@
 
 	MessageUserStore.prototype.hideMessageBodies = function ()
 	{
-		var oMessagesBodiesDom = this.messagesBodiesDom();
-		if (oMessagesBodiesDom)
+		var oMessagesDom = this.messagesBodiesDom();
+		if (oMessagesDom)
 		{
-			oMessagesBodiesDom.find('.b-text-part').hide();
+			oMessagesDom.find('.b-text-part').hide();
 		}
 	};
 
@@ -324,6 +333,9 @@
 		var
 			self = this,
 			iUnseenCount = 0,
+			oMessage = null,
+			sTrashFolder = FolderStore.trashFolder(),
+			sSpamFolder = FolderStore.spamFolder(),
 			aMessageList = this.messageList(),
 			oFromFolder = Cache.getFolderFromCacheList(sFromFolderFullNameRaw),
 			oToFolder = '' === sToFolderFullNameRaw ? null : Cache.getFolderFromCacheList(sToFolderFullNameRaw || ''),
@@ -355,6 +367,11 @@
 
 		if (oToFolder)
 		{
+			if (sTrashFolder === oToFolder.fullNameRaw || sSpamFolder === oToFolder.fullNameRaw)
+			{
+				iUnseenCount = 0;
+			}
+
 			oToFolder.messageCountAll(oToFolder.messageCountAll() + aUidForRemove.length);
 			if (0 < iUnseenCount)
 			{
@@ -403,6 +420,56 @@
 		{
 			Cache.setFolderHash(sToFolderFullNameRaw, '');
 		}
+
+		if ('' !== this.messageListThreadUid())
+		{
+			aMessageList = this.messageList();
+
+			if (aMessageList && 0 < aMessageList.length && !!_.find(aMessageList, function (oMessage) {
+				return !!(oMessage && oMessage.deleted() && oMessage.uid === self.messageListThreadUid());
+			}))
+			{
+				oMessage = _.find(aMessageList, function (oMessage) {
+					return oMessage && !oMessage.deleted();
+				});
+
+				if (oMessage && this.messageListThreadUid() !== Utils.pString(oMessage.uid))
+				{
+					this.messageListThreadUid(Utils.pString(oMessage.uid));
+
+					kn.setHash(Links.mailBox(
+						FolderStore.currentFolderFullNameHash(),
+						this.messageListPage(),
+						this.messageListSearch(),
+						this.messageListThreadUid()
+					), true, true);
+				}
+				else if (!oMessage)
+				{
+					if (1 < this.messageListPage())
+					{
+						this.messageListPage(this.messageListPage() - 1);
+
+						kn.setHash(Links.mailBox(
+							FolderStore.currentFolderFullNameHash(),
+							this.messageListPage(),
+							this.messageListSearch(),
+							this.messageListThreadUid()
+						), true, true);
+					}
+					else
+					{
+						this.messageListThreadUid('');
+
+						kn.setHash(Links.mailBox(
+							FolderStore.currentFolderFullNameHash(),
+							this.messageListPageBeforeThread(),
+							this.messageListSearch()
+						), true, true);
+					}
+				}
+			}
+		}
 	};
 
 	MessageUserStore.prototype.addBlockquoteSwitcherCallback = function ()
@@ -441,20 +508,35 @@
 		}
 	};
 
+	/**
+	 * @param {Object} oMessageTextBody
+	 */
+	MessageUserStore.prototype.initOpenPgpControls = function (oMessageTextBody)
+	{
+		if (oMessageTextBody && oMessageTextBody.find)
+		{
+			oMessageTextBody.find('.b-plain-openpgp:not(.inited)').each(function () {
+				PgpStore.initMessageBodyControls($(this));
+			});
+		}
+	};
+
 	MessageUserStore.prototype.setMessage = function (oData, bCached)
 	{
 		var
 			bNew = false,
 			bIsHtml = false,
+			sTag = 'div',
 			bHasExternals = false,
 			bHasInternals = false,
 			oBody = null,
 			oTextBody = null,
 			sId = '',
+			sPlain = '',
 			sResultHtml = '',
 			bPgpSigned = false,
 			bPgpEncrypted = false,
-			oMessagesBodiesDom = this.messagesBodiesDom(),
+			oMessagesDom = this.messagesBodiesDom(),
 			oSelectedMessage = this.selectorMessageSelected(),
 			oMessage = this.message(),
 			aThreads = []
@@ -492,19 +574,17 @@
 					oMessage.initFlagsByJson(oData.Result);
 				}
 
-				oMessagesBodiesDom = oMessagesBodiesDom && oMessagesBodiesDom[0] ? oMessagesBodiesDom : null;
-				if (oMessagesBodiesDom)
+				oMessagesDom = oMessagesDom && oMessagesDom[0] ? oMessagesDom : null;
+				if (oMessagesDom)
 				{
 					sId = 'rl-mgs-' + oMessage.hash.replace(/[^a-zA-Z0-9]/g, '');
-					oTextBody = oMessagesBodiesDom.find('#' + sId);
+					oTextBody = oMessagesDom.find('#' + sId);
+
 					if (!oTextBody || !oTextBody[0])
 					{
 						bHasExternals = !!oData.Result.HasExternals;
 						bHasInternals = !!oData.Result.HasInternals;
 
-						oBody = $('
').hide().addClass('rl-cache-class'); - oBody.data('rl-cache-count', ++Globals.iMessageBodyCacheCount); - if (Utils.isNormal(oData.Result.Html) && '' !== oData.Result.Html) { bIsHtml = true; @@ -517,13 +597,13 @@ if ((oMessage.isPgpSigned() || oMessage.isPgpEncrypted()) && require('Stores/User/Pgp').capaOpenPGP()) { - oMessage.plainRaw = Utils.pString(oData.Result.Plain); + sPlain = Utils.pString(oData.Result.Plain); - bPgpEncrypted = /---BEGIN PGP MESSAGE---/.test(oMessage.plainRaw); + bPgpEncrypted = /---BEGIN PGP MESSAGE---/.test(sPlain); if (!bPgpEncrypted) { - bPgpSigned = /-----BEGIN PGP SIGNED MESSAGE-----/.test(oMessage.plainRaw) && - /-----BEGIN PGP SIGNATURE-----/.test(oMessage.plainRaw); + bPgpSigned = /-----BEGIN PGP SIGNED MESSAGE-----/.test(sPlain) && + /-----BEGIN PGP SIGNATURE-----/.test(sPlain); } Globals.$div.empty(); @@ -531,7 +611,7 @@ { sResultHtml = Globals.$div.append( - $('
').text(oMessage.plainRaw)
+											$('
').text(sPlain)
 										).html()
 									;
 								}
@@ -539,22 +619,36 @@
 								{
 									sResultHtml =
 										Globals.$div.append(
-											$('
').text(oMessage.plainRaw)
+											$('
').text(sPlain)
 										).html()
 									;
 								}
+								else
+								{
+									sResultHtml = '
' + sResultHtml + '
'; + } + + sPlain = ''; Globals.$div.empty(); oMessage.isPgpSigned(bPgpSigned); oMessage.isPgpEncrypted(bPgpEncrypted); } + else + { + sResultHtml = '
' + sResultHtml + '
'; + } } else { bIsHtml = false; + sResultHtml = '
' + sResultHtml + '
'; } + oBody = $('
').hide().addClass('rl-cache-class'); + oBody.data('rl-cache-count', ++Globals.iMessageBodyCacheCount); + oBody .html(Utils.findEmailAndLinks(sResultHtml)) .addClass('b-text-part ' + (bIsHtml ? 'html' : 'plain')) @@ -562,16 +656,14 @@ oMessage.isHtml(!!bIsHtml); oMessage.hasImages(!!bHasExternals); - oMessage.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None); - oMessage.pgpSignedVerifyUser(''); oMessage.body = oBody; if (oMessage.body) { - oMessagesBodiesDom.append(oMessage.body); + oMessagesDom.append(oMessage.body); } - oMessage.storeDataToDom(); + oMessage.storeDataInDom(); if (bHasInternals) { @@ -591,7 +683,7 @@ if (oMessage.body) { oMessage.body.data('rl-cache-count', ++Globals.iMessageBodyCacheCount); - oMessage.fetchDataToDom(); + oMessage.fetchDataFromDom(); } } @@ -601,6 +693,8 @@ if (oBody) { + this.initOpenPgpControls(oBody); + this.initBlockquoteSwitcher(oBody); } @@ -665,11 +759,19 @@ } }; - MessageUserStore.prototype.selectThreadMessage = function (sFolder, sUid) + MessageUserStore.prototype.selectMessageByFolderAndUid = function (sFolder, sUid) { - if (Remote.message(this.onMessageResponse, sFolder, sUid)) + if (sFolder && sUid) { - this.messageThreadLoading(true); + this.message(this.staticMessage.populateByMessageListItem(null)); + this.message().folderFullNameRaw = sFolder; + this.message().uid = sUid; + + this.populateMessageBody(this.message()); + } + else + { + this.message(null); } }; @@ -694,7 +796,6 @@ this.hideMessageBodies(); this.messageCurrentLoading(false); - this.messageThreadLoading(false); if (Enums.StorageResultType.Success === sResult && oData && oData.Result) { @@ -731,7 +832,6 @@ oData.Result['@Collection'] && Utils.isArray(oData.Result['@Collection'])) { var - self = this, iIndex = 0, iLen = 0, iCount = 0, @@ -813,9 +913,11 @@ this.messageListCount(iCount); this.messageListSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : ''); this.messageListPage(window.Math.ceil((iOffset / SettingsStore.messagesPerPage()) + 1)); + this.messageListThreadUid(Utils.isNormal(oData.Result.ThreadUid) ? Utils.pString(oData.Result.ThreadUid) : ''); this.messageListEndFolder(Utils.isNormal(oData.Result.Folder) ? oData.Result.Folder : ''); - this.messageListEndSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : ''); + this.messageListEndSearch(this.messageListSearch()); + this.messageListEndThreadUid(this.messageListThreadUid()); this.messageListEndPage(this.messageListPage()); this.messageListDisableAutoSelect(true); @@ -825,26 +927,6 @@ Cache.clearNewMessageCache(); - if (AppStore.threadsAllowed() && SettingsStore.useThreads()) - { - oMessage = this.message(); - if (oMessage) - { - Remote.messageThreadsFromCache(function (sResult, oData) { - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result && oData.Result.ThreadUids) - { - self.messageLastThreadUidsData({ - 'Folder': oData.Result.Folder, - 'Uid': oData.Result.Uid, - 'Uids': oData.Result.ThreadUids - }); - } - - }, oMessage.folderFullNameRaw, oMessage.uid); - } - } - if (oFolder && (bCached || bUnreadCountChange || SettingsStore.useThreads())) { require('App/User').folderInformation(oFolder.fullNameRaw, aList); diff --git a/dev/Stores/User/Notification.js b/dev/Stores/User/Notification.js index e17e10821..fb8412e92 100644 --- a/dev/Stores/User/Notification.js +++ b/dev/Stores/User/Notification.js @@ -8,6 +8,7 @@ ko = require('ko'), Enums = require('Common/Enums'), + Events = require('Common/Events'), Audio = require('Common/Audio'), Settings = require('Storage/Settings') @@ -161,7 +162,7 @@ } }; - NotificationUserStore.prototype.displayDesktopNotification = function (sImageSrc, sTitle, sText) + NotificationUserStore.prototype.displayDesktopNotification = function (sImageSrc, sTitle, sText, oMessageData) { if (this.enableDesktopNotification()) { @@ -180,6 +181,19 @@ oNotification.show(); } + if (oMessageData) + { + oNotification.onclick = function () { + + window.focus(); + + if (oMessageData.Folder && oMessageData.Uid) + { + Events.pub('mailbox.message.show', [oMessageData.Folder, oMessageData.Uid]); + } + }; + } + window.setTimeout((function (oLocalNotifications) { return function () { if (oLocalNotifications.cancel) diff --git a/dev/Stores/User/Pgp.js b/dev/Stores/User/Pgp.js index a6e62e6e0..c6ae88594 100644 --- a/dev/Stores/User/Pgp.js +++ b/dev/Stores/User/Pgp.js @@ -5,6 +5,10 @@ var _ = require('_'), ko = require('ko'), + $ = require('$'), + kn = require('Knoin/Knoin'), + + Translator = require('Common/Translator'), Utils = require('Common/Utils') ; @@ -41,32 +45,63 @@ PgpUserStore.prototype.findPublicKeyByHex = function (sHash) { return _.find(this.openpgpkeysPublic(), function (oItem) { - return oItem && sHash === oItem.id; + return sHash && oItem && sHash === oItem.id; + }); + }; + + PgpUserStore.prototype.findPrivateKeyByHex = function (sHash) + { + return _.find(this.openpgpkeysPrivate(), function (oItem) { + return sHash && oItem && sHash === oItem.id; }); }; PgpUserStore.prototype.findPublicKeysByEmail = function (sEmail) + { + return _.compact(_.flatten(_.map(this.openpgpkeysPublic(), function (oItem) { + var oKey = oItem && sEmail === oItem.email ? oItem : null; + return oKey ? oKey.getNativeKeys() : [null]; + }), true)); + }; + + PgpUserStore.prototype.findPublicKeysBySigningKeyIds = function (aSigningKeyIds) { var self = this; - return _.compact(_.map(this.openpgpkeysPublic(), function (oItem) { + return _.compact(_.flatten(_.map(aSigningKeyIds, function (oId) { + var oKey = oId && oId.toHex ? self.findPublicKeyByHex(oId.toHex()) : null; + return oKey ? oKey.getNativeKeys() : [null]; + }), true)); + }; - var oKey = null; - if (oItem && sEmail === oItem.email) - { - try - { - oKey = self.openpgp.key.readArmored(oItem.armor); - if (oKey && !oKey.err && oKey.keys && oKey.keys[0]) - { - return oKey.keys[0]; - } - } - catch (e) {} - } + PgpUserStore.prototype.findPrivateKeysByEncryptionKeyIds = function (aEncryptionKeyIds, bReturnWrapKeys) + { + var self = this; + return _.compact(_.flatten(_.map(aEncryptionKeyIds, function (oId) { + var oKey = oId && oId.toHex ? self.findPrivateKeyByHex(oId.toHex()) : null; + return oKey ? (bReturnWrapKeys ? [oKey] : oKey.getNativeKeys()) : [null]; + }), true)); + }; - return null; + /** + * @param {string} sEmail + * @return {?} + */ + PgpUserStore.prototype.findPublicKeyByEmailNotNative = function (sEmail) + { + return _.find(this.openpgpkeysPublic(), function (oItem) { + return oItem && sEmail === oItem.email; + }) || null; + }; - })); + /** + * @param {string} sEmail + * @return {?} + */ + PgpUserStore.prototype.findPrivateKeyByEmailNotNative = function (sEmail) + { + return _.find(this.openpgpkeysPrivate(), function (oItem) { + return oItem && sEmail === oItem.email; + }) || null; }; /** @@ -77,6 +112,7 @@ PgpUserStore.prototype.findPrivateKeyByEmail = function (sEmail, sPassword) { var + oPrivateKeys = [], oPrivateKey = null, oKey = _.find(this.openpgpkeysPrivate(), function (oItem) { return oItem && sEmail === oItem.email; @@ -85,18 +121,15 @@ if (oKey) { + oPrivateKeys = oKey.getNativeKeys(); + oPrivateKey = oPrivateKeys[0] || null; + try { - oPrivateKey = this.openpgp.key.readArmored(oKey.armor); - if (oPrivateKey && !oPrivateKey.err && oPrivateKey.keys && oPrivateKey.keys[0]) + if (oPrivateKey) { - oPrivateKey = oPrivateKey.keys[0]; oPrivateKey.decrypt(Utils.pString(sPassword)); } - else - { - oPrivateKey = null; - } } catch (e) { @@ -116,6 +149,259 @@ return this.findPrivateKeyByEmail(require('Stores/User/Account').email(), sPassword); }; + PgpUserStore.prototype.decryptMessage = function (oMessage, fCallback) + { + var self = this, aPrivateKeys = [], aEncryptionKeyIds = []; + if (oMessage && oMessage.getSigningKeyIds) + { + aEncryptionKeyIds = oMessage.getEncryptionKeyIds(); + if (aEncryptionKeyIds) + { + aPrivateKeys = this.findPrivateKeysByEncryptionKeyIds(aEncryptionKeyIds, true); + if (aPrivateKeys && 0 < aPrivateKeys.length) + { + kn.showScreenPopup(require('View/Popup/MessageOpenPgp'), [function (oDecriptedKey) { + + if (oDecriptedKey) + { + var oPrivateKey = null, oDecryptedMessage = null; + try + { + oDecryptedMessage = oMessage.decrypt(oDecriptedKey); + } + catch (e) + { + oDecryptedMessage = null; + } + + if (oDecryptedMessage) + { + oPrivateKey = self.findPrivateKeyByHex(oDecriptedKey.primaryKey.keyid.toHex()); + if (oPrivateKey) + { + self.verifyMessage(oDecryptedMessage, function (oValidKey, aSigningKeyIds) { + fCallback(oPrivateKey, oDecryptedMessage, oValidKey || null, aSigningKeyIds || null); + }); + } + else + { + fCallback(oPrivateKey, oDecryptedMessage); + } + } + else + { + fCallback(oPrivateKey, oDecryptedMessage); + } + } + else + { + fCallback(null, null); + } + + }, aPrivateKeys]); + + return false; + } + } + } + + fCallback(null, null); + + return false; + }; + + PgpUserStore.prototype.verifyMessage = function (oMessage, fCallback) + { + var oValid = null, aResult = [], aPublicKeys = [], aSigningKeyIds = []; + if (oMessage && oMessage.getSigningKeyIds) + { + aSigningKeyIds = oMessage.getSigningKeyIds(); + if (aSigningKeyIds && 0 < aSigningKeyIds.length) + { + aPublicKeys = this.findPublicKeysBySigningKeyIds(aSigningKeyIds); + if (aPublicKeys && 0 < aPublicKeys.length) + { + try + { + aResult = oMessage.verify(aPublicKeys); + oValid = _.find(_.isArray(aResult) ? aResult : [], function (oItem) { + return oItem && oItem.valid && oItem.keyid; + }); + + if (oValid && oValid.keyid && oValid.keyid && oValid.keyid.toHex) + { + fCallback(this.findPublicKeyByHex(oValid.keyid.toHex())); + return true; + } + } + catch (e) {} + } + + fCallback(null, aSigningKeyIds); + return false; + } + } + + fCallback(null); + return false; + }; + + /** + * @param {*} mDom + */ + PgpUserStore.prototype.controlsHelper = function (mDom, oVerControl, bSuccess, sTitle, sText) + { + if (bSuccess) + { + mDom.removeClass('error').addClass('success').attr('title', sTitle); + oVerControl.removeClass('error').addClass('success').attr('title', sTitle); + } + else + { + mDom.removeClass('success').addClass('error').attr('title', sTitle); + oVerControl.removeClass('success').addClass('error').attr('title', sTitle); + } + + if (undefined !== sText) + { + mDom.text(Utils.trim(sText.replace(/(\u200C|\u0002)/g, ''))); + } + }; + + /** + * @param {*} mDom + */ + PgpUserStore.prototype.initMessageBodyControls = function (mDom) + { + if (mDom && !mDom.hasClass('inited')) + { + mDom.addClass('inited'); + + var + self = this, + bEncrypted = mDom.hasClass('encrypted'), + bSigned = mDom.hasClass('signed'), + oVerControl = null, + sData = '' + ; + + if (bEncrypted || bSigned) + { + sData = mDom.text(); + mDom.data('openpgp-original', sData); + + if (bEncrypted) + { + oVerControl = $('
') + .attr('title', Translator.i18n('MESSAGE/PGP_ENCRYPTED_MESSAGE_DESC')); + + oVerControl.on('click', function () { + if ($(this).hasClass('success')) + { + return false; + } + + var oMessage = self.openpgp.message.readArmored(sData); + if (oMessage && oMessage.getText && oMessage.verify && oMessage.decrypt) + { + self.decryptMessage(oMessage, function (oValidPrivateKey, oDecriptedMessage, oValidPublicKey, aSigningKeyIds) { + + if (oDecriptedMessage) + { + if (oValidPublicKey) + { + self.controlsHelper(mDom, oVerControl, true, Translator.i18n('PGP_NOTIFICATIONS/GOOD_SIGNATURE', { + 'USER': oValidPublicKey.user + ' (' + oValidPublicKey.id + ')' + }), oDecriptedMessage.getText()); + } + else if (oValidPrivateKey) + { + var + aKeyIds = Utils.isNonEmptyArray(aSigningKeyIds) ? aSigningKeyIds : null, + sAdditional = aKeyIds ? _.compact(_.map(aKeyIds, function (oItem) { + return oItem && oItem.toHex ? oItem.toHex() : null; + })).join(', ') : '' + ; + + self.controlsHelper(mDom, oVerControl, false, + Translator.i18n('PGP_NOTIFICATIONS/UNVERIFIRED_SIGNATURE') + + (sAdditional ? ' (' + sAdditional + ')' : ''), + oDecriptedMessage.getText()); + } + else + { + self.controlsHelper(mDom, oVerControl, false, + Translator.i18n('PGP_NOTIFICATIONS/DECRYPTION_ERROR')); + } + } + else + { + self.controlsHelper(mDom, oVerControl, false, + Translator.i18n('PGP_NOTIFICATIONS/DECRYPTION_ERROR')); + } + }); + + return false; + } + + self.controlsHelper(mDom, oVerControl, false, Translator.i18n('PGP_NOTIFICATIONS/DECRYPTION_ERROR')); + return false; + + }); + } + else if (bSigned) + { + oVerControl = $('
') + .attr('title', Translator.i18n('MESSAGE/PGP_SIGNED_MESSAGE_DESC')); + + oVerControl.on('click', function () { + + if ($(this).hasClass('success') || $(this).hasClass('error')) + { + return false; + } + + var oMessage = self.openpgp.cleartext.readArmored(sData); + if (oMessage && oMessage.getText && oMessage.verify) + { + self.verifyMessage(oMessage, function (oValidKey, aSigningKeyIds) { + if (oValidKey) + { + self.controlsHelper(mDom, oVerControl, true, Translator.i18n('PGP_NOTIFICATIONS/GOOD_SIGNATURE', { + 'USER': oValidKey.user + ' (' + oValidKey.id + ')' + }), oMessage.getText()); + } + else + { + var + aKeyIds = Utils.isNonEmptyArray(aSigningKeyIds) ? aSigningKeyIds : null, + sAdditional = aKeyIds ? _.compact(_.map(aKeyIds, function (oItem) { + return oItem && oItem.toHex ? oItem.toHex() : null; + })).join(', ') : '' + ; + + self.controlsHelper(mDom, oVerControl, false, + Translator.i18n('PGP_NOTIFICATIONS/UNVERIFIRED_SIGNATURE') + + (sAdditional ? ' (' + sAdditional + ')' : '')); + } + }); + + return false; + } + + self.controlsHelper(mDom, oVerControl, false, Translator.i18n('PGP_NOTIFICATIONS/DECRYPTION_ERROR')); + return false; + }); + } + + if (oVerControl) + { + mDom.before(oVerControl).before('
'); + } + } + } + }; + module.exports = new PgpUserStore(); }()); diff --git a/dev/Styles/AdminGeneral.less b/dev/Styles/AdminGeneral.less index 79bb229a1..6158c72e5 100644 --- a/dev/Styles/AdminGeneral.less +++ b/dev/Styles/AdminGeneral.less @@ -6,8 +6,15 @@ } .flag-name { + border-bottom: 1px dashed #555; cursor: pointer; + padding: 2px 0px; + + &:focus { + outline: 1px; + outline-style: dotted; + } } } diff --git a/dev/Styles/Animations.less b/dev/Styles/Animations.less index fb9940869..abf72e01e 100644 --- a/dev/Styles/Animations.less +++ b/dev/Styles/Animations.less @@ -10,7 +10,7 @@ } @keyframes bounce-me { - 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } + 0% { transform: scale(1); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } } @keyframes textLoadingAnimationKeyFrame { diff --git a/dev/Styles/Components.less b/dev/Styles/Components.less index cef5608ba..9bb5d03a3 100644 --- a/dev/Styles/Components.less +++ b/dev/Styles/Components.less @@ -37,13 +37,36 @@ .e-component { + &.e-select { + + select:focus { + outline: 1px; + outline-style: dotted; + } + } + &.e-checkbox { + margin-bottom: 6px; + margin-left: -2px; + padding: 2px; + cursor: pointer; + &:focus { + outline: 1px; + outline-style: dotted; + } + + .e-checkbox-icon { + padding: 1px 0 0 1px; + } + &.disabled { cursor: default; color: #999; + outline: 0; + outline-style: none; } } @@ -60,11 +83,12 @@ .e-component.material-design { - margin-top: 2px; - margin-bottom: 6px; &.e-checkbox { + margin-top: 2px; + padding: 2px 2px 1px 2px; + .sub-checkbox-container { display: inline-block; position: relative; diff --git a/dev/Styles/Filter.less b/dev/Styles/Filter.less index d4860ab6e..3bbdd8af6 100644 --- a/dev/Styles/Filter.less +++ b/dev/Styles/Filter.less @@ -10,5 +10,10 @@ .button-delete { cursor: pointer; } + + .setRecipientsBtn { + margin-top: -2px; + margin-left: 5px; + } } } diff --git a/dev/Styles/FolderList.less b/dev/Styles/FolderList.less index d11993121..a97ac85f9 100644 --- a/dev/Styles/FolderList.less +++ b/dev/Styles/FolderList.less @@ -188,7 +188,7 @@ /**/ } -html.rl-left-panel-disabled { +html.rl-left-panel-disabled, html.rl-left-panel-short { .btn.buttonContacts { margin-top: 10px !important; margin-left: 0 !important; diff --git a/dev/Styles/Layout.less b/dev/Styles/Layout.less index d183aded1..a7aca5690 100644 --- a/dev/Styles/Layout.less +++ b/dev/Styles/Layout.less @@ -205,6 +205,28 @@ html.rl-left-panel-disabled { } } +html.rl-left-panel-short { + + #rl-left { + width: 60px !important; + } + + #rl-right { + left: 60px !important; + } +} + +html.rl-left-panel-none { + + #rl-left { + width: 10px !important; + } + + #rl-right { + left: 10px !important; + } +} + .ui-resizable-helper-w { border-right: 5px solid #777; border-right-color: rgba(255,255,255,0.7); diff --git a/dev/Styles/Login.less b/dev/Styles/Login.less index 2a913bb65..8da8dab3d 100644 --- a/dev/Styles/Login.less +++ b/dev/Styles/Login.less @@ -25,6 +25,9 @@ max-width: 450px; } + .wrapper-parent { + } + .loginForm { background-color: #efefef; text-align: left; @@ -34,6 +37,18 @@ width: 303px; } + .loginWelcomeForm { + display: none; + } + + .welcome-on { + display: block; + } + + .welcome-off { + display: none; + } + /* .control-label { font-size: 16px; line-height: 30px; @@ -60,7 +75,11 @@ } } - .signMeLabel, .languageLabel { + .languageLabel { + margin-top: 5px; + } + + .signMeLabel .e-checkbox { margin-top: 5px; } diff --git a/dev/Styles/MessageList.less b/dev/Styles/MessageList.less index 4c7dba60a..29ad90ad7 100644 --- a/dev/Styles/MessageList.less +++ b/dev/Styles/MessageList.less @@ -178,6 +178,17 @@ html.rl-no-preview-pane { border-bottom: 1px solid #eee; } + .listThreadUidDesc { + font-size: 16px; + padding: 7px 20px 6px 20px; + background-color: #aaa; + border-bottom: 1px solid #888; + color: #fff; + cursor: pointer; + text-shadow: 0 1px 0 #000; + text-align: center; + } + .delimiter { display: block; height: 1px; @@ -313,6 +324,12 @@ html.rl-no-preview-pane { &.e-single-line .dateParent { } + .threadsParent { + display: inline-block; + float: right; + position: relative; + } + .attachmentParent { display: inline-block; float: right; @@ -395,11 +412,25 @@ html.rl-no-preview-pane { .threads-len { .threads-len-data { - background-color: #999; - color: #fff; + + background-color: #eee; + color: #666; border-radius: 6px; - padding: 1px 6px 1px 5px; - margin-right: 5px; + padding: 2px 0px 1px 6px; + margin-right: 2px; + border: 1px solid #ccc; + + [class^="icon-"], + [class*=" icon-"] { + font-size: 14px; + } + + &:hover { + background-color: #aaa; + border-color: #666; + text-shadow: 0 1px 0 #999; + color: #fff; + } } } diff --git a/dev/Styles/MessageView.less b/dev/Styles/MessageView.less index 2b272a3aa..a1440fee4 100644 --- a/dev/Styles/MessageView.less +++ b/dev/Styles/MessageView.less @@ -53,6 +53,10 @@ html.rl-no-preview-pane { } } + .logoPlace { + text-align: center; + } + .b-message-view-desc { text-align: center; font-size: 24px; @@ -65,6 +69,22 @@ html.rl-no-preview-pane { color: #DA4F49; } + .b-message-view-iframe { + } + + .b-message-view-iframe-backdrop { + display: none; + background: transparent; + position: absolute; + width: 100%; + height: 100%; + top: 0px; + left: 0px; + right: 0px; + bottom: 0px; + opacity: .1; + } + .content { -webkit-overflow-scrolling: touch; } @@ -150,6 +170,13 @@ html.rl-no-preview-pane { border-radius: 5px; padding: 10px 15px; overflow: hidden; + + .uiLine { + } + + .uiLabelValue { + word-break: break-all; + } } .emptySubjectText { @@ -263,6 +290,14 @@ html.rl-no-preview-pane { } } + &.unselectedAttachmentsError { + .attachmentItem { + box-shadow: 0 1px 4px red; + box-shadow: 0 1px 5px rgba(255, 0, 0, 0.4); + box-shadow: 0 0 0 1px rgba(255, 0, 0, 0.2), 0 1px 5px rgba(255, 0, 0, 0.3); + } + } + .controls-handle { position: absolute; bottom: 5px; @@ -296,6 +331,10 @@ html.rl-no-preview-pane { } } + .bodySubHeader { + z-index: 2; + } + .bodyText { color: #000; @@ -303,9 +342,11 @@ html.rl-no-preview-pane { .b-text-part { + height: 100%; + div[data-x-div-type=html] { height: 100%; - div[data-x-div-type=html] { + div[data-x-div-type=body] { height: 100%; } } @@ -322,14 +363,10 @@ html.rl-no-preview-pane { } } - table { - border-collapse: separate; - } - blockquote { border-left: 2px solid #000; - margin: 0; padding: 0px 10px; + margin: 0; } .rl-bq-switcher.hidden-bq { @@ -337,8 +374,10 @@ html.rl-no-preview-pane { } &.html { + div[data-x-div-type=body] { - margin: 15px; + padding: 15px; + // margin: 15px; } pre { @@ -368,6 +407,16 @@ html.rl-no-preview-pane { display: inline-block; padding: 6px 10px; border: 1px dashed #666; + background: #fff; + + &.success { + border-color: green; + background-color: rgba(0, 255, 0, 0.03); + } + &.error { + border-color: red; + background-color: rgba(255, 0, 0, 0.03); + } } blockquote { @@ -385,6 +434,27 @@ html.rl-no-preview-pane { color: red; } } + + .b-openpgp-control { + + display: inline-block; + cursor: pointer; + color: #777; + /*float: left;*/ + + &:hover { + color: #111; + } + + &.success { + color: green; + cursor: help; + } + + &.error { + color: red; + } + } } } } @@ -434,6 +504,10 @@ html.rl-no-preview-pane { } } +html.rl-resizer .b-message-view-iframe-backdrop { + display: block !important; +} + html.rl-no-preview-pane .messageView { .toolbar { padding-left: @rlMainBorderSize; diff --git a/dev/Styles/OpenPgpKey.less b/dev/Styles/OpenPgpKey.less index 611c5e5c3..b9ff7a9f2 100644 --- a/dev/Styles/OpenPgpKey.less +++ b/dev/Styles/OpenPgpKey.less @@ -1,5 +1,5 @@ .popups { - .b-open-pgp-key-view-content, .b-open-pgp-key-generate-content, .b-open-pgp-key-add-content, .b-compose-open-pgp-content { + .b-open-pgp-key-view-content, .b-open-pgp-key-generate-content, .b-open-pgp-key-add-content, .b-compose-open-pgp-content, .b-message-open-pgp-content { .modal-header { background-color: #fff; @@ -18,4 +18,101 @@ overflow: auto; } } + + .b-compose-open-pgp-content { + &.modal { + width: 700px; + } + + .key-list { + + background-color: #f9f9f9; + border-radius: 5px; + padding: 10px 15px; + margin-top: 10px; + min-height: 40px; + + &-wrp { + overflow: hidden; + text-overflow: ellipsis; + + &.empty { + text-align: center; + padding-top: 10px; + color: #aaa; + font-size: 16px; + } + } + + &__item { + + color: #333; + white-space: nowrap; + + &-delete { + display: inline; + cursor: pointer; + margin-right: 5px; + } + + &-name { + margin-right: 5px; + color: #333; + display: inline; + + &.empty { + color: red; + } + } + + &-error { + margin-right: 5px; + color: red; + display: inline; + } + + &-hash { + margin-right: 5px; + color: #aaa; + display: inline; + } + } + } + + .key-actions { + margin-top: 10px; + min-height: 40px; + } + } + + .b-message-open-pgp-content { + &.modal { + width: 700px; + } + + .key-list { + + margin-top: 5px; + overflow: hidden; + + &__item { + + color: #555; + cursor: pointer; + text-overflow: ellipsis; + white-space: nowrap; + + &__radio { + padding-right: 5px; + } + + &__name { + + &:hover { + border-bottom: 1px dashed #555; + } + } + } + } + } } diff --git a/dev/Styles/SettingsAccounts.less b/dev/Styles/SettingsAccounts.less index 7c6cd63f6..04aeaf132 100644 --- a/dev/Styles/SettingsAccounts.less +++ b/dev/Styles/SettingsAccounts.less @@ -40,7 +40,7 @@ cursor: pointer; color: #ccc; } - + .identity-name { display: inline-block; word-break: break-all; @@ -50,6 +50,12 @@ } } + .accounts-list-top-padding, .identities-list-top-padding { + display: inline-block; + height: 5px; + width: 5px; + } + .account-item { .e-action { diff --git a/dev/Styles/SettingsFilters.less b/dev/Styles/SettingsFilters.less index ea218b9fe..501098d52 100644 --- a/dev/Styles/SettingsFilters.less +++ b/dev/Styles/SettingsFilters.less @@ -46,6 +46,12 @@ } } + .filters-list-top-padding { + display: inline-block; + height: 5px; + width: 5px; + } + .filter-item { .e-action { diff --git a/dev/Styles/SettingsFolders.less b/dev/Styles/SettingsFolders.less index 734f0e026..8f18ef151 100644 --- a/dev/Styles/SettingsFolders.less +++ b/dev/Styles/SettingsFolders.less @@ -86,7 +86,7 @@ } } - .delete-folder, .subscribe-folder, .unsubscribe-folder { + .delete-folder, .subscribe-folder, .unsubscribe-folder, .check-folder, .uncheck-folder { cursor: pointer; opacity: 0.6; } @@ -94,6 +94,10 @@ .unsubscribe-folder { opacity: 0.2; } + + .uncheck-folder { + opacity: 0.1; + } } .folder-padding.deep-1 { diff --git a/dev/Styles/SettingsGeneral.less b/dev/Styles/SettingsGeneral.less index 7d4a236be..d4cf39586 100644 --- a/dev/Styles/SettingsGeneral.less +++ b/dev/Styles/SettingsGeneral.less @@ -20,7 +20,14 @@ } .flag-name { + border-bottom: 1px dashed #555; cursor: pointer; + padding: 2px 0px; + + &:focus { + outline: 1px; + outline-style: dotted; + } } } diff --git a/dev/Styles/SettingsOpenPGP.less b/dev/Styles/SettingsOpenPGP.less index 3397d2922..894ca86b9 100644 --- a/dev/Styles/SettingsOpenPGP.less +++ b/dev/Styles/SettingsOpenPGP.less @@ -17,8 +17,13 @@ } .open-pgp-key-img { - font-size: 12px; - margin-right: 5px; + + margin-right: 10px; + + .svg-icon { + width: 12px; + height: 12px; + } } .open-pgp-key-id, .open-pgp-key-user { @@ -49,7 +54,11 @@ .delete-open-pgp-key, .view-open-pgp-key { cursor: pointer; - opacity: 0.5; + opacity: 0.7; + + &:hover { + opacity: 0.9; + } } } } \ No newline at end of file diff --git a/dev/Styles/SettingsTemplates.less b/dev/Styles/SettingsTemplates.less index 09ad48c32..3495173b1 100644 --- a/dev/Styles/SettingsTemplates.less +++ b/dev/Styles/SettingsTemplates.less @@ -37,6 +37,12 @@ } } + .templates-list-top-padding { + display: inline-block; + height: 5px; + width: 5px; + } + .template-item { .e-action { diff --git a/dev/Styles/SystemDropDown.less b/dev/Styles/SystemDropDown.less index 32422839f..4bab81b1b 100644 --- a/dev/Styles/SystemDropDown.less +++ b/dev/Styles/SystemDropDown.less @@ -34,16 +34,25 @@ vertical-align: middle; } + .logoPlace { + margin: -5px 10px 0 0; + font-size: 25px; + line-height: 30px; + height: 40px; + } + .audioPlace { font-size: 25px; line-height: 30px; - margin-right: 15px; + margin-right: 10px; + width: 25px; .playIcon, .stopIcon { cursor: pointer; color: orange; text-shadow: 0 1px 0 #555; + float: right; } .playIcon { diff --git a/dev/Styles/Ui.less b/dev/Styles/Ui.less index dbfa7b86b..53a821a38 100644 --- a/dev/Styles/Ui.less +++ b/dev/Styles/Ui.less @@ -21,12 +21,22 @@ color: #336699; text-decoration: underline; cursor: pointer; + padding: 2px; + + &:focus { + outline: 1px; + outline-style: dotted; + } } .g-ui-min-height-300 { min-height: 300px; } +.g-ui-100-proc-height { + height: 100%; +} + .g-ui-absolute-reset { position: absolute; top: 0; @@ -181,12 +191,21 @@ e-spinner { } .e-languages { + margin-top: 8px; color: #333; + .flag-name { + color: #333; - /*text-decoration: underline;*/ border-bottom: 1px dashed #333; + cursor: pointer; + padding: 2px 0px; + + &:focus { + outline: 1px; + outline-style: dotted; + } } } @@ -220,7 +239,6 @@ html.cssanimations { .e-spinner .bounce2 { animation-delay: -0.16s; } - } @keyframes bouncedelay { diff --git a/dev/Styles/_BootstrapFix.less b/dev/Styles/_BootstrapFix.less index 9bb2619b8..3c7544cd0 100644 --- a/dev/Styles/_BootstrapFix.less +++ b/dev/Styles/_BootstrapFix.less @@ -7,7 +7,7 @@ label { cursor: pointer; } -label.inline { +label.inline, span.inline { display: inline-block; } @@ -67,6 +67,10 @@ select { width: 223px; } +.btn .svg-icon { + vertical-align: middle; +} + .btn-small.btn-small-small { padding: 3px 9px; font-size: 11px; diff --git a/dev/Styles/_End.less b/dev/Styles/_End.less index 5fcebedea..d48b671d8 100644 --- a/dev/Styles/_End.less +++ b/dev/Styles/_End.less @@ -69,3 +69,22 @@ } } } + +svg-icon { + display: none; +} + +.svg-icon { + border: 0; + outline: 0; + + height: 16px; + width: 16px; + display: inline-block; + fill: #333; + + &.svg-icon-archive { + height: 14px; + width: 14px; + } +} diff --git a/dev/Styles/_FontasticToBoot.less b/dev/Styles/_FontasticToBoot.less index 9e61f787a..52d8db353 100644 --- a/dev/Styles/_FontasticToBoot.less +++ b/dev/Styles/_FontasticToBoot.less @@ -17,12 +17,19 @@ width: 17px; } +.iconsize50 { + line-height: 50px; + font-size: 50px; + width: 50px; + height: 50px; +} + .iconsize24 { line-height: 24px; font-size: 24px; } -.iconsize24 { +.iconsize20 { line-height: 20px; font-size: 20px; } @@ -142,7 +149,7 @@ border-color: transparent; border-top-color: #999; - animation: rotation .8s infinite linear; + animation: rotation .8s infinite ease-in-out; } &.big { diff --git a/dev/View/Admin/Login.js b/dev/View/Admin/Login.js index e6a64c8ec..84d506e86 100644 --- a/dev/View/Admin/Login.js +++ b/dev/View/Admin/Login.js @@ -87,7 +87,6 @@ { if (oData.Result) { - this.formHidden(true); require('App/Admin').loginAndLogoutReload(true); } else if (oData.ErrorCode) diff --git a/dev/View/Admin/Settings/Pane.js b/dev/View/Admin/Settings/Pane.js index fa6ff52a2..929ee0c67 100644 --- a/dev/View/Admin/Settings/Pane.js +++ b/dev/View/Admin/Settings/Pane.js @@ -26,6 +26,7 @@ this.version = ko.observable(Settings.settingsGet('Version')); this.capa = !!Settings.settingsGet('PremType'); + this.community = RL_COMMUNITY; this.adminManLoading = ko.computed(function () { return '000' !== [ diff --git a/dev/View/Popup/AdvancedSearch.js b/dev/View/Popup/AdvancedSearch.js index ad4eef02a..9200b02b2 100644 --- a/dev/View/Popup/AdvancedSearch.js +++ b/dev/View/Popup/AdvancedSearch.js @@ -8,6 +8,7 @@ ko = require('ko'), Utils = require('Common/Utils'), + Translator = require('Common/Translator'), MessageStore = require('Stores/User/Message'), @@ -46,6 +47,19 @@ this.cancelCommand(); }); + this.selectedDates = ko.computed(function () { + Translator.trigger(); + return [ + {'id': -1, 'name': Translator.i18n('SEARCH/LABEL_ADV_DATE_ALL')}, + {'id': 3, 'name': Translator.i18n('SEARCH/LABEL_ADV_DATE_3_DAYS')}, + {'id': 7, 'name': Translator.i18n('SEARCH/LABEL_ADV_DATE_7_DAYS')}, + {'id': 30, 'name': Translator.i18n('SEARCH/LABEL_ADV_DATE_MONTH')}, + {'id': 90, 'name': Translator.i18n('SEARCH/LABEL_ADV_DATE_3_MONTHS')}, + {'id': 180, 'name': Translator.i18n('SEARCH/LABEL_ADV_DATE_6_MONTHS')}, + {'id': 365, 'name': Translator.i18n('SEARCH/LABEL_ADV_DATE_YEAR')} + ]; + }, this); + kn.constructorEnd(this); } diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index 42b8bf4ab..4e588b2ec 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -1,4 +1,6 @@ +/* global require, module */ + (function () { 'use strict'; @@ -87,6 +89,7 @@ this.resizerTrigger = _.bind(this.resizerTrigger, this); this.allowContacts = !!AppStore.contactsIsAllowed(); + this.allowFolders = !!Settings.capa(Enums.Capa.Folders); this.bSkipNextHide = false; this.composeInEdit = AppStore.composeInEdit; @@ -319,7 +322,7 @@ } }, this)); - this.canBeSendedOrSaved = ko.computed(function () { + this.canBeSentOrSaved = ko.computed(function () { return !this.sending() && !this.saving(); }, this); @@ -373,6 +376,11 @@ } } + if (!this.allowFolders) + { + sSentFolder = Consts.Values.UnuseOptionValue; + } + if ('' === sSentFolder) { kn.showScreenPopup(require('View/Popup/FolderSystem'), [Enums.SetSystemFoldersNotification.Sent]); @@ -430,10 +438,16 @@ ); } } - }, this.canBeSendedOrSaved); + + }, this.canBeSentOrSaved); this.saveCommand = Utils.createCommand(this, function () { + if (!this.allowFolders) + { + return false; + } + if (FolderStore.draftFolderNotEnabled()) { kn.showScreenPopup(require('View/Popup/FolderSystem'), [Enums.SetSystemFoldersNotification.Draft]); @@ -468,7 +482,7 @@ ); } - }, this.canBeSendedOrSaved); + }, this.canBeSentOrSaved); this.skipCommand = Utils.createCommand(this, function () { @@ -482,7 +496,7 @@ this.tryToClosePopup(); - }, this.canBeSendedOrSaved); + }, this.canBeSentOrSaved); this.contactsCommand = Utils.createCommand(this, function () { @@ -523,7 +537,6 @@ if (window.Dropbox) { window.Dropbox.choose({ - //'iframe': true, 'success': function(aFiles) { if (aFiles && aFiles[0] && aFiles[0]['link']) @@ -619,7 +632,7 @@ oEditor.setPlain(sResult); }); }, - this.oEditor.getData(), + this.oEditor.getData(false, true), this.currentIdentity(), this.to(), this.cc(), @@ -634,7 +647,7 @@ sDraftFolder = FolderStore.draftFolder() ; - if ('' !== sDraftFolder) + if ('' !== sDraftFolder && Consts.Values.UnuseOptionValue !== sDraftFolder) { Cache.setFolderHash(sDraftFolder, ''); if (FolderStore.currentFolderFullNameRaw() === sDraftFolder) @@ -1097,6 +1110,26 @@ oText.find('.rlBlockquoteSwitcher').off('.rlBlockquoteSwitcher').remove(); oText.find('[data-html-editor-font-wrapper]').removeAttr('data-html-editor-font-wrapper'); +// (function () { +// +// var oTmp = null, iLimit = 0; +// +// while (true) +// { +// iLimit++; +// +// oTmp = oText.children(); +// if (10 > iLimit && oTmp.is('div') && 1 === oTmp.length) +// { +// oTmp.children().unwrap(); +// continue; +// } +// +// break; +// } +// +// }()); + sText = oText.html(); } @@ -1186,7 +1219,8 @@ }); sText = '

' + sReplyTitle + ':' + - '

' + Utils.trim(sText) + '

'; + '
' + Utils.trim(sText) + '
'; +// '

' + Utils.trim(sText) + '

'; break; @@ -1202,6 +1236,7 @@ '
' + Translator.i18n('COMPOSE/FORWARD_MESSAGE_TOP_SUBJECT') + ': ' + Utils.encodeHtml(sSubject) + '

' + Utils.trim(sText) + '

'; break; + case Enums.ComposeType.ForwardAsAttachment: sText = ''; break; @@ -1390,10 +1425,13 @@ return false; }); - key('ctrl+s, command+s', Enums.KeyState.Compose, function () { - self.saveCommand(); - return false; - }); + if (this.allowFolders) + { + key('ctrl+s, command+s', Enums.KeyState.Compose, function () { + self.saveCommand(); + return false; + }); + } if (!!Settings.settingsGet('AllowCtrlEnterOnCompose')) { @@ -1414,11 +1452,11 @@ Events.sub('window.resize.real', this.resizerTrigger); Events.sub('window.resize.real', _.debounce(this.resizerTrigger, 50)); - if (this.dropboxEnabled()) + if (this.dropboxEnabled() && this.dropboxApiKey() && !window.Dropbox) { oScript = window.document.createElement('script'); oScript.type = 'text/javascript'; - oScript.src = 'https://www.dropbox.com/static/api/1/dropins.js'; + oScript.src = 'https://www.dropbox.com/static/api/2/dropins.js'; $(oScript).attr('id', 'dropboxjs').attr('data-app-key', self.dropboxApiKey()); window.document.body.appendChild(oScript); diff --git a/dev/View/Popup/ComposeOpenPgp.js b/dev/View/Popup/ComposeOpenPgp.js index e77a82f18..70625f669 100644 --- a/dev/View/Popup/ComposeOpenPgp.js +++ b/dev/View/Popup/ComposeOpenPgp.js @@ -28,106 +28,150 @@ { AbstractView.call(this, 'Popups', 'PopupsComposeOpenPgp'); + var self = this; + + this.optionsCaption = Translator.i18n('PGP_NOTIFICATIONS/ADD_A_PUBLICK_KEY'); + this.notification = ko.observable(''); - this.sign = ko.observable(true); - this.encrypt = ko.observable(true); + this.sign = ko.observable(false); + this.encrypt = ko.observable(false); this.password = ko.observable(''); this.password.focus = ko.observable(false); this.buttonFocus = ko.observable(false); - this.from = ko.observable(''); - this.to = ko.observableArray([]); this.text = ko.observable(''); + this.selectedPublicKey = ko.observable(null); - this.resultCallback = null; + this.signKey = ko.observable(null); + this.encryptKeys = ko.observableArray([]); + + this.encryptKeysView = ko.computed(function () { + return _.compact(_.map(this.encryptKeys(), function (oKey) { + return oKey ? oKey.key : null; + })); + }, this); + + this.publicKeysOptions = ko.computed(function () { + return _.compact(_.map(PgpStore.openpgpkeysPublic(), function (oKey) { + return -1 < Utils.inArray(oKey, self.encryptKeysView()) ? null : { + 'id': oKey.guid, + 'name': '(' + oKey.id.substr(-6) + ') ' + oKey.user, + 'key': oKey + }; + })); + }); this.submitRequest = ko.observable(false); + this.resultCallback = null; + // commands this.doCommand = Utils.createCommand(this, function () { var - self = this, bResult = true, oPrivateKey = null, + aPrivateKeys = [], aPublicKeys = [] ; this.submitRequest(true); - if (bResult && this.sign() && '' === this.from()) - { - this.notification(Translator.i18n('PGP_NOTIFICATIONS/SPECIFY_FROM_EMAIL')); - bResult = false; - } - if (bResult && this.sign()) { - oPrivateKey = PgpStore.findPrivateKeyByEmail(this.from(), this.password()); - if (!oPrivateKey) + if (!this.signKey()) + { + this.notification(Translator.i18n('PGP_NOTIFICATIONS/SPECIFY_FROM_EMAIL')); + bResult = false; + } + else if (!this.signKey().key) { this.notification(Translator.i18n('PGP_NOTIFICATIONS/NO_PRIVATE_KEY_FOUND_FOR', { - 'EMAIL': this.from() + 'EMAIL': this.signKey().email })); bResult = false; } - } - if (bResult && this.encrypt() && 0 === this.to().length) - { - this.notification(Translator.i18n('PGP_NOTIFICATIONS/SPECIFY_AT_LEAST_ONE_RECIPIENT')); - bResult = false; + if (bResult) + { + aPrivateKeys = this.signKey().key.getNativeKeys(); + oPrivateKey = aPrivateKeys[0] || null; + + try + { + if (oPrivateKey) + { + oPrivateKey.decrypt(Utils.pString(this.password())); + } + } + catch (e) + { + oPrivateKey = null; + } + + if (!oPrivateKey) + { + this.notification(Translator.i18n('PGP_NOTIFICATIONS/NO_PRIVATE_KEY_FOUND')); + bResult = false; + } + } } if (bResult && this.encrypt()) { - aPublicKeys = []; - _.each(this.to(), function (sEmail) { - var aKeys = PgpStore.findPublicKeysByEmail(sEmail); - if (0 === aKeys.length && bResult) - { - self.notification(Translator.i18n('PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND_FOR', { - 'EMAIL': sEmail - })); + if (0 === this.encryptKeys().length) + { + this.notification(Translator.i18n('PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND')); + bResult = false; + } + else if (this.encryptKeys()) + { + aPublicKeys = []; + _.each(this.encryptKeys(), function (oKey) { + if (oKey && oKey.key) + { + aPublicKeys = aPublicKeys.concat(_.compact(_.flatten(oKey.key.getNativeKeys()))); + } + else if (oKey && oKey.email) + { + self.notification(Translator.i18n('PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND_FOR', { + 'EMAIL': oKey.email + })); + + bResult = false; + } + }); + + if (bResult && (0 === aPublicKeys.length || this.encryptKeys().length !== aPublicKeys.length)) + { bResult = false; } - - aPublicKeys = aPublicKeys.concat(aKeys); - }); - - if (bResult && (0 === aPublicKeys.length || this.to().length !== aPublicKeys.length)) - { - bResult = false; } } - _.delay(function () { + if (bResult && self.resultCallback) + { + _.delay(function () { - if (self.resultCallback && bResult) - { - try { + var oPromise = null; + try + { if (oPrivateKey && 0 === aPublicKeys.length) { - self.resultCallback( - PgpStore.openpgp.signClearMessage([oPrivateKey], self.text()) - ); + oPromise = PgpStore.openpgp.signClearMessage([oPrivateKey], self.text()); } else if (oPrivateKey && 0 < aPublicKeys.length) { - self.resultCallback( - PgpStore.openpgp.signAndEncryptMessage(aPublicKeys, oPrivateKey, self.text()) - ); + oPromise = PgpStore.openpgp.signAndEncryptMessage(aPublicKeys, oPrivateKey, self.text()); } else if (!oPrivateKey && 0 < aPublicKeys.length) { - self.resultCallback( - PgpStore.openpgp.encryptMessage(aPublicKeys, self.text()) - ); + oPromise = PgpStore.openpgp.encryptMessage(aPublicKeys, self.text()); } } catch (e) @@ -135,25 +179,84 @@ self.notification(Translator.i18n('PGP_NOTIFICATIONS/PGP_ERROR', { 'ERROR': '' + e })); - - bResult = false; } - } - if (bResult) - { - self.cancelCommand(); - } + if (oPromise) + { + try + { + oPromise.then(function (mData) { + self.resultCallback(mData); + self.cancelCommand(); + + })['catch'](function (e) { + self.notification(Translator.i18n('PGP_NOTIFICATIONS/PGP_ERROR', { + 'ERROR': '' + e + })); + }); + } + catch (e) + { + self.notification(Translator.i18n('PGP_NOTIFICATIONS/PGP_ERROR', { + 'ERROR': '' + e + })); + } + } + + self.submitRequest(false); + + }, 10); + } + else + { self.submitRequest(false); + } - }, 10); + return bResult; }, function () { return !this.submitRequest() && (this.sign() || this.encrypt()); }); + this.addCommand = Utils.createCommand(this, function () { + + var + sKeyId = this.selectedPublicKey(), + aKeys = this.encryptKeys(), + oOption = sKeyId ? _.find(this.publicKeysOptions(), function (oItem) { + return oItem && sKeyId === oItem.id; + }) : null + ; + + if (oOption) + { + aKeys.push({ + 'empty': !oOption.key, + 'selected': ko.observable(!!oOption.key), + 'user': oOption.key.user, + 'hash': oOption.key.id.substr(-6), + 'key': oOption.key + }); + + this.encryptKeys(aKeys); + } + + }, function () { + return !this.submitRequest() && this.selectedPublicKey(); + }); + + this.selectedPublicKey.subscribe(function (sValue) { + if (sValue) + { + this.addCommand(); + } + }, this); + this.sDefaultKeyScope = Enums.KeyState.PopupComposeOpenPGP; + this.defautOptionsAfterRender = Utils.defautOptionsAfterRender; + + this.deletePublickKey = _.bind(this.deletePublickKey, this); kn.constructorEnd(this); } @@ -161,16 +264,24 @@ kn.extendAsViewModel(['View/Popup/ComposeOpenPgp', 'PopupsComposeOpenPgpViewModel'], ComposeOpenPgpPopupView); _.extend(ComposeOpenPgpPopupView.prototype, AbstractView.prototype); + ComposeOpenPgpPopupView.prototype.deletePublickKey = function (oKey) + { + this.encryptKeys.remove(oKey); + }; + ComposeOpenPgpPopupView.prototype.clearPopup = function () { this.notification(''); + this.sign(false); + this.encrypt(false); + this.password(''); this.password.focus(false); this.buttonFocus(false); - this.from(''); - this.to([]); + this.signKey(null); + this.encryptKeys([]); this.text(''); this.submitRequest(false); @@ -220,6 +331,8 @@ var aRec = [], + sEmail = '', + oKey = null, oEmail = new EmailModel() ; @@ -247,8 +360,44 @@ return '' === oEmail.email ? false : oEmail.email; })); - this.from(oIdentity ? oIdentity.email() : ''); - this.to(aRec); + if (oIdentity && oIdentity.email()) + { + sEmail = oIdentity.email(); + oKey = PgpStore.findPrivateKeyByEmailNotNative(sEmail); + if (oKey) + { + this.signKey({ + 'user': oKey.user || sEmail, + 'hash': oKey.id.substr(-6), + 'key': oKey + }); + } + } + + if (this.signKey()) + { + this.sign(true); + } + + if (aRec && 0 < aRec.length) + { + this.encryptKeys(_.compact(_.map(aRec, function (sEmail) { + var oKey = PgpStore.findPublicKeyByEmailNotNative(sEmail) || null; + return { + 'empty': !oKey, + 'selected': ko.observable(!!oKey), + 'user': oKey ? (oKey.user || sEmail) : sEmail, + 'hash': oKey ? oKey.id.substr(-6) : '', + 'key': oKey + }; + }))); + + if (0 < this.encryptKeys().length) + { + this.encrypt(true); + } + } + this.text(sText); }; diff --git a/dev/View/Popup/Contacts.js b/dev/View/Popup/Contacts.js index 0cf7c8b17..4ac9b6e7e 100644 --- a/dev/View/Popup/Contacts.js +++ b/dev/View/Popup/Contacts.js @@ -21,6 +21,8 @@ SettingsStore = require('Stores/User/Settings'), ContactStore = require('Stores/User/Contact'), + Settings = require('Storage/Settings'), + Remote = require('Remote/User/Ajax'), EmailModel = require('Model/Email'), @@ -237,6 +239,12 @@ }); this.newMessageCommand = Utils.createCommand(this, function () { + + if (!Settings.capa(Enums.Capa.Composer)) + { + return false; + } + var aE = [], aC = this.contactsCheckedOrSelected(), @@ -772,7 +780,10 @@ { this.bBackToCompose = false; - kn.showScreenPopup(require('View/Popup/Compose')); + if (Settings.capa(Enums.Capa.Composer)) + { + kn.showScreenPopup(require('View/Popup/Compose')); + } } }; diff --git a/dev/View/Popup/Filter.js b/dev/View/Popup/Filter.js index c5f5ad428..41465f8ad 100644 --- a/dev/View/Popup/Filter.js +++ b/dev/View/Popup/Filter.js @@ -78,6 +78,7 @@ this.actionTypeOptions = ko.observableArray([]); this.fieldOptions = ko.observableArray([]); this.typeOptions = ko.observableArray([]); + this.typeOptionsSize = ko.observableArray([]); Translator.initOnStartOrLangChange(this.populateOptions, this); @@ -136,7 +137,9 @@ this.fieldOptions([ {'id': Enums.FilterConditionField.From, 'name': Translator.i18n('POPUPS_FILTER/SELECT_FIELD_FROM')}, {'id': Enums.FilterConditionField.Recipient, 'name': Translator.i18n('POPUPS_FILTER/SELECT_FIELD_RECIPIENTS')}, - {'id': Enums.FilterConditionField.Subject, 'name': Translator.i18n('POPUPS_FILTER/SELECT_FIELD_SUBJECT')} + {'id': Enums.FilterConditionField.Subject, 'name': Translator.i18n('POPUPS_FILTER/SELECT_FIELD_SUBJECT')}, + {'id': Enums.FilterConditionField.Size, 'name': Translator.i18n('POPUPS_FILTER/SELECT_FIELD_SIZE')}, + {'id': Enums.FilterConditionField.Header, 'name': Translator.i18n('POPUPS_FILTER/SELECT_FIELD_HEADER')} ]); this.typeOptions([ @@ -145,6 +148,11 @@ {'id': Enums.FilterConditionType.EqualTo, 'name': Translator.i18n('POPUPS_FILTER/SELECT_TYPE_EQUAL_TO')}, {'id': Enums.FilterConditionType.NotEqualTo, 'name': Translator.i18n('POPUPS_FILTER/SELECT_TYPE_NOT_EQUAL_TO')} ]); + + this.typeOptionsSize([ + {'id': Enums.FilterConditionType.Over, 'name': Translator.i18n('POPUPS_FILTER/SELECT_TYPE_OVER')}, + {'id': Enums.FilterConditionType.Under, 'name': Translator.i18n('POPUPS_FILTER/SELECT_TYPE_UNDER')} + ]); }; diff --git a/dev/View/Popup/Languages.js b/dev/View/Popup/Languages.js index cf32623c9..870d8850e 100644 --- a/dev/View/Popup/Languages.js +++ b/dev/View/Popup/Languages.js @@ -24,15 +24,16 @@ var self = this; this.fLang = null; - this.sUserLanguage = ''; + this.userLanguage = ko.observable(''); this.langs = ko.observableArray([]); this.languages = ko.computed(function () { + var sUserLanguage = self.userLanguage(); return _.map(self.langs(), function (sLanguage) { return { 'key': sLanguage, - 'user': sLanguage === self.sUserLanguage, + 'user': sLanguage === sUserLanguage, 'selected': ko.observable(false), 'fullName': Utils.convertLangName(sLanguage) }; @@ -63,21 +64,22 @@ }); }; + LanguagesPopupView.prototype.onBeforeShow = function () + { + this.fLang = null; + this.userLanguage(''); + + this.langs([]); + }; + LanguagesPopupView.prototype.onShow = function (fLanguage, aLangs, sUserLanguage) { this.fLang = fLanguage; - this.sUserLanguage = sUserLanguage || ''; + this.userLanguage(sUserLanguage || ''); this.langs(aLangs); }; - LanguagesPopupView.prototype.onHide = function () - { - this.fLang = null; - this.sUserLanguage = ''; - this.langs([]); - }; - LanguagesPopupView.prototype.changeLanguage = function (sLang) { if (this.fLang) diff --git a/dev/View/Popup/MessageOpenPgp.js b/dev/View/Popup/MessageOpenPgp.js new file mode 100644 index 000000000..7a861c58c --- /dev/null +++ b/dev/View/Popup/MessageOpenPgp.js @@ -0,0 +1,179 @@ + +(function () { + + 'use strict'; + + var + _ = require('_'), + ko = require('ko'), + key = require('key'), + + Utils = require('Common/Utils'), + Enums = require('Common/Enums'), + + kn = require('Knoin/Knoin'), + AbstractView = require('Knoin/AbstractView') + ; + + /** + * @constructor + * @extends AbstractView + */ + function MessageOpenPgpPopupView() + { + AbstractView.call(this, 'Popups', 'PopupsMessageOpenPgp'); + + this.notification = ko.observable(''); + + this.selectedKey = ko.observable(null); + this.privateKeys = ko.observableArray([]); + + this.password = ko.observable(''); + this.password.focus = ko.observable(false); + this.buttonFocus = ko.observable(false); + + this.resultCallback = null; + + this.submitRequest = ko.observable(false); + + // commands + this.doCommand = Utils.createCommand(this, function () { + + this.submitRequest(true); + +_.delay(_.bind(function() { + + var + oPrivateKeys = [], + oPrivateKey = null + ; + + try + { + if (this.resultCallback && this.selectedKey()) + { + oPrivateKeys = this.selectedKey().getNativeKeys(); + oPrivateKey = oPrivateKeys && oPrivateKeys[0] ? oPrivateKeys[0] : null; + + if (oPrivateKey) + { + try + { + if (!oPrivateKey.decrypt(Utils.pString(this.password()))) + { + oPrivateKey = null; + } + } + catch (e) + { + oPrivateKey = null; + } + } + } + } + catch (oExc) + { + oPrivateKey = null; + } + + this.submitRequest(false); + + this.cancelCommand(); + this.resultCallback(oPrivateKey); + +}, this), 100); + + }, function () { + return !this.submitRequest(); + }); + + this.sDefaultKeyScope = Enums.KeyState.PopupMessageOpenPGP; + + kn.constructorEnd(this); + } + + kn.extendAsViewModel(['View/Popup/MessageOpenPgp'], MessageOpenPgpPopupView); + _.extend(MessageOpenPgpPopupView.prototype, AbstractView.prototype); + + MessageOpenPgpPopupView.prototype.clearPopup = function () + { + this.notification(''); + + this.password(''); + this.password.focus(false); + this.buttonFocus(false); + + this.selectedKey(false); + this.submitRequest(false); + + this.resultCallback = null; + this.privateKeys([]); + }; + + MessageOpenPgpPopupView.prototype.onBuild = function (oDom) + { + key('tab,shift+tab', Enums.KeyState.PopupMessageOpenPGP, _.bind(function () { + + switch (true) + { + case this.password.focus(): + this.buttonFocus(true); + break; + case this.buttonFocus(): + this.password.focus(true); + break; + } + + return false; + + }, this)); + + var self = this; + + oDom + .on('click', '.key-list__item', function () { + + oDom.find('.key-list__item .key-list__item__radio') + .addClass('icon-radio-unchecked') + .removeClass('icon-radio-checked') + ; + + $(this).find('.key-list__item__radio') + .removeClass('icon-radio-unchecked') + .addClass('icon-radio-checked') + ; + + self.selectedKey(ko.dataFor(this)); + + self.password.focus(true); + }) + ; + }; + + MessageOpenPgpPopupView.prototype.onHideWithDelay = function () + { + this.clearPopup(); + }; + + MessageOpenPgpPopupView.prototype.onShowWithDelay = function () + { + this.password.focus(true); +// this.buttonFocus(true); + }; + + MessageOpenPgpPopupView.prototype.onShow = function (fCallback, aPrivateKeys) + { + this.clearPopup(); + + this.resultCallback = fCallback; + this.privateKeys(aPrivateKeys); + + if (this.viewModelDom) + { + this.viewModelDom.find('.key-list__item').first().click(); + } + }; + + module.exports = MessageOpenPgpPopupView; + +}()); \ No newline at end of file diff --git a/dev/View/Popup/NewOpenPgpKey.js b/dev/View/Popup/NewOpenPgpKey.js index e929a438a..f57ad9850 100644 --- a/dev/View/Popup/NewOpenPgpKey.js +++ b/dev/View/Popup/NewOpenPgpKey.js @@ -42,7 +42,6 @@ var self = this, sUserID = '', - mKeyPair = null, oOpenpgpKeyring = PgpStore.openpgpKeyring ; @@ -62,29 +61,40 @@ _.delay(function () { - mKeyPair = false; + var mPromise = false; + try { - mKeyPair = PgpStore.openpgp.generateKeyPair({ + + mPromise = PgpStore.openpgp.generateKeyPair({ 'userId': sUserID, 'numBits': Utils.pInt(self.keyBitLength()), 'passphrase': Utils.trim(self.password()) }); - } catch (e) { -// window.console.log(e); - } - if (mKeyPair && mKeyPair.privateKeyArmored) + mPromise.then(function (mKeyPair) { + + self.submitRequest(false); + + if (mKeyPair && mKeyPair.privateKeyArmored) + { + oOpenpgpKeyring.privateKeys.importKey(mKeyPair.privateKeyArmored); + oOpenpgpKeyring.publicKeys.importKey(mKeyPair.publicKeyArmored); + + oOpenpgpKeyring.store(); + + require('App/User').reloadOpenPgpKeys(); + Utils.delegateRun(self, 'cancelCommand'); + } + + })['catch'](function() { + self.submitRequest(false); + }); + } + catch (e) { - oOpenpgpKeyring.privateKeys.importKey(mKeyPair.privateKeyArmored); - oOpenpgpKeyring.publicKeys.importKey(mKeyPair.publicKeyArmored); - oOpenpgpKeyring.store(); - - require('App/User').reloadOpenPgpKeys(); - Utils.delegateRun(self, 'cancelCommand'); + self.submitRequest(false); } - self.submitRequest(false); - }, 100); return true; diff --git a/dev/View/User/AbstractSystemDropDown.js b/dev/View/User/AbstractSystemDropDown.js index 76c1d5e9e..88dcf9474 100644 --- a/dev/View/User/AbstractSystemDropDown.js +++ b/dev/View/User/AbstractSystemDropDown.js @@ -30,6 +30,12 @@ { AbstractView.call(this, 'Right', 'SystemDropDown'); + this.logoImg = Utils.trim(Settings.settingsGet('UserLogo')); + this.logoTitle = Utils.trim(Settings.settingsGet('UserLogoTitle')); + + this.allowSettings = !!Settings.capa(Enums.Capa.Settings); + this.allowHelp = !!Settings.capa(Enums.Capa.Help); + this.currentAudio = AppStore.currentAudio; this.accountEmail = AccountStore.email; @@ -81,12 +87,18 @@ AbstractSystemDropDownUserView.prototype.settingsClick = function () { - require('Knoin/Knoin').setHash(Links.settings()); + if (Settings.capa(Enums.Capa.Settings)) + { + require('Knoin/Knoin').setHash(Links.settings()); + } }; AbstractSystemDropDownUserView.prototype.settingsHelp = function () { - require('Knoin/Knoin').showScreenPopup(require('View/Popup/KeyboardShortcutsHelp')); + if (Settings.capa(Enums.Capa.Help)) + { + require('Knoin/Knoin').showScreenPopup(require('View/Popup/KeyboardShortcutsHelp')); + } }; AbstractSystemDropDownUserView.prototype.addAccountClick = function () diff --git a/dev/View/User/Login.js b/dev/View/User/Login.js index f2ea8c45b..db5dc2e79 100644 --- a/dev/View/User/Login.js +++ b/dev/View/User/Login.js @@ -36,6 +36,8 @@ { AbstractView.call(this, 'Center', 'Login'); + this.welcome = ko.observable(!!Settings.settingsGet('UseLoginWelcomePage')); + this.email = ko.observable(''); this.password = ko.observable(''); this.signMe = ko.observable(false); @@ -213,12 +215,10 @@ } else if (oData.Admin) { - this.formHidden(true); require('App/User').redirectToAdminPanel(); } else { - this.formHidden(true); require('App/User').loginAndLogoutReload(false); } } @@ -296,11 +296,12 @@ }); this.googleLoginEnabled = ko.observable(false); + this.googleFastLoginEnabled = ko.observable(false); this.googleCommand = Utils.createCommand(this, function () { window.open(Links.socialGoogle(), 'Google', - 'left=200,top=100,width=650,height=450,menubar=no,status=no,resizable=yes,scrollbars=yes'); + 'left=200,top=100,width=650,height=500,menubar=no,status=no,resizable=yes,scrollbars=yes'); return true; @@ -308,6 +309,17 @@ return !this.submitRequest() && this.googleLoginEnabled(); }); + this.googleFastCommand = Utils.createCommand(this, function () { + + window.open(Links.socialGoogle(true), 'Google', + 'left=200,top=100,width=650,height=500,menubar=no,status=no,resizable=yes,scrollbars=yes'); + + return true; + + }, function () { + return !this.submitRequest() && this.googleFastLoginEnabled(); + }); + this.twitterLoginEnabled = ko.observable(false); this.twitterCommand = Utils.createCommand(this, function () { @@ -338,6 +350,11 @@ kn.extendAsViewModel(['View/User/Login', 'View/App/Login', 'LoginViewModel'], LoginUserView); _.extend(LoginUserView.prototype, AbstractView.prototype); + LoginUserView.prototype.displayMainForm = function () + { + this.welcome(false); + }; + LoginUserView.prototype.onShow = function () { kn.routeOff(); @@ -382,8 +399,6 @@ if (0 === iErrorCode) { self.submitRequest(true); - self.formHidden(true); - require('App/User').loginAndLogoutReload(false); } else @@ -397,6 +412,8 @@ this.twitterLoginEnabled(!!Settings.settingsGet('AllowTwitterSocial')); this.googleLoginEnabled(!!Settings.settingsGet('AllowGoogleSocial') && !!Settings.settingsGet('AllowGoogleSocialAuth')); + this.googleFastLoginEnabled(!!Settings.settingsGet('AllowGoogleSocial') && + !!Settings.settingsGet('AllowGoogleSocialAuthFast')); switch (sSignMe) { @@ -426,7 +443,7 @@ this.email(AppStore.devEmail); this.password(AppStore.devPassword); - if (this.googleLoginEnabled()) + if (this.googleLoginEnabled() || this.googleFastLoginEnabled()) { window['rl_' + sJsHash + '_google_login_service'] = fSocial; } @@ -471,6 +488,21 @@ ]); }; + LoginUserView.prototype.selectLanguageOnTab = function (bShift) + { + if (!bShift) + { + var self = this; + _.delay(function () { + self.emailFocus(true); + }, 5); + + return false; + } + + return true; + }; + module.exports = LoginUserView; }()); \ No newline at end of file diff --git a/dev/View/User/MailBox/FolderList.js b/dev/View/User/MailBox/FolderList.js index 7004b0fb3..d32f72a6a 100644 --- a/dev/View/User/MailBox/FolderList.js +++ b/dev/View/User/MailBox/FolderList.js @@ -22,6 +22,8 @@ FolderStore = require('Stores/User/Folder'), MessageStore = require('Stores/User/Message'), + Settings = require('Storage/Settings'), + kn = require('Knoin/Knoin'), AbstractView = require('Knoin/AbstractView') ; @@ -50,7 +52,9 @@ this.iDropOverTimer = 0; + this.allowComposer = !!Settings.capa(Enums.Capa.Composer); this.allowContacts = !!AppStore.contactsIsAllowed(); + this.allowFolders = !!Settings.capa(Enums.Capa.Folders); this.folderListFocused = ko.computed(function () { return Enums.Focused.FolderList === AppStore.focusedState(); @@ -259,7 +263,10 @@ FolderListMailBoxUserView.prototype.composeClick = function () { - kn.showScreenPopup(require('View/Popup/Compose')); + if (Settings.capa(Enums.Capa.Composer)) + { + kn.showScreenPopup(require('View/Popup/Compose')); + } }; FolderListMailBoxUserView.prototype.createFolder = function () diff --git a/dev/View/User/MailBox/MessageList.js b/dev/View/User/MailBox/MessageList.js index cd254167f..cc67227a8 100644 --- a/dev/View/User/MailBox/MessageList.js +++ b/dev/View/User/MailBox/MessageList.js @@ -48,7 +48,12 @@ this.bPrefetch = false; this.emptySubjectValue = ''; - this.hideDangerousActions = !!Settings.settingsGet('HideDangerousActions'); + this.allowReload = !!Settings.capa(Enums.Capa.Reload); + this.allowSearch = !!Settings.capa(Enums.Capa.Search); + this.allowSearchAdv = !!Settings.capa(Enums.Capa.SearchAdv); + this.allowComposer = !!Settings.capa(Enums.Capa.Composer); + this.allowMessageListActions = !!Settings.capa(Enums.Capa.MessageListActions); + this.allowDangerousActions = !!Settings.capa(Enums.Capa.DangerousActions); this.popupVisibility = Globals.popupVisibility; @@ -62,6 +67,7 @@ this.selectorMessageFocused = MessageStore.selectorMessageFocused; this.isMessageSelected = MessageStore.isMessageSelected; this.messageListSearch = MessageStore.messageListSearch; + this.messageListThreadUid = MessageStore.messageListThreadUid; this.messageListError = MessageStore.messageListError; this.folderMenuForMove = FolderStore.folderMenuForMove; @@ -69,6 +75,7 @@ this.mainMessageListSearch = MessageStore.mainMessageListSearch; this.messageListEndFolder = MessageStore.messageListEndFolder; + this.messageListEndThreadUid = MessageStore.messageListEndThreadUid; this.messageListChecked = MessageStore.messageListChecked; this.messageListCheckedOrSelected = MessageStore.messageListCheckedOrSelected; @@ -198,18 +205,27 @@ this.canBeMoved = this.hasCheckedOrSelectedLines; this.clearCommand = Utils.createCommand(this, function () { - kn.showScreenPopup(require('View/Popup/FolderClear'), [FolderStore.currentFolder()]); + if (Settings.capa(Enums.Capa.DangerousActions)) + { + kn.showScreenPopup(require('View/Popup/FolderClear'), [FolderStore.currentFolder()]); + } }); this.multyForwardCommand = Utils.createCommand(this, function () { - kn.showScreenPopup(require('View/Popup/Compose'), [ - Enums.ComposeType.ForwardAsAttachment, MessageStore.messageListCheckedOrSelected()]); + if (Settings.capa(Enums.Capa.Composer)) + { + kn.showScreenPopup(require('View/Popup/Compose'), [ + Enums.ComposeType.ForwardAsAttachment, MessageStore.messageListCheckedOrSelected()]); + } }, this.canBeMoved); this.deleteWithoutMoveCommand = Utils.createCommand(this, function () { - require('App/User').deleteMessagesFromFolder(Enums.FolderType.Trash, - FolderStore.currentFolderFullNameRaw(), - MessageStore.messageListCheckedOrSelectedUidsWithSubMails(), false); + if (Settings.capa(Enums.Capa.DangerousActions)) + { + require('App/User').deleteMessagesFromFolder(Enums.FolderType.Trash, + FolderStore.currentFolderFullNameRaw(), + MessageStore.messageListCheckedOrSelectedUidsWithSubMails(), false); + } }, this.canBeMoved); this.deleteCommand = Utils.createCommand(this, function () { @@ -239,7 +255,7 @@ this.moveCommand = Utils.createCommand(this, Utils.emptyFunction, this.canBeMoved); this.reloadCommand = Utils.createCommand(this, function () { - if (!MessageStore.messageListCompleteLoadingThrottleForAnimation()) + if (!MessageStore.messageListCompleteLoadingThrottleForAnimation() && this.allowReload) { require('App/User').reloadMessageList(false, true); } @@ -276,6 +292,35 @@ }, this) ; + Events + .sub('mailbox.message.show', function (sFolder, sUid) { + + var oMessage = _.find(this.messageList(), function (oItem) { + return oItem && sFolder === oItem.folderFullNameRaw && sUid === oItem.uid; + }); + + if ('INBOX' === sFolder) + { + kn.setHash(Links.mailBox(sFolder, 1)); + } + + if (oMessage) + { + this.selector.selectMessageItem(oMessage); + } + else + { + if ('INBOX' !== sFolder) + { + kn.setHash(Links.mailBox(sFolder, 1)); + } + + MessageStore.selectMessageByFolderAndUid(sFolder, sUid); + } + + }, this) + ; + MessageStore.messageListEndHash.subscribe(function () { this.selector.scrollToTop(); }, this); @@ -297,6 +342,11 @@ { var self = this; + if (0 < this.messageListChecked().length) + { + return false; + } + window.clearTimeout(this.iGoToUpUpOrDownDownTimeout); this.iGoToUpUpOrDownDownTimeout = window.setTimeout(function () { @@ -388,6 +438,15 @@ this.inputMessageListSearchFocus(false); }; + MessageListMailBoxUserView.prototype.cancelThreadUid = function () + { + kn.setHash(Links.mailBox( + FolderStore.currentFolderFullNameHash(), + MessageStore.messageListPageBeforeThread(), + MessageStore.messageListSearch() + )); + }; + /** * @param {string} sToFolderFullNameRaw * @param {boolean} bCopy @@ -611,11 +670,34 @@ kn.setHash(Links.mailBox( FolderStore.currentFolderFullNameHash(), oPage.value, - MessageStore.messageListSearch() + MessageStore.messageListSearch(), + MessageStore.messageListThreadUid() )); } }; + MessageListMailBoxUserView.prototype.gotoThread = function (oMessage) + { + if (oMessage && 0 < oMessage.threadsLen()) + { + MessageStore.messageListPageBeforeThread(MessageStore.messageListPage()); + + kn.setHash(Links.mailBox( + FolderStore.currentFolderFullNameHash(), + 1, + MessageStore.messageListSearch(), + oMessage.uid + )); + } + }; + + MessageListMailBoxUserView.prototype.clearListIsVisible = function () + { + return '' === this.messageListSearchDesc() && '' === this.messageListError() && + '' === MessageStore.messageListEndThreadUid() && + 0 < this.messageList().length && (this.isSpamFolder() || this.isTrashFolder()); + }; + MessageListMailBoxUserView.prototype.onBuild = function (oDom) { var self = this; @@ -641,6 +723,12 @@ .on('click', '.messageList .messageListItem .flagParent', function () { self.flagMessages(ko.dataFor(this)); }) + .on('click', '.messageList .messageListItem .threads-len', function () { + self.gotoThread(ko.dataFor(this)); + }) + .on('dblclick', '.messageList .messageListItem .actionHandle', function () { + self.gotoThread(ko.dataFor(this)); + }) ; this.initUploaderForAppend(); @@ -673,37 +761,43 @@ } }); - // archive (zip) - key('z', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.archiveCommand(); - return false; - }); - - // delete - key('delete, shift+delete, shift+3', Enums.KeyState.MessageList, function (event, handler) { - if (event) - { - if (0 < MessageStore.messageListCheckedOrSelected().length) - { - if (handler && 'shift+delete' === handler.shortcut) - { - self.deleteWithoutMoveCommand(); - } - else - { - self.deleteCommand(); - } - } - + if (Settings.capa(Enums.Capa.MessageListActions)) + { + // archive (zip) + key('z', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.archiveCommand(); return false; - } - }); + }); - // check mail - key('ctrl+r, command+r', [Enums.KeyState.FolderList, Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.reloadCommand(); - return false; - }); + // delete + key('delete, shift+delete, shift+3', Enums.KeyState.MessageList, function (event, handler) { + if (event) + { + if (0 < MessageStore.messageListCheckedOrSelected().length) + { + if (handler && 'shift+delete' === handler.shortcut) + { + self.deleteWithoutMoveCommand(); + } + else + { + self.deleteCommand(); + } + } + + return false; + } + }); + } + + if (Settings.capa(Enums.Capa.Reload)) + { + // check mail + key('ctrl+r, command+r', [Enums.KeyState.FolderList, Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.reloadCommand(); + return false; + }); + } // check all key('ctrl+a, command+a', Enums.KeyState.MessageList, function () { @@ -711,46 +805,80 @@ return false; }); - // write/compose (open compose popup) - key('w,c', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - kn.showScreenPopup(require('View/Popup/Compose')); + if (Settings.capa(Enums.Capa.Composer)) + { + // write/compose (open compose popup) + key('w,c', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + kn.showScreenPopup(require('View/Popup/Compose')); + return false; + }); + } + + if (Settings.capa(Enums.Capa.MessageListActions)) + { + // important - star/flag messages + key('i', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.flagMessagesFast(); + return false; + }); + } + + key('t', [Enums.KeyState.MessageList], function () { + + var oMessage = self.selectorMessageSelected(); + if (!oMessage) + { + oMessage = self.selectorMessageFocused(); + } + + if (oMessage && 0 < oMessage.threadsLen()) + { + self.gotoThread(oMessage); + } + return false; }); - // important - star/flag messages - key('i', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.flagMessagesFast(); - return false; - }); + if (Settings.capa(Enums.Capa.MessageListActions)) + { + // move + key('m', Enums.KeyState.MessageList, function () { + self.moveDropdownTrigger(true); + return false; + }); + } - // move - key('m', Enums.KeyState.MessageList, function () { - self.moveDropdownTrigger(true); - return false; - }); + if (Settings.capa(Enums.Capa.MessageListActions)) + { + // read + key('q', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.seenMessagesFast(true); + return false; + }); - // read - key('q', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.seenMessagesFast(true); - return false; - }); + // unread + key('u', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.seenMessagesFast(false); + return false; + }); + } - // unread - key('u', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.seenMessagesFast(false); - return false; - }); + if (Settings.capa(Enums.Capa.Composer)) + { + key('shift+f', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.multyForwardCommand(); + return false; + }); + } - key('shift+f', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.multyForwardCommand(); - return false; - }); - - // search input focus - key('/', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.inputMessageListSearchFocus(true); - return false; - }); + if (Settings.capa(Enums.Capa.Search)) + { + // search input focus + key('/', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.inputMessageListSearchFocus(true); + return false; + }); + } // cancel search key('esc', Enums.KeyState.MessageList, function () { @@ -759,6 +887,11 @@ self.cancelSearch(); return false; } + else if ('' !== self.messageListEndThreadUid()) + { + self.cancelThreadUid(); + return false; + } }); // change focused state @@ -821,12 +954,18 @@ MessageListMailBoxUserView.prototype.composeClick = function () { - kn.showScreenPopup(require('View/Popup/Compose')); + if (Settings.capa(Enums.Capa.Composer)) + { + kn.showScreenPopup(require('View/Popup/Compose')); + } }; MessageListMailBoxUserView.prototype.advancedSearchClick = function () { - kn.showScreenPopup(require('View/Popup/AdvancedSearch')); + if (Settings.capa(Enums.Capa.SearchAdv)) + { + kn.showScreenPopup(require('View/Popup/AdvancedSearch')); + } }; MessageListMailBoxUserView.prototype.quotaTooltip = function () diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index fdba28c18..4109bdc0b 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -4,6 +4,7 @@ 'use strict'; var + window = require('window'), _ = require('_'), $ = require('$'), ko = require('ko'), @@ -19,9 +20,11 @@ Events = require('Common/Events'), Translator = require('Common/Translator'), Audio = require('Common/Audio'), + Links = require('Common/Links'), Cache = require('Common/Cache'), + SocialStore = require('Stores/Social'), AppStore = require('Stores/User/App'), SettingsStore = require('Stores/User/Settings'), AccountStore = require('Stores/User/Account'), @@ -29,6 +32,7 @@ MessageStore = require('Stores/User/Message'), Local = require('Storage/Client'), + Settings = require('Storage/Settings'), Remote = require('Remote/User/Ajax'), Promises = require('Promises/User/Ajax'), @@ -60,8 +64,19 @@ this.oHeaderDom = null; this.oMessageScrollerDom = null; + this.bodyBackgroundColor = ko.observable(''); + this.pswp = null; + this.allowComposer = !!Settings.capa(Enums.Capa.Composer); + this.allowMessageActions = !!Settings.capa(Enums.Capa.MessageActions); + this.allowMessageListActions = !!Settings.capa(Enums.Capa.MessageListActions); + + this.logoImg = Utils.trim(Settings.settingsGet('UserLogoMessage')); + this.logoIframe = Utils.trim(Settings.settingsGet('UserIframeMessage')); + + this.attachmentsActions = AppStore.attachmentsActions; + this.message = MessageStore.message; this.messageListChecked = MessageStore.messageListChecked; this.hasCheckedMessages = MessageStore.hasCheckedMessages; @@ -80,12 +95,68 @@ this.messageListOfThreadsLoading = ko.observable(false).extend({'rateLimit': 1}); - this.allowAttachmnetControls = ko.observable(false); + this.highlightUnselectedAttachments = ko.observable(false).extend({'falseTimeout': 2000}); + this.showAttachmnetControls = ko.observable(false); + this.allowAttachmnetControls = ko.computed(function () { + return 0 < this.attachmentsActions().length && + Settings.capa(Enums.Capa.AttachmentsActions); + }, this); + + this.downloadAsZipAllowed = ko.computed(function () { + return -1 < Utils.inArray('zip', this.attachmentsActions()) && + this.allowAttachmnetControls(); + }, this); + this.downloadAsZipLoading = ko.observable(false); + this.downloadAsZipError = ko.observable(false).extend({'falseTimeout': 7000}); + + this.saveToOwnCloudAllowed = ko.computed(function () { + return -1 < Utils.inArray('owncloud', this.attachmentsActions()) && + this.allowAttachmnetControls(); + }, this); + this.saveToOwnCloudLoading = ko.observable(false); + this.saveToOwnCloudSuccess = ko.observable(false).extend({'falseTimeout': 2000}); + this.saveToOwnCloudError = ko.observable(false).extend({'falseTimeout': 7000}); + + this.saveToOwnCloudSuccess.subscribe(function (bV) { + if (bV) + { + this.saveToOwnCloudError(false); + } + }, this); + + this.saveToOwnCloudError.subscribe(function (bV) { + if (bV) + { + this.saveToOwnCloudSuccess(false); + } + }, this); + + this.saveToDropboxAllowed = ko.computed(function () { + return -1 < Utils.inArray('dropbox', this.attachmentsActions()) && + this.allowAttachmnetControls(); + }, this); + this.saveToDropboxLoading = ko.observable(false); + this.saveToDropboxSuccess = ko.observable(false).extend({'falseTimeout': 2000}); + this.saveToDropboxError = ko.observable(false).extend({'falseTimeout': 7000}); + + this.saveToDropboxSuccess.subscribe(function (bV) { + if (bV) + { + this.saveToDropboxError(false); + } + }, this); + + this.saveToDropboxError.subscribe(function (bV) { + if (bV) + { + this.saveToDropboxSuccess(false); + } + }, this); this.showAttachmnetControls.subscribe(function (bV) { if (this.message()) @@ -155,7 +226,7 @@ this.deleteCommand = Utils.createCommand(this, function () { var oMessage = this.message(); - if (oMessage) + if (oMessage && this.allowMessageListActions) { this.message(null); require('App/User').deleteMessagesFromFolder(Enums.FolderType.Trash, @@ -165,7 +236,7 @@ this.deleteWithoutMoveCommand = Utils.createCommand(this, function () { var oMessage = this.message(); - if (oMessage) + if (oMessage && this.allowMessageListActions) { this.message(null); require('App/User').deleteMessagesFromFolder(Enums.FolderType.Trash, @@ -175,7 +246,7 @@ this.archiveCommand = Utils.createCommand(this, function () { var oMessage = this.message(); - if (oMessage) + if (oMessage && this.allowMessageListActions) { this.message(null); require('App/User').deleteMessagesFromFolder(Enums.FolderType.Archive, @@ -185,7 +256,7 @@ this.spamCommand = Utils.createCommand(this, function () { var oMessage = this.message(); - if (oMessage) + if (oMessage && this.allowMessageListActions) { this.message(null); require('App/User').deleteMessagesFromFolder(Enums.FolderType.Spam, @@ -195,7 +266,7 @@ this.notSpamCommand = Utils.createCommand(this, function () { var oMessage = this.message(); - if (oMessage) + if (oMessage && this.allowMessageListActions) { this.message(null); require('App/User').deleteMessagesFromFolder(Enums.FolderType.NotSpam, @@ -203,6 +274,9 @@ } }, this.messageVisibility); + this.dropboxEnabled = SocialStore.dropbox.enabled; + this.dropboxApiKey = SocialStore.dropbox.apiKey; + // viewer this.viewBodyTopValue = ko.observable(0); @@ -229,174 +303,6 @@ this.viewIsImportant = ko.observable(false); this.viewIsFlagged = ko.observable(false); -// THREADS - this.viewThreads = ko.observableArray([]); - this.viewThreads.trigger = ko.observable(false); - - this.viewThreadMessages = MessageStore.messageThreadList; - - this.viewThreadMessages.error = ko.observable(''); - this.viewThreadMessages.showMore = ko.observable(false); - this.viewThreadMessages.limit = 6; - - this.viewThreadMessages.subscribe(function (aList) { - - var iSelectedIndex = -1; - - this.viewThreadMessages.error(''); - if (aList && 0 < aList.length) - { - _.each(aList, function (oM, iIndex) { - if (oM && oM.selected()) - { - iSelectedIndex = iIndex; - } - }); - - this.viewThreadMessages.showMore(this.viewThreadMessages.limit >= aList.length); - - if (-1 < iSelectedIndex && !this.viewThreadMessages.showMore() && - this.viewThreadMessages.limit < iSelectedIndex) - { - this.viewThreadMessages.showMore(true); - } - - this.selectSelectedThreadMessage(); - require('App/User').reloadFlagsCurrentMessageListAndMessageFromCache(); - } - - }, this); - - MessageStore.messageLastThreadUidsData.subscribe(function (oData) { - if (oData && oData['Uids']) - { - oData['Uid'] = Utils.pString(oData['Uid']); - if (this.viewFolder === oData['Folder'] && this.viewUid === oData['Uid']) - { - this.viewThreads(oData['Uids']); - this.viewThreads.trigger(!this.viewThreads.trigger()); - } - - var oMessage = MessageStore.message(); - if (oMessage && oMessage.folderFullNameRaw === oData['Folder'] && oMessage.uid === oData['Uid']) - { - oMessage.threads(oData['Uids']); - } - - oMessage = _.find(MessageStore.messageList(), function (oMessage) { - return oMessage && oMessage.folderFullNameRaw === oData['Folder'] && oMessage.uid === oData['Uid']; - }); - - if (oMessage && oMessage.folderFullNameRaw === oData['Folder'] && oMessage.uid === oData['Uid']) - { - oMessage.threads(oData['Uids']); - } - } - }, this); - - this.viewThreads.status = ko.computed(function () { - - this.viewThreads.trigger(); - - var - iIndex = 0, - aResult = [false, '', '', '', ''], - aThreads = this.viewThreads.peek(), - iLen = aThreads.length - ; - - if (1 < iLen) - { - iIndex = Utils.inArray(this.viewUid, aThreads); - if (-1 < iIndex) - { - aResult[0] = true; - aResult[1] = (iIndex + 1) + '/' + iLen; - aResult[2] = aThreads[iIndex]; - aResult[3] = 0 < iIndex && aThreads[iIndex - 1] ? aThreads[iIndex - 1] : ''; - aResult[4] = aThreads[iIndex + 1] ? aThreads[iIndex + 1] : ''; - } - } - - return aResult; - - }, this).extend({'notify': 'always'}); - - this.viewThreadsControlVisibility = ko.computed(function () { - return !!this.viewThreads.status()[0]; - }, this); - - this.viewThreadsControlDesc = ko.computed(function () { - return this.viewThreads.status()[1]; - }, this); - - this.viewThreadsControlBackAllow = ko.computed(function () { - return '' !== this.viewThreads.status()[4] && !this.messageLoadingThrottle(); - }, this); - - this.viewThreadsControlForwardAllow = ko.computed(function () { - return '' !== this.viewThreads.status()[3] && !this.messageLoadingThrottle(); - }, this); - - this.threadBackCommand = Utils.createCommand(this, function () { - var aStatus = this.viewThreads.status(); - this.openThreadMessage(aStatus[4]); - }, this.viewThreadsControlBackAllow); - - this.threadForwardCommand = Utils.createCommand(this, function () { - var aStatus = this.viewThreads.status(); - this.openThreadMessage(aStatus[3]); - }, this.viewThreadsControlForwardAllow); - - this.threadsDropdownTrigger = ko.observable(false); - - this.threadListCommand = Utils.createCommand(this, function () { - - var - self = this, - sFolder = this.viewFolder, - sUid = this.viewUid, - aUids = this.viewThreads(), - aStatus = this.viewThreads.status() - ; - - if (aStatus && aStatus[0]) - { - self.viewThreadMessages([]); - - Promises.messageListSimple(sFolder, aUids, this.messageListOfThreadsLoading).then(function (aList) { - - _.each(aList, function (oItem) { - if (oItem && oItem.uid) - { - oItem.selected(sUid === oItem.uid); - } - }); - - self.viewThreadMessages(aList); - - }).fail(function (iErrorCode) { - self.viewThreadMessages([]); - self.viewThreadMessages.error(Translator.getNotification( - iErrorCode, '', Enums.Notification.CantGetMessageList)); - }).done(); - } - - }, function () { - return !this.messageLoadingThrottle() && - !this.messageListOfThreadsLoading(); - }); - -// PGP - this.viewPgpPassword = ko.observable(''); - this.viewPgpSignedVerifyStatus = ko.computed(function () { - return this.message() ? this.message().pgpSignedVerifyStatus() : Enums.SignedVerifyStatus.None; - }, this); - - this.viewPgpSignedVerifyUser = ko.computed(function () { - return this.message() ? this.message().pgpSignedVerifyUser() : ''; - }, this); - this.viewFromDkimStatusIconClass = ko.computed(function () { var sResult = 'icon-none iconcolor-display-none'; @@ -437,12 +343,14 @@ }, this); + this.messageActiveDom.subscribe(function (oDom) { + this.bodyBackgroundColor(oDom ? this.detectDomBackgroundColor(oDom): ''); + }, this); + this.message.subscribe(function (oMessage) { this.messageActiveDom(null); - this.viewPgpPassword(''); - if (oMessage) { this.showAttachmnetControls(false); @@ -472,9 +380,6 @@ this.viewIsImportant(oMessage.isImportant()); this.viewIsFlagged(oMessage.flagged()); - this.viewThreads(oMessage.threads()); - this.viewThreads.trigger(!this.viewThreads.trigger()); - sLastEmail = oMessage.fromAsSingleEmail(); Cache.getUserPic(sLastEmail, function (sPic, sEmail) { if (sPic !== self.viewUserPic() && sLastEmail === sEmail) @@ -495,8 +400,6 @@ this.viewUid = ''; this.viewHash = ''; - this.viewThreads([]); - this.scrollMessageToTop(); } @@ -555,52 +458,54 @@ kn.extendAsViewModel(['View/User/MailBox/MessageView', 'View/App/MailBox/MessageView', 'MailBoxMessageViewViewModel'], MessageViewMailBoxUserView); _.extend(MessageViewMailBoxUserView.prototype, AbstractView.prototype); - MessageViewMailBoxUserView.prototype.openThreadMessage = function (sUid) + MessageViewMailBoxUserView.prototype.detectDomBackgroundColor = function (oDom) { - var oMessage = this.message(); - if (oMessage && sUid) + var + iLimit = 5, + sResult = '', + aC = null, + fFindDom = function (oDom) { + var aC = oDom ? oDom.children() : null; + return (aC && 1 === aC.length && aC.is('table,div,center')) ? aC : null; + }, + fFindColor = function (oDom) { + var sResult = ''; + if (oDom) + { + sResult = oDom.css('background-color') || ''; + if (!oDom.is('table')) + { + sResult = 'rgba(0, 0, 0, 0)' === sResult || 'transparent' === sResult ? '' : sResult; + } + } + + return sResult; + } + ; + + if (oDom && 1 === oDom.length) { - MessageStore.selectThreadMessage(oMessage.folderFullNameRaw, sUid); - } - }; + aC = oDom; + while ('' === sResult) + { + iLimit--; + if (0 >= iLimit) + { + break; + } - MessageViewMailBoxUserView.prototype.isPgpActionVisible = function () - { - return Enums.SignedVerifyStatus.Success !== this.viewPgpSignedVerifyStatus(); - }; + aC = fFindDom(aC); + if (aC) + { + sResult = fFindColor(aC); + } + else + { + break; + } + } - MessageViewMailBoxUserView.prototype.isPgpStatusVerifyVisible = function () - { - return Enums.SignedVerifyStatus.None !== this.viewPgpSignedVerifyStatus(); - }; - - MessageViewMailBoxUserView.prototype.isPgpStatusVerifySuccess = function () - { - return Enums.SignedVerifyStatus.Success === this.viewPgpSignedVerifyStatus(); - }; - - MessageViewMailBoxUserView.prototype.pgpStatusVerifyMessage = function () - { - var sResult = ''; - switch (this.viewPgpSignedVerifyStatus()) - { - case Enums.SignedVerifyStatus.UnknownPublicKeys: - sResult = Translator.i18n('PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND'); - break; - case Enums.SignedVerifyStatus.UnknownPrivateKey: - sResult = Translator.i18n('PGP_NOTIFICATIONS/NO_PRIVATE_KEY_FOUND'); - break; - case Enums.SignedVerifyStatus.Unverified: - sResult = Translator.i18n('PGP_NOTIFICATIONS/UNVERIFIRED_SIGNATURE'); - break; - case Enums.SignedVerifyStatus.Error: - sResult = Translator.i18n('PGP_NOTIFICATIONS/DECRYPTION_ERROR'); - break; - case Enums.SignedVerifyStatus.Success: - sResult = Translator.i18n('PGP_NOTIFICATIONS/GOOD_SIGNATURE', { - 'USER': this.viewPgpSignedVerifyUser() - }); - break; + sResult = 'rgba(0, 0, 0, 0)' === sResult || 'transparent' === sResult ? '' : sResult; } return sResult; @@ -631,7 +536,10 @@ */ MessageViewMailBoxUserView.prototype.replyOrforward = function (sType) { - kn.showScreenPopup(require('View/Popup/Compose'), [sType, MessageStore.message()]); + if (Settings.capa(Enums.Capa.Composer)) + { + kn.showScreenPopup(require('View/Popup/Compose'), [sType, MessageStore.message()]); + } }; MessageViewMailBoxUserView.prototype.checkHeaderHeight = function () @@ -643,10 +551,38 @@ } }; + /** + * @todo + * @param {string} sEmail + */ +// MessageViewMailBoxUserView.prototype.displayMailToPopup = function (sMailToUrl) +// { +// sMailToUrl = sMailToUrl.replace(/\?.+$/, ''); +// +// var +// sResult = '', +// aTo = [], +// EmailModel = require('Model/Email'), +// fParseEmailLine = function (sLine) { +// return sLine ? _.compact(_.map([window.decodeURIComponent(sLine)], function (sItem) { +// var oEmailModel = new EmailModel(); +// oEmailModel.mailsoParse(sItem); +// return '' !== oEmailModel.email ? oEmailModel : null; +// })) : null; +// } +// ; +// +// aTo = fParseEmailLine(sMailToUrl); +// sResult = aTo && aTo[0] ? aTo[0].email : ''; +// +// return sResult; +// }; + MessageViewMailBoxUserView.prototype.onBuild = function (oDom) { var self = this, + oScript = null, sErrorMessage = Translator.i18n('PREVIEW_POPUP/IMAGE_ERROR'), fCheckHeaderHeight = _.bind(this.checkHeaderHeight, this) ; @@ -660,6 +596,7 @@ } }, this); + this.showAttachmnetControls.subscribe(fCheckHeaderHeight); this.fullScreenMode.subscribe(fCheckHeaderHeight); this.showFullInfo.subscribe(fCheckHeaderHeight); this.message.subscribe(fCheckHeaderHeight); @@ -675,6 +612,16 @@ Utils.windowResize(250); }); + if (this.dropboxEnabled() && this.dropboxApiKey() && !window.Dropbox) + { + oScript = window.document.createElement('script'); + oScript.type = 'text/javascript'; + oScript.src = 'https://www.dropbox.com/static/api/2/dropins.js'; + $(oScript).attr('id', 'dropboxjs').attr('data-app-key', self.dropboxApiKey()); + + window.document.body.appendChild(oScript); + } + this.oHeaderDom = $('.messageItemHeader', oDom); this.oHeaderDom = this.oHeaderDom[0] ? this.oHeaderDom : null; @@ -683,9 +630,10 @@ if (this.pswpDom) { oDom - .on('click', '.attachmentImagePreview[data-index]', function (oEvent) { + .on('click', '.attachmentImagePreview.visible', function (oEvent) { var + iIndex = 0, oPs = null, oEl = oEvent.currentTarget || null, aItems = [] @@ -702,14 +650,18 @@ // } ; - oDom.find('.attachmentImagePreview[data-index]').each(function (index, oSubElement) { + oDom.find('.attachmentImagePreview.visible').each(function (index, oSubElement) { var $oItem = $(oSubElement) ; + if (oEl === oSubElement) + { + iIndex = index; + } + aItems.push({ -// 'el': $oItem, 'w': 600, 'h': 400, 'src': $oItem.attr('href'), 'title': $oItem.attr('title') || '' @@ -721,7 +673,7 @@ Globals.useKeyboardShortcuts(false); oPs = new PhotoSwipe(self.pswpDom, PhotoSwipeUI_Default, aItems, { - 'index': Utils.pInt($(oEl).data('index')), + 'index': iIndex, 'bgOpacity': 0.85, 'loadingIndicatorDelay': 500, 'errorMsg': '
' + sErrorMessage + '
', @@ -760,8 +712,24 @@ oDom .on('click', 'a', function (oEvent) { // setup maito protocol - return !(!!oEvent && 3 !== oEvent['which'] && Utils.mailToHelper($(this).attr('href'), require('View/Popup/Compose'))); + return !(!!oEvent && 3 !== oEvent['which'] && Utils.mailToHelper($(this).attr('href'), + Settings.capa(Enums.Capa.Composer) ? require('View/Popup/Compose') : null)); }) +// .on('mouseover', 'a', _.debounce(function (oEvent) { +// +// if (oEvent) +// { +// var sMailToUrl = $(this).attr('href'); +// if (sMailToUrl && 'mailto:' === sMailToUrl.toString().substr(0, 7).toLowerCase()) +// { +// sMailToUrl = sMailToUrl.toString().substr(7); +// self.displayMailToPopup(sMailToUrl); +// } +// } +// +// return true; +// +// }, 1000)) .on('click', '.attachmentsPlace .attachmentIconParent', function (oEvent) { if (oEvent && oEvent.stopPropagation) { @@ -791,32 +759,6 @@ } } }) - .on('click', '.thread-list .more-threads', function (e) { - - var oLast = null; - if (!e || 0 === e.clientX) // probably enter - { - // It's a bad bad hack :( - oLast = $('.thread-list .e-item.thread-list-message.real-msg.more-that:first a.e-link', oDom); - } - - self.viewThreadMessages.showMore(true); - self.threadsDropdownTrigger(true); - - if (oLast && oLast[0]) - { - oLast.focus(); - } - - return false; - }) - .on('click', '.thread-list .thread-list-message', function () { - var oMessage = ko.dataFor(this); - if (oMessage && oMessage.folder && oMessage.uid) - { - self.openThreadMessage(oMessage.uid); - } - }) .on('click', '.attachmentsPlace .attachmentItem .attachmentNameParent', function () { var @@ -869,18 +811,6 @@ this.initShortcuts(); }; - MessageViewMailBoxUserView.prototype.selectSelectedThreadMessage = function () - { - var self = this; - _.delay(function () { - var oLast = self.oDom ? $('.thread-list .e-item.thread-list-message.real-msg.selected a.e-link', self.oDom) : null; - if (oLast && oLast[0]) - { - oLast.focus(); - } - }, 30); - }; - /** * @return {boolean} */ @@ -970,35 +900,16 @@ } }); - key('t', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (MessageStore.message() && self.viewThreadsControlVisibility()) - { - self.threadsDropdownTrigger(true); - self.threadListCommand(); - return false; - } - }); - - key('ctrl+up, command+up', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + key('ctrl+up, command+up, ctrl+left, command+left', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { self.goUpCommand(); return false; }); - key('ctrl+down, command+down', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + key('ctrl+down, command+down, ctrl+right, command+right', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { self.goDownCommand(); return false; }); - key('ctrl+left, command+left', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.threadForwardCommand(); - return false; - }); - - key('ctrl+right, command+right', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.threadBackCommand(); - return false; - }); - // print key('ctrl+p, command+p', Enums.KeyState.MessageView, function () { if (self.message()) @@ -1111,12 +1022,15 @@ MessageViewMailBoxUserView.prototype.composeClick = function () { - kn.showScreenPopup(require('View/Popup/Compose')); + if (Settings.capa(Enums.Capa.Composer)) + { + kn.showScreenPopup(require('View/Popup/Compose')); + } }; MessageViewMailBoxUserView.prototype.editMessage = function () { - if (MessageStore.message()) + if (Settings.capa(Enums.Capa.Composer) && MessageStore.message()) { kn.showScreenPopup(require('View/Popup/Compose'), [Enums.ComposeType.Draft, MessageStore.message()]); } @@ -1154,34 +1068,115 @@ MessageViewMailBoxUserView.prototype.getAttachmentsHashes = function () { return _.compact(_.map(this.message() ? this.message().attachments() : [], function (oItem) { - return oItem && oItem.checked() ? oItem.download : ''; + return oItem && !oItem.isLinked && oItem.checked() ? oItem.download : ''; })); }; MessageViewMailBoxUserView.prototype.downloadAsZip = function () { - var aHashes = this.getAttachmentsHashes(); + var self = this, aHashes = this.getAttachmentsHashes(); if (0 < aHashes.length) { - Promises.attachmentsActions('Zip', aHashes, this.downloadAsZipLoading); + Promises.attachmentsActions('Zip', aHashes, this.downloadAsZipLoading).then(function (oResult) { + if (oResult && oResult.Result && oResult.Result.Files && + oResult.Result.Files[0] && oResult.Result.Files[0].Hash) + { + require('App/User').download( + Links.attachmentDownload(oResult.Result.Files[0].Hash)); + } + else + { + self.downloadAsZipError(true); + } + }).fail(function () { + self.downloadAsZipError(true); + }); + } + else + { + this.highlightUnselectedAttachments(true); } }; MessageViewMailBoxUserView.prototype.saveToOwnCloud = function () { - var aHashes = this.getAttachmentsHashes(); + var self = this, aHashes = this.getAttachmentsHashes(); if (0 < aHashes.length) { - Promises.attachmentsActions('OwnCloud', aHashes, this.saveToOwnCloudLoading); + Promises.attachmentsActions('OwnCloud', aHashes, this.saveToOwnCloudLoading).then(function (oResult) { + if (oResult && oResult.Result) + { + self.saveToOwnCloudSuccess(true); + } + else + { + self.saveToOwnCloudError(true); + } + }).fail(function () { + self.saveToOwnCloudError(true); + }); + } + else + { + this.highlightUnselectedAttachments(true); } }; MessageViewMailBoxUserView.prototype.saveToDropbox = function () { - var aHashes = this.getAttachmentsHashes(); + var self = this, aFiles = [], aHashes = this.getAttachmentsHashes(); if (0 < aHashes.length) { - Promises.attachmentsActions('Dropbox', aHashes, this.saveToDropboxLoading); + if (window.Dropbox) + { + Promises.attachmentsActions('Dropbox', aHashes, this.saveToDropboxLoading).then(function (oResult) { + if (oResult && oResult.Result && oResult.Result.Url && oResult.Result.ShortLife && oResult.Result.Files) + { + if (window.Dropbox && Utils.isArray(oResult.Result.Files)) + { + _.each(oResult.Result.Files, function (oItem) { + aFiles.push({ + 'url': oResult.Result.Url + + Links.attachmentDownload(oItem.Hash, oResult.Result.ShortLife), + 'filename': oItem.FileName + }); + }); + + window.Dropbox.save({ + 'files': aFiles, + 'progress': function () { + self.saveToDropboxLoading(true); + self.saveToDropboxError(false); + self.saveToDropboxSuccess(false); + }, + 'cancel': function () { + self.saveToDropboxSuccess(false); + self.saveToDropboxError(false); + self.saveToDropboxLoading(false); + }, + 'success': function () { + self.saveToDropboxSuccess(true); + self.saveToDropboxLoading(false); + }, + 'error': function () { + self.saveToDropboxError(true); + self.saveToDropboxLoading(false); + } + }); + } + else + { + self.saveToDropboxError(true); + } + } + }).fail(function () { + self.saveToDropboxError(true); + }); + } + } + else + { + this.highlightUnselectedAttachments(true); } }; @@ -1194,6 +1189,8 @@ { oMessage.showExternalImages(true); } + + this.checkHeaderHeight(); }; /** @@ -1205,29 +1202,6 @@ return 0 < iCnt ? (100 > iCnt ? iCnt : '99+') : ''; }; - - /** - * @param {MessageModel} oMessage - */ - MessageViewMailBoxUserView.prototype.verifyPgpSignedClearMessage = function (oMessage) - { - if (oMessage) - { - oMessage.verifyPgpSignedClearMessage(); - } - }; - - /** - * @param {MessageModel} oMessage - */ - MessageViewMailBoxUserView.prototype.decryptPgpEncryptedMessage = function (oMessage) - { - if (oMessage) - { - oMessage.decryptPgpEncryptedMessage(this.viewPgpPassword()); - } - }; - /** * @param {MessageModel} oMessage */ @@ -1246,6 +1220,8 @@ require('App/User').reloadFlagsCurrentMessageListAndMessageFromCache(); } + + this.checkHeaderHeight(); }; module.exports = MessageViewMailBoxUserView; diff --git a/dev/bootstrap.js b/dev/bootstrap.js index d88505169..b15af81a6 100644 --- a/dev/bootstrap.js +++ b/dev/bootstrap.js @@ -23,7 +23,6 @@ Globals.$win .keydown(Utils.kill_CtrlA_CtrlS) - .keyup(Utils.kill_CtrlA_CtrlS) .unload(function () { Globals.bUnload = true; }) @@ -82,7 +81,7 @@ } window['__APP_BOOT'] = null; - + }, 10)); }; diff --git a/gulpfile.js b/gulpfile.js index 4612b4f6d..e6ebe3b55 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,11 +1,17 @@ -/* RainLoop Webmail (c) RainLoop Team | Licensed under CC BY-NC-SA 3.0 */ +/* RainLoop Webmail (c) RainLoop Team | Licensed under AGPL 3 */ 'use strict'; var pkg = require('./package.json'), + head = { + rainloop: '/* RainLoop Webmail (c) RainLoop Team | Licensed under RainLoop Software License */', + agpl: '/* RainLoop Webmail (c) RainLoop Team | Licensed under AGPL v3 */' + }, cfg = { devVersion: '0.0.0', releasesPath: 'build/dist/releases', + community: true, + watch: false, rainloopBuilded: false, destPath: '', @@ -25,20 +31,31 @@ var } }, + _ = require('lodash'), fs = require('node-fs'), path = require('path'), + notifier = require('node-notifier'), + gulp = require('gulp'), concat = require('gulp-concat-util'), header = require('gulp-header'), - eol = require('gulp-eol'), stripbom = require('gulp-stripbom'), rename = require('gulp-rename'), replace = require('gulp-replace'), uglify = require('gulp-uglify'), + notify = require("gulp-notify"), plumber = require('gulp-plumber'), + gulpif = require('gulp-if'), + eol = require('gulp-eol'), + livereload = require('gulp-livereload'), gutil = require('gulp-util') ; +function getHead() +{ + return !cfg.community ? head.rainloop : head.agpl; +} + function regOtherMinTask(sName, sPath, sInc, sOut, sHeader) { gulp.task(sName, function() { @@ -83,7 +100,10 @@ cfg.paths.less = { src: 'dev/Styles/@Main.less', watch: ['dev/Styles/*.less'], options: { - paths: [path.join(__dirname, 'dev/Styles/'), path.join(__dirname, 'vendors/bootstrap/less/')] + paths: [ + path.join(__dirname, 'dev', 'Styles'), + path.join(__dirname, 'vendors', 'bootstrap', 'less') + ] } } }; @@ -97,7 +117,8 @@ cfg.paths.css = { 'vendors/fontastic/styles.css', 'vendors/jquery-nanoscroller/nanoscroller.css', 'vendors/jquery-letterfx/jquery-letterfx.min.css', - 'vendors/simple-pace/styles.css', + 'vendors/progress.js/minified/progressjs.min.css', + 'vendors/progress.js/minified/progressjs.rainloop.css', 'vendors/inputosaurus/inputosaurus.css', 'vendors/opentip/opentip.css', 'vendors/photoswipe/photoswipe.css', @@ -114,14 +135,21 @@ cfg.paths.js = { src: [ 'vendors/json2.min.js', 'vendors/labjs/LAB.min.js', - 'vendors/simple-pace/simple-pace-1.0.min.js', + 'vendors/modernizr.js', + 'vendors/progress.js/minified/progress.min.js', 'vendors/rl/rl-1.5.min.js' ] }, openpgp: { - name: 'openpgp.js', + name: 'openpgp.min.js', src: [ - 'vendors/openpgp/openpgp-0.7.2.min.js' + 'vendors/openpgp/openpgp-0.10.1.min.js' + ] + }, + openpgpworker: { + name: 'openpgp.worker.min.js', + src: [ + 'vendors/openpgp/openpgp-0.10.1.worker.min.js' ] }, encrypt: { @@ -140,12 +168,9 @@ cfg.paths.js = { libs: { name: 'libs.js', src: [ - 'vendors/modernizr.js', 'vendors/underscore/1.6.0/underscore-min.js', - 'vendors/is.js/is.min.js', 'vendors/jquery/jquery-1.11.2.min.js', 'vendors/jquery-ui/js/jquery-ui-1.10.3.custom.min.js', -// 'vendors/jquery-ui.touch-punch/jquery.ui.touch-punch.min.js', 'vendors/jquery-cookie/jquery.cookie-1.4.0.min.js', 'vendors/jquery-finger/jquery.finger.min.js', 'vendors/jquery-mousewheel/jquery.mousewheel-3.1.4.min.js', @@ -163,7 +188,6 @@ cfg.paths.js = { 'vendors/routes/hasher.min.js', 'vendors/routes/crossroads.min.js', 'vendors/knockout/knockout-3.3.0.js', -// 'vendors/knockout-punches/knockout.punches.min.js', 'vendors/knockout-projections/knockout-projections-1.0.0.min.js', 'vendors/knockout-sortable/knockout-sortable.min.js', 'vendors/ssm/ssm.min.js', @@ -176,6 +200,7 @@ cfg.paths.js = { // 'vendors/jsencrypt/jsencrypt.min.js', 'vendors/keymaster/keymaster.min.js', 'vendors/ifvisible/ifvisible.min.js', +// 'vendors/svg4everybody/svg4everybody.js', 'vendors/bootstrap/js/bootstrap.min.js' ] }, @@ -190,14 +215,17 @@ cfg.paths.js = { // CSS gulp.task('less:main', function() { var less = require('gulp-less'); + return gulp.src(cfg.paths.less.main.src) + .pipe(gulpif(cfg.watch, plumber({errorHandler: notify.onError("Error: <%= error.message %>")}))) .pipe(less({ 'paths': cfg.paths.less.main.options.paths })) .pipe(rename(cfg.paths.less.main.name)) .pipe(eol('\n', true)) .pipe(gulp.dest(cfg.paths.staticCSS)) - .on('error', gutil.log); + .on('error', gutil.log) + ; }); gulp.task('css:main-begin', ['less:main'], function() { @@ -209,7 +237,6 @@ gulp.task('css:main-begin', ['less:main'], function() { ; return gulp.src(cfg.paths.css.main.src) - .pipe(plumber()) .pipe(concat(cfg.paths.css.main.name)) .pipe(autoprefixer('last 3 versions', '> 1%', 'ie 9', 'Firefox ESR', 'Opera 12.1')) // .pipe(csscomb()) @@ -217,9 +244,20 @@ gulp.task('css:main-begin', ['less:main'], function() { // .pipe(csslint.reporter()) .pipe(eol('\n', true)) .pipe(gulp.dest(cfg.paths.staticCSS)) + .pipe(livereload()) ; }); +gulp.task('package:community-on', function() { + cfg.community = true; + return true; +}); + +gulp.task('package:community-off', function() { + cfg.community = false; + return true; +}); + gulp.task('css:clear-less', ['css:main-begin'], function() { return gulp.src(cfg.paths.staticCSS + cfg.paths.less.main.name, {read: false}) @@ -231,7 +269,6 @@ gulp.task('css:main', ['css:clear-less']); gulp.task('css:main:min', ['css:main'], function() { var minifyCss = require('gulp-minify-css'); return gulp.src(cfg.paths.staticCSS + cfg.paths.css.main.name) - .pipe(plumber()) .pipe(minifyCss({ 'keepSpecialComments': 0 })) @@ -266,6 +303,13 @@ gulp.task('js:openpgp', function() { .pipe(gulp.dest(cfg.paths.staticMinJS)); }); +gulp.task('js:openpgpworker', function() { + return gulp.src(cfg.paths.js.openpgpworker.src) + .pipe(rename(cfg.paths.js.openpgpworker.name)) + .pipe(eol('\n', true)) + .pipe(gulp.dest(cfg.paths.staticMinJS)); +}); + gulp.task('js:libs', function() { return gulp.src(cfg.paths.js.libs.src) .pipe(concat(cfg.paths.js.libs.name, {separator: '\n\n'})) @@ -289,7 +333,8 @@ gulp.task('js:webpack:clear', function() { .pipe(require('gulp-rimraf')()); }); -gulp.task('js:webpack', ['js:webpack:clear'], function(callback) { +gulp.task('js:webpack', [/*'js:webpack:clear'*/], function(callback) { + var webpack = require('webpack'), webpackCfg = require('./webpack.config.js') @@ -300,18 +345,66 @@ gulp.task('js:webpack', ['js:webpack:clear'], function(callback) { webpackCfg.output.publicPath = cfg.paths.staticJS; } + if (webpackCfg && webpackCfg.plugins) + { + webpackCfg.plugins.push(new webpack.DefinePlugin({ + 'RL_COMMUNITY': !!cfg.community + })); + } + webpack(webpackCfg, function(err, stats) { - if (err) { - throw new gutil.PluginError('webpack', err); + + var + fN = function (err) { + if (err) + { + gutil.log('[webpack]', '---'); + gutil.log('[webpack]', err.error ? err.error.toString() : ''); + gutil.log('[webpack]', err.message || ''); + gutil.log('[webpack]', '---'); + + notifier.notify({ + 'sound': true, + 'title': 'webpack', + 'message': err.error ? err.error.toString() : err.message + }); + } + } + ; + + if (err) + { + if (cfg.watch) + { + fN(err); + } + else + { + throw new gutil.PluginError('webpack', err); + } } - gutil.log('[webpack]', stats.toString({})); + else if (stats && stats.compilation && stats.compilation.errors && + stats.compilation.errors[0]) + { + if (cfg.watch) + { + _.each(stats.compilation.errors, function (err) { + fN(err); + }); + } + else + { + throw new gutil.PluginError('webpack', stats.compilation.errors[0]); + } + } + callback(); }); }); gulp.task('js:app', ['js:webpack'], function() { return gulp.src(cfg.paths.staticJS + cfg.paths.js.app.name) - .pipe(header('/* RainLoop Webmail (c) RainLoop Team | Licensed under CC BY-NC-SA 3.0 */\n')) + .pipe(header(getHead() + '\n')) .pipe(eol('\n', true)) .pipe(gulp.dest(cfg.paths.staticJS)) .on('error', gutil.log); @@ -319,7 +412,7 @@ gulp.task('js:app', ['js:webpack'], function() { gulp.task('js:admin', ['js:webpack'], function() { return gulp.src(cfg.paths.staticJS + cfg.paths.js.admin.name) - .pipe(header('/* RainLoop Webmail (c) RainLoop Team | Licensed under CC BY-NC-SA 3.0 */\n')) + .pipe(header(getHead() + '\n')) .pipe(eol('\n', true)) .pipe(gulp.dest(cfg.paths.staticJS)) .on('error', gutil.log); @@ -327,7 +420,7 @@ gulp.task('js:admin', ['js:webpack'], function() { gulp.task('js:chunks', ['js:webpack'], function() { return gulp.src(cfg.paths.staticJS + '*.subapp.js') - .pipe(header('/* RainLoop Webmail (c) RainLoop Team | Licensed under CC BY-NC-SA 3.0 */\n')) + .pipe(header(getHead() + '\n')) .pipe(eol('\n', true)) .pipe(gulp.dest(cfg.paths.staticJS)) .on('error', gutil.log); @@ -338,7 +431,7 @@ gulp.task('js:min', ['js:app', 'js:admin', 'js:chunks'], function() { return gulp.src(cfg.paths.staticJS + '*.js') .pipe(replace(/"rainloop\/v\/([^\/]+)\/static\/js\/"/g, '"rainloop/v/$1/static/js/min/"')) .pipe(uglify(cfg.uglify)) - .pipe(header('/* RainLoop Webmail (c) RainLoop Team | Licensed under CC BY-NC-SA 3.0 */\n')) + .pipe(header(getHead() + '\n')) .pipe(eol('\n', true)) .pipe(gulp.dest(cfg.paths.staticMinJS)) .on('error', gutil.log); @@ -402,12 +495,21 @@ gulp.task('fontastic-fonts:clear', function() { return cleanDir('rainloop/v/' + cfg.devVersion + '/static/css/fonts/rainloop.*'); }); +gulp.task('fontastic-svg:clear', function() { + return cleanDir('rainloop/v/' + cfg.devVersion + '/static/css/svg/*.svg'); +}); + gulp.task('fontastic-fonts:copy', ['fontastic-fonts:clear'], function() { return gulp.src('vendors/fontastic/fonts/rainloop.*') .pipe(gulp.dest('rainloop/v/' + cfg.devVersion + '/static/css/fonts')); }); -gulp.task('fontastic', ['fontastic-fonts:copy']); +gulp.task('fontastic-svg:copy', ['fontastic-svg:clear'], function() { + return gulp.src('vendors/fontastic/svg/*.svg') + .pipe(gulp.dest('rainloop/v/' + cfg.devVersion + '/static/css/svg')); +}); + +gulp.task('fontastic', ['fontastic-fonts:copy', 'fontastic-svg:copy']); gulp.task('ckeditor:clear', function() { return cleanDir('rainloop/v/' + cfg.devVersion + '/static/ckeditor'); @@ -426,7 +528,6 @@ gulp.task('ckeditor:copy-plugins', ['ckeditor:copy'], function() { gulp.task('ckeditor', ['ckeditor:copy-plugins'], function () { return gulp.src('rainloop/v/' + cfg.devVersion + '/static/ckeditor/*.js') .pipe(stripbom()) -// .pipe(replace("\u200B", "\\u200B")) .pipe(replace('console.log("Detecting changes using MutationObservers")', 'true')) .pipe(header("\uFEFF")) // BOM .pipe(gulp.dest('rainloop/v/' + cfg.devVersion + '/static/ckeditor')); @@ -463,10 +564,15 @@ gulp.task('rainloop:setup', ['rainloop:copy'], function() { fs.writeFileSync(dist + 'rainloop/v/' + versionFull + '/index.php.root', fs.readFileSync(dist + 'index.php')); + if (cfg.community) + { + require('rimraf').sync(dist + 'rainloop/v/' + versionFull + '/app/libraries/RainLoop/Prem/'); + } + cfg.destPath = cfg.releasesPath + '/webmail/' + versionFull + '/'; cfg.cleanPath = dist; cfg.zipSrcPath = dist; - cfg.zipFile = 'rainloop-' + versionFull + '.zip'; + cfg.zipFile = 'rainloop-' + (cfg.community ? 'community-' : '') + versionFull + '.zip'; cfg.md5File = cfg.zipFile; cfg.rainloopBuilded = true; @@ -530,7 +636,10 @@ gulp.task('rainloop:owncloud:setup', ['rainloop:owncloud:copy', ; fs.writeFileSync(dist + 'rainloop/appinfo/info.xml', - fs.readFileSync(dist + 'rainloop/appinfo/info.xml', 'utf8').replace('0.0', '' + versionFull + '')); + fs.readFileSync(dist + 'rainloop/appinfo/info.xml', 'utf8') + .replace('0.0', '' + versionFull + '') + .replace('', '' + (cfg.community ? 'AGPLv3' : 'RainLoop Software License') + '') + ); fs.writeFileSync(dist + 'rainloop/appinfo/version', versionFull); fs.writeFileSync(dist + 'rainloop/VERSION', versionFull); @@ -538,7 +647,7 @@ gulp.task('rainloop:owncloud:setup', ['rainloop:owncloud:copy', cfg.destPath = cfg.releasesPath + '/owncloud/' + versionFull + '/'; cfg.cleanPath = dist; cfg.zipSrcPath = dist; - cfg.zipFile = 'rainloop-owncloud-app-' + versionFull + '.zip'; + cfg.zipFile = 'rainloop-owncloud-app-' + (cfg.community ? '' : 'standard-') + versionFull + '.zip'; cfg.md5File = cfg.zipFile; }); @@ -558,30 +667,56 @@ gulp.task('rainloop:owncloud:clean', ['rainloop:owncloud:copy', 'rainloop:ownclo }); // MAIN -gulp.task('default', ['js:libs', 'js:boot', 'js:openpgp', 'js:min', 'css:main:min', 'ckeditor', 'fontastic']); -gulp.task('fast', ['js:app', 'js:admin', 'js:chunks', 'css:main']); +gulp.task('default', ['js:libs', 'js:boot', 'js:openpgp', 'js:openpgpworker', 'js:min', 'css:main:min', 'ckeditor', 'fontastic']); +gulp.task('fast-', ['js:app', 'js:admin', 'js:chunks', 'css:main']); + +gulp.task('fast', ['package:community-on', 'fast-']); +gulp.task('fast+', ['package:community-off', 'fast-']); gulp.task('rainloop:start', ['js:lint', 'rainloop:copy', 'rainloop:setup']); -gulp.task('rainloop', ['rainloop:start', 'rainloop:zip', 'rainloop:md5', 'rainloop:clean']); -gulp.task('owncloud', ['rainloop:owncloud:copy', +gulp.task('rainloop-', ['rainloop:start', 'rainloop:zip', 'rainloop:md5', 'rainloop:clean']); + +gulp.task('rainloop', ['package:community-on', 'rainloop-']); +gulp.task('rainloop+', ['package:community-off', 'rainloop-']); + +gulp.task('owncloud-', ['rainloop:owncloud:copy', 'rainloop:owncloud:copy-rainloop', 'rainloop:owncloud:copy-rainloop:clean', 'rainloop:owncloud:setup', 'rainloop:owncloud:zip', 'rainloop:owncloud:md5', 'rainloop:owncloud:clean']); +gulp.task('owncloud', ['package:community-on', 'owncloud-']); +gulp.task('owncloud+', ['package:community-off', 'owncloud-']); + //WATCH gulp.task('watch', ['fast'], function() { - gulp.watch(cfg.paths.globjs, {interval: 500}, ['js:app', 'js:admin']); - gulp.watch(cfg.paths.less.main.watch, {interval: 500}, ['css:main']); + cfg.watch = true; + livereload.listen(); + gulp.watch(cfg.paths.globjs, {interval: 1000}, ['js:app', 'js:admin']); + gulp.watch(cfg.paths.less.main.watch, {interval: 1000}, ['css:main']); +}); + +gulp.task('watch+', ['fast+'], function() { + cfg.watch = true; + livereload.listen(); + gulp.watch(cfg.paths.globjs, {interval: 1000}, ['js:app', 'js:admin']); + gulp.watch(cfg.paths.less.main.watch, {interval: 1000}, ['css:main']); }); // ALIASES gulp.task('build', ['rainloop']); +gulp.task('build+', ['rainloop+']); gulp.task('js:hint', ['js:lint']); -gulp.task('own', ['owncloud']); -gulp.task('rl', ['rainloop']); gulp.task('w', ['watch']); +gulp.task('w+', ['watch+']); gulp.task('f', ['fast']); -gulp.task('o', ['owncloud']); +gulp.task('f+', ['fast+']); + gulp.task('b', ['build']); -gulp.task('h', ['js:lint']); \ No newline at end of file +gulp.task('b+', ['build+']); + +gulp.task('o', ['owncloud']); +gulp.task('o+', ['owncloud+']); + +gulp.task('h', ['js:lint']); +gulp.task('l', ['js:lint']); \ No newline at end of file diff --git a/package.json b/package.json index 66ced8835..918f2d74e 100644 --- a/package.json +++ b/package.json @@ -1,75 +1,79 @@ { - "name": "RainLoop", - "title": "RainLoop Webmail", - "version": "1.8.3", - "release": "302", - "description": "Simple, modern & fast web-based email client", - "homepage": "http://rainloop.net", - "main": "gulpfile.js", - "author": { - "name": "RainLoop Team", - "email": "support@rainloop.net", - "web": "http://rainloop.net" - }, - "repository": { - "type": "git", - "url": "git://github.com/RainLoop/rainloop-webmail.git" - }, - "licenses": [ - { - "type": "CC BY-NC-SA 3.0", - "ulr": "http://creativecommons.org/licenses/by-nc-sa/3.0/" - } - ], - "bugs": { - "url": "https://github.com/RainLoop/rainloop-webmail/issues" - }, - "keywords": [ - "webmail", - "php", - "simple", - "modern", - "mail", - "web-based", - "email", - "client", - "plugins" - ], - "readmeFilename": "README.md", - "ownCloudPackageVersion": "3.3", - "engines": { - "node": ">= 0.10.0" - }, - "devDependencies": { - - "node-fs": "*", - "jshint-summary": "*", - - "webpack": "*", - - "gulp": "*", - "gulp-util": "*", - "gulp-uglify": "*", - "gulp-rimraf": "*", - "gulp-jshint": "*", - "gulp-less": "1.3.6", - "gulp-zip": "*", - "gulp-rename": "*", - "gulp-replace": "*", - "gulp-header": "*", - "gulp-eol": "*", - "gulp-stripbom": "*", - "gulp-minify-css": "*", - "gulp-autoprefixer": "*", - "gulp-csscomb": "*", - "gulp-closure-compiler": "*", - "gulp-csslint": "*", - "gulp-beautify": "*", - "gulp-plumber": "*", - "gulp-concat-util": "*" - }, - "scripts": { - "gulp": "gulp", - "w": "gulp w" - } + "name": "RainLoop", + "title": "RainLoop Webmail", + "version": "1.9.2", + "release": "343", + "description": "Simple, modern & fast web-based email client", + "homepage": "http://rainloop.net", + "main": "gulpfile.js", + "author": { + "name": "RainLoop Team", + "email": "support@rainloop.net", + "web": "http://rainloop.net" + }, + "repository": { + "type": "git", + "url": "git://github.com/RainLoop/rainloop-webmail.git" + }, + "licenses": [ + { + "type": "AGPL 3.0", + "ulr": "http://www.gnu.org/licenses/agpl-3.0.html" + }, + { + "type": "RainLoop Software License", + "ulr": "http://www.rainloop.net/licensing/" + } + ], + "bugs": { + "url": "https://github.com/RainLoop/rainloop-webmail/issues" + }, + "keywords": [ + "webmail", + "php", + "simple", + "modern", + "mail", + "web-based", + "email", + "client", + "plugins" + ], + "readmeFilename": "README.md", + "ownCloudPackageVersion": "4.4", + "engines": { + "node": ">= 0.10.0" + }, + "devDependencies": { + "node-fs": "*", + "rimraf": "*", + "jshint-summary": "*", + "webpack": "*", + "gulp": "*", + "gulp-util": "*", + "gulp-uglify": "*", + "gulp-rimraf": "*", + "gulp-jshint": "*", + "gulp-less": "1.3.6", + "gulp-zip": "*", + "gulp-rename": "*", + "gulp-replace": "*", + "gulp-header": "*", + "gulp-eol": "*", + "gulp-stripbom": "*", + "gulp-minify-css": "*", + "gulp-autoprefixer": "*", + "gulp-csscomb": "*", + "gulp-closure-compiler": "*", + "gulp-csslint": "*", + "gulp-beautify": "*", + "gulp-plumber": "*", + "gulp-concat-util": "*", + "gulp-notify": "~2.2.0", + "gulp-through": "~0.3.0", + "lodash": "~3.9.3", + "gulp-if": "~1.2.5", + "node-notifier": "~4.2.3", + "gulp-livereload": "~3.8.0" + } } diff --git a/vendors/is.js/LICENSE b/plugins/virtualmin-change-password/LICENSE similarity index 96% rename from vendors/is.js/LICENSE rename to plugins/virtualmin-change-password/LICENSE index 077f5b9d3..c364cecf0 100644 --- a/vendors/is.js/LICENSE +++ b/plugins/virtualmin-change-password/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2015 Aras Atasaygin +Copyright (c) 2015 icedman21 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/plugins/virtualmin-change-password/README b/plugins/virtualmin-change-password/README new file mode 100644 index 000000000..58f2e0378 --- /dev/null +++ b/plugins/virtualmin-change-password/README @@ -0,0 +1 @@ +This plugin utilizes Virtualmin's remote API to change user passwords. The plugin requires the Admin user name and password to succesfully execute the password change. The host and port where Virtualmin listens on is also needed. See https://www.virtualmin.com/documentation/developer/http for more information. \ No newline at end of file diff --git a/plugins/virtualmin-change-password/VERSION b/plugins/virtualmin-change-password/VERSION new file mode 100644 index 000000000..9f8e9b69a --- /dev/null +++ b/plugins/virtualmin-change-password/VERSION @@ -0,0 +1 @@ +1.0 \ No newline at end of file diff --git a/plugins/virtualmin-change-password/VirtualminChangePasswordDriver.php b/plugins/virtualmin-change-password/VirtualminChangePasswordDriver.php new file mode 100644 index 000000000..c4fbd72d6 --- /dev/null +++ b/plugins/virtualmin-change-password/VirtualminChangePasswordDriver.php @@ -0,0 +1,210 @@ +sHost = $sHost; + $this->sAdminUser = $sAdminUser; + $this->sAdminPassword = $sAdminPassword; + + return $this; + } + + /** + * @param string $sAllowedEmails + * + * @return \VirtualminChangePasswordDriver + */ + public function SetAllowedEmails($sAllowedEmails) + { + $this->sAllowedEmails = $sAllowedEmails; + + return $this; + } + + /** + * @param \MailSo\Log\Logger $oLogger + * + * @return \VirtualminChangePasswordDriver + */ + public function SetLogger($oLogger) + { + if ($oLogger instanceof \MailSo\Log\Logger) + { + $this->oLogger = $oLogger; + } + + return $this; + } + + /** + * @param string $sDesc + * @param int $iType = \MailSo\Log\Enumerations\Type::INFO + * + * @return \VirtualminChangePasswordDriver + */ + public function WriteLog($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO) + { + if ($this->oLogger) + { + $this->oLogger->Write($sDesc, $iType); + } + + return $this; + } + + /** + * @param \RainLoop\Model\Account $oAccount + * + * @return bool + */ + public function PasswordChangePossibility($oAccount) + { + return $oAccount && $oAccount->Email() && + \RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->sAllowedEmails); + } + + /** + * @param \RainLoop\Model\Account $oAccount + * @param string $sPrevPassword + * @param string $sNewPassword + * + * @return bool + */ + public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) + { + $this->WriteLog('Virtualmin: Try to change password for '.$oAccount->Email()); + + $bResult = false; + if (!empty($this->sHost) && !empty($this->sAdminUser) && !empty($this->sAdminPassword) && $oAccount) + { + $this->WriteLog('Virtualmin:[Check] Required Fields Present'); + + $sEmail = \trim(\strtolower($oAccount->Email())); + $sEmailUser = \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail); + $sEmailDomain = \MailSo\Base\Utils::GetDomainFromEmail($sEmail); + + $sHost = \rtrim(\trim($this->sHost), '/'); + $sUrl = $sHost.'/virtual-server/remote.cgi'; + + $sAdminUser = $this->sAdminUser; + $sAdminPassword = $this->sAdminPassword; + + $iCode = 0; + + $aPost = array( + 'user' => $sEmailUser, + 'pass' => $sNewPassword, + 'domain' => $sEmailDomain, + 'program' => 'modify-user' + ); + + $aOptions = array( + CURLOPT_URL => $sUrl, + CURLOPT_HEADER => false, + CURLOPT_FAILONERROR => true, + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => \http_build_query($aPost, '', '&'), + CURLOPT_TIMEOUT => 20, + CURLOPT_SSL_VERIFYHOST => false, + CURLOPT_USERPWD => $sAdminUser.':'.$sAdminPassword + ); + + $oCurl = \curl_init(); + \curl_setopt_array($oCurl, $aOptions); + + $this->WriteLog('Virtualmin: Send post request: '.$sUrl); + + $mResult = \curl_exec($oCurl); + + $iCode = (int) \curl_getinfo($oCurl, CURLINFO_HTTP_CODE); + $sContentType = (string) \curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE); + + $this->WriteLog('Virtualmin: Post request result: (Status: '.$iCode.', ContentType: '.$sContentType.')'); + if (false === $mResult || 200 !== $iCode) + { + $this->WriteLog('Virtualmin: Error: '.\curl_error($oCurl), \MailSo\Log\Enumerations\Type::WARNING); + } + + if (\is_resource($oCurl)) + { + \curl_close($oCurl); + } + + if (false !== $mResult && 200 === $iCode) + { + $aRes = null; + @\parse_str($mResult, $aRes); + if (\is_array($aRes) && (!isset($aRes['error']) || (int) $aRes['error'] !== 1)) + { + $iPos = \strpos($mResult, 'Exit status: '); + + if ($iPos !== false) + { + $aStatus = \explode(' ', $mResult); + $sStatus = \trim(\array_pop($aStatus)); + + if ('0' === $sStatus) + { + $this->WriteLog('Virtualmin: Password Change Status: Success'); + $bResult = true; + } + else + { + $this->WriteLog('Virtualmin[Error]: Response: '.$mResult); + } + } + } + else + { + $this->WriteLog('Virtualmin[Error]: Response: '.$mResult); + } + } + else + { + $this->WriteLog('Virtualmin[Error]: Empty Response: Code: '.$iCode); + } + } + + return $bResult; + } +} diff --git a/plugins/virtualmin-change-password/index.php b/plugins/virtualmin-change-password/index.php new file mode 100644 index 000000000..b4c0a86f6 --- /dev/null +++ b/plugins/virtualmin-change-password/index.php @@ -0,0 +1,54 @@ +addHook('main.fabrica', 'MainFabrica'); + } + + /** + * @param string $sName + * @param mixed $oProvider + */ + public function MainFabrica($sName, &$oProvider) + { + switch ($sName) + { + case 'change-password': + + include_once __DIR__.'/VirtualminChangePasswordDriver.php'; + + $sHost = \trim($this->Config()->Get('plugin', 'host', '')); + $sAdminUser = (string) $this->Config()->Get('plugin', 'admin_user', ''); + $sAdminPassword = (string) $this->Config()->Get('plugin', 'admin_password', ''); + + $oProvider = new \VirtualminChangePasswordDriver(); + $oProvider->SetLogger($this->Manager()->Actions()->Logger()); + $oProvider->SetConfig($sHost, $sAdminUser, $sAdminPassword); + $oProvider->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', '')))); + + break; + } + } + + /** + * @return array + */ + public function configMapping() + { + return array( + \RainLoop\Plugins\Property::NewInstance('host')->SetLabel('Virtualmin Host') + ->SetDefaultValue('https://localhost:10000') + ->SetDescription('Virtualmin host URL. Example: https://example.com:10000'), + \RainLoop\Plugins\Property::NewInstance('admin_user')->SetLabel('Admin User') + ->SetDefaultValue(''), + \RainLoop\Plugins\Property::NewInstance('admin_password')->SetLabel('Admin Password') + ->SetDefaultValue(''), + \RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails') + ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) + ->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net') + ->SetDefaultValue('*') + ); + } +} diff --git a/plugins/vpopmail-change-password/ChangePasswordVpopmailDriver.php b/plugins/vpopmail-change-password/ChangePasswordVpopmailDriver.php new file mode 100755 index 000000000..7013d226e --- /dev/null +++ b/plugins/vpopmail-change-password/ChangePasswordVpopmailDriver.php @@ -0,0 +1,228 @@ +mHost = $mHost; + return $this; + } + + /** + * @param string $mUser + * + * @return \ChangePasswordVpopmailDriver + */ + public function SetmUser($mUser) + { + $this->mUser = $mUser; + return $this; + } + + /** + * @param string $mPass + * + * @return \ChangePasswordVpopmailDriver + */ + public function SetmPass($mPass) + { + $this->mPass = $mPass; + return $this; + } + + /** + * @param string $mDatabase + * + * @return \ChangePasswordVpopmailDriver + */ + public function SetmDatabase($mDatabase) + { + $this->mDatabase = $mDatabase; + return $this; + } + + /** + * @param string $mTable + * + * @return \ChangePasswordVpopmailDriver + */ + public function SetmTable($mTable) + { + $this->mTable = $mTable; + return $this; + } + + /** + * @param string $mColumn + * + * @return \ChangePasswordVpopmailDriver + */ + public function SetmColumn($mColumn) + { + $this->mColumn = $mColumn; + return $this; + } + + /** + * @param \MailSo\Log\Logger $oLogger + * + * @return \ChangePasswordVpopmailDriver + */ + public function SetLogger($oLogger) + { + if ($oLogger instanceof \MailSo\Log\Logger) + { + $this->oLogger = $oLogger; + } + + return $this; + } + + /** + * @param array $aDomains + * + * @return bool + */ + public function SetAllowedDomains($aDomains) + { + if (\is_array($aDomains) && 0 < \count($aDomains)) + { + $this->aDomains = $aDomains; + } + + return $this; + } + + /** + * @param \RainLoop\Account $oAccount + * + * @return bool + */ + public function PasswordChangePossibility($oAccount) + { + return 0 === \count($this->aDomains) || ($oAccount && \in_array(\strtolower( + \MailSo\Base\Utils::GetDomainFromEmail($oAccount->Email)), $this->aDomains)); + } + + /** + * @param \RainLoop\Account $oAccount + * @param string $sPrevPassword + * @param string $sNewPassword + * + * @return bool + */ + public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) + { + if ($this->oLogger) + { + $this->oLogger->Write('Try to change password for '.$oAccount->Email()); + } + + if (empty($this->mHost) || empty($this->mDatabase) || empty($this->mColumn) || empty($this->mTable)) + { + return false; + } + + $bResult = false; + + $sDsn = 'mysql:host='.$this->mHost.';dbname='.$this->mDatabase.';charset=utf8'; + $aOptions = array( + PDO::ATTR_EMULATE_PREPARES => false, + PDO::ATTR_PERSISTENT => true, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION + ); + + $sLoginPart = \MailSo\Base\Utils::GetAccountNameFromEmail($oAccount->Email()); + $sDomainPart = \MailSo\Base\Utils::GetDomainFromEmail($oAccount->Email()); + + try + { + $oConn = new PDO($sDsn, $this->mUser, $this->mPass, $aOptions); + + $oSelect = $oConn->prepare('SELECT '.$this->mColumn.' FROM '.$this->mTable.' WHERE pw_name=? AND pw_domain=? LIMIT 1'); + $oSelect->execute(array($sLoginPart, $sDomainPart)); + + $aColCrypt = $oSelect->fetchAll(PDO::FETCH_ASSOC); + + $sCryptPass = isset($aColCrypt[0][$this->mColumn]) ? $aColCrypt[0][$this->mColumn] : ''; + if (0 < \strlen($sCryptPass) && \crypt($sPrevPassword, $sCryptPass) === $sCryptPass) + { + $oUpdate = $oConn->prepare('UPDATE '.$this->mTable.' SET '.$this->mColumn.'=ENCRYPT(?,concat("$1$",right(md5(rand()), 8 ),"$")), pw_clear_passwd=\'\' WHERE pw_name=? AND pw_domain=?'); + $oUpdate->execute(array( + $sNewPassword, + $sLoginPart, + $sDomainPart + )); + + $bResult = true; + if ($this->oLogger) + { + $this->oLogger->Write('Success! Password changed.'); + } + } + else + { + $bResult = false; + if ($this->oLogger) + { + $this->oLogger->Write('Something went wrong. Either current password is incorrect, or new password does not match criteria.'); + } + } + } + catch (\Exception $oException) + { + $bResult = false; + if ($this->oLogger) + { + $this->oLogger->WriteException($oException); + } + } + + return $bResult; + } +} diff --git a/vendors/jquery-magnific-popup/LICENSE b/plugins/vpopmail-change-password/LICENSE old mode 100644 new mode 100755 similarity index 94% rename from vendors/jquery-magnific-popup/LICENSE rename to plugins/vpopmail-change-password/LICENSE index f6ea3a9d4..6739d4b4e --- a/vendors/jquery-magnific-popup/LICENSE +++ b/plugins/vpopmail-change-password/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Dmitry Semenov, http://dimsemenov.com +Copyright (c) 2015 Almas at Dusal.net Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/plugins/vpopmail-change-password/VERSION b/plugins/vpopmail-change-password/VERSION new file mode 100755 index 000000000..9459d4ba2 --- /dev/null +++ b/plugins/vpopmail-change-password/VERSION @@ -0,0 +1 @@ +1.1 diff --git a/plugins/vpopmail-change-password/index.php b/plugins/vpopmail-change-password/index.php new file mode 100755 index 000000000..8eb5fd5fe --- /dev/null +++ b/plugins/vpopmail-change-password/index.php @@ -0,0 +1,71 @@ +addHook('main.fabrica', 'MainFabrica'); + } + + /** + * @param string $sName + * @param mixed $oProvider + */ + public function MainFabrica($sName, &$oProvider) + { + switch ($sName) + { + case 'change-password': + + include_once __DIR__.'/ChangePasswordVpopmailDriver.php'; + + $oProvider = new ChangePasswordVpopmailDriver(); + + $sDomains = \strtolower(\trim(\preg_replace('/[\s;,]+/', ' ', + $this->Config()->Get('plugin', 'domains', '')))); + + if (0 < \strlen($sDomains)) + { + $aDomains = \explode(' ', $sDomains); + $oProvider->SetAllowedDomains($aDomains); + } + + $oProvider + ->SetLogger($this->Manager()->Actions()->Logger()) + ->SetmHost($this->Config()->Get('plugin', 'mHost', '')) + ->SetmUser($this->Config()->Get('plugin', 'mUser', '')) + ->SetmPass($this->Config()->Get('plugin', 'mPass', '')) + ->SetmDatabase($this->Config()->Get('plugin', 'mDatabase', '')) + ->SetmTable($this->Config()->Get('plugin', 'mTable', '')) + ->SetmColumn($this->Config()->Get('plugin', 'mColumn', '')) + ; + + break; + } + } + + /** + * @return array + */ + public function configMapping() + { + return array( + \RainLoop\Plugins\Property::NewInstance('domains')->SetLabel('Allowed Domains') + ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) + ->SetDescription('Allowed domains, space as delimiter') + ->SetDefaultValue('gmail.com yahoo.com'), + \RainLoop\Plugins\Property::NewInstance('mHost')->SetLabel('MySQL Host') + ->SetDefaultValue('localhost'), + \RainLoop\Plugins\Property::NewInstance('mUser')->SetLabel('MySQL User') + ->SetDefaultValue('vpopmail'), + \RainLoop\Plugins\Property::NewInstance('mPass')->SetLabel('MySQL Password') + ->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD), + \RainLoop\Plugins\Property::NewInstance('mDatabase')->SetLabel('MySQL Database') + ->SetDefaultValue('vpopmail'), + \RainLoop\Plugins\Property::NewInstance('mTable')->SetLabel('MySQL Table') + ->SetDefaultValue('vpopmail'), + \RainLoop\Plugins\Property::NewInstance('mColumn')->SetLabel('MySQL Column') + ->SetDefaultValue('pw_passwd') + ); + } +} diff --git a/rainloop/v/0.0.0/app/handle.php b/rainloop/v/0.0.0/app/handle.php index ebb703d10..464a43e3d 100644 --- a/rainloop/v/0.0.0/app/handle.php +++ b/rainloop/v/0.0.0/app/handle.php @@ -22,7 +22,7 @@ if (!\defined('RAINLOOP_APP_LIBRARIES_PATH')) function rainLoopSplAutoloadNamespaces() { return RAINLOOP_INCLUDE_AS_API_DEF ? array('RainLoop') : - array('RainLoop', 'Facebook', 'GuzzleHttp', 'Symfony', 'PHPThumb', 'Sabre'); + array('RainLoop', 'Facebook', 'GuzzleHttp', 'PHPThumb', 'SabreForRainLoop'); } /** @@ -41,7 +41,7 @@ if (!\defined('RAINLOOP_APP_LIBRARIES_PATH')) { if (0 === \strpos($sClassName, $sNamespaceName.'\\')) { - if ('Sabre' === $sNamespaceName && !RAINLOOP_MB_SUPPORTED && !defined('RL_MB_FIXED')) + if ('SabreForRainLoop' === $sNamespaceName && !RAINLOOP_MB_SUPPORTED && !defined('RL_MB_FIXED')) { \define('RL_MB_FIXED', true); include_once RAINLOOP_APP_LIBRARIES_PATH.'RainLoop/Common/MbStringFix.php'; @@ -59,7 +59,7 @@ if (!\defined('RAINLOOP_APP_LIBRARIES_PATH')) if (\class_exists('RainLoop\Api')) { - if (!\class_exists('MailSo\Version')) + if (!\class_exists('MailSo\Version', false)) { include APP_VERSION_ROOT_PATH.'app/libraries/MailSo/MailSo.php'; } diff --git a/rainloop/v/0.0.0/app/i18n/langs.ini b/rainloop/v/0.0.0/app/i18n/langs.ini index 9f19d3d74..88bea1b60 100644 --- a/rainloop/v/0.0.0/app/i18n/langs.ini +++ b/rainloop/v/0.0.0/app/i18n/langs.ini @@ -104,6 +104,9 @@ LANG_BS = "Bosanski" LANG_BS_BS = "Bosanski" LANG_BS_BA = "Bosanski" +LANG_AR = "‏العربية‏" +LANG_AR_AR = "‏العربية‏" + [LANGS_NAMES_EN] LANG_EN = "English" LANG_EN_US = "English (US)" @@ -210,3 +213,6 @@ LANG_SR_RS = "Serbian" LANG_BS = "Bosnian" LANG_BS_BS = "Bosnian" LANG_BS_BA = "Bosnian" + +LANG_AR = "Arabic" +LANG_AR_AR = "Arabic" diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Base/DateTimeHelper.php b/rainloop/v/0.0.0/app/libraries/MailSo/Base/DateTimeHelper.php index 5896a536b..5ab334e6e 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Base/DateTimeHelper.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Base/DateTimeHelper.php @@ -49,7 +49,13 @@ class DateTimeHelper */ public static function ParseRFC2822DateString($sDateTime) { - $sDateTime = \trim(\preg_replace('/ \([a-zA-Z0-9]+\)$/', '', \trim($sDateTime))); + $sDateTime = \trim($sDateTime); + if (empty($sDateTime)) + { + return 0; + } + + $sDateTime = \trim(\preg_replace('/ \([a-zA-Z0-9]+\)$/', '', $sDateTime)); $oDateTime = \DateTime::createFromFormat('D, d M Y H:i:s O', $sDateTime, \MailSo\Base\DateTimeHelper::GetUtcTimeZoneObject()); return $oDateTime ? $oDateTime->getTimestamp() : 0; } @@ -65,7 +71,12 @@ class DateTimeHelper public static function ParseInternalDateString($sDateTime) { $sDateTime = \trim($sDateTime); - if (\preg_match('/^[a-z]{2,4}, /i', $sDateTime)) // RFC2822 + if (empty($sDateTime)) + { + return 0; + } + + if (\preg_match('/^[a-z]{2,4}, /i', $sDateTime)) // RFC2822 ~ "Thu, 10 Jun 2010 08:58:33 -0700 (PDT)" { return \MailSo\Base\DateTimeHelper::ParseRFC2822DateString($sDateTime); } @@ -83,7 +94,30 @@ class DateTimeHelper */ public static function ParseDateStringType1($sDateTime) { - $oDateTime = \DateTime::createFromFormat('Y-m-d H:i:s O', \trim($sDateTime), \MailSo\Base\DateTimeHelper::GetUtcTimeZoneObject()); + $sDateTime = \trim($sDateTime); + if (empty($sDateTime)) + { + return 0; + } + + $oDateTime = \DateTime::createFromFormat('Y-m-d H:i:s O', $sDateTime, \MailSo\Base\DateTimeHelper::GetUtcTimeZoneObject()); return $oDateTime ? $oDateTime->getTimestamp() : 0; } + + /** + * Parse date string formated as "2015-05-08T14:32:18.483-07:00" + * + * @param string $sDateTime + * + * @return int + */ + public static function TryToParseSpecEtagFormat($sDateTime) + { + $sDateTime = \trim(\preg_replace('/ \([a-zA-Z0-9]+\)$/', '', \trim($sDateTime))); + $sDateTime = \trim(\preg_replace('/(:[\d]{2})\.[\d]{3}/', '$1', \trim($sDateTime))); + $sDateTime = \trim(\preg_replace('/(-[\d]{2})T([\d]{2}:)/', '$1 $2', \trim($sDateTime))); + $sDateTime = \trim(\preg_replace('/([\-+][\d]{2}):([\d]{2})$/', ' $1$2', \trim($sDateTime))); + + return \MailSo\Base\DateTimeHelper::ParseDateStringType1($sDateTime); + } } diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Enumerations/Charset.php b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Enumerations/Charset.php index 8b09686e3..85132e6ea 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Enumerations/Charset.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Enumerations/Charset.php @@ -34,4 +34,5 @@ class Charset const ISO_8859_8 = 'iso-8859-8'; const ISO_8859_8_I = 'iso-8859-8-i'; const ISO_2022_JP = 'iso-2022-jp'; + const CP858 = 'cp858'; } diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Base/HtmlUtils.php b/rainloop/v/0.0.0/app/libraries/MailSo/Base/HtmlUtils.php index 243019693..bb9a2e419 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Base/HtmlUtils.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Base/HtmlUtils.php @@ -35,23 +35,32 @@ class HtmlUtils */ public static function GetDomFromText($sText, $sHtmlAttrs = '', $sBodyAttrs = '') { - static $bOnce = true; - if ($bOnce) + $bState = true; + if (\MailSo\Base\Utils::FunctionExistsAndEnabled('libxml_use_internal_errors')) { - $bOnce = false; - if (\MailSo\Base\Utils::FunctionExistsAndEnabled('libxml_use_internal_errors')) - { - @\libxml_use_internal_errors(true); - } + $bState = \libxml_use_internal_errors(true); } $oDom = new \DOMDocument('1.0', 'utf-8'); $oDom->encoding = 'UTF-8'; + $oDom->strictErrorChecking = false; $oDom->formatOutput = false; @$oDom->loadHTML('<'.'?xml version="1.0" encoding="utf-8"?'.'>'. ''.$sText.''); + @$oDom->normalizeDocument(); + + if (\MailSo\Base\Utils::FunctionExistsAndEnabled('libxml_use_internal_errors')) + { + @\libxml_clear_errors(); + } + + if (\MailSo\Base\Utils::FunctionExistsAndEnabled('libxml_use_internal_errors')) + { + \libxml_use_internal_errors($bState); + } + return $oDom; } @@ -65,13 +74,13 @@ class HtmlUtils public static function ClearBodyAndHtmlTag($sHtml, &$sHtmlAttrs = '', &$sBodyAttrs = '') { $aMatch = array(); - if (preg_match('/]+)>/im', $sHtml, $aMatch) && !empty($aMatch[1])) + if (\preg_match('/]+)>/im', $sHtml, $aMatch) && !empty($aMatch[1])) { $sHtmlAttrs = $aMatch[1]; } $aMatch = array(); - if (preg_match('/]+)>/im', $sHtml, $aMatch) && !empty($aMatch[1])) + if (\preg_match('/]+)>/im', $sHtml, $aMatch) && !empty($aMatch[1])) { $sBodyAttrs = $aMatch[1]; } @@ -81,22 +90,53 @@ class HtmlUtils $sHtml = \preg_replace('/]*)>/im', '', $sHtml); $sHtml = \preg_replace('/<\/html>/im', '', $sHtml); + $sHtmlAttrs = \preg_replace('/xmlns:[a-z]="[^"]*"/im', '', $sHtmlAttrs); + $sHtmlAttrs = \preg_replace('/xmlns="[^"]*"/im', '', $sHtmlAttrs); + $sBodyAttrs = \preg_replace('/xmlns:[a-z]="[^"]*"/im', '', $sBodyAttrs); + return $sHtml; } /** * @param string $sHtml + * @param bool $bClearEmpty = true * * @return string */ - public static function ClearTags($sHtml) + public static function FixSchemas($sHtml, $bClearEmpty = true) + { + if ($bClearEmpty) + { + $sHtml = \str_replace('', '', $sHtml); + } + + $sHtml = \str_replace('', '', $sHtml); + $sHtml = \str_replace('', '', $sHtml); + + return $sHtml; + } + + /** + * @param string $sHtml + * @param bool $bClearStyleAndHead = true + * + * @return string + */ + public static function ClearTags($sHtml, $bClearStyleAndHead = true) { $aRemoveTags = array( - 'head', 'link', 'base', 'meta', 'title', 'style', 'script', 'bgsound', 'keygen', 'source', - 'object', 'embed', 'applet', 'mocha', 'iframe', 'frame', 'frameset', 'video', 'audio' + 'link', 'base', 'meta', 'title', 'script', 'bgsound', 'keygen', 'source', + 'object', 'embed', 'applet', 'mocha', 'iframe', 'frame', 'frameset', 'video', 'audio', 'area', 'map' ); + if ($bClearStyleAndHead) + { + $aRemoveTags[] = 'head'; + $aRemoveTags[] = 'style'; + } + $aToRemove = array( + '/]*><\/p>/i', '/]*>/msi', '/<\?xml [^>]*\?>/msi' ); @@ -150,6 +190,227 @@ class HtmlUtils return \preg_replace($aToReplace, 'оn\\1', $sHtml); } +// public static function ClearStyleUrlValueParserHelper($oUrlValue, $oRule, $oRuleSet, +// $oElem = null, +// &$bHasExternals = false, &$aFoundCIDs = array(), +// $aContentLocationUrls = array(), &$aFoundedContentLocationUrls = array(), +// $bDoNotReplaceExternalUrl = false, $fAdditionalExternalFilter = null +// ) +// { +// if ($oUrlValue instanceof \Sabberworm\CSS\Value\URL) +// { +// $oNewRule = new \Sabberworm\CSS\Rule\Rule('x-rl-orig-'.$oRule->getRule()); +// $oNewRule->setValue((string) $oRule->getValue()); +// $oNewRule->setIsImportant($oRule->getIsImportant()); +// +// $oRuleSet->addRule($oNewRule); +// +// $oUrl = $oUrlValue->getURL(); +// $sUrl = $oUrl ? $oUrl->getString() : ''; +// +// if ('cid:' === \strtolower(\substr($sUrl, 0, 4))) +// { +// $aFoundCIDs[] = \substr($sUrl, 4); +// +// $oRule->setRule('x-rl-mod-'.$oRule->getRule()); +// +// if ($oElem) +// { +// $oElem->setAttribute('data-x-style-mod', '1'); +// } +// } +// else +// { +// if (\preg_match('/http[s]?:\/\//i', $sUrl) || '//' === \substr($sUrl, 0, 2)) +// { +// $oRule->setRule('x-rl-mod-'.$oRule->getRule()); +// +// if (\in_array($sUrl, $aContentLocationUrls)) +// { +// $aFoundedContentLocationUrls[] = $sUrl; +// } +// else +// { +// $bHasExternals = true; +// if (!$bDoNotReplaceExternalUrl) +// { +// if ($fAdditionalExternalFilter) +// { +// $sAdditionalResult = \call_user_func($fAdditionalExternalFilter, $sUrl); +// if (0 < \strlen($sAdditionalResult) && $oUrl) +// { +// $oUrl->setString($sAdditionalResult); +// } +// } +// } +// } +// +// if ($oElem) +// { +// $oElem->setAttribute('data-x-style-mod', '1'); +// } +// } +// else if ('data:image/' !== \strtolower(\substr(\trim($sUrl), 0, 11))) +// { +// $oRuleSet->removeRule($oRule); +// } +// } +// } +// else if ($oRule instanceof \Sabberworm\CSS\Rule\Rule) +// { +// if ('x-rl-' !== \substr($oRule->getRule(), 0, 5)) +// { +// $oValue = $oRule->getValue(); +// if ($oValue instanceof \Sabberworm\CSS\Value\URL) +// { +// \MailSo\Base\HtmlUtils::ClearStyleUrlValueParserHelper($oValue, $oRule, $oRuleSet, $oElem, +// $bHasExternals, $aFoundCIDs, +// $aContentLocationUrls, $aFoundedContentLocationUrls, +// $bDoNotReplaceExternalUrl, $fAdditionalExternalFilter); +// } +// else if ($oValue instanceof \Sabberworm\CSS\Value\RuleValueList) +// { +// $aComps = $oValue->getListComponents(); +// foreach ($aComps as $oValue) +// { +// if ($oValue instanceof \Sabberworm\CSS\Value\URL) +// { +// \MailSo\Base\HtmlUtils::ClearStyleUrlValueParserHelper($oValue, $oRule, $oRuleSet, $oElem, +// $bHasExternals, $aFoundCIDs, +// $aContentLocationUrls, $aFoundedContentLocationUrls, +// $bDoNotReplaceExternalUrl, $fAdditionalExternalFilter); +// } +// } +// } +// } +// } +// } +// +// public static function ClearStyleSmart($sStyle, $oElement = null, +// &$bHasExternals = false, &$aFoundCIDs = array(), +// $aContentLocationUrls = array(), &$aFoundedContentLocationUrls = array(), +// $bDoNotReplaceExternalUrl = false, $fAdditionalExternalFilter = null, +// $sSelectorPrefix = '') +// { +// $mResult = false; +// $oCss = null; +// +// if (!\class_exists('Sabberworm\CSS\Parser')) +// { +// return $mResult; +// } +// +// $sStyle = \trim($sStyle); +// if (empty($sStyle)) +// { +// return ''; +// } +// +// $sStyle = \trim(\preg_replace('/[\r\n\t\s]+/', ' ', $sStyle)); +// +// try +// { +// $oSettings = \Sabberworm\CSS\Settings::create(); +// $oSettings->beStrict(); +// $oSettings->withMultibyteSupport(false); +// +// $oCssParser = new \Sabberworm\CSS\Parser($sStyle, $oSettings); +// $oCss = $oCssParser->parse(); +// } +// catch (\Exception $oEception) +// { +// unset($oEception); +// $mResult = false; +// } +// +// if ($oCss) +// { +// foreach ($oCss->getAllDeclarationBlocks() as $oBlock) +// { +// foreach($oBlock->getSelectors() as $oSelector) +// { +// $sS = ' '.\trim($oSelector->getSelector()).' '; +// $sS = \preg_replace('/ body([\.# ])/i', ' [data-x-div-type="body"]$1', $sS); +// $sS = \preg_replace('/ html([\.# ])/i', ' [data-x-div-type="html"]$1', $sS); +// +// if (0 < \strlen($sSelectorPrefix)) +// { +// $sS = \trim($sSelectorPrefix.' '.\trim($sS)); +// } +// +// $oSelector->setSelector(\trim($sS)); +// } +// } +// +// $aRulesToRemove = array( +// 'pointer-events', 'content', 'behavior', 'cursor', +// ); +// +// foreach($oCss->getAllRuleSets() as $oRuleSet) +// { +// foreach ($aRulesToRemove as $sRuleToRemove) +// { +// $oRuleSet->removeRule($sRuleToRemove); +// } +// +// // position: fixed -> position: fixed -> absolute +// $aRules = $oRuleSet->getRules('position'); +// if (\is_array($aRules)) +// { +// foreach ($aRules as $oRule) +// { +// $mValue = $oRule->getValue(); +// if (\is_string($mValue) && 'fixed' === \trim(\strtolower($mValue))) +// { +// $oRule->setValue('absolute'); +// } +// } +// } +// } +// +// foreach($oCss->getAllDeclarationBlocks() as $oRuleSet) +// { +// if ($oRuleSet instanceof \Sabberworm\CSS\RuleSet\RuleSet) +// { +// if ($oRuleSet instanceof \Sabberworm\CSS\RuleSet\DeclarationBlock) +// { +// $oRuleSet->expandBackgroundShorthand(); +// $oRuleSet->expandListStyleShorthand(); +// } +// +// $aRules = $oRuleSet->getRules(); +// if (\is_array($aRules) && 0 < \count($aRules)) +// { +// foreach ($aRules as $oRule) +// { +// if ($oRule instanceof \Sabberworm\CSS\Rule\Rule) +// { +// \MailSo\Base\HtmlUtils::ClearStyleUrlValueParserHelper(null, $oRule, $oRuleSet, +// $oElement, +// $bHasExternals, $aFoundCIDs, +// $aContentLocationUrls, $aFoundedContentLocationUrls, +// $bDoNotReplaceExternalUrl, $fAdditionalExternalFilter +// ); +// } +// } +// } +// } +// } +// +// try +// { +// $mResult = $oCss->render(\Sabberworm\CSS\OutputFormat::createCompact()); +// } +// catch (\Exception $oEception) +// { +// unset($oEception); +// $mResult = false; +// } +// } +// +// return $mResult; +// } + /** * * @param string $sStyle @@ -208,7 +469,7 @@ class HtmlUtils { // skip } - else if (\in_array($sName, array('background-image', 'background', 'list-style-image', 'content')) + else if (\in_array($sName, array('background-image', 'background', 'list-style', 'list-style-image', 'content')) && \preg_match('/url[\s]?\(([^)]+)\)/im', $sValue, $aMatch) && !empty($aMatch[1])) { $sFullUrl = \trim($aMatch[0], '"\' '); @@ -409,14 +670,18 @@ class HtmlUtils * @param bool $bDoNotReplaceExternalUrl = false * @param bool $bFindLinksInHtml = false * @param callback|null $fAdditionalExternalFilter = null + * @param callback|null $fAdditionalDomReader = null * * @return string */ public static function ClearHtml($sHtml, &$bHasExternals = false, &$aFoundCIDs = array(), $aContentLocationUrls = array(), &$aFoundedContentLocationUrls = array(), - $bDoNotReplaceExternalUrl = false, $bFindLinksInHtml = false, $fAdditionalExternalFilter = null) + $bDoNotReplaceExternalUrl = false, $bFindLinksInHtml = false, + $fAdditionalExternalFilter = null, $fAdditionalDomReader = false, + $bTryToDetectHiddenImages = false) { $sResult = ''; + $sHtml = null === $sHtml ? '' : (string) $sHtml; $sHtml = \trim($sHtml); if (0 === \strlen($sHtml)) @@ -429,9 +694,16 @@ class HtmlUtils $fAdditionalExternalFilter = null; } + if ($fAdditionalDomReader && !\is_callable($fAdditionalDomReader)) + { + $fAdditionalDomReader = null; + } + $bHasExternals = false; - $sHtml = \MailSo\Base\HtmlUtils::ClearTags($sHtml); + $sHtml = \MailSo\Base\HtmlUtils::FixSchemas($sHtml); + + $sHtml = \MailSo\Base\HtmlUtils::ClearTags($sHtml, false); $sHtml = \MailSo\Base\HtmlUtils::ClearOn($sHtml); $sHtmlAttrs = $sBodyAttrs = ''; @@ -443,22 +715,58 @@ class HtmlUtils if ($oDom) { + if ($fAdditionalDomReader) + { + $oResDom = \call_user_func($fAdditionalDomReader, $oDom); + if ($oResDom) + { + $oDom = $oResDom; + } + + unset($oResDom); + } + if ($bFindLinksInHtml) { \MailSo\Base\HtmlUtils::FindLinksInDOM($oDom); } - $aNodes = $oDom->getElementsByTagName('*'); - foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement) + $oXpath = new \DOMXpath($oDom); + $oComments = $oXpath->query('//comment()'); + if ($oComments) { - if (\in_array(\strtolower($oElement->tagName), array('svg', 'head', 'link', - 'base', 'meta', 'title', 'style', 'x-script', 'script', 'bgsound', 'keygen', 'source', - 'object', 'embed', 'applet', 'mocha', 'iframe', 'frame', 'frameset', 'video', 'audio')) && isset($oElement->parentNode)) + foreach ($oComments as $oComment) { - @$oElement->parentNode->removeChild($oElement); + if (isset($oComment->parentNode)) + { + @$oComment->parentNode->removeChild($oComment); + } } } + unset($oXpath, $oComments); + + $aNodes = $oDom->getElementsByTagName('*'); + foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement) + { + if ($oElement) + { + $sTagNameLower = \strtolower($oElement->tagName); + + if ('' !== $sTagNameLower && \in_array($sTagNameLower, array('svg', 'head', 'link', + 'base', 'meta', 'title', 'style', 'x-script', 'script', 'bgsound', 'keygen', 'source', + 'object', 'embed', 'applet', 'mocha', 'iframe', 'frame', 'frameset', + 'video', 'audio', 'area', 'map'))) + { + if (isset($oElement->parentNode)) + { + @$oElement->parentNode->removeChild($oElement); + } + } + } + } + + $sLinkColor = ''; $aNodes = $oDom->getElementsByTagName('*'); foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement) { @@ -468,6 +776,7 @@ class HtmlUtils if ('body' === $sTagNameLower) { $aAttrs = array( + 'link' => '', 'text' => '', 'topmargin' => '', 'leftmargin' => '', @@ -499,6 +808,13 @@ class HtmlUtils switch ($sIndex) { + case 'link': + $sLinkColor = \trim($aItem[1]); + if (!\preg_match('/^#[abcdef0-9]{3,6}$/i', $sLinkColor)) + { + $sLinkColor = ''; + } + break; case 'text': $aStyles[] = 'color: '.$aItem[1]; break; @@ -520,7 +836,7 @@ class HtmlUtils if (0 < \count($aStyles)) { - $sStyles = $oElement->hasAttribute('style') ? $oElement->getAttribute('style') : ''; + $sStyles = $oElement->hasAttribute('style') ? \trim(\trim(\trim($oElement->getAttribute('style')), ';')) : ''; $oElement->setAttribute('style', (empty($sStyles) ? '' : $sStyles.'; ').\implode('; ', $aStyles)); } } @@ -530,6 +846,15 @@ class HtmlUtils $oElement->setAttribute('src', 'javascript:false'); } + if ('a' === $sTagNameLower && !empty($sLinkColor)) + { + $sStyles = $oElement->hasAttribute('style') + ? \trim(\trim(\trim($oElement->getAttribute('style')), ';')) : ''; + + $oElement->setAttribute('style', + 'color: '.$sLinkColor.\trim((empty($sStyles) ? '' : '; '.$sStyles))); + } + if (\in_array($sTagNameLower, array('a', 'form', 'area'))) { $oElement->setAttribute('target', '_blank'); @@ -540,14 +865,11 @@ class HtmlUtils $oElement->setAttribute('tabindex', '-1'); } -// if ('blockquote' === $sTagNameLower) -// { -// $oElement->removeAttribute('style'); -// } - foreach (array( - 'id', 'class', 'contenteditable', 'designmode', 'formaction', - 'data-bind', 'xmlns', 'srcset' + 'id', 'class', + 'contenteditable', 'designmode', 'formaction', + 'data-bind', 'data-reactid', 'xmlns', 'srcset', + 'data-x-skip-style' ) as $sAttr) { @$oElement->removeAttribute($sAttr); @@ -578,6 +900,58 @@ class HtmlUtils } } + if ($bTryToDetectHiddenImages && 'img' === $sTagNameLower) + { + $sAlt = $oElement->hasAttribute('alt') + ? \trim($oElement->getAttribute('alt')) : ''; + + if ($oElement->hasAttribute('src') && '' === $sAlt) + { + $aH = array( + 'email.microsoftemail.com/open', + 'github.com/notifications/beacon/', + 'mandrillapp.com/track/open', + 'list-manage.com/track/open' + ); + + $sH = $oElement->hasAttribute('height') + ? \trim($oElement->getAttribute('height')) : ''; + +// $sW = $oElement->hasAttribute('width') +// ? \trim($oElement->getAttribute('width')) : ''; + + $sStyles = $oElement->hasAttribute('style') + ? \preg_replace('/[\s]+/', '', \trim(\trim(\trim($oElement->getAttribute('style')), ';'))) : ''; + + $sSrc = \trim($oElement->getAttribute('src')); + + $bC = \in_array($sH, array('1', '0', '1px', '0px')) || + \preg_match('/(display:none|visibility:hidden|height:0|height:[01][a-z][a-z])/i', $sStyles); + + if (!$bC) + { + $sSrcLower = \strtolower($sSrc); + foreach ($aH as $sLine) + { + if (false !== \strpos($sSrcLower, $sLine)) + { + $bC = true; + break; + } + } + } + + if ($bC) + { + $oElement->setAttribute('style', 'display:none'); + $oElement->setAttribute('data-x-skip-style', 'true'); + $oElement->setAttribute('data-x-hidden-src', $sSrc); + + $oElement->removeAttribute('src'); + } + } + } + if ($oElement->hasAttribute('src')) { $sSrc = \trim($oElement->getAttribute('src')); @@ -636,7 +1010,7 @@ class HtmlUtils { $aStyles = array(); $sStyles = $oElement->hasAttribute('style') - ? $oElement->getAttribute('style') : ''; + ? \trim(\trim(\trim($oElement->getAttribute('style')), ';')) : ''; if (!empty($sBackground)) { @@ -653,12 +1027,14 @@ class HtmlUtils $oElement->setAttribute('style', (empty($sStyles) ? '' : $sStyles.'; ').\implode('; ', $aStyles)); } - if ($oElement->hasAttribute('style')) + if ($oElement->hasAttribute('style') && !$oElement->hasAttribute('data-x-skip-style')) { $oElement->setAttribute('style', \MailSo\Base\HtmlUtils::ClearStyle($oElement->getAttribute('style'), $oElement, $bHasExternals, $aFoundCIDs, $aContentLocationUrls, $aFoundedContentLocationUrls, $bDoNotReplaceExternalUrl, $fAdditionalExternalFilter)); } + + $oElement->removeAttribute('data-x-skip-style'); } $sResult = $oDom->saveHTML(); @@ -674,6 +1050,7 @@ class HtmlUtils $sResult = '
'.$sResult.'
'; $sResult = \str_replace(\MailSo\Base\HtmlUtils::$KOS, ':', $sResult); + $sResult = \MailSo\Base\Utils::StripSpaces($sResult); return \trim($sResult); } @@ -925,103 +1302,104 @@ class HtmlUtils */ public static function ConvertHtmlToPlain($sText) { - $sText = trim(stripslashes($sText)); - $sText = preg_replace('/[\s]+/', ' ', $sText); - $sText = preg_replace(array( - "/\r/", - "/[\n\t]+/", - '/]*>.*?<\/script>/i', - '/]*>.*?<\/style>/i', - '/]*>.*?<\/title>/i', - '/]*>(.+?)<\/h[123]>/i', - '/]*>(.+?)<\/h[456]>/i', - '/]*>/i', - '/]*>/i', - '/]*>(.+?)<\/b>/i', - '/]*>(.+?)<\/i>/i', - '/(]*>|<\/ul>)/i', - '/(]*>|<\/ol>)/i', - '/]*>/i', - '/]*href="([^"]+)"[^>]*>(.+?)<\/a>/i', - '/]*>/i', - '/(]*>|<\/table>)/i', - '/(]*>|<\/tr>)/i', - '/]*>(.+?)<\/td>/i', - '/]*>(.+?)<\/th>/i', - '/ /i', - '/"/i', - '/>/i', - '/</i', - '/&/i', - '/©/i', - '/™/i', - '/“/', - '/”/', - '/–/', - '/’/', - '/&/', - '/©/', - '/™/', - '/—/', - '/“/', - '/”/', - '/•/', - '/®/i', - '/•/i', - '/&[&;]+;/i', - '/'/', - '/ /' - ), array( - '', - ' ', - '', - '', - '', - "\n\n\\1\n\n", - "\n\n\\1\n\n", - "\n\n\t", - "\n", - '\\1', - '\\1', - "\n\n", - "\n\n", - "\n\t* ", - '\\2 (\\1)', - "\n------------------------------------\n", - "\n", - "\n", - "\t\\1\n", - "\t\\1\n", - ' ', - '"', - '>', - '<', - '&', - '(c)', - '(tm)', - '"', - '"', - '-', - "'", - '&', - '(c)', - '(tm)', - '--', - '"', - '"', - '*', - '(R)', - '*', - '', - '\'', - '' - ), $sText); + $sText = \trim(\stripslashes($sText)); + $sText = \MailSo\Base\Utils::StripSpaces($sText); - $sText = str_ireplace('
',"\n
", $sText); - $sText = strip_tags($sText, ''); - $sText = preg_replace("/\n\\s+\n/", "\n", $sText); - $sText = preg_replace("/[\n]{3,}/", "\n\n", $sText); + $sText = \preg_replace(array( + "/\r/", + "/[\n\t]+/", + '/]*>.*?<\/script>/i', + '/]*>.*?<\/style>/i', + '/]*>.*?<\/title>/i', + '/]*>(.+?)<\/h[123]>/i', + '/]*>(.+?)<\/h[456]>/i', + '/]*>/i', + '/]*>/i', + '/]*>(.+?)<\/b>/i', + '/]*>(.+?)<\/i>/i', + '/(]*>|<\/ul>)/i', + '/(]*>|<\/ol>)/i', + '/]*>/i', + '/]*href="([^"]+)"[^>]*>(.+?)<\/a>/i', + '/]*>/i', + '/(]*>|<\/table>)/i', + '/(]*>|<\/tr>)/i', + '/]*>(.+?)<\/td>/i', + '/]*>(.+?)<\/th>/i', + '/ /i', + '/"/i', + '/>/i', + '/</i', + '/&/i', + '/©/i', + '/™/i', + '/“/', + '/”/', + '/–/', + '/’/', + '/&/', + '/©/', + '/™/', + '/—/', + '/“/', + '/”/', + '/•/', + '/®/i', + '/•/i', + '/&[&;]+;/i', + '/'/', + '/ /' + ), array( + '', + ' ', + '', + '', + '', + "\n\n\\1\n\n", + "\n\n\\1\n\n", + "\n\n\t", + "\n", + '\\1', + '\\1', + "\n\n", + "\n\n", + "\n\t* ", + '\\2 (\\1)', + "\n------------------------------------\n", + "\n", + "\n", + "\t\\1\n", + "\t\\1\n", + ' ', + '"', + '>', + '<', + '&', + '(c)', + '(tm)', + '"', + '"', + '-', + "'", + '&', + '(c)', + '(tm)', + '--', + '"', + '"', + '*', + '(R)', + '*', + '', + '\'', + '' + ), $sText); - return trim($sText); + $sText = \str_ireplace('
',"\n
", $sText); + $sText = \strip_tags($sText, ''); + $sText = \preg_replace("/\n\\s+\n/", "\n", $sText); + $sText = \preg_replace("/[\n]{3,}/", "\n\n", $sText); + + return \trim($sText); } } diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Http.php b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Http.php index 4294908da..f34e47214 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Http.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Http.php @@ -567,6 +567,12 @@ class Http return false; } + $sUrl = \trim($sUrl); + if ('//' === substr($sUrl, 0, 2)) + { + $sUrl = 'http:'.$sUrl; + } + $aOptions = array( CURLOPT_URL => $sUrl, CURLOPT_HEADER => false, @@ -679,10 +685,10 @@ class Http { if ($bSetCacheHeader) { - \header('Cache-Control: public', true); - \header('Pragma: public', true); - \header('Last-Modified: '.\gmdate('D, d M Y H:i:s', $iUtcTimeStamp - $iExpireTime).' UTC', true); - \header('Expires: '.\gmdate('D, j M Y H:i:s', $iUtcTimeStamp + $iExpireTime).' UTC', true); + @\header('Cache-Control: public', true); + @\header('Pragma: public', true); + @\header('Last-Modified: '.\gmdate('D, d M Y H:i:s', $iUtcTimeStamp - $iExpireTime).' UTC', true); + @\header('Expires: '.\gmdate('D, j M Y H:i:s', $iUtcTimeStamp + $iExpireTime).' UTC', true); if (0 < strlen($sEtag)) { diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Base/StreamWrappers/TempFile.php b/rainloop/v/0.0.0/app/libraries/MailSo/Base/StreamWrappers/TempFile.php index dfe6ff609..196b2b5f5 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Base/StreamWrappers/TempFile.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Base/StreamWrappers/TempFile.php @@ -43,14 +43,16 @@ class TempFile /** * @param string $sHash + * @param string $sFileName * * @return resource|bool */ - public static function CreateStream($sHash) + public static function CreateStream($sHash, &$sFileName = '') { self::Reg(); - return fopen(self::STREAM_NAME.'://'.$sHash, 'r+b'); + $sFileName = self::STREAM_NAME.'://'.$sHash; + return fopen($sFileName, 'r+b'); } /** @@ -72,6 +74,7 @@ class TempFile is_resource(self::$aStreams[$sHashName])) { $this->rSream = self::$aStreams[$sHashName]; + \fseek($this->rSream, 0); $bResult = true; } else @@ -93,7 +96,7 @@ class TempFile */ public function stream_close() { - return -1 !== fseek($this->rSream, 0); + return true; } /** diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php index 669f24dae..d2608c334 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php @@ -235,6 +235,56 @@ END; return $sCharset; } + /** + * @param string $sFilePath + * @param function $fFileExistsCallback = null + * + * @return string + */ + public static function SmartFileExists($sFilePath, $fFileExistsCallback = null) + { + $sFilePath = \str_replace('\\', '/', \trim($sFilePath)); + if (!$fFileExistsCallback) + { + $fFileExistsCallback = function ($sPath) { + return \file_exists($sPath); + }; + } + + if (!\call_user_func($fFileExistsCallback, $sFilePath)) + { + return $sFilePath; + } + + $aFileInfo = \pathinfo($sFilePath); + + $iIndex = 0; + + do + { + $iIndex++; + + $sFilePathNew = $aFileInfo['dirname'].'/'. + \preg_replace('/\(\d{1,2}\)$/', '', $aFileInfo['filename']). + ' ('.$iIndex.')'. + (empty($aFileInfo['extension']) ? '' : '.'.$aFileInfo['extension']) + ; + + if (!\call_user_func($fFileExistsCallback, $sFilePathNew)) + { + $sFilePath = $sFilePathNew; + break; + } + else if (10 < $iIndex) + { + break; + } + } + while (true); + + return $sFilePath; + } + /** * @return bool */ @@ -500,6 +550,17 @@ END; return \MailSo\Base\Utils::IsAscii($sValue) ? \strtoupper($sValue) : $sValue; } + /** + * @param string $sValue + * + * @return string + */ + public static function StripSpaces($sValue) + { + return \MailSo\Base\Utils::Trim( + \preg_replace('/[\s]+/u', ' ', $sValue)); + } + /** * @param string $sValue * @@ -507,7 +568,7 @@ END; */ public static function IsUtf8($sValue) { - return (bool) ( \function_exists('mb_check_encoding') ? + return (bool) (\function_exists('mb_check_encoding') ? \mb_check_encoding($sValue, 'UTF-8') : \preg_match('//u', $sValue)); } @@ -551,6 +612,16 @@ END; return $sResult; } + /** + * @param string $sInputValue + * + * @return string + */ + public static function DecodeFlowedFormat($sInputValue) + { + return \preg_replace('/ ([\r]?[\n])/m', ' ', $sInputValue); + } + /** * @param string $sEncodedValue * @param string $sIncomingCharset = '' @@ -670,6 +741,64 @@ END; return $sValue; } + /** + * @param string $sIncHeaders + * @param string $aHeadersToRemove = array() + * + * @return string + */ + public static function RemoveHeaderFromHeaders($sIncHeaders, $aHeadersToRemove = array()) + { + $sResultHeaders = $sIncHeaders; + + if (\is_array($aHeadersToRemove) && 0 < \count($aHeadersToRemove)) + { + $aHeadersToRemove = \array_map('strtolower', $aHeadersToRemove); + + $sIncHeaders = \preg_replace('/[\r\n]+/', "\n", $sIncHeaders); + $aHeaders = \explode("\n", $sIncHeaders); + + $bSkip = false; + $aResult = array(); + + foreach ($aHeaders as $sLine) + { + if (0 < \strlen($sLine)) + { + $sFirst = $sLine{1}; + if (' ' === $sFirst || "\t" === $sFirst) + { + if (!$bSkip) + { + $aResult[] = $sLine; + } + } + else + { + $bSkip = false; + $aParts = \explode(':', $sLine, 2); + + if (!empty($aParts) && !empty($aParts[0])) + { + if (\in_array(\strtolower(\trim($aParts[0])), $aHeadersToRemove)) + { + $bSkip = true; + } + else + { + $aResult[] = $sLine; + } + } + } + } + } + + $sResultHeaders = \implode("\r\n", $aResult); + } + + return $sResultHeaders; + } + /** * @param string $sEncodeType * @param string $sValue @@ -812,7 +941,7 @@ END; $sResult = ''; if (0 < \strlen($sEmail)) { - $iPos = \strpos($sEmail, '@'); + $iPos = \strrpos($sEmail, '@'); $sResult = (false === $iPos) ? $sEmail : \substr($sEmail, 0, $iPos); } @@ -829,7 +958,7 @@ END; $sResult = ''; if (0 < \strlen($sEmail)) { - $iPos = \strpos($sEmail, '@'); + $iPos = \strrpos($sEmail, '@'); if (false !== $iPos && 0 < $iPos) { $sResult = \substr($sEmail, $iPos + 1); @@ -839,6 +968,20 @@ END; return $sResult; } + /** + * @param string $sDomain + * + * @return string + */ + public static function GetClearDomainName($sDomain) + { + $sResultDomain = \preg_replace( + '/^(webmail|email|mail|www|imap4|pop3|imap|pop|demo|client|ssl|secure|test|cloud|box|m)\./i', + '', $sDomain); + + return false === \strpos($sResultDomain, '.') ? $sDomain : $sResultDomain; + } + /** * @param string $sFileName * @@ -1230,8 +1373,9 @@ END; */ public static function ClearFileName($sFileName) { - return \MailSo\Base\Utils::ClearNullBite(\preg_replace('/[\s]+/u', ' ', - \str_replace(array('"', '/', '\\', '*', '?', '<', '>', '|', ':'), ' ', $sFileName))); + return \MailSo\Base\Utils::Trim(\MailSo\Base\Utils::ClearNullBite( + \MailSo\Base\Utils::StripSpaces( + \str_replace(array('"', '/', '\\', '*', '?', '<', '>', '|', ':'), ' ', $sFileName)))); } /** @@ -1241,8 +1385,8 @@ END; */ public static function ClearXss($sValue) { - return \MailSo\Base\Utils::ClearNullBite( - \str_replace(array('"', '/', '\\', '*', '?', '<', '>', '|', ':'), ' ', $sValue)); + return \MailSo\Base\Utils::Trim(\MailSo\Base\Utils::ClearNullBite( + \str_replace(array('"', '/', '\\', '*', '?', '<', '>', '|', ':'), ' ', $sValue))); } /** @@ -2224,7 +2368,8 @@ END; { $aMatch = array(); return \preg_match('/.+(\.[a-zA-Z]+)$/', $sDomain, $aMatch) && !empty($aMatch[1]) && \in_array($aMatch[1], \explode(' ', - '.aero .asia .biz .cat .com .coop .edu .gov .info .int .jobs .mil .mobi .museum .name .net .org .pro .tel .travel .xxx .ac .ad .ae .af .ag .ai .al .am .an .ao .aq .ar .as .at .au .aw .ax .az .ba .bb .bd .be .bf .bg .bh .bi .bj .bm .bn .bo .br .bs .bt .bv .bw .by .bz .ca .cc .cd .cf .cg .ch .ci .ck .cl .cm .cn .co .cr .cs .cu .cv .cx .cy .cz .dd .de .dj .dk .dm .do .dz .ec .ee .eg .er .es .et .eu .fi .fj .fk .fm .fo .fr .ga .gb .gd .ge .gf .gg .gh .gi .gl .gm .gn .gp .gq .gr .gs .gt .gu .gw .gy .hk .hm .hn .hr .ht .hu .id .ie .il .im .in .io .iq .ir .is .it .je .jm .jo .jp .ke .kg .kh .ki .km .kn .kp .kr .kw .ky .kz .la .lb .lc .li .lk .lr .ls .lt .lu .lv .ly .ma .mc .md .me .mg .mh .mk .ml .mm .mn .mo .mp .mq .mr .ms .mt .mu .mv .mw .mx .my .mz .na .nc .ne .nf .ng .ni .nl .no .np .nr .nu .nz .om .pa .pe .pf .pg .ph .pk .pl .pm .pn .pr .ps .pt .pw .py .qa .re .ro .rs .ru . .rw .sa .sb .sc .sd .se .sg .sh .si .sj .sk .sl .sm .sn .so .sr .st .su .sv .sy .sz .tc .td .tf .tg .th .tj .tk .tl .tm .tn .to .tp .tr .tt .tv .tw .tz .ua .ug .uk .us .uy .uz .va .vc .ve .vg .vi .vn .vu .wf .ws .ye .yt .za .zm .zw' + '.academy .actor .agency .audio .bar .beer .bike .blue .boutique .cab .camera .camp .capital .cards .careers .cash .catering .center .cheap .city .cleaning .clinic .clothing .club .coffee .community .company .computer .construction .consulting .contractors .cool .credit .dance .dating .democrat .dental .diamonds .digital .direct .directory .discount .domains .education .email .energy .equipment .estate .events .expert .exposed .fail .farm .fish .fitness .florist .fund .futbol .gallery .gift .glass .graphics .guru .help .holdings .holiday .host .hosting .house .institute .international .kitchen .land .life .lighting .limo .link .management .market .marketing .media .menu .moda .partners .parts .photo .photography .photos .pics .pink .press .productions .pub .red .rentals .repair .report .rest .sexy .shoes .social .solar .solutions .space .support .systems .tattoo .tax .technology .tips .today .tools .town .toys .trade .training .university .uno .vacations .vision .vodka .voyage .watch .webcam .wiki .work .works .wtf .zone .aero .asia .biz .cat .com .coop .edu .gov .info .int .jobs .mil .mobi .museum .name .net .org .pro .tel .travel .xxx '. + '.ac .ad .ae .af .ag .ai .al .am .an .ao .aq .ar .as .at .au .aw .ax .az .ba .bb .bd .be .bf .bg .bh .bi .bj .bm .bn .bo .br .bs .bt .bv .bw .by .bz .ca .cc .cd .cf .cg .ch .ci .ck .cl .cm .cn .co .cr .cs .cu .cv .cx .cy .cz .dd .de .dj .dk .dm .do .dz .ec .ee .eg .er .es .et .eu .fi .fj .fk .fm .fo .fr .ga .gb .gd .ge .gf .gg .gh .gi .gl .gm .gn .gp .gq .gr .gs .gt .gu .gw .gy .hk .hm .hn .hr .ht .hu .id .ie .il .im .in .io .iq .ir .is .it .je .jm .jo .jp .ke .kg .kh .ki .km .kn .kp .kr .kw .ky .kz .la .lb .lc .li .lk .lr .ls .lt .lu .lv .ly .ma .mc .md .me .mg .mh .mk .ml .mm .mn .mo .mp .mq .mr .ms .mt .mu .mv .mw .mx .my .mz .na .nc .ne .nf .ng .ni .nl .no .np .nr .nu .nz .om .pa .pe .pf .pg .ph .pk .pl .pm .pn .pr .ps .pt .pw .py .qa .re .ro .rs .ru . .rw .sa .sb .sc .sd .se .sg .sh .si .sj .sk .sl .sm .sn .so .sr .st .su .sv .sy .sz .tc .td .tf .tg .th .tj .tk .tl .tm .tn .to .tp .tr .tt .tv .tw .tz .ua .ug .uk .us .uy .uz .va .vc .ve .vg .vi .vn .vu .wf .ws .ye .yt .za .zm .zw' )); } @@ -2303,6 +2448,38 @@ END; return ('' === $sUser ? '' : $sUser.'@').$sDomain; } + /** + * @param string $sHash + * @param string $sSalt + * + * @return int + */ + public static function HashToId($sHash, $sSalt = '') + { + $sData = $sHash ? @\MailSo\Base\Crypt::XxteaDecrypt(\hex2bin($sHash), \md5($sSalt)) : null; + + $aMatch = array(); + if ($sData && preg_match('/^id:(\d+)$/', $sData, $aMatch) && isset($aMatch[1])) + { + return is_numeric($aMatch[1]) ? (int) $aMatch[1] : null; + } + + return null; + } + + /** + * @param int $iID + * @param string $sSalt + * + * @return string + */ + public static function IdToHash($iID, $sSalt = '') + { + return is_int($iID) ? + \bin2hex(\MailSo\Base\Crypt::XxteaEncrypt('id:'.$iID, \md5($sSalt))) : null + ; + } + /** * @param string $sPassword * diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Config.php b/rainloop/v/0.0.0/app/libraries/MailSo/Config.php index 682b0439b..add7b0a33 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Config.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Config.php @@ -46,11 +46,21 @@ class Config */ public static $MessageListDateFilter = 0; + /** + * @var string + */ + public static $MessageListPermanentFilter = ''; + /** * @var int */ public static $LargeThreadLimit = 50; + /** + * @var bool + */ + public static $MessageAllHeaders = false; + /** * @var bool */ @@ -61,6 +71,11 @@ class Config */ public static $PreferStartTlsIfAutoDetect = true; + /** + * @var string + */ + public static $BoundaryPrefix = '_Part_'; + /** * @var \MailSo\Log\Logger|null */ diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/BodyStructure.php b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/BodyStructure.php index eaf460485..624f2beb8 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/BodyStructure.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/BodyStructure.php @@ -285,6 +285,22 @@ class BodyStructure return $bResult; } + /** + * @return bool + */ + public function IsFlowedFormat() + { + $bResult = !empty($this->aBodyParams['format']) && + 'flowed' === \strtolower(\trim($this->aBodyParams['format'])); + + if ($bResult && \in_array(\strtolower($this->MailEncodingName()), array('base64', 'quoted-printable'))) + { + $bResult = false; + } + + return $bResult; + } + /** * @return array|null */ diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/FolderResponseStatus.php b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/FolderResponseStatus.php index f1f14fee8..588473edf 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/FolderResponseStatus.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/FolderResponseStatus.php @@ -22,5 +22,6 @@ class FolderResponseStatus const RECENT = 'RECENT'; const UNSEEN = 'UNSEEN'; const UIDNEXT = 'UIDNEXT'; + const HIGHESTMODSEQ = 'HIGHESTMODSEQ'; const UIDVALIDITY = 'UIDVALIDITY'; } diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/FolderStatus.php b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/FolderStatus.php index d958e4897..7b9fc4e70 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/FolderStatus.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/FolderStatus.php @@ -22,5 +22,6 @@ class FolderStatus const RECENT = 'RECENT'; const UNSEEN = 'UNSEEN'; const UIDNEXT = 'UIDNEXT'; + const HIGHESTMODSEQ = 'HIGHESTMODSEQ'; const UIDVALIDITY = 'UIDVALIDITY'; } diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Folder.php b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Folder.php index 26dc3cfac..50fd42337 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Folder.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Folder.php @@ -94,6 +94,11 @@ class Folder if (0 < \strlen($this->sDelimiter)) { $aNames = \explode($this->sDelimiter, $this->sFullNameRaw); + if (false !== \array_search('', $aNames)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + $this->sNameRaw = \end($aNames); } } @@ -102,7 +107,7 @@ class Folder * @param string $sFullNameRaw * @param string $sDelimiter = '.' * @param array $aFlags = array() - * + * * @return \MailSo\Imap\Folder * * @throws \MailSo\Base\Exceptions\InvalidArgumentException @@ -167,7 +172,7 @@ class Folder { return 'INBOX' === \strtoupper($this->sFullNameRaw) || \in_array('\inbox', $this->aFlagsLowerCase); } - + /** * @param string $sName * @param mixed $mData @@ -176,7 +181,7 @@ class Folder { $this->aExtended[$sName] = $mData; } - + /** * @param string $sName * @return mixed diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/FolderInformation.php b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/FolderInformation.php index c5b437889..f6ac83e43 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/FolderInformation.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/FolderInformation.php @@ -62,6 +62,11 @@ class FolderInformation */ public $Uidnext; + /** + * @var string + */ + public $HighestModSeq; + /** * @access private * @@ -79,6 +84,7 @@ class FolderInformation $this->Unread = null; $this->Uidnext = null; + $this->HighestModSeq = null; } /** diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php index 8abaea90a..85ed08edd 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php @@ -326,7 +326,24 @@ class ImapClient extends \MailSo\Net\NetClient try { - $this->SendRequestWithCheck('AUTHENTICATE', array('XOAUTH2', \trim($sXOAuth2Token))); + $this->SendRequest('AUTHENTICATE', array('XOAUTH2', \trim($sXOAuth2Token))); + $aR = $this->parseResponseWithValidation(); + + if (\is_array($aR) && 0 < \count($aR) && isset($aR[\count($aR) - 1])) + { + $oR = $aR[\count($aR) - 1]; + if (\MailSo\Imap\Enumerations\ResponseType::CONTINUATION === $oR->ResponseType) + { + if (!empty($oR->ResponseList[1]) && preg_match('/^[a-zA-Z0-9=+\/]+$/', $oR->ResponseList[1])) + { + $this->Logger()->Write(\base64_decode($oR->ResponseList[1]), + \MailSo\Log\Enumerations\Type::WARNING); + } + + $this->sendRaw(''); + $this->parseResponseWithValidation(); + } + } } catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) { @@ -681,6 +698,7 @@ class ImapClient extends \MailSo\Net\NetClient { $sName = null; $aStatus = array(); + foreach ($oImapResponse->ResponseList[3] as $sArrayItem) { if (null === $sName) @@ -734,17 +752,21 @@ class ImapClient extends \MailSo\Net\NetClient $this->EscapeString($sListPattern) ); - if ($bUseListStatus && $this->IsSupported('LIST-STATUS')) + if ($bUseListStatus && !$bIsSubscribeList && $this->IsSupported('LIST-STATUS')) { - $aParameters[] = 'RETURN'; - $aParameters[] = array( - 'STATUS', - array( - \MailSo\Imap\Enumerations\FolderStatus::MESSAGES, - \MailSo\Imap\Enumerations\FolderStatus::UNSEEN, - \MailSo\Imap\Enumerations\FolderStatus::UIDNEXT - ) + $aL = array( + \MailSo\Imap\Enumerations\FolderStatus::MESSAGES, + \MailSo\Imap\Enumerations\FolderStatus::UNSEEN, + \MailSo\Imap\Enumerations\FolderStatus::UIDNEXT ); + +// if ($this->IsSupported('CONDSTORE')) +// { +// $aL[] = \MailSo\Imap\Enumerations\FolderStatus::HIGHESTMODSEQ; +// } + + $aParameters[] = 'RETURN'; + $aParameters[] = array('STATUS', $aL); } else { @@ -846,6 +868,12 @@ class ImapClient extends \MailSo\Net\NetClient { $oResult->Uidnext = $oImapResponse->OptionalResponse[1]; } + else if ('HIGHESTMODSEQ' === $oImapResponse->OptionalResponse[0] && + isset($oImapResponse->OptionalResponse[1]) && + \is_numeric($oImapResponse->OptionalResponse[1])) + { + $oResult->HighestModSeq = \trim($oImapResponse->OptionalResponse[1]); + } } if (\count($oImapResponse->ResponseList) > 2 && @@ -1861,7 +1889,7 @@ class ImapClient extends \MailSo\Net\NetClient * @throws \MailSo\Net\Exceptions\Exception */ private function partialParseResponseBranch(&$oImapResponse, $iStackIndex = -1, - $bTreatAsAtom = false, $sParentToken = '') + $bTreatAsAtom = false, $sParentToken = '', $sOpenBracket = '') { $mNull = null; @@ -1992,7 +2020,7 @@ class ImapClient extends \MailSo\Net\NetClient if ($bTreatAsAtom) { $sAtomBlock = $this->partialParseResponseBranch($mNull, $iStackIndex, true, - null === $sPreviousAtomUpperCase ? '' : \strtoupper($sPreviousAtomUpperCase)); + null === $sPreviousAtomUpperCase ? '' : \strtoupper($sPreviousAtomUpperCase), $sOpenBracket); $sAtomBuilder .= $sAtomBlock; $iPos = $this->iResponseBufParsedPos; @@ -2007,7 +2035,7 @@ class ImapClient extends \MailSo\Net\NetClient else if ($bIsGotoNotAtomBracket) { $aSubItems = $this->partialParseResponseBranch($mNull, $iStackIndex, false, - null === $sPreviousAtomUpperCase ? '' : \strtoupper($sPreviousAtomUpperCase)); + null === $sPreviousAtomUpperCase ? '' : \strtoupper($sPreviousAtomUpperCase), $sOpenBracket); $aList[] = $aSubItems; $iPos = $this->iResponseBufParsedPos; @@ -2037,27 +2065,36 @@ class ImapClient extends \MailSo\Net\NetClient $sChar = $this->sResponseBuffer[$iPos]; } - switch ($sChar) + switch (true) { - case ']': - case ')': + case ']' === $sChar: $iPos++; $sPreviousAtomUpperCase = null; $bIsEndOfList = true; break; - case ' ': + case ')' === $sChar: + $iPos++; + $sPreviousAtomUpperCase = null; + $bIsEndOfList = true; + break; + case ' ' === $sChar: if ($bTreatAsAtom) { $sAtomBuilder .= ' '; } $iPos++; break; - case '[': + case '[' === $sChar: $bIsClosingBracketSquare = true; - case '(': + case '(' === $sChar: + if ('(' === $sChar) + { + $bIsClosingBracketSquare = false; + } + if ($bTreatAsAtom) { - $sAtomBuilder .= ($bIsClosingBracketSquare) ? '[' : '('; + $sAtomBuilder .= $bIsClosingBracketSquare ? '[' : '('; } $iPos++; @@ -2065,13 +2102,15 @@ class ImapClient extends \MailSo\Net\NetClient if ($bTreatAsAtom) { $bIsGotoAtomBracket = true; + $sOpenBracket = $bIsClosingBracketSquare ? '[' : '('; } else { $bIsGotoNotAtomBracket = true; + $sOpenBracket = $bIsClosingBracketSquare ? '[' : '('; } break; - case '{': + case '{' === $sChar: $bIsLiteralParsed = false; $mLiteralEndPos = \strpos($this->sResponseBuffer, '}', $iPos); if (false !== $mLiteralEndPos && $mLiteralEndPos > $iPos) @@ -2092,7 +2131,7 @@ class ImapClient extends \MailSo\Net\NetClient } $sPreviousAtomUpperCase = null; break; - case '"': + case '"' === $sChar: $bIsQuotedParsed = false; while (true) { @@ -2178,7 +2217,7 @@ class ImapClient extends \MailSo\Net\NetClient $sPreviousAtomUpperCase = null; break; - case 'GOTO_DEFAULT': + case 'GOTO_DEFAULT' === $sChar: default: $iCharBlockStartPos = $iPos; @@ -2186,7 +2225,7 @@ class ImapClient extends \MailSo\Net\NetClient { $iPos = $iBufferEndIndex; - while ($iPos > $iCharBlockStartPos && $this->sResponseBuffer[$iCharBlockStartPos] == ' ') + while ($iPos > $iCharBlockStartPos && $this->sResponseBuffer[$iCharBlockStartPos] === ' ') { $iCharBlockStartPos++; } @@ -2196,9 +2235,9 @@ class ImapClient extends \MailSo\Net\NetClient while (!$bIsAtomDone && ($iPos <= $iBufferEndIndex)) { $sCharDef = $this->sResponseBuffer[$iPos]; - switch ($sCharDef) + switch (true) { - case '[': + case '[' === $sCharDef: if (null === $sAtomBuilder) { $sAtomBuilder = ''; @@ -2210,7 +2249,7 @@ class ImapClient extends \MailSo\Net\NetClient $this->iResponseBufParsedPos = $iPos; $sListBlock = $this->partialParseResponseBranch($mNull, $iStackIndex, true, - null === $sPreviousAtomUpperCase ? '' : \strtoupper($sPreviousAtomUpperCase)); + null === $sPreviousAtomUpperCase ? '' : \strtoupper($sPreviousAtomUpperCase), '['); if (null !== $sListBlock) { @@ -2220,9 +2259,9 @@ class ImapClient extends \MailSo\Net\NetClient $iPos = $this->iResponseBufParsedPos; $iCharBlockStartPos = $iPos; break; - case ' ': - case ']': - case ')': + case ' ' === $sCharDef: + case ')' === $sCharDef && '(' === $sOpenBracket: + case ']' === $sCharDef && '[' === $sOpenBracket: $bIsAtomDone = true; break; default: diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Log/Driver.php b/rainloop/v/0.0.0/app/libraries/MailSo/Log/Driver.php index 60a8d0021..755df58cb 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Log/Driver.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Log/Driver.php @@ -47,6 +47,11 @@ abstract class Driver */ protected $bTypedPrefix; + /** + * @var string + */ + protected $sNewLine; + /** * @var int */ @@ -79,10 +84,13 @@ abstract class Driver { $this->sDatePattern = 'H:i:s'; $this->sName = 'INFO'; + $this->sNewLine = "\r\n"; $this->bTimePrefix = true; $this->bTypedPrefix = true; $this->bGuidPrefix = true; + $this->iTimeOffset = 0; + $this->iWriteOnTimeoutOnly = 0; $this->bWriteOnErrorOnly = false; $this->bWriteOnPhpErrorOnly = false; @@ -106,6 +114,17 @@ abstract class Driver ); } + /** + * @param int $iTimeOffset + * + * @return \MailSo\Log\Driver + */ + public function SetTimeOffset($iTimeOffset) + { + $this->iTimeOffset = $iTimeOffset; + return $this; + } + /** * @return \MailSo\Log\Driver */ @@ -217,7 +236,7 @@ abstract class Driver protected function getTimeWithMicroSec() { $aMicroTimeItems = \explode(' ', \microtime()); - return \gmdate($this->sDatePattern, $aMicroTimeItems[1]).'.'. + return \MailSo\Log\Logger::DateHelper($this->sDatePattern, $this->iTimeOffset, $aMicroTimeItems[1]).'.'. \str_pad((int) ($aMicroTimeItems[0] * 1000), 3, '0', STR_PAD_LEFT); } @@ -233,21 +252,50 @@ abstract class Driver return isset($this->aPrefixes[$iType]) ? $sName.$this->aPrefixes[$iType].': ' : ''; } + /** + * @param string|array $mDesc + * @param bool $bDiplayCrLf = false + * + * @return string + */ + protected function localWriteImplementation($mDesc, $bDiplayCrLf = false) + { + if ($bDiplayCrLf) + { + if (\is_array($mDesc)) + { + foreach ($mDesc as &$sLine) + { + $sLine = \strtr($sLine, array("\r" => '\r', "\n" => '\n'.$this->sNewLine)); + $sLine = \rtrim($sLine); + } + } + else + { + $mDesc = \strtr($mDesc, array("\r" => '\r', "\n" => '\n'.$this->sNewLine)); + $mDesc = \rtrim($mDesc); + } + } + + return $this->writeImplementation($mDesc); + } + /** * @final * @param string $sDesc * @param int $iType = \MailSo\Log\Enumerations\Type::INFO * @param string $sName = '' + * @param bool $bDiplayCrLf = false * * @return bool */ - final public function Write($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO, $sName = '') + final public function Write($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO, $sName = '', $bDiplayCrLf = false) { $bResult = true; if (!$this->bFlushCache && ($this->bWriteOnErrorOnly || $this->bWriteOnPhpErrorOnly || 0 < $this->iWriteOnTimeoutOnly)) { $bErrorPhp = false; - + $bError = $this->bWriteOnErrorOnly && \in_array($iType, array( \MailSo\Log\Enumerations\Type::NOTICE, \MailSo\Log\Enumerations\Type::NOTICE_PHP, @@ -272,18 +320,18 @@ abstract class Driver if (isset($this->aCache[0]) && empty($this->aCache[0])) { $this->aCache[0] = $sFlush; - array_unshift($this->aCache, ''); + \array_unshift($this->aCache, ''); } else { - array_unshift($this->aCache, $sFlush); + \array_unshift($this->aCache, $sFlush); } $this->aCache[] = '--- FlushLogCache: Trigger'; $this->aCache[] = $this->loggerLineImplementation($this->getTimeWithMicroSec(), $sDesc, $iType, $sName); $this->bFlushCache = true; - $bResult = $this->writeImplementation($this->aCache); + $bResult = $this->localWriteImplementation($this->aCache, $bDiplayCrLf); $this->aCache = array(); } else if (0 < $this->iWriteOnTimeoutOnly && \time() - APP_START_TIME > $this->iWriteOnTimeoutOnly) @@ -292,18 +340,18 @@ abstract class Driver if (isset($this->aCache[0]) && empty($this->aCache[0])) { $this->aCache[0] = $sFlush; - array_unshift($this->aCache, ''); + \array_unshift($this->aCache, ''); } else { - array_unshift($this->aCache, $sFlush); + \array_unshift($this->aCache, $sFlush); } $this->aCache[] = '--- FlushLogCache: Trigger'; $this->aCache[] = $this->loggerLineImplementation($this->getTimeWithMicroSec(), $sDesc, $iType, $sName); $this->bFlushCache = true; - $bResult = $this->writeImplementation($this->aCache); + $bResult = $this->localWriteImplementation($this->aCache, $bDiplayCrLf); $this->aCache = array(); } else @@ -313,13 +361,21 @@ abstract class Driver } else { - $bResult = $this->writeImplementation( - $this->loggerLineImplementation($this->getTimeWithMicroSec(), $sDesc, $iType, $sName)); + $bResult = $this->localWriteImplementation( + $this->loggerLineImplementation($this->getTimeWithMicroSec(), $sDesc, $iType, $sName), $bDiplayCrLf); } return $bResult; } + /** + * @return string + */ + public function GetNewLine() + { + return $this->sNewLine; + } + /** * @final * @return bool diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Log/Drivers/File.php b/rainloop/v/0.0.0/app/libraries/MailSo/Log/Drivers/File.php index 942df84f0..b3c3678c1 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Log/Drivers/File.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Log/Drivers/File.php @@ -23,23 +23,18 @@ class File extends \MailSo\Log\Driver */ private $sLoggerFileName; - /** - * @var string - */ - private $sCrLf; - /** * @access protected * * @param string $sLoggerFileName - * @param string $sCrLf = "\r\n" + * @param string $sNewLine = "\r\n" */ - protected function __construct($sLoggerFileName, $sCrLf = "\r\n") + protected function __construct($sLoggerFileName, $sNewLine = "\r\n") { parent::__construct(); $this->sLoggerFileName = $sLoggerFileName; - $this->sCrLf = $sCrLf; + $this->sNewLine = $sNewLine; } /** @@ -52,13 +47,13 @@ class File extends \MailSo\Log\Driver /** * @param string $sLoggerFileName - * @param string $sCrLf = "\r\n" + * @param string $sNewLine = "\r\n" * * @return \MailSo\Log\Drivers\File */ - public static function NewInstance($sLoggerFileName, $sCrLf = "\r\n") + public static function NewInstance($sLoggerFileName, $sNewLine = "\r\n") { - return new self($sLoggerFileName, $sCrLf); + return new self($sLoggerFileName, $sNewLine); } /** @@ -86,11 +81,11 @@ class File extends \MailSo\Log\Driver */ private function writeToLogFile($mDesc) { - if (is_array($mDesc)) + if (\is_array($mDesc)) { - $mDesc = \implode($this->sCrLf, $mDesc); + $mDesc = \implode($this->sNewLine, $mDesc); } - - return \error_log($mDesc.$this->sCrLf, 3, $this->sLoggerFileName); + + return \error_log($mDesc.$this->sNewLine, 3, $this->sLoggerFileName); } } diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Log/Drivers/Inline.php b/rainloop/v/0.0.0/app/libraries/MailSo/Log/Drivers/Inline.php index 529a3106b..817ffbb5b 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Log/Drivers/Inline.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Log/Drivers/Inline.php @@ -18,11 +18,6 @@ namespace MailSo\Log\Drivers; */ class Inline extends \MailSo\Log\Driver { - /** - * @var string - */ - private $sNewLine; - /** * @var bool */ diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Log/Logger.php b/rainloop/v/0.0.0/app/libraries/MailSo/Log/Logger.php index 3d513f170..49022c446 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Log/Logger.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Log/Logger.php @@ -91,6 +91,21 @@ class Logger extends \MailSo\Base\Collection return $oInstance; } + /** + * @param string $sFormat + * @param int $iTimeOffset = 0 + * @param int $iTimestamp = 0 + * + * @return string + */ + public static function DateHelper($sFormat, $iTimeOffset = 0, $iTimestamp = null) + { + $iTimestamp = null === $iTimestamp ? \time() : (int) $iTimestamp; + $iTimeOffset = (int) $iTimeOffset; + + return \gmdate($sFormat, $iTimestamp + $iTimeOffset * 3600); + } + /** * @return bool */ @@ -150,7 +165,7 @@ class Logger extends \MailSo\Base\Collection */ public function AddSecret($sWord) { - if (0 < \strlen(\trim($sWord))) + if (\is_string($sWord) && 0 < \strlen(\trim($sWord))) { $this->aSecretWords[] = $sWord; $this->aSecretWords = \array_unique($this->aSecretWords); @@ -281,11 +296,13 @@ class Logger extends \MailSo\Base\Collection * @param string $sDesc * @param int $iType = \MailSo\Log\Enumerations\Type::INFO * @param string $sName = '' - * @param bool $bSearchWords = false + * @param bool $bSearchSecretWords = true + * @param bool $bDiplayCrLf = false * * @return bool */ - public function Write($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO, $sName = '', $bSearchWords = false) + public function Write($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO, + $sName = '', $bSearchSecretWords = true, $bDiplayCrLf = false) { if (isset($this->aForbiddenTypes[$iType]) && true === $this->aForbiddenTypes[$iType]) { @@ -298,7 +315,7 @@ class Logger extends \MailSo\Base\Collection $aLoggers = array(); $iResult = 1; - if ($bSearchWords && !$this->bShowSecter && 0 < \count($this->aSecretWords)) + if ($bSearchSecretWords && !$this->bShowSecter && 0 < \count($this->aSecretWords)) { $sDesc = \str_replace($this->aSecretWords, '*******', $sDesc); } @@ -306,7 +323,7 @@ class Logger extends \MailSo\Base\Collection $aLoggers =& $this->GetAsArray(); foreach ($aLoggers as /* @var $oLogger \MailSo\Log\Driver */ $oLogger) { - $iResult &= $oLogger->Write($sDesc, $iType, $sName); + $iResult &= $oLogger->Write($sDesc, $iType, $sName, $bDiplayCrLf); } return (bool) $iResult; @@ -317,12 +334,14 @@ class Logger extends \MailSo\Base\Collection * @param int $iType = \MailSo\Log\Enumerations\Type::INFO * @param string $sName = '' * @param bool $bSearchSecretWords = false + * @param bool $bDiplayCrLf = false * * @return bool */ - public function WriteDump($oValue, $iType = \MailSo\Log\Enumerations\Type::INFO, $sName = '', $bSearchSecretWords = false) + public function WriteDump($oValue, $iType = \MailSo\Log\Enumerations\Type::INFO, $sName = '', + $bSearchSecretWords = false, $bDiplayCrLf = false) { - return $this->Write(\print_r($oValue, true), $iType, $sName, $bSearchSecretWords); + return $this->Write(\print_r($oValue, true), $iType, $sName, $bSearchSecretWords, $bDiplayCrLf); } /** @@ -330,10 +349,12 @@ class Logger extends \MailSo\Base\Collection * @param int $iType = \MailSo\Log\Enumerations\Type::NOTICE * @param string $sName = '' * @param bool $bSearchSecretWords = true + * @param bool $bDiplayCrLf = false * * @return bool */ - public function WriteException($oException, $iType = \MailSo\Log\Enumerations\Type::NOTICE, $sName = '', $bSearchSecretWords = true) + public function WriteException($oException, $iType = \MailSo\Log\Enumerations\Type::NOTICE, $sName = '', + $bSearchSecretWords = true, $bDiplayCrLf = false) { if ($oException instanceof \Exception) { @@ -344,7 +365,34 @@ class Logger extends \MailSo\Base\Collection $oException->__LOGINNED__ = true; - return $this->Write((string) $oException, $iType, $sName, $bSearchSecretWords); + return $this->Write((string) $oException, $iType, $sName, $bSearchSecretWords, $bDiplayCrLf); + } + + return false; + } + + /** + * @param \Exception $oException + * @param int $iType = \MailSo\Log\Enumerations\Type::NOTICE + * @param string $sName = '' + * @param bool $bSearchSecretWords = true + * @param bool $bDiplayCrLf = false + * + * @return bool + */ + public function WriteExceptionShort($oException, $iType = \MailSo\Log\Enumerations\Type::NOTICE, $sName = '', + $bSearchSecretWords = true, $bDiplayCrLf = false) + { + if ($oException instanceof \Exception) + { + if (isset($oException->__LOGINNED__)) + { + return true; + } + + $oException->__LOGINNED__ = true; + + return $this->Write($oException->getMessage(), $iType, $sName, $bSearchSecretWords, $bDiplayCrLf); } return false; @@ -355,10 +403,12 @@ class Logger extends \MailSo\Base\Collection * @param int $iType = \MailSo\Log\Enumerations\Type::NOTICE * @param string $sName = '' * @param bool $bSearchSecretWords = true + * @param bool $bDiplayCrLf = false * * @return bool */ - public function WriteMixed($mData, $iType = null, $sName = '', $bSearchSecretWords = true) + public function WriteMixed($mData, $iType = null, $sName = '', + $bSearchSecretWords = true, $bDiplayCrLf = false) { $iType = null === $iType ? \MailSo\Log\Enumerations\Type::INFO : $iType; if (\is_array($mData) || \is_object($mData)) @@ -366,16 +416,16 @@ class Logger extends \MailSo\Base\Collection if ($mData instanceof \Exception) { $iType = null === $iType ? \MailSo\Log\Enumerations\Type::NOTICE : $iType; - return $this->WriteException($mData, $iType, $sName, $bSearchSecretWords); + return $this->WriteException($mData, $iType, $sName, $bSearchSecretWords, $bDiplayCrLf); } else { - return $this->WriteDump($mData, $iType, $sName, $bSearchSecretWords); + return $this->WriteDump($mData, $iType, $sName, $bSearchSecretWords, $bDiplayCrLf); } } else { - return $this->Write($mData, $iType, $sName, $bSearchSecretWords); + return $this->Write($mData, $iType, $sName, $bSearchSecretWords, $bDiplayCrLf); } return false; diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/FolderCollection.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/FolderCollection.php index 25303c8b6..9f0c00a0e 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/FolderCollection.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/FolderCollection.php @@ -20,7 +20,7 @@ class FolderCollection extends \MailSo\Base\Collection /** * @var string */ - private $sNamespace; + public $Namespace; /** * @var string @@ -49,7 +49,7 @@ class FolderCollection extends \MailSo\Base\Collection { parent::__construct(); - $this->sNamespace = ''; + $this->Namespace = ''; $this->FoldersHash = ''; $this->SystemFolders = array(); $this->IsThreadsSupported = false; @@ -96,12 +96,30 @@ class FolderCollection extends \MailSo\Base\Collection return $mResult; } + /** + * @return int + */ + public function CountRec() + { + $iResult = $this->Count(); + foreach ($this->aItems as /* @var $oFolder \MailSo\Mail\Folder */ $oFolder) + { + if ($oFolder) + { + $oSub = $oFolder->SubFolders(); + $iResult += $oSub ? $oSub->CountRec() : 0; + } + } + + return $iResult; + } + /** * @return string */ public function GetNamespace() { - return $this->sNamespace; + return $this->Namespace; } /** @@ -110,7 +128,7 @@ class FolderCollection extends \MailSo\Base\Collection public function FindDelimiter() { $sDelimiter = '/'; - + $oFolder = $this->GetByFullNameRaw('INBOX'); if (!$oFolder) { @@ -132,7 +150,7 @@ class FolderCollection extends \MailSo\Base\Collection */ public function SetNamespace($sNamespace) { - $this->sNamespace = $sNamespace; + $this->Namespace = $sNamespace; return $this; } @@ -172,8 +190,15 @@ class FolderCollection extends \MailSo\Base\Collection if (!isset($aSortedByLenImapFolders[$sNonExistenFolderFullNameRaw])) { - $aAddedFolders[$sNonExistenFolderFullNameRaw] = - Folder::NewNonExistenInstance($sNonExistenFolderFullNameRaw, $sDelimiter); + try + { + $aAddedFolders[$sNonExistenFolderFullNameRaw] = + Folder::NewNonExistenInstance($sNonExistenFolderFullNameRaw, $sDelimiter); + } + catch (\Exception $oExc) + { + unset($oExc); + } } } } diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php index ce428e586..ea8665381 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php @@ -179,33 +179,41 @@ class MailClient */ private function getEnvelopeOrHeadersRequestString() { - return \MailSo\Imap\Enumerations\FetchType::BODY_HEADER_PEEK; + if (\MailSo\Config::$MessageAllHeaders) + { + return \MailSo\Imap\Enumerations\FetchType::BODY_HEADER_PEEK; + } -// return \MailSo\Imap\Enumerations\FetchType::ENVELOPE; + return \MailSo\Imap\Enumerations\FetchType::BuildBodyCustomHeaderRequest(array( + \MailSo\Mime\Enumerations\Header::RETURN_PATH, + \MailSo\Mime\Enumerations\Header::RECEIVED, + \MailSo\Mime\Enumerations\Header::MIME_VERSION, + \MailSo\Mime\Enumerations\Header::MESSAGE_ID, + \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + \MailSo\Mime\Enumerations\Header::FROM_, + \MailSo\Mime\Enumerations\Header::TO_, + \MailSo\Mime\Enumerations\Header::CC, + \MailSo\Mime\Enumerations\Header::BCC, + \MailSo\Mime\Enumerations\Header::SENDER, + \MailSo\Mime\Enumerations\Header::REPLY_TO, + \MailSo\Mime\Enumerations\Header::DELIVERED_TO, + \MailSo\Mime\Enumerations\Header::IN_REPLY_TO, + \MailSo\Mime\Enumerations\Header::REFERENCES, + \MailSo\Mime\Enumerations\Header::DATE, + \MailSo\Mime\Enumerations\Header::SUBJECT, + \MailSo\Mime\Enumerations\Header::SENSITIVITY, + \MailSo\Mime\Enumerations\Header::X_MSMAIL_PRIORITY, + \MailSo\Mime\Enumerations\Header::IMPORTANCE, + \MailSo\Mime\Enumerations\Header::X_PRIORITY, + \MailSo\Mime\Enumerations\Header::X_DRAFT_INFO, + \MailSo\Mime\Enumerations\Header::RETURN_RECEIPT_TO, + \MailSo\Mime\Enumerations\Header::DISPOSITION_NOTIFICATION_TO, + \MailSo\Mime\Enumerations\Header::X_CONFIRM_READING_TO, + \MailSo\Mime\Enumerations\Header::AUTHENTICATION_RESULTS, + \MailSo\Mime\Enumerations\Header::X_DKIM_AUTHENTICATION_RESULTS, + ), true); // -// return \MailSo\Imap\Enumerations\FetchType::BuildBodyCustomHeaderRequest(array( -// \MailSo\Mime\Enumerations\Header::RETURN_PATH, -// \MailSo\Mime\Enumerations\Header::RECEIVED, -// \MailSo\Mime\Enumerations\Header::MIME_VERSION, -// \MailSo\Mime\Enumerations\Header::MESSAGE_ID, -// \MailSo\Mime\Enumerations\Header::FROM_, -// \MailSo\Mime\Enumerations\Header::TO_, -// \MailSo\Mime\Enumerations\Header::CC, -// \MailSo\Mime\Enumerations\Header::BCC, -// \MailSo\Mime\Enumerations\Header::SENDER, -// \MailSo\Mime\Enumerations\Header::REPLY_TO, -// \MailSo\Mime\Enumerations\Header::IN_REPLY_TO, -// \MailSo\Mime\Enumerations\Header::DATE, -// \MailSo\Mime\Enumerations\Header::SUBJECT, -// \MailSo\Mime\Enumerations\Header::X_MSMAIL_PRIORITY, -// \MailSo\Mime\Enumerations\Header::IMPORTANCE, -// \MailSo\Mime\Enumerations\Header::X_PRIORITY, -// \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, -// \MailSo\Mime\Enumerations\Header::REFERENCES, -// \MailSo\Mime\Enumerations\Header::X_DRAFT_INFO, -// \MailSo\Mime\Enumerations\Header::RECEIVED_SPF, -// \MailSo\Mime\Enumerations\Header::AUTHENTICATION_RESULTS, -// ), true); +// return \MailSo\Imap\Enumerations\FetchType::ENVELOPE; } /** @@ -684,16 +692,25 @@ class MailClient * @param int $iCount * @param int $iUnseenCount * @param string $sUidNext + * @param string $sHighestModSeq * * @return void */ - protected function initFolderValues($sFolderName, &$iCount, &$iUnseenCount, &$sUidNext) + protected function initFolderValues($sFolderName, &$iCount, &$iUnseenCount, + &$sUidNext, &$sHighestModSeq = '') { - $aFolderStatus = $this->oImapClient->FolderStatus($sFolderName, array( + $aTypes = array( \MailSo\Imap\Enumerations\FolderResponseStatus::MESSAGES, \MailSo\Imap\Enumerations\FolderResponseStatus::UNSEEN, \MailSo\Imap\Enumerations\FolderResponseStatus::UIDNEXT - )); + ); + + if ($this->oImapClient->IsSupported('CONDSTORE')) + { + $aTypes[] = \MailSo\Imap\Enumerations\FolderResponseStatus::HIGHESTMODSEQ; + } + + $aFolderStatus = $this->oImapClient->FolderStatus($sFolderName, $aTypes); $iCount = isset($aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::MESSAGES]) ? (int) $aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::MESSAGES] : 0; @@ -704,7 +721,11 @@ class MailClient $sUidNext = isset($aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::UIDNEXT]) ? (string) $aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::UIDNEXT] : '0'; - if ($this->IsGmail()) + $sHighestModSeq = isset($aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::HIGHESTMODSEQ]) + ? (string) $aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::HIGHESTMODSEQ] : ''; + + if ($this->IsGmail() && + ('INBOX' === $sFolderName || '[gmail]' === \strtolower(\substr($sFolderName, 0, 7)))) { $oFolder = $this->oImapClient->FolderCurrentInformation(); if ($oFolder && null !== $oFolder->Exists && $oFolder->FolderName === $sFolderName) @@ -735,14 +756,16 @@ class MailClient * @param int $iCount * @param int $iUnseenCount * @param string $sUidNext + * @param string $sHighestModSeq = '' * * @return string */ - public function GenerateFolderHash($sFolder, $iCount, $iUnseenCount, $sUidNext) + public function GenerateFolderHash($sFolder, $iCount, $iUnseenCount, $sUidNext, $sHighestModSeq = '') { $iUnseenCount = 0; // unneccessery return \md5('FolderHash/'.$sFolder.'-'.$iCount.'-'.$iUnseenCount.'-'.$sUidNext.'-'. - $this->GenerateImapClientHash() + $sHighestModSeq.'-'.$this->GenerateImapClientHash().'-'. + \MailSo\Config::$MessageListPermanentFilter ); } @@ -833,7 +856,8 @@ class MailClient $aFlags = array(); $bSelect = false; - if ($this->IsGmail()) + if ($this->IsGmail() && + ('INBOX' === $sFolderName || '[gmail]' === \strtolower(\substr($sFolderName, 0, 7)))) { $this->oImapClient->FolderSelect($sFolderName); $bSelect = true; @@ -866,16 +890,18 @@ class MailClient $iCount = 0; $iUnseenCount = 0; $sUidNext = '0'; + $sHighestModSeq = ''; - $this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $sUidNext); + $this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $sUidNext, $sHighestModSeq); $aResult = array( 'Folder' => $sFolderName, - 'Hash' => $this->GenerateFolderHash($sFolderName, $iCount, $iUnseenCount, $sUidNext), + 'Hash' => $this->GenerateFolderHash($sFolderName, $iCount, $iUnseenCount, $sUidNext, $sHighestModSeq), 'MessageCount' => $iCount, 'MessageUnseenCount' => $iUnseenCount, 'UidNext' => $sUidNext, 'Flags' => $aFlags, + 'HighestModSeq' => $sHighestModSeq, 'NewMessages' => 'INBOX' === $sFolderName ? $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext) : array() ); @@ -897,10 +923,11 @@ class MailClient $iCount = 0; $iUnseenCount = 0; $sUidNext = '0'; + $sHighestModSeq = ''; - $this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $sUidNext); + $this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $sUidNext, $sHighestModSeq); - return $this->GenerateFolderHash($sFolderName, $iCount, $iUnseenCount, $sUidNext); + return $this->GenerateFolderHash($sFolderName, $iCount, $iUnseenCount, $sUidNext, $sHighestModSeq); } /** @@ -1013,7 +1040,7 @@ class MailClient $sReg = 'e?mail|from|to|subject|has|is|date|text|body|size|larger|bigger|smaller|maxsize|minsize'; - $sSearch = \trim(\preg_replace('/[\s]+/', ' ', $sSearch)); + $sSearch = \MailSo\Base\Utils::StripSpaces($sSearch); $sSearch = \trim(\preg_replace('/('.$sReg.'): /i', '\\1:', $sSearch)); $mMatch = array(); @@ -1060,7 +1087,7 @@ class MailClient $sSearch = \str_replace($sToken, '', $sSearch); } - $sSearch = \trim(\preg_replace('/[\s]+/', ' ', $sSearch)); + $sSearch = \MailSo\Base\Utils::StripSpaces($sSearch); } foreach ($mMatch[1] as $iIndex => $sName) @@ -1124,12 +1151,13 @@ class MailClient /** * @param string $sSearch + * @param string $sFilter * @param int $iTimeZoneOffset = 0 * @param bool $bUseCache = true * * @return string */ - private function getImapSearchCriterias($sSearch, $iTimeZoneOffset = 0, &$bUseCache = true) + private function getImapSearchCriterias($sSearch, $sFilter, $iTimeZoneOffset = 0, &$bUseCache = true) { $bUseCache = true; $iTimeFilter = 0; @@ -1317,12 +1345,9 @@ class MailClient { $aCriteriasResult[] = 'SINCE'; $aCriteriasResult[] = \gmdate('j-M-Y', $iTimeFilter > $iDateStampFrom ? - $iDateStampFrom : $iTimeFilter); + $iTimeFilter : $iDateStampFrom); - if (0 < $iTimeFilter && $iTimeFilter > $iDateStampFrom) - { - $iTimeFilter = 0; - } + $iTimeFilter = 0; } if (0 < $iDateStampTo) @@ -1336,7 +1361,7 @@ class MailClient if ('' !== \trim($sMainText)) { - $sMainText = \trim(\trim(preg_replace('/[\s]+/', ' ', $sMainText)), '"'); + $sMainText = \trim(\MailSo\Base\Utils::StripSpaces($sMainText), '"'); if ($bIsGmail) { $sGmailRawSearch .= ' '.$sMainText; @@ -1370,6 +1395,21 @@ class MailClient $sCriteriasResult .= ' SINCE '.\gmdate('j-M-Y', $iTimeFilter); } + $sCriteriasResult = \trim($sCriteriasResult); + $sCriteriasResult .= ' NOT DELETED'; + + $sFilter = \trim($sFilter); + if ('' !== $sFilter) + { + $sCriteriasResult .= ' '.$sFilter; + } + + $sCriteriasResult = \trim($sCriteriasResult); + if ('' !== \MailSo\Config::$MessageListPermanentFilter) + { + $sCriteriasResult .= ' '.\MailSo\Config::$MessageListPermanentFilter; + } + $sCriteriasResult = \trim($sCriteriasResult); if ('' === $sCriteriasResult) { @@ -1658,7 +1698,8 @@ class MailClient \MailSo\Imap\Enumerations\FetchType::INTERNALDATE, \MailSo\Imap\Enumerations\FetchType::FLAGS, \MailSo\Imap\Enumerations\FetchType::BODYSTRUCTURE, - $bSimple ? $this->getEnvelopeOrHeadersRequestStringForSimpleList() : + $bSimple ? + $this->getEnvelopeOrHeadersRequestStringForSimpleList() : $this->getEnvelopeOrHeadersRequestString() ), \MailSo\Base\Utils::PrepearFetchSequence($aRequestIndexOrUids), $bIndexAsUid); @@ -1701,31 +1742,66 @@ class MailClient } /** - * @param string $sSearch * @param string $sFolderName - * @param string|bool $sFolderHash - * @param bool $bUseSortIfSupported = true - * @param bool $bUseESearchOrESortRequest = false - * @param \MailSo\Cache\CacheClient|null $oCacher = null + * @param array $aUids * - * @return Array|bool + * @return \MailSo\Mail\MessageCollection + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception */ - private function getSearchUidsResult($sSearch, $sFolderName, $sFolderHash, - $bUseSortIfSupported = true, $bUseESearchOrESortRequest = false, $oCacher = null) + public function MessageListSimple($sFolderName, $aUids) + { + if (0 === \strlen($sFolderName) || !\MailSo\Base\Validator::NotEmptyArray($aUids)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oImapClient->FolderExamine($sFolderName); + + $oMessageCollection = \MailSo\Mail\MessageCollection::NewInstance(); + $oMessageCollection->FolderName = $sFolderName; + + $this->MessageListByRequestIndexOrUids($oMessageCollection, $aUids, true, true); + + return $oMessageCollection->GetAsArray(); + } + + /** + * @param \MailSo\Cache\CacheClient|null $oCacher + * @param string $sSearch + * @param string $sFilter + * @param string $sFolderName + * @param string $sFolderHash + * @param bool $bUseSortIfSupported = false + * + * @return array + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function GetUids($oCacher, $sSearch, $sFilter, $sFolderName, $sFolderHash, $bUseSortIfSupported = false) { $aResultUids = false; $bUidsFromCacher = false; $bUseCacheAfterSearch = true; + $sSerializedHash = ''; + $sSerializedLog = ''; - $bESortSupported = $bUseSortIfSupported && $bUseESearchOrESortRequest ? $this->oImapClient->IsSupported('ESORT') : false; - $bESearchSupported = $bUseESearchOrESortRequest ? $this->oImapClient->IsSupported('ESEARCH') : false; - $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; + $bUseSortIfSupported = $bUseSortIfSupported ? !!$this->oImapClient->IsSupported('SORT') : false; - $sSearchCriterias = $this->getImapSearchCriterias($sSearch, 0, $bUseCacheAfterSearch); + if (0 < \strlen($sSearch)) + { + $bUseSortIfSupported = false; + } + + $sSearchCriterias = $this->getImapSearchCriterias($sSearch, $sFilter, 0, $bUseCacheAfterSearch); if ($bUseCacheAfterSearch && $oCacher && $oCacher->IsInited()) { - $sSerializedHash = 'SearchSortUids/'. + $sSerializedHash = 'GetUids/'. ($bUseSortIfSupported ? 'S': 'N').'/'. $this->GenerateImapClientHash().'/'. $sFolderName.'/'.$sSearchCriterias; @@ -1754,71 +1830,10 @@ class MailClient if (!\is_array($aResultUids)) { - if ($bUseSortIfSupported) - { - if ($bESortSupported) - { - $aESorthData = $this->oImapClient->MessageSimpleESort(array('ARRIVAL'), $sSearchCriterias, array('ALL'), true, ''); - if (isset($aESorthData['ALL'])) - { - $aResultUids = \MailSo\Base\Utils::ParseFetchSequence($aESorthData['ALL']); - $aResultUids = \array_reverse($aResultUids); - } - - unset($aESorthData); - } - else - { - $aResultUids = $this->oImapClient->MessageSimpleSort(array('REVERSE ARRIVAL'), $sSearchCriterias, true); - } - } - else - { - if (!\MailSo\Base\Utils::IsAscii($sSearch)) - { - try - { - if ($bESearchSupported) - { - $aESearchData = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, array('ALL'), true, '', 'UTF-8'); - if (isset($aESearchData['ALL'])) - { - $aResultUids = \MailSo\Base\Utils::ParseFetchSequence($aESearchData['ALL']); - $aResultUids = \array_reverse($aResultUids); - } - unset($aESearchData); - } - else - { - $aResultUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, true, 'UTF-8'); - } - } - catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) - { - $oException = null; - $aResultUids = false; - } - } - - if (false === $aResultUids) - { - if ($bESearchSupported) - { - $aESearchData = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, array('ALL'), true); - if (isset($aESearchData['ALL'])) - { - $aResultUids = \MailSo\Base\Utils::ParseFetchSequence($aESearchData['ALL']); - $aResultUids = \array_reverse($aResultUids); - } - - unset($aESearchData); - } - else - { - $aResultUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, true); - } - } - } + $aResultUids = $bUseSortIfSupported ? + $this->oImapClient->MessageSimpleSort(array('REVERSE ARRIVAL'), $sSearchCriterias, true) : + $this->oImapClient->MessageSimpleSearch($sSearchCriterias, true) + ; if (!$bUidsFromCacher && $bUseCacheAfterSearch && \is_array($aResultUids) && $oCacher && $oCacher->IsInited() && 0 < \strlen($sSerializedHash)) { @@ -1837,80 +1852,6 @@ class MailClient return $aResultUids; } - /** - * @param string $sFolderName - * @param string $sFolderHash - * @param string $sUid - * @param \MailSo\Cache\CacheClient|null $oCacher = null - * - * @return array - */ - public function MessageThreadUidsFromCache($sFolderName, $sFolderHash, $sUid, $oCacher = null) - { - $aResult = array(); - if (0 < \strlen($sFolderName) && 0 < \strlen($sFolderHash) && 0 < \strlen($sUid) && $oCacher && $oCacher->IsInited()) - { - $mThreads = $this->MessageListThreadsMap($sFolderName, $sFolderHash, array(), $oCacher, true); - - if (\is_array($mThreads)) - { - $iUid = (int) $sUid; - foreach ($mThreads as $iSubUid => $aSubUids) - { - if ($iUid === $iSubUid) - { - $aResult = $aSubUids; - if (!\is_array($aResult)) - { - $aResult = array(); - } - - \array_unshift($aResult, $iSubUid); - break; - } - else if (\is_array($aSubUids)) - { - if (\in_array($iUid, $aSubUids)) - { - $aResult = $aSubUids; - \array_unshift($aResult, $iSubUid); - break; - } - } - } - } - } - - return \array_map('trim', $aResult); - } - - /** - * @param string $sFolderName - * @param array $aUids - * - * @return \MailSo\Mail\MessageCollection - * - * @throws \MailSo\Base\Exceptions\InvalidArgumentException - * @throws \MailSo\Net\Exceptions\Exception - * @throws \MailSo\Imap\Exceptions\Exception - */ - public function MessageListSimple($sFolderName, $aUids) - { - if (0 === \strlen($sFolderName) || !\MailSo\Base\Validator::NotEmptyArray($aUids)) - { - throw new \MailSo\Base\Exceptions\InvalidArgumentException(); - } - - $this->oImapClient->FolderExamine($sFolderName); - - $oMessageCollection = \MailSo\Mail\MessageCollection::NewInstance(); - $oMessageCollection->FolderName = $sFolderName; - - $this->MessageListByRequestIndexOrUids($oMessageCollection, $aUids, true, true); - - return $oMessageCollection->GetAsArray(); - } - /** * @param string $sFolderName * @param int $iOffset = 0 @@ -1921,6 +1862,8 @@ class MailClient * @param bool $bUseSortIfSupported = false * @param bool $bUseThreadSortIfSupported = false * @param bool $bUseESearchOrESortRequest = false + * @param string $sThreadUid = '' + * @param string $sFilter = '' * * @return \MailSo\Mail\MessageCollection * @@ -1929,8 +1872,9 @@ class MailClient * @throws \MailSo\Imap\Exceptions\Exception */ public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', $oCacher = null, - $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $bUseESearchOrESortRequest = false) + $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $sThreadUid = '', $sFilter = '') { + $sFilter = \trim($sFilter); $sSearch = \trim($sSearch); if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) || !\MailSo\Base\Validator::RangeInt($iLimit, 0, 999)) @@ -1938,6 +1882,8 @@ class MailClient throw new \MailSo\Base\Exceptions\InvalidArgumentException(); } + $bUseFilter = '' !== $sFilter; + $this->oImapClient->FolderSelect($sFolderName); $oMessageCollection = MessageCollection::NewInstance(); @@ -1945,30 +1891,52 @@ class MailClient $oMessageCollection->Offset = $iOffset; $oMessageCollection->Limit = $iLimit; $oMessageCollection->Search = $sSearch; + $oMessageCollection->ThreadUid = $sThreadUid; + $oMessageCollection->Filtered = '' !== \MailSo\Config::$MessageListPermanentFilter; - $aThreads = array(); + $aUids = array(); + $mAllSortedUids = null; + $mAllThreads = null; + + $iThreadUid = empty($sThreadUid) ? 0 : (int) $sThreadUid; - $iMessageCount = 0; $iMessageRealCount = 0; $iMessageUnseenCount = 0; $sUidNext = '0'; + $sHighestModSeq = ''; $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; $bUseThreadSortIfSupported = $bUseThreadSortIfSupported ? ($this->oImapClient->IsSupported('THREAD=REFS') || $this->oImapClient->IsSupported('THREAD=REFERENCES') || $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT')) : false; + if (!empty($sThreadUid) && !$bUseThreadSortIfSupported) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + if (!$oCacher || !($oCacher instanceof \MailSo\Cache\CacheClient)) { $oCacher = null; } - $this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); - $iMessageCount = $iMessageRealCount; + $this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext, $sHighestModSeq); + + if ($bUseFilter) + { + $iMessageUnseenCount = 0; + } + + $oMessageCollection->FolderHash = $this->GenerateFolderHash( + $sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext, $sHighestModSeq); - $oMessageCollection->FolderHash = $this->GenerateFolderHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); $oMessageCollection->UidNext = $sUidNext; - $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext); + + if (empty($sThreadUid) && 0 < \strlen($sPrevUidNext) && 'INBOX' === $sFolderName) + { + $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation( + $sFolderName, $sPrevUidNext, $sUidNext); + } $bSearch = false; $bMessageListOptimization = 0 < \MailSo\Config::$MessageListCountLimitTrigger && @@ -1978,98 +1946,121 @@ class MailClient { $bUseSortIfSupported = false; $bUseThreadSortIfSupported = false; - $bUseESearchOrESortRequest = false; } if (0 < $iMessageRealCount) { - $bIndexAsUid = false; - $aIndexOrUids = array(); + $mAllSortedUids = $this->GetUids($oCacher, '', $sFilter, + $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported); - if (0 < \strlen($sSearch)) - { - $aIndexOrUids = $this->getSearchUidsResult($sSearch, - $oMessageCollection->FolderName, $oMessageCollection->FolderHash, - $bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher); + $mAllThreads = $bUseThreadSortIfSupported ? $this->MessageListThreadsMap( + $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $mAllSortedUids, $oCacher) : null; - $bIndexAsUid = true; - } - else + if ($bUseThreadSortIfSupported && 0 < $iThreadUid && \is_array($mAllThreads)) { - if ($bUseThreadSortIfSupported && 1 < $iMessageCount) + $aUids = array(); + $iResultRootUid = 0; + + if (isset($mAllThreads[$iThreadUid])) { - $aIndexOrUids = $this->getSearchUidsResult('', - $oMessageCollection->FolderName, $oMessageCollection->FolderHash, - $bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher); - - $aThreads = $this->MessageListThreadsMap( - $oMessageCollection->FolderName, $oMessageCollection->FolderHash, - $aIndexOrUids, $oCacher); - - $aNewIndexOrUids = array(); - foreach ($aIndexOrUids as $iUid) + $iResultRootUid = $iThreadUid; + if (\is_array($mAllThreads[$iThreadUid])) { - if (isset($aThreads[$iUid])) - { - $aNewIndexOrUids[] = $iUid; - } + $aUids = $mAllThreads[$iThreadUid]; } - - $aIndexOrUids = $aNewIndexOrUids; - unset($aNewIndexOrUids); - - $iMessageCount = \count($aIndexOrUids); - $bIndexAsUid = true; } else { - $aIndexOrUids = array(1); - $bIndexAsUid = false; - - if (1 < $iMessageCount) + foreach ($mAllThreads as $iRootUid => $mSubUids) { - if (0 === \MailSo\Config::$MessageListDateFilter && - ($bMessageListOptimization || !$bUseSortIfSupported)) + if (\is_array($mSubUids) && \in_array($iThreadUid, $mSubUids)) { - $aIndexOrUids = \array_reverse(\range(1, $iMessageCount)); - } - else - { - $aIndexOrUids = $this->getSearchUidsResult('', - $oMessageCollection->FolderName, $oMessageCollection->FolderHash, - $bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher); - - $bIndexAsUid = true; + $iResultRootUid = $iRootUid; + $aUids = $mSubUids; + continue; } } } + + if (0 < $iResultRootUid && \in_array($iResultRootUid, $mAllSortedUids)) + { + \array_unshift($aUids, $iResultRootUid); + } + } + else if ($bUseThreadSortIfSupported && \is_array($mAllThreads)) + { + $aUids = \array_keys($mAllThreads); + } + else + { + $bUseThreadSortIfSupported = false; + $aUids = $mAllSortedUids; } - if (\is_array($aIndexOrUids)) + if (0 < \strlen($sSearch) && \is_array($aUids)) + { + $aSearchedUids = $this->GetUids($oCacher, $sSearch, $sFilter, + $oMessageCollection->FolderName, $oMessageCollection->FolderHash); + + if (\is_array($aSearchedUids) && 0 < \count($aSearchedUids)) + { + $aFlippedSearchedUids = \array_flip($aSearchedUids); + + $bSearch = true; + $aNewUids = array(); + + foreach ($aUids as $iUid) + { + if (isset($aFlippedSearchedUids[$iUid])) + { + $aNewUids[] = $iUid; + } + else if ($bUseThreadSortIfSupported && 0 === $iThreadUid && isset($mAllThreads[$iUid]) && \is_array($mAllThreads[$iUid])) + { + foreach ($mAllThreads[$iUid] as $iSubUid) + { + if (isset($aFlippedSearchedUids[$iSubUid])) + { + $aNewUids[] = $iUid; + continue; + } + } + } + } + + $aUids = \array_unique($aNewUids); + unset($aNewUids); + } + else + { + $aUids = array(); + } + } + + if (\is_array($aUids)) { $oMessageCollection->MessageCount = $iMessageRealCount; $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; - $oMessageCollection->MessageResultCount = 0 === \strlen($sSearch) - ? $iMessageCount : \count($aIndexOrUids); + $oMessageCollection->MessageResultCount = \count($aUids); - if (0 < \count($aIndexOrUids)) + if (0 < \count($aUids)) { $iOffset = (0 > $iOffset) ? 0 : $iOffset; - $aRequestIndexOrUids = \array_slice($aIndexOrUids, $iOffset, $iLimit); + $aRequestUids = \array_slice($aUids, $iOffset, $iLimit); - $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexOrUids, $bIndexAsUid); + $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestUids, true); } } } - if (!$bSearch && $bUseThreadSortIfSupported && 0 < \count($aThreads)) + if ($bUseThreadSortIfSupported && 0 === $iThreadUid && \is_array($mAllThreads) && 0 < \count($mAllThreads)) { - $oMessageCollection->ForeachList(function (/* @var $oMessage \MailSo\Mail\Message */ $oMessage) use ($aThreads) { + $oMessageCollection->ForeachList(function (/* @var $oMessage \MailSo\Mail\Message */ $oMessage) use ($mAllThreads) { $iUid = $oMessage->Uid(); - if (isset($aThreads[$iUid]) && \is_array($aThreads[$iUid]) && 0 < \count($aThreads[$iUid])) + if (isset($mAllThreads[$iUid]) && \is_array($mAllThreads[$iUid]) && 0 < \count($mAllThreads[$iUid])) { - $aSubThreads = $aThreads[$iUid]; + $aSubThreads = $mAllThreads[$iUid]; \array_unshift($aSubThreads, $iUid); $oMessage->SetThreads(\array_map('trim', $aSubThreads)); @@ -2263,7 +2254,10 @@ class MailClient { $aSubscribedFolders = $this->oImapClient->FolderSubscribeList($sParent, $sListPattern); } - catch (\Exception $oException) {} + catch (\Exception $oException) + { + unset($oException); + } } $aImapSubscribedFoldersHelper = null; @@ -2336,7 +2330,6 @@ class MailClient $oFolderCollection->IsThreadsSupported = $this->IsThreadsSupported(); } - return $oFolderCollection; } @@ -2554,7 +2547,7 @@ class MailClient $this->oImapClient->FolderSelect($sFolderFullNameRaw); $oFolderInformation = $this->oImapClient->FolderCurrentInformation(); - if ($oFolderInformation && 0 < $oFolderInformation->Exists) // STATUS? + if ($oFolderInformation && $oFolderInformation->Exists && 0 < $oFolderInformation->Exists) // STATUS? { $this->oImapClient->MessageStoreFlag('1:*', false, array(\MailSo\Imap\Enumerations\MessageFlag::DELETED), diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/Message.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/Message.php index 7424f1bbf..029b5b748 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/Message.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/Message.php @@ -620,8 +620,8 @@ class Message $this->oDeliveredTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::DELIVERED_TO, $bCharsetAutoDetect); $this->sInReplyTo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IN_REPLY_TO); - $this->sReferences = \trim(\preg_replace('/[\s]+/', ' ', - $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::REFERENCES))); + $this->sReferences = \MailSo\Base\Utils::StripSpaces( + $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::REFERENCES)); $sHeaderDate = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DATE); $this->sHeaderDate = $sHeaderDate; @@ -751,8 +751,8 @@ class Message $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8; } - $sHtmlParts = array(); - $sPlainParts = array(); + $aHtmlParts = array(); + $aPlainParts = array(); foreach ($aTextParts as $oPart) { @@ -782,22 +782,27 @@ class Message if ('text/html' === $oPart->ContentType()) { - $sHtmlParts[] = $sText; + $aHtmlParts[] = $sText; } else { - $sPlainParts[] = $sText; + if ($oPart->IsFlowedFormat()) + { + $sText = \MailSo\Base\Utils::DecodeFlowedFormat($sText); + } + + $aPlainParts[] = $sText; } } } - if (0 < \count($sHtmlParts)) + if (0 < \count($aHtmlParts)) { - $this->sHtml = \implode('
', $sHtmlParts); + $this->sHtml = \implode('
', $aHtmlParts); } else { - $this->sPlain = \trim(\implode("\n", $sPlainParts)); + $this->sPlain = \trim(\implode("\n", $aPlainParts)); } $aMatch = array(); @@ -813,7 +818,7 @@ class Message $this->bPgpEncrypted = true; } - unset($sHtmlParts, $sPlainParts, $aMatch); + unset($aHtmlParts, $aPlainParts, $aMatch); } // if (empty($this->sPgpSignature) && 'multipart/signed' === \strtolower($this->sContentType) && diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MessageCollection.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MessageCollection.php index 34c8cf884..427a18cac 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MessageCollection.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MessageCollection.php @@ -62,15 +62,20 @@ class MessageCollection extends \MailSo\Base\Collection */ public $UidNext; + /** + * @var string + */ + public $ThreadUid; + /** * @var array */ public $NewMessages; /** - * @var array + * @var bool */ - public $LastCollapsedThreadUids; + public $Filtered; /** * @access protected @@ -108,9 +113,10 @@ class MessageCollection extends \MailSo\Base\Collection $this->Limit = 0; $this->Search = ''; $this->UidNext = ''; + $this->ThreadUid = ''; $this->NewMessages = array(); - - $this->LastCollapsedThreadUids = array(); + + $this->Filtered = false; return $this; } diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Email.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Email.php index 5e1b8ad68..ee03c6720 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Email.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Email.php @@ -201,6 +201,8 @@ class Email } $sEmail = \trim(\trim($sEmail), '<>'); + $sEmail = \rtrim(\trim($sEmail), '.'); + $sEmail = \trim($sEmail); $sName = \trim(\trim($sName), '"'); $sName = \trim($sName, '\''); diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Enumerations/Parameter.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Enumerations/Parameter.php index 8facb3ecd..c175df43d 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Enumerations/Parameter.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Enumerations/Parameter.php @@ -21,6 +21,7 @@ class Parameter const CHARSET = 'charset'; const NAME = 'name'; const FILENAME = 'filename'; + const FORMAT = 'format'; const BOUNDARY = 'boundary'; const PROTOCOL = 'protocol'; } diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Message.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Message.php index 7bfaec046..44dfa80b4 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Message.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Message.php @@ -257,7 +257,7 @@ class Message public function SetReferences($sReferences) { $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::REFERENCES] = - \trim(\preg_replace('/[\s]+/', ' ', $sReferences)); + \MailSo\Base\Utils::StripSpaces($sReferences); return $this; } @@ -511,7 +511,8 @@ class Message */ private function generateNewBoundary() { - return '----=_Part_'.rand(100, 999).'_'.rand(100000000, 999999999).'.'.time(); + return '--='.\MailSo\Config::$BoundaryPrefix. + \rand(100, 999).'_'.rand(100000000, 999999999).'.'.\time(); } /** diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Part.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Part.php index 9ae9c3aa5..2e19af03f 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Part.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Part.php @@ -210,6 +210,27 @@ class Part \MailSo\Mime\Enumerations\Header::CONTENT_LOCATION)) : ''; } + /** + * @return bool + */ + public function IsFlowedFormat() + { + $bResult = false; + if ($this->Headers) + { + $bResult = 'flowed' === \trim(\strtolower($this->Headers->ParameterValue( + \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + \MailSo\Mime\Enumerations\Parameter::FORMAT))); + + if ($bResult && \in_array(\strtolower($this->MailEncodingName()), array('base64', 'quoted-printable'))) + { + $bResult = false; + } + } + + return $bResult; + } + /** * @return string */ diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php index 1eec18afe..3812b6911 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php @@ -557,11 +557,11 @@ abstract class NetClient * * @return void */ - protected function writeLog($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO) + protected function writeLog($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO, $bDiplayCrLf = false) { if ($this->oLogger) { - $this->oLogger->Write($sDesc, $iDescType, $this->getLogName()); + $this->oLogger->Write($sDesc, $iDescType, $this->getLogName(), true, $bDiplayCrLf); } } @@ -573,7 +573,7 @@ abstract class NetClient */ protected function writeLogWithCrlf($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO) { - $this->writeLog(\strtr($sDesc, array("\r" => '\r', "\n" => '\n')), $iDescType); + $this->writeLog($sDesc, $iDescType, true); } /** diff --git a/rainloop/v/0.0.0/app/libraries/PHPThumb/GD.php b/rainloop/v/0.0.0/app/libraries/PHPThumb/GD.php index 190d8a0ad..733fe476c 100644 --- a/rainloop/v/0.0.0/app/libraries/PHPThumb/GD.php +++ b/rainloop/v/0.0.0/app/libraries/PHPThumb/GD.php @@ -1353,13 +1353,13 @@ class GD extends PHPThumb switch ($this->format) { case 'GIF': - $isCompatible = $gdInfo['GIF Create Support']; + $isCompatible = isset($gdInfo['GIF Create Support']); break; case 'JPG': $isCompatible = (isset($gdInfo['JPG Support']) || isset($gdInfo['JPEG Support'])) ? true : false; break; case 'PNG': - $isCompatible = $gdInfo[$this->format . ' Support']; + $isCompatible = isset($gdInfo[$this->format . ' Support']); break; default: $isCompatible = false; @@ -1367,7 +1367,7 @@ class GD extends PHPThumb if (!$isCompatible) { // one last check for "JPEG" instead - $isCompatible = $gdInfo['JPEG Support']; + $isCompatible = isset($gdInfo['JPEG Support']); if (!$isCompatible) { throw new \Exception("Your GD installation does not support {$this->format} image types"); diff --git a/rainloop/v/0.0.0/app/libraries/PHPThumb/PHPThumb.php b/rainloop/v/0.0.0/app/libraries/PHPThumb/PHPThumb.php index 7521b9d90..a86c8c91e 100644 --- a/rainloop/v/0.0.0/app/libraries/PHPThumb/PHPThumb.php +++ b/rainloop/v/0.0.0/app/libraries/PHPThumb/PHPThumb.php @@ -27,11 +27,6 @@ abstract class PHPThumb */ protected $fileName; - /** - * @var \Symfony\Component\Filesystem\Filesystem - */ - protected $filesystem; - /** * What the file format is (mime-type) * @@ -59,7 +54,6 @@ abstract class PHPThumb */ public function __construct($fileName, array $options = array(), array $plugins = array()) { - $this->filesystem = new \Symfony\Component\Filesystem\Filesystem(); $this->fileName = $fileName; $this->remoteImage = false; @@ -89,9 +83,9 @@ abstract class PHPThumb return true; } - if($this->filesystem->exists($filename)) { - return true; - } + if (file_exists($filename)) { + return true; + } return false; } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/.gitignore b/rainloop/v/0.0.0/app/libraries/RainLoop/.gitignore new file mode 100644 index 000000000..416618dd3 --- /dev/null +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/.gitignore @@ -0,0 +1,2 @@ +/Prem/** +/_Prem/** \ No newline at end of file diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php index 713062acf..88759c1b5 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -110,6 +110,11 @@ class Actions */ private $oTwoFactorAuthProvider; + /** + * @var \RainLoop\Providers\Prem + */ + private $oPremProvider; + /** * @var \RainLoop\Config\Application */ @@ -146,6 +151,7 @@ class Actions $this->oSuggestionsProvider = null; $this->oChangePasswordProvider = null; $this->oTwoFactorAuthProvider = null; + $this->oPremProvider = null; $this->sSpecAuthToken = ''; @@ -188,9 +194,8 @@ class Actions */ public function GetShortLifeSpecAuthToken($iLife = 60) { - $sToken = $this->getAuthToken(); - $aAccountHash = \RainLoop\Utils::DecodeKeyValues($sToken); - if (!empty($aAccountHash[0]) && 'token' === $aAccountHash[0] && is_array($aAccountHash)) + $aAccountHash = \RainLoop\Utils::DecodeKeyValues($this->getLocalAuthToken()); + if (!empty($aAccountHash[0]) && 'token' === $aAccountHash[0] && \is_array($aAccountHash)) { $aAccountHash[10] = \time() + $iLife; return \RainLoop\Utils::EncodeKeyValues($aAccountHash); @@ -235,74 +240,77 @@ class Actions */ private function fabrica($sName, $oAccount = null) { - $oResult = null; + $mResult = null; $this->Plugins() - ->RunHook('main.fabrica', array($sName, &$oResult), false) - ->RunHook('main.fabrica[2]', array($sName, &$oResult, $oAccount), false) + ->RunHook('main.fabrica', array($sName, &$mResult), false) + ->RunHook('main.fabrica[2]', array($sName, &$mResult, $oAccount), false) ; - if (null === $oResult) + if (null === $mResult) { switch ($sName) { case 'files': // RainLoop\Providers\Files\IFiles - $oResult = new \RainLoop\Providers\Files\FileStorage(APP_PRIVATE_DATA.'storage/files'); + $mResult = new \RainLoop\Providers\Files\FileStorage(APP_PRIVATE_DATA.'storage/files'); break; case 'storage': case 'storage-local': // RainLoop\Providers\Storage\IStorage - $oResult = new \RainLoop\Providers\Storage\FileStorage( + $mResult = new \RainLoop\Providers\Storage\FileStorage( APP_PRIVATE_DATA.'storage', 'storage-local' === $sName); break; case 'settings': case 'settings-local': // RainLoop\Providers\Settings\ISettings - $oResult = new \RainLoop\Providers\Settings\DefaultSettings( + $mResult = new \RainLoop\Providers\Settings\DefaultSettings( $this->StorageProvider('settings-local' === $sName)); break; case 'login': // \RainLoop\Providers\Login\LoginInterface - $oResult = new \RainLoop\Providers\Login\DefaultLogin(); + $mResult = new \RainLoop\Providers\Login\DefaultLogin(); break; case 'domain': // \RainLoop\Providers\Domain\DomainAdminInterface - $oResult = new \RainLoop\Providers\Domain\DefaultDomain(APP_PRIVATE_DATA.'domains', $this->Cacher()); + $mResult = new \RainLoop\Providers\Domain\DefaultDomain(APP_PRIVATE_DATA.'domains', $this->Cacher()); break; case 'filters': // \RainLoop\Providers\Filters\FiltersInterface - $oResult = new \RainLoop\Providers\Filters\SieveStorage( + $mResult = new \RainLoop\Providers\Filters\SieveStorage( $this->Plugins(), $this->Config() ); break; case 'address-book': // \RainLoop\Providers\AddressBook\AddressBookInterface - if (!\RainLoop\Utils::IsOwnCloud()) // disabled for ownCloud - { - $sDsn = \trim($this->Config()->Get('contacts', 'pdo_dsn', '')); - $sUser = \trim($this->Config()->Get('contacts', 'pdo_user', '')); - $sPassword = (string) $this->Config()->Get('contacts', 'pdo_password', ''); + $sDsn = \trim($this->Config()->Get('contacts', 'pdo_dsn', '')); + $sUser = \trim($this->Config()->Get('contacts', 'pdo_user', '')); + $sPassword = (string) $this->Config()->Get('contacts', 'pdo_password', ''); - $sDsnType = $this->ValidateContactPdoType(\trim($this->Config()->Get('contacts', 'type', 'sqlite'))); - if ('sqlite' === $sDsnType) - { - $oResult = new \RainLoop\Providers\AddressBook\PdoAddressBook( - 'sqlite:'.APP_PRIVATE_DATA.'AddressBook.sqlite', '', '', 'sqlite'); - } - else - { - $oResult = new \RainLoop\Providers\AddressBook\PdoAddressBook($sDsn, $sUser, $sPassword, $sDsnType); - } + $sDsnType = $this->ValidateContactPdoType(\trim($this->Config()->Get('contacts', 'type', 'sqlite'))); + if ('sqlite' === $sDsnType) + { + $mResult = new \RainLoop\Providers\AddressBook\PdoAddressBook( + 'sqlite:'.APP_PRIVATE_DATA.'AddressBook.sqlite', '', '', 'sqlite'); + } + else + { + $mResult = new \RainLoop\Providers\AddressBook\PdoAddressBook($sDsn, $sUser, $sPassword, $sDsnType); } break; case 'suggestions': - // \RainLoop\Providers\Suggestions\ISuggestions -// $oResult = new \RainLoop\Providers\Suggestions\TestSuggestions(); - if (\RainLoop\Utils::IsOwnCloud()) + if (null === $mResult) { - $oResult = new \RainLoop\Providers\Suggestions\OwnCloudSuggestions(); + $mResult = array(); + } + + // \RainLoop\Providers\Suggestions\ISuggestions +// $mResult[] = new \RainLoop\Providers\Suggestions\TestSuggestions(); + + if (\is_array($mResult) && \RainLoop\Utils::IsOwnCloud()) + { + $mResult[] = new \RainLoop\Providers\Suggestions\OwnCloudSuggestions(); } break; @@ -311,19 +319,22 @@ class Actions break; case 'two-factor-auth': // \RainLoop\Providers\TwoFactorAuth\TwoFactorAuthInterface - $oResult = new \RainLoop\Providers\TwoFactorAuth\GoogleTwoFactorAuth(); + $mResult = new \RainLoop\Providers\TwoFactorAuth\GoogleTwoFactorAuth(); break; } } - if ($oResult && \method_exists($oResult, 'SetLogger')) + foreach (\is_array($mResult) ? $mResult : array($mResult) as $oItem) { - $oResult->SetLogger($this->Logger()); + if ($oItem && \method_exists($oItem, 'SetLogger')) + { + $oItem->SetLogger($this->Logger()); + } } - $this->Plugins()->RunHook('filter.fabrica', array($sName, &$oResult, $oAccount), false); + $this->Plugins()->RunHook('filter.fabrica', array($sName, &$mResult, $oAccount), false); - return $oResult; + return $mResult; } /** @@ -400,15 +411,17 @@ class Actions /** * @param string $sLine * @param \RainLoop\Model\Account $oAccount = null + * @param bool $bUrlEncode = false * * @return string */ - private function compileLogParams($sLine, $oAccount = null) + private function compileLogParams($sLine, $oAccount = null, $bUrlEncode = false) { if (false !== \strpos($sLine, '{date:')) { - $sLine = \preg_replace_callback('/\{date:([^}]+)\}/', function ($aMatch) { - return \gmdate($aMatch[1]); + $iTimeOffset = (int) $this->Config()->Get('logs', 'time_offset', 0); + $sLine = \preg_replace_callback('/\{date:([^}]+)\}/', function ($aMatch) use ($iTimeOffset, $bUrlEncode) { + return \RainLoop\Utils::UrlEncode(\MailSo\Log\Logger::DateHelper($aMatch[1], $iTimeOffset), $bUrlEncode); }, $sLine); $sLine = \preg_replace('/\{date:([^}]*)\}/', 'date', $sLine); @@ -424,25 +437,38 @@ class Actions if ($oAccount) { - $sLine = \str_replace('{imap:login}', $oAccount->IncLogin(), $sLine); - $sLine = \str_replace('{imap:host}', $oAccount->DomainIncHost(), $sLine); - $sLine = \str_replace('{imap:port}', $oAccount->DomainIncPort(), $sLine); + $sLine = \str_replace('{imap:login}', \RainLoop\Utils::UrlEncode($oAccount->IncLogin(), $bUrlEncode), $sLine); + $sLine = \str_replace('{imap:host}', \RainLoop\Utils::UrlEncode($oAccount->DomainIncHost(), $bUrlEncode), $sLine); + $sLine = \str_replace('{imap:port}', \RainLoop\Utils::UrlEncode($oAccount->DomainIncPort(), $bUrlEncode), $sLine); - $sLine = \str_replace('{smtp:login}', $oAccount->OutLogin(), $sLine); - $sLine = \str_replace('{smtp:host}', $oAccount->DomainOutHost(), $sLine); - $sLine = \str_replace('{smtp:port}', $oAccount->DomainOutPort(), $sLine); + $sLine = \str_replace('{smtp:login}', \RainLoop\Utils::UrlEncode($oAccount->OutLogin(), $bUrlEncode), $sLine); + $sLine = \str_replace('{smtp:host}', \RainLoop\Utils::UrlEncode($oAccount->DomainOutHost(), $bUrlEncode), $sLine); + $sLine = \str_replace('{smtp:port}', \RainLoop\Utils::UrlEncode($oAccount->DomainOutPort(), $bUrlEncode), $sLine); } $sLine = \preg_replace('/\{imap:([^}]*)\}/i', 'imap', $sLine); - $sLine = \preg_replace('/\{smtp:([^}]*)\}/i', 'imap', $sLine); + $sLine = \preg_replace('/\{smtp:([^}]*)\}/i', 'smtp', $sLine); } if (false !== \strpos($sLine, '{request:')) { if (false !== \strpos($sLine, '{request:ip}')) { - $sLine = \str_replace('{request:ip}', $this->Http()->GetClientIp( - $this->Config()->Get('labs', 'http_client_ip_check_proxy', false)), $sLine); + $sLine = \str_replace('{request:ip}', \RainLoop\Utils::UrlEncode($this->Http()->GetClientIp( + $this->Config()->Get('labs', 'http_client_ip_check_proxy', false)), $bUrlEncode), $sLine); + } + + if (false !== \strpos($sLine, '{request:domain}')) + { + $sLine = \str_replace('{request:domain}', + \RainLoop\Utils::UrlEncode($this->Http()->GetHost(false, true, true), $bUrlEncode), $sLine); + } + + if (false !== \strpos($sLine, '{request:domain-clear}')) + { + $sLine = \str_replace('{request:domain-clear}', + \RainLoop\Utils::UrlEncode( + \MailSo\Base\Utils::GetClearDomainName($this->Http()->GetHost(false, true, true)), $bUrlEncode), $sLine); } $sLine = \preg_replace('/\{request:([^}]*)\}/i', 'request', $sLine); @@ -453,15 +479,16 @@ class Actions if (false !== \strpos($sLine, '{user:uid}')) { $sLine = \str_replace('{user:uid}', - \base_convert(\sprintf('%u', \crc32(\md5(\RainLoop\Utils::GetConnectionToken()))), 10, 32), + \RainLoop\Utils::UrlEncode(\base_convert(\sprintf('%u', + \crc32(\md5(\RainLoop\Utils::GetConnectionToken()))), 10, 32), $bUrlEncode), $sLine ); } if (false !== \strpos($sLine, '{user:ip}')) { - $sLine = \str_replace('{user:ip}', $this->Http()->GetClientIp( - $this->Config()->Get('labs', 'http_client_ip_check_proxy', false)), $sLine); + $sLine = \str_replace('{user:ip}', \RainLoop\Utils::UrlEncode($this->Http()->GetClientIp( + $this->Config()->Get('labs', 'http_client_ip_check_proxy', false)), $bUrlEncode), $sLine); } if (\preg_match('/\{user:(email|login|domain)\}/i', $sLine)) @@ -475,9 +502,15 @@ class Actions if ($oAccount) { $sEmail = $oAccount->Email(); - $sLine = \str_replace('{user:email}', $sEmail, $sLine); - $sLine = \str_replace('{user:login}', \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail), $sLine); - $sLine = \str_replace('{user:domain}', \MailSo\Base\Utils::GetDomainFromEmail($sEmail), $sLine); + + $sLine = \str_replace('{user:email}', \RainLoop\Utils::UrlEncode($sEmail, $bUrlEncode), $sLine); + $sLine = \str_replace('{user:login}', \RainLoop\Utils::UrlEncode( + \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail), $bUrlEncode), $sLine); + $sLine = \str_replace('{user:domain}', \RainLoop\Utils::UrlEncode( + \MailSo\Base\Utils::GetDomainFromEmail($sEmail), $bUrlEncode), $sLine); + $sLine = \str_replace('{user:domain-clear}', \RainLoop\Utils::UrlEncode( + \MailSo\Base\Utils::GetClearDomainName( + \MailSo\Base\Utils::GetDomainFromEmail($sEmail)), $bUrlEncode), $sLine); } } @@ -527,7 +560,7 @@ class Actions public function SetAuthLogoutToken() { @\header('X-RainLoop-Action: Logout'); - \RainLoop\Utils::SetCookie(self::AUTH_SPEC_LOGOUT_TOKEN_KEY, \md5(APP_START_TIME), 0, '/', null, null, true); + \RainLoop\Utils::SetCookie(self::AUTH_SPEC_LOGOUT_TOKEN_KEY, \md5(APP_START_TIME), 0); } /** @@ -539,26 +572,26 @@ class Actions { if ($oAccount) { - $sSpecAuthToken = '_'.$oAccount->GetAuthToken(); + $sSpecAuthToken = '_'.$oAccount->GetAuthTokenQ(); $this->SetSpecAuthToken($sSpecAuthToken); - \RainLoop\Utils::SetCookie(self::AUTH_SPEC_TOKEN_KEY, $sSpecAuthToken, 0, '/', null, null, true); + \RainLoop\Utils::SetCookie(self::AUTH_SPEC_TOKEN_KEY, $sSpecAuthToken, 0); if ($oAccount->SignMe() && 0 < \strlen($oAccount->SignMeToken())) { \RainLoop\Utils::SetCookie(self::AUTH_SIGN_ME_TOKEN_KEY, - \RainLoop\Utils::EncodeKeyValues(array( + \RainLoop\Utils::EncodeKeyValuesQ(array( 'e' => $oAccount->Email(), 't' => $oAccount->SignMeToken() )), - \time() + 60 * 60 * 24 * 30, '/', null, null, true); + \time() + 60 * 60 * 24 * 30); $this->StorageProvider()->Put($oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'sign_me', - \RainLoop\Utils::EncodeKeyValues(array( + \RainLoop\Utils::EncodeKeyValuesQ(array( 'Time' => \time(), - 'AuthToken' => $oAccount->GetAuthToken(), + 'AuthToken' => $oAccount->GetAuthTokenQ(), 'SignMetToken' => $oAccount->SignMeToken() )) ); @@ -599,13 +632,13 @@ class Actions */ private function setAdminAuthToken($sToken) { - \RainLoop\Utils::SetCookie(self::AUTH_ADMIN_TOKEN_KEY, $sToken, 0, '/', null, null, true); + \RainLoop\Utils::SetCookie(self::AUTH_ADMIN_TOKEN_KEY, $sToken, 0); } /** * @return string */ - private function getAuthToken() + private function getLocalAuthToken() { $sToken = $this->GetSpecAuthToken(); return !empty($sToken) && '_' === \substr($sToken, 0, 1) ? \substr($sToken, 1) : ''; @@ -624,7 +657,7 @@ class Actions */ public function ClearAdminAuthToken() { - $aAdminHash = \RainLoop\Utils::DecodeKeyValues($this->getAdminAuthToken()); + $aAdminHash = \RainLoop\Utils::DecodeKeyValuesQ($this->getAdminAuthToken()); if ( !empty($aAdminHash[0]) && !empty($aAdminHash[1]) && !empty($aAdminHash[2]) && 'token' === $aAdminHash[0] && \md5(APP_SALT) === $aAdminHash[1] @@ -731,6 +764,28 @@ class Actions return $this->oTwoFactorAuthProvider; } + /** + * @return \RainLoop\Providers\Prem + */ + public function PremProvider() + { + if (null === $this->oPremProvider) + { + if (\file_exists(APP_VERSION_ROOT_PATH.'app/libraries/RainLoop/Prem/Provider.php')) + { + $this->oPremProvider = new \RainLoop\Prem\Provider( + $this->Config(), $this->Logger(), $this->Cacher(null, true) + ); + } + else + { + $this->oPremProvider = false; + } + } + + return $this->oPremProvider; + } + /** * @param bool $bLocal = false * @@ -826,7 +881,8 @@ class Actions { if (null === $this->oSuggestionsProvider) { - $this->oSuggestionsProvider = new \RainLoop\Providers\Suggestions($this->fabrica('suggestions')); + $this->oSuggestionsProvider = new \RainLoop\Providers\Suggestions( + $this->fabrica('suggestions')); } return $this->oSuggestionsProvider; @@ -842,9 +898,16 @@ class Actions { if (null === $this->oAddressBookProvider) { - $this->oAddressBookProvider = new \RainLoop\Providers\AddressBook( - $this->Config()->Get('contacts', 'enable', false) || $bForceEnable ? $this->fabrica('address-book', $oAccount) : null); + $oDriver = null; + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::CONTACTS, $oAccount)) + { + if ($this->Config()->Get('contacts', 'enable', false) || $bForceEnable) + { + $oDriver = $this->fabrica('address-book', $oAccount); + } + } + $this->oAddressBookProvider = new \RainLoop\Providers\AddressBook($oDriver); $this->oAddressBookProvider->SetLogger($this->Logger()); } @@ -939,6 +1002,20 @@ class Actions if (!!$this->Config()->Get('logs', 'enable', false)) { + $sSessionFilter = (string) $this->Config()->Get('logs', 'session_filter', ''); + if (!empty($sSessionFilter)) + { + $aSessionParts = \explode(':', $sSessionFilter, 2); + + if (empty($aSessionParts[0]) || empty($aSessionParts[1]) || + (string) $aSessionParts[1] !== (string) \RainLoop\Utils::GetCookie($aSessionParts[0], '')) + { + return $this->oLogger; + } + } + + $iTimeOffset = (int) $this->Config()->Get('logs', 'time_offset', 0); + $this->oLogger->SetShowSecter(!$this->Config()->Get('logs', 'hide_passwords', true)); $sLogFileFullPath = \APP_PRIVATE_DATA.'logs/'.$this->compileLogFileName( @@ -956,6 +1033,7 @@ class Actions ->WriteOnErrorOnly($this->Config()->Get('logs', 'write_on_error_only', false)) ->WriteOnPhpErrorOnly($this->Config()->Get('logs', 'write_on_php_error_only', false)) ->WriteOnTimeoutOnly($this->Config()->Get('logs', 'write_on_timeout_only', 0)) + ->SetTimeOffset($iTimeOffset) ); if (!$this->Config()->Get('debug', 'enable', false)) @@ -967,7 +1045,10 @@ class Actions $oHttp = $this->Http(); - $this->oLogger->Write('[DATE:'.\gmdate('d.m.y').'][RL:'.APP_VERSION.'][PHP:'.PHP_VERSION.'][IP:'. + $this->oLogger->Write('[DATE:'.\MailSo\Log\Logger::DateHelper('d.m.y', $iTimeOffset). + (0 !== $iTimeOffset ? '][OFFSET:'.(0 < $iTimeOffset ? '+' : '-'). + \str_pad((string) \abs($iTimeOffset), 2, '0', STR_PAD_LEFT) : ''). + '][RL:'.APP_VERSION.'][PHP:'.PHP_VERSION.'][IP:'. $oHttp->GetClientIp($this->Config()->Get('labs', 'http_client_ip_check_proxy', false)).'][PID:'. (\MailSo\Base\Utils::FunctionExistsAndEnabled('getmypid') ? \getmypid() : 'unknown').']['. $oHttp->GetServer('SERVER_SOFTWARE', '~').']['. @@ -1020,9 +1101,13 @@ class Actions $this->oLoggerAuth->AddForbiddenType(\MailSo\Log\Enumerations\Type::TIME); $this->oLoggerAuth->AddForbiddenType(\MailSo\Log\Enumerations\Type::TIME_DELTA); - $this->oLoggerAuth->Add( - \MailSo\Log\Drivers\File::NewInstance($sAuthLogFileFullPath) - ); + $oDriver = \MailSo\Log\Drivers\File::NewInstance($sAuthLogFileFullPath); + + $oDriver->DisableTimePrefix(); + $oDriver->DisableGuidPrefix(); + $oDriver->DisableTypedPrefix(); + + $this->oLoggerAuth->Add($oDriver); } } @@ -1043,7 +1128,7 @@ class Actions $sRand = ''; } - return '' === $sRand ? '' : \RainLoop\Utils::EncodeKeyValues(array('token', \md5(APP_SALT), $sRand)); + return '' === $sRand ? '' : \RainLoop\Utils::EncodeKeyValuesQ(array('token', \md5(APP_SALT), $sRand)); } /** @@ -1056,7 +1141,7 @@ class Actions $bResult = false; if ($this->Config()->Get('security', 'allow_admin_panel', true)) { - $aAdminHash = \RainLoop\Utils::DecodeKeyValues($this->getAdminAuthToken()); + $aAdminHash = \RainLoop\Utils::DecodeKeyValuesQ($this->getAdminAuthToken()); if (!empty($aAdminHash[0]) && !empty($aAdminHash[1]) && !empty($aAdminHash[2]) && 'token' === $aAdminHash[0] && \md5(APP_SALT) === $aAdminHash[1] && '' !== $this->Cacher(null, true)->Get(\RainLoop\KeyPathHelper::SessionAdminKey($aAdminHash[2]), '') @@ -1082,11 +1167,11 @@ class Actions if (!empty($sTo)) { \RainLoop\Utils::SetCookie(self::AUTH_MAILTO_TOKEN_KEY, - \RainLoop\Utils::EncodeKeyValues(array( + \RainLoop\Utils::EncodeKeyValuesQ(array( 'Time' => \microtime(true), 'MailTo' => 'MailTo', 'To' => $sTo - )), 0, '/', null, null, true); + )), 0); } } @@ -1135,16 +1220,17 @@ class Actions * @param string $sToken * @param bool $bThrowExceptionOnFalse = true * @param bool $bValidateShortToken = true + * @param bool $bQ = false * * @return \RainLoop\Model\Account|bool * @throws \RainLoop\Exceptions\ClientException */ - public function GetAccountFromCustomToken($sToken, $bThrowExceptionOnFalse = true, $bValidateShortToken = true) + public function GetAccountFromCustomToken($sToken, $bThrowExceptionOnFalse = true, $bValidateShortToken = true, $bQ = false) { $oResult = false; if (!empty($sToken)) { - $aAccountHash = \RainLoop\Utils::DecodeKeyValues($sToken); + $aAccountHash = $bQ ? \RainLoop\Utils::DecodeKeyValuesQ($sToken) : \RainLoop\Utils::DecodeKeyValues($sToken); if (!empty($aAccountHash[0]) && 'token' === $aAccountHash[0] && // simple token validation 8 <= \count($aAccountHash) && // length checking !empty($aAccountHash[7]) && // does short token exist @@ -1194,7 +1280,7 @@ class Actions $sSignMeToken = \RainLoop\Utils::GetCookie(\RainLoop\Actions::AUTH_SIGN_ME_TOKEN_KEY, ''); if (!empty($sSignMeToken)) { - $aTokenData = \RainLoop\Utils::DecodeKeyValues($sSignMeToken); + $aTokenData = \RainLoop\Utils::DecodeKeyValuesQ($sSignMeToken); if (\is_array($aTokenData) && !empty($aTokenData['e']) && !empty($aTokenData['t'])) { $sTokenSettings = $this->StorageProvider()->Get($aTokenData['e'], @@ -1204,13 +1290,13 @@ class Actions if (!empty($sTokenSettings)) { - $aSignMeData = \RainLoop\Utils::DecodeKeyValues($sTokenSettings); + $aSignMeData = \RainLoop\Utils::DecodeKeyValuesQ($sTokenSettings); if (\is_array($aSignMeData) && !empty($aSignMeData['AuthToken']) && !empty($aSignMeData['SignMetToken']) && $aSignMeData['SignMetToken'] === $aTokenData['t']) { - $oAccount = $this->GetAccountFromCustomToken($aSignMeData['AuthToken'], false, false); + $oAccount = $this->GetAccountFromCustomToken($aSignMeData['AuthToken'], false, false, true); } } } @@ -1229,23 +1315,17 @@ class Actions * @return \RainLoop\Model\Account|bool * @throws \RainLoop\Exceptions\ClientException */ - private function getAccountFromToken($bThrowExceptionOnFalse = true) + public function getAccountFromToken($bThrowExceptionOnFalse = true) { - return $this->GetAccountFromCustomToken($this->getAuthToken(), $bThrowExceptionOnFalse); + return $this->GetAccountFromCustomToken($this->getLocalAuthToken(), $bThrowExceptionOnFalse, true, true); } /** * @return bool */ - private function PremType() + public function IsOpen() { - static $bResult = null; - if (null === $bResult) - { - $bResult = $this->licenseParser($this->licenseHelper(false, true)); - } - - return $bResult; + return !$this->PremProvider(); } /** @@ -1264,6 +1344,8 @@ class Actions $oAccount = null; $oConfig = $this->Config(); + $oPremProvider = $this->PremProvider(); + $aResult = array( 'Version' => APP_VERSION, 'Auth' => false, @@ -1285,6 +1367,8 @@ class Actions 'LoginBackground' => '', 'LoginCss' => '', 'UserLogo' => '', + 'UserLogoTitle' => '', + 'UserLogoMessage' => '', 'UserCss' => '', 'WelcomePageUrl' => '', 'WelcomePageDisplay' => 'none', @@ -1298,12 +1382,12 @@ class Actions 'AllowCtrlEnterOnCompose' => (bool) $oConfig->Get('labs', 'allow_ctrl_enter_on_compose', false), 'UseRsaEncryption' => (bool) $oConfig->Get('security', 'use_rsa_encryption', false), 'RsaPublicKey' => '', - 'HideDangerousActions' => $oConfig->Get('labs', 'hide_dangerous_actions', false), 'CustomLoginLink' => $oConfig->Get('labs', 'custom_login_link', ''), 'CustomLogoutLink' => $oConfig->Get('labs', 'custom_logout_link', ''), 'LoginDefaultDomain' => $oConfig->Get('login', 'default_domain', ''), 'DetermineUserLanguage' => (bool) $oConfig->Get('login', 'determine_user_language', true), 'DetermineUserDomain' => (bool) $oConfig->Get('login', 'determine_user_domain', false), + 'UseLoginWelcomePage' => (bool) $oConfig->Get('login', 'welcome_page', false), 'ForgotPasswordLinkUrl' => \trim($oConfig->Get('login', 'forgot_password_link_url', '')), 'RegistrationLinkUrl' => \trim($oConfig->Get('login', 'registration_link_url', '')), 'ContactsIsAllowed' => false, @@ -1314,13 +1398,39 @@ class Actions 'UseImapSubscribe' => (bool) $oConfig->Get('labs', 'use_imap_list_subscribe', true), 'AllowAppendMessage' => (bool) $oConfig->Get('labs', 'allow_message_append', false), 'MaterialDesign' => (bool) $oConfig->Get('labs', 'use_material_design', true), - 'PremType' => $this->PremType(), - 'ZipSupported' => !!\class_exists('ZipArchive'), + 'FolderSpecLimit' => (int) $oConfig->Get('labs', 'folders_spec_limit', 50), + 'StartupUrl' => \trim(\ltrim(\trim($oConfig->Get('labs', 'startup_url', '')), '#/')), + 'FaviconStatus' => (bool) $oConfig->Get('labs', 'favicon_status', true), + 'Filtered' => '' !== \trim(\RainLoop\Api::Config()->Get('labs', 'imap_message_list_permanent_filter', '')), + 'Community' => true, + 'PremType' => false, 'Admin' => array(), 'Capa' => array(), + 'AttachmentsActions' => array(), 'Plugins' => array() ); + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ATTACHMENTS_ACTIONS)) + { + if (!!\class_exists('ZipArchive')) + { + $aResult['AttachmentsActions'][] = 'zip'; + } + + if (\RainLoop\Utils::IsOwnCloudLoggedIn() && \class_exists('OCP\Files')) + { + $aResult['AttachmentsActions'][] = 'owncloud'; + } + + if ($oConfig->Get('social', 'dropbox_enable', false) && 0 < \strlen(\trim($oConfig->Get('social', 'dropbox_api_key', '')))) + { + $aResult['AttachmentsActions'][] = 'dropbox'; + } + } + + $aResult['AllowDropboxSocial'] = (bool) $oConfig->Get('social', 'dropbox_enable', false); + $aResult['DropboxApiKey'] = \trim($oConfig->Get('social', 'dropbox_api_key', '')); + if ($aResult['UseRsaEncryption'] && \file_exists(APP_PRIVATE_DATA.'rsa/public') && \file_exists(APP_PRIVATE_DATA.'rsa/private')) { @@ -1333,7 +1443,7 @@ class Actions } } - if (0 === strlen($aResult['RsaPublicKey'])) + if (0 === \strlen($aResult['RsaPublicKey'])) { $aResult['UseRsaEncryption'] = false; } @@ -1346,23 +1456,17 @@ class Actions $aResult['Title'] = $oConfig->Get('webmail', 'title', ''); $aResult['LoadingDescription'] = $oConfig->Get('webmail', 'loading_description', ''); - if ($this->PremType()) + if ($oPremProvider) { - $aResult['LoginLogo'] = $oConfig->Get('branding', 'login_logo', ''); - $aResult['LoginBackground'] = $oConfig->Get('branding', 'login_background', ''); - $aResult['LoginCss'] = $oConfig->Get('branding', 'login_css', ''); - $aResult['LoginDescription'] = $oConfig->Get('branding', 'login_desc', ''); - $aResult['LoginPowered'] = !!$oConfig->Get('branding', 'login_powered', true); - $aResult['UserLogo'] = $oConfig->Get('branding', 'user_logo', ''); - $aResult['UserCss'] = $oConfig->Get('branding', 'user_css', ''); - $aResult['WelcomePageUrl'] = $oConfig->Get('branding', 'welcome_page_url', ''); - $aResult['WelcomePageDisplay'] = \strtolower($oConfig->Get('branding', 'welcome_page_display', 'none')); + $oPremProvider->PopulateAppData($aResult); } - $aResult['LoadingDescriptionEsc'] = \htmlspecialchars($aResult['LoadingDescription'], ENT_QUOTES|ENT_IGNORE, 'UTF-8'); + if ('' !== $aResult['LoadingDescription'] && 'RainLoop' !== $aResult['LoadingDescription']) + { + $aResult['LoadingDescriptionEsc'] = @\htmlspecialchars($aResult['LoadingDescription'], ENT_QUOTES|ENT_IGNORE, 'UTF-8'); + } $oSettings = null; - $oSettingsLocal = null; if (!$bAdmin) { @@ -1408,9 +1512,10 @@ class Actions if (null !== $sToken) { \RainLoop\Utils::ClearCookie(self::AUTH_MAILTO_TOKEN_KEY); - $mMailToData = \RainLoop\Utils::DecodeKeyValues($sToken); - if (\is_array($mMailToData) && !empty($mMailToData['MailTo']) && 'MailTo' === $mMailToData['MailTo'] && - !empty($mMailToData['To'])) + + $mMailToData = \RainLoop\Utils::DecodeKeyValuesQ($sToken); + if (\is_array($mMailToData) && !empty($mMailToData['MailTo']) && + 'MailTo' === $mMailToData['MailTo'] && !empty($mMailToData['To'])) { $aResult['MailToEmail'] = $mMailToData['To']; } @@ -1418,7 +1523,7 @@ class Actions } $oSettings = $this->SettingsProvider()->Load($oAccount); - $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); + if (!$oAccount->IsAdditionalAccount() && !empty($aResult['WelcomePageUrl']) && ('once' === $aResult['WelcomePageDisplay'] || 'always' === $aResult['WelcomePageDisplay'])) @@ -1437,6 +1542,16 @@ class Actions $aResult['WelcomePageUrl'] = ''; $aResult['WelcomePageDisplay'] = ''; } + + if (!empty($aResult['StartupUrl'])) + { + $aResult['StartupUrl'] = $this->compileLogParams($aResult['StartupUrl'], $oAccount, true); + } + + if (!empty($aResult['UserIframeMessage'])) + { + $aResult['UserIframeMessage'] = $this->compileLogParams($aResult['UserIframeMessage'], $oAccount, true); + } } else { @@ -1450,10 +1565,13 @@ class Actions $aResult['WelcomePageUrl'] = ''; $aResult['WelcomePageDisplay'] = ''; + + $aResult['StartupUrl'] = ''; } $aResult['AllowGoogleSocial'] = (bool) $oConfig->Get('social', 'google_enable', false); $aResult['AllowGoogleSocialAuth'] = (bool) $oConfig->Get('social', 'google_enable_auth', true); + $aResult['AllowGoogleSocialAuthFast'] = (bool) $oConfig->Get('social', 'google_enable_auth_fast', true); $aResult['AllowGoogleSocialDrive'] = (bool) $oConfig->Get('social', 'google_enable_drive', true); $aResult['AllowGoogleSocialPreview'] = (bool) $oConfig->Get('social', 'google_enable_preview', true); @@ -1464,6 +1582,7 @@ class Actions '' === \trim($oConfig->Get('social', 'google_client_id', '')) || '' === \trim($oConfig->Get('social', 'google_client_secret', ''))))) { $aResult['AllowGoogleSocialAuth'] = false; + $aResult['AllowGoogleSocialAuthFast'] = false; $aResult['AllowGoogleSocialDrive'] = false; $aResult['GoogleClientID'] = ''; $aResult['GoogleApiKey'] = ''; @@ -1474,7 +1593,9 @@ class Actions $aResult['AllowGoogleSocialPreview'] = false; } - if ($aResult['AllowGoogleSocial'] && !$aResult['AllowGoogleSocialAuth'] && !$aResult['AllowGoogleSocialDrive'] && !$aResult['AllowGoogleSocialPreview']) + if ($aResult['AllowGoogleSocial'] && + !$aResult['AllowGoogleSocialAuth'] && !$aResult['AllowGoogleSocialAuthFast'] && + !$aResult['AllowGoogleSocialDrive'] && !$aResult['AllowGoogleSocialPreview']) { $aResult['AllowGoogleSocial'] = false; } @@ -1526,15 +1647,15 @@ class Actions $aResult['Auth'] = $this->IsAdminLoggined(false); if ($aResult['Auth']) { - $aResult['AdminLogin'] = $oConfig->Get('security', 'admin_login', ''); $aResult['AdminDomain'] = APP_SITE; + $aResult['AdminLogin'] = (string) $oConfig->Get('security', 'admin_login', ''); $aResult['UseTokenProtection'] = (bool) $oConfig->Get('security', 'csrf_protection', true); $aResult['EnabledPlugins'] = (bool) $oConfig->Get('plugins', 'enable', false); - $aResult['VerifySslCertificate'] = !!$oConfig->Get('ssl', 'verify_certificate', false); - $aResult['AllowSelfSigned'] = !!$oConfig->Get('ssl', 'allow_self_signed', true); + $aResult['VerifySslCertificate'] = (bool) $oConfig->Get('ssl', 'verify_certificate', false); + $aResult['AllowSelfSigned'] = (bool) $oConfig->Get('ssl', 'allow_self_signed', true); - $aDrivers = \class_exists('PDO') ? \PDO::getAvailableDrivers() : array(); + $aDrivers = \class_exists('PDO') ? \PDO::getAvailableDrivers() : null; $aResult['MySqlIsSupported'] = \is_array($aDrivers) ? \in_array('mysql', $aDrivers) : false; $aResult['SQLiteIsSupported'] = \is_array($aDrivers) ? \in_array('sqlite', $aDrivers) : false; $aResult['PostgreSqlIsSupported'] = \is_array($aDrivers) ? \in_array('pgsql', $aDrivers) : false; @@ -1542,14 +1663,15 @@ class Actions $aResult['ContactsEnable'] = (bool) $oConfig->Get('contacts', 'enable', false); $aResult['ContactsSharing'] = (bool) $oConfig->Get('contacts', 'allow_sharing', false); $aResult['ContactsSync'] = (bool) $oConfig->Get('contacts', 'allow_sync', false); - $aResult['ContactsPdoType'] = $this->ValidateContactPdoType(\trim($this->Config()->Get('contacts', 'type', 'sqlite'))); + $aResult['ContactsPdoType'] = (string) $this->ValidateContactPdoType(\trim($this->Config()->Get('contacts', 'type', 'sqlite'))); $aResult['ContactsPdoDsn'] = (string) $oConfig->Get('contacts', 'pdo_dsn', ''); $aResult['ContactsPdoType'] = (string) $oConfig->Get('contacts', 'type', ''); $aResult['ContactsPdoUser'] = (string) $oConfig->Get('contacts', 'pdo_user', ''); - $aResult['ContactsPdoPassword'] = APP_DUMMY; + $aResult['ContactsPdoPassword'] = (string) APP_DUMMY; $aResult['AllowGoogleSocial'] = (bool) $oConfig->Get('social', 'google_enable', false); $aResult['AllowGoogleSocialAuth'] = (bool) $oConfig->Get('social', 'google_enable_auth', true); + $aResult['AllowGoogleSocialAuthFast'] = (bool) $oConfig->Get('social', 'google_enable_auth_fast', true); $aResult['AllowGoogleSocialDrive'] = (bool) $oConfig->Get('social', 'google_enable_drive', true); $aResult['AllowGoogleSocialPreview'] = (bool) $oConfig->Get('social', 'google_enable_preview', true); @@ -1568,11 +1690,11 @@ class Actions $aResult['AllowDropboxSocial'] = (bool) $oConfig->Get('social', 'dropbox_enable', false); $aResult['DropboxApiKey'] = (string) $oConfig->Get('social', 'dropbox_api_key', ''); - $aResult['SubscriptionEnabled'] = \MailSo\Base\Utils::ValidateDomain($aResult['AdminDomain']); + $aResult['SubscriptionEnabled'] = (bool) \MailSo\Base\Utils::ValidateDomain($aResult['AdminDomain']); // || \MailSo\Base\Utils::ValidateIP($aResult['AdminDomain']); - $aResult['WeakPassword'] = $oConfig->ValidatePassword('12345'); - $aResult['CoreAccess'] = $this->rainLoopCoreAccess(); + $aResult['WeakPassword'] = (bool) $oConfig->ValidatePassword('12345'); + $aResult['CoreAccess'] = (bool) $this->rainLoopCoreAccess(); $aResult['PhpUploadSizes'] = array( 'upload_max_filesize' => \ini_get('upload_max_filesize'), @@ -1600,6 +1722,7 @@ class Actions $aResult['Themes'] = $this->GetThemes(); $aResult['Languages'] = $this->GetLanguages(false); $aResult['LanguagesAdmin'] = $this->GetLanguages(true); + $aResult['AllowLanguagesOnSettings'] = (bool) $oConfig->Get('webmail', 'allow_languages_on_settings', true); $aResult['AllowLanguagesOnLogin'] = (bool) $oConfig->Get('login', 'allow_languages_on_login', true); $aResult['AttachmentLimit'] = ((int) $oConfig->Get('webmail', 'attachment_size_limit', 10)) * 1024 * 1024; @@ -1624,58 +1747,73 @@ class Actions $aResult['UserBackgroundName'] = ''; $aResult['UserBackgroundHash'] = ''; - if (!$bAdmin && $oSettings instanceof \RainLoop\Settings && - $oSettingsLocal instanceof \RainLoop\Settings) + if (!$bAdmin && $oAccount instanceof \RainLoop\Model\Account) { - if ($oConfig->Get('webmail', 'allow_languages_on_settings', true)) - { - $sLanguage = $oSettings->GetConf('Language', $sLanguage); - } - - if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::THEMES, $oAccount)) - { - $sTheme = $oSettingsLocal->GetConf('Theme', $sTheme); - } - - $aResult['SentFolder'] = $oSettingsLocal->GetConf('SentFolder', ''); - $aResult['DraftFolder'] = $oSettingsLocal->GetConf('DraftFolder', ''); - $aResult['SpamFolder'] = $oSettingsLocal->GetConf('SpamFolder', ''); - $aResult['TrashFolder'] = $oSettingsLocal->GetConf('TrashFolder', ''); - $aResult['ArchiveFolder'] = $oSettingsLocal->GetConf('ArchiveFolder', ''); - $aResult['NullFolder'] = $oSettingsLocal->GetConf('NullFolder', ''); - - $aResult['EditorDefaultType'] = $oSettings->GetConf('EditorDefaultType', $aResult['EditorDefaultType']); - $aResult['ShowImages'] = (bool) $oSettings->GetConf('ShowImages', $aResult['ShowImages']); - $aResult['ContactsAutosave'] = (bool) $oSettings->GetConf('ContactsAutosave', $aResult['ContactsAutosave']); - $aResult['MPP'] = (int) $oSettings->GetConf('MPP', $aResult['MPP']); - $aResult['SoundNotification'] = (bool) $oSettings->GetConf('SoundNotification', $aResult['SoundNotification']); - $aResult['DesktopNotifications'] = (bool) $oSettings->GetConf('DesktopNotifications', $aResult['DesktopNotifications']); - $aResult['UseCheckboxesInList'] = (bool) $oSettings->GetConf('UseCheckboxesInList', $aResult['UseCheckboxesInList']); - $aResult['AutoLogout'] = (int) $oSettings->GetConf('AutoLogout', $aResult['AutoLogout']); - $aResult['Layout'] = (int) $oSettings->GetConf('Layout', $aResult['Layout']); - - $aResult['UseThreads'] = (bool) $oSettingsLocal->GetConf('UseThreads', $aResult['UseThreads']); - $aResult['ReplySameFolder'] = (bool) $oSettingsLocal->GetConf('ReplySameFolder', $aResult['ReplySameFolder']); - - if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::AUTOLOGOUT, $oAccount)) - { - $aResult['AutoLogout'] = 0; - } - - if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::USER_BACKGROUND, $oAccount)) - { - $aResult['UserBackgroundName'] = (string) $oSettings->GetConf('UserBackgroundName', $aResult['UserBackgroundName']); - $aResult['UserBackgroundHash'] = (string) $oSettings->GetConf('UserBackgroundHash', $aResult['UserBackgroundHash']); -// if (!empty($aResult['UserBackgroundName']) && !empty($aResult['UserBackgroundHash'])) -// { -// $aResult['IncludeBackground'] = './?/Raw/&q[]=/{{USER}}/UserBackground/&q[]=/'. -// $aResult['UserBackgroundHash'].'/'; -// } - } - - $aResult['EnableTwoFactor'] = !!$oSettings->GetConf('EnableTwoFactor', $aResult['EnableTwoFactor']); - $aResult['ParentEmail'] = $oAccount->ParentEmail(); + + $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); + + if ($oSettingsLocal instanceof \RainLoop\Settings) + { + // if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount)) + + $aResult['SentFolder'] = (string) $oSettingsLocal->GetConf('SentFolder', ''); + $aResult['DraftFolder'] = (string) $oSettingsLocal->GetConf('DraftFolder', ''); + $aResult['SpamFolder'] = (string) $oSettingsLocal->GetConf('SpamFolder', ''); + $aResult['TrashFolder'] = (string) $oSettingsLocal->GetConf('TrashFolder', ''); + $aResult['ArchiveFolder'] = (string) $oSettingsLocal->GetConf('ArchiveFolder', ''); + $aResult['NullFolder'] = (string) $oSettingsLocal->GetConf('NullFolder', ''); + } + + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::SETTINGS, $oAccount)) + { + if ($oSettings instanceof \RainLoop\Settings) + { + if ($oConfig->Get('webmail', 'allow_languages_on_settings', true)) + { + $sLanguage = (string) $oSettings->GetConf('Language', $sLanguage); + } + + $aResult['EditorDefaultType'] = (string) $oSettings->GetConf('EditorDefaultType', $aResult['EditorDefaultType']); + $aResult['ShowImages'] = (bool) $oSettings->GetConf('ShowImages', $aResult['ShowImages']); + $aResult['ContactsAutosave'] = (bool) $oSettings->GetConf('ContactsAutosave', $aResult['ContactsAutosave']); + $aResult['MPP'] = (int) $oSettings->GetConf('MPP', $aResult['MPP']); + $aResult['SoundNotification'] = (bool) $oSettings->GetConf('SoundNotification', $aResult['SoundNotification']); + $aResult['DesktopNotifications'] = (bool) $oSettings->GetConf('DesktopNotifications', $aResult['DesktopNotifications']); + $aResult['UseCheckboxesInList'] = (bool) $oSettings->GetConf('UseCheckboxesInList', $aResult['UseCheckboxesInList']); + $aResult['AutoLogout'] = (int) $oSettings->GetConf('AutoLogout', $aResult['AutoLogout']); + $aResult['Layout'] = (int) $oSettings->GetConf('Layout', $aResult['Layout']); + + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::AUTOLOGOUT, $oAccount)) + { + $aResult['AutoLogout'] = 0; + } + + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::USER_BACKGROUND, $oAccount)) + { + $aResult['UserBackgroundName'] = (string) $oSettings->GetConf('UserBackgroundName', $aResult['UserBackgroundName']); + $aResult['UserBackgroundHash'] = (string) $oSettings->GetConf('UserBackgroundHash', $aResult['UserBackgroundHash']); + // if (!empty($aResult['UserBackgroundName']) && !empty($aResult['UserBackgroundHash'])) + // { + // $aResult['IncludeBackground'] = './?/Raw/&q[]=/{{USER}}/UserBackground/&q[]=/'. + // $aResult['UserBackgroundHash'].'/'; + // } + } + + $aResult['EnableTwoFactor'] = (bool) $oSettings->GetConf('EnableTwoFactor', $aResult['EnableTwoFactor']); + } + + if ($oSettingsLocal instanceof \RainLoop\Settings) + { + $aResult['UseThreads'] = (bool) $oSettingsLocal->GetConf('UseThreads', $aResult['UseThreads']); + $aResult['ReplySameFolder'] = (bool) $oSettingsLocal->GetConf('ReplySameFolder', $aResult['ReplySameFolder']); + + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::THEMES, $oAccount)) + { + $sTheme = (string) $oSettingsLocal->GetConf('Theme', $sTheme); + } + } + } } $sStaticCache = \md5(APP_VERSION.$this->Plugins()->Hash()); @@ -1709,8 +1847,9 @@ class Actions $aResult['LanguageAdmin'] = $this->ValidateLanguage($sLanguageAdmin, '', true); $aResult['UserLanguageRaw'] = $this->detectUserLanguage(); - $aResult['UserLanguage'] = $this->ValidateLanguage($aResult['UserLanguageRaw'], $aResult['Language'], false); - $aResult['UserLanguageAdmin'] = $this->ValidateLanguage($aResult['UserLanguageRaw'], $aResult['LanguageAdmin'], true); + + $aResult['UserLanguage'] = $this->ValidateLanguage($aResult['UserLanguageRaw'], '', false, true, true); + $aResult['UserLanguageAdmin'] = $this->ValidateLanguage($aResult['UserLanguageRaw'], '', true, true, true); $aResult['LangLink'] = './?/Lang/0/'.($bAdmin ? 'Admin' : 'App').'/'. ($bAdmin ? $aResult['LanguageAdmin'] : $aResult['Language']).'/'.$sStaticCache.'/'; @@ -1741,7 +1880,7 @@ class Actions if (false !== \strpos($sAcceptLang, ',')) { $aParts = \explode(',', $sAcceptLang, 2); - $sLang = !empty($aParts[0]) ? \trim(\strtolower($aParts[0])) : ''; + $sLang = empty($aParts[0]) ? '' : \trim(\strtolower($aParts[0])); } return $sLang; @@ -1755,14 +1894,30 @@ class Actions return \preg_replace('/[^a-zA-Z0-9]+/', '-', $this->getUserLanguageFromHeader()); } + /** + * @param int $iWait = 1 + * @param int $iDelay = 1 + */ + private function requestSleep($iWait = 1, $iDelay = 1) + { + if (0 < $iDelay && 0 < $iWait) + { + if ($iWait > \time() - APP_START_TIME) + { + \sleep($iDelay); + } + } + } + private function loginErrorDelay() { $iDelay = (int) $this->Config()->Get('labs', 'login_fault_delay', 0); if (0 < $iDelay) { - \sleep($iDelay); + $this->requestSleep(1, $iDelay); } } + /** * @param \RainLoop\Model\Account $oAccount */ @@ -1866,7 +2021,7 @@ class Actions { $sLine = \trim(\implode('.', $aDomainParts), '. '); - $oDomain = $oDomainProvider->Load($sLine); + $oDomain = $oDomainProvider->Load($sLine, false); if ($oDomain && $oDomain instanceof \RainLoop\Model\Domain) { $bAdded = true; @@ -1885,6 +2040,24 @@ class Actions $iLimit--; } + if (!$bAdded) + { + $sLine = $sUserHost; + $oDomain = $oDomainProvider->Load($sLine, true); + if ($oDomain && $oDomain instanceof \RainLoop\Model\Domain) + { + $bAdded = true; + $this->Logger()->Write('Check "'.$sLine.'" with wildcard: OK ('.$sEmail.' > '.$sEmail.'@'.$sLine.')', + \MailSo\Log\Enumerations\Type::INFO, 'LOGIN'); + + $sEmail = $sEmail.'@'.$sLine; + } + else + { + $this->Logger()->Write('Check "'.$sLine.'" with wildcard: NO', \MailSo\Log\Enumerations\Type::INFO, 'LOGIN'); + } + } + if (!$bAdded) { $this->Logger()->Write('Domain was not found!', \MailSo\Log\Enumerations\Type::INFO, 'LOGIN'); @@ -1979,7 +2152,7 @@ class Actions if ($bAdditionalCodeSignMe) { \RainLoop\Utils::SetCookie(self::AUTH_TFA_SIGN_ME_TOKEN_KEY, $sSecretHash, - \time() + 60 * 60 * 24 * 14, '/', null, null, true); + \time() + 60 * 60 * 24 * 14); } if (!$bGood && !$this->TwoFactorAuthProvider()->VerifyCode($aData['Secret'], $sAdditionalCode)) @@ -2014,51 +2187,27 @@ class Actions */ private function clientRsaDecryptHelper($sEncryptedData) { - $aMatch = array(); - if ('rsa:xxx:' === substr($sEncryptedData, 0, 8) && $this->Config()->Get('security', 'use_rsa_encryption', false)) - { - $oLogger = $this->Logger(); - $oLogger->Write('Trying to decode encrypted data', \MailSo\Log\Enumerations\Type::INFO, 'RSA'); - - $sPrivateKey = file_exists(APP_PRIVATE_DATA.'rsa/private') ? - \file_get_contents(APP_PRIVATE_DATA.'rsa/private') : ''; - - if (!empty($sPrivateKey)) - { - $sData = \trim(\substr($sEncryptedData, 8)); - - if (!\class_exists('Crypt_RSA')) - { - \set_include_path(\get_include_path().PATH_SEPARATOR.APP_VERSION_ROOT_PATH.'app/libraries/phpseclib'); - include_once 'Crypt/RSA.php'; - \defined('CRYPT_RSA_MODE') || \define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL); - } - - $oLogger->HideErrorNotices(true); - - $oRsa = new \Crypt_RSA(); - $oRsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1); - $oRsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1); - $oRsa->setPrivateKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); - $oRsa->loadKey($sPrivateKey, CRYPT_RSA_PRIVATE_FORMAT_PKCS1); - - $sData = $oRsa->decrypt(\base64_decode($sData)); - if (\preg_match('/^[a-z0-9]{32}:(.+):[a-z0-9]{32}$/', $sData, $aMatch) && isset($aMatch[1])) - { - $sEncryptedData = $aMatch[1]; - } - else - { - $oLogger->Write('Invalid decrypted data', \MailSo\Log\Enumerations\Type::WARNING, 'RSA'); - } - - $oLogger->HideErrorNotices(false); - } - else - { - $oLogger->Write('Private key is not found', \MailSo\Log\Enumerations\Type::WARNING, 'RSA'); - } - } +// $aMatch = array(); +// if ('rsa:xxx:' === \substr($sEncryptedData, 0, 8) && $this->Config()->Get('security', 'use_rsa_encryption', false)) +// { +// $oLogger = $this->Logger(); +// $oLogger->Write('Trying to decode encrypted data', \MailSo\Log\Enumerations\Type::INFO, 'RSA'); +// $oLogger->HideErrorNotices(true); +// +// $sData = \trim(\substr($sEncryptedData, 8)); +// $sData = \RainLoop\Utils::DecryptStringRSA(\base64_decode($sData)); +// +// if (false !== $sData && \preg_match('/^[a-z0-9]{32}:(.+):[a-z0-9]{32}$/', $sData, $aMatch) && isset($aMatch[1])) +// { +// $sEncryptedData = $aMatch[1]; +// } +// else +// { +// $oLogger->Write('Invalid decrypted data', \MailSo\Log\Enumerations\Type::WARNING, 'RSA'); +// } +// +// $oLogger->HideErrorNotices(false); +// } return $sEncryptedData; } @@ -2195,6 +2344,7 @@ class Actions 1 < \count($aOrder['Accounts'])) { $aAccounts = \array_merge(\array_flip($aOrder['Accounts']), $aAccounts); + $aAccounts = \array_filter($aAccounts, function ($sHash) { return 5 < \strlen($sHash); }); @@ -2300,6 +2450,9 @@ class Actions */ public function GetIdentities($oAccount) { + $bAllowIdentities = $this->GetCapa(false, + \RainLoop\Enumerations\Capa::IDENTITIES, $oAccount); + $aIdentities = array(); if ($oAccount) { @@ -2326,14 +2479,14 @@ class Actions if ($oItem && $oItem->Validate()) { - if ('' === $oItem->Id()) + if ($oItem->IsAccountIdentities()) { $oItem->SetEmail($oAccount->Email()); $bHasAccountIdentity = true; - \array_unshift($aIdentities, $oItem); + \array_push($aIdentities, $oItem); } - else + else if ($bAllowIdentities) { \array_push($aIdentities, $oItem); } @@ -2347,7 +2500,7 @@ class Actions \RainLoop\Model\Identity::NewInstanceFromAccount($oAccount)); } - if (1 < \count($aIdentities)) + if (1 < \count($aIdentities) && $bAllowIdentities) { $sOrder = $this->StorageProvider()->Get($oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, @@ -2359,8 +2512,16 @@ class Actions 1 < \count($aOrder['Identities'])) { $aList = $aOrder['Identities']; + foreach ($aList as $iIndex => $sItem) + { + if ('' === $sItem) + { + $aList[$iIndex] = '---'; + } + } + \usort($aIdentities, function ($a, $b) use ($aList) { - return \array_search($a->Id(), $aList) < \array_search($b->Id(), $aList) ? -1 : 1; + return \array_search($a->Id(true), $aList) < \array_search($b->Id(true), $aList) ? -1 : 1; }); } } @@ -2379,6 +2540,7 @@ class Actions public function GetIdentityByID($oAccount, $sID, $bFirstOnEmpty = false) { $aIdentities = $this->GetIdentities($oAccount); + if (\is_array($aIdentities)) { foreach ($aIdentities as $oIdentity) @@ -2437,9 +2599,16 @@ class Actions */ public function SetIdentities($oAccount, $aIdentities = array()) { + $bAllowIdentities = $this->GetCapa(false, \RainLoop\Enumerations\Capa::IDENTITIES, $oAccount); + $aResult = array(); foreach ($aIdentities as $oItem) { + if (!$bAllowIdentities && $oItem && !$oItem->IsAccountIdentities()) + { + continue; + } + $aResult[] = $oItem->ToSimpleJSON(false); } @@ -2580,7 +2749,7 @@ class Actions $oNewAccount->SetParentEmail($sParentEmail); $aAccounts[$oNewAccount->Email()] = $oNewAccount->GetAuthToken(); - if (0 === \strlen($oAccount->ParentEmail())) + if (!$oAccount->IsAdditionalAccount()) { $aAccounts[$oAccount->Email()] = $oAccount->GetAuthToken(); } @@ -2637,10 +2806,202 @@ class Actions */ public function DoAttachmentsActions() { - \sleep(1); - return $this->TrueResponse(__FUNCTION__); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::ATTACHMENTS_ACTIONS)) + { + return $this->FalseResponse(__FUNCTION__); + } + + $oAccount = $this->initMailClientConnection(); + + $sAction = $this->GetActionParam('Do', ''); + $aHashes = $this->GetActionParam('Hashes', null); + + $mResult = false; + $bError = false; + $aData = false; + + if (\is_array($aHashes) && 0 < \count($aHashes)) + { + $aData = array(); + foreach ($aHashes as $sZipHash) + { + $aResult = $this->getMimeFileByHash($oAccount, $sZipHash); + if (\is_array($aResult) && !empty($aResult['FileHash'])) + { + $aData[] = $aResult; + } + else + { + $bError = true; + break; + } + } + } + + $oFilesProvider = $this->FilesProvider(); + if (!empty($sAction) && !$bError && \is_array($aData) && 0 < \count($aData) && + $oFilesProvider && $oFilesProvider->IsActive()) + { + + $bError = false; + switch (\strtolower($sAction)) + { + case 'zip': + + if (\class_exists('ZipArchive')) + { + $sZipHash = \MailSo\Base\Utils::Md5Rand(); + $sZipFileName = $oFilesProvider->GenerateLocalFullFileName($oAccount, $sZipHash); + + if (!empty($sZipFileName)) + { + $oZip = new \ZipArchive(); + $oZip->open($sZipFileName, \ZIPARCHIVE::CREATE | \ZIPARCHIVE::OVERWRITE); + $oZip->setArchiveComment('RainLoop/'.APP_VERSION); + + foreach ($aData as $aItem) + { + $sFileName = (string) (isset($aItem['FileName']) ? $aItem['FileName'] : 'file.dat'); + $sFileHash = (string) (isset($aItem['FileHash']) ? $aItem['FileHash'] : ''); + + if (!empty($sFileHash)) + { + $sFullFileNameHash = $oFilesProvider->GetFileName($oAccount, $sFileHash); + if (!$oZip->addFile($sFullFileNameHash, $sFileName)) + { + $bError = true; + } + } + } + + if (!$bError) + { + $bError = !$oZip->close(); + } + else + { + $oZip->close(); + } + } + + foreach ($aData as $aItem) + { + $sFileHash = (string) (isset($aItem['FileHash']) ? $aItem['FileHash'] : ''); + if (!empty($sFileHash)) + { + $oFilesProvider->Clear($oAccount, $sFileHash); + } + } + + if (!$bError) + { + $mResult = array( + 'Files' => array(array( + 'FileName' => 'attachments.zip', + 'Hash' => \RainLoop\Utils::EncodeKeyValuesQ(array( + 'V' => APP_VERSION, + 'Account' => $oAccount ? \md5($oAccount->Hash()) : '', + 'FileName' => 'attachments.zip', + 'MimeType' => 'application/zip', + 'FileHash' => $sZipHash + )) + )) + ); + } + } + break; + + case 'owncloud': + + $mResult = false; + + if (\RainLoop\Utils::IsOwnCloudLoggedIn() && \class_exists('OCP\Files')) + { + $sSaveFolder = $this->Config()->Get('labs', 'owncloud_save_folder', ''); + if (empty($sSaveFolder)) + { + $sSaveFolder = 'Attachments'; + } + + $oFiles = \OCP\Files::getStorage('files'); + + if ($oFilesProvider && $oFiles && $oFilesProvider->IsActive() && + \method_exists($oFiles, 'file_put_contents')) + { + if (!$oFiles->is_dir($sSaveFolder)) + { + $oFiles->mkdir($sSaveFolder); + } + + $mResult = true; + foreach ($aData as $aItem) + { + $sSavedFileName = isset($aItem['FileName']) ? $aItem['FileName'] : 'file.dat'; + $sSavedFileHash = !empty($aItem['FileHash']) ? $aItem['FileHash'] : ''; + + if (!empty($sSavedFileHash)) + { + $fFile = $oFilesProvider->GetFile($oAccount, $sSavedFileHash, 'rb'); + if (\is_resource($fFile)) + { + $sSavedFileNameFull = \MailSo\Base\Utils::SmartFileExists($sSaveFolder.'/'.$sSavedFileName, function ($sPath) use ($oFiles) { + return $oFiles->file_exists($sPath); + }); + + if (!$oFiles->file_put_contents($sSavedFileNameFull, $fFile)) + { + $mResult = false; + } + + if (\is_resource($fFile)) + { + @\fclose($fFile); + } + } + } + } + } + } + + foreach ($aData as $aItem) + { + $sFileHash = (string) (isset($aItem['FileHash']) ? $aItem['FileHash'] : ''); + if (!empty($sFileHash)) + { + $oFilesProvider->Clear($oAccount, $sFileHash); + } + } + + break; + + case 'dropbox': + + $mResult = array( + 'ShortLife' => '_'.$this->GetShortLifeSpecAuthToken(), + 'Url' => \preg_replace('/\?(.*)$/', '', $this->Http()->GetFullUrl()), + 'Files' => array() + ); + + foreach ($aData as $aItem) + { + $mResult['Files'][] = array( + 'FileName' => isset($aItem['FileName']) ? $aItem['FileName'] : 'file.dat', + 'Hash' => \RainLoop\Utils::EncodeKeyValuesQ($aItem) + ); + } + + break; + } + } + else + { + $bError = true; + } + + $this->requestSleep(); + return $this->DefaultResponse(__FUNCTION__, $bError ? false : $mResult); } - + /** * @return array * @@ -2656,18 +3017,30 @@ class Actions throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidInputArgument); } - $aIdentitiesForSave = array(); - $aIdentities = $this->GetIdentities($oAccount); + + $bAdded = false; + $aIdentitiesForSave = array(); foreach ($aIdentities as $oItem) { - if ($oItem && $oItem->Id() !== $oIdentity->Id()) + if ($oItem) { - $aIdentitiesForSave[] = $oItem; + if ($oItem->Id() === $oIdentity->Id()) + { + $aIdentitiesForSave[] = $oIdentity; + $bAdded = true; + } + else + { + $aIdentitiesForSave[] = $oItem; + } } } - $aIdentitiesForSave[] = $oIdentity; + if (!$bAdded) + { + $aIdentitiesForSave[] = $oIdentity; + } return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aIdentitiesForSave)); } @@ -2681,6 +3054,11 @@ class Actions { $oAccount = $this->getAccountFromToken(); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::IDENTITIES, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } + $sId = \trim($this->GetActionParam('IdToDelete', '')); if (empty($sId)) { @@ -2689,6 +3067,7 @@ class Actions $aNew = array(); $aIdentities = $this->GetIdentities($oAccount); + foreach ($aIdentities as $oItem) { if ($oItem && $sId !== $oItem->Id()) @@ -2823,7 +3202,7 @@ class Actions $aAccounts = $this->GetActionParam('Accounts', null); $aIdentities = $this->GetActionParam('Identities', null); - if (!\is_array($aAccounts) || !\is_array($aIdentities)) + if (!\is_array($aAccounts) && !\is_array($aIdentities)) { return $this->FalseResponse(__FUNCTION__); } @@ -2831,8 +3210,8 @@ class Actions return $this->DefaultResponse(__FUNCTION__, $this->StorageProvider()->Put($oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'accounts_identities_order', \json_encode(array( - 'Accounts' => $aAccounts, - 'Identities' => $aIdentities + 'Accounts' => \is_array($aAccounts) ? $aAccounts : array(), + 'Identities' => \is_array($aIdentities) ? $aIdentities : array() )) )); } @@ -2847,6 +3226,7 @@ class Actions $oAccount = $this->getAccountFromToken(); $mAccounts = false; + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) { $mAccounts = $this->GetAccounts($oAccount); @@ -3071,7 +3451,11 @@ class Actions } else if ($bVersionsCache) { - $this->removeOldVersion(); + $oPremProvider = $this->PremProvider(); + if ($oPremProvider) + { + $oPremProvider->ClearOldVersion(); + } } $this->Plugins()->RunHook('service.app-delay-start-end'); @@ -3107,7 +3491,7 @@ class Actions * @param string $sType = 'string' * @param callable|null $mStringCallback = null */ - private function setConfigFromParams(&$oConfig, $sParamName, $sConfigSector, $sConfigName, $sType = 'string', $mStringCallback = null) + public function setConfigFromParams(&$oConfig, $sParamName, $sConfigSector, $sConfigName, $sType = 'string', $mStringCallback = null) { $sValue = $this->GetActionParam($sParamName, ''); if ($this->HasActionParam($sParamName)) @@ -3157,8 +3541,11 @@ class Actions case \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS: $this->setConfigFromParams($oConfig, $sParamName, 'webmail', 'allow_additional_accounts', 'bool'); break; + case \RainLoop\Enumerations\Capa::IDENTITIES: + $this->setConfigFromParams($oConfig, $sParamName, 'webmail', 'allow_additional_identities', 'bool'); + break; case \RainLoop\Enumerations\Capa::TEMPLATES: - $this->setConfigFromParams($oConfig, $sParamName, 'capa', 'templates', 'bool'); + $this->setConfigFromParams($oConfig, $sParamName, 'capa', 'x-templates', 'bool'); break; case \RainLoop\Enumerations\Capa::TWO_FACTOR: $this->setConfigFromParams($oConfig, $sParamName, 'security', 'allow_two_factor_auth', 'bool'); @@ -3269,6 +3656,7 @@ class Actions }); $this->setCapaFromParams($oConfig, 'CapaAdditionalAccounts', \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS); + $this->setCapaFromParams($oConfig, 'CapaIdentities', \RainLoop\Enumerations\Capa::IDENTITIES); $this->setCapaFromParams($oConfig, 'CapaTemplates', \RainLoop\Enumerations\Capa::TEMPLATES); $this->setCapaFromParams($oConfig, 'CapaTwoFactorAuth', \RainLoop\Enumerations\Capa::TWO_FACTOR); $this->setCapaFromParams($oConfig, 'CapaTwoFactorAuthForce', \RainLoop\Enumerations\Capa::TWO_FACTOR_FORCE); @@ -3284,30 +3672,12 @@ class Actions $this->setConfigFromParams($oConfig, 'Title', 'webmail', 'title', 'string'); $this->setConfigFromParams($oConfig, 'LoadingDescription', 'webmail', 'loading_description', 'string'); - if ($this->HasOneOfActionParams(array( - 'LoginLogo', 'LoginBackground', 'LoginDescription', 'LoginCss', 'LoginPowered', - 'UserLogo', 'UserCss', - 'WelcomePageUrl', 'WelcomePageDisplay' - )) && $this->PremType()) - { - $this->setConfigFromParams($oConfig, 'LoginLogo', 'branding', 'login_logo', 'string'); - $this->setConfigFromParams($oConfig, 'LoginBackground', 'branding', 'login_background', 'string'); - $this->setConfigFromParams($oConfig, 'LoginDescription', 'branding', 'login_desc', 'string'); - $this->setConfigFromParams($oConfig, 'LoginCss', 'branding', 'login_css', 'string'); - $this->setConfigFromParams($oConfig, 'LoginPowered', 'branding', 'login_powered', 'bool'); - - $this->setConfigFromParams($oConfig, 'UserLogo', 'branding', 'user_logo', 'string'); - $this->setConfigFromParams($oConfig, 'UserCss', 'branding', 'user_css', 'string'); - - $this->setConfigFromParams($oConfig, 'WelcomePageUrl', 'branding', 'welcome_page_url', 'string'); - $this->setConfigFromParams($oConfig, 'WelcomePageDisplay', 'branding', 'welcome_page_display', 'string'); - } - $this->setConfigFromParams($oConfig, 'TokenProtection', 'security', 'csrf_protection', 'bool'); $this->setConfigFromParams($oConfig, 'EnabledPlugins', 'plugins', 'enable', 'bool'); $this->setConfigFromParams($oConfig, 'GoogleEnable', 'social', 'google_enable', 'bool'); $this->setConfigFromParams($oConfig, 'GoogleEnableAuth', 'social', 'google_enable_auth', 'bool'); + $this->setConfigFromParams($oConfig, 'GoogleEnableAuthFast', 'social', 'google_enable_auth_fast', 'bool'); $this->setConfigFromParams($oConfig, 'GoogleEnableDrive', 'social', 'google_enable_drive', 'bool'); $this->setConfigFromParams($oConfig, 'GoogleEnablePreview', 'social', 'google_enable_preview', 'bool'); $this->setConfigFromParams($oConfig, 'GoogleClientID', 'social', 'google_client_id', 'string'); @@ -3325,6 +3695,12 @@ class Actions $this->setConfigFromParams($oConfig, 'DropboxEnable', 'social', 'dropbox_enable', 'bool'); $this->setConfigFromParams($oConfig, 'DropboxApiKey', 'social', 'dropbox_api_key', 'string'); + $oPremProvider = $this->PremProvider(); + if ($oPremProvider) + { + $oPremProvider->PremSection($this, $oConfig); + } + return $this->DefaultResponse(__FUNCTION__, $oConfig->Save()); } @@ -3399,150 +3775,11 @@ class Actions )); } - /** - * @param string $sDomain - * - * @return string - */ -// public function domainPathHelper($sDomain) -// { -// $sDomain = \strtolower(\trim($sDomain)); -// -// $sTempDomain = \preg_replace('/^(webmail|email|mail)\./', '', $sDomain); -// if (false === \strpos($sTempDomain, '.')) -// { -// $sTempDomain = $sDomain; -// } -// -// $sDomainPrefix = $sTempDomain; -// if (false === \strpos($sDomainPrefix, '.')) -// { -// $sDomainPrefix = $sTempDomain; -// } -// -// $sDomainPrefix = \substr(\preg_replace('/[^a-z0-9]+/', '', $sDomainPrefix), 0, 2); -// $sDomainPrefix = \str_pad($sDomainPrefix, 2, '_'); -// -// return 'd/'.\substr($sDomainPrefix, 0, 1).'/'.$sDomainPrefix.'/'.\urlencode($sTempDomain); -// } - - /** - * @return string - */ - public function licenseHelper($sForce = false, $bLongCache = false, $iFastCacheTimeInMin = 10, $iLongCacheTimeInDays = 3) - { - $sDomain = \trim(APP_SITE); - - $oCacher = $this->Cacher(null, true); - $oHttp = \MailSo\Base\Http::SingletonInstance(); - - if (0 === \strlen($sDomain) || $oHttp->CheckLocalhost($sDomain) || !$oCacher || !$oCacher->Verify(true)) - { - return 'NO'; - } - - $sDomainKeyValue = \RainLoop\KeyPathHelper::LicensingDomainKeyValue($sDomain); - $sDomainLongKeyValue = \RainLoop\KeyPathHelper::LicensingDomainKeyOtherValue($sDomain); - - $sValue = ''; - if (!$sForce) - { - if ($bLongCache) - { - $bLock = $oCacher->GetLock($sDomainLongKeyValue); - $iTime = $bLock ? 0 : $oCacher->GetTimer($sDomainLongKeyValue); - - if ($bLock || (0 < $iTime && \time() < $iTime + (60 * 60 * 24) * $iLongCacheTimeInDays)) - { - $sValue = $oCacher->Get($sDomainLongKeyValue); - } - } - else - { - $iTime = $oCacher->GetTimer($sDomainKeyValue); - if (0 < $iTime && \time() < $iTime + 60 * $iFastCacheTimeInMin) - { - $sValue = $oCacher->Get($sDomainKeyValue); - } - } - } - - if (0 === \strlen($sValue)) - { - if ($bLongCache) - { - if (!$oCacher->SetTimer($sDomainLongKeyValue)) - { - return 'NO'; - } - - $oCacher->SetLock($sDomainLongKeyValue); - } - - $iCode = 0; - $sContentType = ''; - -// $sValue = $oHttp->GetUrlAsString(APP_STATUS_PATH.$this->domainPathHelper($sDomain), -// 'RainLoop/'.APP_VERSION, $sContentType, $iCode, $this->Logger(), 5, -// $this->Config()->Get('labs', 'curl_proxy', ''), $this->Config()->Get('labs', 'curl_proxy_auth', ''), -// array(), false -// ); - - $sValue = $oHttp->GetUrlAsString(APP_API_PATH.'status/'.\urlencode($sDomain), - 'RainLoop/'.APP_VERSION, $sContentType, $iCode, $this->Logger(), 5, - $this->Config()->Get('labs', 'curl_proxy', ''), $this->Config()->Get('labs', 'curl_proxy_auth', ''), - array(), false - ); - - $this->Logger()->Write($sValue); - - /*if (404 === $iCode) - { - $sValue = 'NO'; - } - else */if (200 !== $iCode) - { - $sValue = ''; - } - - $oCacher->SetTimer($sDomainKeyValue); - - $oCacher->Set($sDomainKeyValue, $sValue); - $oCacher->Set($sDomainLongKeyValue, $sValue); - - if ($bLongCache) - { - $oCacher->RemoveLock($sDomainLongKeyValue); - } - } - - return $sValue; - } - - /** - * @param string $sInput - * @param int $iExpired = 0 - * - * @return bool - */ - public function licenseParser($sInput, &$iExpired = 0) - { - $aMatch = array(); - if (\preg_match('/^EXPIRED:([\d]+)$/', $sInput, $aMatch)) - { - $iExpired = (int) $aMatch[1]; - return \time() < $iExpired; - } - - return false; - } - /** * @return array */ public function DoAdminLicensing() { - $iStart = \time(); $this->IsAdminLoggined(); $bForce = '1' === (string) $this->GetActionParam('Force', '0'); @@ -3550,17 +3787,16 @@ class Actions $mResult = false; $iErrorCode = -1; - if (2 < \strlen(APP_SITE)) - { - $sValue = $this->licenseHelper($bForce); + $oPremProvider = $this->PremProvider(); - if ($iStart === \time()) - { - \sleep(1); - } + if ($oPremProvider && 2 < \strlen(APP_SITE)) + { + $sValue = $oPremProvider->Fetcher($bForce); + + $this->requestSleep(); $iExpired = 0; - if ($this->licenseParser($sValue, $iExpired)) + if ($oPremProvider->Parser($sValue, $iExpired)) { $mResult = array( 'Banned' => false, @@ -3594,7 +3830,6 @@ class Actions */ public function DoAdminLicensingActivate() { - $iStart = \time(); $this->IsAdminLoggined(); $sDomain = (string) $this->GetActionParam('Domain', ''); @@ -3603,29 +3838,14 @@ class Actions $mResult = false; $iErrorCode = -1; - if (2 < \strlen($sDomain) && 2 < \strlen($sKey) && $sDomain === APP_SITE) + $oPrem = $this->PremProvider(); + + if ($oPrem && 2 < \strlen($sDomain) && 2 < \strlen($sKey) && $sDomain === APP_SITE) { $iCode = 0; - $sContentType = ''; + $sValue = $oPrem->Activate($sDomain, $sKey, $iCode); - $oHttp = \MailSo\Base\Http::SingletonInstance(); - - \sleep(1); - $sValue = $oHttp->GetUrlAsString(APP_API_PATH.'activate/'.\urlencode($sDomain).'/'.\urlencode($sKey), - 'RainLoop/'.APP_VERSION, $sContentType, $iCode, $this->Logger(), 10, - $this->Config()->Get('labs', 'curl_proxy', ''), $this->Config()->Get('labs', 'curl_proxy_auth', ''), - array(), false - ); - - if (200 !== $iCode) - { - $sValue = ''; - } - - if ($iStart + 2 > \time()) - { - \sleep(1); - } + $this->requestSleep(); $aMatch = array(); if ('OK' === $sValue) @@ -3639,6 +3859,7 @@ class Actions else if (\preg_match('/^ERROR:(.+)$/', $sValue, $aMatch) && !empty($aMatch[1])) { $mResult = trim($aMatch[1]); + $this->Logger()->Write('Activation error for: '.$sKey.' ('.$sDomain.')', \MailSo\Log\Enumerations\Type::ERROR); $this->Logger()->Write($mResult, \MailSo\Log\Enumerations\Type::ERROR); } @@ -3905,9 +4126,9 @@ class Actions /** * @return string */ - private function rainloopRepo() + private function rainLoopRepo() { - $sUrl = APP_REP_PATH; + $sUrl = APP_REPOSITORY_PATH; if ('' !== $sUrl) { $sUrl = rtrim($sUrl, '\\/').'/'; @@ -4094,7 +4315,7 @@ class Actions { $bRainLoopUpdatable = $this->rainLoopUpdatable(); - $aResult = $this->getRepositoryDataByUrl($this->rainloopRepo(), $bReal); + $aResult = $this->getRepositoryDataByUrl($this->rainLoopRepo(), $bReal); $aSub = array(); if (\is_array($aResult)) @@ -4240,10 +4461,10 @@ class Actions $this->IsAdminLoggined(); $bReal = false; - $sNewVersion = ''; $bRainLoopUpdatable = $this->rainLoopUpdatable(); $bRainLoopAccess = $this->rainLoopCoreAccess(); + $oPremProvider = $this->PremProvider(); $aData = array(); if ($bRainLoopUpdatable && $bRainLoopAccess) @@ -4252,132 +4473,14 @@ class Actions } $bResult = false; - if ($bReal && !empty($aData['file'])) + if ($bReal && $oPremProvider && !empty($aData['file'])) { - $sTmp = $this->downloadRemotePackageByUrl($aData['file']); - if (!empty($sTmp)) - { - include_once APP_VERSION_ROOT_PATH.'app/libraries/pclzip/pclzip.lib.php'; - - $oArchive = new \PclZip($sTmp); - $sTmpFolder = APP_PRIVATE_DATA.\md5($sTmp); - - \mkdir($sTmpFolder); - if (\is_dir($sTmpFolder)) - { - $bResult = 0 !== $oArchive->extract(PCLZIP_OPT_PATH, $sTmpFolder); - if (!$bResult) - { - $this->Logger()->Write('Cannot extract package files: '.$oArchive->errorInfo(), \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); - } - - if ($bResult && \file_exists($sTmpFolder.'/index.php') && - \is_writable(APP_INDEX_ROOT_PATH.'rainloop/') && - \is_writable(APP_INDEX_ROOT_PATH.'index.php') && - \is_dir($sTmpFolder.'/rainloop/')) - { - $aMatch = array(); - $sIndexFile = \file_get_contents($sTmpFolder.'/index.php'); - if (\preg_match('/\'APP_VERSION\', \'([^\']+)\'/', $sIndexFile, $aMatch) && !empty($aMatch[1])) - { - $sNewVersion = \trim($aMatch[1]); - } - - if (empty($sNewVersion)) - { - $this->Logger()->Write('Unknown version', \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); - } - else if (!\is_dir(APP_INDEX_ROOT_PATH.'rainloop/v/'.$sNewVersion)) - { - \MailSo\Base\Utils::CopyDir($sTmpFolder.'/rainloop/', APP_INDEX_ROOT_PATH.'rainloop/'); - - if (\is_dir(APP_INDEX_ROOT_PATH.'rainloop/v/'.$sNewVersion) && - \is_file(APP_INDEX_ROOT_PATH.'rainloop/v/'.$sNewVersion.'/index.php')) - { - $bResult = \copy($sTmpFolder.'/index.php', APP_INDEX_ROOT_PATH.'index.php'); - - if ($bResult) - { - if (\MailSo\Base\Utils::FunctionExistsAndEnabled('opcache_invalidate')) - { - @\opcache_invalidate(APP_INDEX_ROOT_PATH.'index.php', true); - } - - if (\MailSo\Base\Utils::FunctionExistsAndEnabled('apc_delete_file')) - { - @\apc_delete_file(APP_INDEX_ROOT_PATH.'index.php'); - } - } - } - else - { - $this->Logger()->Write('Cannot copy new package files', \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); - $this->Logger()->Write($sTmpFolder.'/rainloop/ -> '.APP_INDEX_ROOT_PATH.'rainloop/', \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); - } - } - else if (!empty($sNewVersion)) - { - $this->Logger()->Write('"'.$sNewVersion.'" version already installed', \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); - } - } - else if ($bResult) - { - $this->Logger()->Write('Cannot validate package files', \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); - } - - \MailSo\Base\Utils::RecRmDir($sTmpFolder); - } - else - { - $this->Logger()->Write('Cannot create tmp folder: '.$sTmpFolder, \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); - } - - @\unlink($sTmp); - } + $bResult = $oPremProvider->UpdateCore($this, $aData['file']); } return $this->DefaultResponse(__FUNCTION__, $bResult); } - public function removeOldVersion() - { - $sVPath = APP_INDEX_ROOT_PATH.'rainloop/v/'; - - $this->Logger()->Write('Versions GC: Begin'); - - $aDirs = @\array_map('basename', @\array_filter(@\glob($sVPath.'*'), 'is_dir')); - - $this->Logger()->Write('Versions GC: Count:'.(\is_array($aDirs) ? \count($aDirs) : 0)); - - if (\is_array($aDirs) && 5 < \count($aDirs)) - { - \uasort($aDirs, 'version_compare'); - - foreach ($aDirs as $sName) - { - if (APP_DEV_VERSION !== $sName && APP_VERSION !== $sName) - { - $this->Logger()->Write('Versions GC: Begin to remove "'.$sVPath.$sName.'" version'); - - if (@\unlink($sVPath.$sName.'/index.php')) - { - @\MailSo\Base\Utils::RecRmDir($sVPath.$sName); - } - else - { - $this->Logger()->Write('Versions GC (Error): index file cant be removed from"'.$sVPath.$sName.'"', - \MailSo\Log\Enumerations\Type::ERROR); - } - - $this->Logger()->Write('Versions GC: End to remove "'.$sVPath.$sName.'" version'); - break; - } - } - } - - $this->Logger()->Write('Versions GC: End'); - } - /** * @return array */ @@ -4419,7 +4522,7 @@ class Actions * * @return string */ - private function downloadRemotePackageByUrl($sUrl) + public function downloadRemotePackageByUrl($sUrl) { $bResult = false; $sTmp = APP_PRIVATE_DATA.\md5(\microtime(true).$sUrl).'.zip'; @@ -4486,7 +4589,7 @@ class Actions $bResult = false; if ('' !== $sRealFile) { - $sUrl = $this->rainloopRepo().$sRealFile; + $sUrl = $this->rainLoopRepo().$sRealFile; $sTmp = $this->downloadRemotePackageByUrl($sUrl); } @@ -4737,11 +4840,15 @@ class Actions */ public function DoSettingsUpdate() { + $oAccount = $this->getAccountFromToken(); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::SETTINGS, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } + $self = $this; $oConfig = $this->Config(); - $oAccount = $this->getAccountFromToken(); - $oSettings = $this->SettingsProvider()->Load($oAccount); $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); @@ -4817,12 +4924,14 @@ class Actions */ public function DoChangePassword() { + $mResult = false; + $oAccount = $this->getAccountFromToken(); if ($oAccount) { try { - $this->ChangePasswordProvider()->ChangePassword( + $mResult = $this->ChangePasswordProvider()->ChangePassword( $oAccount, $this->GetActionParam('PrevPassword', ''), $this->GetActionParam('NewPassword', '') @@ -4837,7 +4946,7 @@ class Actions } } - return $this->TrueResponse(__FUNCTION__); + return $this->DefaultResponse(__FUNCTION__, $mResult); } /** @@ -5076,15 +5185,6 @@ class Actions */ public function DoFolders() { -// \sleep(1); -// throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::MailServerError); - - $sRawKey = (string) $this->GetActionParam('RawKey', ''); - if (0 < \strlen($sRawKey)) - { - $this->verifyCacheByKey($sRawKey); - } - $oAccount = $this->initMailClientConnection(); $oFolderCollection = null; @@ -5092,7 +5192,8 @@ class Actions if (null === $oFolderCollection) { - $oFolderCollection = $this->MailClient()->Folders('', '*', + $oFolderCollection = $this->MailClient()->Folders('', + $this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount) ? '*' : 'INBOX', !!$this->Config()->Get('labs', 'use_imap_list_subscribe', true), (int) $this->Config()->Get('labs', 'imap_folder_list_limit', 200) ); @@ -5102,14 +5203,17 @@ class Actions if ($oFolderCollection instanceof \MailSo\Mail\FolderCollection) { - $aSystemFolders = array(); + $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); + $aSystemFolders = array(); $this->recFoldersTypes($oAccount, $oFolderCollection, $aSystemFolders); $oFolderCollection->SystemFolders = $aSystemFolders; - if ($this->Config()->Get('labs', 'autocreate_system_folders', true)) + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount) && + $this->Config()->Get('labs', 'autocreate_system_folders', true)) { $bDoItAgain = false; + $sNamespace = $oFolderCollection->GetNamespace(); $sParent = empty($sNamespace) ? '' : \substr($sNamespace, 0, -1); @@ -5117,23 +5221,28 @@ class Actions $aList = array(); $aMap = $this->systemFoldersNames($oAccount); - if ('' === $this->GetActionParam('SentFolder', '')) + + if ('' === $oSettingsLocal->GetConf('SentFolder', '')) { $aList[] = \MailSo\Imap\Enumerations\FolderType::SENT; } - if ('' === $this->GetActionParam('DraftFolder', '')) + + if ('' === $oSettingsLocal->GetConf('DraftFolder', '')) { $aList[] = \MailSo\Imap\Enumerations\FolderType::DRAFTS; } - if ('' === $this->GetActionParam('SpamFolder', '')) + + if ('' === $oSettingsLocal->GetConf('SpamFolder', '')) { $aList[] = \MailSo\Imap\Enumerations\FolderType::JUNK; } - if ('' === $this->GetActionParam('TrashFolder', '')) + + if ('' === $oSettingsLocal->GetConf('TrashFolder', '')) { $aList[] = \MailSo\Imap\Enumerations\FolderType::TRASH; } - if ('' === $this->GetActionParam('ArchiveFolder', '')) + + if ('' === $oSettingsLocal->GetConf('ArchiveFolder', '')) { $aList[] = \MailSo\Imap\Enumerations\FolderType::ALL; } @@ -5208,8 +5317,6 @@ class Actions if ($oFolderCollection) { $oFolderCollection->FoldersHash = \md5(\implode("\x0", $this->recFoldersNames($oFolderCollection))); - - $this->cacheByKey($sRawKey); } } @@ -5223,10 +5330,12 @@ class Actions */ public function DoFolderCreate() { -// \sleep(1); -// throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantCreateFolder); + $oAccount = $this->initMailClientConnection(); - $this->initMailClientConnection(); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } try { @@ -5249,14 +5358,19 @@ class Actions */ public function DoFolderSubscribe() { - $this->initMailClientConnection(); + $oAccount = $this->initMailClientConnection(); - $sFolderNameInUtf = $this->GetActionParam('Folder', ''); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } + + $sFolderFullNameRaw = $this->GetActionParam('Folder', ''); $bSubscribe = '1' === (string) $this->GetActionParam('Subscribe', '0'); try { - $this->MailClient()->FolderSubscribe($sFolderNameInUtf, !!$bSubscribe); + $this->MailClient()->FolderSubscribe($sFolderFullNameRaw, !!$bSubscribe); } catch (\Exception $oException) { @@ -5273,6 +5387,56 @@ class Actions return $this->TrueResponse(__FUNCTION__); } + /** + * @return array + */ + public function DoFolderCheckable() + { + $oAccount = $this->getAccountFromToken(); + + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } + + $sFolderFullNameRaw = $this->GetActionParam('Folder', ''); + $bCheckable = '1' === (string) $this->GetActionParam('Checkable', '0'); + + $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); + + $sCheckableFolder = $oSettingsLocal->GetConf('CheckableFolder', '[]'); + $aCheckableFolder = @\json_decode($sCheckableFolder); + + if (!\is_array($aCheckableFolder)) + { + $aCheckableFolder = array(); + } + + if ($bCheckable) + { + $aCheckableFolder[] = $sFolderFullNameRaw; + } + else + { + $aCheckableFolderNew = array(); + foreach ($aCheckableFolder as $sFolder) + { + if ($sFolder !== $sFolderFullNameRaw) + { + $aCheckableFolderNew[] = $sFolder; + } + } + $aCheckableFolder = $aCheckableFolderNew; + } + + $aCheckableFolder = \array_unique($aCheckableFolder); + + $oSettingsLocal->SetConf('CheckableFolder', @\json_encode($aCheckableFolder)); + + return $this->DefaultResponse(__FUNCTION__, + $this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal)); + } + /** * @return array * @@ -5280,7 +5444,12 @@ class Actions */ public function DoFolderRename() { - $this->initMailClientConnection(); + $oAccount = $this->initMailClientConnection(); + + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } $sPrevFolderFullNameRaw = $this->GetActionParam('Folder', ''); $sNewTopFolderNameInUtf = $this->GetActionParam('NewFolderName', ''); @@ -5305,10 +5474,12 @@ class Actions */ public function DoFolderDelete() { -// \sleep(1); -// throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantRenameFolder); + $oAccount = $this->initMailClientConnection(); - $this->initMailClientConnection(); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } $sFolderFullNameRaw = $this->GetActionParam('Folder', ''); @@ -5454,45 +5625,6 @@ class Actions return $this->DefaultResponse(__FUNCTION__, $aResult); } - /** - * @return array - * - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoMessageThreadsFromCache() - { - $sFolder = $this->GetActionParam('Folder', ''); - $sFolderHash = $this->GetActionParam('FolderHash', ''); - $sUid = (string) $this->GetActionParam('Uid', ''); - - if (0 === \strlen($sFolder) || 0 === \strlen($sUid)) - { - throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidInputArgument); - } - - $aResult = array( - 'Folder' => $sFolder, - 'Uid' => $sUid, - 'FolderHash' => $sFolderHash, - 'ThreadUids' => null - ); - - $oCache = $this->cacherForUids(); - if ($oCache && $this->Config()->Get('labs', 'use_imap_thread', false)) - { - $aThreadUids = $this->MailClient()->MessageThreadUidsFromCache( - $sFolder, $sFolderHash, $sUid, $oCache - ); - - if (\is_array($aThreadUids) && 1 < \count($aThreadUids)) - { - $aResult['ThreadUids'] = $aThreadUids; - } - } - - return $this->DefaultResponse(__FUNCTION__, $aResult); - } - /** * @return array * @@ -5509,11 +5641,12 @@ class Actions $sSearch = ''; $sUidNext = ''; $bUseThreads = false; + $sThreadUid = ''; $sRawKey = $this->GetActionParam('RawKey', ''); $aValues = $this->getDecodedClientRawKeyValue($sRawKey, 9); - if (\is_array($aValues) && 9 === \count($aValues)) + if (\is_array($aValues) && 7 < \count($aValues)) { $sFolder =(string) $aValues[0]; $iOffset = (int) $aValues[1]; @@ -5522,6 +5655,11 @@ class Actions $sUidNext = (string) $aValues[6]; $bUseThreads = (bool) $aValues[7]; + if ($bUseThreads) + { + $sThreadUid = isset($aValues[8]) ? (string) $aValues[8] : ''; + } + $this->verifyCacheByKey($sRawKey); } else @@ -5532,6 +5670,11 @@ class Actions $sSearch = $this->GetActionParam('Search', ''); $sUidNext = $this->GetActionParam('UidNext', ''); $bUseThreads = '1' === (string) $this->GetActionParam('UseThreads', '0'); + + if ($bUseThreads) + { + $sThreadUid = (string) $this->GetActionParam('ThreadUid', ''); + } } if (0 === strlen($sFolder)) @@ -5553,7 +5696,8 @@ class Actions $this->cacherForUids(), !!$this->Config()->Get('labs', 'use_imap_sort', false), $bUseThreads, - !!$this->Config()->Get('labs', 'use_imap_esearch_esort', false) + $sThreadUid, + '' ); } catch (\Exception $oException) @@ -5569,40 +5713,6 @@ class Actions return $this->DefaultResponse(__FUNCTION__, $oMessageList); } - /** - * @return array - * - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoMessageListSimple() - { -// \sleep(2); -// throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantGetMessageList); - - $sFolder = $this->GetActionParam('Folder', ''); - $aUids = $this->GetActionParam('Uids', null); - - if (0 === \strlen($sFolder) || !\is_array($aUids)) - { - throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidInputArgument); - } - - $this->initMailClientConnection(); - - $aMessageList = array(); - - try - { - $aMessageList = $this->MailClient()->MessageListSimple($sFolder, $aUids); - } - catch (\Exception $oException) - { - throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantGetMessageList, $oException); - } - - return $this->DefaultResponse(__FUNCTION__, $aMessageList); - } - /** * @param \RainLoop\Model\Account $oAccount * @param bool $bWithDraftInfo = true @@ -5854,6 +5964,11 @@ class Actions { $oAccount = $this->initMailClientConnection(); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::COMPOSER, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } + $sMessageFolder = $this->GetActionParam('MessageFolder', ''); $sMessageUid = $this->GetActionParam('MessageUid', ''); @@ -5976,11 +6091,26 @@ class Actions list($sMailHeaders, $sMailBody) = \explode("\r\n\r\n", $sRawBody, 2); unset($sRawBody); -// $this->Logger()->WriteDump(array( -// $sMailTo, $sMailSubject, $sMailBody, $sMailHeaders -// )); + if ($this->Config()->Get('labs', 'mail_func_clear_headers', true)) + { + $sMailHeaders = \MailSo\Base\Utils::RemoveHeaderFromHeaders($sMailHeaders, array( + \MailSo\Mime\Enumerations\Header::TO_, + \MailSo\Mime\Enumerations\Header::SUBJECT + )); + } - if (!\mail($sMailTo, $sMailSubject, $sMailBody, $sMailHeaders/*, '-f'.$oFrom->GetEmail()*/)) + if ($this->Config()->Get('debug', 'enable', false)) + { + $this->Logger()->WriteDump(array( + $sMailTo, $sMailSubject, $sMailBody, $sMailHeaders + )); + } + + $bR = $this->Config()->Get('labs', 'mail_func_additional_parameters', false) ? + \mail($sMailTo, $sMailSubject, $sMailBody, $sMailHeaders, '-f'.$oFrom->GetEmail()) : + \mail($sMailTo, $sMailSubject, $sMailBody, $sMailHeaders); + + if (!$bR) { throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantSendMessage); } @@ -6066,6 +6196,11 @@ class Actions { $oAccount = $this->initMailClientConnection(); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::COMPOSER, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } + $oConfig = $this->Config(); $sDraftFolder = $this->GetActionParam('MessageFolder', ''); @@ -6251,6 +6386,11 @@ class Actions { $oAccount = $this->initMailClientConnection(); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::COMPOSER, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } + $oMessage = $this->buildReadReceiptMessage($oAccount); $this->Plugins()->RunHook('filter.send-read-receipt-message', array(&$oMessage, $oAccount)); @@ -6318,7 +6458,12 @@ class Actions */ public function DoQuota() { - $this->initMailClientConnection(); + $oAccount = $this->initMailClientConnection(); + + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::QUOTA, $oAccount)) + { + return $this->DefaultResponse(__FUNCTION__, array(0, 0, 0, 0)); + } try { @@ -6576,7 +6721,8 @@ class Actions )) ); - \sleep(1); + $this->requestSleep(); + return $this->DefaultResponse(__FUNCTION__, $this->getTwoFactorInfo($oAccount)); } @@ -6660,7 +6806,8 @@ class Actions // $this->TwoFactorAuthProvider()->VerifyCode($sSecret, $sCode) // )); - \sleep(1); + $this->requestSleep(); + return $this->DefaultResponse(__FUNCTION__, $this->TwoFactorAuthProvider()->VerifyCode($sSecret, $sCode)); } @@ -6795,6 +6942,8 @@ class Actions $oContact->Etag = \md5($oContact->ToVCard()); } + $oContact->PopulateDisplayAndFullNameValue(true); + $bResult = $oAddressBookProvider->ContactSave($oAccount->ParentEmailHelper(), $oContact); } @@ -6857,8 +7006,7 @@ class Actions $oSuggestionsProvider = $this->SuggestionsProvider(); if ($oSuggestionsProvider && $oSuggestionsProvider->IsActive()) { - $iSuggestionLimit = $iLimit - \count($aResult); - $aSuggestionsProviderResult = $oSuggestionsProvider->Process($oAccount, $sQuery, $iSuggestionLimit); + $aSuggestionsProviderResult = $oSuggestionsProvider->Process($oAccount, $sQuery, $iLimit); if (\is_array($aSuggestionsProviderResult) && 0 < \count($aSuggestionsProviderResult)) { $aResult = \array_merge($aResult, $aSuggestionsProviderResult); @@ -7043,12 +7191,25 @@ class Actions $sFromFolder = $this->GetActionParam('FromFolder', ''); $sToFolder = $this->GetActionParam('ToFolder', ''); $aUids = \explode(',', (string) $this->GetActionParam('Uids', '')); + $bMarkAsRead = '1' === (string) $this->GetActionParam('MarkAsRead', '0'); $aFilteredUids = \array_filter($aUids, function (&$mUid) { $mUid = (int) \trim($mUid); return 0 < $mUid; }); + if ($bMarkAsRead) + { + try + { + $this->MailClient()->MessageSetSeen($sFromFolder, $aFilteredUids, true, true); + } + catch (\Exception $oException) + { + unset($oException); + } + } + try { $this->MailClient()->MessageMove($sFromFolder, $sToFolder, $aFilteredUids, true, @@ -7112,7 +7273,7 @@ class Actions public function MainClearFileName($sFileName, $sContentType, $sMimeIndex, $iMaxLength = 250) { $sFileName = 0 === \strlen($sFileName) ? \preg_replace('/[^a-zA-Z0-9]/', '.', (empty($sMimeIndex) ? '' : $sMimeIndex.'.').$sContentType) : $sFileName; - $sClearedFileName = \preg_replace('/[\s]+/', ' ', \preg_replace('/[\.]+/', '.', $sFileName)); + $sClearedFileName = \MailSo\Base\Utils::StripSpaces(\preg_replace('/[\.]+/', '.', $sFileName)); $sExt = \MailSo\Base\Utils::GetFileExtension($sClearedFileName); if (10 < $iMaxLength && $iMaxLength < \strlen($sClearedFileName) - \strlen($sExt)) @@ -7136,19 +7297,19 @@ class Actions try { $aAttachments = $this->GetActionParam('Attachments', array()); - if (is_array($aAttachments) && 0 < count($aAttachments)) + if (\is_array($aAttachments) && 0 < \count($aAttachments)) { $mResult = array(); foreach ($aAttachments as $sAttachment) { - $aValues = \RainLoop\Utils::DecodeKeyValues($sAttachment); - if (is_array($aValues)) + $aValues = \RainLoop\Utils::DecodeKeyValuesQ($sAttachment); + if (\is_array($aValues)) { $sFolder = isset($aValues['Folder']) ? $aValues['Folder'] : ''; $iUid = (int) isset($aValues['Uid']) ? $aValues['Uid'] : 0; $sMimeIndex = (string) isset($aValues['MimeIndex']) ? $aValues['MimeIndex'] : ''; - $sTempName = md5($sAttachment); + $sTempName = \md5($sAttachment); if (!$this->FilesProvider()->FileExists($oAccount, $sTempName)) { $this->MailClient()->MessageMimeStream( @@ -7724,10 +7885,10 @@ class Actions $iUid = (int) (isset($aValues['Uid']) ? $aValues['Uid'] : 0); $sMimeIndex = (string) (isset($aValues['MimeIndex']) ? $aValues['MimeIndex'] : ''); - header('Content-Type: text/plain', true); + \header('Content-Type: text/plain', true); return $this->MailClient()->MessageMimeStream(function ($rResource) { - if (is_resource($rResource)) + if (\is_resource($rResource)) { \MailSo\Base\Utils::FpassthruWithTimeLimitReset($rResource); } @@ -7746,7 +7907,7 @@ class Actions $aParams = $this->GetActionParam('Params', null); $this->Http()->ServerNoCache(); - $aData = \RainLoop\Utils::DecodeKeyValues($sRawKey); + $aData = \RainLoop\Utils::DecodeKeyValuesQ($sRawKey); if (isset($aParams[0], $aParams[1], $aParams[2]) && 'Raw' === $aParams[0] && 'FramedView' === $aParams[2] && isset($aData['Framed']) && $aData['Framed'] && $aData['FileName']) { @@ -7831,23 +7992,73 @@ class Actions $aResult = array(); - if ($oConfig->Get('capa', 'filters', false)) + if ($oConfig->Get('capa', 'folders', true)) { - $aResult[] = \RainLoop\Enumerations\Capa::FILTERS; - if ($bAdmin || ($oAccount && $oAccount->Domain()->UseSieve())) + $aResult[] = \RainLoop\Enumerations\Capa::FOLDERS; + + if ($oConfig->Get('capa', 'messagelist_actions', true)) { - $aResult[] = \RainLoop\Enumerations\Capa::SIEVE; + $aResult[] = \RainLoop\Enumerations\Capa::MESSAGELIST_ACTIONS; + + if ($oConfig->Get('capa', 'dangerous_actions', true)) + { + $aResult[] = \RainLoop\Enumerations\Capa::DANGEROUS_ACTIONS; + } } } -// if ($oConfig->Get('capa', 'templates', true)) -// { -// $aResult[] = \RainLoop\Enumerations\Capa::TEMPLATES; -// } - - if ($oConfig->Get('webmail', 'allow_additional_accounts', false)) + if ($oConfig->Get('capa', 'reload', true)) { - $aResult[] = \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS; + $aResult[] = \RainLoop\Enumerations\Capa::RELOAD; + } + + if ($oConfig->Get('capa', 'quota', true)) + { + $aResult[] = \RainLoop\Enumerations\Capa::QUOTA; + } + + if ($oConfig->Get('capa', 'settings', true)) + { + $aResult[] = \RainLoop\Enumerations\Capa::SETTINGS; + + if ($oConfig->Get('webmail', 'allow_additional_accounts', false)) + { + $aResult[] = \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS; + } + + if ($oConfig->Get('webmail', 'allow_additional_identities', false)) + { + $aResult[] = \RainLoop\Enumerations\Capa::IDENTITIES; + } + + if ($oConfig->Get('capa', 'x-templates', true)) + { + $aResult[] = \RainLoop\Enumerations\Capa::TEMPLATES; + } + + if ($oConfig->Get('webmail', 'allow_themes', false)) + { + $aResult[] = \RainLoop\Enumerations\Capa::THEMES; + } + + if ($oConfig->Get('webmail', 'allow_user_background', false)) + { + $aResult[] = \RainLoop\Enumerations\Capa::USER_BACKGROUND; + } + + if ($oConfig->Get('security', 'openpgp', false)) + { + $aResult[] = \RainLoop\Enumerations\Capa::OPEN_PGP; + } + + if ($oConfig->Get('capa', 'filters', false)) + { + $aResult[] = \RainLoop\Enumerations\Capa::FILTERS; + if ($bAdmin || ($oAccount && $oAccount->Domain()->UseSieve())) + { + $aResult[] = \RainLoop\Enumerations\Capa::SIEVE; + } + } } if ($oConfig->Get('security', 'allow_two_factor_auth', false) && @@ -7862,6 +8073,41 @@ class Actions } } + if ($oConfig->Get('capa', 'help', true)) + { + $aResult[] = \RainLoop\Enumerations\Capa::HELP; + } + + if ($oConfig->Get('capa', 'attachments_actions', false)) + { + $aResult[] = \RainLoop\Enumerations\Capa::ATTACHMENTS_ACTIONS; + } + + if ($oConfig->Get('capa', 'message_actions', true)) + { + $aResult[] = \RainLoop\Enumerations\Capa::MESSAGE_ACTIONS; + } + + if ($oConfig->Get('capa', 'composer', true)) + { + $aResult[] = \RainLoop\Enumerations\Capa::COMPOSER; + + if ($oConfig->Get('capa', 'contacts', true)) + { + $aResult[] = \RainLoop\Enumerations\Capa::CONTACTS; + } + } + + if ($oConfig->Get('capa', 'search', true)) + { + $aResult[] = \RainLoop\Enumerations\Capa::SEARCH; + + if ($oConfig->Get('capa', 'search_adv', true)) + { + $aResult[] = \RainLoop\Enumerations\Capa::SEARCH_ADV; + } + } + if ($oConfig->Get('labs', 'allow_gravatar', false)) { $aResult[] = \RainLoop\Enumerations\Capa::GRAVATAR; @@ -7877,21 +8123,6 @@ class Actions $aResult[] = \RainLoop\Enumerations\Capa::PREFETCH; } - if ($oConfig->Get('webmail', 'allow_themes', false)) - { - $aResult[] = \RainLoop\Enumerations\Capa::THEMES; - } - - if ($oConfig->Get('webmail', 'allow_user_background', false)) - { - $aResult[] = \RainLoop\Enumerations\Capa::USER_BACKGROUND; - } - - if ($oConfig->Get('security', 'openpgp', false)) - { - $aResult[] = \RainLoop\Enumerations\Capa::OPEN_PGP; - } - if (!\RainLoop\Utils::IsOwnCloud()) { $aResult[] = \RainLoop\Enumerations\Capa::AUTOLOGOUT; @@ -7955,6 +8186,57 @@ class Actions } } + /** + * @param \RainLoop\Model\Account $oAccount + * @param string $sHash + * + * @return array + */ + private function getMimeFileByHash($oAccount, $sHash) + { + $aValues = $this->getDecodedRawKeyValue($sHash); + + $sFolder = isset($aValues['Folder']) ? $aValues['Folder'] : ''; + $iUid = (int) isset($aValues['Uid']) ? $aValues['Uid'] : 0; + $sMimeIndex = (string) isset($aValues['MimeIndex']) ? $aValues['MimeIndex'] : ''; + + $sContentTypeIn = (string) isset($aValues['MimeType']) ? $aValues['MimeType'] : ''; + $sFileNameIn = (string) isset($aValues['FileName']) ? $aValues['FileName'] : ''; + + $oFileProvider = $this->FilesProvider(); + + $sResultHash = ''; + + $mResult = $this->MailClient()->MessageMimeStream(function($rResource, $sContentType, $sFileName, $sMimeIndex = '') + use ($oAccount, $oFileProvider, $sFileNameIn, $sContentTypeIn, &$sResultHash) { + + if ($oAccount && \is_resource($rResource)) + { + $sHash = \MailSo\Base\Utils::Md5Rand($sFileNameIn.'~'.$sContentTypeIn); + $rTempResource = $oFileProvider->GetFile($oAccount, $sHash, 'wb+'); + + if (@\is_resource($rTempResource)) + { + if (false !== \MailSo\Base\Utils::MultipleStreamWriter($rResource, array($rTempResource))) + { + $sResultHash = $sHash; + } + + @\fclose($rTempResource); + } + } + + }, $sFolder, $iUid, true, $sMimeIndex); + + $aValues['FileHash'] = ''; + if ($mResult) + { + $aValues['FileHash'] = $sResultHash; + } + + return $aValues; + } + /** * @param bool $bDownload * @param bool $bThumbnail = false @@ -7967,15 +8249,50 @@ class Actions $aValues = $this->getDecodedRawKeyValue($sRawKey); $sFolder = isset($aValues['Folder']) ? $aValues['Folder'] : ''; - $iUid = (int) isset($aValues['Uid']) ? $aValues['Uid'] : 0; - $sMimeIndex = (string) isset($aValues['MimeIndex']) ? $aValues['MimeIndex'] : ''; + $iUid = isset($aValues['Uid']) ? (int) $aValues['Uid'] : 0; + $sMimeIndex = isset($aValues['MimeIndex']) ? (string) $aValues['MimeIndex'] : ''; - $sContentTypeIn = (string) isset($aValues['MimeType']) ? $aValues['MimeType'] : ''; - $sFileNameIn = (string) isset($aValues['FileName']) ? $aValues['FileName'] : ''; + $sContentTypeIn = isset($aValues['MimeType']) ? (string) $aValues['MimeType'] : ''; + $sFileNameIn = isset($aValues['FileName']) ? (string) $aValues['FileName'] : ''; + $sFileHashIn = isset($aValues['FileHash']) ? (string) $aValues['FileHash'] : ''; - if (!empty($sFolder) && 0 < $iUid) + if (!empty($sFileHashIn)) { $this->verifyCacheByKey($sRawKey); + + $oAccount = $this->getAccountFromToken(); + + $sContentTypeOut = empty($sContentTypeIn) ? + \MailSo\Base\Utils::MimeContentType($sFileNameIn) : $sContentTypeIn; + + $sFileNameOut = $this->MainClearFileName($sFileNameIn, $sContentTypeIn, $sMimeIndex); + + $rResource = $this->FilesProvider()->GetFile($oAccount, $sFileHashIn); + if (\is_resource($rResource)) + { + $sFileNameOut = \MailSo\Base\Utils::ConvertEncoding( + $sFileNameOut, \MailSo\Base\Enumerations\Charset::UTF_8, + \MailSo\Base\Enumerations\Charset::CP858); + + \header('Content-Type: '.$sContentTypeOut); + \header('Content-Disposition: attachment; '. + \trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileNameOut)), true); + + \header('Accept-Ranges: none', true); + \header('Content-Transfer-Encoding: binary'); + + \MailSo\Base\Utils::FpassthruWithTimeLimitReset($rResource); + return true; + } + + return false; + } + else + { + if (!empty($sFolder) && 0 < $iUid) + { + $this->verifyCacheByKey($sRawKey); + } } $oAccount = $this->initMailClientConnection(); @@ -8008,21 +8325,28 @@ class Actions $bDone = false; if ($bThumbnail && !$bDownload) { - \MailSo\Base\StreamWrappers\TempFile::Reg(); + $sFileName = ''; + $rTempResource = \MailSo\Base\StreamWrappers\TempFile::CreateStream( + \MailSo\Base\Utils::Md5Rand($sFileNameOut), $sFileName); - $sFileName = 'mailsotempfile://'.\MailSo\Base\Utils::Md5Rand($sFileNameOut); - - $rTempResource = @\fopen($sFileName, 'r+b'); if (@\is_resource($rTempResource)) { + $bDone = true; + \MailSo\Base\Utils::MultipleStreamWriter($rResource, array($rTempResource)); @\fclose($rTempResource); - $oThumb =@ new \PHPThumb\GD($sFileName); - if ($oThumb) + try { - $oThumb->adaptiveResize(60, 60)->show(); - $bDone = true; + $oThumb = new \PHPThumb\GD($sFileName); + if ($oThumb) + { + $oThumb->adaptiveResize(60, 60)->show(); + } + } + catch (\Exception $oException) + { + $self->Logger()->WriteExceptionShort($oException); } } } @@ -8321,7 +8645,7 @@ class Actions $bResult = false; if (!empty($sRawKey)) { - $aValues = \RainLoop\Utils::DecodeKeyValues($sRawKey); + $aValues = \RainLoop\Utils::DecodeKeyValuesQ($sRawKey); if (is_array($aValues)) { $bResult = $aValues; @@ -8369,10 +8693,11 @@ class Actions * @param string $sDefault = '' * @param bool $bAdmin = false * @param bool $bSearchShortName = false + * @param bool $bAllowEmptyResult = false * * @return string */ - public function ValidateLanguage($sLanguage, $sDefault = '', $bAdmin = false, $bSearchShortName = false) + public function ValidateLanguage($sLanguage, $sDefault = '', $bAdmin = false, $bSearchShortName = false, $bAllowEmptyResult = false) { $sResult = ''; $aLang = $this->GetLanguages($bAdmin); @@ -8398,7 +8723,7 @@ class Actions $sResult = $sDefault; } - if (empty($sResult)) + if (empty($sResult) && !$bAllowEmptyResult) { $sResult = $this->Config()->Get('webmail', $bAdmin ? 'language_admin' : 'language', 'en'); $sResult = \in_array($sResult, $aLang) ? $sResult : 'en'; @@ -9050,17 +9375,59 @@ class Actions if (\is_object($mResponse)) { $bHook = true; + $self = $this; $sClassName = \get_class($mResponse); $bHasSimpleJsonFunc = \method_exists($mResponse, 'ToSimpleJSON'); $bThumb = $this->GetCapa(false, \RainLoop\Enumerations\Capa::ATTACHMENT_THUMBNAILS); + $oAccountCache = null; + $fGetAccount = function () use ($self, &$oAccountCache) { + if (null === $oAccountCache) + { + $oAccount = $self->getAccountFromToken(false); + $oAccountCache = $oAccount; + } + + return $oAccountCache; + }; + + $aCheckableFoldersCache = null; + $fGetCheckableFolder = function () use ($self, &$aCheckableFoldersCache) { + if (null === $aCheckableFoldersCache) + { + $oAccount = $self->getAccountFromToken(false); + + $oSettingsLocal = $self->SettingsProvider(true)->Load($oAccount); + $sCheckable = $oSettingsLocal->GetConf('CheckableFolder', '[]'); + $aCheckable = @\json_decode($sCheckable); + if (!\is_array($aCheckable)) + { + $aCheckable = array(); + } + + $aCheckableFoldersCache = $aCheckable; + } + + return $aCheckableFoldersCache; + }; + if ($bHasSimpleJsonFunc) { $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), $mResponse->ToSimpleJSON(true)); } else if ('MailSo\Mail\Message' === $sClassName) { - $oAccount = $this->getAccountFromToken(false); + $oAccount = \call_user_func($fGetAccount); + + $iDateTimeStampInUTC = $mResponse->InternalTimeStampInUTC(); + if (0 === $iDateTimeStampInUTC || !!$this->Config()->Get('labs', 'date_from_headers', false)) + { + $iDateTimeStampInUTC = $mResponse->HeaderTimeStampInUTC(); + if (0 === $iDateTimeStampInUTC) + { + $iDateTimeStampInUTC = $mResponse->InternalTimeStampInUTC(); + } + } $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array( 'Folder' => $mResponse->Folder(), @@ -9068,8 +9435,7 @@ class Actions 'Subject' => \trim(\MailSo\Base\Utils::Utf8Clear($mResponse->Subject())), 'MessageId' => $mResponse->MessageId(), 'Size' => $mResponse->Size(), - 'DateTimeStampInUTC' => !!$this->Config()->Get('labs', 'date_from_headers', false) - ? $mResponse->HeaderTimeStampInUTC() : $mResponse->InternalTimeStampInUTC(), + 'DateTimeStampInUTC' => $iDateTimeStampInUTC, 'ReplyTo' => $this->responseObject($mResponse->ReplyTo(), $sParent, $aParameters), 'From' => $this->responseObject($mResponse->From(), $sParent, $aParameters), 'To' => $this->responseObject($mResponse->To(), $sParent, $aParameters), @@ -9094,7 +9460,7 @@ class Actions $sSubject = $mResult['Subject']; $mResult['Hash'] = \md5($mResult['Folder'].$mResult['Uid']); - $mResult['RequestHash'] = \RainLoop\Utils::EncodeKeyValues(array( + $mResult['RequestHash'] = \RainLoop\Utils::EncodeKeyValuesQ(array( 'V' => APP_VERSION, 'Account' => $oAccount ? \md5($oAccount->Hash()) : '', 'Folder' => $mResult['Folder'], @@ -9116,6 +9482,11 @@ class Actions $mResult['IsForwarded'] = 0 < \strlen($sForwardedFlag) && \in_array(\strtolower($sForwardedFlag), $aFlags); $mResult['IsReadReceipt'] = 0 < \strlen($sReadReceiptFlag) && \in_array(\strtolower($sReadReceiptFlag), $aFlags); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::COMPOSER, $oAccount)) + { + $mResult['IsReadReceipt'] = true; + } + $mResult['TextPartIsTrimmed'] = false; if ('Message' === $sParent) @@ -9155,11 +9526,29 @@ class Actions $mResult['InReplyTo'] = $mResponse->InReplyTo(); $mResult['References'] = $mResponse->References(); + $fAdditionalDomReader = null; + if (0 < \strlen($sHtml) && $this->Config()->Get('labs', 'emogrifier', false)) + { + if (!\class_exists('Pelago\Emogrifier', false)) + { + include_once APP_VERSION_ROOT_PATH.'app/libraries/emogrifier/Emogrifier.php'; + } + + if (\class_exists('Pelago\Emogrifier', false)) + { + $fAdditionalDomReader = function ($oDom) { + $oEmogrifier = new \Pelago\Emogrifier(); + $oEmogrifier->preserveEncoding = false; + return $oEmogrifier->emogrify($oDom); + }; + } + } + $fAdditionalExternalFilter = null; if (!!$this->Config()->Get('labs', 'use_local_proxy_for_external_images', false)) { $fAdditionalExternalFilter = function ($sUrl) { - return './?/ProxyExternal/'.\RainLoop\Utils::EncodeKeyValues(array( + return './?/ProxyExternal/'.\RainLoop\Utils::EncodeKeyValuesQ(array( 'Rnd' => \md5(\microtime(true)), 'Token' => \RainLoop\Utils::GetConnectionToken(), 'Url' => $sUrl @@ -9167,9 +9556,14 @@ class Actions }; } +// $this->Logger()->Write('---'); +// $this->Logger()->Write($sHtml); + $mResult['Html'] = 0 === \strlen($sHtml) ? '' : \MailSo\Base\HtmlUtils::ClearHtml( $sHtml, $bHasExternals, $mFoundedCIDs, $aContentLocationUrls, $mFoundedContentLocationUrls, false, false, - $fAdditionalExternalFilter); + $fAdditionalExternalFilter, $fAdditionalDomReader, + !!$this->Config()->Get('labs', 'try_to_detect_hidden_images', false) + ); $mResult['ExternalProxy'] = null !== $fAdditionalExternalFilter; @@ -9309,7 +9703,7 @@ class Actions $mResult['IsThumbnail'] = $this->isFileHasThumbnail($mResult['FileName']); } - $mResult['Download'] = \RainLoop\Utils::EncodeKeyValues(array( + $mResult['Download'] = \RainLoop\Utils::EncodeKeyValuesQ(array( 'V' => APP_VERSION, 'Account' => $oAccount ? \md5($oAccount->Hash()) : '', 'Folder' => $mResult['Folder'], @@ -9323,16 +9717,24 @@ class Actions else if ('MailSo\Mail\Folder' === $sClassName) { $aExtended = null; - $mStatus = $mResponse->Status(); - if (\is_array($mStatus) && isset($mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT'])) + +// $mStatus = $mResponse->Status(); +// if (\is_array($mStatus) && isset($mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT'])) +// { +// $aExtended = array( +// 'MessageCount' => (int) $mStatus['MESSAGES'], +// 'MessageUnseenCount' => (int) $mStatus['UNSEEN'], +// 'UidNext' => (string) $mStatus['UIDNEXT'], +// 'Hash' => $this->MailClient()->GenerateFolderHash( +// $mResponse->FullNameRaw(), $mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT'], +// empty($mStatus['HIGHESTMODSEQ']) ? '' : $mStatus['HIGHESTMODSEQ']) +// ); +// } + + $aCheckableFolder = \call_user_func($fGetCheckableFolder); + if (!\is_array($aCheckableFolder)) { - $aExtended = array( - 'MessageCount' => (int) $mStatus['MESSAGES'], - 'MessageUnseenCount' => (int) $mStatus['UNSEEN'], - 'UidNext' => (string) $mStatus['UIDNEXT'], - 'Hash' => $this->MailClient()->GenerateFolderHash( - $mResponse->FullNameRaw(), $mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT']) - ); + $aCheckableFolder = array(); } $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array( @@ -9346,6 +9748,7 @@ class Actions 'IsExists' => $mResponse->IsExists(), 'IsSelectable' => $mResponse->IsSelectable(), 'Flags' => $mResponse->FlagsLowerCase(), + 'Checkable' => \in_array($mResponse->FullNameRaw(), $aCheckableFolder), 'Extended' => $aExtended, 'SubFolders' => $this->responseObject($mResponse->SubFolders(), $sParent, $aParameters) )); @@ -9359,8 +9762,9 @@ class Actions 'Folder' => $mResponse->FolderName, 'FolderHash' => $mResponse->FolderHash, 'UidNext' => $mResponse->UidNext, + 'ThreadUid' => $mResponse->ThreadUid, 'NewMessages' => $this->responseObject($mResponse->NewMessages), -// 'LastCollapsedThreadUids' => $mResponse->LastCollapsedThreadUids, + 'Filtered' => $mResponse->Filtered, 'Offset' => $mResponse->Offset, 'Limit' => $mResponse->Limit, 'Search' => $mResponse->Search @@ -9379,7 +9783,9 @@ class Actions 'FoldersHash' => isset($mResponse->FoldersHash) ? $mResponse->FoldersHash : '', 'IsThreadsSupported' => $mResponse->IsThreadsSupported, 'Optimized' => $mResponse->Optimized, - 'SystemFolders' => isset($mResponse->SystemFolders) && \is_array($mResponse->SystemFolders) ? $mResponse->SystemFolders : array() + 'CountRec' => $mResponse->CountRec(), + 'SystemFolders' => isset($mResponse->SystemFolders) && \is_array($mResponse->SystemFolders) ? + $mResponse->SystemFolders : array() )); } else if ($mResponse instanceof \MailSo\Base\Collection) diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Api.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Api.php index c05c589fe..5680c1359 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Api.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Api.php @@ -32,6 +32,7 @@ class Api if ($bOne) { \RainLoop\Api::SetupDefaultMailSoConfig(); + $bOne = \RainLoop\Api::RunResult(); } } @@ -91,14 +92,24 @@ class Api \MailSo\Config::$MessageListDateFilter = (int) \RainLoop\Api::Config()->Get('labs', 'imap_message_list_date_filter', 0); + \MailSo\Config::$MessageListPermanentFilter = + \trim(\RainLoop\Api::Config()->Get('labs', 'imap_message_list_permanent_filter', '')); + + \MailSo\Config::$MessageAllHeaders = + !!\RainLoop\Api::Config()->Get('labs', 'imap_message_all_headers', false); + \MailSo\Config::$LargeThreadLimit = (int) \RainLoop\Api::Config()->Get('labs', 'imap_large_thread_limit', 50); + \MailSo\Config::$BoundaryPrefix = '_RainLoop_'; + \MailSo\Config::$SystemLogger = \RainLoop\Api::Logger(); $sSslCafile = \RainLoop\Api::Config()->Get('ssl', 'cafile', ''); $sSslCapath = \RainLoop\Api::Config()->Get('ssl', 'capath', ''); + \RainLoop\Utils::$CookieDefaultPath = \RainLoop\Api::Config()->Get('labs', 'cookie_path', '/'); + if (!empty($sSslCafile) || !empty($sSslCapath)) { \MailSo\Hooks::Add('Net.NetClient.StreamContextSettings/Filter', function (&$aStreamContextSettings) use ($sSslCafile, $sSslCapath) { @@ -139,12 +150,13 @@ class Api { $sSsoHash = \MailSo\Base\Utils::Sha1Rand($sEmail.$sPassword); - return \RainLoop\Api::Actions()->Cacher()->Set(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash), \RainLoop\Utils::EncodeKeyValues(array( - 'Email' => $sEmail, - 'Password' => $sPassword, - 'AdditionalOptions' => $aAdditionalOptions, - 'Time' => $bUseTimeout ? \time() : 0 - ))) ? $sSsoHash : ''; + return \RainLoop\Api::Actions()->Cacher()->Set(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash), + \RainLoop\Utils::EncodeKeyValuesQ(array( + 'Email' => $sEmail, + 'Password' => $sPassword, + 'AdditionalOptions' => $aAdditionalOptions, + 'Time' => $bUseTimeout ? \time() : 0 + ))) ? $sSsoHash : ''; } /** diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Common/PdoAbstract.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Common/PdoAbstract.php index 36dac7f96..13c5d9e59 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Common/PdoAbstract.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Common/PdoAbstract.php @@ -14,6 +14,11 @@ abstract class PdoAbstract */ protected $bExplain = false; + /** + * @var bool + */ + protected $bSqliteCollate = true; + /** * @var \MailSo\Log\Logger */ @@ -48,6 +53,18 @@ abstract class PdoAbstract return array('', '', '', ''); } + /** + * @param string $sStr1 + * @param string $sStr2 + * + * @return int + */ + public function sqliteNoCaseCollationHelper($sStr1, $sStr2) + { + $this->oLogger->WriteDump(array($sStr1, $sStr2)); + return \strcmp(\mb_strtoupper($sStr1, 'UTF-8'), \mb_strtoupper($sStr2, 'UTF-8')); + } + /** * @return \PDO * @@ -67,6 +84,7 @@ abstract class PdoAbstract $sType = $sDsn = $sDbLogin = $sDbPassword = ''; list($sType, $sDsn, $sDbLogin, $sDbPassword) = $this->getPdoAccessData(); + if (!\in_array($sType, array('mysql', 'sqlite', 'pgsql'))) { throw new \Exception('Unknown PDO SQL connection type'); @@ -82,15 +100,28 @@ abstract class PdoAbstract $oPdo = false; try { +// $bCaseFunc = false; $oPdo = @new \PDO($sDsn, $sDbLogin, $sDbPassword); if ($oPdo) { + $sPdoType = $oPdo->getAttribute(\PDO::ATTR_DRIVER_NAME); $oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - if ('mysql' === $sType && 'mysql' === $oPdo->getAttribute(\PDO::ATTR_DRIVER_NAME)) + + if ('mysql' === $sType && 'mysql' === $sPdoType) { $oPdo->exec('SET NAMES utf8 COLLATE utf8_general_ci'); // $oPdo->exec('SET NAMES utf8'); } +// else if ('sqlite' === $sType && 'sqlite' === $sPdoType && $this->bSqliteCollate) +// { +// if (\method_exists($oPdo, 'sqliteCreateCollation') && \MailSo\Base\Utils::FunctionExistsAndEnabled('mb_strtoupper')) +// { +// $oPdo->sqliteCreateCollation('SQLITE_NOCASE_UTF8', array($this, 'sqliteNoCaseCollationHelper')); +// $bCaseFunc = true; +// } +// } +// +// $this->oLogger->Write('PDO:'.$sPdoType.($bCaseFunc ? '/SQLITE_NOCASE_UTF8' : '')); } } catch (\Exception $oException) @@ -156,10 +187,11 @@ abstract class PdoAbstract * @param string $sSql * @param array $aParams * @param bool $bMultiplyParams = false + * @param bool $bLogParams = false * * @return \PDOStatement|null */ - protected function prepareAndExecute($sSql, $aParams = array(), $bMultiplyParams = false) + protected function prepareAndExecute($sSql, $aParams = array(), $bMultiplyParams = false, $bLogParams = false) { if ($this->bExplain && !$bMultiplyParams) { @@ -172,16 +204,27 @@ abstract class PdoAbstract $oStmt = $this->getPDO()->prepare($sSql); if ($oStmt) { + $aLogs = array(); $aRootParams = $bMultiplyParams ? $aParams : array($aParams); foreach ($aRootParams as $aSubParams) { foreach ($aSubParams as $sName => $aValue) { + if ($bLogParams) + { + $aLogs[$sName] = $aValue[0]; + } + $oStmt->bindValue($sName, $aValue[0], $aValue[1]); } $mResult = $oStmt->execute() && !$bMultiplyParams ? $oStmt : null; } + + if ($bLogParams && $aLogs) + { + $this->writeLog('Params: '.@\json_encode($aLogs, \defined('JSON_UNESCAPED_UNICODE') ? JSON_UNESCAPED_UNICODE : 0)); + } } return $mResult; diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Config/AbstractConfig.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Config/AbstractConfig.php index 6403e7940..43d589751 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Config/AbstractConfig.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Config/AbstractConfig.php @@ -9,6 +9,11 @@ abstract class AbstractConfig */ private $sFile; + /** + * @var string + */ + private $sAdditionalFile; + /** * @var array */ @@ -27,12 +32,19 @@ abstract class AbstractConfig /** * @param string $sFileName * @param string $sFileHeader = '' + * @param string $sAdditionalFileName = '' * * @return void */ - public function __construct($sFileName, $sFileHeader = '') + public function __construct($sFileName, $sFileHeader = '', $sAdditionalFileName = '') { - $this->sFile = \APP_PRIVATE_DATA.'configs/'.$sFileName; + $this->sFile = \APP_PRIVATE_DATA.'configs/'.\trim($sFileName); + + $sAdditionalFileName = \trim($sAdditionalFileName); + $this->sAdditionalFile = \APP_PRIVATE_DATA.'configs/'.$sAdditionalFileName; + $this->sAdditionalFile = 0 < \strlen($sAdditionalFileName) && + \file_exists($this->sAdditionalFile) ? $this->sAdditionalFile : ''; + $this->sFileHeader = $sFileHeader; $this->aData = $this->defaultValues(); @@ -109,7 +121,7 @@ abstract class AbstractConfig */ private function cacheKey() { - return 'config:'.\sha1($this->sFile).':'; + return 'config:'.\sha1($this->sFile).':'.\sha1($this->sAdditionalFile).':'; } /** @@ -120,12 +132,17 @@ abstract class AbstractConfig if ($this->bUseApcCache) { $iMTime = @\filemtime($this->sFile); - if (\is_int($iMTime) && 0 < $iMTime) + $iMTime = \is_int($iMTime) && 0 < $iMTime ? $iMTime : 0; + + $iATime = $this->sAdditionalFile ? @\filemtime($this->sAdditionalFile) : 0; + $iATime = \is_int($iATime) && 0 < $iATime ? $iATime : 0; + + if (0 < $iMTime) { $sKey = $this->cacheKey(); - $iTime = \apc_fetch($sKey.'time'); - if ($iTime && $iMTime === (int) $iTime) + $sTimeHash = \apc_fetch($sKey.'time'); + if ($sTimeHash && $sTimeHash === \md5($iMTime.'/'.$iATime)) { $aFetchData = \apc_fetch($sKey.'data'); if (\is_array($aFetchData)) @@ -148,11 +165,16 @@ abstract class AbstractConfig if ($this->bUseApcCache) { $iMTime = @\filemtime($this->sFile); - if (\is_int($iMTime) && 0 < $iMTime) + $iMTime = \is_int($iMTime) && 0 < $iMTime ? $iMTime : 0; + + $iATime = $this->sAdditionalFile ? @\filemtime($this->sAdditionalFile) : 0; + $iATime = \is_int($iATime) && 0 < $iATime ? $iATime : 0; + + if (0 < $iMTime) { $sKey = $this->cacheKey(); - \apc_store($sKey.'time', $iMTime); + \apc_store($sKey.'time', \md5($iMTime.'/'.$iATime)); \apc_store($sKey.'data', $this->aData); return true; @@ -193,7 +215,7 @@ abstract class AbstractConfig } $aData = \RainLoop\Utils::CustomParseIniFile($this->sFile, true); - if (\is_array($aData) && 0 < count($aData)) + if (\is_array($aData) && 0 < \count($aData)) { foreach ($aData as $sSectionKey => $aSectionValue) { @@ -206,6 +228,28 @@ abstract class AbstractConfig } } + unset($aData); + + if (\file_exists($this->sAdditionalFile) && \is_readable($this->sAdditionalFile)) + { + $aSubData = \RainLoop\Utils::CustomParseIniFile($this->sAdditionalFile, true); + if (\is_array($aSubData) && 0 < \count($aSubData)) + { + foreach ($aSubData as $sSectionKey => $aSectionValue) + { + if (\is_array($aSectionValue)) + { + foreach ($aSectionValue as $sParamKey => $mParamValue) + { + $this->Set($sSectionKey, $sParamKey, $mParamValue); + } + } + } + } + + unset($aSubData); + } + $this->storeDataToCache(); return true; diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php index 64eca8f7b..1282de2c9 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php @@ -11,7 +11,8 @@ class Application extends \RainLoop\Config\AbstractConfig { parent::__construct('application.ini', '; RainLoop Webmail configuration file -; Please don\'t add custom parameters here, those will be overwritten'); +; Please don\'t add custom parameters here, those will be overwritten', + defined('APP_ADDITIONAL_CONFIGURATION_NAME') ? APP_ADDITIONAL_CONFIGURATION_NAME : ''); } /** @@ -70,6 +71,7 @@ class Application extends \RainLoop\Config\AbstractConfig 'allow_languages_on_settings' => array(true, 'Allow language selection on settings screen'), 'allow_additional_accounts' => array(true, ''), + 'allow_additional_identities' => array(true, ''), 'messages_per_page' => array(20, ' Number of messages displayed on page by default'), @@ -88,8 +90,13 @@ class Application extends \RainLoop\Config\AbstractConfig 'login_desc' => array(''), 'login_css' => array(''), 'login_powered' => array(true), - 'user_logo' => array(''), + 'user_css' => array(''), + 'user_logo' => array(''), + 'user_logo_title' => array(''), + 'user_logo_message' => array(''), + 'user_iframe_message' => array(''), + 'welcome_page_url' => array(''), 'welcome_page_display' => array('none') ), @@ -132,8 +139,21 @@ class Application extends \RainLoop\Config\AbstractConfig ), 'capa' => array( + 'folders' => array(true), + 'composer' => array(true), + 'contacts' => array(true), + 'settings' => array(true), + 'quota' => array(true), + 'help' => array(true), + 'reload' => array(true), + 'search' => array(true), + 'search_adv' => array(true), 'filters' => array(true), - 'templates' => array(true) + 'x-templates' => array(false), + 'dangerous_actions' => array(true), + 'message_actions' => array(true), + 'messagelist_actions' => array(true), + 'attachments_actions' => array(true) ), 'login' => array( @@ -146,6 +166,8 @@ class Application extends \RainLoop\Config\AbstractConfig 'determine_user_language' => array(true, ''), 'determine_user_domain' => array(false, ''), + 'welcome_page' => array(false, ''), + 'forgot_password_link_url' => array('', ''), 'registration_link_url' => array('', ''), @@ -166,7 +188,7 @@ Values: 'defaults' => array( 'view_editor_type' => array('Html', 'Editor mode used by default (Plain, Html, HtmlForced or PlainForced)'), - 'view_layout' => array(1, 'layout: 0 - no preview, 1 - side preview, 3 - bottom preview'), + 'view_layout' => array(1, 'layout: 0 - no preview, 1 - side preview, 2 - bottom preview'), 'view_use_checkboxes' => array(true), 'autologout' => array(30), 'show_images' => array(false), @@ -186,6 +208,9 @@ Values: 'hide_passwords' => array(true, 'Required for development purposes only. Disabling this option is not recommended.'), + 'time_offset' => array(0), + 'session_filter' => array(''), + 'filename' => array('log-{date:Y-m-d}.txt', 'Log filename. For security reasons, some characters are removed from filename. @@ -216,7 +241,7 @@ Examples: 'auth_logging' => array(false, 'Enable auth logging in a separate file (for fail2ban)'), 'auth_logging_filename' => array('fail2ban/auth-{date:Y-m-d}.txt'), - 'auth_logging_format' => array('Auth failed: ip={request:ip} user={imap:login} host={imap:host} port={imap:port}') + 'auth_logging_format' => array('[{date:Y-m-d H:i:s}] Auth failed: ip={request:ip} user={imap:login} host={imap:host} port={imap:port}') ), 'debug' => array( @@ -226,6 +251,7 @@ Examples: 'social' => array( 'google_enable' => array(false, 'Google'), 'google_enable_auth' => array(false), + 'google_enable_auth_fast' => array(false), 'google_enable_drive' => array(false), 'google_enable_preview' => array(false), 'google_client_id' => array(''), @@ -278,11 +304,11 @@ Enables caching in the system'), 'allow_html_editor_source_button' => array(false), 'allow_html_editor_biti_buttons' => array(false), 'allow_ctrl_enter_on_compose' => array(false), + 'try_to_detect_hidden_images' => array(false), 'hide_dangerous_actions' => array(false), 'use_app_debug_js' => array(false), 'use_app_debug_css' => array(false), 'use_imap_sort' => array(true), - 'use_imap_esearch_esort' => array(true), 'use_imap_force_selection' => array(false), 'use_imap_list_subscribe' => array(true), 'use_imap_thread' => array(true), @@ -295,12 +321,19 @@ Enables caching in the system'), 'imap_message_list_fast_simple_search' => array(true), 'imap_message_list_count_limit_trigger' => array(0), 'imap_message_list_date_filter' => array(0), + 'imap_message_list_permanent_filter' => array(''), + 'imap_message_all_headers' => array(false), 'imap_large_thread_limit' => array(50), 'imap_folder_list_limit' => array(200), 'imap_show_login_alert' => array(true), 'smtp_show_server_errors' => array(false), 'sieve_allow_raw_script' => array(false), 'sieve_utf8_folder_name' => array(true), + 'mail_func_clear_headers' => array(true), + 'mail_func_additional_parameters' => array(false), + 'favicon_status' => array(true), + 'folders_spec_limit' => array(50), + 'owncloud_save_folder' => array('Attachments'), 'curl_proxy' => array(''), 'curl_proxy_auth' => array(''), 'in_iframe' => array(false), @@ -315,6 +348,9 @@ Enables caching in the system'), 'fast_cache_memcache_port' => array(11211), 'fast_cache_memcache_expire' => array(43200), 'use_local_proxy_for_external_images' => array(false), + 'cookie_path' => array('/'), + 'startup_url' => array(''), + 'emogrifier' => array(true), 'dev_email' => array(''), 'dev_password' => array('') ), diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Plugin.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Plugin.php index 294823fcb..ee7bb5caa 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Plugin.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Plugin.php @@ -25,7 +25,7 @@ class Plugin extends \RainLoop\Config\AbstractConfig */ private function convertConfigMap($aMap) { - if (0 < count($aMap)) + if (0 < \count($aMap)) { $aResultMap = array(); foreach ($aMap as /* @var $oProperty \RainLoop\Plugins\Property */ $oProperty) @@ -33,12 +33,12 @@ class Plugin extends \RainLoop\Config\AbstractConfig if ($oProperty) { $mValue = $oProperty->DefaultValue(); - $sValue = is_array($mValue) && isset($mValue[0]) ? $mValue[0] : $mValue; + $sValue = \is_array($mValue) && isset($mValue[0]) ? $mValue[0] : $mValue; $aResultMap[$oProperty->Name()] = array($sValue, ''); } } - if (0 < count($aResultMap)) + if (0 < \count($aResultMap)) { return array( 'plugin' => $aResultMap diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php index 2770881af..56912b5e2 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php @@ -16,6 +16,20 @@ class Capa const FILTERS = 'FILTERS'; const ATTACHMENT_THUMBNAILS = 'ATTACHMENT_THUMBNAILS'; const ADDITIONAL_ACCOUNTS = 'ADDITIONAL_ACCOUNTS'; + const IDENTITIES = 'IDENTITIES'; + const FOLDERS = 'FOLDERS'; + const COMPOSER = 'COMPOSER'; + const CONTACTS = 'CONTACTS'; + const RELOAD = 'RELOAD'; + const SEARCH = 'SEARCH'; + const SEARCH_ADV = 'SEARCH_ADV'; + const SETTINGS = 'SETTINGS'; + const QUOTA = 'QUOTA'; + const HELP = 'HELP'; const TEMPLATES = 'TEMPLATES'; + const MESSAGE_ACTIONS = 'MESSAGE_ACTIONS'; + const MESSAGELIST_ACTIONS = 'MESSAGELIST_ACTIONS'; + const ATTACHMENTS_ACTIONS = 'ATTACHMENTS_ACTIONS'; + const DANGEROUS_ACTIONS = 'DANGEROUS_ACTIONS'; const AUTOLOGOUT = 'AUTOLOGOUT'; } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php index 82c463685..31108e1f1 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php @@ -362,7 +362,27 @@ class Account extends \RainLoop\Account // for backward compatibility \RainLoop\Utils::GetShortToken(), // 7 $this->sProxyAuthUser, // 8 $this->sProxyAuthPassword, // 9 - 0 // 10 + 0 // 10 // timelife + )); + } + + /** + * @return string + */ + public function GetAuthTokenQ() + { + return \RainLoop\Utils::EncodeKeyValuesQ(array( + 'token', // 0 + $this->sEmail, // 1 + $this->sLogin, // 2 + $this->sPassword, // 3 + \RainLoop\Utils::Fingerprint(), // 4 + $this->sSignMeToken, // 5 + $this->sParentEmail, // 6 + \RainLoop\Utils::GetShortToken(), // 7 + $this->sProxyAuthUser, // 8 + $this->sProxyAuthPassword, // 9 + 0 // 10 // timelife )); } @@ -417,8 +437,18 @@ class Account extends \RainLoop\Account // for backward compatibility } else { - $oMailClient->Login($aImapCredentials['Login'], $aImapCredentials['Password'], '', - $aImapCredentials['UseAuthPlainIfSupported']); + $iGatLen = \strlen(APP_GOOGLE_ACCESS_TOKEN_PREFIX); + $sPassword = $aImapCredentials['Password']; + if (APP_GOOGLE_ACCESS_TOKEN_PREFIX === \substr($sPassword, 0, $iGatLen)) + { + $oMailClient->LoginWithXOauth2( + \base64_encode('user='.$aImapCredentials['Login']."\1".'auth=Bearer '.\substr($sPassword, $iGatLen)."\1\1")); + } + else + { + $oMailClient->Login($aImapCredentials['Login'], $aImapCredentials['Password'], '', + $aImapCredentials['UseAuthPlainIfSupported']); + } } $bLogin = true; @@ -475,7 +505,17 @@ class Account extends \RainLoop\Account // for backward compatibility if ($aSmtpCredentials['UseAuth'] && !$aSmtpCredentials['UsePhpMail'] && $oSmtpClient) { - $oSmtpClient->Login($aSmtpCredentials['Login'], $aSmtpCredentials['Password']); + $iGatLen = \strlen(APP_GOOGLE_ACCESS_TOKEN_PREFIX); + $sPassword = $aSmtpCredentials['Password']; + if (APP_GOOGLE_ACCESS_TOKEN_PREFIX === \substr($sPassword, 0, $iGatLen)) + { + $oSmtpClient->LoginWithXOauth2( + \base64_encode('user='.$aSmtpCredentials['Login']."\1".'auth=Bearer '.\substr($sPassword, $iGatLen)."\1\1")); + } + else + { + $oSmtpClient->Login($aSmtpCredentials['Login'], $aSmtpCredentials['Password']); + } $bLogin = true; } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Identity.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Identity.php index 19dd0c661..1923ce66e 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Identity.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Identity.php @@ -75,11 +75,13 @@ class Identity } /** + * @param bool $bFillOnEmpty = false + * * @return string */ - public function Id() + public function Id($bFillOnEmpty = false) { - return $this->sId; + return $bFillOnEmpty ? ('' === $this->sId ? '---' : $this->sId) : $this->sId; } /** @@ -192,4 +194,12 @@ class Identity { return !empty($this->sEmail); } + + /** + * @return bool + */ + public function IsAccountIdentities() + { + return '' === $this->Id(); + } } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/AbstractPlugin.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/AbstractPlugin.php index 67b147a12..5f4b8101d 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/AbstractPlugin.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/AbstractPlugin.php @@ -304,6 +304,22 @@ abstract class AbstractPlugin return $this; } + /** + * @param string $sFile + * @param bool $bAdminScope = false + * + * @return self + */ + protected function replaceTemplate($sFile, $bAdminScope = false) + { + if ($this->oPluginManager) + { + $this->oPluginManager->AddTemplate($this->sPath.'/'.$sFile, $bAdminScope); + } + + return $this; + } + /** * @param string $sActionName * @param string $sFunctionName diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php index a4ecfb7ca..00d751723 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php @@ -230,7 +230,7 @@ class Manager public function HaveJs($bAdminScope = false) { $bResult = false; - + if ($this->bIsEnabled) { $bResult = $bAdminScope ? 0 < \count($this->aAdminJs) : 0 < \count($this->aJs); @@ -274,27 +274,24 @@ class Manager } /** + * @param array $aList * @param bool $bAdminScope = false * @return string */ - public function CompileTemplate($bAdminScope = false) + public function CompileTemplate(&$aList, $bAdminScope = false) { - $sResult = ''; if ($this->bIsEnabled) { $aTemplates = $bAdminScope ? $this->aAdminTemplates : $this->aTemplates; foreach ($aTemplates as $sFile) { - if (file_exists($sFile)) + if (\file_exists($sFile)) { - $sTemplateName = substr(basename($sFile), 0, -5); - $sResult .= ''; + $sTemplateName = \substr(\basename($sFile), 0, -5); + $aList[$sTemplateName] = $sFile; } } } - - return $sResult; } /** diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php index 8ea5a138e..dfe914de1 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php @@ -318,7 +318,7 @@ class AddressBook extends \RainLoop\Providers\AbstractProvider { $iCount = 0; - if (\class_exists('Sabre\DAV\Client') && $this->IsActive() && \is_string($sVcfData)) + if (\class_exists('SabreForRainLoop\DAV\Client') && $this->IsActive() && \is_string($sVcfData)) { $sVcfData = \trim($sVcfData); if ("\xef\xbb\xbf" === \substr($sVcfData, 0, 3)) @@ -329,7 +329,7 @@ class AddressBook extends \RainLoop\Providers\AbstractProvider $oVCardSplitter = null; try { - $oVCardSplitter = new \Sabre\VObject\Splitter\VCard($sVcfData); + $oVCardSplitter = new \SabreForRainLoop\VObject\Splitter\VCard($sVcfData); } catch (\Exception $oExc) { @@ -344,13 +344,13 @@ class AddressBook extends \RainLoop\Providers\AbstractProvider while ($oVCard = $oVCardSplitter->getNext()) { - if ($oVCard instanceof \Sabre\VObject\Component\VCard) + if ($oVCard instanceof \SabreForRainLoop\VObject\Component\VCard) { \MailSo\Base\Utils::ResetTimeLimit(); if (empty($oVCard->UID)) { - $oVCard->UID = \Sabre\DAV\UUIDUtil::getUUID(); + $oVCard->UID = \SabreForRainLoop\DAV\UUIDUtil::getUUID(); } $oContact->PopulateByVCard($oVCard->UID, $oVCard->serialize()); diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php index 7fd425139..41085ff1b 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php @@ -66,8 +66,9 @@ class Contact $this->Etag = ''; } - public function UpdateDependentValues() + public function PopulateDisplayAndFullNameValue($bForceFullNameReplace = false) { + $sFullName = ''; $sLastName = ''; $sFirstName = ''; $sEmail = ''; @@ -100,8 +101,12 @@ class Contact { $sFirstName = $oProperty->Value; } - else if (\in_array($oProperty->Type, array( - PropertyType::FULLNAME, PropertyType::PHONE + else if ('' === $sFullName && PropertyType::FULLNAME === $oProperty->Type) + { + $sFullName = $oProperty->Value; + } + else if ('' === $sOther && \in_array($oProperty->Type, array( + PropertyType::PHONE ))) { $sOther = $oProperty->Value; @@ -110,25 +115,26 @@ class Contact } } - if (empty($this->IdContactStr)) - { - $this->RegenerateContactStr(); - } + $sDisplay = $bForceFullNameReplace ? '' : \trim($sFullName); - $sDisplay = ''; - if (0 < \strlen($sLastName) || 0 < \strlen($sFirstName)) + if ('' === $sDisplay && (0 < \strlen($sLastName) || 0 < \strlen($sFirstName))) { $sDisplay = \trim($sFirstName.' '.$sLastName); } - if ('' === $sDisplay && 0 < \strlen($sEmail)) + if ('' === $sDisplay) + { + $sDisplay = \trim($sFullName); + } + + if ('' === $sDisplay) { $sDisplay = \trim($sEmail); } if ('' === $sDisplay) { - $sDisplay = $sOther; + $sDisplay = \trim($sOther); } $this->Display = \trim($sDisplay); @@ -145,13 +151,23 @@ class Contact } } + public function UpdateDependentValues() + { + if (empty($this->IdContactStr)) + { + $this->RegenerateContactStr(); + } + + $this->PopulateDisplayAndFullNameValue(); + } + /** * @return array */ public function RegenerateContactStr() { - $this->IdContactStr = \class_exists('Sabre\DAV\Client') ? - \Sabre\DAV\UUIDUtil::getUUID() : \MailSo\Base\Utils::Md5Rand(); + $this->IdContactStr = \class_exists('SabreForRainLoop\DAV\Client') ? + \SabreForRainLoop\DAV\UUIDUtil::getUUID() : \MailSo\Base\Utils::Md5Rand(); } /** @@ -186,7 +202,7 @@ class Contact { $this->UpdateDependentValues(); - if (!\class_exists('Sabre\DAV\Client')) + if (!\class_exists('SabreForRainLoop\DAV\Client')) { return ''; } @@ -201,7 +217,7 @@ class Contact { try { - $oVCard = \Sabre\VObject\Reader::read($sPreVCard); + $oVCard = \SabreForRainLoop\VObject\Reader::read($sPreVCard); } catch (\Exception $oExc) { @@ -213,9 +229,14 @@ class Contact } } +// if ($oLogger) +// { +// $oLogger->WriteDump($sPreVCard); +// } + if (!$oVCard) { - $oVCard = new \Sabre\VObject\Component\VCard(); + $oVCard = new \SabreForRainLoop\VObject\Component\VCard(); } $oVCard->VERSION = '3.0'; @@ -223,7 +244,7 @@ class Contact unset($oVCard->FN, $oVCard->EMAIL, $oVCard->TEL, $oVCard->URL, $oVCard->NICKNAME); - $sFirstName = $sLastName = $sMiddleName = $sSuffix = $sPrefix = ''; + $sUid = $sFirstName = $sLastName = $sMiddleName = $sSuffix = $sPrefix = ''; foreach ($this->Properties as /* @var $oProperty \RainLoop\Providers\AddressBook\Classes\Property */ &$oProperty) { if ($oProperty) @@ -240,6 +261,9 @@ class Contact case PropertyType::NOTE: $oVCard->NOTE = $oProperty->Value; break; + case PropertyType::UID: + $sUid = $oProperty->Value; + break; case PropertyType::FIRST_NAME: $sFirstName = $oProperty->Value; break; @@ -278,7 +302,7 @@ class Contact } } - $oVCard->UID = $this->IdContactStr; + $oVCard->UID = empty($sUid) ? $this->IdContactStr : $sUid; $oVCard->N = array($sLastName, $sFirstName, $sMiddleName, $sPrefix, $sSuffix); $oVCard->REV = \gmdate('Ymd', $this->Changed).'T'.\gmdate('His', $this->Changed).'Z'; @@ -505,7 +529,7 @@ class Contact $this->Properties = array(); - if (!\class_exists('Sabre\DAV\Client')) + if (!\class_exists('SabreForRainLoop\DAV\Client')) { return false; } @@ -515,9 +539,11 @@ class Contact $this->Etag = $sEtag; } + $this->IdContactStr = $sUid; + try { - $oVCard = \Sabre\VObject\Reader::read($sVCard); + $oVCard = \SabreForRainLoop\VObject\Reader::read($sVCard); } catch (\Exception $oExc) { @@ -526,18 +552,24 @@ class Contact $oLogger->WriteException($oExc); $oLogger->WriteDump($sVCard); } - - $this->IdContactStr = $sUid; } +// if ($oLogger) +// { +// $oLogger->WriteDump($sVCard); +// } + + $bOwnCloud = false; $aProperties = array(); + if ($oVCard) { + $bOwnCloud = empty($oVCard->PRODID) ? false : + false !== \strpos(\strtolower($oVCard->PRODID), 'owncloud'); + $bOldVersion = empty($oVCard->VERSION) ? false : \in_array((string) $oVCard->VERSION, array('2.1', '2.0', '1.0')); - $this->IdContactStr = $oVCard->UID ? (string) $oVCard->UID : \Sabre\DAV\UUIDUtil::getUUID(); - if (isset($oVCard->FN) && '' !== \trim($oVCard->FN)) { $sValue = $this->getPropertyValueHelper($oVCard->FN, $bOldVersion); @@ -612,6 +644,14 @@ class Contact $this->addArrayPropertyHelper($aProperties, $oVCard->TEL, PropertyType::PHONE); } + $sUidValue = $oVCard->UID ? (string) $oVCard->UID : \SabreForRainLoop\DAV\UUIDUtil::getUUID(); + $aProperties[] = new Property(PropertyType::UID, $sUidValue); + + if (empty($this->IdContactStr)) + { + $this->IdContactStr = $sUidValue; + } + $this->Properties = $aProperties; } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Property.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Property.php index a301ffe2f..78db4e428 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Property.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Property.php @@ -10,7 +10,7 @@ class Property * @var int */ public $IdProperty; - + /** * @var int */ @@ -26,6 +26,11 @@ class Property */ public $Value; + /** + * @var string + */ + public $ValueLower; + /** * @var string */ @@ -49,16 +54,26 @@ class Property public function Clear() { $this->IdProperty = 0; - + $this->Type = PropertyType::UNKNOWN; $this->TypeStr = ''; $this->Value = ''; + $this->ValueLower = ''; $this->ValueCustom = ''; $this->Frec = 0; } + /** + * @return bool + */ + public function IsName() + { + return \in_array($this->Type, array(PropertyType::FULLNAME, PropertyType::FIRST_NAME, + PropertyType::LAST_NAME, PropertyType::MIDDLE_NAME, PropertyType::NICK_NAME)); + } + /** * @return bool */ @@ -66,7 +81,7 @@ class Property { return PropertyType::EMAIl === $this->Type; } - + /** * @return bool */ @@ -83,6 +98,14 @@ class Property return PropertyType::WEB_PAGE === $this->Type; } + /** + * @return bool + */ + public function IsValueForLower() + { + return $this->IsEmail() || $this->IsName() || $this->IsWeb(); + } + /** * @return bool */ @@ -111,7 +134,8 @@ class Property $this->Value = \trim($this->Value); $this->ValueCustom = \trim($this->ValueCustom); $this->TypeStr = \trim($this->TypeStr); - + $this->ValueLower = ''; + if (0 < \strlen($this->Value)) { // lower @@ -120,13 +144,25 @@ class Property $this->Value = \MailSo\Base\Utils::StrToLowerIfAscii($this->Value); } - // phones clear value for searching + if ($this->IsName()) + { + $this->Value = \MailSo\Base\Utils::StripSpaces($this->Value); + } + + // lower value for searching + if ($this->IsValueForLower() && \MailSo\Base\Utils::FunctionExistsAndEnabled('mb_strtolower')) + { + $this->ValueLower = (string) @\mb_strtolower($this->Value, 'UTF-8'); + } + + // phone value for searching if ($this->IsPhone()) { - $sPhone = $this->Value; + $sPhone = \trim($this->Value); $sPhone = \preg_replace('/^[+]+/', '', $sPhone); $sPhone = \preg_replace('/[^\d]/', '', $sPhone); - $this->ValueCustom = $sPhone; + + $this->ValueCustom = \trim($sPhone); } } } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Enumerations/PropertyType.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Enumerations/PropertyType.php index 4068e4abc..5b1bdae94 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Enumerations/PropertyType.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Enumerations/PropertyType.php @@ -6,8 +6,9 @@ class PropertyType { const UNKNOWN = 0; + const UID = 9; const FULLNAME = 10; - + const FIRST_NAME = 15; const LAST_NAME = 16; const MIDDLE_NAME = 17; @@ -21,7 +22,7 @@ class PropertyType // const MOBILE = 32; // const FAX = 33; const WEB_PAGE = 32; - + const BIRTHDAY = 40; const FACEBOOK = 90; diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php index b2100bc05..7ef050381 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php @@ -117,11 +117,14 @@ class PdoAddressBook try { $this->oLogger->Write('PROPFIND '.$sPath, \MailSo\Log\Enumerations\Type::INFO, 'DAV'); + $aResponse = $oClient->propFind($sPath, array( '{DAV:}getlastmodified', + '{DAV:}resourcetype', '{DAV:}getetag' ), 1); +// $this->oLogger->WriteDump($aResponse); } catch (\Exception $oException) { @@ -137,10 +140,11 @@ class PdoAddressBook if (!empty($sKey) && is_array($aItem)) { $aItem = \array_change_key_case($aItem, \CASE_LOWER); - if (isset($aItem['{dav:}getetag'], $aItem['{dav:}getlastmodified'])) + if (isset($aItem['{dav:}getetag'])) { $aMatch = array(); - if (\preg_match('/\/([^\/?]+)$/', $sKey, $aMatch) && !empty($aMatch[1])) + if (\preg_match('/\/([^\/?]+)$/', $sKey, $aMatch) && !empty($aMatch[1]) && + (!$aItem['{dav:}resourcetype'] || !$aItem['{dav:}resourcetype']->is('{DAV:}collection'))) { $sVcfFileName = \urldecode(\urldecode($aMatch[1])); $sKeyID = \preg_replace('/\.vcf$/i', '', $sVcfFileName); @@ -150,10 +154,23 @@ class PdoAddressBook 'uid' => $sKeyID, 'vcf' => $sVcfFileName, 'etag' => \trim(\trim($aItem['{dav:}getetag']), '"\''), - 'lastmodified' => $aItem['{dav:}getlastmodified'], - 'changed' => \MailSo\Base\DateTimeHelper::ParseRFC2822DateString($aItem['{dav:}getlastmodified']) + 'lastmodified' => '', + 'changed' => 0 ); + if (isset($aItem['{dav:}getlastmodified'])) + { + $mResult[$sKeyID]['lastmodified'] = $aItem['{dav:}getlastmodified']; + $mResult[$sKeyID]['changed'] = \MailSo\Base\DateTimeHelper::ParseRFC2822DateString( + $aItem['{dav:}getlastmodified']); + } + else + { + $mResult[$sKeyID]['changed'] = \MailSo\Base\DateTimeHelper::TryToParseSpecEtagFormat($mResult[$sKeyID]['etag']); + $mResult[$sKeyID]['lastmodified'] = 0 < $mResult[$sKeyID]['changed'] ? + \gmdate('c', $mResult[$sKeyID]['changed']) : ''; + } + $mResult[$sKeyID]['changed_'] = \gmdate('c', $mResult[$sKeyID]['changed']); } } @@ -168,24 +185,32 @@ class PdoAddressBook { \MailSo\Base\Utils::ResetTimeLimit(); - $this->oLogger->Write($sCmd.' '.$sUrl.('PUT' === $sCmd && null !== $mData ? ' ('.\strlen($mData).')' : ''), + $this->oLogger->Write($sCmd.' '.$sUrl.(('PUT' === $sCmd || 'POST' === $sCmd) && null !== $mData ? ' ('.\strlen($mData).')' : ''), \MailSo\Log\Enumerations\Type::INFO, 'DAV'); - if ('PUT' === $sCmd) - { - $this->oLogger->Write($mData, \MailSo\Log\Enumerations\Type::INFO, 'DAV'); - } +// if ('PUT' === $sCmd || 'POST' === $sCmd) +// { +// $this->oLogger->Write($mData, \MailSo\Log\Enumerations\Type::INFO, 'DAV'); +// } $oResponse = false; try { - $oResponse = 'PUT' === $sCmd && null !== $mData ? - $oClient->request($sCmd, $sUrl, $mData) : $oClient->request($sCmd, $sUrl); - - if ('GET' === $sCmd && false) + if (('PUT' === $sCmd || 'POST' === $sCmd) && null !== $mData) { - $this->oLogger->WriteDump($oResponse, \MailSo\Log\Enumerations\Type::INFO, 'DAV'); + $oResponse = $oClient->request($sCmd, $sUrl, $mData, array( + 'Content-Type' => 'text/vcard; charset=utf-8' + )); } + else + { + $oResponse = $oClient->request($sCmd, $sUrl); + } + +// if ('GET' === $sCmd) +// { +// $this->oLogger->WriteDump($oResponse, \MailSo\Log\Enumerations\Type::INFO, 'DAV'); +// } } catch (\Exception $oException) { @@ -196,24 +221,304 @@ class PdoAddressBook } /** - * @param string $sEmail - * @param string $sUrl + * @param \SabreForRainLoop\DAV\Client $oClient + * @param string $sPath + * + * @return bool + */ + private function detectionPropFind($oClient, $sPath) + { + $aResponse = null; + + try + { + $this->oLogger->Write('PROPFIND '.$sPath, \MailSo\Log\Enumerations\Type::INFO, 'DAV'); + + $aResponse = $oClient->propFind($sPath, array( + '{DAV:}current-user-principal', + '{DAV:}resourcetype', + '{DAV:}displayname', + '{urn:ietf:params:xml:ns:carddav}addressbook-home-set' + ), 1); + +// $this->oLogger->WriteDump($aResponse); + } + catch (\Exception $oException) + { + $this->oLogger->WriteException($oException); + } + + return $aResponse; + } + + /** + * @param \SabreForRainLoop\DAV\Client $oClient * @param string $sUser * @param string $sPassword * @param string $sProxy = '' * + * @return array + */ + private function getContactsPaths(&$oClient, $sUser, $sPassword, $sProxy = '') + { + $aContactsPaths = array(); + + $sCurrentUserPrincipal = ''; + $sAddressbookHomeSet = ''; + +// [{DAV:}current-user-principal] => /cloud/remote.php/carddav/principals/admin/ +// [{urn:ietf:params:xml:ns:carddav}addressbook-home-set] => /cloud/remote.php/carddav/addressbooks/admin/ + + if (!$oClient) + { + return $aContactsPaths; + } + + $aResponse = $this->detectionPropFind($oClient, '/.well-known/carddav'); + + $sNextPath = ''; + $sFirstNextPath = ''; + if (\is_array($aResponse)) + { + foreach ($aResponse as $sKey => $aItem) + { + if (empty($sAddressbookHomeSet) && !empty($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']) && + false === \strpos($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set'], '/calendar-proxy')) + { + $sAddressbookHomeSet = $aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']; + continue; + } + + if (empty($sCurrentUserPrincipal) && !empty($aItem['{DAV:}current-user-principal'])) + { + $sCurrentUserPrincipal = $aItem['{DAV:}current-user-principal']; + continue; + } + + if (!empty($sKey)) + { + if (empty($sFirstNextPath)) + { + $sFirstNextPath = $sKey; + } + + if (empty($sNextPath)) + { + $oResourceType = isset($aItem['{DAV:}resourcetype']) ? $aItem['{DAV:}resourcetype'] : null; + /* @var $oResourceType \SabreForRainLoop\DAV\Property\ResourceType */ + if ($oResourceType && $oResourceType->is('{DAV:}collection')) + { + $sNextPath = $sKey; + continue; + } + } + } + } + + if (empty($sNextPath) && empty($sCurrentUserPrincipal) && empty($sAddressbookHomeSet) && !empty($sFirstNextPath)) + { + $sNextPath = $sFirstNextPath; + } + } + + if (empty($sCurrentUserPrincipal) && empty($sAddressbookHomeSet)) + { + if (empty($sNextPath)) + { + return $aContactsPaths; + } + else + { + if (\preg_match('/^http[s]?:\/\//i', $sNextPath)) + { + $oClient = $this->getDavClientFromUrl($sNextPath, $sUser, $sPassword, $sProxy); + if ($oClient) + { + $sNextPath = $oClient->__UrlPath__; + } + else + { + return $aContactsPaths; + } + } + + $aResponse = $this->detectionPropFind($oClient, $sNextPath); + if (\is_array($aResponse)) + { + foreach ($aResponse as $sKey => $aItem) + { + if (empty($sAddressbookHomeSet) && !empty($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']) && + false === \strpos($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set'], '/calendar-proxy')) + { + $sAddressbookHomeSet = $aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']; + continue; + } + + if (empty($sCurrentUserPrincipal) && !empty($aItem['{DAV:}current-user-principal'])) + { + $sCurrentUserPrincipal = $aItem['{DAV:}current-user-principal']; + continue; + } + } + } + } + } + + if (empty($sAddressbookHomeSet)) + { + if (empty($sCurrentUserPrincipal)) + { + return $aContactsPaths; + } + else + { + if (\preg_match('/^http[s]?:\/\//i', $sCurrentUserPrincipal)) + { + $oClient = $this->getDavClientFromUrl($sCurrentUserPrincipal, $sUser, $sPassword, $sProxy); + if ($oClient) + { + $sCurrentUserPrincipal = $oClient->__UrlPath__; + } + else + { + return $aContactsPaths; + } + } + + $aResponse = $this->detectionPropFind($oClient, $sCurrentUserPrincipal); + if (\is_array($aResponse)) + { + foreach ($aResponse as $sKey => $aItem) + { + if (empty($sAddressbookHomeSet) && !empty($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']) && + false === \strpos($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set'], '/calendar-proxy')) + { + $sAddressbookHomeSet = $aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']; + continue; + } + } + } + } + } + + if (empty($sAddressbookHomeSet)) + { + return $aContactsPaths; + } + else + { + if (\preg_match('/^http[s]?:\/\//i', $sAddressbookHomeSet)) + { + $oClient = $this->getDavClientFromUrl($sAddressbookHomeSet, $sUser, $sPassword, $sProxy); + if ($oClient) + { + $sAddressbookHomeSet = $oClient->__UrlPath__; + } + else + { + return $aContactsPaths; + } + } + + $aResponse = $this->detectionPropFind($oClient, $sAddressbookHomeSet); + if (\is_array($aResponse)) + { + foreach ($aResponse as $sKey => $aItem) + { + if (!empty($sKey) && $aItem && isset($aItem['{DAV:}resourcetype'])) + { + $oResourceType = $aItem['{DAV:}resourcetype']; + /* @var $oResourceType \SabreForRainLoop\DAV\Property\ResourceType */ + + if ($oResourceType && $oResourceType->is('{DAV:}collection')) + { + if ($oResourceType->is('{urn:ietf:params:xml:ns:carddav}addressbook')) + { + $aContactsPaths[$sKey] = isset($aItem['{DAV:}displayname']) ? \trim($aItem['{DAV:}displayname']) : ''; + } + } + } + } + } + } + + return $aContactsPaths; + } + + /** + * @param \SabreForRainLoop\DAV\Client $oClient + * @param string $sPath + * * @return bool */ - public function Sync($sEmail, $sUrl, $sUser, $sPassword, $sProxy = '') + private function checkContactsPath(&$oClient, $sPath) { - $this->SyncDatabase(); - - $iUserID = $this->getUserId($sEmail); - if (0 >= $iUserID) + if (!$oClient) { return false; } + $this->oLogger->Write('PROPFIND '.$sPath, \MailSo\Log\Enumerations\Type::INFO, 'DAV'); + + $aResponse = null; + try + { + $aResponse = $oClient->propFind($sPath, array( + '{DAV:}resourcetype' + ), 1); + +// $this->oLogger->WriteDump($aResponse); + } + catch (\Exception $oException) + { + $this->oLogger->WriteException($oException); + } + + $bGood = false; + if (\is_array($aResponse)) + { + foreach ($aResponse as $sKey => $aItem) + { + if (!empty($sKey) && isset($aItem['{DAV:}resourcetype'])) + { + $oResourceType = $aItem['{DAV:}resourcetype']; + /* @var $oResourceType \SabreForRainLoop\DAV\Property\ResourceType */ + + if ($oResourceType && $oResourceType->is('{DAV:}collection') && + $oResourceType->is('{urn:ietf:params:xml:ns:carddav}addressbook')) + { + $bGood = true; + } + } + } + } + + if ($bGood) + { + $oClient->__UrlPath__ = $sPath; + } + + return $bGood; + } + + public function getDavClientFromUrl($sUrl, $sUser, $sPassword, $sProxy = '') + { + if (!\preg_match('/^http[s]?:\/\//i', $sUrl)) + { + $sUrl = \preg_replace('/^fruux\.com/i', 'dav.fruux.com', $sUrl); + $sUrl = \preg_replace('/^icloud\.com/i', 'contacts.icloud.com', $sUrl); + $sUrl = \preg_replace('/^gmail\.com/i', 'google.com', $sUrl); + + if (\preg_match('/^(google\.|dav\.fruux\.com|contacts\.icloud\.com)/i', $sUrl)) + { + $sUrl = 'https://'.$sUrl; + } + else + { + $sUrl = 'http://'.$sUrl; + } + } + $aUrl = \parse_url($sUrl); if (!\is_array($aUrl)) { @@ -238,17 +543,146 @@ class PdoAddressBook $aSettings['proxy'] = $sProxy; } - $sPath = $aUrl['path']; + $oClient = new \SabreForRainLoop\DAV\Client($aSettings); + $oClient->setVerifyPeer(false); - if (!\class_exists('Sabre\DAV\Client')) + $oClient->__UrlPath__ = $aUrl['path']; + + $this->oLogger->Write('DavClient: User: '.$aSettings['userName'].', Url: '.$sUrl, \MailSo\Log\Enumerations\Type::INFO, 'DAV'); + + return $oClient; + } + + /** + * @param string $sEmail + * @param string $sUrl + * @param string $sUser + * @param string $sPassword + * @param string $sProxy = '' + * + * @return bool + */ + public function getDavClient($sUrl, $sUser, $sPassword, $sProxy = '') + { + if (!\class_exists('SabreForRainLoop\DAV\Client')) { return false; } - $oClient = new \Sabre\DAV\Client($aSettings); - $oClient->setVerifyPeer(false); + $aMatch = array(); + $sUserAddressBookNameName = ''; - $this->oLogger->Write('User: '.$aSettings['userName'].', Url: '.$sUrl, \MailSo\Log\Enumerations\Type::INFO, 'DAV'); + if (\preg_match('/\|(.+)$/', $sUrl, $aMatch) && !empty($aMatch[1])) + { + $sUserAddressBookNameName = \trim($aMatch[1]); + $sUserAddressBookNameName = \MailSo\Base\Utils::StrToLowerIfAscii($sUserAddressBookNameName); + + $sUrl = \preg_replace('/\|(.+)$/', '', $sUrl); + } + + $oClient = $this->getDavClientFromUrl($sUrl, $sUser, $sPassword, $sProxy); + if (!$oClient) + { + return false; + } + + $bGood = false; + $sPath = $oClient->__UrlPath__; + + $bGood = false; + if ('' === $sPath || '/' === $sPath || !$this->checkContactsPath($oClient, $sPath)) + { + $sNewPath = ''; + + $aPaths = $this->getContactsPaths($oClient, $sUser, $sPassword, $sProxy); + $this->oLogger->WriteDump($aPaths); + + if (\is_array($aPaths)) + { + if (1 < \count($aPaths)) + { + if ('' !== $sUserAddressBookNameName) + { + foreach ($aPaths as $sKey => $sValue) + { + $sValue = \MailSo\Base\Utils::StrToLowerIfAscii(\trim($sValue)); + if ($sValue === $sUserAddressBookNameName) + { + $sNewPath = $sKey; + break; + } + } + } + + if (empty($sNewPath)) + { + foreach ($aPaths as $sKey => $sValue) + { + $sValue = \MailSo\Base\Utils::StrToLowerIfAscii($sValue); + + if (\in_array($sValue, array('contacts', 'default', 'addressbook', 'address book'))) + { + $sNewPath = $sKey; + break; + } + } + } + } + + if (empty($sNewPath)) + { + foreach ($aPaths as $sKey => $sValue) + { + $sNewPath = $sKey; + break; + } + } + } + + + $sPath = $sNewPath; + + $bGood = $this->checkContactsPath($oClient, $sPath); + } + else + { + $bGood = true; + } + + if (!$bGood) + { + $oClient = false; + } + + return $oClient; + } + + /** + * @param string $sEmail + * @param string $sUrl + * @param string $sUser + * @param string $sPassword + * @param string $sProxy = '' + * + * @return bool + */ + public function Sync($sEmail, $sUrl, $sUser, $sPassword, $sProxy = '') + { + $this->SyncDatabase(); + + $iUserID = $this->getUserId($sEmail); + if (0 >= $iUserID) + { + return false; + } + + $oClient = $this->getDavClient($sUrl, $sUser, $sPassword, $sProxy); + if (!$oClient) + { + return false; + } + + $sPath = $oClient->__UrlPath__; $aRemoteSyncData = $this->prepearRemoteSyncData($oClient, $sPath); if (false === $aRemoteSyncData) @@ -258,8 +692,8 @@ class PdoAddressBook $aDatabaseSyncData = $this->prepearDatabaseSyncData($iUserID); -// $this->oLogger->WriteDump($aDatabaseSyncData); // $this->oLogger->WriteDump($aRemoteSyncData); +// $this->oLogger->WriteDump($aDatabaseSyncData); //+++del (from carddav) foreach ($aDatabaseSyncData as $sKey => $aData) @@ -315,10 +749,13 @@ class PdoAddressBook { $sExsistensBody = \trim($oResponse['body']); } + +// $this->oLogger->WriteDump($sExsistensBody); } $oResponse = $this->davClientRequest($oClient, 'PUT', - $sPath.$oContact->CardDavNameUri(), $oContact->ToVCard($sExsistensBody, $this->oLogger)."\r\n\r\n"); + $sPath.(0 < \strlen($mExsistenRemoteID) ? $mExsistenRemoteID : $oContact->CardDavNameUri()), + $oContact->ToVCard($sExsistensBody, $this->oLogger)."\r\n\r\n"); if ($oResponse && isset($oResponse['headers'], $oResponse['headers']['etag'])) { @@ -521,6 +958,7 @@ class PdoAddressBook ':prop_type' => array($oProp->Type, \PDO::PARAM_INT), ':prop_type_str' => array($oProp->TypeStr, \PDO::PARAM_STR), ':prop_value' => array($oProp->Value, \PDO::PARAM_STR), + ':prop_value_lower' => array($oProp->ValueLower, \PDO::PARAM_STR), ':prop_value_custom' => array($oProp->ValueCustom, \PDO::PARAM_STR), ':prop_frec' => array($iFreq, \PDO::PARAM_INT), ); @@ -529,9 +967,9 @@ class PdoAddressBook if (0 < \count($aParams)) { $sSql = 'INSERT INTO rainloop_ab_properties '. - '( id_contact, id_user, prop_type, prop_type_str, prop_value, prop_value_custom, prop_frec)'. + '( id_contact, id_user, prop_type, prop_type_str, prop_value, prop_value_lower, prop_value_custom, prop_frec)'. ' VALUES '. - '(:id_contact, :id_user, :prop_type, :prop_type_str, :prop_value, :prop_value_custom, :prop_frec)'; + '(:id_contact, :id_user, :prop_type, :prop_type_str, :prop_value, :prop_value_lower, :prop_value_custom, :prop_frec)'; $this->prepareAndExecute($sSql, $aParams, true); } @@ -636,6 +1074,7 @@ class PdoAddressBook if (0 < \strlen($sSearch)) { $sCustomSearch = $this->specialConvertSearchValueCustomPhone($sSearch); + $sLowerSearch = $this->specialConvertSearchValueLower($sSearch, '='); $sSearchTypes = \implode(',', array( PropertyType::EMAIl, PropertyType::FIRST_NAME, PropertyType::LAST_NAME, PropertyType::NICK_NAME, @@ -643,8 +1082,10 @@ class PdoAddressBook )); $sSql = 'SELECT id_user, id_prop, id_contact FROM rainloop_ab_properties '. - 'WHERE (id_user = :id_user) AND prop_type IN ('.$sSearchTypes.') AND (prop_value LIKE :search ESCAPE \'=\''. - (0 < \strlen($sCustomSearch) ? ' OR (prop_type = '.PropertyType::PHONE.' AND prop_value_custom <> \'\' AND prop_value_custom LIKE :search_custom_phone)' : ''). + 'WHERE (id_user = :id_user) AND prop_type IN ('.$sSearchTypes.') AND ('. + 'prop_value LIKE :search ESCAPE \'=\''. +(0 < \strlen($sLowerSearch) ? ' OR (prop_value_lower <> \'\' AND prop_value_lower LIKE :search_lower ESCAPE \'=\')' : ''). +(0 < \strlen($sCustomSearch) ? ' OR (prop_type = '.PropertyType::PHONE.' AND prop_value_custom <> \'\' AND prop_value_custom LIKE :search_custom_phone)' : ''). ') GROUP BY id_contact, id_prop'; $aParams = array( @@ -652,12 +1093,17 @@ class PdoAddressBook ':search' => array($this->specialConvertSearchValue($sSearch, '='), \PDO::PARAM_STR) ); + if (0 < \strlen($sLowerSearch)) + { + $aParams[':search_lower'] = array($sLowerSearch, \PDO::PARAM_STR); + } + if (0 < \strlen($sCustomSearch)) { $aParams[':search_custom_phone'] = array($sCustomSearch, \PDO::PARAM_STR); } - $oStmt = $this->prepareAndExecute($sSql, $aParams); + $oStmt = $this->prepareAndExecute($sSql, $aParams, false, true); if ($oStmt) { $aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC); @@ -775,6 +1221,7 @@ class PdoAddressBook $oProperty->Type = (int) $aItem['prop_type']; $oProperty->TypeStr = isset($aItem['prop_type_str']) ? (string) $aItem['prop_type_str'] : ''; $oProperty->Value = (string) $aItem['prop_value']; + $oProperty->ValueLower = isset($aItem['prop_value_lower']) ? (string) $aItem['prop_value_lower'] : ''; $oProperty->ValueCustom = isset($aItem['prop_value_custom']) ? (string) $aItem['prop_value_custom'] : ''; $oProperty->Frec = isset($aItem['prop_frec']) ? (int) $aItem['prop_frec'] : 0; @@ -884,6 +1331,7 @@ class PdoAddressBook $oProperty->Type = (int) $aItem['prop_type']; $oProperty->TypeStr = isset($aItem['prop_type_str']) ? (string) $aItem['prop_type_str'] : ''; $oProperty->Value = (string) $aItem['prop_value']; + $oProperty->ValueLower = isset($aItem['prop_value_lower']) ? (string) $aItem['prop_value_lower'] : ''; $oProperty->ValueCustom = isset($aItem['prop_value_custom']) ? (string) $aItem['prop_value_custom'] : ''; $oProperty->Frec = isset($aItem['prop_frec']) ? (int) $aItem['prop_frec'] : 0; @@ -928,8 +1376,14 @@ class PdoAddressBook PropertyType::EMAIl, PropertyType::FIRST_NAME, PropertyType::LAST_NAME, PropertyType::NICK_NAME )); + $sLowerSearch = $this->specialConvertSearchValueLower($sSearch); + $sSql = 'SELECT id_contact, id_prop, prop_type, prop_value FROM rainloop_ab_properties '. - 'WHERE (id_user = :id_user) AND prop_type IN ('.$sTypes.') AND prop_value LIKE :search ESCAPE \'=\''; + 'WHERE (id_user = :id_user) AND prop_type IN ('.$sTypes.') AND ('. + 'prop_value LIKE :search ESCAPE \'=\''. +(0 < \strlen($sLowerSearch) ? ' OR (prop_value_lower <> \'\' AND prop_value_lower LIKE :search_lower ESCAPE \'=\')' : ''). + ')' + ; $aParams = array( ':id_user' => array($iUserID, \PDO::PARAM_INT), @@ -937,6 +1391,11 @@ class PdoAddressBook ':search' => array($this->specialConvertSearchValue($sSearch, '='), \PDO::PARAM_STR) ); + if (0 < \strlen($sLowerSearch)) + { + $aParams[':search_lower'] = array($sLowerSearch, \PDO::PARAM_STR); + } + $sSql .= ' ORDER BY prop_frec DESC'; $sSql .= ' LIMIT :limit'; @@ -1111,7 +1570,7 @@ class PdoAddressBook { $oResult = \MailSo\Mime\Email::Parse(\trim($mItem)); } - catch (\Exception $oException) {} + catch (\Exception $oException) { unset($oException); } return $oResult; }, $aEmails); @@ -1401,7 +1860,7 @@ SQLITEINITIAL; break; } - if (0 < strlen($sInitial)) + if (0 < \strlen($sInitial)) { $aList = \explode(';', \trim($sInitial)); foreach ($aList as $sV) @@ -1433,17 +1892,33 @@ SQLITEINITIAL; { case 'mysql': $mCache = $this->dataBaseUpgrade($this->sDsnType.'-ab-version', array( - 1 => $this->getInitialTablesArray($this->sDsnType) + 1 => $this->getInitialTablesArray($this->sDsnType), + 2 => array( +'ALTER TABLE rainloop_ab_properties ADD prop_value_lower varchar(255) NOT NULL DEFAULT \'\' AFTER prop_value_custom;' + ), + 3 => array( +'ALTER TABLE rainloop_ab_properties CHANGE prop_value prop_value TEXT NOT NULL;', +'ALTER TABLE rainloop_ab_properties CHANGE prop_value_custom prop_value_custom TEXT NOT NULL;', +'ALTER TABLE rainloop_ab_properties CHANGE prop_value_lower prop_value_lower TEXT NOT NULL;' + ) )); break; case 'pgsql': $mCache = $this->dataBaseUpgrade($this->sDsnType.'-ab-version', array( - 1 => $this->getInitialTablesArray($this->sDsnType) + 1 => $this->getInitialTablesArray($this->sDsnType), + 2 => array( +'ALTER TABLE rainloop_ab_properties ADD prop_value_lower text NOT NULL DEFAULT \'\';' + ), + 3 => array() )); break; case 'sqlite': $mCache = $this->dataBaseUpgrade($this->sDsnType.'-ab-version', array( - 1 => $this->getInitialTablesArray($this->sDsnType) + 1 => $this->getInitialTablesArray($this->sDsnType), + 2 => array( +'ALTER TABLE rainloop_ab_properties ADD prop_value_lower text NOT NULL DEFAULT \'\';' + ), + 3 => array() )); break; } @@ -1498,6 +1973,24 @@ SQLITEINITIAL; array($sEscapeSign.$sEscapeSign, $sEscapeSign.'_', $sEscapeSign.'%'), $sSearch).'%'; } + /** + * @param string $sSearch + * @param string $sEscapeSign = '=' + * + * @return string + */ + private function specialConvertSearchValueLower($sSearch, $sEscapeSign = '=') + { + if (!\MailSo\Base\Utils::FunctionExistsAndEnabled('mb_strtolower')) + { + return ''; + } + + return '%'.\str_replace(array($sEscapeSign, '_', '%'), + array($sEscapeSign.$sEscapeSign, $sEscapeSign.'_', $sEscapeSign.'%'), + (string) @\mb_strtolower($sSearch, 'UTF-8')).'%'; + } + /** * @param string $sSearch * diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/ChangePassword.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/ChangePassword.php index b344b227c..180b7afc1 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/ChangePassword.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/ChangePassword.php @@ -53,6 +53,8 @@ class ChangePassword extends \RainLoop\Providers\AbstractProvider */ public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) { + $mResult = false; + if ($this->oDriver instanceof \RainLoop\Providers\ChangePassword\ChangePasswordInterface && $this->PasswordChangePossibility($oAccount)) { @@ -79,11 +81,15 @@ class ChangePassword extends \RainLoop\Providers\AbstractProvider $oAccount->SetPassword($sNewPassword); $this->oActions->SetAuthToken($oAccount); + + $mResult = $this->oActions->GetSpecAuthToken(); } else { throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CouldNotSaveNewPassword); } + + return $mResult; } /** diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files.php index c3539b9c8..31d72a8c4 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files.php @@ -116,6 +116,17 @@ class Files extends \RainLoop\Providers\AbstractProvider $this->oDriver->CloseAllOpenedFiles() : false; } + /** + * @param \RainLoop\Model\Account $oAccount + * @param string $sKey + * + * @return string + */ + public function GenerateLocalFullFileName($oAccount, $sKey) + { + return $this->oDriver ? $this->oDriver->GenerateLocalFullFileName($oAccount, $sKey) : ''; + } + /** * @return bool */ diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/FileStorage.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/FileStorage.php index bc2591523..3ae703a8a 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/FileStorage.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/FileStorage.php @@ -25,6 +25,17 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles $this->sDataPath = \rtrim(\trim($sStoragePath), '\\/'); } + /** + * @param \RainLoop\Model\Account $oAccount + * @param string $sKey + * + * @return string + */ + public function GenerateLocalFullFileName($oAccount, $sKey) + { + return $this->generateFullFileName($oAccount, $sKey, true); + } + /** * @param \RainLoop\Model\Account $oAccount * @param string $sKey @@ -37,7 +48,7 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles $bResult = false; if ($rSource) { - $rOpenOutput = @\fopen($this->generateFileName($oAccount, $sKey, true), 'w+b'); + $rOpenOutput = @\fopen($this->generateFullFileName($oAccount, $sKey, true), 'w+b'); if ($rOpenOutput) { $bResult = (false !== \MailSo\Base\Utils::MultipleStreamWriter($rSource, array($rOpenOutput))); @@ -57,7 +68,7 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles public function MoveUploadedFile($oAccount, $sKey, $sSource) { return @\move_uploaded_file($sSource, - $this->generateFileName($oAccount, $sKey, true)); + $this->generateFullFileName($oAccount, $sKey, true)); } /** @@ -72,7 +83,7 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles $mResult = false; $bCreate = !!\preg_match('/[wac]/', $sOpenMode); - $sFileName = $this->generateFileName($oAccount, $sKey, $bCreate); + $sFileName = $this->generateFullFileName($oAccount, $sKey, $bCreate); if ($bCreate || \file_exists($sFileName)) { $mResult = @\fopen($sFileName, $sOpenMode); @@ -95,7 +106,7 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles public function GetFileName($oAccount, $sKey) { $mResult = false; - $sFileName = $this->generateFileName($oAccount, $sKey); + $sFileName = $this->generateFullFileName($oAccount, $sKey); if (\file_exists($sFileName)) { $mResult = $sFileName; @@ -113,7 +124,7 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles public function Clear($oAccount, $sKey) { $mResult = true; - $sFileName = $this->generateFileName($oAccount, $sKey); + $sFileName = $this->generateFullFileName($oAccount, $sKey); if (\file_exists($sFileName)) { if (isset($this->aResources[$sFileName]) && \is_resource($this->aResources[$sFileName])) @@ -136,7 +147,7 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles public function FileSize($oAccount, $sKey) { $mResult = false; - $sFileName = $this->generateFileName($oAccount, $sKey); + $sFileName = $this->generateFullFileName($oAccount, $sKey); if (\file_exists($sFileName)) { $mResult = \filesize($sFileName); @@ -153,7 +164,7 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles */ public function FileExists($oAccount, $sKey) { - return @\file_exists($this->generateFileName($oAccount, $sKey)); + return @\file_exists($this->generateFullFileName($oAccount, $sKey)); } /** @@ -198,7 +209,7 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles * * @return string */ - private function generateFileName($oAccount, $sKey, $bMkDir = false) + private function generateFullFileName($oAccount, $sKey, $bMkDir = false) { $sEmail = $sSubEmail = ''; if ($oAccount instanceof \RainLoop\Model\Account) diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/IFiles.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/IFiles.php index cb7aaceae..c31e231be 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/IFiles.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/IFiles.php @@ -4,6 +4,14 @@ namespace RainLoop\Providers\Files; interface IFiles { + /** + * @param \RainLoop\Model\Account $oAccount + * @param string $sKey + * + * @return string + */ + public function GenerateLocalFullFileName($oAccount, $sKey); + /** * @param \RainLoop\Model\Account $oAccount * @param string $sKey diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/Filter.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/Filter.php index 360a2c074..09c181344 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/Filter.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/Filter.php @@ -49,6 +49,11 @@ class Filter */ private $sActionValueThird; + /** + * @var string + */ + private $sActionValueFourth; + /** * @var bool */ @@ -89,6 +94,7 @@ class Filter $this->sActionValue = ''; $this->sActionValueSecond = ''; $this->sActionValueThird = ''; + $this->sActionValueFourth = ''; $this->bMarkAsRead = false; $this->bKeep = true; @@ -167,6 +173,14 @@ class Filter return $this->sActionValueThird; } + /** + * @return string + */ + public function ActionValueFourth() + { + return $this->sActionValueFourth; + } + /** * @return bool */ @@ -236,6 +250,7 @@ class Filter $this->sActionValue = isset($aFilter['ActionValue']) ? $aFilter['ActionValue'] : ''; $this->sActionValueSecond = isset($aFilter['ActionValueSecond']) ? $aFilter['ActionValueSecond'] : ''; $this->sActionValueThird = isset($aFilter['ActionValueThird']) ? $aFilter['ActionValueThird'] : ''; + $this->sActionValueFourth = isset($aFilter['ActionValueFourth']) ? $aFilter['ActionValueFourth'] : ''; $this->bKeep = isset($aFilter['Keep']) ? '1' === (string) $aFilter['Keep'] : true; $this->bStop = isset($aFilter['Stop']) ? '1' === (string) $aFilter['Stop'] : true; @@ -276,6 +291,7 @@ class Filter 'ActionValue' => $this->ActionValue(), 'ActionValueSecond' => $this->ActionValueSecond(), 'ActionValueThird' => $this->ActionValueThird(), + 'ActionValueFourth' => $this->ActionValueFourth(), 'Keep' => $this->Keep(), 'Stop' => $this->Stop(), 'MarkAsRead' => $this->MarkAsRead() diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/FilterCondition.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/FilterCondition.php index b56e92fdf..173d66dfa 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/FilterCondition.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/FilterCondition.php @@ -19,6 +19,11 @@ class FilterCondition */ private $sValue; + /** + * @var string + */ + private $sValueSecond; + public function __construct() { $this->Clear(); @@ -29,6 +34,7 @@ class FilterCondition $this->sField = \RainLoop\Providers\Filters\Enumerations\ConditionField::FROM; $this->sType = \RainLoop\Providers\Filters\Enumerations\ConditionType::EQUAL_TO; $this->sValue = ''; + $this->sValueSecond = ''; } /** @@ -55,6 +61,14 @@ class FilterCondition return $this->sValue; } + /** + * @return string + */ + public function ValueSecond() + { + return $this->sValueSecond; + } + /** * @param array $aData * @@ -70,7 +84,8 @@ class FilterCondition $this->sType = isset($aData['Type']) ? $aData['Type'] : \RainLoop\Providers\Filters\Enumerations\ConditionType::EQUAL_TO; - $this->sValue = isset($aData['Value']) ? $aData['Value'] : ''; + $this->sValue = isset($aData['Value']) ? (string) $aData['Value'] : ''; + $this->sValueSecond = isset($aData['ValueSecond']) ? (string) $aData['ValueSecond'] : ''; return true; } @@ -88,7 +103,8 @@ class FilterCondition return array( 'Field' => $this->Field(), 'Type' => $this->Type(), - 'Value' => $this->Value() + 'Value' => $this->Value(), + 'ValueSecond' => $this->ValueSecond() ); } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Enumerations/ConditionField.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Enumerations/ConditionField.php index 7853ba457..e78f95402 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Enumerations/ConditionField.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Enumerations/ConditionField.php @@ -7,4 +7,6 @@ class ConditionField const FROM = 'From'; const RECIPIENT = 'Recipient'; const SUBJECT = 'Subject'; + const HEADER = 'Header'; + const SIZE = 'Size'; } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Enumerations/ConditionType.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Enumerations/ConditionType.php index 96b6c4113..126bdf642 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Enumerations/ConditionType.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Enumerations/ConditionType.php @@ -8,4 +8,6 @@ class ConditionType const NOT_EQUAL_TO = 'NotEqualTo'; const CONTAINS = 'Contains'; const NOT_CONTAINS = 'NotContains'; + const OVER = 'Over'; + const UNDER = 'Under'; } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/SieveStorage.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/SieveStorage.php index 4d14d2b16..590dc9568 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/SieveStorage.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Filters/SieveStorage.php @@ -163,12 +163,23 @@ class SieveStorage implements \RainLoop\Providers\Filters\FiltersInterface { $sResult = ''; $sTypeWord = ''; + $bTrue = true; $sValue = \trim($oCondition->Value()); - if (0 < strlen($sValue)) + $sValueSecond = \trim($oCondition->ValueSecond()); + + if (0 < \strlen($sValue) || + (0 < \strlen($sValue) && 0 < \strlen($sValueSecond) && + \RainLoop\Providers\Filters\Enumerations\ConditionField::HEADER === $oCondition->Field())) { switch ($oCondition->Type()) { + case \RainLoop\Providers\Filters\Enumerations\ConditionType::OVER: + $sTypeWord = ':over'; + break; + case \RainLoop\Providers\Filters\Enumerations\ConditionType::UNDER: + $sTypeWord = ':under'; + break; case \RainLoop\Providers\Filters\Enumerations\ConditionType::NOT_EQUAL_TO: $sResult .= 'not '; case \RainLoop\Providers\Filters\Enumerations\ConditionType::EQUAL_TO: @@ -179,6 +190,10 @@ class SieveStorage implements \RainLoop\Providers\Filters\FiltersInterface case \RainLoop\Providers\Filters\Enumerations\ConditionType::CONTAINS: $sTypeWord = ':contains'; break; + default: + $bTrue = false; + $sResult = '/* @Error: unknown type value */ false'; + break; } switch ($oCondition->Field()) @@ -192,26 +207,43 @@ class SieveStorage implements \RainLoop\Providers\Filters\FiltersInterface case \RainLoop\Providers\Filters\Enumerations\ConditionField::SUBJECT: $sResult .= 'header '.$sTypeWord.' ["Subject"]'; break; + case \RainLoop\Providers\Filters\Enumerations\ConditionField::HEADER: + $sResult .= 'header '.$sTypeWord.' ["'.$this->quote($sValueSecond).'"]'; + break; + case \RainLoop\Providers\Filters\Enumerations\ConditionField::SIZE: + $sResult .= 'size '.$sTypeWord; + break; + default: + $bTrue = false; + $sResult = '/* @Error: unknown field value */ false'; + break; } - if (\in_array($oCondition->Field(), array( - \RainLoop\Providers\Filters\Enumerations\ConditionField::FROM, - \RainLoop\Providers\Filters\Enumerations\ConditionField::RECIPIENT - )) && false !== \strpos($sValue, ',')) + if ($bTrue) { - $self = $this; - $aValue = \array_map(function ($sValue) use ($self) { - return '"'.$self->quote(\trim($sValue)).'"'; - }, \explode(',', $sValue)); + if (\in_array($oCondition->Field(), array( + \RainLoop\Providers\Filters\Enumerations\ConditionField::FROM, + \RainLoop\Providers\Filters\Enumerations\ConditionField::RECIPIENT + )) && false !== \strpos($sValue, ',')) + { + $self = $this; + $aValue = \array_map(function ($sValue) use ($self) { + return '"'.$self->quote(\trim($sValue)).'"'; + }, \explode(',', $sValue)); - $sResult .= ' ['.\trim(\implode(', ', $aValue)).']'; - } - else - { - $sResult .= ' "'.$this->quote($sValue).'"'; - } + $sResult .= ' ['.\trim(\implode(', ', $aValue)).']'; + } + else if (\RainLoop\Providers\Filters\Enumerations\ConditionField::SIZE === $oCondition->Field()) + { + $sResult .= ' '.$this->quote($sValue); + } + else + { + $sResult .= ' "'.$this->quote($sValue).'"'; + } - $sResult = \preg_replace('/[\s]+/u', ' ', $sResult); + $sResult = \MailSo\Base\Utils::StripSpaces($sResult); + } } else { @@ -318,6 +350,7 @@ class SieveStorage implements \RainLoop\Providers\Filters\FiltersInterface $sValue = \trim($oFilter->ActionValue()); $sValueSecond = \trim($oFilter->ActionValueSecond()); $sValueThird = \trim($oFilter->ActionValueThird()); + $sValueFourth = \trim($oFilter->ActionValueFourth()); if (0 < \strlen($sValue)) { $aCapa['vacation'] = true; @@ -326,8 +359,8 @@ class SieveStorage implements \RainLoop\Providers\Filters\FiltersInterface $sSubject = ''; if (0 < \strlen($sValueSecond)) { - $sSubject = ':subject "'.$this->quote( - \preg_replace('/[\s]+/u', ' ', $sValueSecond)).'" '; + $sSubject = ':subject "'. + $this->quote(\MailSo\Base\Utils::StripSpaces($sValueSecond)).'" '; } if (0 < \strlen($sValueThird) && \is_numeric($sValueThird) && 1 < (int) $sValueThird) @@ -335,8 +368,24 @@ class SieveStorage implements \RainLoop\Providers\Filters\FiltersInterface $iDays = (int) $sValueThird; } - $aResult[] = $sTab.'vacation :days '.$iDays.' '.$sSubject.'"'.$this->quote($sValue).'";'; + $sAddresses = ''; + if (0 < \strlen($sValueFourth)) + { + $self = $this; + $aAddresses = \explode(',', $sValueFourth); + $aAddresses = \array_filter(\array_map(function ($sEmail) use ($self) { + $sEmail = \trim($sEmail); + return 0 < \strlen($sEmail) ? '"'.$self->quote($sEmail).'"' : ''; + }, $aAddresses), 'strlen'); + + if (0 < \count($aAddresses)) + { + $sAddresses = ':addresses ['.\implode(', ', $aAddresses).'] '; + } + } + + $aResult[] = $sTab.'vacation :days '.$iDays.' '.$sAddresses.$sSubject.'"'.$this->quote($sValue).'";'; if ($oFilter->Stop()) { $aResult[] = $sTab.'stop;'; @@ -491,7 +540,7 @@ class SieveStorage implements \RainLoop\Providers\Filters\FiltersInterface * * @return string */ - private function quote($sValue) + public function quote($sValue) { return \str_replace(array('\\', '"'), array('\\\\', '\\"'), \trim($sValue)); } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions.php index d4b5b27bc..13cc8cbe9 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions.php @@ -5,31 +5,72 @@ namespace RainLoop\Providers; class Suggestions extends \RainLoop\Providers\AbstractProvider { /** - * @var \RainLoop\Providers\Suggestions\ISuggestions + * @var \RainLoop\Providers\Suggestions\ISuggestions[] */ - private $oDriver; + private $aDrivers; /** - * @param \RainLoop\Providers\Suggestions\ISuggestions|null $oDriver = null + * @param \RainLoop\Providers\Suggestions\ISuggestions[]|null $aDriver = null * * @return void */ - public function __construct($oDriver = null) + public function __construct($aDriver = null) { - $this->oDriver = $oDriver; + if (\is_array($aDriver)) + { + $aDriver = \array_filter($aDriver, function ($oDriver) { + return $oDriver instanceof \RainLoop\Providers\Suggestions\ISuggestions; + }); + } + + $this->aDrivers = \is_array($aDriver) && 0 < \count($aDriver) ? $aDriver : null; } /** - * @param \RainLoop\Account $oAccount + * @param \RainLoop\Model\Account $oAccount * @param string $sQuery * @param int $iLimit = 20 * * @return array */ - public function Process(\RainLoop\Account $oAccount, $sQuery, $iLimit = 20) + public function Process($oAccount, $sQuery, $iLimit = 20) { - return $this->oDriver && $this->IsActive() && 0 < \strlen($sQuery) ? - $this->oDriver->Process($oAccount, $sQuery, $iLimit = 20) : array(); + $aResult = array(); + $aSuggestions = array(); + if ($oAccount instanceof \RainLoop\Model\Account && + $this->IsActive() && \is_array($this->aDrivers) && 0 < \strlen($sQuery)) + { + foreach ($this->aDrivers as $oDriver) + { + $aSubs = null; + if ($oDriver) + { + $aSubs = $oDriver->Process($oAccount, $sQuery, $iLimit); + if (\is_array($aSubs) && 0 < \count($aSubs)) + { + $aSuggestions = \array_merge($aSuggestions, $aSubs); + } + } + } + } + + $aCache = array(); + foreach ($aSuggestions as $aItem) // remove duplicates + { + $sLine = \implode('~~', $aItem); + if (!isset($aCache[$sLine])) + { + $aCache[$sLine] = true; + $aResult[] = $aItem; + } + } + + if ($iLimit < \count($aResult)) + { + $aResult = \array_slice($aResult, 0, $iLimit); + } + + return $aResult; } /** @@ -37,6 +78,6 @@ class Suggestions extends \RainLoop\Providers\AbstractProvider */ public function IsActive() { - return $this->oDriver instanceof \RainLoop\Providers\Suggestions\ISuggestions; + return \is_array($this->aDrivers) && 0 < \count($this->aDrivers); } } \ No newline at end of file diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions/ISuggestions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions/ISuggestions.php index cbb8130d2..93050fbce 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions/ISuggestions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions/ISuggestions.php @@ -9,7 +9,7 @@ interface ISuggestions * @param string $sQuery * @param int $iLimit = 20 * - * @return array + * @return array [['email@1', 'name_1'], ['email@2', 'name_2']] */ public function Process($oAccount, $sQuery, $iLimit = 20); } \ No newline at end of file diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions/OwnCloudSuggestions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions/OwnCloudSuggestions.php index d4a7aac97..33eae71bf 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions/OwnCloudSuggestions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions/OwnCloudSuggestions.php @@ -24,9 +24,8 @@ class OwnCloudSuggestions implements \RainLoop\Providers\Suggestions\ISuggestion try { - if ('' === $sQuery || !$oAccount || !\RainLoop\Utils::IsOwnCloud() || - !\class_exists('\\OCP\\Contacts') || !\OCP\Contacts::isEnabled() || - !\class_exists('\\OCP\\User') || !\OCP\User::isLoggedIn() + if ('' === $sQuery || !$oAccount || !\RainLoop\Utils::IsOwnCloudLoggedIn() || + !\class_exists('OCP\Contacts') || !\OCP\Contacts::isEnabled() ) { return $aResult; diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions/TestSuggestions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions/TestSuggestions.php index fd9cbfc9c..f1c640c46 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions/TestSuggestions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Suggestions/TestSuggestions.php @@ -15,7 +15,7 @@ class TestSuggestions implements \RainLoop\Providers\Suggestions\ISuggestions { return array( array($oAccount->Email(), ''), - array('xxx@xxx', 'xxx') + array('email@domain.com', 'name') ); } } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php index 896fbdfa7..903e615c1 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php @@ -193,17 +193,23 @@ class Service $sResult .= ''; + $sResult .= '] //-->'; } // Output result @@ -260,7 +266,9 @@ class Service '{{BaseAppOpenPgpScriptLink}}' => $aData['OpenPgpJsLink'], '{{BaseAppMainCommonScriptLink}}' => $aData['AppJsCommonLink'], '{{BaseAppMainScriptLink}}' => $aData['AppJsLink'], - '{{BaseDir}}' => \in_array($aData['Language'], array('ar', 'he', 'ur')) ? 'rtl' : 'ltr' + '{{BaseVersion}}' => APP_VERSION, + '{{BaseDir}}' => 'ltr' +// '{{BaseDir}}' => \in_array($aData['Language'], array('ar', 'he', 'ur')) ? 'rtl' : 'ltr' ); $aTemplateParameters['{{BaseHash}}'] = \md5( diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php index 76eb2c773..19b2cb183 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php @@ -429,7 +429,7 @@ class ServiceActions { $this->oActions->verifyCacheByKey($sData); - $aData = \RainLoop\Utils::DecodeKeyValues($sData); + $aData = \RainLoop\Utils::DecodeKeyValuesQ($sData); if (\is_array($aData) && !empty($aData['Token']) && !empty($aData['Url']) && $aData['Token'] === \RainLoop\Utils::GetConnectionToken()) { $iCode = 404; @@ -766,7 +766,8 @@ class ServiceActions */ public function ServiceSocialGoogle() { - return $this->oActions->Social()->GooglePopupService(); + $bXAuth = '1' === (string) $this->oHttp->GetQuery('xauth', '0'); + return $this->oActions->Social()->GooglePopupService($bXAuth); } /** @@ -892,7 +893,7 @@ class ServiceActions $sSsoSubData = $this->Cacher()->Get(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash)); if (!empty($sSsoSubData)) { - $mData = \RainLoop\Utils::DecodeKeyValues($sSsoSubData); + $mData = \RainLoop\Utils::DecodeKeyValuesQ($sSsoSubData); $this->Cacher()->Delete(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash)); if (\is_array($mData) && !empty($mData['Email']) && isset($mData['Password'], $mData['Time']) && @@ -1219,11 +1220,23 @@ class ServiceActions */ public function compileTemplates($bAdmin = false, $bJsOutput = true) { - $sHtml = - \RainLoop\Utils::CompileTemplates(APP_VERSION_ROOT_PATH.'app/templates/Views/Components', $this->oActions, 'Component'). - \RainLoop\Utils::CompileTemplates(APP_VERSION_ROOT_PATH.'app/templates/Views/'.($bAdmin ? 'Admin' : 'User'), $this->oActions). - \RainLoop\Utils::CompileTemplates(APP_VERSION_ROOT_PATH.'app/templates/Views/Common', $this->oActions). - $this->oActions->Plugins()->CompileTemplate($bAdmin); + $aTemplates = array(); + + \RainLoop\Utils::CompileTemplates($aTemplates, APP_VERSION_ROOT_PATH.'app/templates/Views/Components', 'Component'); + \RainLoop\Utils::CompileTemplates($aTemplates, APP_VERSION_ROOT_PATH.'app/templates/Views/'.($bAdmin ? 'Admin' : 'User')); + \RainLoop\Utils::CompileTemplates($aTemplates, APP_VERSION_ROOT_PATH.'app/templates/Views/Common'); + + $this->oActions->Plugins()->CompileTemplate($aTemplates, $bAdmin); + + $sHtml = ''; + foreach ($aTemplates as $sName => $sFile) + { + $sName = \preg_replace('/[^a-zA-Z0-9]/', '', $sName); + $sHtml .= ''; + } + + unset($aTemplates); return $bJsOutput ? 'window.rainloopTEMPLATES='.\MailSo\Base\Utils::Php2js(array($sHtml), $this->Logger()).';' : $sHtml; } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Social.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Social.php index aa0175c40..0183b84f3 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Social.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Social.php @@ -25,152 +25,6 @@ class Social $this->oActions = $oActions; } - /** - * @param array $oItem - * @param array $aPics - * - * @return array|null - */ - private function convertGoogleJsonContactToResponseContact($oItem, &$aPics) - { - $mResult = null; - if (!empty($oItem['gd$email'][0]['address'])) - { - $mEmail = \MailSo\Base\Utils::IdnToAscii($oItem['gd$email'][0]['address'], true); - if (\is_array($oItem['gd$email']) && 1 < \count($oItem['gd$email'])) - { - $mEmail = array(); - foreach ($oItem['gd$email'] as $oEmail) - { - if (!empty($oEmail['address'])) - { - $mEmail[] = \MailSo\Base\Utils::IdnToAscii($oEmail['address'], true); - } - } - } - - $sImg = ''; - if (!empty($oItem['link']) && \is_array($oItem['link'])) - { - foreach ($oItem['link'] as $oLink) - { - if ($oLink && isset($oLink['type'], $oLink['href'], $oLink['rel']) && - 'image/*' === $oLink['type'] && '#photo' === \substr($oLink['rel'], -6)) - { - $sImg = $oLink['href']; - break; - } - } - } - - $mResult = array( - 'email' => $mEmail, - 'name' => !empty($oItem['title']['$t']) ? $oItem['title']['$t'] : '' - ); - - if (0 < \strlen($sImg)) - { - $sHash = \RainLoop\Utils::EncodeKeyValues(array( - 'url' => $sImg, - 'type' => 'google_access_token' - )); - - $mData = array(); - if (isset($aPics[$sHash])) - { - $mData = $aPics[$sHash]; - if (!\is_array($mData)) - { - $mData = array($mData); - } - } - - if (\is_array($mEmail)) - { - $mData = \array_merge($mData, $mEmail); - $mData = \array_unique($mData); - } - else if (0 < \strlen($mEmail)) - { - $mData[] = $mEmail; - } - - if (\is_array($mData)) - { - if (1 === \count($mData) && !empty($mData[0])) - { - $aPics[$sHash] = $mData[0]; - } - else if (1 < \count($mData)) - { - $aPics[$sHash] = $mData; - } - } - } - } - - return $mResult; - } - - /** - * @return array - */ - public function GoogleUserContacts($oAccount) - { - $mResult = false; - $oGoogle = $this->GoogleConnector(); - $aPics = array(); - - if ($oAccount && $oGoogle) - { - $sAccessToken = $this->GoogleAccessToken($oAccount, $oGoogle); - if (!empty($sAccessToken)) - { - $oGoogle->setAccessToken($sAccessToken); - - $aResponse = $oGoogle->fetch('https://www.google.com/m8/feeds/contacts/default/full', array( - 'alt' => 'json' - )); - - if (!empty($aResponse['result']['feed']['entry']) && \is_array($aResponse['result']['feed']['entry'])) - { - $mResult = array(); - foreach ($aResponse['result']['feed']['entry'] as $oItem) - { - $aItem = $this->convertGoogleJsonContactToResponseContact($oItem, $aPics); - if ($aItem) - { - if (\is_array($aItem['email'])) - { - $aNewItem = $aItem; - unset($aNewItem['email']); - - foreach ($aItem['email'] as $sEmail) - { - $aNewItem['email'] = $sEmail; - $mResult[] = $aNewItem; - } - } - else - { - $mResult[] = $aItem; - } - } - } - } - } - else - { - $this->oActions->Logger()->Write('Empty Google Access Token', \MailSo\Log\Enumerations\Type::ERROR); - } - } - - return false !== $mResult ? array( - 'List' => $mResult, - 'Pics' => $aPics - ) : false; - } - /** * @return bool */ @@ -185,7 +39,7 @@ class Social if (!empty($sEncodedeData)) { $aData = \RainLoop\Utils::DecodeKeyValues($sEncodedeData); - if (\is_array($aData) && isset($aData['access_token'], $aData['id'])) + if (\is_array($aData) && !empty($aData['id'])) { $this->oActions->StorageProvider()->Clear(null, \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, @@ -271,7 +125,7 @@ class Social /** * @return string */ - public function GooglePopupService() + public function GooglePopupService($bGmail = false) { $sResult = ''; $sLoginUrl = ''; @@ -298,23 +152,36 @@ class Social $sState = $this->oHttp->GetQuery('state'); if (!empty($sState)) { - $aParts = explode('|', $sState, 2); - $sCheckToken = !empty($aParts[0]) ? $aParts[0] : ''; - $sCheckAuth = !empty($aParts[1]) ? $aParts[1] : ''; + $aParts = explode('|', $sState, 3); + + if (!$bGmail) + { + $bGmail = !empty($aParts[0]) ? '1' === (string) $aParts[0] : false; + } + + $sCheckToken = !empty($aParts[1]) ? $aParts[1] : ''; + $sCheckAuth = !empty($aParts[2]) ? $aParts[2] : ''; } $sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialGoogle'; if (!$this->oHttp->HasQuery('code')) { -// https://www.google.com/m8/feeds/ $aParams = array( - 'scope' => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile', - 'state' => \RainLoop\Utils::GetConnectionToken().'|'.$this->oActions->GetSpecAuthToken(), -// 'access_type' => 'offline', -// 'approval_prompt' => 'force', + 'scope' => \trim(\implode(' ', array( + 'https://www.googleapis.com/auth/userinfo.email', + 'https://www.googleapis.com/auth/userinfo.profile', + $bGmail ? 'https://mail.google.com/' : '' + ))), + 'state' => ($bGmail ? '1' : '0').'|'.\RainLoop\Utils::GetConnectionToken().'|'.$this->oActions->GetSpecAuthToken(), 'response_type' => 'code' ); +// if ($bGmail) +// { +// $aParams['access_type'] = 'offline'; +// $aParams['approval_prompt'] = 'force'; +// } + $sLoginUrl = $oGoogle->getAuthenticationUrl('https://accounts.google.com/o/oauth2/auth', $sRedirectUrl, $aParams); } else if (!empty($sState) && $sCheckToken === \RainLoop\Utils::GetConnectionToken()) @@ -332,18 +199,32 @@ class Social if (!empty($aAuthorizationResponse['result']['access_token'])) { $oGoogle->setAccessToken($aAuthorizationResponse['result']['access_token']); - $aUserinfoResponse = $oGoogle->fetch('https://www.googleapis.com/oauth2/v2/userinfo'); + $aUserInfoResponse = $oGoogle->fetch('https://www.googleapis.com/oauth2/v2/userinfo'); - if (!empty($aUserinfoResponse['result']['id'])) + if (!empty($aUserInfoResponse['result']['id'])) { if ($bLogin) { - $sUserData = $this->oActions->StorageProvider()->Get(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - $this->GoogleUserLoginStorageKey($oGoogle, $aUserinfoResponse['result']['id']) - ); + $aUserData = null; + if ($bGmail) + { + if (!empty($aUserInfoResponse['result']['email'])) + { + $aUserData = array( + 'Email' => $aUserInfoResponse['result']['email'], + 'Password' => APP_GOOGLE_ACCESS_TOKEN_PREFIX.$aAuthorizationResponse['result']['access_token'] + ); + } + } + else + { + $sUserData = $this->oActions->StorageProvider()->Get(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $this->GoogleUserLoginStorageKey($oGoogle, $aUserInfoResponse['result']['id']) + ); - $aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData); + $aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData); + } if ($aUserData && \is_array($aUserData) && !empty($aUserData['Email']) && isset($aUserData['Password'])) @@ -356,24 +237,31 @@ class Social } } - if ($oAccount) + if ($oAccount && !$bGmail) { $aUserData = array( + 'ID' => $aUserInfoResponse['result']['id'], 'Email' => $oAccount->Email(), 'Password' => $oAccount->Password() ); - $sSocialName = !empty($aUserinfoResponse['result']['name']) ? $aUserinfoResponse['result']['name'] : ''; - $sSocialName .= !empty($aUserinfoResponse['result']['email']) ? ' ('.$aUserinfoResponse['result']['email'].')' : ''; + $sSocialName = !empty($aUserInfoResponse['result']['name']) ? $aUserInfoResponse['result']['name'] : ''; + $sSocialName .= !empty($aUserInfoResponse['result']['email']) ? ' ('.$aUserInfoResponse['result']['email'].')' : ''; $sSocialName = \trim($sSocialName); $oSettings = $this->oActions->SettingsProvider()->Load($oAccount); + + $oSettings->SetConf('GoogleAccessToken', \RainLoop\Utils::EncodeKeyValues(array( + 'id' => $aUserInfoResponse['result']['id'] + ))); + $oSettings->SetConf('GoogleSocialName', $sSocialName); + $this->oActions->SettingsProvider()->Save($oAccount, $oSettings); $this->oActions->StorageProvider()->Put(null, \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - $this->GoogleUserLoginStorageKey($oGoogle, $aUserinfoResponse['result']['id']), + $this->GoogleUserLoginStorageKey($oGoogle, $aUserInfoResponse['result']['id']), \RainLoop\Utils::EncodeKeyValues($aUserData)); $iErrorCode = 0; @@ -577,9 +465,7 @@ class Social if (200 === $iCode && isset($oTwitter->response['response'])) { - $this->oActions->Logger()->WriteDump($oTwitter->response['response']); $aAccessToken = $oTwitter->extract_params($oTwitter->response['response']); - $this->oActions->Logger()->WriteDump($aAccessToken); if ($aAccessToken && isset($aAccessToken['oauth_token']) && !empty($aAccessToken['user_id'])) { $oTwitter->config['user_token'] = $aAccessToken['oauth_token']; diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php index b85f33c99..56a53082f 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php @@ -4,8 +4,17 @@ namespace RainLoop; class Utils { + /** + * @var string + */ + static $CookieDefaultPath = '/'; + static $Cookies = null; + static $RSA = null; + + static $RsaKey = null; + /** * @return void */ @@ -13,6 +22,164 @@ class Utils { } + /** + * @param string $sFileName + * @param string $sSignature + * + * @return bool + */ + static public function PgpVerifyFile($sFileName, $sSignature) + { + $sKeyFile = APP_VERSION_ROOT_PATH.'app/resources/RainLoop.asc'; + if (\file_exists($sKeyFile) && \file_exists($sFileName) && !empty($sSignature)) + { + $sKeyFile = @\file_get_contents($sKeyFile); + return !empty($sKeyFile); // TODO + } + + return false; + } + + /** + * @return \Crypt_RSA|null + */ + static public function CryptRSA() + { + if (null === \RainLoop\Utils::$RSA) + { + if (!\defined('_phpseclib_')) + { + \set_include_path(\get_include_path().PATH_SEPARATOR.APP_VERSION_ROOT_PATH.'app/libraries/phpseclib'); + define('_phpseclib_', true); + } + + if (!\class_exists('Crypt_RSA', false)) + { + include_once 'Crypt/RSA.php'; + \defined('CRYPT_RSA_MODE') || \define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL); + } + + if (\class_exists('Crypt_RSA')) + { + $oRsa = new \Crypt_RSA(); + + $oRsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1); + $oRsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1); + $oRsa->setPrivateKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); + + $sPrivateKey = \file_exists(APP_PRIVATE_DATA.'rsa/private') ? + \file_get_contents(APP_PRIVATE_DATA.'rsa/private') : ''; + + if (!empty($sPrivateKey)) + { + $oRsa->loadKey($sPrivateKey, CRYPT_RSA_PRIVATE_FORMAT_PKCS1); + $oRsa->loadKey($oRsa->getPublicKey(), CRYPT_RSA_PUBLIC_FORMAT_PKCS1); + + \RainLoop\Utils::$RSA = $oRsa; + } + } + } + + return \RainLoop\Utils::$RSA; + } + + /** + * @return string + */ + static public function RsaPrivateKey() + { + if (!empty(\RainLoop\Utils::$RsaKey)) + { + return \RainLoop\Utils::$RsaKey; + } + + \RainLoop\Utils::$RsaKey = \file_exists(APP_PRIVATE_DATA.'rsa/private') ? + \file_get_contents(APP_PRIVATE_DATA.'rsa/private') : ''; + + \RainLoop\Utils::$RsaKey = \is_string(\RainLoop\Utils::$RsaKey) ? \RainLoop\Utils::$RsaKey : ''; + } + + /** + * @param string $sString + * @param string $sKey = '' + * + * @return string|false + */ + static public function EncryptStringRSA($sString, $sKey = '') + { + $sResult = ''; + $sKey = \md5($sKey); + + $sPrivateKey = \RainLoop\Utils::RsaPrivateKey(); + if (!empty($sPrivateKey)) + { + $oPrivKey = \openssl_pkey_get_private($sPrivateKey); + $oKeyDetails = \openssl_pkey_get_details($oPrivKey); + + if (!empty($oKeyDetails['key']) && !empty($oKeyDetails['bits'])) + { + $oPubKey = \openssl_pkey_get_public($oKeyDetails['key']); + + $iC = (($oKeyDetails['bits'] / 8) - 15); + $aString = \str_split($sString, $iC); + + foreach ($aString as $iIndex => $sLine) + { + $sEncrypted = ''; + \openssl_public_encrypt($sLine, $sEncrypted, $oPubKey); + $aString[$iIndex] = $sEncrypted; + } + + $aString[] = $sKey; + $sResult = @\serialize($aString); + + \openssl_free_key($oPubKey); + } + + \openssl_free_key($oPrivKey); + } + + return $sResult; + } + + /** + * @param string $sString + * @param string $sKey = '' + * + * @return string|false + */ + static public function DecryptStringRSA($sString, $sKey = '') + { + $sResult = ''; + $sKey = \md5($sKey); + + $sPrivateKey = \RainLoop\Utils::RsaPrivateKey(); + if (!empty($sPrivateKey) && !empty($sString)) + { + $oPrivKey = \openssl_pkey_get_private($sPrivateKey); + + $aString = @\unserialize($sString); + if (\is_array($aString)) + { + if ($sKey === \array_pop($aString)) + { + foreach ($aString as $iIndex => $sLine) + { + $sDecrypted = ''; + \openssl_private_decrypt($sLine, $sDecrypted, $oPrivKey); + $aString[$iIndex] = $sDecrypted; + } + + $sResult = \implode('', $aString); + } + } + + \openssl_free_key($oPrivKey); + } + + return $sResult; + } + /** * @param string $sString * @param string $sKey @@ -35,6 +202,42 @@ class Utils return \MailSo\Base\Crypt::XxteaDecrypt($sEncriptedString, $sKey); } + /** + * @param string $sString + * @param string $sKey + * + * @return string + */ + static public function EncryptStringQ($sString, $sKey) + { +// if (\MailSo\Base\Utils::FunctionExistsAndEnabled('openssl_pkey_get_private')) +// { +// return \RainLoop\Utils::EncryptStringRSA($sString, +// $sKey.'Q'.\RainLoop\Utils::GetShortToken()); +// } + + return \MailSo\Base\Crypt::XxteaEncrypt($sString, + $sKey.'Q'.\RainLoop\Utils::GetShortToken()); + } + + /** + * @param string $sEncriptedString + * @param string $sKey + * + * @return string + */ + static public function DecryptStringQ($sEncriptedString, $sKey) + { +// if (\MailSo\Base\Utils::FunctionExistsAndEnabled('openssl_pkey_get_private')) +// { +// return \RainLoop\Utils::DecryptStringRSA($sEncriptedString, +// $sKey.'Q'.\RainLoop\Utils::GetShortToken()); +// } + + return \MailSo\Base\Crypt::XxteaDecrypt($sEncriptedString, + $sKey.'Q'.\RainLoop\Utils::GetShortToken()); + } + /** * @param array $aValues * @param string $sCustomKey = '' @@ -44,7 +247,7 @@ class Utils static public function EncodeKeyValues(array $aValues, $sCustomKey = '') { return \MailSo\Base\Utils::UrlSafeBase64Encode( - \RainLoop\Utils::EncryptString(\serialize($aValues), \md5(APP_SALT.$sCustomKey))); + \RainLoop\Utils::EncryptString(@\serialize($aValues), \md5(APP_SALT.$sCustomKey))); } /** @@ -55,13 +258,41 @@ class Utils */ static public function DecodeKeyValues($sEncodedValues, $sCustomKey = '') { - $aResult = \unserialize( + $aResult = @\unserialize( \RainLoop\Utils::DecryptString( \MailSo\Base\Utils::UrlSafeBase64Decode($sEncodedValues), \md5(APP_SALT.$sCustomKey))); return \is_array($aResult) ? $aResult : array(); } + /** + * @param array $aValues + * @param string $sCustomKey = '' + * + * @return string + */ + static public function EncodeKeyValuesQ(array $aValues, $sCustomKey = '') + { + return \MailSo\Base\Utils::UrlSafeBase64Encode( + \RainLoop\Utils::EncryptStringQ( + @\serialize($aValues), \md5(APP_SALT.$sCustomKey))); + } + + /** + * @param string $sEncodedValues + * @param string $sCustomKey = '' + * + * @return array + */ + static public function DecodeKeyValuesQ($sEncodedValues, $sCustomKey = '') + { + $aResult = @\unserialize( + \RainLoop\Utils::DecryptStringQ( + \MailSo\Base\Utils::UrlSafeBase64Decode($sEncodedValues), \md5(APP_SALT.$sCustomKey))); + + return \is_array($aResult) ? $aResult : array(); + } + /** * @return string */ @@ -73,7 +304,7 @@ class Utils if (null === $sToken) { $sToken = \MailSo\Base\Utils::Md5Rand(APP_SALT); - \RainLoop\Utils::SetCookie($sKey, $sToken, \time() + 60 * 60 * 24 * 30, '/', null, null, true); + \RainLoop\Utils::SetCookie($sKey, $sToken, \time() + 60 * 60 * 24 * 30); } return \md5('Connection'.APP_SALT.$sToken.'Token'.APP_SALT); @@ -98,7 +329,7 @@ class Utils if (null === $sToken) { $sToken = \MailSo\Base\Utils::Md5Rand(APP_SALT); - \RainLoop\Utils::SetCookie($sKey, $sToken, 0, '/', null, null, true); + \RainLoop\Utils::SetCookie($sKey, $sToken, 0); } return \md5('Session'.APP_SALT.$sToken.'Token'.APP_SALT); @@ -114,7 +345,7 @@ class Utils $sToken = \RainLoop\Utils::GetCookie($sKey, ''); if (!empty($sToken)) { - \RainLoop\Utils::SetCookie($sKey, $sToken, \time() + 60 * 60 * 24 * 30, '/', null, null, true); + \RainLoop\Utils::SetCookie($sKey, $sToken, \time() + 60 * 60 * 24 * 30); } } @@ -244,30 +475,22 @@ class Utils } /** + * @param array $aList * @param string $sDirName - * @param \RainLoop\Actions $oAction * @param string $sNameSuffix = '' - * - * @return string */ - public static function CompileTemplates($sDirName, $oAction, $sNameSuffix = '') + public static function CompileTemplates(&$aList, $sDirName, $sNameSuffix = '') { - $sResult = ''; if (\file_exists($sDirName)) { - $aList = \RainLoop\Utils::FolderFiles($sDirName, '.html'); + $aFileList = \RainLoop\Utils::FolderFiles($sDirName, '.html'); - foreach ($aList as $sName) + foreach ($aFileList as $sName) { $sTemplateName = \substr($sName, 0, -5).$sNameSuffix; - $sResult .= ''; + $aList[$sTemplateName] = $sDirName.'/'.$sName; } - - $sResult = \trim($sResult); } - - return $sResult; } /** @@ -277,34 +500,39 @@ class Utils */ public static function GetCookie($sName, $mDefault = null) { - if (null === self::$Cookies) + if (null === \RainLoop\Utils::$Cookies) { - self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); + \RainLoop\Utils::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); } - return isset(self::$Cookies[$sName]) ? self::$Cookies[$sName] : $mDefault; + return isset(\RainLoop\Utils::$Cookies[$sName]) ? \RainLoop\Utils::$Cookies[$sName] : $mDefault; } - public static function SetCookie($sName, $sValue = '', $iExpire = 0, $sPath = '/', $sDomain = '', $sSecure = false, $bHttpOnly = false) + public static function SetCookie($sName, $sValue = '', $iExpire = 0, $sPath = null, $sDomain = null, $sSecure = null, $bHttpOnly = true) { - if (null === self::$Cookies) + if (null === \RainLoop\Utils::$Cookies) { - self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); + \RainLoop\Utils::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); } - self::$Cookies[$sName] = $sValue; + if (null === $sPath) + { + $sPath = \RainLoop\Utils::$CookieDefaultPath; + } + + \RainLoop\Utils::$Cookies[$sName] = $sValue; @\setcookie($sName, $sValue, $iExpire, $sPath, $sDomain, $sSecure, $bHttpOnly); } public static function ClearCookie($sName) { - if (null === self::$Cookies) + if (null === \RainLoop\Utils::$Cookies) { - self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); + \RainLoop\Utils::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); } - unset(self::$Cookies[$sName]); - @\setcookie($sName, '', \time() - 3600 * 24 * 30, '/'); + unset(\RainLoop\Utils::$Cookies[$sName]); + @\setcookie($sName, '', \time() - 3600 * 24 * 30); } /** @@ -313,7 +541,25 @@ class Utils public static function IsOwnCloud() { return isset($_ENV['RAINLOOP_OWNCLOUD']) && $_ENV['RAINLOOP_OWNCLOUD'] && - \class_exists('\\OC'); + \class_exists('OC'); + } + /** + * @return bool + */ + public static function IsOwnCloudLoggedIn() + { + return self::IsOwnCloud() && \class_exists('OCP\User') && \OCP\User::isLoggedIn(); + } + + /** + * @param string $sV + * @param bool $bEncode = false + * + * @return string + */ + public static function UrlEncode($sV, $bEncode = false) + { + return $bEncode ? \urlencode($sV) : $sV; } /** @@ -324,7 +570,7 @@ class Utils $sAppPath = ''; if (\RainLoop\Utils::IsOwnCloud()) { - if (\class_exists('\\OC_App')) + if (\class_exists('OC_App')) { $sAppPath = \rtrim(\trim(\OC_App::getAppWebPath('rainloop')), '\\/').'/app/'; } diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/Backend/AbstractBackend.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/Backend/AbstractBackend.php similarity index 93% rename from rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/Backend/AbstractBackend.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/Backend/AbstractBackend.php index 21f88162b..eab644076 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/Backend/AbstractBackend.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/Backend/AbstractBackend.php @@ -1,9 +1,9 @@ getCalendarObjects($calendarId); - $validator = new \Sabre\CalDAV\CalendarQueryValidator(); + $validator = new \SabreForRainLoop\CalDAV\CalendarQueryValidator(); foreach($objects as $object) { diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/Backend/BackendInterface.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/Backend/BackendInterface.php similarity index 97% rename from rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/Backend/BackendInterface.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/Backend/BackendInterface.php index b8334e5d0..ddfe5d8c0 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/Backend/BackendInterface.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/Backend/BackendInterface.php @@ -1,6 +1,6 @@ getValue()); } @@ -497,7 +497,7 @@ class PDO extends AbstractBackend { } } if (!$componentType) { - throw new \Sabre\DAV\Exception\BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component'); + throw new \SabreForRainLoop\DAV\Exception\BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component'); } if ($componentType === 'VEVENT') { $firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp(); @@ -572,7 +572,7 @@ class PDO extends AbstractBackend { * query. * * The list of filters are specified as an array. The exact array is - * documented by \Sabre\CalDAV\CalendarQueryParser. + * documented by \SabreForRainLoop\CalDAV\CalendarQueryParser. * * Note that it is extremely likely that getCalendarObject for every path * returned from this method will be called almost immediately after. You @@ -601,7 +601,7 @@ class PDO extends AbstractBackend { * time-range filter specified on a VEVENT must for instance also handle * recurrence rules correctly. * A good example of how to interprete all these filters can also simply - * be found in \Sabre\CalDAV\CalendarQueryFilter. This class is as correct + * be found in \SabreForRainLoop\CalDAV\CalendarQueryFilter. This class is as correct * as possible, so it gives you a good idea on what type of stuff you need * to think of. * @@ -615,7 +615,7 @@ class PDO extends AbstractBackend { public function calendarQuery($calendarId, array $filters) { $result = array(); - $validator = new \Sabre\CalDAV\CalendarQueryValidator(); + $validator = new \SabreForRainLoop\CalDAV\CalendarQueryValidator(); $componentType = null; $requirePostFilter = true; diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/Backend/SharingSupport.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/Backend/SharingSupport.php similarity index 96% rename from rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/Backend/SharingSupport.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/Backend/SharingSupport.php index 8fb2b320c..3bfcc145d 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/Backend/SharingSupport.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/Backend/SharingSupport.php @@ -1,6 +1,6 @@ xpath->query('/cal:calendar-query/cal:filter'); if ($filter->length !== 1) { - throw new \Sabre\DAV\Exception\BadRequest('Only one filter element is allowed'); + throw new \SabreForRainLoop\DAV\Exception\BadRequest('Only one filter element is allowed'); } $compFilters = $this->parseCompFilters($filter->item(0)); if (count($compFilters)!==1) { - throw new \Sabre\DAV\Exception\BadRequest('There must be exactly 1 top-level comp-filter.'); + throw new \SabreForRainLoop\DAV\Exception\BadRequest('There must be exactly 1 top-level comp-filter.'); } $this->filters = $compFilters[0]; - $this->requestedProperties = array_keys(\Sabre\DAV\XMLUtil::parseProperties($this->dom->firstChild)); + $this->requestedProperties = array_keys(\SabreForRainLoop\DAV\XMLUtil::parseProperties($this->dom->firstChild)); $expand = $this->xpath->query('/cal:calendar-query/dav:prop/cal:calendar-data/cal:expand'); if ($expand->length>0) { @@ -132,7 +132,7 @@ class CalendarQueryParser { 'VFREEBUSY', 'VALARM', ))) { - throw new \Sabre\DAV\Exception\BadRequest('The time-range filter is not defined for the ' . $compFilter['name'] . ' component'); + throw new \SabreForRainLoop\DAV\Exception\BadRequest('The time-range filter is not defined for the ' . $compFilter['name'] . ' component'); }; $result[] = $compFilter; @@ -253,7 +253,7 @@ class CalendarQueryParser { } if (!is_null($start) && !is_null($end) && $end <= $start) { - throw new \Sabre\DAV\Exception\BadRequest('The end-date must be larger than the start-date in the time-range filter'); + throw new \SabreForRainLoop\DAV\Exception\BadRequest('The end-date must be larger than the start-date in the time-range filter'); } return array( @@ -273,19 +273,19 @@ class CalendarQueryParser { $start = $parentNode->getAttribute('start'); if(!$start) { - throw new \Sabre\DAV\Exception\BadRequest('The "start" attribute is required for the CALDAV:expand element'); + throw new \SabreForRainLoop\DAV\Exception\BadRequest('The "start" attribute is required for the CALDAV:expand element'); } $start = VObject\DateTimeParser::parseDateTime($start); $end = $parentNode->getAttribute('end'); if(!$end) { - throw new \Sabre\DAV\Exception\BadRequest('The "end" attribute is required for the CALDAV:expand element'); + throw new \SabreForRainLoop\DAV\Exception\BadRequest('The "end" attribute is required for the CALDAV:expand element'); } $end = VObject\DateTimeParser::parseDateTime($end); if ($end <= $start) { - throw new \Sabre\DAV\Exception\BadRequest('The end-date must be larger than the start-date in the expand element.'); + throw new \SabreForRainLoop\DAV\Exception\BadRequest('The end-date must be larger than the start-date in the expand element.'); } return array( diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/CalendarQueryValidator.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/CalendarQueryValidator.php similarity index 95% rename from rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/CalendarQueryValidator.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/CalendarQueryValidator.php index fd47127f2..4537d3bf5 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/CalendarQueryValidator.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/CalendarQueryValidator.php @@ -1,8 +1,8 @@ name . ' components'); + throw new \SabreForRainLoop\DAV\Exception\NotImplemented('time-range filters are currently not supported on ' . $component->name . ' components'); case 'COMPLETED' : case 'CREATED' : @@ -383,7 +383,7 @@ class CalendarQueryValidator { default : - throw new \Sabre\DAV\Exception\BadRequest('You cannot create a time-range filter on a ' . $component->name . ' component'); + throw new \SabreForRainLoop\DAV\Exception\BadRequest('You cannot create a time-range filter on a ' . $component->name . ' component'); } diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/CalendarRootNode.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/CalendarRootNode.php similarity index 84% rename from rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/CalendarRootNode.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/CalendarRootNode.php index 5d1ee7780..69e01b1a4 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/CalendarRootNode.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/CalendarRootNode.php @@ -1,8 +1,8 @@ xmlNamespaces[self::NS_CALDAV] = 'cal'; $server->xmlNamespaces[self::NS_CALENDARSERVER] = 'cs'; - $server->propertyMap['{' . self::NS_CALDAV . '}supported-calendar-component-set'] = 'Sabre\\CalDAV\\Property\\SupportedCalendarComponentSet'; - $server->propertyMap['{' . self::NS_CALDAV . '}schedule-calendar-transp'] = 'Sabre\\CalDAV\\Property\\ScheduleCalendarTransp'; + $server->propertyMap['{' . self::NS_CALDAV . '}supported-calendar-component-set'] = 'SabreForRainLoop\\CalDAV\\Property\\SupportedCalendarComponentSet'; + $server->propertyMap['{' . self::NS_CALDAV . '}schedule-calendar-transp'] = 'SabreForRainLoop\\CalDAV\\Property\\ScheduleCalendarTransp'; - $server->resourceTypeMapping['\\Sabre\\CalDAV\\ICalendar'] = '{urn:ietf:params:xml:ns:caldav}calendar'; - $server->resourceTypeMapping['\\Sabre\\CalDAV\\Schedule\\IOutbox'] = '{urn:ietf:params:xml:ns:caldav}schedule-outbox'; - $server->resourceTypeMapping['\\Sabre\\CalDAV\\Principal\\IProxyRead'] = '{http://calendarserver.org/ns/}calendar-proxy-read'; - $server->resourceTypeMapping['\\Sabre\\CalDAV\\Principal\\IProxyWrite'] = '{http://calendarserver.org/ns/}calendar-proxy-write'; - $server->resourceTypeMapping['\\Sabre\\CalDAV\\Notifications\\ICollection'] = '{' . self::NS_CALENDARSERVER . '}notification'; + $server->resourceTypeMapping['\\SabreForRainLoop\\CalDAV\\ICalendar'] = '{urn:ietf:params:xml:ns:caldav}calendar'; + $server->resourceTypeMapping['\\SabreForRainLoop\\CalDAV\\Schedule\\IOutbox'] = '{urn:ietf:params:xml:ns:caldav}schedule-outbox'; + $server->resourceTypeMapping['\\SabreForRainLoop\\CalDAV\\Principal\\IProxyRead'] = '{http://calendarserver.org/ns/}calendar-proxy-read'; + $server->resourceTypeMapping['\\SabreForRainLoop\\CalDAV\\Principal\\IProxyWrite'] = '{http://calendarserver.org/ns/}calendar-proxy-write'; + $server->resourceTypeMapping['\\SabreForRainLoop\\CalDAV\\Notifications\\ICollection'] = '{' . self::NS_CALENDARSERVER . '}notification'; array_push($server->protectedProperties, @@ -286,7 +286,7 @@ class Plugin extends DAV\ServerPlugin { // for clients matching iCal in the user agent //$ua = $this->server->httpRequest->getHeader('User-Agent'); //if (strpos($ua,'iCal/')!==false) { - // throw new \Sabre\DAV\Exception\Forbidden('iCal has major bugs in it\'s RFC3744 support. Therefore we are left with no other choice but disabling this feature.'); + // throw new \SabreForRainLoop\DAV\Exception\Forbidden('iCal has major bugs in it\'s RFC3744 support. Therefore we are left with no other choice but disabling this feature.'); //} $body = $this->server->httpRequest->getBody(true); diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/Principal/Collection.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/Principal/Collection.php similarity index 91% rename from rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/Principal/Collection.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/Principal/Collection.php index 4fc70e265..e4559c878 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/Principal/Collection.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/Principal/Collection.php @@ -1,7 +1,7 @@ server = $server; - $server->resourceTypeMapping['Sabre\\CalDAV\\ISharedCalendar'] = '{' . Plugin::NS_CALENDARSERVER . '}shared'; + $server->resourceTypeMapping['SabreForRainLoop\\CalDAV\\ISharedCalendar'] = '{' . Plugin::NS_CALENDARSERVER . '}shared'; array_push( $this->server->protectedProperties, diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/UserCalendars.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/UserCalendars.php similarity index 97% rename from rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/UserCalendars.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/UserCalendars.php index a3be4fdd3..17f7956f0 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/CalDAV/UserCalendars.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CalDAV/UserCalendars.php @@ -1,9 +1,9 @@ xmlNamespaces[self::NS_CARDDAV] = 'card'; /* Mapping Interfaces to {DAV:}resourcetype values */ - $server->resourceTypeMapping['Sabre\\CardDAV\\IAddressBook'] = '{' . self::NS_CARDDAV . '}addressbook'; - $server->resourceTypeMapping['Sabre\\CardDAV\\IDirectory'] = '{' . self::NS_CARDDAV . '}directory'; + $server->resourceTypeMapping['SabreForRainLoop\\CardDAV\\IAddressBook'] = '{' . self::NS_CARDDAV . '}addressbook'; + $server->resourceTypeMapping['SabreForRainLoop\\CardDAV\\IDirectory'] = '{' . self::NS_CARDDAV . '}directory'; /* Adding properties that may never be changed */ $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}supported-address-data'; @@ -73,7 +73,7 @@ class Plugin extends DAV\ServerPlugin { $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}addressbook-home-set'; $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}supported-collation-set'; - $server->propertyMap['{http://calendarserver.org/ns/}me-card'] = 'Sabre\\DAV\\Property\\Href'; + $server->propertyMap['{http://calendarserver.org/ns/}me-card'] = 'SabreForRainLoop\\DAV\\Property\\Href'; $this->server = $server; @@ -654,7 +654,7 @@ class Plugin extends DAV\ServerPlugin { /** * This method is used to generate HTML output for the - * Sabre\DAV\Browser\Plugin. This allows us to generate an interface users + * SabreForRainLoop\DAV\Browser\Plugin. This allows us to generate an interface users * can use to create new calendars. * * @param DAV\INode $node diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/CardDAV/Property/SupportedAddressData.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CardDAV/Property/SupportedAddressData.php similarity index 94% rename from rainloop/v/0.0.0/app/libraries/Sabre/CardDAV/Property/SupportedAddressData.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CardDAV/Property/SupportedAddressData.php index b2bb6b551..084c06f32 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/CardDAV/Property/SupportedAddressData.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/CardDAV/Property/SupportedAddressData.php @@ -1,9 +1,9 @@ 'icons/file', - 'Sabre\\DAV\\ICollection' => 'icons/collection', - 'Sabre\\DAVACL\\IPrincipal' => 'icons/principal', - 'Sabre\\CalDAV\\ICalendar' => 'icons/calendar', - 'Sabre\\CardDAV\\IAddressBook' => 'icons/addressbook', - 'Sabre\\CardDAV\\ICard' => 'icons/card', + 'SabreForRainLoop\\DAV\\IFile' => 'icons/file', + 'SabreForRainLoop\\DAV\\ICollection' => 'icons/collection', + 'SabreForRainLoop\\DAVACL\\IPrincipal' => 'icons/principal', + 'SabreForRainLoop\\CalDAV\\ICalendar' => 'icons/calendar', + 'SabreForRainLoop\\CardDAV\\IAddressBook' => 'icons/addressbook', + 'SabreForRainLoop\\CardDAV\\ICard' => 'icons/card', ); /** @@ -49,7 +49,7 @@ class Plugin extends DAV\ServerPlugin { /** * reference to server class * - * @var Sabre\DAV\Server + * @var SabreForRainLoop\DAV\Server */ protected $server; @@ -400,7 +400,7 @@ class Plugin extends DAV\ServerPlugin { // We also know fairly certain that if an object is a non-extended // SimpleCollection, we won't need to show the panel either. - if (get_class($node)==='Sabre\\DAV\\SimpleCollection') + if (get_class($node)==='SabreForRainLoop\\DAV\\SimpleCollection') return; $output.= '
diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/favicon.ico b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/favicon.ico similarity index 100% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/favicon.ico rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/favicon.ico diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/addressbook.png b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/addressbook.png similarity index 100% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/addressbook.png rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/addressbook.png diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/calendar.png b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/calendar.png similarity index 100% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/calendar.png rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/calendar.png diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/card.png b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/card.png similarity index 100% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/card.png rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/card.png diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/collection.png b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/collection.png similarity index 100% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/collection.png rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/collection.png diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/file.png b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/file.png similarity index 100% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/file.png rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/file.png diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/parent.png b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/parent.png similarity index 100% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/parent.png rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/parent.png diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/principal.png b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/principal.png similarity index 100% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Browser/assets/icons/principal.png rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Browser/assets/icons/principal.png diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Client.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Client.php similarity index 98% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Client.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Client.php index e2831bf70..8941d74cb 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Client.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Client.php @@ -1,6 +1,6 @@ authType = self::AUTH_BASIC | self::AUTH_DIGEST; } - $this->propertyMap['{DAV:}resourcetype'] = 'Sabre\\DAV\\Property\\ResourceType'; + $this->propertyMap['{DAV:}resourcetype'] = 'SabreForRainLoop\\DAV\\Property\\ResourceType'; } @@ -376,6 +376,9 @@ class Client { $curlSettings[CURLOPT_USERPWD] = $this->userName . ':' . $this->password; } +// var_dump($url); +// var_dump($curlSettings); + list( $response, $curlInfo, @@ -383,9 +386,12 @@ class Client { $curlError ) = $this->curlRequest($url, $curlSettings); +// var_dump($response); + $headerBlob = substr($response, 0, $curlInfo['header_size']); $response = substr($response, $curlInfo['header_size']); + // In the case of 100 Continue, or redirects we'll have multiple lists // of headers for each separate HTTP response. We can easily split this // because they are separated by \r\n\r\n diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Collection.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Collection.php similarity index 95% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Collection.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Collection.php index d8d5265b9..1e070e76c 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Collection.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Collection.php @@ -1,6 +1,6 @@ ownerDocument->createElementNS('DAV:','d:valid-resourcetype'); $errorNode->appendChild($error); diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Exception/LockTokenMatchesRequestUri.php similarity index 93% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Exception/LockTokenMatchesRequestUri.php index a8f8407f0..6fbd28891 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Exception/LockTokenMatchesRequestUri.php @@ -1,8 +1,8 @@ getAllowedMethods($server->getRequestUri()); diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Exception/NotAuthenticated.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Exception/NotAuthenticated.php similarity index 88% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Exception/NotAuthenticated.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Exception/NotAuthenticated.php index 695edda15..99e2ad262 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Exception/NotAuthenticated.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Exception/NotAuthenticated.php @@ -1,8 +1,8 @@ addPlugin($lockPlugin); * * @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/). @@ -30,7 +30,7 @@ class Plugin extends DAV\ServerPlugin { /** * server * - * @var Sabre\DAV\Server + * @var SabreForRainLoop\DAV\Server */ protected $server; @@ -66,7 +66,7 @@ class Plugin extends DAV\ServerPlugin { * Returns a plugin name. * * Using this name other plugins will be able to access other plugins - * using Sabre\DAV\Server::getPlugin + * using SabreForRainLoop\DAV\Server::getPlugin * * @return string */ @@ -216,7 +216,7 @@ class Plugin extends DAV\ServerPlugin { /** * Returns all lock information on a particular uri * - * This function should return an array with Sabre\DAV\Locks\LockInfo objects. If there are no locks on a file, return an empty array. + * This function should return an array with SabreForRainLoop\DAV\Locks\LockInfo objects. If there are no locks on a file, return an empty array. * * Additionally there is also the possibility of locks on parent nodes, so we'll need to traverse every part of the tree * If the $returnChildLocks argument is set to true, we'll also traverse all the children of the object @@ -449,7 +449,7 @@ class Plugin extends DAV\ServerPlugin { * It will check if the requested url is locked, and see if the correct lock tokens are passed * * @param mixed $urls List of relevant urls. Can be an array, a string or nothing at all for the current request uri - * @param mixed $lastLock This variable will be populated with the last checked lock object (Sabre\DAV\Locks\LockInfo) + * @param mixed $lastLock This variable will be populated with the last checked lock object (SabreForRainLoop\DAV\Locks\LockInfo) * @param bool $checkChildLocks If set to true, this function will also look for any locks set on child resources of the supplied urls. This is needed for for example deletion of entire trees. * @return bool */ @@ -614,7 +614,7 @@ class Plugin extends DAV\ServerPlugin { } /** - * Parses a webdav lock xml body, and returns a new Sabre\DAV\Locks\LockInfo object + * Parses a webdav lock xml body, and returns a new SabreForRainLoop\DAV\Locks\LockInfo object * * @param string $body * @return DAV\Locks\LockInfo diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Mount/Plugin.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Mount/Plugin.php similarity index 95% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Mount/Plugin.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Mount/Plugin.php index 669acafc0..4959f012b 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Mount/Plugin.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Mount/Plugin.php @@ -1,8 +1,8 @@ addPlugin($patchPlugin); * * @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/). @@ -23,7 +23,7 @@ class Plugin extends DAV\ServerPlugin { /** * Reference to server * - * @var Sabre\DAV\Server + * @var SabreForRainLoop\DAV\Server */ protected $server; diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Property.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Property.php similarity index 95% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Property.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Property.php index 00f0df3fe..36d4ea694 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Property.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Property.php @@ -1,6 +1,6 @@ responses = $responses; diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Property/SupportedLock.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Property/SupportedLock.php similarity index 96% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/Property/SupportedLock.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Property/SupportedLock.php index e6f477c38..5ddde6478 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/Property/SupportedLock.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/Property/SupportedLock.php @@ -1,8 +1,8 @@ 'Sabre\\DAV\\Property\\ResourceType', + '{DAV:}resourcetype' => 'SabreForRainLoop\\DAV\\Property\\ResourceType', ); public $protectedProperties = array( @@ -131,12 +131,12 @@ class Server { * based on a node's classname or interface. * * The preset ensures that {DAV:}collection is automaticlly added for nodes - * implementing Sabre\DAV\ICollection. + * implementing SabreForRainLoop\DAV\ICollection. * * @var array */ public $resourceTypeMapping = array( - 'Sabre\\DAV\\ICollection' => '{DAV:}collection', + 'SabreForRainLoop\\DAV\\ICollection' => '{DAV:}collection', ); /** @@ -152,12 +152,12 @@ class Server { /** * Sets up the server * - * If a Sabre\DAV\Tree object is passed as an argument, it will - * use it as the directory tree. If a Sabre\DAV\INode is passed, it - * will create a Sabre\DAV\ObjectTree and use the node as the root. + * If a SabreForRainLoop\DAV\Tree object is passed as an argument, it will + * use it as the directory tree. If a SabreForRainLoop\DAV\INode is passed, it + * will create a SabreForRainLoop\DAV\ObjectTree and use the node as the root. * - * If nothing is passed, a Sabre\DAV\SimpleCollection is created in - * a Sabre\DAV\ObjectTree. + * If nothing is passed, a SabreForRainLoop\DAV\SimpleCollection is created in + * a SabreForRainLoop\DAV\ObjectTree. * * If an array is passed, we automatically create a root node, and use * the nodes in the array as top-level children. @@ -176,7 +176,7 @@ class Server { // create the root node. foreach($treeOrNode as $node) { if (!($node instanceof INode)) { - throw new Exception('Invalid argument passed to constructor. If you\'re passing an array, all the values must implement Sabre\\DAV\\INode'); + throw new Exception('Invalid argument passed to constructor. If you\'re passing an array, all the values must implement SabreForRainLoop\\DAV\\INode'); } } @@ -187,7 +187,7 @@ class Server { $root = new SimpleCollection('root'); $this->tree = new ObjectTree($root); } else { - throw new Exception('Invalid argument passed to constructor. Argument must either be an instance of Sabre\\DAV\\Tree, Sabre\\DAV\\INode, an array or null'); + throw new Exception('Invalid argument passed to constructor. Argument must either be an instance of SabreForRainLoop\\DAV\\Tree, SabreForRainLoop\\DAV\\INode, an array or null'); } $this->httpResponse = new HTTP\Response(); $this->httpRequest = new HTTP\Request(); @@ -340,7 +340,7 @@ class Server { /** * Adds a plugin to the server * - * For more information, console the documentation of Sabre\DAV\ServerPlugin + * For more information, console the documentation of SabreForRainLoop\DAV\ServerPlugin * * @param ServerPlugin $plugin * @return void @@ -1157,7 +1157,7 @@ class Server { /** * Returns the HTTP depth header * - * This method returns the contents of the HTTP depth request header. If the depth header was 'infinity' it will return the Sabre\DAV\Server::DEPTH_INFINITY object + * This method returns the contents of the HTTP depth request header. If the depth header was 'infinity' it will return the SabreForRainLoop\DAV\Server::DEPTH_INFINITY object * It is possible to supply a default depth value, which is used when the depth header has invalid content, or is completely non-existent * * @param mixed $default @@ -1820,7 +1820,7 @@ class Server { )); } - // If the node is not an instance of Sabre\DAV\IProperties, every + // If the node is not an instance of SabreForRainLoop\DAV\IProperties, every // property is 403 Forbidden if (!$hasError && count($remainingProperties) && !($node instanceof IProperties)) { $hasError = true; diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/ServerPlugin.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/ServerPlugin.php similarity index 92% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/ServerPlugin.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/ServerPlugin.php index b8396abaf..83cde5756 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/ServerPlugin.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/ServerPlugin.php @@ -1,6 +1,6 @@ name = $name; foreach($children as $child) { - if (!($child instanceof INode)) throw new Exception('Only instances of Sabre\DAV\INode are allowed to be passed in the children argument'); + if (!($child instanceof INode)) throw new Exception('Only instances of SabreForRainLoop\DAV\INode are allowed to be passed in the children argument'); $this->addChild($child); } @@ -78,7 +78,7 @@ class SimpleCollection extends Collection { * This method makes use of the getChildren method to grab all the child nodes, and compares the name. * Generally its wise to override this, as this can usually be optimized * - * This method must throw Sabre\DAV\Exception\NotFound if the node does not + * This method must throw SabreForRainLoop\DAV\Exception\NotFound if the node does not * exist. * * @param string $name diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/SimpleFile.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/SimpleFile.php similarity index 98% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAV/SimpleFile.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/SimpleFile.php index 694207eec..d1b2d7e3a 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/DAV/SimpleFile.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAV/SimpleFile.php @@ -1,6 +1,6 @@ server->getPlugin('auth'); if (is_null($authPlugin)) return null; - /** @var $authPlugin Sabre\DAV\Auth\Plugin */ + /** @var $authPlugin SabreForRainLoop\DAV\Auth\Plugin */ $userName = $authPlugin->getCurrentUser(); if (!$userName) return null; @@ -599,7 +599,7 @@ class Plugin extends DAV\ServerPlugin { * If this is ommitted, the standard * principal collection-set will be used. * @return array This method returns an array structure similar to - * Sabre\DAV\Server::getPropertiesForPath. Returned + * SabreForRainLoop\DAV\Server::getPropertiesForPath. Returned * properties are index by a HTTP status code. * */ @@ -678,11 +678,11 @@ class Plugin extends DAV\ServerPlugin { // Automatically mapping nodes implementing IPrincipal to the // {DAV:}principal resourcetype. - $server->resourceTypeMapping['Sabre\\DAVACL\\IPrincipal'] = '{DAV:}principal'; + $server->resourceTypeMapping['SabreForRainLoop\\DAVACL\\IPrincipal'] = '{DAV:}principal'; // Mapping the group-member-set property to the HrefList property // class. - $server->propertyMap['{DAV:}group-member-set'] = 'Sabre\\DAV\\Property\\HrefList'; + $server->propertyMap['{DAV:}group-member-set'] = 'SabreForRainLoop\\DAV\\Property\\HrefList'; } @@ -965,7 +965,7 @@ class Plugin extends DAV\ServerPlugin { $propertyDelta['{DAV:}group-member-set']->getHrefs() ); } else { - throw new DAV\Exception('The group-member-set property MUST be an instance of Sabre\DAV\Property\HrefList or null'); + throw new DAV\Exception('The group-member-set property MUST be an instance of SabreForRainLoop\DAV\Property\HrefList or null'); } if (!($node instanceof IPrincipal)) { diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/DAVACL/Principal.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAVACL/Principal.php similarity index 96% rename from rainloop/v/0.0.0/app/libraries/Sabre/DAVACL/Principal.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAVACL/Principal.php index 267100212..b2d9e9da5 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/DAVACL/Principal.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/DAVACL/Principal.php @@ -1,8 +1,8 @@ children[] = $property; } } else { - throw new \InvalidArgumentException('You must pass a \\Sabre\\VObject\\Component, \\Sabre\\VObject\\Property or scalar type'); + throw new \InvalidArgumentException('You must pass a \\SabreForRainLoop\\VObject\\Component, \\SabreForRainLoop\\VObject\\Property or scalar type'); } } diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/VObject/Component/VAlarm.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/VObject/Component/VAlarm.php similarity index 98% rename from rainloop/v/0.0.0/app/libraries/Sabre/VObject/Component/VAlarm.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/VObject/Component/VAlarm.php index 2f86c44fd..6951c1996 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/VObject/Component/VAlarm.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/VObject/Component/VAlarm.php @@ -1,7 +1,7 @@ 'Sabre\\VObject\\Component\\VEvent', - 'VFREEBUSY' => 'Sabre\\VObject\\Component\\VFreeBusy', - 'VJOURNAL' => 'Sabre\\VObject\\Component\\VJournal', - 'VTODO' => 'Sabre\\VObject\\Component\\VTodo', - 'VALARM' => 'Sabre\\VObject\\Component\\VAlarm', + 'VEVENT' => 'SabreForRainLoop\\VObject\\Component\\VEvent', + 'VFREEBUSY' => 'SabreForRainLoop\\VObject\\Component\\VFreeBusy', + 'VJOURNAL' => 'SabreForRainLoop\\VObject\\Component\\VJournal', + 'VTODO' => 'SabreForRainLoop\\VObject\\Component\\VTodo', + 'VALARM' => 'SabreForRainLoop\\VObject\\Component\\VAlarm', ); /** @@ -45,21 +45,21 @@ class VCalendar extends VObject\Document { * @var array */ static public $valueMap = array( - 'BINARY' => 'Sabre\\VObject\\Property\\Binary', - 'BOOLEAN' => 'Sabre\\VObject\\Property\\Boolean', - 'CAL-ADDRESS' => 'Sabre\\VObject\\Property\\ICalendar\\CalAddress', - 'DATE' => 'Sabre\\VObject\\Property\\ICalendar\\Date', - 'DATE-TIME' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime', - 'DURATION' => 'Sabre\\VObject\\Property\\ICalendar\\Duration', - 'FLOAT' => 'Sabre\\VObject\\Property\\Float', - 'INTEGER' => 'Sabre\\VObject\\Property\\Integer', - 'PERIOD' => 'Sabre\\VObject\\Property\\ICalendar\\Period', - 'RECUR' => 'Sabre\\VObject\\Property\\ICalendar\\Recur', - 'TEXT' => 'Sabre\\VObject\\Property\\Text', - 'TIME' => 'Sabre\\VObject\\Property\\Time', - 'UNKNOWN' => 'Sabre\\VObject\\Property\\Unknown', // jCard / jCal-only. - 'URI' => 'Sabre\\VObject\\Property\\Uri', - 'UTC-OFFSET' => 'Sabre\\VObject\\Property\\UtcOffset', + 'BINARY' => 'SabreForRainLoop\\VObject\\Property\\Binary', + 'BOOLEAN' => 'SabreForRainLoop\\VObject\\Property\\Boolean', + 'CAL-ADDRESS' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\CalAddress', + 'DATE' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\Date', + 'DATE-TIME' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\DateTime', + 'DURATION' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\Duration', + 'FLOAT' => 'SabreForRainLoop\\VObject\\Property\\Float', + 'INTEGER' => 'SabreForRainLoop\\VObject\\Property\\Integer', + 'PERIOD' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\Period', + 'RECUR' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\Recur', + 'TEXT' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'TIME' => 'SabreForRainLoop\\VObject\\Property\\Time', + 'UNKNOWN' => 'SabreForRainLoop\\VObject\\Property\\Unknown', // jCard / jCal-only. + 'URI' => 'SabreForRainLoop\\VObject\\Property\\Uri', + 'UTC-OFFSET' => 'SabreForRainLoop\\VObject\\Property\\UtcOffset', ); /** @@ -69,75 +69,75 @@ class VCalendar extends VObject\Document { */ static public $propertyMap = array( // Calendar properties - 'CALSCALE' => 'Sabre\\VObject\\Property\\FlatText', - 'METHOD' => 'Sabre\\VObject\\Property\\FlatText', - 'PRODID' => 'Sabre\\VObject\\Property\\FlatText', - 'VERSION' => 'Sabre\\VObject\\Property\\FlatText', + 'CALSCALE' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'METHOD' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'PRODID' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'VERSION' => 'SabreForRainLoop\\VObject\\Property\\FlatText', // Component properties - 'ATTACH' => 'Sabre\\VObject\\Property\\Binary', - 'CATEGORIES' => 'Sabre\\VObject\\Property\\Text', - 'CLASS' => 'Sabre\\VObject\\Property\\FlatText', - 'COMMENT' => 'Sabre\\VObject\\Property\\FlatText', - 'DESCRIPTION' => 'Sabre\\VObject\\Property\\FlatText', - 'GEO' => 'Sabre\\VObject\\Property\\Float', - 'LOCATION' => 'Sabre\\VObject\\Property\\FlatText', - 'PERCENT-COMPLETE' => 'Sabre\\VObject\\Property\\Integer', - 'PRIORITY' => 'Sabre\\VObject\\Property\\Integer', - 'RESOURCES' => 'Sabre\\VObject\\Property\\Text', - 'STATUS' => 'Sabre\\VObject\\Property\\FlatText', - 'SUMMARY' => 'Sabre\\VObject\\Property\\FlatText', + 'ATTACH' => 'SabreForRainLoop\\VObject\\Property\\Binary', + 'CATEGORIES' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'CLASS' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'COMMENT' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'DESCRIPTION' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'GEO' => 'SabreForRainLoop\\VObject\\Property\\Float', + 'LOCATION' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'PERCENT-COMPLETE' => 'SabreForRainLoop\\VObject\\Property\\Integer', + 'PRIORITY' => 'SabreForRainLoop\\VObject\\Property\\Integer', + 'RESOURCES' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'STATUS' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'SUMMARY' => 'SabreForRainLoop\\VObject\\Property\\FlatText', // Date and Time Component Properties - 'COMPLETED' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime', - 'DTEND' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime', - 'DUE' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime', - 'DTSTART' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime', - 'DURATION' => 'Sabre\\VObject\\Property\\ICalendar\\Duration', - 'FREEBUSY' => 'Sabre\\VObject\\Property\\ICalendar\\Period', - 'TRANSP' => 'Sabre\\VObject\\Property\\FlatText', + 'COMPLETED' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\DateTime', + 'DTEND' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\DateTime', + 'DUE' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\DateTime', + 'DTSTART' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\DateTime', + 'DURATION' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\Duration', + 'FREEBUSY' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\Period', + 'TRANSP' => 'SabreForRainLoop\\VObject\\Property\\FlatText', // Time Zone Component Properties - 'TZID' => 'Sabre\\VObject\\Property\\FlatText', - 'TZNAME' => 'Sabre\\VObject\\Property\\FlatText', - 'TZOFFSETFROM' => 'Sabre\\VObject\\Property\\UtcOffset', - 'TZOFFSETTO' => 'Sabre\\VObject\\Property\\UtcOffset', - 'TZURL' => 'Sabre\\VObject\\Property\\Uri', + 'TZID' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'TZNAME' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'TZOFFSETFROM' => 'SabreForRainLoop\\VObject\\Property\\UtcOffset', + 'TZOFFSETTO' => 'SabreForRainLoop\\VObject\\Property\\UtcOffset', + 'TZURL' => 'SabreForRainLoop\\VObject\\Property\\Uri', // Relationship Component Properties - 'ATTENDEE' => 'Sabre\\VObject\\Property\\ICalendar\\CalAddress', - 'CONTACT' => 'Sabre\\VObject\\Property\\FlatText', - 'ORGANIZER' => 'Sabre\\VObject\\Property\\ICalendar\\CalAddress', - 'RECURRENCE-ID' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime', - 'RELATED-TO' => 'Sabre\\VObject\\Property\\FlatText', - 'URL' => 'Sabre\\VObject\\Property\\Uri', - 'UID' => 'Sabre\\VObject\\Property\\FlatText', + 'ATTENDEE' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\CalAddress', + 'CONTACT' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'ORGANIZER' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\CalAddress', + 'RECURRENCE-ID' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\DateTime', + 'RELATED-TO' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'URL' => 'SabreForRainLoop\\VObject\\Property\\Uri', + 'UID' => 'SabreForRainLoop\\VObject\\Property\\FlatText', // Recurrence Component Properties - 'EXDATE' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime', - 'RDATE' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime', - 'RRULE' => 'Sabre\\VObject\\Property\\ICalendar\\Recur', - 'EXRULE' => 'Sabre\\VObject\\Property\\ICalendar\\Recur', // Deprecated since rfc5545 + 'EXDATE' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\DateTime', + 'RDATE' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\DateTime', + 'RRULE' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\Recur', + 'EXRULE' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\Recur', // Deprecated since rfc5545 // Alarm Component Properties - 'ACTION' => 'Sabre\\VObject\\Property\\FlatText', - 'REPEAT' => 'Sabre\\VObject\\Property\\Integer', - 'TRIGGER' => 'Sabre\\VObject\\Property\\ICalendar\\Duration', + 'ACTION' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'REPEAT' => 'SabreForRainLoop\\VObject\\Property\\Integer', + 'TRIGGER' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\Duration', // Change Management Component Properties - 'CREATED' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime', - 'DTSTAMP' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime', - 'LAST-MODIFIED' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime', - 'SEQUENCE' => 'Sabre\\VObject\\Property\\Integer', + 'CREATED' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\DateTime', + 'DTSTAMP' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\DateTime', + 'LAST-MODIFIED' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\DateTime', + 'SEQUENCE' => 'SabreForRainLoop\\VObject\\Property\\Integer', // Request Status - 'REQUEST-STATUS' => 'Sabre\\VObject\\Property\\Text', + 'REQUEST-STATUS' => 'SabreForRainLoop\\VObject\\Property\\Text', // Additions from draft-daboo-valarm-extensions-04 - 'ALARM-AGENT' => 'Sabre\\VObject\\Property\\Text', - 'ACKNOWLEDGED' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime', - 'PROXIMITY' => 'Sabre\\VObject\\Property\\Text', - 'DEFAULT-ALARM' => 'Sabre\\VObject\\Property\\Boolean', + 'ALARM-AGENT' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'ACKNOWLEDGED' => 'SabreForRainLoop\\VObject\\Property\\ICalendar\\DateTime', + 'PROXIMITY' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'DEFAULT-ALARM' => 'SabreForRainLoop\\VObject\\Property\\Boolean', ); diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/VObject/Component/VCard.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/VObject/Component/VCard.php similarity index 63% rename from rainloop/v/0.0.0/app/libraries/Sabre/VObject/Component/VCard.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/VObject/Component/VCard.php index 69eb8d4c1..e44ac3f1f 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/VObject/Component/VCard.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/VObject/Component/VCard.php @@ -1,9 +1,9 @@ 'Sabre\\VObject\\Property\\Binary', - 'BOOLEAN' => 'Sabre\\VObject\\Property\\Boolean', - 'CONTENT-ID' => 'Sabre\\VObject\\Property\\FlatText', // vCard 2.1 only - 'DATE' => 'Sabre\\VObject\\Property\\VCard\\Date', - 'DATE-TIME' => 'Sabre\\VObject\\Property\\VCard\\DateTime', - 'DATE-AND-OR-TIME' => 'Sabre\\VObject\\Property\\VCard\\DateAndOrTime', // vCard only - 'FLOAT' => 'Sabre\\VObject\\Property\\Float', - 'INTEGER' => 'Sabre\\VObject\\Property\\Integer', - 'LANGUAGE-TAG' => 'Sabre\\VObject\\Property\\VCard\\LanguageTag', - 'TIMESTAMP' => 'Sabre\\VObject\\Property\\VCard\\TimeStamp', - 'TEXT' => 'Sabre\\VObject\\Property\\Text', - 'TIME' => 'Sabre\\VObject\\Property\\Time', - 'UNKNOWN' => 'Sabre\\VObject\\Property\\Unknown', // jCard / jCal-only. - 'URI' => 'Sabre\\VObject\\Property\\Uri', - 'URL' => 'Sabre\\VObject\\Property\\Uri', // vCard 2.1 only - 'UTC-OFFSET' => 'Sabre\\VObject\\Property\\UtcOffset', + 'BINARY' => 'SabreForRainLoop\\VObject\\Property\\Binary', + 'BOOLEAN' => 'SabreForRainLoop\\VObject\\Property\\Boolean', + 'CONTENT-ID' => 'SabreForRainLoop\\VObject\\Property\\FlatText', // vCard 2.1 only + 'DATE' => 'SabreForRainLoop\\VObject\\Property\\VCard\\Date', + 'DATE-TIME' => 'SabreForRainLoop\\VObject\\Property\\VCard\\DateTime', + 'DATE-AND-OR-TIME' => 'SabreForRainLoop\\VObject\\Property\\VCard\\DateAndOrTime', // vCard only + 'FLOAT' => 'SabreForRainLoop\\VObject\\Property\\Float', + 'INTEGER' => 'SabreForRainLoop\\VObject\\Property\\Integer', + 'LANGUAGE-TAG' => 'SabreForRainLoop\\VObject\\Property\\VCard\\LanguageTag', + 'TIMESTAMP' => 'SabreForRainLoop\\VObject\\Property\\VCard\\TimeStamp', + 'TEXT' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'TIME' => 'SabreForRainLoop\\VObject\\Property\\Time', + 'UNKNOWN' => 'SabreForRainLoop\\VObject\\Property\\Unknown', // jCard / jCal-only. + 'URI' => 'SabreForRainLoop\\VObject\\Property\\Uri', + 'URL' => 'SabreForRainLoop\\VObject\\Property\\Uri', // vCard 2.1 only + 'UTC-OFFSET' => 'SabreForRainLoop\\VObject\\Property\\UtcOffset', ); /** @@ -65,53 +65,53 @@ class VCard extends VObject\Document { static public $propertyMap = array( // vCard 2.1 properties and up - 'N' => 'Sabre\\VObject\\Property\\Text', - 'FN' => 'Sabre\\VObject\\Property\\FlatText', - 'PHOTO' => 'Sabre\\VObject\\Property\\Binary', // Todo: we should add a class for Binary values. - 'BDAY' => 'Sabre\\VObject\\Property\\VCard\\DateAndOrTime', - 'ADR' => 'Sabre\\VObject\\Property\\Text', - 'LABEL' => 'Sabre\\VObject\\Property\\FlatText', // Removed in vCard 4.0 - 'TEL' => 'Sabre\\VObject\\Property\\FlatText', - 'EMAIL' => 'Sabre\\VObject\\Property\\FlatText', - 'MAILER' => 'Sabre\\VObject\\Property\\FlatText', // Removed in vCard 4.0 - 'GEO' => 'Sabre\\VObject\\Property\\FlatText', - 'TITLE' => 'Sabre\\VObject\\Property\\FlatText', - 'ROLE' => 'Sabre\\VObject\\Property\\FlatText', - 'LOGO' => 'Sabre\\VObject\\Property\\Binary', - // 'AGENT' => 'Sabre\\VObject\\Property\\', // Todo: is an embedded vCard. Probably rare, so + 'N' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'FN' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'PHOTO' => 'SabreForRainLoop\\VObject\\Property\\Binary', // Todo: we should add a class for Binary values. + 'BDAY' => 'SabreForRainLoop\\VObject\\Property\\VCard\\DateAndOrTime', + 'ADR' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'LABEL' => 'SabreForRainLoop\\VObject\\Property\\FlatText', // Removed in vCard 4.0 + 'TEL' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'EMAIL' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'MAILER' => 'SabreForRainLoop\\VObject\\Property\\FlatText', // Removed in vCard 4.0 + 'GEO' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'TITLE' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'ROLE' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'LOGO' => 'SabreForRainLoop\\VObject\\Property\\Binary', + // 'AGENT' => 'SabreForRainLoop\\VObject\\Property\\', // Todo: is an embedded vCard. Probably rare, so // not supported at the moment - 'ORG' => 'Sabre\\VObject\\Property\\Text', - 'NOTE' => 'Sabre\\VObject\\Property\\FlatText', - 'REV' => 'Sabre\\VObject\\Property\\VCard\\TimeStamp', - 'SOUND' => 'Sabre\\VObject\\Property\\FlatText', - 'URL' => 'Sabre\\VObject\\Property\\Uri', - 'UID' => 'Sabre\\VObject\\Property\\FlatText', - 'VERSION' => 'Sabre\\VObject\\Property\\FlatText', - 'KEY' => 'Sabre\\VObject\\Property\\FlatText', - 'TZ' => 'Sabre\\VObject\\Property\\Text', + 'ORG' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'NOTE' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'REV' => 'SabreForRainLoop\\VObject\\Property\\VCard\\TimeStamp', + 'SOUND' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'URL' => 'SabreForRainLoop\\VObject\\Property\\Uri', + 'UID' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'VERSION' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'KEY' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'TZ' => 'SabreForRainLoop\\VObject\\Property\\Text', // vCard 3.0 properties - 'CATEGORIES' => 'Sabre\\VObject\\Property\\Text', - 'SORT-STRING' => 'Sabre\\VObject\\Property\\FlatText', - 'PRODID' => 'Sabre\\VObject\\Property\\FlatText', - 'NICKNAME' => 'Sabre\\VObject\\Property\\Text', - 'CLASS' => 'Sabre\\VObject\\Property\\FlatText', // Removed in vCard 4.0 + 'CATEGORIES' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'SORT-STRING' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'PRODID' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'NICKNAME' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'CLASS' => 'SabreForRainLoop\\VObject\\Property\\FlatText', // Removed in vCard 4.0 // rfc2739 properties - 'FBURL' => 'Sabre\\VObject\\Property\\Uri', - 'CAPURI' => 'Sabre\\VObject\\Property\\Uri', - 'CALURI' => 'Sabre\\VObject\\Property\\Uri', + 'FBURL' => 'SabreForRainLoop\\VObject\\Property\\Uri', + 'CAPURI' => 'SabreForRainLoop\\VObject\\Property\\Uri', + 'CALURI' => 'SabreForRainLoop\\VObject\\Property\\Uri', // rfc4770 properties - 'IMPP' => 'Sabre\\VObject\\Property\\Uri', + 'IMPP' => 'SabreForRainLoop\\VObject\\Property\\Uri', // vCard 4.0 properties - 'XML' => 'Sabre\\VObject\\Property\\FlatText', - 'ANNIVERSARY' => 'Sabre\\VObject\\Property\\VCard\\DateAndOrTime', - 'CLIENTPIDMAP' => 'Sabre\\VObject\\Property\\Text', - 'LANG' => 'Sabre\\VObject\\Property\\VCard\\LanguageTag', - 'GENDER' => 'Sabre\\VObject\\Property\\Text', - 'KIND' => 'Sabre\\VObject\\Property\\FlatText', + 'XML' => 'SabreForRainLoop\\VObject\\Property\\FlatText', + 'ANNIVERSARY' => 'SabreForRainLoop\\VObject\\Property\\VCard\\DateAndOrTime', + 'CLIENTPIDMAP' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'LANG' => 'SabreForRainLoop\\VObject\\Property\\VCard\\LanguageTag', + 'GENDER' => 'SabreForRainLoop\\VObject\\Property\\Text', + 'KIND' => 'SabreForRainLoop\\VObject\\Property\\FlatText', ); @@ -342,8 +342,8 @@ class VCard extends VObject\Document { $className = parent::getClassNameForPropertyName($propertyName); // In vCard 4, BINARY no longer exists, and we need URI instead. - if ($className == 'Sabre\\VObject\\Property\\Binary' && $this->getDocumentType()===self::VCARD40) { - return 'Sabre\\VObject\\Property\\Uri'; + if ($className == 'SabreForRainLoop\\VObject\\Property\\Binary' && $this->getDocumentType()===self::VCARD40) { + return 'SabreForRainLoop\\VObject\\Property\\Uri'; } return $className; diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/VObject/Component/VEvent.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/VObject/Component/VEvent.php similarity index 96% rename from rainloop/v/0.0.0/app/libraries/Sabre/VObject/Component/VEvent.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/VObject/Component/VEvent.php index 0ce204566..b1dc19331 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/VObject/Component/VEvent.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/VObject/Component/VEvent.php @@ -1,7 +1,7 @@ objects[] = $object; } else { - throw new \InvalidArgumentException('You can only pass strings or \\Sabre\\VObject\\Component arguments to setObjects'); + throw new \InvalidArgumentException('You can only pass strings or \\SabreForRainLoop\\VObject\\Component arguments to setObjects'); } } diff --git a/rainloop/v/0.0.0/app/libraries/Sabre/VObject/Node.php b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/VObject/Node.php similarity index 99% rename from rainloop/v/0.0.0/app/libraries/Sabre/VObject/Node.php rename to rainloop/v/0.0.0/app/libraries/SabreForRainLoop/VObject/Node.php index 3260a8c02..3330fceff 100644 --- a/rainloop/v/0.0.0/app/libraries/Sabre/VObject/Node.php +++ b/rainloop/v/0.0.0/app/libraries/SabreForRainLoop/VObject/Node.php @@ -1,6 +1,6 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * Exception interface for all exceptions thrown by the component. - * - * @author Romain Neutron - * - * @api - */ -interface ExceptionInterface -{ -} diff --git a/rainloop/v/0.0.0/app/libraries/Symfony/Component/Filesystem/Exception/FileNotFoundException.php b/rainloop/v/0.0.0/app/libraries/Symfony/Component/Filesystem/Exception/FileNotFoundException.php deleted file mode 100644 index 15533db40..000000000 --- a/rainloop/v/0.0.0/app/libraries/Symfony/Component/Filesystem/Exception/FileNotFoundException.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * Exception class thrown when a file couldn't be found - * - * @author Fabien Potencier - * @author Christian Gärtner - */ -class FileNotFoundException extends IOException -{ - public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null) - { - if (null === $message) { - if (null === $path) { - $message = 'File could not be found.'; - } else { - $message = sprintf('File "%s" could not be found.', $path); - } - } - - parent::__construct($message, $code, $previous, $path); - } -} diff --git a/rainloop/v/0.0.0/app/libraries/Symfony/Component/Filesystem/Exception/IOException.php b/rainloop/v/0.0.0/app/libraries/Symfony/Component/Filesystem/Exception/IOException.php deleted file mode 100644 index 4b551af71..000000000 --- a/rainloop/v/0.0.0/app/libraries/Symfony/Component/Filesystem/Exception/IOException.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * Exception class thrown when a filesystem operation failure happens - * - * @author Romain Neutron - * @author Christian Gärtner - * @author Fabien Potencier - * - * @api - */ -class IOException extends \RuntimeException implements IOExceptionInterface -{ - private $path; - - public function __construct($message, $code = 0, \Exception $previous = null, $path = null) - { - $this->path = $path; - - parent::__construct($message, $code, $previous); - } - - /** - * {@inheritdoc} - */ - public function getPath() - { - return $this->path; - } -} diff --git a/rainloop/v/0.0.0/app/libraries/Symfony/Component/Filesystem/Exception/IOExceptionInterface.php b/rainloop/v/0.0.0/app/libraries/Symfony/Component/Filesystem/Exception/IOExceptionInterface.php deleted file mode 100644 index de9f3e714..000000000 --- a/rainloop/v/0.0.0/app/libraries/Symfony/Component/Filesystem/Exception/IOExceptionInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * IOException interface for file and input/output stream releated exceptions thrown by the component. - * - * @author Christian Gärtner - */ -interface IOExceptionInterface extends ExceptionInterface -{ - /** - * Returns the associated path for the exception - * - * @return string The path. - */ - public function getPath(); -} diff --git a/rainloop/v/0.0.0/app/libraries/Symfony/Component/Filesystem/Filesystem.php b/rainloop/v/0.0.0/app/libraries/Symfony/Component/Filesystem/Filesystem.php deleted file mode 100644 index 9e45d2ba3..000000000 --- a/rainloop/v/0.0.0/app/libraries/Symfony/Component/Filesystem/Filesystem.php +++ /dev/null @@ -1,474 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem; - -use Symfony\Component\Filesystem\Exception\IOException; -use Symfony\Component\Filesystem\Exception\FileNotFoundException; - -/** - * Provides basic utility to manipulate the file system. - * - * @author Fabien Potencier - */ -class Filesystem -{ - /** - * Copies a file. - * - * This method only copies the file if the origin file is newer than the target file. - * - * By default, if the target already exists, it is not overridden. - * - * @param string $originFile The original filename - * @param string $targetFile The target filename - * @param boolean $override Whether to override an existing file or not - * - * @throws FileNotFoundException When orginFile doesn't exist - * @throws IOException When copy fails - */ - public function copy($originFile, $targetFile, $override = false) - { - if (stream_is_local($originFile) && !is_file($originFile)) { - throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile); - } - - $this->mkdir(dirname($targetFile)); - - if (!$override && is_file($targetFile)) { - $doCopy = filemtime($originFile) > filemtime($targetFile); - } else { - $doCopy = true; - } - - if ($doCopy) { - // https://bugs.php.net/bug.php?id=64634 - $source = fopen($originFile, 'r'); - $target = fopen($targetFile, 'w+'); - stream_copy_to_stream($source, $target); - fclose($source); - fclose($target); - unset($source, $target); - - if (!is_file($targetFile)) { - throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile); - } - } - } - - /** - * Creates a directory recursively. - * - * @param string|array|\Traversable $dirs The directory path - * @param integer $mode The directory mode - * - * @throws IOException On any directory creation failure - */ - public function mkdir($dirs, $mode = 0777) - { - foreach ($this->toIterator($dirs) as $dir) { - if (is_dir($dir)) { - continue; - } - - if (true !== @mkdir($dir, $mode, true)) { - throw new IOException(sprintf('Failed to create "%s".', $dir), 0, null, $dir); - } - } - } - - /** - * Checks the existence of files or directories. - * - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to check - * - * @return Boolean true if the file exists, false otherwise - */ - public function exists($files) - { - foreach ($this->toIterator($files) as $file) { - if (!file_exists($file)) { - return false; - } - } - - return true; - } - - /** - * Sets access and modification time of file. - * - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create - * @param integer $time The touch time as a unix timestamp - * @param integer $atime The access time as a unix timestamp - * - * @throws IOException When touch fails - */ - public function touch($files, $time = null, $atime = null) - { - foreach ($this->toIterator($files) as $file) { - $touch = $time ? @touch($file, $time, $atime) : @touch($file); - if (true !== $touch) { - throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file); - } - } - } - - /** - * Removes files or directories. - * - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove - * - * @throws IOException When removal fails - */ - public function remove($files) - { - $files = iterator_to_array($this->toIterator($files)); - $files = array_reverse($files); - foreach ($files as $file) { - if (!file_exists($file) && !is_link($file)) { - continue; - } - - if (is_dir($file) && !is_link($file)) { - $this->remove(new \FilesystemIterator($file)); - - if (true !== @rmdir($file)) { - throw new IOException(sprintf('Failed to remove directory "%s".', $file), 0, null, $file); - } - } else { - // https://bugs.php.net/bug.php?id=52176 - if (defined('PHP_WINDOWS_VERSION_MAJOR') && is_dir($file)) { - if (true !== @rmdir($file)) { - throw new IOException(sprintf('Failed to remove file "%s".', $file), 0, null, $file); - } - } else { - if (true !== @unlink($file)) { - throw new IOException(sprintf('Failed to remove file "%s".', $file), 0, null, $file); - } - } - } - } - } - - /** - * Change mode for an array of files or directories. - * - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change mode - * @param integer $mode The new mode (octal) - * @param integer $umask The mode mask (octal) - * @param Boolean $recursive Whether change the mod recursively or not - * - * @throws IOException When the change fail - */ - public function chmod($files, $mode, $umask = 0000, $recursive = false) - { - foreach ($this->toIterator($files) as $file) { - if ($recursive && is_dir($file) && !is_link($file)) { - $this->chmod(new \FilesystemIterator($file), $mode, $umask, true); - } - if (true !== @chmod($file, $mode & ~$umask)) { - throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file); - } - } - } - - /** - * Change the owner of an array of files or directories - * - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change owner - * @param string $user The new owner user name - * @param Boolean $recursive Whether change the owner recursively or not - * - * @throws IOException When the change fail - */ - public function chown($files, $user, $recursive = false) - { - foreach ($this->toIterator($files) as $file) { - if ($recursive && is_dir($file) && !is_link($file)) { - $this->chown(new \FilesystemIterator($file), $user, true); - } - if (is_link($file) && function_exists('lchown')) { - if (true !== @lchown($file, $user)) { - throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file); - } - } else { - if (true !== @chown($file, $user)) { - throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file); - } - } - } - } - - /** - * Change the group of an array of files or directories - * - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change group - * @param string $group The group name - * @param Boolean $recursive Whether change the group recursively or not - * - * @throws IOException When the change fail - */ - public function chgrp($files, $group, $recursive = false) - { - foreach ($this->toIterator($files) as $file) { - if ($recursive && is_dir($file) && !is_link($file)) { - $this->chgrp(new \FilesystemIterator($file), $group, true); - } - if (is_link($file) && function_exists('lchgrp')) { - if (true !== @lchgrp($file, $group)) { - throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); - } - } else { - if (true !== @chgrp($file, $group)) { - throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); - } - } - } - } - - /** - * Renames a file or a directory. - * - * @param string $origin The origin filename or directory - * @param string $target The new filename or directory - * @param Boolean $overwrite Whether to overwrite the target if it already exists - * - * @throws IOException When target file or directory already exists - * @throws IOException When origin cannot be renamed - */ - public function rename($origin, $target, $overwrite = false) - { - // we check that target does not exist - if (!$overwrite && is_readable($target)) { - throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target); - } - - if (true !== @rename($origin, $target)) { - throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target); - } - } - - /** - * Creates a symbolic link or copy a directory. - * - * @param string $originDir The origin directory path - * @param string $targetDir The symbolic link name - * @param Boolean $copyOnWindows Whether to copy files if on Windows - * - * @throws IOException When symlink fails - */ - public function symlink($originDir, $targetDir, $copyOnWindows = false) - { - if (!function_exists('symlink') && $copyOnWindows) { - $this->mirror($originDir, $targetDir); - - return; - } - - $this->mkdir(dirname($targetDir)); - - $ok = false; - if (is_link($targetDir)) { - if (readlink($targetDir) != $originDir) { - $this->remove($targetDir); - } else { - $ok = true; - } - } - - if (!$ok) { - if (true !== @symlink($originDir, $targetDir)) { - $report = error_get_last(); - if (is_array($report)) { - if (defined('PHP_WINDOWS_VERSION_MAJOR') && false !== strpos($report['message'], 'error code(1314)')) { - throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?'); - } - } - - throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir); - } - } - } - - /** - * Given an existing path, convert it to a path relative to a given starting path - * - * @param string $endPath Absolute path of target - * @param string $startPath Absolute path where traversal begins - * - * @return string Path of target relative to starting path - */ - public function makePathRelative($endPath, $startPath) - { - // Normalize separators on windows - if (defined('PHP_WINDOWS_VERSION_MAJOR')) { - $endPath = strtr($endPath, '\\', '/'); - $startPath = strtr($startPath, '\\', '/'); - } - - // Split the paths into arrays - $startPathArr = explode('/', trim($startPath, '/')); - $endPathArr = explode('/', trim($endPath, '/')); - - // Find for which directory the common path stops - $index = 0; - while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) { - $index++; - } - - // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels) - $depth = count($startPathArr) - $index; - - // Repeated "../" for each level need to reach the common path - $traverser = str_repeat('../', $depth); - - $endPathRemainder = implode('/', array_slice($endPathArr, $index)); - - // Construct $endPath from traversing to the common path, then to the remaining $endPath - $relativePath = $traverser.(strlen($endPathRemainder) > 0 ? $endPathRemainder.'/' : ''); - - return (strlen($relativePath) === 0) ? './' : $relativePath; - } - - /** - * Mirrors a directory to another. - * - * @param string $originDir The origin directory - * @param string $targetDir The target directory - * @param \Traversable $iterator A Traversable instance - * @param array $options An array of boolean options - * Valid options are: - * - $options['override'] Whether to override an existing file on copy or not (see copy()) - * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink()) - * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) - * - * @throws IOException When file type is unknown - */ - public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array()) - { - $targetDir = rtrim($targetDir, '/\\'); - $originDir = rtrim($originDir, '/\\'); - - // Iterate in destination folder to remove obsolete entries - if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) { - $deleteIterator = $iterator; - if (null === $deleteIterator) { - $flags = \FilesystemIterator::SKIP_DOTS; - $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST); - } - foreach ($deleteIterator as $file) { - $origin = str_replace($targetDir, $originDir, $file->getPathname()); - if (!$this->exists($origin)) { - $this->remove($file); - } - } - } - - $copyOnWindows = false; - if (isset($options['copy_on_windows']) && !function_exists('symlink')) { - $copyOnWindows = $options['copy_on_windows']; - } - - if (null === $iterator) { - $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS; - $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST); - } - - foreach ($iterator as $file) { - $target = str_replace($originDir, $targetDir, $file->getPathname()); - - if ($copyOnWindows) { - if (is_link($file) || is_file($file)) { - $this->copy($file, $target, isset($options['override']) ? $options['override'] : false); - } elseif (is_dir($file)) { - $this->mkdir($target); - } else { - throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file); - } - } else { - if (is_link($file)) { - $this->symlink($file, $target); - } elseif (is_dir($file)) { - $this->mkdir($target); - } elseif (is_file($file)) { - $this->copy($file, $target, isset($options['override']) ? $options['override'] : false); - } else { - throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file); - } - } - } - } - - /** - * Returns whether the file path is an absolute path. - * - * @param string $file A file path - * - * @return Boolean - */ - public function isAbsolutePath($file) - { - if (strspn($file, '/\\', 0, 1) - || (strlen($file) > 3 && ctype_alpha($file[0]) - && substr($file, 1, 1) === ':' - && (strspn($file, '/\\', 2, 1)) - ) - || null !== parse_url($file, PHP_URL_SCHEME) - ) { - return true; - } - - return false; - } - - /** - * Atomically dumps content into a file. - * - * @param string $filename The file to be written to. - * @param string $content The data to write into the file. - * @param integer $mode The file mode (octal). - * @throws IOException If the file cannot be written to. - */ - public function dumpFile($filename, $content, $mode = 0666) - { - $dir = dirname($filename); - - if (!is_dir($dir)) { - $this->mkdir($dir); - } elseif (!is_writable($dir)) { - throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir); - } - - $tmpFile = tempnam($dir, basename($filename)); - - if (false === @file_put_contents($tmpFile, $content)) { - throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); - } - - $this->rename($tmpFile, $filename, true); - $this->chmod($filename, $mode); - } - - /** - * @param mixed $files - * - * @return \Traversable - */ - private function toIterator($files) - { - if (!$files instanceof \Traversable) { - $files = new \ArrayObject(is_array($files) ? $files : array($files)); - } - - return $files; - } -} diff --git a/rainloop/v/0.0.0/app/libraries/emogrifier/CHANGELOG.TXT b/rainloop/v/0.0.0/app/libraries/emogrifier/CHANGELOG.TXT new file mode 100644 index 000000000..55c062e72 --- /dev/null +++ b/rainloop/v/0.0.0/app/libraries/emogrifier/CHANGELOG.TXT @@ -0,0 +1,73 @@ +2012-05-01 +Made removal of invisible nodes operate in a case-insensitive manner... Thanks Juha P.! + +2012-02-07 +Fixed some recent code introductions to use class constants rather than global constants. +Fixed some recent code introductions to make it cleaner to read. + +2012-01-31 +Fixed a bug that was introduced with the 2011-12-22 revision... Thanks Sagi L. and M. Bąkowski! +Added extraction of @@ -89,7 +90,10 @@ if (window.$LAB && window.rainloopAppData && window.rainloopAppData['TemplatesLink'] && window.rainloopAppData['LangLink']) { - __simplePace(10); + var oProgress = progressJs(); + + oProgress.setOptions({'theme': 'rainloop'}); + oProgress.start().set(5); window.$LAB .script(function () { @@ -98,7 +102,9 @@ ]; }) .wait(function () { - __simplePace(20); + + oProgress.set(20); + if (window.rainloopAppData['IncludeBackground']) { $('#rl-bg').attr('style', 'background-image: none !important;').backstretch( window.rainloopAppData['IncludeBackground'].replace('{{USER}}', @@ -114,20 +120,20 @@ ]; }) .wait(function () { - __simplePace(10); + oProgress.set(30); }) .script(function () { return {'src': '{{BaseAppMainScriptLink}}', 'type': 'text/javascript', 'charset': 'utf-8'}; }) .wait(function () { - __simplePace(20); + oProgress.set(50); }) .script(function () { return window.rainloopAppData['PluginsLink'] ? {'src': window.rainloopAppData['PluginsLink'], 'type': 'text/javascript', 'charset': 'utf-8'} : null; }) .wait(function () { - __simplePace(5); + oProgress.set(55); __runBoot(false); }) .script(function () { diff --git a/rainloop/v/0.0.0/app/templates/Themes/template.less b/rainloop/v/0.0.0/app/templates/Themes/template.less index d9e69c07a..570df86a5 100644 --- a/rainloop/v/0.0.0/app/templates/Themes/template.less +++ b/rainloop/v/0.0.0/app/templates/Themes/template.less @@ -59,14 +59,17 @@ } .thm-login { - color: @login-color !important; border: @login-border !important; .thm-rgba-background-color(@login-background-color, @login-rgba-background-color); .thm-linear-gradient-mixin(@login-gradient-start, @login-gradient-end); .thm-border-radius(@login-border-radius); .thm-box-shadow(@login-box-shadow); +} - .legend, .checkboxSignMe, .checkboxAdditionalCodeSignMe, .g-ui-link, .social-button, .language-button { +.thm-login-text { + color: @login-color !important; + + .legend, .e-checkbox-icon, .g-ui-link, .social-button, .language-button { color: @login-color !important; } } @@ -85,7 +88,7 @@ color: @languages-color; .flag-name { color: @languages-color; - border-bottom: 1px dashed @languages-color; + border-color: @languages-color; } } diff --git a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminLogin.html b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminLogin.html index 1dc30c7c2..40a343a09 100644 --- a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminLogin.html +++ b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminLogin.html @@ -5,7 +5,7 @@
- +
- Powered by RainLoop + Powered by RainLoop
diff --git a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminPane.html b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminPane.html index 2edd2e437..9c0845f63 100644 --- a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminPane.html +++ b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminPane.html @@ -5,11 +5,11 @@    RainLoop - () + ()    - () + ()
diff --git a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsAbout.html b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsAbout.html index 609f9000d..d4586d32e 100644 --- a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsAbout.html +++ b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsAbout.html @@ -4,10 +4,10 @@
-
@@ -19,7 +19,7 @@

-
+
   diff --git a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsBranding.html b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsBranding.html index 378b1cda3..23d724312 100644 --- a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsBranding.html +++ b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsBranding.html @@ -29,7 +29,7 @@

-
-
 
-
+
 
+
-
 
-
+
+ +
+
\ No newline at end of file diff --git a/rainloop/v/0.0.0/include.php b/rainloop/v/0.0.0/include.php index 3651251a9..1d438b2e2 100644 --- a/rainloop/v/0.0.0/include.php +++ b/rainloop/v/0.0.0/include.php @@ -22,16 +22,6 @@ Options -Indexes define('APP_USE_APC_CACHE', true); - $sCustomDataPath = ''; - if (file_exists(APP_INDEX_ROOT_PATH.'include.php')) - { - include_once APP_INDEX_ROOT_PATH.'include.php'; - } - - $sCustomDataPath = function_exists('__get_custom_data_full_path') ? rtrim(trim(__get_custom_data_full_path()), '\\/') : ''; - define('APP_DATA_FOLDER_PATH', 0 === strlen($sCustomDataPath) ? APP_INDEX_ROOT_PATH.'data/' : $sCustomDataPath.'/'); - unset($sCustomDataPath); - if (function_exists('date_default_timezone_set')) { date_default_timezone_set('UTC'); @@ -54,14 +44,33 @@ Options -Indexes define('APP_DUMMY', '********'); define('APP_DEV_VERSION', '0.0.0'); + define('APP_GOOGLE_ACCESS_TOKEN_PREFIX', ':GAT:'); + define('APP_WEB_SITE', 'http://www.rainloop.net/'); define('APP_API_PATH', 'http://api.rainloop.net/'); - define('APP_REP_PATH', 'http://repository.rainloop.net/v1/'); - define('APP_REPO_CORE_FILE', 'http://repository.rainloop.net/v2/core.{{channel}}.json'); define('APP_STATUS_PATH', 'http://status.rainloop.net/'); + define('APP_REPOSITORY_PATH', 'http://repository.rainloop.net/v1/'); + define('APP_REPO_CORE_FILE', 'http://repository.rainloop.net/v2/core.{{channel}}.json'); + + $sCustomDataPath = ''; + $sCustomConfiguration = ''; + + if (file_exists(APP_INDEX_ROOT_PATH.'include.php')) + { + include_once APP_INDEX_ROOT_PATH.'include.php'; + } + + $sCustomDataPath = function_exists('__get_custom_data_full_path') ? rtrim(trim(__get_custom_data_full_path()), '\\/') : ''; + define('APP_DATA_FOLDER_PATH', 0 === strlen($sCustomDataPath) ? APP_INDEX_ROOT_PATH.'data/' : $sCustomDataPath.'/'); + unset($sCustomDataPath); + + $sCustomConfiguration = function_exists('__get_additional_configuration_name') ? trim(__get_additional_configuration_name()) : ''; + define('APP_ADDITIONAL_CONFIGURATION_NAME', $sCustomConfiguration); + unset($sCustomConfiguration); + define('APP_DATA_FOLDER_PATH_UNIX', str_replace('\\', '/', APP_DATA_FOLDER_PATH)); $sSalt = @file_get_contents(APP_DATA_FOLDER_PATH.'SALT.php'); - $sData = @file_get_contents(APP_DATA_FOLDER_PATH.'DATA.php'); + $sData = file_exists(APP_DATA_FOLDER_PATH.'DATA.php') ? @file_get_contents(APP_DATA_FOLDER_PATH.'DATA.php') : ''; $sInstalled = @file_get_contents(APP_DATA_FOLDER_PATH.'INSTALLED'); // installation checking data folder @@ -120,29 +129,20 @@ Options -Indexes unset($sCheckName, $sCheckFilePath, $sCheckFolder, $sTest); } - if (false === $sSalt || false === $sData) + if (false === $sSalt) { - if (false === $sSalt) - { - // random salt - $sSalt = '<'.'?php //' - .md5(microtime(true).rand(1000, 5000)) - .md5(microtime(true).rand(5000, 9999)) - .md5(microtime(true).rand(1000, 5000)); + // random salt + $sSalt = '<'.'?php //' + .md5(microtime(true).rand(1000, 5000)) + .md5(microtime(true).rand(5000, 9999)) + .md5(microtime(true).rand(1000, 5000)); - @file_put_contents(APP_DATA_FOLDER_PATH.'SALT.php', $sSalt); - } - - if (false === $sData) - { - // random data folder name - $sData = '<'.'?php //'.md5(microtime(true).rand(1000, 9999)); - @file_put_contents(APP_DATA_FOLDER_PATH.'DATA.php', $sData); - } + @file_put_contents(APP_DATA_FOLDER_PATH.'SALT.php', $sSalt); } define('APP_SALT', md5($sSalt.APP_PRIVATE_DATA_NAME.$sSalt)); - define('APP_PRIVATE_DATA', APP_DATA_FOLDER_PATH.'_data_'.md5($sData).'/'.APP_PRIVATE_DATA_NAME.'/'); + define('APP_PRIVATE_DATA', APP_DATA_FOLDER_PATH.'_data_'.($sData ? md5($sData) : '').'/'.APP_PRIVATE_DATA_NAME.'/'); + define('APP_PLUGINS_PATH', APP_PRIVATE_DATA.'plugins/'); if (APP_VERSION !== $sInstalled || (APP_MULTIPLY && !@is_dir(APP_PRIVATE_DATA))) @@ -199,25 +199,25 @@ Options -Indexes } } - $sClearedSiteName = preg_replace('/^(www|demo|rainloop|webmail|email|mail|imap|imap4|smtp|pop|pop3)\./i', '', trim(APP_SITE)); - if (!empty($sClearedSiteName) && @file_exists(APP_VERSION_ROOT_PATH.'app/domains/default.ini.dist') && - !@file_exists(APP_PRIVATE_DATA.'domains/'.$sClearedSiteName.'.ini')) - { - $sConfigTemplate = @file_get_contents(APP_VERSION_ROOT_PATH.'app/domains/default.ini.dist'); - if (!empty($sConfigTemplate)) - { - @file_put_contents(APP_PRIVATE_DATA.'domains/'.$sClearedSiteName.'.ini', strtr($sConfigTemplate, array( - 'IMAP_HOST' => 'localhost' !== $sClearedSiteName? 'imap.'.$sClearedSiteName : $sClearedSiteName, - 'IMAP_PORT' => '993', - 'SMTP_HOST' => 'localhost' !== $sClearedSiteName? 'smtp.'.$sClearedSiteName : $sClearedSiteName, - 'SMTP_PORT' => '465' - ))); - } +// $sClearedSiteName = preg_replace('/^(www|demo|rainloop|webmail|email|mail|imap|imap4|smtp|pop|pop3)\./i', '', trim(APP_SITE)); +// if (!empty($sClearedSiteName) && @file_exists(APP_VERSION_ROOT_PATH.'app/domains/default.ini.dist') && +// !@file_exists(APP_PRIVATE_DATA.'domains/'.$sClearedSiteName.'.ini')) +// { +// $sConfigTemplate = @file_get_contents(APP_VERSION_ROOT_PATH.'app/domains/default.ini.dist'); +// if (!empty($sConfigTemplate)) +// { +// @file_put_contents(APP_PRIVATE_DATA.'domains/'.$sClearedSiteName.'.ini', strtr($sConfigTemplate, array( +// 'IMAP_HOST' => 'localhost' !== $sClearedSiteName? 'imap.'.$sClearedSiteName : $sClearedSiteName, +// 'IMAP_PORT' => '993', +// 'SMTP_HOST' => 'localhost' !== $sClearedSiteName? 'smtp.'.$sClearedSiteName : $sClearedSiteName, +// 'SMTP_PORT' => '465' +// ))); +// } +// +// unset($sConfigTemplate); +// } - unset($sConfigTemplate); - } - - unset($aFiles, $sFile, $sNewFileName, $sNewFile, $sClearedSiteName); + unset($aFiles, $sFile, $sNewFileName, $sNewFile); } } } diff --git a/rainloop/v/0.0.0/langs/admin/de.ini b/rainloop/v/0.0.0/langs/admin/de.ini new file mode 100644 index 000000000..501891c83 --- /dev/null +++ b/rainloop/v/0.0.0/langs/admin/de.ini @@ -0,0 +1,321 @@ + +[LOGIN] +LABEL_LOGIN = "Benutzer" +LABEL_PASSWORD = "Passwort" +BUTTON_LOGIN = "Im Adminpanel anmelden" + +[TOP_PANEL] +LABEL_PREMIUM = "Premium" +LABEL_ADMIN_PANEL = "Adminpanel" + +[TABS_LABELS] +LABEL_GENERAL_NAME = "Allgemein" +LABEL_LOGIN_NAME = "Anmeldung" +LABEL_BRANDING_NAME = "Branding" +LABEL_CONTACTS_NAME = "Kontakte" +LABEL_DOMAINS_NAME = "Domains" +LABEL_SECURITY_NAME = "Sicherheit" +LABEL_INTEGRATION_NAME = "Integration" +LABEL_PLUGINS_NAME = "Plugins" +LABEL_PACKAGES_NAME = "Pakete" +LABEL_LICENSING_NAME = "Lizenzierung" +LABEL_ABOUT_NAME = "Über" + +[TAB_GENERAL] +LEGEND_INTERFACE = "Oberfläche" +LABEL_LANGUAGE = "Sprache" +LABEL_LANGUAGE_ADMIN = "Sprache (Admin)" +LABEL_THEME = "Thema" +LABEL_ALLOW_LANGUAGES_ON_SETTINGS = "Sprachauswahl in den Einstellungen zulassen" +LABEL_ALLOW_THEMES_ON_SETTINGS = "Themaauswahl in den Einstellungen zulassen" +LABEL_ALLOW_BACKGROUND_ON_SETTINGS = "Hintergrundauswahl in den Einstellungen zulassen" +LABEL_SHOW_THUMBNAILS = "Vorschaubilder anzeigen (Anhänge)" +LABEL_ALLOW_GRAVATAR = "Gravatar erlauben" +LEGEND_MAIN = "Haupt" +LABEL_ATTACHMENT_SIZE_LIMIT = "Größenlimit für Anhänge" +LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Zusätzliche Konten erlauben" +LABEL_ALLOW_IDENTITIES = "Mehrere Identitäten erlauben" +LABEL_ALLOW_TEMPLATES = "Vorlagen erlauben" +ALERT_WARNING = "Warnung!" +HTML_ALERT_WEAK_PASSWORD = "Sie verwenden das Standard-Admin-Passwort. +
+Bitte
ändern Sie +aus Sicherheitsgründen das Passwort jetzt." + +[TAB_LOGIN] +LEGEND_LOGIN_SCREEN = "Anmeldebildschirm" +LABEL_DEFAULT_DOMAIN = "Standard-Domain" +LABEL_DETERMINE_USER_DOMAIN = "Versuche Domain des Benutzers zu ermitteln" +LABEL_ALLOW_LANGUAGES_ON_LOGIN = "Sprachauswahl bei der Anmeldung zulassen" +LABEL_DETERMINE_USER_LANGUAGE = "Versuche Sprache des Benutzers zu ermitteln" + +[TAB_BRANDING] +LEGEND_BRANDING = "Branding" +LABEL_PAGE_TITLE = "Seitentitel" +LABEL_LOADING_DESCRIPTION = "Ladevorgang-Beschreibung" +LEGEND_LOGIN = "Anmeldung" +LABEL_LOGIN_LOGO = "Logo" +LABEL_LOGIN_DESCRIPTION = "Beschreibung" +LABEL_LOGIN_BACKGROUND = "Hintergrund" +LABEL_LOGIN_CUSTOM_CSS = "Benutzerdefiniertes CSS" +LABEL_LOGIN_SHOW_POWERED_LINK = "\"Powered by RainLoop\"-Link anzeigen" +LEGEND_USER = "Benutzer" +LABEL_USER_LOGO = "Logo" +LABEL_USER_LOGO_TITLE = "Logo Titel" +LABEL_USER_LOGO_MESSAGE = "Logo (Nachrichten-Ansicht)" +LABEL_USER_CUSTOM_CSS = "Benutzerdefiniertes CSS" +LEGEND_WELCOME_PAGE = "Willkommensseite" +LABEL_WELCOME_PAGE_TITLE = "Titel" +LABEL_WELCOME_PAGE_URL = "URL" +LABEL_WELCOME_PAGE_DISPLAY = "Anzeigen" +OPTION_WELCOME_PAGE_DISPLAY_NONE = "Nie" +OPTION_WELCOME_PAGE_DISPLAY_ONCE = "Einmal" +OPTION_WELCOME_PAGE_DISPLAY_ALWAYS = "Immer" +HTML_ALERT_PREMIUM = "Diese Funktionalität ist für Premium-Abonnenten verfügbar." + +[TAB_CONTACTS] +LEGEND_CONTACTS = "Kontakte" +LEGEND_STORAGE = "Speicher (PDO)" +LABEL_ENABLE_CONTACTS = "Kontakte akivieren" +LABEL_ALLOW_SYNC = "Kontakte-Synchronisierung erlauben (mit externem CardDAV-Server)" +LABEL_STORAGE_TYPE = "Typ" +LABEL_STORAGE_DSN = "DSN" +LABEL_STORAGE_USER = "Benutzer" +LABEL_STORAGE_PASSWORD = "Passwort" +BUTTON_TEST = "Testen" +ALERT_NOTICE = "Hinweis!" +HTML_ALERT_DO_NOT_USE_THIS_DATABASE = "Verwenden Sie diesen Datenbanktyp nicht bei einer hohen Anzahl aktiver Benutzer." +HTML_ALERT_DOES_NOT_SUPPORTED = "Ihr System unterstützt keine Kontakte. +
+Sie müssen die PDO-Erweiterung (SQLite / MySQL / PostgreSQL) auf Ihrem Server installieren oder aktivieren." + +[TAB_DOMAINS] +LEGEND_DOMAINS = "Domains" +BUTTON_ADD_DOMAIN = "Domain hinzufügen" +DELETE_ARE_YOU_SURE = "Sind Sie sicher?" +HTML_DOMAINS_HELPER = "Liste der Domains, die Webmail abrufen darf. +
Klicken Sie auf den Namen, um die Domain zu konfigurieren." + +[TAB_SECURITY] +LEGEND_SECURITY = "Sicherheit" +LABEL_ALLOW_TWO_STEP = "Zwei-Faktor-Authentifizierung erlauben" +LABEL_FORCE_TWO_STEP = "Zwei-Faktor-Authentifizierung erzwingen" +LABEL_USE_IMAGE_PROXY = "Lokalen Proxy für externe Bilder verwenden" +LABEL_ALLOW_OPEN_PGP = "OpenPGP erlauben" +LABEL_SHOW_PHP_INFO = "PHP-Informationen anzeigen" +LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS = "Adminpanel-Zugangsdaten" +LABEL_CURRENT_PASSWORD = "Aktuelles Passwort" +LABEL_NEW_LOGIN = "Neuer Benutzer" +LABEL_NEW_PASSWORD = "Neues Passwort" +LABEL_REPEAT_PASSWORD = "Wiederholen" +BUTTON_UPDATE_PASSWORD = "Passwort aktualisieren" +LEGEND_SSL = "SSL" +LABEL_REQUIRE_VERIFICATION = "Verlangen, dass das verwendete SSL-Zertifikat beglaubigt ist (IMAP/SMTP)" +LABEL_ALLOW_SELF_SIGNED = "Selbst-signierte Zertifikate erlauben" + +[TAB_INTEGRATIONS] +LEGEND_GOOGLE = "Google" +LABEL_ENABLE_GOOGLE = "Google-Integration aktivieren" +LABEL_GOOGLE_AUTH = "Autorisierung" +LABEL_GOOGLE_DRIVE = "Google-Drive-Integration (Erstellen-Ansicht)" +LABEL_GOOGLE_PREVIEW = "Google-Viewer-Integration (Vorschau für Microsoft Word-, Excel- und PowerPoint-Dateien)" +LABEL_GOOGLE_CLIENT_ID = "Client-ID" +LABEL_GOOGLE_CLIENT_SECRET = "Client-Geheimnis" +LABEL_GOOGLE_API_KEY = "API-Schlüssel" +HINT_GOOGLE_API_KEY = "Wird für Google-Drive-Dateiauswahl benötigt" +LEGEND_FACEBOOK = "Facebook" +LABEL_ENABLE_FACEBOOK = "Facebook-Integration aktivieren (Autorisierung)" +LABEL_FACEBOOK_APP_ID = "App-ID" +LABEL_FACEBOOK_APP_SECRET = "App-Geheimnis" +LEGEND_TWITTER = "Twitter" +LABEL_ENABLE_TWITTER = "Twitter-Integration aktivieren (Autorisierung)" +LABEL_TWITTER_CONSUMER_KEY = "Consumer-Schlüssel" +LABEL_TWITTER_CONSUMER_SECRET = "Consumer-Geheimnis" +LEGEND_DROPBOX = "Dropbox" +LABEL_ENABLE_DROPBOX = "Dropbox-Integration aktivieren" +LABEL_DROPBOX_API_KEY = "API-Schlüssel" +TOP_ALERT = "Detaillierte Informationen zur Integration von Social-Diensten finden Sie unter" + +[TAB_PLUGINS] +LEGEND_PLUGINS = "Plugins" +LABEL_ENABLE_PLUGINS = "Plugins aktivieren" +ALERT_NO_PLUGINS = "Es wurden noch keine Plugins installiert." +LINK_INSTALL_NEW = "Hier klicken, um Plugins zu installieren!" +HINT_CLICK_NAME = "Klicken Sie auf den Namen, um das Plugin zu konfigurieren." + +[TAB_PACKAGES] +LEGEND_AVAILABLE_FOR_UPDATE = "Zur Aktualisierung verfügbar" +LEGEND_AVAILABLE_FOR_INSTALLATION = "Zur Installation verfügbar" +LEGEND_INSTALLED_PACKAGES = "Installierte Pakete" +ALERT_CANNOT_ACCESS_REPOSITORY = "Auf das Plugin-Repository kann derzeit nicht zugegriffen werden." + +[TAB_LICENSING] +LABEL_YOUR_DOMAIN = "Ihre Domain" +LABEL_VERSION = "Version" +LABEL_CHECKING = "Überprüfe" +TYPE_BASIC_HINT = "Diese Domain ist nicht für die kommerzielle Nutzung (mit zusätzlichen Funktionen) lizenziert." +TYPE_BASIC_HINT_2 = "Diese Domain kann nicht lizenziert werden." +HTML_ALERT_TOP_1 = "RainLoop Webmail steht unter folgender Lizenz:" +HTML_ALERT_TOP_2 = "Sie dürfen es für persönliche Projekte nutzen." +HTML_ALERT_TOP_3 = "Kommerzielle Nutzung (mit zusätzlichen Funktionen) von RainLoop Webmail erfordert eine +Subscription." +TYPE_PREMIUM_LIFETIME = "Lebenszeit" +TYPE_PREMIUM_HINT = "Diese Domain ist nicht für die kommerzielle Nutzung (mit zusätzlichen Funktionen) lizenziert." +LABEL_SUB_EXPIRES = "Ablauf der Subscription:" +BUTTON_ACTIVATE = "Subscription-Schlüssel für diese Domain aktivieren" +BUTTON_PURCHASE = "Erwerben" +BUTTON_TRIAL = "Testversion" + +[TAB_ABOUT] +LEGEND_ABOUT = "Über" +LABEL_TAG_HINT = "Einfacher, moderner und schneller webbasierter E-Mail-Client" +LABEL_ALL_RIGHTS_RESERVED = "Alle Rechte vorbehalten." +HINT_READ_CHANGE_LOG = "Bitte Lesen Sie das Änderungsprotokoll vor dem Update." +HINT_IS_UP_TO_DATE = "RainLoop ist auf dem neusten Stand." +HTML_NEW_VERSION = "Neue Version %VERSION% verfügbar." +LABEL_UPDATING = "Aktualisiere" +LABEL_CHECKING = "Prüfe auf Aktualisierungen" +BUTTON_UPDATE = "Aktualisieren" +BUTTON_DOWNLOAD = "Herunterladen" +BUTTON_CHANGELOG = "Änderungsprotokoll" + +[POPUPS_ACTIVATE] +TITLE_ACTIVATE = "Subscription-Schlüssel aktivieren?" +TITLE_ACTIVATION = "Aktiviere..." +LABEL_DOMAIN = "Domain" +LABEL_SUB_KEY = "Subscription-Schlüssel" +BUTTON_ACTIVATE = "Aktivieren" +LABEL_ACTIVATED = "Aktiviert" +ERROR_INVALID_SUBS_KEY = "Ungültiger Subscription-Schlüssel" +SUBS_KEY_ACTIVATED = "Subscription-Schlüssel erfolgreich aktiviert" +HTML_DESC = "Nach der Aktivierung wird %DOMAIN% um die Premium-Subscription erweitert. +
+Beachten Sie, dass ein Subscription-Schlüssel nur für eine einzelne Domain aktiviert werden kann. +

+Nach dem Start kann der Aktivierungsprozess nicht unterbrochen oder abgebrochen werden." + +[POPUPS_DOMAIN] +TITLE_ADD_DOMAIN = "Domain hinzufügen" +TITLE_ADD_DOMAIN_WITH_NAME = "Domain \"%NAME%\" hinzufügen" +TITLE_EDIT_DOMAIN = "Domain \"%NAME%\" bearbeiten" +LABEL_NAME = "Name" +NAME_HELPER = "Platzhalter unterstützt" +LABEL_IMAP = "IMAP" +LABEL_SMTP = "SMTP" +LABEL_SIEVE = "SIEVE" +LABEL_SERVER = "Server" +LABEL_PORT = "Port" +LABEL_SECURE = "Sicherheit" +LABEL_WHITE_LIST = "Whitelist" +SECURE_OPTION_NONE = "Ohne" +SECURE_OPTION_SSL = "SSL/TLS" +SECURE_OPTION_STARTTLS = "STARTTLS" +LABEL_ALLOW_SIEVE_SCRIPTS = "Sieve-Skripte erlauben" +LABEL_ALLOW_USER_SCRIPT = "Benutzerdefiniertes Skript erlauben" +LABEL_USE_SHORT_LOGIN = "Kurze Benutzernamen verwenden" +LABEL_USE_AUTH = "Authentifizierung verwenden" +LABEL_USE_PHP_MAIL = "PHPs mail()-Funktion verwenden" +BUTTON_TEST = "Testen" +BUTTON_WHITE_LIST = "Whitelist" +BUTTON_SIEVE_CONFIGURATION = "Sieve-Konfiguration" +BUTTON_BACK_TO_IMAP = "Zurück zu IMAP-Einstellungen" +BUTTON_BACK = "Zurück" +BUTTON_CLOSE = "Schließen" +BUTTON_ADD = "Hinzufügen" +BUTTON_UPDATE = "Aktualisieren" +WHITE_LIST_ALERT = "Liste der Domains, die Webmail abrufen darf. +Verwenden Sie Leerzeichen als Trenner." + +[POPUPS_PLUGIN] +TITLE_PLUGIN = "Plugin" +DESC_NOTHING_TO_CONFIGURE = "Nichts zu konfigurieren" +BUTTON_CLOSE = "Schließen" +BUTTON_SAVE = "Speichern" +TOOLTIP_ABOUT_TITLE = "Über" + +[POPUPS_ASK] +BUTTON_YES = "Ja" +BUTTON_NO = "Nein" +DESC_WANT_CLOSE_THIS_WINDOW = "Sind Sie sicher, dass Sie dieses Fenster schließen möchten?" +DESC_WANT_DELETE_MESSAGES = "Sind Sie sicher, dass Sie die Nachricht(en) löschen möchten?" + +[POPUPS_LANGUAGES] +TITLE_LANGUAGES = "Wählen Sie Ihre Sprache" + +[HINTS] +BETA = "Beta" +UNSTABLE = "Nicht stabil" +WARNING = "Warnung!" +NOT_SUPPORTED = "Nicht unterstützt" +REQUIRES_PHP_54 = "PHP 5.4 oder höher ist erforderlich" + +[ERRORS] +DOMAIN_ALREADY_EXISTS = "Domain existiert bereits" +UNKNOWN_ERROR = "Unbekannter Fehler" + +[NOTIFICATIONS] +INVALID_TOKEN = "Ungültiger Token" +AUTH_ERROR = "Authentifizierung fehlgeschlagen" +ACCESS_ERROR = "Zugriffsfehler" +CONNECTION_ERROR = "Serververbindung kann nicht hergestellt werden" +CAPTCHA_ERROR = "Falsche CAPTCHA-Eingabe." +SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE = "Diese Social-ID ist bisher mit keinem E-Mail-Konto verbunden. Melden Sie sich mit Ihren E-Mail-Anmeldedaten an und aktivieren Sie diese Funktion in Ihren Konteneinstellungen." +SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE = "Diese Social-ID ist bisher mit keinem E-Mail-Konto verbunden. Melden Sie sich mit Ihren E-Mail-Anmeldedaten an und aktivieren Sie diese Funktion in Ihren Konteneinstellungen." +SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE = "Diese Social-ID ist bisher mit keinem E-Mail-Konto verbunden. Melden Sie sich mit Ihren E-Mail-Anmeldedaten an und aktivieren Sie diese Funktion in Ihren Konteneinstellungen." +DOMAIN_NOT_ALLOWED = "Diese Domain ist nicht zugelassen." +ACCOUNT_NOT_ALLOWED = "Konto ist nicht zugelassen." +ACCOUNT_TWO_FACTOR_AUTH_REQUIRED = "Zwei-Faktor-Authentifizierung erforderlich" +ACCOUNT_TWO_FACTOR_AUTH_ERROR = "Fehler bei Zwei-Faktor-Authentifizierung" +COULD_NOT_SAVE_NEW_PASSWORD = "Neues Passwort konnte nicht gespeichert werden" +CURRENT_PASSWORD_INCORRECT = "Aktuelles Passwort falsch" +NEW_PASSWORD_SHORT = "Passwort ist zu kurz" +NEW_PASSWORD_WEAK = "Passwort ist zu einfach" +NEW_PASSWORD_FORBIDDENT = "Passwort enthält unzulässige Zeichen" +CONTACTS_SYNC_ERROR = "Fehler bei Kontakte-Synchronisierung" +CANT_GET_MESSAGE_LIST = "Die Nachrichtenliste ist nicht verfügbar" +CANT_GET_MESSAGE = "Diese Nachricht ist nicht verfügbar" +CANT_DELETE_MESSAGE = "Diese Nachricht kann nicht gelöscht werden" +CANT_MOVE_MESSAGE = "Diese Nachricht kann nicht verschoben werden" +CANT_SAVE_MESSAGE = "Diese Nachricht kann nicht gespeichert werden" +CANT_SEND_MESSAGE = "Diese Nachricht kann nicht gesendet werden" +INVALID_RECIPIENTS = "Ungültige Empfängeradressen" +CANT_SAVE_FILTERS = "Die Filter können nicht gespeichert werden" +CANT_GET_FILTERS = "Die Filter sind nicht verfügbar" +FILTERS_ARE_NOT_CORRECT = "Die Filter sind fehlerhaft" +CANT_CREATE_FOLDER = "Dieser Ordner kann nicht angelegt werden" +CANT_RENAME_FOLDER = "Dieser Ordner kann nicht umbenannt werden" +CANT_DELETE_FOLDER = "Dieser Ordner kann nicht gelöscht werden" +CANT_DELETE_NON_EMPTY_FOLDER = "Der Ordner kann nicht gelöscht werden; er ist nicht leer" +CANT_SUBSCRIBE_FOLDER = "Dieser Ordner kann nicht abonniert werden" +CANT_UNSUBSCRIBE_FOLDER = "Das Abonnement dieses Ordners kann nicht gelöscht werden" +CANT_SAVE_SETTINGS = "Einstellungen können nicht gespeichert werden" +CANT_SAVE_PLUGIN_SETTINGS = "Einstellungen können nicht gespeichert werden" +DOMAIN_ALREADY_EXISTS = "Diese Domain existiert bereits" +CANT_INSTALL_PACKAGE = "Paket konnte nicht installiert werden" +CANT_DELETE_PACKAGE = "Paket konnte nicht entfernt werden" +INVALID_PLUGIN_PACKAGE = "Plugin-Paket ist ungültig" +UNSUPPORTED_PLUGIN_PACKAGE = "Plugin-Paket wird nicht unterstützt" +LICENSING_SERVER_IS_UNAVAILABLE = "Der Subscription-Server kann nicht erreicht werden" +LICENSING_DOMAIN_EXPIRED = "Die Subscription dieser Domain ist abgelaufen." +LICENSING_DOMAIN_BANNED = "Die Subscription dieser Domain ist gesperrt." +DEMO_SEND_MESSAGE_ERROR = "Dieses Demokonto darf aus Sicherheitsgründen keine Nachrichten an externe E-Mail-Adressen versenden!" +DEMO_ACCOUNT_ERROR = "Aus Sicherheitsgründen ist dieses Konto nicht zu dieser Aktion berechtigt!" +ACCOUNT_ALREADY_EXISTS = "Dieses Konto existiert bereits" +MAIL_SERVER_ERROR = "Beim Zugriff auf den E-Mail-Server trat ein Fehler auf." +INVALID_INPUT_ARGUMENT = "Ungültige Eingabe" +UNKNOWN_ERROR = "Unbekannter Fehler" + +[STATIC] +BACK_LINK = "Aktualisieren" +DOMAIN_LIST_DESC = "Liste der Domains, auf die zugegriffen werden darf" +PHP_EXSTENSIONS_ERROR_DESC = "Notwendige PHP-Erweiterungen sind in Ihrer PHP-Konfiguration nicht vorhanden!" +PHP_VERSION_ERROR_DESC = "Ihre PHP Version (%VERSION%) ist älter als die notwendige Version: 5.3.0!" +NO_SCRIPT_TITLE = "Diese Anwendung benötigt JavaScript." +NO_SCRIPT_DESC = "Ihr Browser unterstützt JavaScript nicht. +Aktivieren Sie bitte die JavaScript-Unterstützung in Ihrem Browser und versuchen Sie es erneut." +NO_COOKIE_TITLE = "Diese Anwendung benötigt Cookies." +NO_COOKIE_DESC = "Ihr Browser unterstützt Cookies nicht. +Aktivieren Sie bitte die Cookie-Unterstützung in Ihrem Browser und versuchen Sie es erneut." +BAD_BROWSER_TITLE = "Ihr Browser ist veraltet." +BAD_BROWSER_DESC = "Um alle Funktionen dieser Anwendung nutzen zu können, +sollten Sie einen der folgenden Browser herunterladen und installieren:" diff --git a/rainloop/v/0.0.0/langs/admin/en.ini b/rainloop/v/0.0.0/langs/admin/en.ini index 4ff2f1350..0485dbea1 100644 --- a/rainloop/v/0.0.0/langs/admin/en.ini +++ b/rainloop/v/0.0.0/langs/admin/en.ini @@ -34,6 +34,7 @@ LABEL_ALLOW_GRAVATAR = "Allow Gravatar" LEGEND_MAIN = "Main" LABEL_ATTACHMENT_SIZE_LIMIT = "Attachment size limit" LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Allow additional accounts" +LABEL_ALLOW_IDENTITIES = "Allow multiple identities" LABEL_ALLOW_TEMPLATES = "Allow templates" ALERT_WARNING = "Warning!" HTML_ALERT_WEAK_PASSWORD = "You are using the default admin password. @@ -61,6 +62,8 @@ LABEL_LOGIN_CUSTOM_CSS = "Custom CSS" LABEL_LOGIN_SHOW_POWERED_LINK = "Show \"Powered by RainLoop\" link" LEGEND_USER = "User" LABEL_USER_LOGO = "Logo" +LABEL_USER_LOGO_TITLE = "Logo Title" +LABEL_USER_LOGO_MESSAGE = "Logo (Message View)" LABEL_USER_CUSTOM_CSS = "Custom CSS" LEGEND_WELCOME_PAGE = "Welcome page" LABEL_WELCOME_PAGE_TITLE = "Title" @@ -130,7 +133,7 @@ LABEL_ENABLE_TWITTER = "Enable Twitter Integration (Authorization)" LABEL_TWITTER_CONSUMER_KEY = "Consumer Key" LABEL_TWITTER_CONSUMER_SECRET = "Consumer Secret" LEGEND_DROPBOX = "Dropbox" -LABEL_ENABLE_DROPBOX = "Enable Dropbox Integration (Compose view)" +LABEL_ENABLE_DROPBOX = "Enable Dropbox Integration" LABEL_DROPBOX_API_KEY = "Api Key" TOP_ALERT = "Detailed information on social integration is found at" @@ -151,14 +154,12 @@ ALERT_CANNOT_ACCESS_REPOSITORY = "Cannot access the repository at the moment." LABEL_YOUR_DOMAIN = "Your domain" LABEL_VERSION = "Version" LABEL_CHECKING = "Checking" -TYPE_BASIC = "Basic" TYPE_BASIC_HINT = "This domain isn't licensed for commercial use (with additional features)." TYPE_BASIC_HINT_2 = "This domain can't be licensed." HTML_ALERT_TOP_1 = "RainLoop Webmail is licensed under" HTML_ALERT_TOP_2 = "You are free to use it for your personal projects." HTML_ALERT_TOP_3 = "Commercial use (with additional features) of RainLoop Webmail requires getting a subscription." -TYPE_PREMIUM = "Premium" TYPE_PREMIUM_LIFETIME = "Lifetime" TYPE_PREMIUM_HINT = "This domain isn't licensed for commercial use (with additional features)." LABEL_SUB_EXPIRES = "Subscription expires:" diff --git a/rainloop/v/0.0.0/langs/admin/it.ini b/rainloop/v/0.0.0/langs/admin/it.ini new file mode 100644 index 000000000..ea1bdfe63 --- /dev/null +++ b/rainloop/v/0.0.0/langs/admin/it.ini @@ -0,0 +1,322 @@ + +[LOGIN] +LABEL_LOGIN = "Nome utente" +LABEL_PASSWORD = "Password" +BUTTON_LOGIN = "Accedi al pannello di amministrazione" + +[TOP_PANEL] +LABEL_PREMIUM = "Premium" +LABEL_ADMIN_PANEL = "Pannello di amministrazione" + +[TABS_LABELS] +LABEL_GENERAL_NAME = "Generali" +LABEL_LOGIN_NAME = "Accesso" +LABEL_BRANDING_NAME = "Personalizzazione" +LABEL_CONTACTS_NAME = "Contatti" +LABEL_DOMAINS_NAME = "Domini" +LABEL_SECURITY_NAME = "Sicurezza" +LABEL_INTEGRATION_NAME = "Integrazioni" +LABEL_PLUGINS_NAME = "Plugin" +LABEL_PACKAGES_NAME = "Pacchetti" +LABEL_LICENSING_NAME = "Licenze" +LABEL_ABOUT_NAME = "Informazioni" + +[TAB_GENERAL] +LEGEND_INTERFACE = "Interfaccia" +LABEL_LANGUAGE = "Lingua" +LABEL_LANGUAGE_ADMIN = "Lingua (amministrazione)" +LABEL_THEME = "Tema" +LABEL_ALLOW_LANGUAGES_ON_SETTINGS = "Permetti di cambiare lingua all'accesso" +LABEL_ALLOW_THEMES_ON_SETTINGS = "Permetti di cambiare tema dalle impostazioni" +LABEL_ALLOW_BACKGROUND_ON_SETTINGS = "Permetti di scegliere lo sfondo dalle impostazioni" +LABEL_SHOW_THUMBNAILS = "Visualizza anteprime degli allegati" +LABEL_ALLOW_GRAVATAR = "Abilita Gravatar" +LEGEND_MAIN = "Principale" +LABEL_ATTACHMENT_SIZE_LIMIT = "Limite di grandezza degli allegati" +LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Permetti di possedere più account" +LABEL_ALLOW_IDENTITIES = "Permetti di registrare identità multiple" +LABEL_ALLOW_TEMPLATES = "Permetti di creare template" +ALERT_WARNING = "Attenzione!" +HTML_ALERT_WEAK_PASSWORD = "Stai usando la password di amministrazione predefinita. +
+Per ragioni di sicurezza, +cambiala +con una nuova password immediatamente." + +[TAB_LOGIN] +LEGEND_LOGIN_SCREEN = "Schermata di accesso" +LABEL_DEFAULT_DOMAIN = "Dominio predefinito" +LABEL_DETERMINE_USER_DOMAIN = "Prova a determinare il dominio dell'utente" +LABEL_ALLOW_LANGUAGES_ON_LOGIN = "Permetti di cambiare lingua all'accesso" +LABEL_DETERMINE_USER_LANGUAGE = "Prova a determinare la lingua dell'utente" + +[TAB_BRANDING] +LEGEND_BRANDING = "Personalizzazione" +LABEL_PAGE_TITLE = "Titolo della pagina" +LABEL_LOADING_DESCRIPTION = "Messaggio di caricamento" +LEGEND_LOGIN = "Pagina di accesso" +LABEL_LOGIN_LOGO = "Logo" +LABEL_LOGIN_DESCRIPTION = "Descrizione" +LABEL_LOGIN_BACKGROUND = "Sfondo" +LABEL_LOGIN_CUSTOM_CSS = "CSS personalizzato" +LABEL_LOGIN_SHOW_POWERED_LINK = "Visualizza il link \"Powered by RainLoop\"" +LEGEND_USER = "Vista utente" +LABEL_USER_LOGO = "Logo" +LABEL_USER_LOGO_TITLE = "Titolo del logo" +LABEL_USER_LOGO_MESSAGE = "Logo (vista del messaggio)" +LABEL_USER_CUSTOM_CSS = "CSS personalizzato" +LEGEND_WELCOME_PAGE = "Pagina di benvenuto" +LABEL_WELCOME_PAGE_TITLE = "Titolo" +LABEL_WELCOME_PAGE_URL = "Indirizzo" +LABEL_WELCOME_PAGE_DISPLAY = "Visualizza" +OPTION_WELCOME_PAGE_DISPLAY_NONE = "Mai" +OPTION_WELCOME_PAGE_DISPLAY_ONCE = "Solo una volta" +OPTION_WELCOME_PAGE_DISPLAY_ALWAYS = "Sempre" +HTML_ALERT_PREMIUM = "Questa funzionalità è disponibile solo per coloro che hanno acquistato una licenza Premium." + +[TAB_CONTACTS] +LEGEND_CONTACTS = "Contatti" +LEGEND_STORAGE = "Metodo di salvataggio (PDO)" +LABEL_ENABLE_CONTACTS = "Abilita contatti" +LABEL_ALLOW_SYNC = "Abilita la sincronizzazione dei contatti (con un server CardDAV esterno)" +LABEL_STORAGE_TYPE = "Tipo" +LABEL_STORAGE_DSN = "DSN" +LABEL_STORAGE_USER = "Nome utente" +LABEL_STORAGE_PASSWORD = "Password" +BUTTON_TEST = "Verifica dati" +ALERT_NOTICE = "Attenzione!" +HTML_ALERT_DO_NOT_USE_THIS_DATABASE = "Non usare questo tipo di database con un alto numero di utenti attivi." +HTML_ALERT_DOES_NOT_SUPPORTED = "Il tuo server non supporta il salvataggio dei contatti. +
+Devi abilitare l'estensione PDO (SQLite / MySQL / PostgreSQL) sul tuo server." + +[TAB_DOMAINS] +LEGEND_DOMAINS = "Domini" +BUTTON_ADD_DOMAIN = "Aggiungi dominio" +DELETE_ARE_YOU_SURE = "Ne sei sicuro?" +HTML_DOMAINS_HELPER = "Lista di domini a cui la webmail è abilitata ad accedere. +
Clicca su un nome per configurare quel dominio." + +[TAB_SECURITY] +LEGEND_SECURITY = "Security" +LABEL_ALLOW_TWO_STEP = "Abilita l'autenticazione a due fattori" +LABEL_FORCE_TWO_STEP = "Forza l'autenticazione a due fattori" +LABEL_USE_IMAGE_PROXY = "Usa un proxy locale per le immagini" +LABEL_ALLOW_OPEN_PGP = "Abilita OpenPGP" +LABEL_SHOW_PHP_INFO = "Visualizza informazioni su PHP" +LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS = "Dati di accesso al pannello di controllo" +LABEL_CURRENT_PASSWORD = "Password corrente" +LABEL_NEW_LOGIN = "Nuovo nome utente" +LABEL_NEW_PASSWORD = "Nuova password" +LABEL_REPEAT_PASSWORD = "Ripeti nuova password" +BUTTON_UPDATE_PASSWORD = "Aggiorna password" +LEGEND_SSL = "SSL" +LABEL_REQUIRE_VERIFICATION = "Richiedi verifica dei certificati SSL (IMAP/SMTP)" +LABEL_ALLOW_SELF_SIGNED = "Abilita certificati autofirmati" + +[TAB_INTEGRATIONS] +LEGEND_GOOGLE = "Google" +LABEL_ENABLE_GOOGLE = "Abilita integrazione con Google" +LABEL_GOOGLE_AUTH = "Autenticazione" +LABEL_GOOGLE_DRIVE = "Integrazione con Google Drive (finestra di scrittura)" +LABEL_GOOGLE_PREVIEW = "Integrazione con Google Docs (anteprima per i file di Microsoft Word, Excel e PowerPoint)" +LABEL_GOOGLE_CLIENT_ID = "Client ID" +LABEL_GOOGLE_CLIENT_SECRET = "Client Secret" +LABEL_GOOGLE_API_KEY = "API Key" +HINT_GOOGLE_API_KEY = "Richiesta per la selezione dei file di Google Drive" +LEGEND_FACEBOOK = "Facebook" +LABEL_ENABLE_FACEBOOK = "Abilita l'integrazione con Facebook (autenticazione)" +LABEL_FACEBOOK_APP_ID = "App ID" +LABEL_FACEBOOK_APP_SECRET = "App Secret" +LEGEND_TWITTER = "Twitter" +LABEL_ENABLE_TWITTER = "Abilita l'integrazione con Twitter (autenticazione)" +LABEL_TWITTER_CONSUMER_KEY = "Consumer Key" +LABEL_TWITTER_CONSUMER_SECRET = "Consumer Secret" +LEGEND_DROPBOX = "Dropbox" +LABEL_ENABLE_DROPBOX = "Abilita l'integrazione con Dropbox" +LABEL_DROPBOX_API_KEY = "API Key" +TOP_ALERT = "Informazioni dettagliate circa l'integrazione con i social network è disponibile su" + +[TAB_PLUGINS] +LEGEND_PLUGINS = "Plugin" +LABEL_ENABLE_PLUGINS = "Abilita plugin" +ALERT_NO_PLUGINS = "Nessun plugin è stato installato." +LINK_INSTALL_NEW = "Clicca qui per installarne di nuovi!" +HINT_CLICK_NAME = "Clicca sul nome di un plugin per configurarlo." + +[TAB_PACKAGES] +LEGEND_AVAILABLE_FOR_UPDATE = "Disponibili per l'aggiornamento" +LEGEND_AVAILABLE_FOR_INSTALLATION = "Disponibili per l'installazione" +LEGEND_INSTALLED_PACKAGES = "Pacchetti installati" +ALERT_CANNOT_ACCESS_REPOSITORY = "Impossibile accedere al repository in questo momento." + +[TAB_LICENSING] +LABEL_YOUR_DOMAIN = "Il tuo dominio" +LABEL_VERSION = "Licenza" +LABEL_CHECKING = "Controllo in corso..." +TYPE_BASIC_HINT = "Questo dominio non possiede una licenza commerciale (con funzionalità aggiuntive)." +TYPE_BASIC_HINT_2 = "Questo dominio non può possedere una licenza." +HTML_ALERT_TOP_1 = "RainLoop Webmail è rilasciato sotto la licenza" +HTML_ALERT_TOP_2 = "Sei libero di usarla per i tuoi progetti personali." +HTML_ALERT_TOP_3 = "L'uso commerciale (con funzionalità aggiuntive) di RainLoop Webmail richiede di ottenere una +licenza." +TYPE_PREMIUM_LIFETIME = "A vita" +TYPE_PREMIUM_HINT = "Questo dominio non possiede una licenza per uso commerciale (con funzionalità aggiuntive)." +LABEL_SUB_EXPIRES = "La licenza scade il:" +BUTTON_ACTIVATE = "Attiva una chiave di licenza per questo dominio" +BUTTON_PURCHASE = "Compra una licenza" +BUTTON_TRIAL = "Versione di prova" + +[TAB_ABOUT] +LEGEND_ABOUT = "Informazioni" +LABEL_TAG_HINT = "Semplice, moderno e veloce client email online" +LABEL_ALL_RIGHTS_RESERVED = "Tutti i diritti riservati." +HINT_READ_CHANGE_LOG = "Leggere il changelog prima di effettuare l'aggiornamento." +HINT_IS_UP_TO_DATE = "RainLoop è aggiornato." +HTML_NEW_VERSION = "La nuova versione %VERSION% è disponibile." +LABEL_UPDATING = "Aggiornamento in corso..." +LABEL_CHECKING = "Controllo della presenza di aggiornamenti..." +BUTTON_UPDATE = "Aggiorna" +BUTTON_DOWNLOAD = "Scarica" +BUTTON_CHANGELOG = "Changelog" + +[POPUPS_ACTIVATE] +TITLE_ACTIVATE = "Attivare chiave di licenza?" +TITLE_ACTIVATION = "Attivazione..." +LABEL_DOMAIN = "Dominio" +LABEL_SUB_KEY = "Chiave di licenza" +BUTTON_ACTIVATE = "Attiva" +LABEL_ACTIVATED = "Attivata" +ERROR_INVALID_SUBS_KEY = "Chiave di licenza non valida" +SUBS_KEY_ACTIVATED = "Chiave di licenza attivata correttamente" +HTML_DESC = "Dopo l'attivazione, la licenza Premium per %DOMAIN% sarà estesa. +
+Una chiave di licenza può essere attivata su un solo dominio. +

+Una volta iniziato, il processo di attivazione non potrà essere bloccato od annullato." + +[POPUPS_DOMAIN] +TITLE_ADD_DOMAIN = "Aggiungi dominio" +TITLE_ADD_DOMAIN_WITH_NAME = "Aggiungi il dominio \"%NAME%\"" +TITLE_EDIT_DOMAIN = "Modifica il dominio \"%NAME%\"" +LABEL_NAME = "Nome dominio" +NAME_HELPER = "asterischi supportati" +LABEL_IMAP = "IMAP" +LABEL_SMTP = "SMTP" +LABEL_SIEVE = "SIEVE" +LABEL_SERVER = "Server" +LABEL_PORT = "porta" +LABEL_SECURE = "Sicuro" +LABEL_WHITE_LIST = "Whitelist" +SECURE_OPTION_NONE = "Nessuna" +SECURE_OPTION_SSL = "SSL/TLS" +SECURE_OPTION_STARTTLS = "STARTTLS" +LABEL_ALLOW_SIEVE_SCRIPTS = "Abilita script sieve" +LABEL_ALLOW_USER_SCRIPT = "Abilita script personalizzati" +LABEL_USE_SHORT_LOGIN = "Utilizza login corto" +LABEL_USE_AUTH = "Utilizza autenticazione" +LABEL_USE_PHP_MAIL = "Usa la funzione mail() di PHP" +BUTTON_TEST = "Verifica" +BUTTON_WHITE_LIST = "Whitelist" +BUTTON_SIEVE_CONFIGURATION = "Configurazione di Sieve" +BUTTON_BACK_TO_IMAP = "Torna alle impostazioni IMAP" +BUTTON_BACK = "Indietro" +BUTTON_CLOSE = "Chiudi" +BUTTON_ADD = "Aggiungi" +BUTTON_UPDATE = "Aggiorna" +WHITE_LIST_ALERT = "Lista di domini a cui gli utenti sono autorizzati ad accedere. +Utilizzare uno spazio come separatore." + +[POPUPS_PLUGIN] +TITLE_PLUGIN = "Plugin" +DESC_NOTHING_TO_CONFIGURE = "Niente da configurare" +BUTTON_CLOSE = "Chiudi" +BUTTON_SAVE = "Salva" +TOOLTIP_ABOUT_TITLE = "Informazioni" + +[POPUPS_ASK] +BUTTON_YES = "Si" +BUTTON_NO = "No" +DESC_WANT_CLOSE_THIS_WINDOW = "Sei sicuro di voler chiudere questa finestra?" +DESC_WANT_DELETE_MESSAGES = "Sei sicuro di voler cancellare questi messaggi?" + +[POPUPS_LANGUAGES] +TITLE_LANGUAGES = "Scegli la tua lingua" + +[HINTS] +BETA = "beta" +UNSTABLE = "instabile" +WARNING = "Attenzione!" +NOT_SUPPORTED = "non supportato" +REQUIRES_PHP_54 = "richiede PHP 5.4 o maggiori" + +[ERRORS] +DOMAIN_ALREADY_EXISTS = "Il dominio esiste già" +UNKNOWN_ERROR = "Errore sconosciuto" + +[NOTIFICATIONS] +INVALID_TOKEN = "Token invalido" +AUTH_ERROR = "Autenticazione fallita" +ACCESS_ERROR = "Errore di accesso" +CONNECTION_ERROR = "Impossibile connettersi al server" +CAPTCHA_ERROR = "CAPTCHA non corretto." +SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE = "Questo account social non è assegnato ancora a nessun indirizzo email. Accedi utilizzando le credenziali dell'indirizzo e abilita la funzionalità nelle impostazioni." +SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE = "Questo account social non è assegnato ancora a nessun indirizzo email. Accedi utilizzando le credenziali dell'indirizzo e abilita la funzionalità nelle impostazioni." +SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE = "Questo account social non è assegnato ancora a nessun indirizzo email. Accedi utilizzando le credenziali dell'indirizzo e abilita la funzionalità nelle impostazioni." +DOMAIN_NOT_ALLOWED = "Dominio non autorizzato" +ACCOUNT_NOT_ALLOWED = "Account non autorizzato" +ACCOUNT_TWO_FACTOR_AUTH_REQUIRED = "Autenticazione a due fattori richiesta" +ACCOUNT_TWO_FACTOR_AUTH_ERROR = "Errore durante l'autenticazione a due fattori" +COULD_NOT_SAVE_NEW_PASSWORD = "Impossibile salvare la nuova password" +CURRENT_PASSWORD_INCORRECT = "Password corrente incorreta" +NEW_PASSWORD_SHORT = "Password troppo corta" +NEW_PASSWORD_WEAK = "Password troppo facile" +NEW_PASSWORD_FORBIDDENT = "Password vietata" +CONTACTS_SYNC_ERROR = "Errore durante la sincronizzazione dei contatti" +CANT_GET_MESSAGE_LIST = "Errore durante il caricamento della lista dei messaggi" +CANT_GET_MESSAGE = "Errore durante il caricamento del messaggio" +CANT_DELETE_MESSAGE = "Impossibile cancellare il messaggio" +CANT_MOVE_MESSAGE = "Impossibile spostare il messaggio" +CANT_SAVE_MESSAGE = "Impossibile salvare il messaggio" +CANT_SEND_MESSAGE = "Impossibile inviare il messaggio" +INVALID_RECIPIENTS = "Destinatari invalidi" +CANT_SAVE_FILTERS = "Impossibile salvare i filtri" +CANT_GET_FILTERS = "Impossibile caricare i filtri" +FILTERS_ARE_NOT_CORRECT = "I filtri non sono corretti" +CANT_CREATE_FOLDER = "Impossibile creare la cartella" +CANT_RENAME_FOLDER = "Impossibile rinominare la cartella" +CANT_DELETE_FOLDER = "Impossibile cancellare la cartella" +CANT_DELETE_NON_EMPTY_FOLDER = "Non è possibile cancellare cartelle piene" +CANT_SUBSCRIBE_FOLDER = "Impossibile sottoscriversi alla cartella" +CANT_UNSUBSCRIBE_FOLDER = "Impossibile rimuovere la sottoscrizione dalla cartella" +CANT_SAVE_SETTINGS = "Impossibile salvare le impostazioni" +CANT_SAVE_PLUGIN_SETTINGS = "Impossibile salvare le impostazioni" +DOMAIN_ALREADY_EXISTS = "Il dominio già esiste" +CANT_INSTALL_PACKAGE = "Impossibile installare il pacchetto" +CANT_DELETE_PACKAGE = "Impossibile rimuovere il pacchetto" +INVALID_PLUGIN_PACKAGE = "Pacchetto non valido" +UNSUPPORTED_PLUGIN_PACKAGE = "Pacchetto non supportato" +LICENSING_SERVER_IS_UNAVAILABLE = "Il server dlele licenze non è dispobibile" +LICENSING_DOMAIN_EXPIRED = "La licenza per questo dominio è scaduta" +LICENSING_DOMAIN_BANNED = "La licenza per questo dominio è stata revocata" +DEMO_SEND_MESSAGE_ERROR = "Per ragioni di sicurezza, questo account non è abilitato ad inviare email all'esterno." +DEMO_ACCOUNT_ERROR = "Per ragioni di sicurezza, questa funzionalità è bloccata." +ACCOUNT_ALREADY_EXISTS = "Questo account esiste già" +MAIL_SERVER_ERROR = "Errore durante la connessione con il server mail" +INVALID_INPUT_ARGUMENT = "Argomento non valido" +UNKNOWN_ERROR = "Errore sconosciuto" + +[STATIC] +BACK_LINK = "Ricarica" +DOMAIN_LIST_DESC = "Lista di domini a cui la webmail è abilitata ad accedere" +PHP_EXSTENSIONS_ERROR_DESC = "Un estensione di PHP richiesta non è disponibile." +PHP_VERSION_ERROR_DESC = "La versione di PHP corrente (%VERSION%) è più vecchia di quella minima supportata (PHP 5.3.0)" +NO_SCRIPT_TITLE = "Questa applicazione richiede JacaScript" +NO_SCRIPT_DESC = "Il supporto a JavaScript è disabilitato nel browser. +Abilita JavaScript e ricarica la pagina." +NO_COOKIE_TITLE = "Questa applicazione richiede i cookie" +NO_COOKIE_DESC = "Il supporto ai cookie è disabilitato nel browser. +Abilita i cookie e ricarica la pagina." +BAD_BROWSER_TITLE = "Il tuo browser è troppo vecchio" +BAD_BROWSER_DESC = "Per usare tutte le funzionalità di questa applicazione, +scarica uno dei seguenti browser:" diff --git a/rainloop/v/0.0.0/langs/admin/nl.ini b/rainloop/v/0.0.0/langs/admin/nl.ini new file mode 100644 index 000000000..11d86e5ec --- /dev/null +++ b/rainloop/v/0.0.0/langs/admin/nl.ini @@ -0,0 +1,319 @@ + +[LOGIN] +LABEL_LOGIN = "Inlognaam" +LABEL_PASSWORD = "Wachtwoord" +BUTTON_LOGIN = "Aanmelden in het beheer paneel" + +[TOP_PANEL] +LABEL_PREMIUM = "Premium" +LABEL_ADMIN_PANEL = "Beheer paneel" + +[TABS_LABELS] +LABEL_GENERAL_NAME = "Algemeen" +LABEL_LOGIN_NAME = "Inlognaam" +LABEL_BRANDING_NAME = "Huisstijl" +LABEL_CONTACTS_NAME = "Contactpersonen" +LABEL_DOMAINS_NAME = "Domeinen" +LABEL_SECURITY_NAME = "Beveiliging" +LABEL_INTEGRATION_NAME = "Integratie" +LABEL_PLUGINS_NAME = "Invoegtoepassingen" +LABEL_PACKAGES_NAME = "Paketten" +LABEL_LICENSING_NAME = "Licentieovereenkomst" +LABEL_ABOUT_NAME = "Over" + +[TAB_GENERAL] +LEGEND_INTERFACE = "Interface" +LABEL_LANGUAGE = "Taal" +LABEL_LANGUAGE_ADMIN = "Taal (admin)" +LABEL_THEME = "Thema" +LABEL_ALLOW_LANGUAGES_ON_SETTINGS = "Sta taalselectie toe in het instellingen scherm" +LABEL_ALLOW_THEMES_ON_SETTINGS = "Sta thema selectie toe in het instellingen scherm" +LABEL_ALLOW_BACKGROUND_ON_SETTINGS = "Sta achtergrond selectie toe in het instellingen scherm" +LABEL_SHOW_THUMBNAILS = "Toon miniaturen (bijlage)" +LABEL_ALLOW_GRAVATAR = "Toon Gravatar" +LEGEND_MAIN = "Diverse" +LABEL_ATTACHMENT_SIZE_LIMIT = "Maximale bijlage grootte" +LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Sta extra accounts toe" +LABEL_ALLOW_TEMPLATES = "Sta templates toe" +ALERT_WARNING = "Waarschuwing!" +HTML_ALERT_WEAK_PASSWORD = "U gebruikt het standaard beheer wachtwoord. +
+Wijzig +a.u.b. voor uw veiligheid direct het wachtwoord." + +[TAB_LOGIN] +LEGEND_LOGIN_SCREEN = "Login scherm" +LABEL_DEFAULT_DOMAIN = "Standaard domein" +LABEL_DETERMINE_USER_DOMAIN = "Probeer gebruikersdomein te bepalen" +LABEL_ALLOW_LANGUAGES_ON_LOGIN = "Sta taal selectie toe in het login scherm" +LABEL_DETERMINE_USER_LANGUAGE = "Probeer gebruiker taal te bepalen" + +[TAB_BRANDING] +LEGEND_BRANDING = "Huisstijl" +LABEL_PAGE_TITLE = "Pagina titel" +LABEL_LOADING_DESCRIPTION = "Beschrijving tijdens laden" +LEGEND_LOGIN = "Login scherm" +LABEL_LOGIN_LOGO = "Logo" +LABEL_LOGIN_DESCRIPTION = "Beschrijving" +LABEL_LOGIN_BACKGROUND = "Achtergrond" +LABEL_LOGIN_CUSTOM_CSS = "Aangepaste CSS" +LABEL_LOGIN_SHOW_POWERED_LINK = "Toon \"Powered by RainLoop\" link" +LEGEND_USER = "Gebruiker" +LABEL_USER_LOGO = "Logo" +LABEL_USER_LOGO_TITLE = "Logo titel" +LABEL_USER_CUSTOM_CSS = "Aangepaste CSS" +LEGEND_WELCOME_PAGE = "Welcom pagina" +LABEL_WELCOME_PAGE_TITLE = "Titel" +LABEL_WELCOME_PAGE_URL = "URL" +LABEL_WELCOME_PAGE_DISPLAY = "Weergave" +OPTION_WELCOME_PAGE_DISPLAY_NONE = "Nooit" +OPTION_WELCOME_PAGE_DISPLAY_ONCE = "Eenmalig" +OPTION_WELCOME_PAGE_DISPLAY_ALWAYS = "Altijd" +HTML_ALERT_PREMIUM = "Deze functionaliteit is alleen beschikbaar voor Premium abonnees." + +[TAB_CONTACTS] +LEGEND_CONTACTS = "Contactpersonen" +LEGEND_STORAGE = "Opslag (PDO)" +LABEL_ENABLE_CONTACTS = "Contactpersonen inschakelen" +LABEL_ALLOW_SYNC = "Contactpersoon synchronisatie (met externe CardDAV server) inschakelen" +LABEL_STORAGE_TYPE = "Soort" +LABEL_STORAGE_DSN = "Dsn" +LABEL_STORAGE_USER = "Gebruikersnaam" +LABEL_STORAGE_PASSWORD = "Wachtwoord" +BUTTON_TEST = "Test" +ALERT_NOTICE = "Aandacht!" +HTML_ALERT_DO_NOT_USE_THIS_DATABASE = "Gegruik deze database soort niet met een groot aantal actieve gebrukers." +HTML_ALERT_DOES_NOT_SUPPORTED = "Uw systeem ondersteund geen contactpersonen. +
+U moet een PDO (SQLite / MySQL / PostgreSQL) extentie op uw server installeren of activeren." + +[TAB_DOMAINS] +LEGEND_DOMAINS = "Domeinen" +BUTTON_ADD_DOMAIN = "Domein toevoegen" +DELETE_ARE_YOU_SURE = "Weet u het zeker?" +HTML_DOMAINS_HELPER = "Lijst van toegestane domeinen. +
Klik op de domeinnaam om deze te configureren." + +[TAB_SECURITY] +LEGEND_SECURITY = "Beveiliging" +LABEL_ALLOW_TWO_STEP = "2-Stap verificatie toestaan" +LABEL_FORCE_TWO_STEP = "2-Stap verificatie afdwingen" +LABEL_USE_IMAGE_PROXY = "Gebruik de server als proxy voor externe afbeeldingen" +LABEL_ALLOW_OPEN_PGP = "OpenPGP toestaan" +LABEL_SHOW_PHP_INFO = "PHP informatie tonen" +LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS = "Toegangsgegevens beheer paneel" +LABEL_CURRENT_PASSWORD = "Huidig wachtwoord" +LABEL_NEW_LOGIN = "Nieuwe gebruikersnaam" +LABEL_NEW_PASSWORD = "Nieuw wachtwoord" +LABEL_REPEAT_PASSWORD = "Herhaal nieuw wachtwoord" +BUTTON_UPDATE_PASSWORD = "Gegevens bijwerken" +LEGEND_SSL = "SSL" +LABEL_REQUIRE_VERIFICATION = "Verificatie van SSL certificaten (IMAP/SMTP)" +LABEL_ALLOW_SELF_SIGNED = "Sta zelf ondertekende certificaten toe" + +[TAB_INTEGRATIONS] +LEGEND_GOOGLE = "Google" +LABEL_ENABLE_GOOGLE = "Google integratie inschakelen" +LABEL_GOOGLE_AUTH = "Autorisatie" +LABEL_GOOGLE_DRIVE = "Google Drive integratie (tijdens bericht opstellen)" +LABEL_GOOGLE_PREVIEW = "Google Viewer integratie (Microsoft Word, Excel en PowerPoint voorbeelweergave)" +LABEL_GOOGLE_CLIENT_ID = "Client ID" +LABEL_GOOGLE_CLIENT_SECRET = "Geheime sleutel" +LABEL_GOOGLE_API_KEY = "API sleutel" +HINT_GOOGLE_API_KEY = "Vereist voor Google Drive bestand verkenner" +LEGEND_FACEBOOK = "Facebook" +LABEL_ENABLE_FACEBOOK = "Facebook integratie (autorisatie) inschakelen" +LABEL_FACEBOOK_APP_ID = "App ID" +LABEL_FACEBOOK_APP_SECRET = "App sleutel" +LEGEND_TWITTER = "Twitter" +LABEL_ENABLE_TWITTER = "Twitter integratie (autorisatie) inschakelen" +LABEL_TWITTER_CONSUMER_KEY = "Consumer sleutel" +LABEL_TWITTER_CONSUMER_SECRET = "Consumer geheime sleutel" +LEGEND_DROPBOX = "Dropbox" +LABEL_ENABLE_DROPBOX = "Dropbox integratie" +LABEL_DROPBOX_API_KEY = "API sleutel" +TOP_ALERT = "Gedetaileerde informatie over integraties is te vinden op" + +[TAB_PLUGINS] +LEGEND_PLUGINS = "Invoegtoepassingen" +LABEL_ENABLE_PLUGINS = "Invoegtoepassingen inschakelen" +ALERT_NO_PLUGINS = "Er zijn nog geen invoegtoepassingen geïnstalleerd" +LINK_INSTALL_NEW = "Klik hier om een invoegtoepassing te installeren!" +HINT_CLICK_NAME = "Klik op de naam om de invoegtoepassing te configuren." + +[TAB_PACKAGES] +LEGEND_AVAILABLE_FOR_UPDATE = "Available for Update" +LEGEND_AVAILABLE_FOR_INSTALLATION = "Available for Installation" +LEGEND_INSTALLED_PACKAGES = "Installed Packages" +ALERT_CANNOT_ACCESS_REPOSITORY = "Cannot access the repository at the moment." + +[TAB_LICENSING] +LABEL_YOUR_DOMAIN = "Your domain" +LABEL_VERSION = "Version" +LABEL_CHECKING = "Checking" +TYPE_BASIC_HINT = "This domain isn't licensed for commercial use (with additional features)." +TYPE_BASIC_HINT_2 = "This domain can't be licensed." +HTML_ALERT_TOP_1 = "RainLoop Webmail is licensed under" +HTML_ALERT_TOP_2 = "You are free to use it for your personal projects." +HTML_ALERT_TOP_3 = "Commercial use (with additional features) of RainLoop Webmail requires getting a +subscription." +TYPE_PREMIUM_LIFETIME = "Lifetime" +TYPE_PREMIUM_HINT = "This domain isn't licensed for commercial use (with additional features)." +LABEL_SUB_EXPIRES = "Subscription expires:" +BUTTON_ACTIVATE = "Activate Subscription Key for this domain" +BUTTON_PURCHASE = "Purchase" +BUTTON_TRIAL = "Trial" + +[TAB_ABOUT] +LEGEND_ABOUT = "About" +LABEL_TAG_HINT = "Simple, modern & fast web-based email client" +LABEL_ALL_RIGHTS_RESERVED = "All Rights Reserved." +HINT_READ_CHANGE_LOG = "Please read the change log before updating." +HINT_IS_UP_TO_DATE = "RainLoop is up to date." +HTML_NEW_VERSION = "New %VERSION% version is available." +LABEL_UPDATING = "Updating" +LABEL_CHECKING = "Checking for updates" +BUTTON_UPDATE = "Update" +BUTTON_DOWNLOAD = "Download" +BUTTON_CHANGELOG = "Changelog" + +[POPUPS_ACTIVATE] +TITLE_ACTIVATE = "Activate Subscription Key?" +TITLE_ACTIVATION = "Activation..." +LABEL_DOMAIN = "Domain" +LABEL_SUB_KEY = "Subscription Key" +BUTTON_ACTIVATE = "Activate" +LABEL_ACTIVATED = "Activated" +ERROR_INVALID_SUBS_KEY = "Invalid Subscription Key" +SUBS_KEY_ACTIVATED = "Subscription Key Activated Successfully" +HTML_DESC = "After activation, premium subscription for %DOMAIN% will be extended. +
+Note that subscription key can be activated for a single domain only. +

+Once started, the process of activation cannot be aborted or cancelled." + +[POPUPS_DOMAIN] +TITLE_ADD_DOMAIN = "Add Domain" +TITLE_ADD_DOMAIN_WITH_NAME = "Add Domain \"%NAME%\"" +TITLE_EDIT_DOMAIN = "Edit Domain \"%NAME%\"" +LABEL_NAME = "Name" +NAME_HELPER = "wildcard supported" +LABEL_IMAP = "IMAP" +LABEL_SMTP = "SMTP" +LABEL_SIEVE = "SIEVE" +LABEL_SERVER = "Server" +LABEL_PORT = "Port" +LABEL_SECURE = "Secure" +LABEL_WHITE_LIST = "White List" +SECURE_OPTION_NONE = "None" +SECURE_OPTION_SSL = "SSL/TLS" +SECURE_OPTION_STARTTLS = "STARTTLS" +LABEL_ALLOW_SIEVE_SCRIPTS = "Allow sieve scripts" +LABEL_ALLOW_USER_SCRIPT = "Allow custom user script" +LABEL_USE_SHORT_LOGIN = "Use short login" +LABEL_USE_AUTH = "Use authentication" +LABEL_USE_PHP_MAIL = "Use php mail() function" +BUTTON_TEST = "Test" +BUTTON_WHITE_LIST = "White List" +BUTTON_SIEVE_CONFIGURATION = "Sieve configuration" +BUTTON_BACK_TO_IMAP = "Back to IMAP settings" +BUTTON_BACK = "Back" +BUTTON_CLOSE = "Close" +BUTTON_ADD = "Add" +BUTTON_UPDATE = "Update" +WHITE_LIST_ALERT = "List of domain users webmail is allowed to access. +Use a space as delimiter." + +[POPUPS_PLUGIN] +TITLE_PLUGIN = "Plugin" +DESC_NOTHING_TO_CONFIGURE = "Nothing to configure" +BUTTON_CLOSE = "Close" +BUTTON_SAVE = "Save" +TOOLTIP_ABOUT_TITLE = "About" + +[POPUPS_ASK] +BUTTON_YES = "Yes" +BUTTON_NO = "No" +DESC_WANT_CLOSE_THIS_WINDOW = "Are you sure you want to close this window?" +DESC_WANT_DELETE_MESSAGES = "Are you sure you want to delete the message(s)?" + +[POPUPS_LANGUAGES] +TITLE_LANGUAGES = "Choose your language" + +[HINTS] +BETA = "beta" +UNSTABLE = "unstable" +WARNING = "Warning!" +NOT_SUPPORTED = "not supported" +REQUIRES_PHP_54 = "requires PHP 5.4 or greater" + +[ERRORS] +DOMAIN_ALREADY_EXISTS = "Domain already exists" +UNKNOWN_ERROR = "Unknown error" + +[NOTIFICATIONS] +INVALID_TOKEN = "Invalid token" +AUTH_ERROR = "Authentication failed" +ACCESS_ERROR = "Access error" +CONNECTION_ERROR = "Can't connect to server" +CAPTCHA_ERROR = "Incorrect CAPTCHA." +SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE = "This social ID is not assigned for any email account yet. Log in using email credentials and enable this feature in account settings." +SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE = "This social ID is not assigned for any email account yet. Log in using email credentials and enable this feature in account settings." +SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE = "This social ID is not assigned for any email account yet. Log in using email credentials and enable this feature in account settings." +DOMAIN_NOT_ALLOWED = "Domain is not allowed" +ACCOUNT_NOT_ALLOWED = "Account is not allowed" +ACCOUNT_TWO_FACTOR_AUTH_REQUIRED = "Two factor verification required" +ACCOUNT_TWO_FACTOR_AUTH_ERROR = "Two factor verification error" +COULD_NOT_SAVE_NEW_PASSWORD = "Could not save new password" +CURRENT_PASSWORD_INCORRECT = "Current password incorrect" +NEW_PASSWORD_SHORT = "Password is too short" +NEW_PASSWORD_WEAK = "Password is too easy" +NEW_PASSWORD_FORBIDDENT = "Password contains forbidden characters" +CONTACTS_SYNC_ERROR = "Contacts synchronization error" +CANT_GET_MESSAGE_LIST = "Can't get message list" +CANT_GET_MESSAGE = "Can't get message" +CANT_DELETE_MESSAGE = "Can't delete message" +CANT_MOVE_MESSAGE = "Can't move message" +CANT_SAVE_MESSAGE = "Can't save message" +CANT_SEND_MESSAGE = "Can't send message" +INVALID_RECIPIENTS = "Invalid recipients" +CANT_SAVE_FILTERS = "Can't save filters" +CANT_GET_FILTERS = "Can't get filters" +FILTERS_ARE_NOT_CORRECT = "Filters are not correct" +CANT_CREATE_FOLDER = "Can't create folder" +CANT_RENAME_FOLDER = "Can't rename folder" +CANT_DELETE_FOLDER = "Can't delete folder" +CANT_DELETE_NON_EMPTY_FOLDER = "Can't delete non-empty directory" +CANT_SUBSCRIBE_FOLDER = "Can't subscribe folder" +CANT_UNSUBSCRIBE_FOLDER = "Can't unsubscribe folder" +CANT_SAVE_SETTINGS = "Can't save settings" +CANT_SAVE_PLUGIN_SETTINGS = "Can't save settings" +DOMAIN_ALREADY_EXISTS = "Domain already exists" +CANT_INSTALL_PACKAGE = "Failed to install package" +CANT_DELETE_PACKAGE = "Failed to remove package" +INVALID_PLUGIN_PACKAGE = "Invalid plugin package" +UNSUPPORTED_PLUGIN_PACKAGE = "Unsupported plugin package" +LICENSING_SERVER_IS_UNAVAILABLE = "Subscription server is unvailable" +LICENSING_DOMAIN_EXPIRED = "Subscription for this domain has expired." +LICENSING_DOMAIN_BANNED = "Subscription for this domain is banned." +DEMO_SEND_MESSAGE_ERROR = "For security purposes, this account is not allowed to send messages to external e-mail addresses!" +DEMO_ACCOUNT_ERROR = "For security purposes, this account is not allowed for this action!" +ACCOUNT_ALREADY_EXISTS = "Account already exists" +MAIL_SERVER_ERROR = "An error has occured while accessing mail server" +INVALID_INPUT_ARGUMENT = "Invalid input argument" +UNKNOWN_ERROR = "Unknown error" + +[STATIC] +BACK_LINK = "Reload" +DOMAIN_LIST_DESC = "List of domains webmail is allowed to access." +PHP_EXSTENSIONS_ERROR_DESC = "Required PHP extension are not available in your PHP configuration!" +PHP_VERSION_ERROR_DESC = "Your PHP version (%VERSION%) is lower than the minimal required 5.3.0!" +NO_SCRIPT_TITLE = "JavaScript is required for this application." +NO_SCRIPT_DESC = "JavaScript support is not available in your browser. +Please enable JavaScript support in your browser settings and retry." +NO_COOKIE_TITLE = "Cookies support is required for this application." +NO_COOKIE_DESC = "Cookies support is not available in your browser. +Please enable Cookie support in your browser settings and retry." +BAD_BROWSER_TITLE = "Your browser is outdated." +BAD_BROWSER_DESC = "To use all the features of the application, +download and install one of these browsers:" \ No newline at end of file diff --git a/rainloop/v/0.0.0/langs/admin/pl.ini b/rainloop/v/0.0.0/langs/admin/pl.ini new file mode 100644 index 000000000..b19479857 --- /dev/null +++ b/rainloop/v/0.0.0/langs/admin/pl.ini @@ -0,0 +1,321 @@ + +[LOGIN] +LABEL_LOGIN = "Login" +LABEL_PASSWORD = "Hasło" +BUTTON_LOGIN = "Zaloguj" + +[TOP_PANEL] +LABEL_PREMIUM = "Premium" +LABEL_ADMIN_PANEL = "Panel administracyjny" + +[TABS_LABELS] +LABEL_GENERAL_NAME = "Ogólne" +LABEL_LOGIN_NAME = "Login" +LABEL_BRANDING_NAME = "Personalizacja" +LABEL_CONTACTS_NAME = "Kontakty" +LABEL_DOMAINS_NAME = "Domeny" +LABEL_SECURITY_NAME = "Bezpieczeństwo" +LABEL_INTEGRATION_NAME = "Integracja" +LABEL_PLUGINS_NAME = "Wtyczki" +LABEL_PACKAGES_NAME = "Zarządzanie wtyczkami" +LABEL_LICENSING_NAME = "Licencjonowanie" +LABEL_ABOUT_NAME = "O skrypcie" + +[TAB_GENERAL] +LEGEND_INTERFACE = "Interfejs" +LABEL_LANGUAGE = "Język:" +LABEL_LANGUAGE_ADMIN = "Język (admin):" +LABEL_THEME = "Motyw:" +LABEL_ALLOW_LANGUAGES_ON_SETTINGS = "Zezwól użytkownikowi na wybór języka" +LABEL_ALLOW_THEMES_ON_SETTINGS = "Zezwól użytkownikowi na zmianę motywu" +LABEL_ALLOW_BACKGROUND_ON_SETTINGS = "Zezwól użytkownikowi na użycie własnego tła" +LABEL_SHOW_THUMBNAILS = "Pokaż miniatury (załączniki)" +LABEL_ALLOW_GRAVATAR = "Zezwól na używanie gravatarów" +LEGEND_MAIN = "Główne" +LABEL_ATTACHMENT_SIZE_LIMIT = "Maks. rozmiar zał.:" +LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Zezwól na dodatkowe konta" +LABEL_ALLOW_IDENTITIES = "Zezwól na posiadanie wielu tożsamości" +LABEL_ALLOW_TEMPLATES = "Zezwól na używanie szablonów" +ALERT_WARNING = "Ostrzeżenie!" +HTML_ALERT_WEAK_PASSWORD = "Korzystasz z domyślnego hasła administratora. +
+Ze względów bezpieczeństwa, proszę +zmienić hasło +na inne." + +[TAB_LOGIN] +LEGEND_LOGIN_SCREEN = "Logowanie" +LABEL_DEFAULT_DOMAIN = "Domyślna domena:" +LABEL_DETERMINE_USER_DOMAIN = "Spróbuj określić domenę użytkownika" +LABEL_ALLOW_LANGUAGES_ON_LOGIN = "Zezwól na zmianę języka podczas logowania" +LABEL_DETERMINE_USER_LANGUAGE = "Spróbuj określić język użytkownika" + +[TAB_BRANDING] +LEGEND_BRANDING = "Personalizacja" +LABEL_PAGE_TITLE = "Tytuł strony:" +LABEL_LOADING_DESCRIPTION = "Komunikat ład. strony:" +LEGEND_LOGIN = "Login" +LABEL_LOGIN_LOGO = "Logo:" +LABEL_LOGIN_DESCRIPTION = "Opis:" +LABEL_LOGIN_BACKGROUND = "Tło:" +LABEL_LOGIN_CUSTOM_CSS = "Własny arkusz stylów:" +LABEL_LOGIN_SHOW_POWERED_LINK = "Pokaż link: \"Powered by RainLoop\"" +LEGEND_USER = "Użytkownik" +LABEL_USER_LOGO = "Logo:" +LABEL_USER_LOGO_TITLE = "Tytuł loga:" +LABEL_USER_LOGO_MESSAGE = "Logo (widok wiad.)" +LABEL_USER_CUSTOM_CSS = "Własny arkusz stylów:" +LEGEND_WELCOME_PAGE = "Str. główna" +LABEL_WELCOME_PAGE_TITLE = "Tytuł:" +LABEL_WELCOME_PAGE_URL = "Adres URL:" +LABEL_WELCOME_PAGE_DISPLAY = "Wyświetl:" +OPTION_WELCOME_PAGE_DISPLAY_NONE = "nigdy" +OPTION_WELCOME_PAGE_DISPLAY_ONCE = "raz" +OPTION_WELCOME_PAGE_DISPLAY_ALWAYS = "zawsze" +HTML_ALERT_PREMIUM = "Ta opcja jest dostępna tylko dla licencji premium." + +[TAB_CONTACTS] +LEGEND_CONTACTS = "Kontakty" +LEGEND_STORAGE = "Baza danych (PDO)" +LABEL_ENABLE_CONTACTS = "Włącz kontakty" +LABEL_ALLOW_SYNC = "Zezwól na synchronizację kontaktów (przy użyciu zewnętrznego serwera CardDAV)" +LABEL_STORAGE_TYPE = "Typ:" +LABEL_STORAGE_DSN = "Adres DSN:" +LABEL_STORAGE_USER = "Użytkownik:" +LABEL_STORAGE_PASSWORD = "Hasło:" +BUTTON_TEST = "Testuj" +ALERT_NOTICE = "Powiadomienie!" +HTML_ALERT_DO_NOT_USE_THIS_DATABASE = "Nie używaj tej bazy danych z dużą ilością aktywnych użytkowników." +HTML_ALERT_DOES_NOT_SUPPORTED = "Twój system nie zawiera wsparcia dla obsługi kontaktów. +
+Musisz zainstalować lub uruchomić na serwerze jedno z rozszerzeń PDO (SQLite / MySQL / PostgreSQL)." + +[TAB_DOMAINS] +LEGEND_DOMAINS = "Domeny" +BUTTON_ADD_DOMAIN = "Dodaj domenę" +DELETE_ARE_YOU_SURE = "Czy na pewno?" +HTML_DOMAINS_HELPER = "Lista domen, do których można uzyskać dostęp poprzez tego klienta. +
Kliknij na nazwę, aby skonfigurować domenę." + +[TAB_SECURITY] +LEGEND_SECURITY = "Bezpieczeństwo" +LABEL_ALLOW_TWO_STEP = "Zezwól na dwuskładnikową autoryzację" +LABEL_FORCE_TWO_STEP = "Wymuś dwuskładnikową autoryzację" +LABEL_USE_IMAGE_PROXY = "Użyj lokalnego serwera proxy dla zewnętrznych obrazów" +LABEL_ALLOW_OPEN_PGP = "Zezwól na użycie OpenPGP" +LABEL_SHOW_PHP_INFO = "Pokaż informacje o wersji PHP" +LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS = "Dane dostępowe panelu administracyjnego" +LABEL_CURRENT_PASSWORD = "Bieżące hasło:" +LABEL_NEW_LOGIN = "Nowy login:" +LABEL_NEW_PASSWORD = "Nowe hasło:" +LABEL_REPEAT_PASSWORD = "Powtórz hasło:" +BUTTON_UPDATE_PASSWORD = "Zaktualizuj hasło" +LEGEND_SSL = "SSL" +LABEL_REQUIRE_VERIFICATION = "Wymagaj sprawdzania poprawności certyfikatów SSL (IMAP/SMTP)" +LABEL_ALLOW_SELF_SIGNED = "Zezwól na używanie certyfikatów podpisanych przez siebie" + +[TAB_INTEGRATIONS] +LEGEND_GOOGLE = "Google" +LABEL_ENABLE_GOOGLE = "Włącz obsługę platformy Google" +LABEL_GOOGLE_AUTH = "Autoryzacja" +LABEL_GOOGLE_DRIVE = "Obsługa dysku Google (widok tworz. wiadomości)" +LABEL_GOOGLE_PREVIEW = "Obsługa przeglądarki Google (podgląd dla plików: Microsoft Word, Excel i PowerPoint)" +LABEL_GOOGLE_CLIENT_ID = "Identyfikator:" +LABEL_GOOGLE_CLIENT_SECRET = "Hasło:" +LABEL_GOOGLE_API_KEY = "Klucz API:" +HINT_GOOGLE_API_KEY = "Wymagane dla obsługi interfejsu usługi: 'Dysk Google'" +LEGEND_FACEBOOK = "Facebook" +LABEL_ENABLE_FACEBOOK = "Włącz obsługę platformy Facebook (autoryzacja)" +LABEL_FACEBOOK_APP_ID = "Identyfikator aplikacji:" +LABEL_FACEBOOK_APP_SECRET = "Hasło aplikacji:" +LEGEND_TWITTER = "Twitter" +LABEL_ENABLE_TWITTER = "Włącz obsługę platformy Twitter (autoryzacja)" +LABEL_TWITTER_CONSUMER_KEY = "Klucz użytkownika:" +LABEL_TWITTER_CONSUMER_SECRET = "Hasło użytkownika:" +LEGEND_DROPBOX = "Dropbox" +LABEL_ENABLE_DROPBOX = "Włącz obsługę platformy Dropbox" +LABEL_DROPBOX_API_KEY = "Klucz API:" +TOP_ALERT = "Szczegółowe informacje na temat obsługi platform, można znaleźść pod adresem: " + +[TAB_PLUGINS] +LEGEND_PLUGINS = "Wtyczki" +LABEL_ENABLE_PLUGINS = "Włącz obsługę wtyczek" +ALERT_NO_PLUGINS = "Nie zainstalowano żadnych wtyczek." +LINK_INSTALL_NEW = "Kliknij tutaj, aby zainstalować nowe wtyczki!" +HINT_CLICK_NAME = "Kliknij na nazwę, aby skonfigurować wtyczkę." + +[TAB_PACKAGES] +LEGEND_AVAILABLE_FOR_UPDATE = "Aktualizacja" +LEGEND_AVAILABLE_FOR_INSTALLATION = "Do zainstalowania" +LEGEND_INSTALLED_PACKAGES = "Zainstalowane" +ALERT_CANNOT_ACCESS_REPOSITORY = "Nie można uzyskać dostępu do repozytorium." + +[TAB_LICENSING] +LABEL_YOUR_DOMAIN = "Domena:" +LABEL_VERSION = "Wersja:" +LABEL_CHECKING = "sprawdzanie..." +TYPE_BASIC_HINT = "Ta domena nie jest licencjonowana do użytku komercyjnego." +TYPE_BASIC_HINT_2 = "Nie można dodać licencji dla tej domeny." +HTML_ALERT_TOP_1 = "RainLoop Webmail korzysta z licencji:" +HTML_ALERT_TOP_2 = "Możesz używać tego klienta za darmo, tylko dla prywatnych (własnych) projektów." +HTML_ALERT_TOP_3 = "Do komercyjnego użytku (używania dodatkowych opcji) RainLoop Webmail, wymagane jest posiadanie +ważnej subskrypcji." +TYPE_PREMIUM_LIFETIME = "Dożywotnia" +TYPE_PREMIUM_HINT = "Ta domena nie jest licencjonowana dla użytku komercyjnego." +LABEL_SUB_EXPIRES = "Subskrypcja wygasa:" +BUTTON_ACTIVATE = "Aktywuj klucz" +BUTTON_PURCHASE = "Kup klucz" +BUTTON_TRIAL = "Wersja testowa" + +[TAB_ABOUT] +LEGEND_ABOUT = "O skrypcie" +LABEL_TAG_HINT = "Prosty, nowoczesny i szybki klient pocztowy" +LABEL_ALL_RIGHTS_RESERVED = "Wszystkie prawa zastrzeżone." +HINT_READ_CHANGE_LOG = "Przed aktualizacją, proszę przeczytać listę zmian." +HINT_IS_UP_TO_DATE = "Klient RainLoop jest aktualny." +HTML_NEW_VERSION = "Dostępna jest nowa wersja: %VERSION%." +LABEL_UPDATING = "Aktualizowanie..." +LABEL_CHECKING = "Szukanie aktualizacji..." +BUTTON_UPDATE = "Zaktualizuj" +BUTTON_DOWNLOAD = "Pobierz" +BUTTON_CHANGELOG = "Lista zmian" + +[POPUPS_ACTIVATE] +TITLE_ACTIVATE = "Aktywacja klucza subskrypcji" +TITLE_ACTIVATION = "Aktywowanie..." +LABEL_DOMAIN = "Domena:" +LABEL_SUB_KEY = "Klucz subskrypcji:" +BUTTON_ACTIVATE = "Aktywuj" +LABEL_ACTIVATED = "Aktywowano" +ERROR_INVALID_SUBS_KEY = "Niepoprawny klucz subskrypcji" +SUBS_KEY_ACTIVATED = "Aktywowano klucz subskrypcji" +HTML_DESC = "Subskrypcja premium dla domeny: %DOMAIN%, zostanie przedłużona po aktywacji. +
+Zwróc uwagę, że klucz subskrypcji może być aktywowany tylko dla jednej domeny. +

+Po uruchomieniu aktywacji, nie można jej przerwac lub anulować." + +[POPUPS_DOMAIN] +TITLE_ADD_DOMAIN = "Dodawanie domeny" +TITLE_ADD_DOMAIN_WITH_NAME = "Dodawanie domeny: \"%NAME%\"" +TITLE_EDIT_DOMAIN = "Edycja domeny: \"%NAME%\"" +LABEL_NAME = "Nazwa" +NAME_HELPER = "obsługiwany znak wieloznaczności - *" +LABEL_IMAP = "IMAP" +LABEL_SMTP = "SMTP" +LABEL_SIEVE = "SIEVE" +LABEL_SERVER = "Serwer:" +LABEL_PORT = "Port:" +LABEL_SECURE = "Rodzaj połączenia:" +LABEL_WHITE_LIST = "Biała lista" +SECURE_OPTION_NONE = "Bez zabezpieczeń" +SECURE_OPTION_SSL = "SSL/TLS" +SECURE_OPTION_STARTTLS = "STARTTLS" +LABEL_ALLOW_SIEVE_SCRIPTS = "Zezwól na skrypty sieve" +LABEL_ALLOW_USER_SCRIPT = "Zezwól na spersonalizowany skrypt użytkownika" +LABEL_USE_SHORT_LOGIN = "Użyj krótkiego loginu" +LABEL_USE_AUTH = "Użyj autoryzacji" +LABEL_USE_PHP_MAIL = "Użyj funkcji php: 'mail()'" +BUTTON_TEST = "Test" +BUTTON_WHITE_LIST = "Biała lista" +BUTTON_SIEVE_CONFIGURATION = "Konfiguracja sieve" +BUTTON_BACK_TO_IMAP = "Powrót do ustawień serwera IMAP" +BUTTON_BACK = "Wstecz" +BUTTON_CLOSE = "Zamknij" +BUTTON_ADD = "Dodaj" +BUTTON_UPDATE = "Zaktualizuj" +WHITE_LIST_ALERT = "Lista użytkowników domeny, którzy mogą uzyskać dostęp poprzez tego klienta. +Użyj spacji do rozdzielenia." + +[POPUPS_PLUGIN] +TITLE_PLUGIN = "Wtyczka: " +DESC_NOTHING_TO_CONFIGURE = "Brak opcji do skonfigurowania" +BUTTON_CLOSE = "Zamknij" +BUTTON_SAVE = "Zapisz" +TOOLTIP_ABOUT_TITLE = "O wtyczce" + +[POPUPS_ASK] +BUTTON_YES = "Tak" +BUTTON_NO = "Nie" +DESC_WANT_CLOSE_THIS_WINDOW = "Czy na pewno chcesz zamknąć to okno?" +DESC_WANT_DELETE_MESSAGES = "Czy na pewno chcesz usunąć tą wiadomość(-i)?" + +[POPUPS_LANGUAGES] +TITLE_LANGUAGES = "Wybierz swój język" + +[HINTS] +BETA = "Beta" +UNSTABLE = "Niestabilna" +WARNING = "Ostrzeżenie!" +NOT_SUPPORTED = "nieobsługiwana" +REQUIRES_PHP_54 = "Wymaga PHP w wersji 5.4 lub wyższej" + +[ERRORS] +DOMAIN_ALREADY_EXISTS = "Ta domena już istnieje" +UNKNOWN_ERROR = "Nieznany błąd" + +[NOTIFICATIONS] +INVALID_TOKEN = "Nieważny token" +AUTH_ERROR = "Autoryzacja zakończona niepowodzeniem" +ACCESS_ERROR = "Błąd dostępu" +CONNECTION_ERROR = "Nie można połączyć się z serwerem" +CAPTCHA_ERROR = "Niepoprawny kod CAPTCHA." +SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE = "Logowanie poprzez tą platformę, nie zostało jeszcze aktywowane dla żadnego z kont e-mail. Zaloguj się używając loginu i hasła, a następnie włącz tą funkcję w ustawieniach konta." +SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE = "Logowanie poprzez tą platformę, nie zostało jeszcze aktywowane dla żadnego z kont e-mail. Zaloguj się używając loginu i hasła, a następnie włącz tą funkcję w ustawieniach konta." +SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE = "Logowanie poprzez tą platformę, nie zostało jeszcze aktywowane dla żadnego z kont e-mail. Zaloguj się używając loginu i hasła, a następnie włącz tą funkcję w ustawieniach konta." +DOMAIN_NOT_ALLOWED = "Brak zezwolenia na użycie tej domeny" +ACCOUNT_NOT_ALLOWED = "Brak zezwolenia dla tego konta" +ACCOUNT_TWO_FACTOR_AUTH_REQUIRED = "Wymagana dwuskładnikowa autoryzacja" +ACCOUNT_TWO_FACTOR_AUTH_ERROR = "Błąd autoryzacji dwuskładnikowej" +COULD_NOT_SAVE_NEW_PASSWORD = "Nie można było zapisać nowego hasła" +CURRENT_PASSWORD_INCORRECT = "Bieżące hasło jest niepoprawne" +NEW_PASSWORD_SHORT = "Wybrane hasło jest za krótkie" +NEW_PASSWORD_WEAK = "Wybrane hasło jest zbyt proste" +NEW_PASSWORD_FORBIDDENT = "Wybrane hasło zawiera zakazane znaki" +CONTACTS_SYNC_ERROR = "Błąd synchronizacji kontaktów" +CANT_GET_MESSAGE_LIST = "Nie można pobrać listy wiadomości" +CANT_GET_MESSAGE = "Nie można pobrać wiadomości" +CANT_DELETE_MESSAGE = "Nie można usunąć wiadomości" +CANT_MOVE_MESSAGE = "Nie można przenieść wiadomości" +CANT_SAVE_MESSAGE = "Nie można zapisać wiadomości" +CANT_SEND_MESSAGE = "Nie można wysłać wiadomości" +INVALID_RECIPIENTS = "Niepoprawny adres odbiorcy" +CANT_SAVE_FILTERS = "Nie można zapisać filtrów" +CANT_GET_FILTERS = "Nie można pobrać filtrów" +FILTERS_ARE_NOT_CORRECT = "Brak poprawności filtrów" +CANT_CREATE_FOLDER = "Nie można utworzyć folderu" +CANT_RENAME_FOLDER = "Nie można zmienić nazwy folderu" +CANT_DELETE_FOLDER = "Nie można usunąć folderu" +CANT_DELETE_NON_EMPTY_FOLDER = "Nie można usunąć folderu, w którym znajduje się zawartość" +CANT_SUBSCRIBE_FOLDER = "Nie można zasubskrybować folderu" +CANT_UNSUBSCRIBE_FOLDER = "Nie można usunąć subskrypcji folderu" +CANT_SAVE_SETTINGS = "Nie można zapisać ustawień" +CANT_SAVE_PLUGIN_SETTINGS = "Nie można zapisać ustawień wtyczki" +DOMAIN_ALREADY_EXISTS = "Ta domena już istnieje" +CANT_INSTALL_PACKAGE = "Instalacja wtyczki zakończona niepowodzeniem" +CANT_DELETE_PACKAGE = "Usunięcie wtyczki zakończone niepowodzeniem" +INVALID_PLUGIN_PACKAGE = "Niepoprawna wtyczka" +UNSUPPORTED_PLUGIN_PACKAGE = "Nieobsługiwana wtyczka" +LICENSING_SERVER_IS_UNAVAILABLE = "Serwer aktywacji subskrypcji jest niedostępny" +LICENSING_DOMAIN_EXPIRED = "Subskrypcja dla tej domeny wygasła." +LICENSING_DOMAIN_BANNED = "Subskrypcja dla tej domeny została zawieszona." +DEMO_SEND_MESSAGE_ERROR = "Ze względów bezpieczeństwa, to konto nie posiada zezwolenia na wysyłanie wiadomości na zewnętrzne adresy e-mail!" +DEMO_ACCOUNT_ERROR = "Ze względów bezpieczeństwa, to konto nie posiada uprawnień do wykonania tego zadania!" +ACCOUNT_ALREADY_EXISTS = "To konto już istnieje" +MAIL_SERVER_ERROR = "Wystąpił błąd podczas dostępu do serwera" +INVALID_INPUT_ARGUMENT = "Niepoprawny argument wejścia" +UNKNOWN_ERROR = "Nieznany błąd" + +[STATIC] +BACK_LINK = "Odśwież" +DOMAIN_LIST_DESC = "Lista domen, do których można uzyskać dostęp za pomocą tego klienta." +PHP_EXSTENSIONS_ERROR_DESC = "Brak wymaganych rozszerzeń w konfiguracji PHP!" +PHP_VERSION_ERROR_DESC = "Twoja wersja PHP: (%VERSION%), jest niższa niż minimalna: 5.3.0!" +NO_SCRIPT_TITLE = "Ta aplikacja do poprawnej pracy wymaga javascript-u." +NO_SCRIPT_DESC = "Twoja przeglądarka nie obsługuje javascript-u. +Proszę o jego włączenie i ponowną próbę." +NO_COOKIE_TITLE = "Obsługa plików cookies jest wymagana dla poprawnego działania skryptu." +NO_COOKIE_DESC = "Twoja przeglądarka nie obsługuje plików cookies. +Proszę o ich włączenie i ponowną próbę." +BAD_BROWSER_TITLE = "Posiadasz nieaktualną wersję przeglądarki." +BAD_BROWSER_DESC = "Aby korzystać ze wszyskich funkcji tego skryptu, pobierz i zainstaluj jedną z niżej wymienionych przeglądarek:" \ No newline at end of file diff --git a/rainloop/v/0.0.0/langs/admin/pt-br.ini b/rainloop/v/0.0.0/langs/admin/pt-br.ini index f85961252..064506f74 100644 --- a/rainloop/v/0.0.0/langs/admin/pt-br.ini +++ b/rainloop/v/0.0.0/langs/admin/pt-br.ini @@ -34,12 +34,13 @@ LABEL_ALLOW_GRAVATAR = "Permitir Gravatar" LEGEND_MAIN = "Principal" LABEL_ATTACHMENT_SIZE_LIMIT = "Tamanho limite de anexo" LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Permitir contas adicionais" +LABEL_ALLOW_IDENTITIES = "Allow multiple identities" LABEL_ALLOW_TEMPLATES = "Permitir templates" ALERT_WARNING = "Aviso!" HTML_ALERT_WEAK_PASSWORD = "Você está usando a senha administrativa padrão.
-Por motivo de segurança por favor -troque a senha +Por motivo de segurança por favor +troque a senha agora." [TAB_LOGIN] @@ -61,6 +62,8 @@ LABEL_LOGIN_CUSTOM_CSS = "CSS personalizado" LABEL_LOGIN_SHOW_POWERED_LINK = "Mostrar link \"Powered by RainLoop\"" LEGEND_USER = "Internas" LABEL_USER_LOGO = "Logo" +LABEL_USER_LOGO_TITLE = "Logo Title" +LABEL_USER_LOGO_MESSAGE = "Logo (Message View)" LABEL_USER_CUSTOM_CSS = "CSS personalizado" LEGEND_WELCOME_PAGE = "Página de boas-vindas" LABEL_WELCOME_PAGE_TITLE = "Título" @@ -130,7 +133,7 @@ LABEL_ENABLE_TWITTER = "Habilitar integração com o Twitter (Autenticação)" LABEL_TWITTER_CONSUMER_KEY = "Consumer Key" LABEL_TWITTER_CONSUMER_SECRET = "Consumer Secret" LEGEND_DROPBOX = "Dropbox" -LABEL_ENABLE_DROPBOX = "Habilitar integração com o Dropbox (Anexos)" +LABEL_ENABLE_DROPBOX = "Habilitar integração com o Dropbox" LABEL_DROPBOX_API_KEY = "Api Key" TOP_ALERT = "Informações detalhadas sobre as integrações em" @@ -151,14 +154,12 @@ ALERT_CANNOT_ACCESS_REPOSITORY = "Não foi possível acessar o repositório no m LABEL_YOUR_DOMAIN = "Seu domínio" LABEL_VERSION = "Versão" LABEL_CHECKING = "Checando" -TYPE_BASIC = "Básico" TYPE_BASIC_HINT = "Esse domínio não está licenciado para uso comercial (com recursos adicionais)." TYPE_BASIC_HINT_2 = "Esse domínio não pode ser licenciado." HTML_ALERT_TOP_1 = "RainLoop Webmail é licenciado sob" HTML_ALERT_TOP_2 = "Você é livre para usá-lo em seus projetos pessoais." -HTML_ALERT_TOP_3 = "Uso comercial (com recursos adicionais) do RainLoop Webmail +HTML_ALERT_TOP_3 = "Uso comercial (com recursos adicionais) do RainLoop Webmail requer uma assinatura." -TYPE_PREMIUM = "Premium" TYPE_PREMIUM_LIFETIME = "Lifetime" TYPE_PREMIUM_HINT = "Esse domínio está licenciado para uso comercial (com recursos adicionais)." LABEL_SUB_EXPIRES = "A assinatura expira em:" @@ -237,7 +238,7 @@ TOOLTIP_ABOUT_TITLE = "Sobre" BUTTON_YES = "Sim" BUTTON_NO = "Não" DESC_WANT_CLOSE_THIS_WINDOW = "Você tem certeza que deseja fechar esta janela?" -DESC_WANT_DELETE_MESSAGES = Você tem certeza que deseja apagar a(s) mensagem(s)?" +DESC_WANT_DELETE_MESSAGES = "Você tem certeza que deseja apagar a(s) mensagem(s)?" [POPUPS_LANGUAGES] TITLE_LANGUAGES = "Selecionar idioma" diff --git a/rainloop/v/0.0.0/langs/admin/ru.ini b/rainloop/v/0.0.0/langs/admin/ru.ini index 4d9516d4c..56a597af4 100644 --- a/rainloop/v/0.0.0/langs/admin/ru.ini +++ b/rainloop/v/0.0.0/langs/admin/ru.ini @@ -15,7 +15,7 @@ LABEL_BRANDING_NAME = "Брендинг" LABEL_CONTACTS_NAME = "Контакты" LABEL_DOMAINS_NAME = "Домены" LABEL_SECURITY_NAME = "Безопасность" -LABEL_INTEGRATION_NAME = "Инеграция" +LABEL_INTEGRATION_NAME = "Интеграция" LABEL_PLUGINS_NAME = "Плагины" LABEL_PACKAGES_NAME = "Пакеты" LABEL_LICENSING_NAME = "Лицензия" @@ -34,6 +34,7 @@ LABEL_ALLOW_GRAVATAR = "Разрешить граватары" LEGEND_MAIN = "Основное" LABEL_ATTACHMENT_SIZE_LIMIT = "Предельный размер вложений" LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Разрешить дополнительные аккаунты" +LABEL_ALLOW_IDENTITIES = "Разрешить множественные профили" LABEL_ALLOW_TEMPLATES = "Разрешить шаблоны" ALERT_WARNING = "Внимание!" HTML_ALERT_WEAK_PASSWORD = "Вы используете пароль администратора по умолчанию. @@ -60,6 +61,8 @@ LABEL_LOGIN_CUSTOM_CSS = "Кастомный CSS" LABEL_LOGIN_SHOW_POWERED_LINK = "Показывать ссылку \"Powered by RainLoop\"" LEGEND_USER = "Экран пользователя" LABEL_USER_LOGO = "Логотип" +LABEL_USER_LOGO_TITLE = "Название логотипа" +LABEL_USER_LOGO_MESSAGE = "Логотип (Message View)" LABEL_USER_CUSTOM_CSS = "Кастомный CSS" LEGEND_WELCOME_PAGE = "Приветствие" LABEL_WELCOME_PAGE_TITLE = "Название" @@ -129,7 +132,7 @@ LABEL_ENABLE_TWITTER = "Включить Twitter интеграцию (Авто LABEL_TWITTER_CONSUMER_KEY = "Consumer Key" LABEL_TWITTER_CONSUMER_SECRET = "Consumer Secret" LEGEND_DROPBOX = "Dropbox" -LABEL_ENABLE_DROPBOX = "Включить Dropbox интеграцию (Экран нового сообщения)" +LABEL_ENABLE_DROPBOX = "Включить Dropbox интеграцию" LABEL_DROPBOX_API_KEY = "Api Key" TOP_ALERT = "Подробная информация о социальной интеграции находится на" @@ -150,14 +153,12 @@ ALERT_CANNOT_ACCESS_REPOSITORY = "Не удается получить дост LABEL_YOUR_DOMAIN = "Ваш домен" LABEL_VERSION = "Версия" LABEL_CHECKING = "Проверка" -TYPE_BASIC = "Базовая" TYPE_BASIC_HINT = "Этот домен не имеет лицензию для коммерческого использования (с дополнительными функциями)." TYPE_BASIC_HINT_2 = "Этот домен не может быть лицензирован." HTML_ALERT_TOP_1 = "Код RainLoop Webmail лицензирован под" HTML_ALERT_TOP_2 = "Вы можете свободно использовать его в своих личных проектах." HTML_ALERT_TOP_3 = "Коммерческое использование (с дополнительными функциями) RainLoop Webmail требует получение лицензии." -TYPE_PREMIUM = "Премиум" TYPE_PREMIUM_LIFETIME = "бесконечная" TYPE_PREMIUM_HINT = "Этот домен не имеет лицензию для коммерческого использования (с дополнительными функциями)." LABEL_SUB_EXPIRES = "Подписка истекает:" diff --git a/rainloop/v/0.0.0/langs/ar.ini b/rainloop/v/0.0.0/langs/ar.ini new file mode 100644 index 000000000..1fffb29a1 --- /dev/null +++ b/rainloop/v/0.0.0/langs/ar.ini @@ -0,0 +1,726 @@ + +[LOGIN] +LABEL_EMAIL = "إيميل" +LABEL_LOGIN = "تسيجيل الدخول" +LABEL_PASSWORD = "كلمة السر" +LABEL_SIGN_ME = "تذكرني" +LABEL_VERIFICATION_CODE = "كود التحقق" +LABEL_DONT_ASK_VERIFICATION_CODE = "لاتسألني عن الكود الا بعد مرور اسبوعين" +BUTTON_SIGN_IN = "الدخول" +TITLE_SIGN_IN_GOOGLE = "Google+ الدخول باستخدام" +TITLE_SIGN_IN_FACEBOOK = "Facebook الدخول باستخدام" +TITLE_SIGN_IN_TWITTER = "Twitter الدخول باستخدام" +LABEL_FORGOT_PASSWORD = "نسيت كلمة السر" +LABEL_REGISTRATION = "التسجيل" + +[TOP_TOOLBAR] +BUTTON_ADD_ACCOUNT = "ضفّ حساب" +BUTTON_SETTINGS = "الإعدادات" +BUTTON_HELP = "المساعدة" +BUTTON_LOGOUT = "تسجيل الخروج" + +[SEARCH] +MAIN_INPUT_PLACEHOLDER = "بحث" +TITLE_ADV = "البحث المطور" +LABEL_ADV_FROM = "من" +LABEL_ADV_TO = "الى" +LABEL_ADV_SUBJECT = "الموضوع" +LABEL_ADV_TEXT = "النص" +LABEL_ADV_HAS_ATTACHMENT = "يحتوي على مرفق" +LABEL_ADV_HAS_ATTACHMENTS = "يحتوي مرفقات" +LABEL_ADV_FLAGGED = "عليه علم" +LABEL_ADV_UNSEEN = "لم يقرأ" +LABEL_ADV_DATE = "التاريخ" +LABEL_ADV_DATE_ALL = "الكل" +LABEL_ADV_DATE_3_DAYS = "منذ 3 أيام" +LABEL_ADV_DATE_7_DAYS = "منذ أسبوع" +LABEL_ADV_DATE_MONTH = "منذ شهر" +LABEL_ADV_DATE_3_MONTHS = "منذ 3 أشهر" +LABEL_ADV_DATE_6_MONTHS = "منذ 6 أشهر" +LABEL_ADV_DATE_YEAR = "منذ سنة" +BUTTON_ADV_SEARCH = "إبحث" + +[PREVIEW_POPUP] +FULLSCREEN = "إعداد افتراضي لوضع ملء الشاشة" +ZOOM = "Zoom in/out" +CLOSE = "أغلق (Esc)" +LOADING = "..جاري التحميل" +GALLERY_PREV = "السابق( السهم اليسار)" +GALLERY_NEXT = "اليمين(السهم اليميني)" +GALLERY_COUNTER = "%curr% of %total%" +IMAGE_ERROR = "الصورة لم نتمكن من عرض." +AJAX_ERROR = "المحتوى لم نتمكن من عرض." + +[FOLDER_LIST] +BUTTON_COMPOSE = "إنشاء" +BUTTON_CONTACTS = "جهات الإتصال" +INBOX_NAME = "البريد الوارد" +SENT_NAME = "البريد المرسل" +DRAFTS_NAME = "المسودات" +SPAM_NAME = "الرسائل غير المرغوب فيها" +TRASH_NAME = "المهملات" +ARCHIVE_NAME = "الأرشيف" + +[QUOTA] +TITLE = "Quota usage" + +[MESSAGE_LIST] +BUTTON_RELOAD = "أعد تحميل قائمة الرسائل" +BUTTON_MOVE_TO = "..انقل الى" +BUTTON_DELETE = "حذف" +BUTTON_ARCHIVE = "وضع في الأرشيف" +BUTTON_SPAM = "الإبلاغ عن الرسائل غير المرغوب فيها" +BUTTON_NOT_SPAM = "ليست رسائل غير مرغوب فيها" +BUTTON_EMPTY_FOLDER = "افرغ محتويات المجلد" +BUTTON_MULTY_FORWARD = "إعادة توجيه كملحقات" +BUTTON_DELETE_WITHOUT_MOVE = "الحذف نهائياً" +BUTTON_MORE = "المزيد" +MENU_SET_SEEN = "تعليمها بـ مقروءة" +MENU_SET_ALL_SEEN = "تعليم جميع الرسائل كـ مقروءة" +MENU_UNSET_SEEN = "تعليمها بـ غير مقروءة" +MENU_SET_FLAG = "مهمة" +MENU_UNSET_FLAG = "إزالة الأهمية" +MENU_SELECT_ALL = "الكل" +MENU_SELECT_NONE = "بدون" +MENU_SELECT_INVERT = "Invert" +MENU_SELECT_UNSEEN = "غير مقروء" +MENU_SELECT_SEEN = "مقروء" +MENU_SELECT_FLAGGED = "محدد كـ مهم" +MENU_SELECT_UNFLAGGED = "إزالة الأهمية" +EMPTY_LIST = "إفراغ القائمة" +EMPTY_SEARCH_LIST = "ليست هناك أية رسائل تطابق بحثك." +SEARCH_RESULT_FOR = "نتيجة البحث لـ \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "العودة الى قائمة الرسائل" +LIST_LOADING = "..جاري التحميل" +EMPTY_SUBJECT_TEXT = "(لايوجدموضوع)" +PUT_MESSAGE_HERE = "حرك الرسالة الى هنا.. لكي تراها في قائمة الرسائل" +TODAY_AT = "اليوم عند %TIME%" +YESTERDAY_AT = "البارحة عند %TIME%" +SEARCH_PLACEHOLDER = "البحث" +NEW_MESSAGE_NOTIFICATION = "يوجد لديك %COUNT% رسالة جديدة!" +QUOTA_SIZE = "Using %SIZE% (%PROC%%) of your %LIMIT%" + +[MESSAGE] +BUTTON_EDIT = "تعديل" +BUTTON_BACK = "العودة" +BUTTON_CLOSE = "إغلاق" +BUTTON_DELETE = "حذف" +BUTTON_ARCHIVE = "أرشيف" +BUTTON_SPAM = "رسالة غير مرغوبة" +BUTTON_NOT_SPAM = "ليست رسالة غير مرغوبة" +BUTTON_MOVE_TO = "انقل الى" +BUTTON_MORE = "المزيد" +BUTTON_REPLY = "الرد" +BUTTON_REPLY_ALL = "الرد على الجميع" +BUTTON_FORWARD = "إعادة توجيه" +BUTTON_FORWARD_AS_ATTACHMENT = "إعادة توجيه كملحقات" +BUTTON_EDIT_AS_NEW = "التعديل كـ جديد" +BUTTON_SHOW_IMAGES = "عرض الصور الخارجية" +BUTTON_NOTIFY_READ_RECEIPT = "لقد طلب المرسل أن يتم إعلامه في حال قراءة الرسالة" +BUTTON_IN_NEW_WINDOW = "العرض في نافذة منفصلة" +BUTTON_THREAD_LIST = "قائمة المواضيع" +BUTTON_THREAD_PREV = "السابق" +BUTTON_THREAD_NEXT = "التالي" +BUTTON_THREAD_MORE = "المزيد من الرسائل" +MENU_HEADERS = "Show message headers" +MENU_VIEW_ORIGINAL = "إظهار المصدر" +MENU_DOWNLOAD_ORIGINAL = ".eml التنزيل كملف" +MENU_FILTER_SIMILAR = "تصفية رسائل مثل هذه" +MENU_PRINT = "طباعة" +EMPTY_SUBJECT_TEXT = "(لايوجد موضوع)" +LABEL_SUBJECT = "الموضوع" +LABEL_DATE = "التاريخ" +LABEL_FROM = "من" +LABEL_FROM_SHORT = "من" +LABEL_TO = "الى" +LABEL_TO_SHORT = "الى" +LABEL_CC = "نسخة الى" +LABEL_BCC = "نسخة مخفية الوجهة" +LABEL_REPLY_TO = "الرد-الى" +PRINT_LABEL_FROM = "من" +PRINT_LABEL_TO = "الى" +PRINT_LABEL_CC = "نسخة الى" +PRINT_LABEL_BCC = "نسخة مخفية الوجهة" +PRINT_LABEL_REPLY_TO = "الرد-الى" +PRINT_LABEL_DATE = "التاريخ" +PRINT_LABEL_SUBJECT = "الموضوع" +PRINT_LABEL_ATTACHMENTS = "الملحقات" +MESSAGE_LOADING = "..جاري التحميل" +MESSAGE_VIEW_DESC = "حدد رسالة من القائمة ليتم عرضها هنا" +PGP_PASSWORD_INPUT_PLACEHOLDER = "كلمة السر" +PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" +PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "zip تنزيل كـ" +LINK_SAVE_TO_OWNCLOUD = "ownCloud الحفظ الى" +LINK_SAVE_TO_DROPBOX = "Dropbox الحفظ الى" + +[READ_RECEIPT] +SUBJECT = "إعلام بالقراءة (تم عرضها) - %SUBJECT%" +BODY = "هذا إعلام بأن الرسالة المرسلة قد تمت قرائتها %READ-RECEIPT%." + +[SUGGESTIONS] +SEARCHING_DESC = "يتم البحث..." + +[CONTACTS] +LEGEND_CONTACTS = "جهات الإتصال" +SEARCH_INPUT_PLACEHOLDER = "بحث" +BUTTON_ADD_CONTACT = "إضافة جهة إتصال" +BUTTON_CREATE_CONTACT = "إنشاء" +BUTTON_UPDATE_CONTACT = "تحديث" +BUTTON_IMPORT = "إستيراد (csv, vcf, vCard)" +BUTTON_EXPORT_VCARD = "تصدير كـ (vcf, vCard)" +BUTTON_EXPORT_CSV = "تصدير كـ (csv)" +ERROR_IMPORT_FILE = "خطأ في الإستيراد(نوع ملف غير صحيح)" +LIST_LOADING = "جاري التحميل" +EMPTY_LIST = "لايوجد جهات إتصال" +EMPTY_SEARCH = "لم يتم ايجاد جهة الإتصال" +CLEAR_SEARCH = "إزالة البحث" +CONTACT_VIEW_DESC = "حدد جهة إتصال من القائمة لكي يتم عرضها هنا" +LABEL_DISPLAY_NAME = "الإسم المعروض" +LABEL_EMAIL = "البريد الإلكتروني" +LABEL_PHONE = "رقم الهاتف" +LABEL_WEB = "الموقع" +LABEL_BIRTHDAY = "تاريخ الميلاد" +LINK_ADD_EMAIL = "قم باضافة البريد الالكتروني" +LINK_ADD_PHONE = "قم باضافة رقم الهاتف" +LINK_BIRTHDAY = "تاريخ الميلاد" +PLACEHOLDER_ENTER_DISPLAY_NAME = "ادخل الاسم المعروض" +PLACEHOLDER_ENTER_LAST_NAME = "ادخل اسم العائلة" +PLACEHOLDER_ENTER_FIRST_NAME = "ادخل الاسم" +PLACEHOLDER_ENTER_NICK_NAME = "ادخل اللقب" +LABEL_READ_ONLY = "قراءة فقط" +LABEL_SHARE = "مشاركة" +ADD_MENU_LABEL = "اضافة" +ADD_MENU_NICKNAME = "اللقب" +ADD_MENU_NOTES = "الملاحظات" +ADD_MENU_EMAIL = "البريد الإلكتروني" +ADD_MENU_PHONE = "الهاتف" +ADD_MENU_URL = "الرابط" +ADD_MENU_ADDRESS = "العنوان" +ADD_MENU_BIRTHDAY = "تاريخ الميلاد" +ADD_MENU_TAGS = "Tags" +BUTTON_SHARE_NONE = "لاأحد" +BUTTON_SHARE_ALL = "الجميع" +BUTTON_SYNC = "المزامنة (CardDAV)" + +[COMPOSE] +TITLE_FROM = "من" +TITLE_TO = "الى" +TITLE_CC = "نسخة الى" +TITLE_BCC = "نسخة مخفية الوجهة" +TITLE_REPLY_TO = "الرد-الى" +TITLE_SUBJECT = "الموضوع" +LINK_SHOW_INPUTS = "إظهار جميع الحقول" +BUTTON_SEND = "إرسال" +BUTTON_SAVE = "حفظ" +BUTTON_DELETE = "حذف" +BUTTON_CANCEL = "إلغاء" +BUTTON_MINIMIZE = "تصغير" +SAVED_TIME = "تم الحفظ عند %TIME%" +SAVED_ERROR_ON_SEND = "تم إرسال الرسالة.. ولكن لم يتم حفظها في مجلد المرسلات" +DISCARD_UNSAVED_DATA = "تجاهل البيانات الغير محفوظة؟" +ATTACH_FILES = "ارفاق الملفات" +ATTACH_DROP_FILES_DESC = "حرك الملفات الى هنا" +ATTACH_ITEM_CANCEL = "الغاء" +DROPBOX = "Dropbox" +GOOGLE_DRIVE = "Google Drive" +REPLY_MESSAGE_TITLE = "%DATETIME%, %EMAIL% wrote" +FORWARD_MESSAGE_TOP_TITLE = "-------- رسالة معاد توجيهها -------" +FORWARD_MESSAGE_TOP_FROM = "من" +FORWARD_MESSAGE_TOP_TO = "الى" +FORWARD_MESSAGE_TOP_CC = "نسخة الى" +FORWARD_MESSAGE_TOP_SENT = "تم الإرسال" +FORWARD_MESSAGE_TOP_SUBJECT = "الموضوع" +EMPTY_TO_ERROR_DESC = "رجاءً حدد مستلم واحد على الأقل." +NO_ATTACHMENTS_HERE_DESC = "لايوجد مرفقات" +ATTACHMENTS_ERROR_DESC = "تحذير! لم يتم إرفاق جميع المرفقات" +ATTACHMENTS_UPLOAD_ERROR_DESC = "لم تنتهي عملية الإرفاق بعد" +BUTTON_REQUEST_READ_RECEIPT = "اطلب اعلاماً بالقراءة" +BUTTON_MARK_AS_IMPORTANT = "تحديده كـ هام" +BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" +BUTTON_REQUEST_DSN = "اطلب اعلاماً بايصال البريد" + +[POPUPS_WELCOME_PAGE] +BUTTON_CLOSE = "إغلاق" + +[POPUPS_ASK] +BUTTON_YES = "نعم" +BUTTON_NO = "لا" +DESC_WANT_CLOSE_THIS_WINDOW = "هل أنت متأكد من رغبتك باغلاق هذه النافذة؟" +DESC_WANT_DELETE_MESSAGES = "هل أنت متأكد من رغبتك بحذف هذه الرسائل؟" + +[POPUPS_LANGUAGES] +TITLE_LANGUAGES = "حدّد لغتك" + +[POPUPS_ADD_ACCOUNT] +TITLE_ADD_ACCOUNT = "قم باضافة حساب؟" +BUTTON_ADD_ACCOUNT = "إضافة" +TITLE_UPDATE_ACCOUNT = "تحديث الحساب؟" +BUTTON_UPDATE_ACCOUNT = "تحديث" + +[POPUPS_IDENTITY] +TITLE_ADD_IDENTITY = "إضافة هوية؟" +TITLE_UPDATE_IDENTITY = "تحديث الهوية؟" +BUTTON_ADD_IDENTITY = "إضافة" +BUTTON_UPDATE_IDENTITY = "تحديث" +LABEL_EMAIL = "البريد الإلكتروني" +LABEL_NAME = "الإسم" +LABEL_REPLY_TO = "الرد-الى" +LABEL_SIGNATURE = "التوقيع" +LABEL_CC = "نسخة الى" +LABEL_BCC = "نسخة مخفية الوجهة" +LABEL_SIGNATURE_INSERT_BEFORE = "قم بوضع التوقيع قبل النص المأخوذ من الرسائل في عملية الرد" + +[POPUPS_CREATE_FOLDER] +TITLE_CREATE_FOLDER = "إنشاء مجلد؟" +SELECT_NO_PARENT = "" +LABEL_NAME = "إسم المجلد" +LABEL_PARENT = "المجلد الأساسي" +BUTTON_CREATE = "إنشاء" +BUTTON_CANCEL = "إلغاء" +BUTTON_CLOSE = "إغلاق" +TITLE_CREATING_PROCESS = "يتم إنشاء المجلد" + +[POPUPS_CLEAR_FOLDER] +TITLE_CLEAR_FOLDER = "دمج جميع الرسائل من المجلد؟" +BUTTON_CLEAR = "Clear" +BUTTON_CANCEL = "إلغاء" +BUTTON_CLOSE = "إغلاق" +DANGER_DESC_WARNING = "تحذير!" +DANGER_DESC_HTML_1 = "هذا الإجراء سينجم عنه إزالة جميع محتويات المجلد %FOLDER% بشكل كامل" +DANGER_DESC_HTML_2 = "في حال بدء العملية , فلا يمكن ايقافها او الغائها" +TITLE_CLEARING_PROCESS = "...يتم دمج المجلد" + +[POPUPS_IMPORT_OPEN_PGP_KEY] +TITLE_IMPORT_OPEN_PGP_KEY = "OpenPGP استيراد مفتاح" +BUTTON_IMPORT_OPEN_PGP_KEY = "استيراد" + +[POPUPS_VIEW_OPEN_PGP_KEY] +TITLE_VIEW_OPEN_PGP_KEY = "عرض OpenPGP key" +BUTTON_SELECT = "تحديد" +BUTTON_CLOSE = "إغلاق" + +[POPUPS_GENERATE_OPEN_PGP_KEYS] +TITLE_GENERATE_OPEN_PGP_KEYS = "OpenPGP توليد مفتاح" +LABEL_EMAIL = "البريد الإلكتروني" +LABEL_NAME = "الإسم" +LABEL_PASSWORD = "كلمة السر" +LABEL_KEY_BIT_LENGTH = "طول المفتاح" +BUTTON_GENERATE_OPEN_PGP_KEYS = "قم بالتوليد" + +[POPUPS_COMPOSE_OPEN_PGP] +TITLE_COMPOSE_OPEN_PGP = "OpenPGP Sign/Encrypt" +LABEL_SIGN = "تسجيل" +LABEL_ENCRYPT = "تشفير" +LABEL_PASSWORD = "كلمة السر" +BUTTON_SIGN = "تسجيل" +BUTTON_ENCRYPT = "تشفير" +BUTTON_SIGN_AND_ENCRYPT = "سجل و قم بالتشفير" + +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP فك تشفير" +LABEL_KEY = "مفتاح خاص" +LABEL_PASSWORD = "كلمة السر" +BUTTON_DECRYPT = "فك تشفير" + +[POPUPS_TWO_FACTOR_TEST] +TITLE_TEST_CODE = "التأكد من الهوية على مرحلتين" +LABEL_CODE = "الكود" +BUTTON_TEST = "تجريب" + +[POPUPS_FILTER] +TITLE_CREATE_FILTER = "إنشاء عامل تصفية؟" +TITLE_EDIT_FILTER = "تحديث عامل التصفية؟" +FILTER_NAME = "الإسم" +LEGEND_CONDITIONS = "الشروط" +LEGEND_ACTIONS = "التطبيقات" +BUTTON_DONE = "إنتهاء" +BUTTON_ADD_CONDITION = "إضافة تطبيق" +SELECT_ACTION_NONE = "None" +SELECT_ACTION_MOVE_TO = "إنقل الى" +SELECT_ACTION_FORWARD_TO = "أعد التوجيه الى" +SELECT_ACTION_REJECT = "الرفض" +SELECT_ACTION_VACATION_MESSAGE = "رسالة العطلة" +SELECT_ACTION_DISCARD = "تجاهل" +SELECT_FIELD_FROM = "من" +SELECT_FIELD_RECIPIENTS = "المستلمين (الى أو نسخة الى)" +SELECT_FIELD_SUBJECT = "الموضوع" +SELECT_FIELD_HEADER = "Header" +SELECT_FIELD_SIZE = "الحجم" +SELECT_TYPE_CONTAINS = "يحتوي" +SELECT_TYPE_NOT_CONTAINS = "لايحتوي" +SELECT_TYPE_MATCHES = "يطابق (* و ? مدعوم)" +SELECT_TYPE_NOT_MATCHES = "لايطابق (* و ? مدعوم)" +SELECT_TYPE_REGEXP = "ممنهج" +SELECT_TYPE_NOT_REGEXP = "غير ممنهج" +SELECT_TYPE_EQUAL_TO = "مساوي الى" +SELECT_TYPE_NOT_EQUAL_TO = "غير مساوي الى" +SELECT_TYPE_OVER = "فوق" +SELECT_TYPE_UNDER = "تحت" +SELECT_MATCH_ANY = "مطابق لإحدى الشروط" +SELECT_MATCH_ALL = "مطابق لجميع الشروط" +MARK_AS_READ_LABEL = "تعليمها بـ مقروءة" +REPLY_INTERVAL_LABEL = "فترة الرد (بلأيام)" +KEEP_LABEL = "الإحتفاظ بها" +STOP_LABEL = "لاتتوقف عن المعالجة بالشروط" +EMAIL_LABEL = "البريد الإلكتروني" +VACATION_SUBJECT_LABEL = "الموضوع (خياري)" +VACATION_MESSAGE_LABEL = "الرسالة" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" +REJECT_MESSAGE_LABEL = "رفض الرسالة" +ALL_INCOMING_MESSAGES_DESC = "جميع الرسائل الواردة" + +[POPUPS_SYSTEM_FOLDERS] +TITLE_SYSTEM_FOLDERS = "حدد مجلدات النظام" +SELECT_CHOOSE_ONE = "إختر واحد" +SELECT_UNUSE_NAME = "لاتستخدم" +LABEL_SENT = "أرسلت" +LABEL_DRAFTS = "المسودات" +LABEL_SPAM = "الرسائل غير المرغوب فيها" +LABEL_TRASH = "المهملات" +LABEL_ARCHIVE = "الأرشيف" +BUTTON_CANCEL = "إلغاء" +BUTTON_CLOSE = "إغلاق" +NOTIFICATION_SENT = "You haven't selected \"Sent\" system folder messages are put to after sending. +If you don't want to save sent message, please select \"Do not use\" option." +NOTIFICATION_DRAFTS = "You haven't selected \"Drafts\" system folder messages are saved to while composing." +NOTIFICATION_SPAM = "You haven't selected \"Spam\" system folder spamed messages are placed to. +If you wish to remove messages permanently, please select \"Do not use\" option." +NOTIFICATION_TRASH = "You haven't selected \"Trash\" system folder deleted messages are placed to. +If you wish to remove messages permanently, please select \"Do not use\" option." +NOTIFICATION_ARCHIVE = "You haven't selected \"Archive\" system folder achived messages are placed to." + +[POPUPS_TWO_FACTOR_CFG] +LEGEND_TWO_FACTOR_AUTH = "التحقق الثنائي (TOTP)" +LABEL_ENABLE_TWO_FACTOR = "تفعيل عملية التحقق الثنائي" +LABEL_TWO_FACTOR_USER = "المستخدم" +LABEL_TWO_FACTOR_STATUS = "الحالة" +LABEL_TWO_FACTOR_SECRET = "السر" +LABEL_TWO_FACTOR_BACKUP_CODES = "كود التحقق الإحتياطي" +BUTTON_CREATE = "قم بإنشاء سر" +BUTTON_ACTIVATE = "فعل" +BUTTON_CLEAR = "Clear" +BUTTON_LOGOUT = "تسجيل خروج" +BUTTON_DONE = "إنتهى" +BUTTON_TEST = "تجريب" +LINK_TEST = "تجريب" +BUTTON_SHOW_SECRET = "إظهار السر" +BUTTON_HIDE_SECRET = "إخفاء السر" +TWO_FACTOR_REQUIRE_DESC = "حسابك بحاجة الى إعداد مراحل التحقق الثنائية" +TWO_FACTOR_SECRET_CONFIGURED_DESC = "تم التكوين" +TWO_FACTOR_SECRET_NOT_CONFIGURED_DESC = "لم يتم التكوين" +TWO_FACTOR_SECRET_DESC = "قم باستيراد هذه المعلومات لمركز توثيق غوغل باستخدام رمز الكيو-اّر او بنسخ الكود يدوياً (or other TOTP client)" +TWO_FACTOR_BACKUP_CODES_DESC = "إذا لم تتمكن من الحصول على الكود من مركز التوثيق في غوغل يمكنك إستخدام الكود الإحتياطي لتسجيل الدخول,ولكن سيصبح كود الإحتياط غير فعال بعد ذلك" +TWO_FACTOR_SECRET_TEST_BEFORE_DESC = "لايمكنك تغيير هذه الإعدادات بدون تجريب." + +[TITLES] +LOADING = "..جاري التحميل" +LOGIN = "تسجيل الدخول" +MAILBOX = "صندوق البريد" +SETTINGS = "الإعدادات" +COMPOSE = "إنشاء" + +[UPLOAD] +ERROR_FILE_IS_TOO_BIG = "حجم الملف كبير جداً" +ERROR_FILE_PARTIALLY_UPLOADED = "لقد تم إضافة الملف بشكل جزئي ..بسبب خطأ غير معروف" +ERROR_NO_FILE_UPLOADED = "لم تتم عملية إضافة الملفات" +ERROR_MISSING_TEMP_FOLDER = "الملف المؤقت مفقود" +ERROR_ON_SAVING_FILE = "حدث خطأ نتيجة إضافة ملف غير معروف النوع" +ERROR_FILE_TYPE = "نوع الملف مرفوض" +ERROR_UNKNOWN = "حدث خطأ نتيجة إضافة ملف غير معروف النوع" + +[EDITOR] +TEXT_SWITCHER_PLAINT_TEXT = "نص عادي" +TEXT_SWITCHER_RICH_FORMATTING = "غني بالتنسيقات" +TEXT_SWITCHER_CONFIRM = "التنسيقات و الصور المضافة ستزال.. هل أنت متأكد من الإستمرار" + +[SETTINGS_LABELS] +LABEL_PERSONAL_NAME = "الشخصي" +LABEL_GENERAL_NAME = "العام" +LABEL_CONTACTS_NAME = "جهات الإتصال" +LABEL_FOLDERS_NAME = "المجلدات" +LABEL_ACCOUNTS_NAME = "الحسابات" +LABEL_IDENTITY_NAME = "الهوية" +LABEL_IDENTITIES_NAME = "الهويات" +LABEL_FILTERS_NAME = "عوامل التصفية" +LABEL_TEMPLATES_NAME = "القوالب" +LABEL_SECURITY_NAME = "الأمان" +LABEL_SOCIAL_NAME = "الشبكات الإجتماعية" +LABEL_THEMES_NAME = "المظاهر العامة" +LABEL_CHANGE_PASSWORD_NAME = "كلمة السر" +LABEL_OPEN_PGP_NAME = "OpenPGP" +BUTTON_BACK = "العودة" + +[SETTINGS_FILTERS] +LEGEND_FILTERS = "عوامل التصفية" +BUTTON_SAVE = "حفظ" +BUTTON_ADD_FILTER = "إضافة عامل تصفية" +BUTTON_DELETE = "حذف" +BUTTON_RAW_SCRIPT = "إستخدام سكربت مخصصة للمستخدم" +SUBNAME_NONE = "None" +SUBNAME_MOVE_TO = "\"%FOLDER%\" نقل الى" +SUBNAME_FORWARD_TO = "\"%EMAIL%\" إعادة توجيه الى" +SUBNAME_REJECT = "رفض" +SUBNAME_VACATION_MESSAGE = "رسالة العطلة" +SUBNAME_DISCARD = "تجاهل" +CAPABILITY_LABEL = "القدرة" +LOADING_PROCESS = "تحديث قائمة عوامل التصفية" +DELETING_ASK = "هل أنت متأكد؟" +CHACHES_NEED_TO_BE_SAVED_DESC = "هذه التغييرات بحاجة الى أن يتم حفظها على المخدم." + +[SETTINGS_IDENTITY] +LEGEND_IDENTITY = "الهوية" +LABEL_DISPLAY_NAME = "الإسم" +LABEL_REPLY_TO = "الرد-الى" +LABEL_SIGNATURE = "التوقيع" +LABEL_ADD_SIGNATURE_TO_ALL = "قم بإضافة توقيعك على جميع الرسائل الصادرة" + +[SETTINGS_SECURITY] +LEGEND_SECURITY = "الأمان" +LABEL_CONFIGURATE_TWO_FACTOR = "تكوين عملية التأكد ثنائية المراحل" +LABEL_AUTOLOGOUT = "تسجيل الخروج التلقائي" +AUTOLOGIN_NEVER_OPTION_NAME = "أبداَ" +AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% دقيقة" + +[SETTINGS_GENERAL] +LEGEND_GENERAL = "عام" +LABEL_LANGUAGE = "اللغة" +LABEL_IDENTITY = "الهوية" +LABEL_LAYOUT = "التصميم" +LABEL_LAYOUT_NO_SPLIT = "بدون إنقسام" +LABEL_LAYOUT_VERTICAL_SPLIT = "إنقسام عمودي" +LABEL_LAYOUT_HORIZONTAL_SPLIT = "إنقسام أفقي" +LABEL_EDITOR = "المحرر النصي الأساسي" +LABEL_EDITOR_HTML = "Html" +LABEL_EDITOR_PLAIN = "عادي" +LABEL_EDITOR_HTML_FORCED = "Html (إجباري)" +LABEL_EDITOR_PLAIN_FORCED = "عادي (إجباري)" +LABEL_ANIMATION = "مؤثرات الواجهة الحية" +LABEL_ANIMATION_FULL = "كامل" +LABEL_ANIMATION_NORMAL = "عادي" +LABEL_ANIMATION_NONE = "بدون" +LABEL_VIEW_OPTIONS = "إظهار الخيارات" +LABEL_USE_PREVIEW_PANE = "استخدام جزئية العرض الجانبي" +LABEL_USE_CHECKBOXES_IN_LIST = "عرض مربعات التحديد في القائمة" +LABEL_USE_THREADS = "إستخدام المواضيع" +LABEL_REPLY_SAME_FOLDER = "ضع الردود في مجلد الرسالة التي يتم الرد عليها" +LABEL_SHOW_IMAGES = "قم دائماَ بعرض الصور القادمة في الرسالة" +LABEL_SHOW_ANIMATION = "أظهر التأثيرات الخاصة" +LABEL_MESSAGE_PER_PAGE = "الرسائل في الصفحة" +LABEL_NOTIFICATIONS = "التنبيهات" +LABEL_SOUND_NOTIFICATION = "صوت التنبيهات" +LABEL_CHROME_NOTIFICATION_DESC = "إظهار نافذة منبثقة في حالة قدوم ايميل جديد" +LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(تم إعتراضها من قبل المتصفح)" + +[SETTINGS_CONTACTS] +LEGEND_CONTACTS = "جهات الإتصال" +LABEL_CONTACTS_AUTOSAVE = "قم باضافة المستلمين تلقائيا الى دفتر العناوين" +LEGEND_CONTACTS_SYNC = "(CardDAV)التزامن عن بعد" +LABEL_CONTACTS_SYNC_ENABLE = "تفعيل التزامن عن بعد" +LABEL_CONTACTS_SYNC_SERVER = "المخدم" +LABEL_CONTACTS_SYNC_AB_URL = "وصلة دفتر العناوين" +LABEL_CONTACTS_SYNC_USER = "المستخدم" +LABEL_CONTACTS_SYNC_PASSWORD = "كلمة السر" + +[SETTINGS_THEMES] +LEGEND_THEMES = "المظاهر العامة" +LEGEND_THEMES_CUSTOM = "تجهيز المظهر المخصص" +LABEL_CUSTOM_TYPE = "النوع" +LABEL_CUSTOM_TYPE_LIGHT = "فاتح" +LABEL_CUSTOM_TYPE_DARK = "غامق" +LABEL_CUSTOM_BACKGROUND_IMAGE = "الخلفية" +BUTTON_UPLOAD_BACKGROUND_IMAGE = "(JPG, PNG)حمل صورة الخلفية" +ERROR_FILE_IS_TOO_BIG = "حجم الملف كبير جداً" +ERROR_FILE_TYPE_ERROR = "مسموحة فقط(JPG,PNG)نوع الملف خطأ" +ERROR_UNKNOWN = "حدث خطأ أثناء رفع الملف" + +[SETTINGS_SOCIAL] +LEGEND_GOOGLE = "غوغل" +BUTTON_GOOGLE_CONNECT = "إتصل بغوغل" +BUTTON_GOOGLE_DISCONNECT = "إفصل الإتصال مع غوغل" +MAIN_GOOGLE_DESC = "بعد تفعيل الإتصال مع غوغل.. يمكنك تسجيل الدخول الى حسابك باستخدام زر غوغل على صفحة تسجيل الدخول" +LEGEND_FACEBOOK = "فيسبوك" +BUTTON_FACEBOOK_CONNECT = "إتصل بفيسبوك" +BUTTON_FACEBOOK_DISCONNECT = "إفصل الإتصال مع فيسبوك" +MAIN_FACEBOOK_DESC = "بعد تفعيل الإتصال مع فيسبوك.. يمكنك تسجيل الدخول الى حسابك باستخدام زر فيسبوك على صفحة تسجيل الدخول" +LEGEND_TWITTER = "تويتر" +BUTTON_TWITTER_CONNECT = "إتصل بتويتر" +BUTTON_TWITTER_DISCONNECT = "إفصل الإتصال بتويتر" +MAIN_TWITTER_DESC = "بعد تفعيل الإتصال مع تويتر.. يمكنك تسجيل الدخول الى حسابك باستخدام زر تويتر على صفحة تسجيل الدخول" + +[SETTINGS_FOLDERS] +LEGEND_FOLDERS = "قائمة المجلدات" +BUTTON_CREATE = "أنشأ مجلد" +BUTTON_SYSTEM = "قم بتحديد مجلدات النظام" +BUTTON_DELETE = "حذف" +BUTTON_SUBSCRIBE = "الإشتراك" +BUTTON_UNSUBSCRIBE = "الغاء الإشتراك" +LOADING_PROCESS = "جاري تحديث قائمة المجلدات" +CREATING_PROCESS = "جاري إنشاء المجلد" +DELETING_PROCESS = "جاري حذف المجلد" +RENAMING_PROCESS = "جاري إعادة تسمية المجلد" +DELETING_ASK = "هل أنت متأكد؟" +TO_MANY_FOLDERS_DESC_1 = "لديك الكثير من المجلدات!" +TO_MANY_FOLDERS_DESC_2 = "لقد قمنا بإظهار جزء منهم تفادياَ لضعف الأداء" +HELP_DELETE_FOLDER = "إحذف المجلد" +HELP_SHOW_HIDE_FOLDER = "إخفاء\\إظهار المجلد" +HELP_CHECK_FOR_NEW_MESSAGES = "تأكد\\لاتتأكد من وصول ايميلات جديدة" + +[SETTINGS_ACCOUNTS] +LEGEND_ACCOUNTS = "الحسابات" +LEGEND_IDENTITIES = "الهويات" +LEGEND_ACCOUNTS_AND_IDENTITIES = "الحسابات و الهويات" +BUTTON_ADD_ACCOUNT = "قم باضافة حساب" +BUTTON_ADD_IDENTITY = "قم باضافة هوية" +BUTTON_DELETE = "إحذف" +LOADING_PROCESS = "..جاري التحميل" +DELETING_ASK = "هل أنت متأكد؟" +DEFAULT_IDENTITY_LABEL = "الافتراضي" + +[SETTINGS_IDENTITIES] +LEGEND_IDENTITY = "الهوية" +LEGEND_IDENTITIES = "الهويات الإضافية" +LABEL_DEFAULT = "الافتراضي" +LABEL_DISPLAY_NAME = "الإسم" +LABEL_REPLY_TO = "الرد-الى" +LABEL_SIGNATURE = "التوفيع" +LABEL_ADD_SIGNATURE_TO_ALL = "قم باضافة التوقيع الى جميع الرسائل الصادرة" +BUTTON_ADD_IDENTITY = "قم بإضافة هوية" +BUTTON_DELETE = "حذف" +LOADING_PROCESS = "جاري تحديث قائمة الهويات" +DELETING_ASK = "هل أنت متأكد؟" + +[SETTINGS_CHANGE_PASSWORD] +LEGEND_CHANGE_PASSWORD = "غيّر كلمة السر" +LABEL_CURRENT_PASSWORD = "كلمة السر الحالية" +LABEL_NEW_PASSWORD = "كلمة السر الجديدة" +LABEL_REPEAT_PASSWORD = "تأكيد كلمة السر الجديدة" +BUTTON_UPDATE_PASSWORD = "تعيين كلمة السر الجديدة" +ERROR_PASSWORD_MISMATCH = "كلمات السر غير متطابقة,لطفاَ أعد كتابتها" + +[SETTINGS_OPEN_PGP] +LEGEND_OPEN_PGP = "OpenPGP" +BUTTON_ADD_OPEN_PGP_KEY = "OpenPGP إستيراد مفتاح" +BUTTON_GENERATE_OPEN_PGP_KEYS = "OpenPGP توليد مفتاح" +TITLE_PRIVATE = "خاص" +TITLE_PUBLIC = "عام" +DELETING_ASK = "هل أنت متأكد؟" +GENERATE_ONLY_HTTPS = "HTTPS فقط" + +[SHORTCUTS_HELP] +LEGEND_SHORTCUTS_HELP = "مساعدة في إختصارات لوحة المفاتيح" +TAB_MAILBOX = "صندوق البريد" +TAB_MESSAGE_LIST = "قائمة الرسائل" +TAB_MESSAGE_VIEW = "عرض الرسائل" +TAB_COMPOSE = "إنشاء" +LABEL_OPEN_USER_DROPDOWN = "فتح نافذة الأعضاء المنبثقة" +LABEL_REPLY = "الرد" +LABEL_REPLY_ALL = "الرد للجميع" +LABEL_FORWARD = "إعادة التوجيه" +LABEL_FORWARD_MULTIPLY = "إعادة التوجيه كملف مرفق" +LABEL_HELP = "المساعدة" +LABEL_CHECK_ALL = "تحديد جميع الرسائل" +LABEL_ARCHIVE = "أرشيف" +LABEL_DELETE = "حذف" +LABEL_OPEN_THREAD = "فتح المواضيع المحددة" +LABEL_MOVE = "نقل" +LABEL_READ = "إقرأ الرسائل المحددة" +LABEL_UNREAD = "لاتقم بقراءة الرسائل المحددة" +LABEL_IMPORTANT = "هام, النجمة/العلم الرسائل المحددة" +LABEL_SEARCH = "بحث" +LABEL_CANCEL_SEARCH = "إلغاء البحث" +LABEL_FULLSCREEN_ENTER = "وضع ملء الشاشة" +LABEL_VIEW_MESSAGE_ENTER = "مشاهدة الرسائل (بدون نافذة المشاهدة)" +LABEL_SWITCH_TO_MESSAGE = "تحويل التركيز الى الرسائل المحددة" +LABEL_SWITCH_TO_FOLDER_LIST = "تحويل التركيز الى قائمة المجلدات" +LABEL_FULLSCREEN_TOGGLE = "تفعيل وضعية ملء الشاشة" +LABEL_BLOCKQUOTES_TOGGLE = "إقتباس الرسائل" +LABEL_THREAD_NEXT = "الرسالة التالية في الموضوع" +LABEL_THREAD_PREV = "الرسالة السابقة من الموضوع" +LABEL_PRINT = "طباعة" +LABEL_EXIT_FULLSCREEN = "الخروج من وضع ملء الشاشة" +LABEL_CLOSE_MESSAGE = "إغلاق الرسالة (بدون نافذة العرض)" +LABEL_SWITCH_TO_LIST = "تحويل التركيز الى قائمة الرسائل" +LABEL_OPEN_COMPOSE_POPUP = "إفتح نافذة خاصة لإنشاء الرسائل" +LABEL_OPEN_IDENTITIES_DROPDOWN = "فتح قائمة الهويات" +LABEL_SAVE_MESSAGE = "حفظ الرسالة" +LABEL_SEND_MESSAGE = "إرسال الرسالة" +LABEL_CLOSE_COMPOSE = "إغلاق الرسالة" + +[PGP_NOTIFICATIONS] +NO_PUBLIC_KEYS_FOUND = "لم يتم إيجاد المفتاح العام" +NO_PUBLIC_KEYS_FOUND_FOR = "لم يتم إيجاد مفتاح عام\"%EMAIL%\" email" +NO_PRIVATE_KEY_FOUND = "لم يتم إيجاد مفتاح خاص" +NO_PRIVATE_KEY_FOUND_FOR = "لم يتم إيجاد المفتاح الخاص لـ \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" +UNVERIFIRED_SIGNATURE = "توقيع غير موثق" +DECRYPTION_ERROR = "OpenPGP خطأ فك تشفير" +GOOD_SIGNATURE = "توقيع جيد من %USER%" +PGP_ERROR = "OpenPGP error: %ERROR%" +SPECIFY_FROM_EMAIL = "يرجى التأكد من الإيميل" +SPECIFY_AT_LEAST_ONE_RECIPIENT = "يرجى تحديد مستلم واحد على الأقل" + +[NOTIFICATIONS] +INVALID_TOKEN = "خاطىء token" +AUTH_ERROR = "خطأ في كلمة السر \\اسم المستخدم" +ACCESS_ERROR = "خطأ في الوصول" +CONNECTION_ERROR = "لايمكن الإتصال بالمخدم" +CAPTCHA_ERROR = "رمز تحقق خاطىء." +SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE = "إن المعرف الإجتماعي غير مرتبط بـ أي حساب حالياَ. سجل الدخول الى مركز التوثيق في بريدك الإلكتروني وفعل هذه الخاصية في إعدادات حسابك" +SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE = "إن المعرف الإجتماعي غير مرتبط بـ أي حساب حالياَ. سجل الدخول الى مركز التوثيق في بريدك الإلكتروني وفعل هذه الخاصية في إعدادات حسابك" +SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE = "إن المعرف الإجتماعي غير مرتبط بـ أي حساب حالياَ. سجل الدخول الى مركز التوثيق في بريدك الإلكتروني وفعل هذه الخاصية في إعدادات حسابك" +DOMAIN_NOT_ALLOWED = "غير مسموح لهذا الموقع" +ACCOUNT_NOT_ALLOWED = "الحساب غير مسموح له" +ACCOUNT_TWO_FACTOR_AUTH_REQUIRED = "عامل التحقق الثنائي من الهوية مطلوب" +ACCOUNT_TWO_FACTOR_AUTH_ERROR = "خطأ في عملية التحقق الثنائية" +COULD_NOT_SAVE_NEW_PASSWORD = "لم نتمكن من حفظ كلمة السر الجديدة" +CURRENT_PASSWORD_INCORRECT = "كلمة السر الحالية خاطئة" +NEW_PASSWORD_SHORT = "كلمة السر قصيرة جداً" +NEW_PASSWORD_WEAK = "كلمة السر سهلة جداً" +NEW_PASSWORD_FORBIDDENT = "كلمة السر تحتوي على محارف غير مسموح بها" +CONTACTS_SYNC_ERROR = "خطأ في مزامنة جهات الإتصال" +CANT_GET_MESSAGE_LIST = "لايمكن الوصول الى قائمة الرسائل" +CANT_GET_MESSAGE = "لايمكن الوصول الى الرسالة" +CANT_DELETE_MESSAGE = "لايمكن حذف الرسالة" +CANT_MOVE_MESSAGE = "لايمكن نقل الرسالة" +CANT_SAVE_MESSAGE = "لايمكن حفظ الرسالة" +CANT_SEND_MESSAGE = "لايمكن إرسال الرسالة" +INVALID_RECIPIENTS = "يرجى التأكد من عناوين المرسل اليهم" +CANT_SAVE_FILTERS = "لايمكن حفظ عامل التصفية" +CANT_GET_FILTERS = "لايمكن الوصول الى عوامل التصفية" +FILTERS_ARE_NOT_CORRECT = "عوامل التصفية خطأ" +CANT_CREATE_FOLDER = "لايمكن إنشاء مجلد" +CANT_RENAME_FOLDER = "لايمكن إعادة تسمية المجلد" +CANT_DELETE_FOLDER = "لايمكن حذف المجلد" +CANT_DELETE_NON_EMPTY_FOLDER = "لايمكن حذف مجلد ممتلأ" +CANT_SUBSCRIBE_FOLDER = "لايمكن الإشتراك بالمجلد" +CANT_UNSUBSCRIBE_FOLDER = "لايمكن حذف الإشتراك من المجلد" +CANT_SAVE_SETTINGS = "لايمكن حفظ الإعدادات" +CANT_SAVE_PLUGIN_SETTINGS = "لايمكن حفظ الإعدادات" +DOMAIN_ALREADY_EXISTS = "الموقع موجود مسبقاَ" +CANT_INSTALL_PACKAGE = "فشل في تنزيل الحزمة" +CANT_DELETE_PACKAGE = "فشل في إزالة الحزمة" +INVALID_PLUGIN_PACKAGE = "خطأ في الحزمة المراد تنزيلها" +UNSUPPORTED_PLUGIN_PACKAGE = "حزمة غير مدعومة" +LICENSING_SERVER_IS_UNAVAILABLE = "مخدم الإشتراكات غير متوفر" +LICENSING_DOMAIN_EXPIRED = "الإشتراك لهذا الموقع قد انتهى" +LICENSING_DOMAIN_BANNED = "الإشتراك لهذا الموقع قد تم حجبه" +DEMO_SEND_MESSAGE_ERROR = "لأسباب أمنية, هذا الحساب غير مسموح له إرسال رسائل" +DEMO_ACCOUNT_ERROR = "لأسباب أمنية , هذا الحساب قد منع من هذا الإجراء" +ACCOUNT_ALREADY_EXISTS = "الحساب موجود مسبقاَ" +MAIL_SERVER_ERROR = "حدث خطأ أثناء محاولة الوصول الى المخدم البريدي" +INVALID_INPUT_ARGUMENT = "Invalid input argument" +UNKNOWN_ERROR = "خطأ غير معروف" + +[STATIC] +BACK_LINK = "إعادة التحميل" +DOMAIN_LIST_DESC = "قائمة المواقع البريدية المسموح فيها لهذا البريد بالوصول" +PHP_EXSTENSIONS_ERROR_DESC = "!إضافات الـ بي إتش بي المطلوبة,غير متوافرة في إعدادات الـ بي إتش بي لديك" +PHP_VERSION_ERROR_DESC = "أقل من الإصدار المطلوب 5.3.0!(%VERSION%) PHP إصدار" +NO_SCRIPT_TITLE = "الجافا سكريبت مطلوبة لهذا البرنامج" +NO_SCRIPT_DESC = "إن متصفحك لايدعم الجافا سكريبت . يرجى تفعيل الدعم أو تجريب متصفح أخر" +NO_COOKIE_TITLE = "Cookies support is required for this application." +NO_COOKIE_DESC = "Cookies support is not available in your browser. +Please enable Cookie support in your browser settings and retry." +BAD_BROWSER_TITLE = "متصفحك بحاجة الى تحديث" +BAD_BROWSER_DESC = "لإصتخدام جميع ميزات هذا البرنامج يرجى تنزيل أحد المتصفحات التالية الداعمة:" diff --git a/rainloop/v/0.0.0/langs/bg.ini b/rainloop/v/0.0.0/langs/bg.ini index c959c0e0a..dea61f5e9 100644 --- a/rainloop/v/0.0.0/langs/bg.ini +++ b/rainloop/v/0.0.0/langs/bg.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "С премахнат флаг" EMPTY_LIST = "Празен списък." EMPTY_SEARCH_LIST = "Няма съобщения, които да отговарят на търсенето." SEARCH_RESULT_FOR = "Резултати от търсенето за \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Зареждане" EMPTY_SUBJECT_TEXT = "(Няма заглавие)" PUT_MESSAGE_HERE = "Пуснете съобщението тук, за да го видите в списъка" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Изберете съобщение, за да го вид PGP_PASSWORD_INPUT_PLACEHOLDER = "Парола" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Обратна разписка (displayed) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Sign" BUTTON_ENCRYPT = "Encrypt" BUTTON_SIGN_AND_ENCRYPT = "Sign and encrypt" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "Двустъпков тест за удостоверяване" LABEL_CODE = "Код" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Общи" LABEL_LANGUAGE = "Език" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Renaming a folder" DELETING_ASK = "Are you sure?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Списък с акаунти" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generate OpenPGP Keys" TITLE_PRIVATE = "Private" TITLE_PUBLIC = "Public" DELETING_ASK = "Are you sure?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Keyboard shortcuts help" @@ -607,6 +625,7 @@ LABEL_HELP = "Помощ" LABEL_CHECK_ALL = "Провери всички съобщения" LABEL_ARCHIVE = "Архивирай" LABEL_DELETE = "Изтрий" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Премести" LABEL_READ = "Прочети избраните съобщения" LABEL_UNREAD = "Маркирай като непрочетени избраните съобщения" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Поддръжката на Бисквитки не е нал Моля, разрешете поддръжката на Бисквитки в настройките на вашия браузър и опитайте отново." BAD_BROWSER_TITLE = "Вашият браузър е остарял." BAD_BROWSER_DESC = "За да използвате всички функции на приложението, -изтеглете и инсталирайте един от тези браузъри:" \ No newline at end of file +изтеглете и инсталирайте един от тези браузъри:" diff --git a/rainloop/v/0.0.0/langs/cs.ini b/rainloop/v/0.0.0/langs/cs.ini index 9b722039c..2505d5170 100644 --- a/rainloop/v/0.0.0/langs/cs.ini +++ b/rainloop/v/0.0.0/langs/cs.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Neoznačené" EMPTY_LIST = "Seznam je prázdny." EMPTY_SEARCH_LIST = "Vašemu vyhledávání neodpovídají žádné zprávy." SEARCH_RESULT_FOR = "Výsledky vyhledávání pro \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Načítám" EMPTY_SUBJECT_TEXT = "(Bez předmětu)" PUT_MESSAGE_HERE = "Přesuňte zprávu sem pro její zobrazení v seznamu" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Vyberte zprávu ze seznamu pro její zobrazení zde." PGP_PASSWORD_INPUT_PLACEHOLDER = "Heslo" PGP_SIGNED_MESSAGE_DESC = "Zpráva podepsaná OpenPGP (klikněte pro ověření)" PGP_ENCRYPTED_MESSAGE_DESC = "Zpráva šifrovaná OpenPGP (klikněte pro dešifraci)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Potvrzení o zobrazení zprávy - %SUBJECT%" @@ -315,6 +319,12 @@ BUTTON_SIGN = "Podepsat" BUTTON_ENCRYPT = "Šifrovat" BUTTON_SIGN_AND_ENCRYPT = "Podepsat a šifrovat" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "Dvoufázové ověření" LABEL_CODE = "Kód" @@ -347,6 +357,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Rovná se" SELECT_TYPE_NOT_EQUAL_TO = "Nerovná se" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Vyhovuje alespoň jednomu pravidlu" SELECT_MATCH_ALL = "Vyhovuje všem pravidlům" MARK_AS_READ_LABEL = "Odznačit jako přečtené" @@ -356,6 +368,7 @@ STOP_LABEL = "Neukončovat zpracování pravidel" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Předmět (volitelný)" VACATION_MESSAGE_LABEL = "Zpráva" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Odmítnout zprávu" ALL_INCOMING_MESSAGES_DESC = "Všechny příchozí zprávy" @@ -474,6 +487,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Všeobecné" LABEL_LANGUAGE = "Jazyk" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertikální rozdělení" @@ -550,6 +564,9 @@ RENAMING_PROCESS = "Přejmenovávam složku" DELETING_ASK = "Opravdu to chcete?" TO_MANY_FOLDERS_DESC_1 = "Máte moc složek!" TO_MANY_FOLDERS_DESC_2 = "Můžeme zobrazit jen část z nich, abychom zabránili problémům s výkonem." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Seznam účtů" @@ -590,6 +607,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generovat OpenPGP Klíče" TITLE_PRIVATE = "Soukromý" TITLE_PUBLIC = "Veřejný" DELETING_ASK = "Opravdu to chcete?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Klávesové zkratky" @@ -606,6 +624,7 @@ LABEL_HELP = "Nápověda" LABEL_CHECK_ALL = "Zjistit nové zprávy" LABEL_ARCHIVE = "Archivovat" LABEL_DELETE = "Smazat" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Přesunout" LABEL_READ = "Read selected messages" LABEL_UNREAD = "Unread selected messages" @@ -635,6 +654,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -707,4 +727,4 @@ NO_COOKIE_DESC = "Váš internetový prohlížeč nepodporuje Cookies. Prosím povolte podporu Cookies v nastavení vašeho internetového prohlížeče a zkuste to znovu." BAD_BROWSER_TITLE = "Používáte zastaralý internetový prohlížeč." BAD_BROWSER_DESC = "Abyste mohli využívat všchny funkcie této aplikace, -použijte některý z následujících internetových prohlížečů:" \ No newline at end of file +použijte některý z následujících internetových prohlížečů:" diff --git a/rainloop/v/0.0.0/langs/de.ini b/rainloop/v/0.0.0/langs/de.ini index 401d239ab..a9a48698e 100644 --- a/rainloop/v/0.0.0/langs/de.ini +++ b/rainloop/v/0.0.0/langs/de.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Nicht markiert" EMPTY_LIST = "Liste ist leer." EMPTY_SEARCH_LIST = "Keine Treffer für Ihre Suche." SEARCH_RESULT_FOR = "Suchergebnisse für \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "Zurück zur Nachrichtenliste" LIST_LOADING = "Die Liste wird geladen" EMPTY_SUBJECT_TEXT = "(Kein Betreff)" PUT_MESSAGE_HERE = "Ziehen Sie die Nachricht hierhin, um sie in der Liste anzuzeigen" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Wählen Sie eine Nachricht aus der Liste aus, um sie anzuze PGP_PASSWORD_INPUT_PLACEHOLDER = "Passwort" PGP_SIGNED_MESSAGE_DESC = "OpenPGP-signierte Nachricht (klicken, um zu überprüfen)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP-verschlüsselte Nachricht (klicken, um zu entschlüsseln)" +LINK_DOWNLOAD_AS_ZIP = "Als ZIP-Datei herunterladen" +LINK_SAVE_TO_OWNCLOUD = "In ownCloud speichern" +LINK_SAVE_TO_DROPBOX = "In Dropbox speichern" [READ_RECEIPT] SUBJECT = "Empfangsbestätigung (angezeigt) - %SUBJECT%" @@ -240,7 +244,7 @@ BUTTON_OPEN_PGP = "OpenPGP (nur bei unformatiertem Text)" BUTTON_REQUEST_DSN = "Übermittlungsstatus anfordern" [POPUPS_WELCOME_PAGE] -BUTTON_CLOSE = "Close" +BUTTON_CLOSE = "Schließen" [POPUPS_ASK] BUTTON_YES = "Ja" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Unterschreiben" BUTTON_ENCRYPT = "Verschlüsseln" BUTTON_SIGN_AND_ENCRYPT = "Unterschreiben und verschlüsseln" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "Zwei-Faktor-Authentifizierung" LABEL_CODE = "Code" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regulärer Ausdruck" SELECT_TYPE_NOT_REGEXP = "Regulärer Ausdruck (negiert)" SELECT_TYPE_EQUAL_TO = "Gleich" SELECT_TYPE_NOT_EQUAL_TO = "Ungleich" +SELECT_TYPE_OVER = "Über" +SELECT_TYPE_UNDER = "Unter" SELECT_MATCH_ANY = "Eine der folgenden Regeln trifft zu" SELECT_MATCH_ALL = "Alle folgenden Regeln treffen zu" MARK_AS_READ_LABEL = "Als Gelesen markieren" @@ -357,6 +369,7 @@ STOP_LABEL = "Weiterverarbeitung der Regeln nicht verhindern" EMAIL_LABEL = "E-Mail" VACATION_SUBJECT_LABEL = "Betreff (optional)" VACATION_MESSAGE_LABEL = "Nachricht" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Ablehnnachricht" ALL_INCOMING_MESSAGES_DESC = "Alle eingehenden Nachrichten" @@ -381,27 +394,27 @@ Falls Sie gelöschte Nachrichten endgültig löschen möchten, wählen Sie die O NOTIFICATION_ARCHIVE = "Sie haben keinen \"Archiv\"-Systemordner gewählt, in dem die archivierten Nachrichten abgelegt werden." [POPUPS_TWO_FACTOR_CFG] -LEGEND_TWO_FACTOR_AUTH = "2-Step Verification" -LABEL_ENABLE_TWO_FACTOR = "Enable 2-Step verification" -LABEL_TWO_FACTOR_USER = "User" +LEGEND_TWO_FACTOR_AUTH = "Zwei-Faktor-Authentifizierung" +LABEL_ENABLE_TWO_FACTOR = "Zwei-Faktor-Authentifizierung aktivieren" +LABEL_TWO_FACTOR_USER = "Benutzer" LABEL_TWO_FACTOR_STATUS = "Status" -LABEL_TWO_FACTOR_SECRET = "Secret" -LABEL_TWO_FACTOR_BACKUP_CODES = "Backup codes" -BUTTON_CREATE = "Create New Secret" -BUTTON_ACTIVATE = "Activate" -BUTTON_CLEAR = "Clear" -BUTTON_LOGOUT = "Logout" -BUTTON_DONE = "Done" +LABEL_TWO_FACTOR_SECRET = "Geheimnis" +LABEL_TWO_FACTOR_BACKUP_CODES = "Sicherungscodes" +BUTTON_CREATE = "Neues Geheimnis erstellen" +BUTTON_ACTIVATE = "Aktivieren" +BUTTON_CLEAR = "Löschen" +BUTTON_LOGOUT = "Abmelden" +BUTTON_DONE = "Erledigt" BUTTON_TEST = "Test" LINK_TEST = "test" -BUTTON_SHOW_SECRET = "Show Secret" -BUTTON_HIDE_SECRET = "Hide Secret" -TWO_FACTOR_REQUIRE_DESC = "Your account requires 2-Step verification configuration." -TWO_FACTOR_SECRET_CONFIGURED_DESC = "Configured" -TWO_FACTOR_SECRET_NOT_CONFIGURED_DESC = "Not configured" -TWO_FACTOR_SECRET_DESC = "Import this info into your Google Authenticator client (or other TOTP client) using the provided QR code below or by entering the code manually." -TWO_FACTOR_BACKUP_CODES_DESC = "If you can't receive codes via Google Authenticator, you can use backup codes to sign in. After you’ve used a backup code to sign in, it will become inactive." -TWO_FACTOR_SECRET_TEST_BEFORE_DESC = "You can't change this setting before test." +BUTTON_SHOW_SECRET = "Geheimnis einblenden" +BUTTON_HIDE_SECRET = "Geheminis ausblenden" +TWO_FACTOR_REQUIRE_DESC = "Ihr Benutzerkonto erfordert die Einrichtung der Zwei-Faktor-Authentifizierung." +TWO_FACTOR_SECRET_CONFIGURED_DESC = "Konfiguriert" +TWO_FACTOR_SECRET_NOT_CONFIGURED_DESC = "Nicht konfiguriert" +TWO_FACTOR_SECRET_DESC = "Importieren Sie diese Information in Ihre Google-Authenticator-Anwendung (oder andere TOTP-Anwendung), indem Sie den unten bereitgestellten QR-Code verwenden oder den Code manuell eingeben." +TWO_FACTOR_BACKUP_CODES_DESC = "Sollten Sie keine Codes über den Google Authenticator erhalten, können Sie einen Sicherungscode zur Anmeldung verwenden. Der Sicherungscode wird inaktiv, sobald Sie ihn zur Anmeldung verwendet haben." +TWO_FACTOR_SECRET_TEST_BEFORE_DESC = "Sie können diese Einstellung nicht ohne vorherigen Test verändern." [TITLES] LOADING = "Wird geladen" @@ -467,7 +480,7 @@ LABEL_ADD_SIGNATURE_TO_ALL = "Signatur zu allen ausgehenden Nachrichten hinzufü [SETTINGS_SECURITY] LEGEND_SECURITY = "Sicherheit" -LABEL_CONFIGURATE_TWO_FACTOR = "Configurate 2-Step verification" +LABEL_CONFIGURATE_TWO_FACTOR = "Zwei-Faktor-Authentifizierung konfigurieren" LABEL_AUTOLOGOUT = "Automatische Abmeldung" AUTOLOGIN_NEVER_OPTION_NAME = "Nie" AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% Minute(n)" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% Minute(n)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Allgemein" LABEL_LANGUAGE = "Sprache" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "Keine Aufteilung" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertikale Aufteilung" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Ordner wird umbenannt" DELETING_ASK = "Sind Sie sicher?" TO_MANY_FOLDERS_DESC_1 = "Sie haben zu viele Ordner!" TO_MANY_FOLDERS_DESC_2 = "Aus Leistungsgründen zeigen wir nur einen Teil davon an." +HELP_DELETE_FOLDER = "Ordner löschen" +HELP_SHOW_HIDE_FOLDER = "Ordner ein-/ausblenden" +HELP_CHECK_FOR_NEW_MESSAGES = "Auf neue Nachrichten prüfen/nicht prüfen" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Konten" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "OpenPGP-Schlüssel generieren" TITLE_PRIVATE = "Privat" TITLE_PUBLIC = "Öffentlich" DELETING_ASK = "Sind Sie sicher?" +GENERATE_ONLY_HTTPS = "Nur HTTPS" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Tastaturkürzel-Hilfe" @@ -607,6 +625,7 @@ LABEL_HELP = "Hilfe" LABEL_CHECK_ALL = "Alle Nachrichten auswählen" LABEL_ARCHIVE = "Archivieren" LABEL_DELETE = "Löschen" +LABEL_OPEN_THREAD = "Ausgewählte Unterhaltung öffnen" LABEL_MOVE = "Verschieben" LABEL_READ = "Ausgewählte Nachrichten als gelesen markieren" LABEL_UNREAD = "Ausgewählte Nachrichten als ungelesen markieren" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "Keine öffentlichen Schlüssel gefunden" NO_PUBLIC_KEYS_FOUND_FOR = "Keine öffentlichen Schlüssel für die E-Mail \"%EMAIL%\" gefunden" NO_PRIVATE_KEY_FOUND = "Keine privaten Schlüssel gefunden" NO_PRIVATE_KEY_FOUND_FOR = "Keine privaten Schlüssel für die E-Mail \"%EMAIL%\" gefunden" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Nich verifizierte Unterschrift" DECRYPTION_ERROR = "OpenPGP-Entschlüsselungsfehler" GOOD_SIGNATURE = "Gültige Unterschrift von %USER%" @@ -647,7 +667,7 @@ SPECIFY_AT_LEAST_ONE_RECIPIENT = "Bitte geben Sie mindestens einen Empfänger an INVALID_TOKEN = "Ungültiger Token" AUTH_ERROR = "Authentifizierung fehlgeschlagen" ACCESS_ERROR = "Zugriffsfehler" -CONNECTION_ERROR = "Kann nicht mit dem Server verbinden" +CONNECTION_ERROR = "Serververbindung kann nicht hergestellt werden" CAPTCHA_ERROR = "Falsche CAPTCHA-Eingabe." SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE = "Diese Social-ID ist bisher mit keinem E-Mail-Konto verbunden. Melden Sie sich mit Ihren E-Mail-Anmeldedaten an und aktivieren Sie diese Funktion in Ihren Konteneinstellungen." SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE = "Diese Social-ID ist bisher mit keinem E-Mail-Konto verbunden. Melden Sie sich mit Ihren E-Mail-Anmeldedaten an und aktivieren Sie diese Funktion in Ihren Konteneinstellungen." @@ -685,8 +705,8 @@ CANT_INSTALL_PACKAGE = "Paket konnte nicht installiert werden" CANT_DELETE_PACKAGE = "Paket konnte nicht entfernt werden" INVALID_PLUGIN_PACKAGE = "Plugin-Paket ist ungültig" UNSUPPORTED_PLUGIN_PACKAGE = "Plugin-Paket wird nicht unterstützt" -LICENSING_SERVER_IS_UNAVAILABLE = "Subscription-Server kann nicht erreicht werden" -LICENSING_DOMAIN_EXPIRED = "Die Subscription dieser Domain ist ausgelaufen." +LICENSING_SERVER_IS_UNAVAILABLE = "Der Subscription-Server kann nicht erreicht werden" +LICENSING_DOMAIN_EXPIRED = "Die Subscription dieser Domain ist abgelaufen." LICENSING_DOMAIN_BANNED = "Die Subscription dieser Domain ist gesperrt." DEMO_SEND_MESSAGE_ERROR = "Dieses Demokonto darf aus Sicherheitsgründen keine Nachrichten an externe E-Mail-Adressen versenden!" DEMO_ACCOUNT_ERROR = "Aus Sicherheitsgründen ist dieses Konto nicht zu dieser Aktion berechtigt!" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Ihr Browser unterstützt Cookies nicht. Aktivieren Sie bitte die Cookie-Unterstützung in Ihrem Browser und versuchen Sie es erneut." BAD_BROWSER_TITLE = "Ihr Browser ist veraltet." BAD_BROWSER_DESC = "Um alle Funktionen dieser Anwendung nutzen zu können, -sollten Sie einen der folgenden Browser herunterladen und installieren:" \ No newline at end of file +sollten Sie einen der folgenden Browser herunterladen und installieren:" diff --git a/rainloop/v/0.0.0/langs/en-gb.ini b/rainloop/v/0.0.0/langs/en-gb.ini index b701e6963..53fcf762c 100644 --- a/rainloop/v/0.0.0/langs/en-gb.ini +++ b/rainloop/v/0.0.0/langs/en-gb.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Unflagged" EMPTY_LIST = "Empty list." EMPTY_SEARCH_LIST = "No messages matched your search." SEARCH_RESULT_FOR = "Search results for \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Loading" EMPTY_SUBJECT_TEXT = "(No subject)" PUT_MESSAGE_HERE = "Drop message here to view it in the list" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Select message in list to view it here." PGP_PASSWORD_INPUT_PLACEHOLDER = "Password" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Return Receipt (displayed) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Sign" BUTTON_ENCRYPT = "Encrypt" BUTTON_SIGN_AND_ENCRYPT = "Sign and encrypt" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-Step verification test" LABEL_CODE = "Code" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "General" LABEL_LANGUAGE = "Language" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Renaming a folder" DELETING_ASK = "Are you sure?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Accounts" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generate OpenPGP Keys" TITLE_PRIVATE = "Private" TITLE_PUBLIC = "Public" DELETING_ASK = "Are you sure?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Keyboard shortcuts help" @@ -607,6 +625,7 @@ LABEL_HELP = "Help" LABEL_CHECK_ALL = "Select all messages" LABEL_ARCHIVE = "Archive" LABEL_DELETE = "Delete" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Move" LABEL_READ = "Read selected messages" LABEL_UNREAD = "Unread selected messages" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Cookies support is not available in your browser. Please enable Cookie support in your browser settings and retry." BAD_BROWSER_TITLE = "Your browser is outdated." BAD_BROWSER_DESC = "To use all the features of the application, -download and install one of these browsers:" \ No newline at end of file +download and install one of these browsers:" diff --git a/rainloop/v/0.0.0/langs/en.ini b/rainloop/v/0.0.0/langs/en.ini index b701e6963..53fcf762c 100644 --- a/rainloop/v/0.0.0/langs/en.ini +++ b/rainloop/v/0.0.0/langs/en.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Unflagged" EMPTY_LIST = "Empty list." EMPTY_SEARCH_LIST = "No messages matched your search." SEARCH_RESULT_FOR = "Search results for \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Loading" EMPTY_SUBJECT_TEXT = "(No subject)" PUT_MESSAGE_HERE = "Drop message here to view it in the list" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Select message in list to view it here." PGP_PASSWORD_INPUT_PLACEHOLDER = "Password" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Return Receipt (displayed) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Sign" BUTTON_ENCRYPT = "Encrypt" BUTTON_SIGN_AND_ENCRYPT = "Sign and encrypt" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-Step verification test" LABEL_CODE = "Code" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "General" LABEL_LANGUAGE = "Language" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Renaming a folder" DELETING_ASK = "Are you sure?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Accounts" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generate OpenPGP Keys" TITLE_PRIVATE = "Private" TITLE_PUBLIC = "Public" DELETING_ASK = "Are you sure?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Keyboard shortcuts help" @@ -607,6 +625,7 @@ LABEL_HELP = "Help" LABEL_CHECK_ALL = "Select all messages" LABEL_ARCHIVE = "Archive" LABEL_DELETE = "Delete" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Move" LABEL_READ = "Read selected messages" LABEL_UNREAD = "Unread selected messages" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Cookies support is not available in your browser. Please enable Cookie support in your browser settings and retry." BAD_BROWSER_TITLE = "Your browser is outdated." BAD_BROWSER_DESC = "To use all the features of the application, -download and install one of these browsers:" \ No newline at end of file +download and install one of these browsers:" diff --git a/rainloop/v/0.0.0/langs/es.ini b/rainloop/v/0.0.0/langs/es.ini index 76db7ee5c..2b8461b1a 100644 --- a/rainloop/v/0.0.0/langs/es.ini +++ b/rainloop/v/0.0.0/langs/es.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "No Destacado" EMPTY_LIST = "No hay mensajes." EMPTY_SEARCH_LIST = "La búsqueda no ha producido resultados." SEARCH_RESULT_FOR = "Resultados de búsqueda para \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Cargando" EMPTY_SUBJECT_TEXT = "(Sin asunto)" PUT_MESSAGE_HERE = "Arrastre su mensaje aquí para verlo en la lista" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Seleccione un mensaje en la lista para verlo aquí." PGP_PASSWORD_INPUT_PLACEHOLDER = "Contraseña" PGP_SIGNED_MESSAGE_DESC = "Mensaje firmado mediante OpenPGP (click para verificar)" PGP_ENCRYPTED_MESSAGE_DESC = "Mensaje cifrado mediante OpenPGP (click para desencriptar)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Acuse de recibo (se visualiza) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Firmar" BUTTON_ENCRYPT = "Encriptar" BUTTON_SIGN_AND_ENCRYPT = "Firmar and encriptar" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "Prueba de verificación de 2 pasos" LABEL_CODE = "Código" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "General" LABEL_LANGUAGE = "Idioma" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Renombrando carpeta" DELETING_ASK = "¿Está usted seguro?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Lista de cuentas" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generar llaves OpenPGP" TITLE_PRIVATE = "Privado" TITLE_PUBLIC = "Público" DELETING_ASK = "¿Está usted seguro?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Ayuda de atajos de teclado" @@ -607,6 +625,7 @@ LABEL_HELP = "Ayuda" LABEL_CHECK_ALL = "Comprobar todos los mensajes" LABEL_ARCHIVE = "Archivo" LABEL_DELETE = "Eliminar" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Mover" LABEL_READ = "Marcar los mensajes seleccionados como leídos" LABEL_UNREAD = "Marcar los mensajes seleccionados como no leídos" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "No se encontraron claves públicas" NO_PUBLIC_KEYS_FOUND_FOR = "No hay claves públicas encontrados para el email %MAIL%" NO_PRIVATE_KEY_FOUND = "No se encontró la clave privada" NO_PRIVATE_KEY_FOUND_FOR = "No hay una clave privada para el email %EMAIL%" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Firma no verificada" DECRYPTION_ERROR = "Error de descifrado OpenPGP" GOOD_SIGNATURE = "Buena firma de %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "El soporte de Cookies no esta disponible en su navegador. Por favor habilite los Cookie en la configuración de su navegador e inténtelo de nuevo." BAD_BROWSER_TITLE = "Su navegador no está actualizado." BAD_BROWSER_DESC = "Para usar todas las características de esta aplicación, -descargue e instale uno de estos navegadores:" \ No newline at end of file +descargue e instale uno de estos navegadores:" diff --git a/rainloop/v/0.0.0/langs/fr.ini b/rainloop/v/0.0.0/langs/fr.ini index dc990eb9a..bbbc30d75 100644 --- a/rainloop/v/0.0.0/langs/fr.ini +++ b/rainloop/v/0.0.0/langs/fr.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Non marqué" EMPTY_LIST = "Liste vide." EMPTY_SEARCH_LIST = "Aucun message ne correspond à votre recherche." SEARCH_RESULT_FOR = "Résultats de recherche pour \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Chargement" EMPTY_SUBJECT_TEXT = "(Pas de sujet)" PUT_MESSAGE_HERE = "Glisser un message ici pour l'afficher dans la liste" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Sélectionner un message dans la liste pour l'afficher ici. PGP_PASSWORD_INPUT_PLACEHOLDER = "Mot de passe" PGP_SIGNED_MESSAGE_DESC = "Message signé par OpenPGP (cliquer pour vérifier)" PGP_ENCRYPTED_MESSAGE_DESC = "Message chiffré par OpenPGP (cliquer pour déchiffrer)" +LINK_DOWNLOAD_AS_ZIP = "Télécharger le zip" +LINK_SAVE_TO_OWNCLOUD = "Enregistrer sur ownCloud" +LINK_SAVE_TO_DROPBOX = "Enregistrer sur Dropbox" [READ_RECEIPT] SUBJECT = "Accusé de réception (affiché) - %SUBJECT%" @@ -240,7 +244,7 @@ BUTTON_OPEN_PGP = "OpenPGP (Texte non-formatté uniquement)" BUTTON_REQUEST_DSN = "Demander un accusé de réception" [POPUPS_WELCOME_PAGE] -BUTTON_CLOSE = "Close" +BUTTON_CLOSE = "Fermer" [POPUPS_ASK] BUTTON_YES = "Oui" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Signer" BUTTON_ENCRYPT = "Chiffrer" BUTTON_SIGN_AND_ENCRYPT = "Signer et chiffrer" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Clé Privée" +LABEL_PASSWORD = "Mot de passe" +BUTTON_DECRYPT = "Déchiffrer" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "Test d'authentification en deux étapes" LABEL_CODE = "Code" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Expression régulière" SELECT_TYPE_NOT_REGEXP = "Pas d'expression régulière" SELECT_TYPE_EQUAL_TO = "Egal à" SELECT_TYPE_NOT_EQUAL_TO = "Différent de" +SELECT_TYPE_OVER = "Au dessus de" +SELECT_TYPE_UNDER = "Au dessous de" SELECT_MATCH_ANY = "Correspondant à l'une des règles suivantes" SELECT_MATCH_ALL = "Correspondant à toutes les règles suivantes" MARK_AS_READ_LABEL = "Marquer comme lu" @@ -357,6 +369,7 @@ STOP_LABEL = "Ne pas arrêter le traîtement des règles" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Sujet (optionnel)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Message rejeté" ALL_INCOMING_MESSAGES_DESC = "Tous les messages entrants" @@ -390,13 +403,13 @@ LABEL_TWO_FACTOR_BACKUP_CODES = "Code de sauvegarde" BUTTON_CREATE = "Créer une nouvelle clef secrète" BUTTON_ACTIVATE = "Activate" BUTTON_CLEAR = "Effacer" -BUTTON_LOGOUT = "Logout" +BUTTON_LOGOUT = "Déconnexion" BUTTON_DONE = "Done" BUTTON_TEST = "Tester" LINK_TEST = "test" BUTTON_SHOW_SECRET = "Montrer la clef secrète" BUTTON_HIDE_SECRET = "Masquer la clef secrète" -TWO_FACTOR_REQUIRE_DESC = "Your account requires 2-Step verification configuration." +TWO_FACTOR_REQUIRE_DESC = "Votre compte requiert une configuration d'une vérification à deux étapes." TWO_FACTOR_SECRET_CONFIGURED_DESC = "Configurer" TWO_FACTOR_SECRET_NOT_CONFIGURED_DESC = "Non configuré" TWO_FACTOR_SECRET_DESC = "Importez ces informations dans votre client Google Authenticator (ou un autre client TOTP) en utilisant le code QR fourni ci-dessous ou en entrant les valeurs manuellement." @@ -433,7 +446,7 @@ LABEL_ACCOUNTS_NAME = "Comptes" LABEL_IDENTITY_NAME = "Identité" LABEL_IDENTITIES_NAME = "Identities" LABEL_FILTERS_NAME = "Filters" -LABEL_TEMPLATES_NAME = "Templates" +LABEL_TEMPLATES_NAME = "Modèles" LABEL_SECURITY_NAME = "Securité" LABEL_SOCIAL_NAME = "Social" LABEL_THEMES_NAME = "Thèmes" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Général" LABEL_LANGUAGE = "Langue" +LABEL_IDENTITY = "Identité" LABEL_LAYOUT = "Disposition" LABEL_LAYOUT_NO_SPLIT = "Pas de séparation" LABEL_LAYOUT_VERTICAL_SPLIT = "Partage vertical" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Renommer un dossier" DELETING_ASK = "Êtes-vous sûr ?" TO_MANY_FOLDERS_DESC_1 = "Vous avez trop de dossiers !" TO_MANY_FOLDERS_DESC_2 = "Seulement une partie d'entre eux ont été affichés afin de limiter les problèmes de performance." +HELP_DELETE_FOLDER = "Supprimer le dossier" +HELP_SHOW_HIDE_FOLDER = "Afficher/masquer le dossier" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Liste des comptes" @@ -560,7 +577,7 @@ BUTTON_ADD_ACCOUNT = "Ajouter un compte" BUTTON_ADD_IDENTITY = "Ajouter une identité" BUTTON_DELETE = "Supprimer" LOADING_PROCESS = "Mise à jour de la liste des comptes" -DELETING_ASK = "Êtes-vous sûr ?" +DELETING_ASK = "Êtes-vous sûr-e ?" DEFAULT_IDENTITY_LABEL = "défaut" [SETTINGS_IDENTITIES] @@ -574,7 +591,7 @@ LABEL_ADD_SIGNATURE_TO_ALL = "Ajouter votre signature à tous les messages sorta BUTTON_ADD_IDENTITY = "Ajouter une identitié" BUTTON_DELETE = "Supprimer" LOADING_PROCESS = "Met à jour la liste d'identités" -DELETING_ASK = "Êtes-vous sûr ?" +DELETING_ASK = "Êtes-vous sûr-e ?" [SETTINGS_CHANGE_PASSWORD] LEGEND_CHANGE_PASSWORD = "Modifier le mot de passe" @@ -590,7 +607,8 @@ BUTTON_ADD_OPEN_PGP_KEY = "Importer la clef OpenPGP" BUTTON_GENERATE_OPEN_PGP_KEYS = "Générer les clefs OpenPGP" TITLE_PRIVATE = "Privé" TITLE_PUBLIC = "Public" -DELETING_ASK = "Êtes-vous sûr ?" +DELETING_ASK = "Êtes-vous sûr-e ?" +GENERATE_ONLY_HTTPS = "HTTPS seulement" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Aide pour les raccourcis clavier" @@ -607,6 +625,7 @@ LABEL_HELP = "Aide" LABEL_CHECK_ALL = "Marquer tous les messages comme lus" LABEL_ARCHIVE = "Archiver" LABEL_DELETE = "Supprimer" +LABEL_OPEN_THREAD = "Ouvrir le message selectionné" LABEL_MOVE = "Déplacer" LABEL_READ = "Marquer les messages sélectionnés comme lus" LABEL_UNREAD = "Marquer les messages sélectionnés comme non-lus" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "Aucune clef publique n'a pu être trouvée" NO_PUBLIC_KEYS_FOUND_FOR = "Aucune clef publique n'a pu être trouvée pour \"%EMAIL%\"" NO_PRIVATE_KEY_FOUND = "Aucune clef privée n'a pu être trouvée" NO_PRIVATE_KEY_FOUND_FOR = "Aucune clef privée n'a pu être trouvée pour \"%EMAIL%\"" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Signature non-vérifiée" DECRYPTION_ERROR = "Erreur lors du déchiffrement OpenPGP" GOOD_SIGNATURE = "Signature valide pour %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Le support des cookies n'est pas disponible dans votre navigat S'il vous plaît activer le support des cookies dans les paramètres de votre navigateur et réessayez." BAD_BROWSER_TITLE = "Votre navigateur n'est pas à jour." BAD_BROWSER_DESC = "Pour utiliser toutes les fonctionnalités de l'application, -télécharger et installer l'un de ces navigateurs :" \ No newline at end of file +télécharger et installer l'un de ces navigateurs :" diff --git a/rainloop/v/0.0.0/langs/hu.ini b/rainloop/v/0.0.0/langs/hu.ini index 2cade922e..30759e708 100644 --- a/rainloop/v/0.0.0/langs/hu.ini +++ b/rainloop/v/0.0.0/langs/hu.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Jelöletlen" EMPTY_LIST = "Lista üres." EMPTY_SEARCH_LIST = "Nincs a keresésnek megfelelő levél." SEARCH_RESULT_FOR = "Eredmény: \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Betöltés" EMPTY_SUBJECT_TEXT = "(Nincs tárgy)" PUT_MESSAGE_HERE = "Drop message here to view it in the list" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Select message in list to view it here." PGP_PASSWORD_INPUT_PLACEHOLDER = "Jelszó" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Return Receipt (displayed) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Aláírás" BUTTON_ENCRYPT = "Titkosítás" BUTTON_SIGN_AND_ENCRYPT = "Aláírás és titkosítás" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-lépés hitelesítés teszt" LABEL_CODE = "Kód" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "General" LABEL_LANGUAGE = "Language" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Renaming a folder" DELETING_ASK = "Biztosak vagyunk benne?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Fiók lista" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "OpenPGP kulcs generálás" TITLE_PRIVATE = "Private" TITLE_PUBLIC = "Public" DELETING_ASK = "Are you sure?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Keyboard shortcuts help" @@ -607,6 +625,7 @@ LABEL_HELP = "Súgó" LABEL_CHECK_ALL = "Select all messages" LABEL_ARCHIVE = "Archiválás" LABEL_DELETE = "Tőrlés" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Move" LABEL_READ = "Read selected messages" LABEL_UNREAD = "Unread selected messages" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Cookies support is not available in your browser. Please enable Cookie support in your browser settings and retry." BAD_BROWSER_TITLE = "A böngésző elavult." BAD_BROWSER_DESC = "To use all the features of the application, -download and install one of these browsers:" \ No newline at end of file +download and install one of these browsers:" diff --git a/rainloop/v/0.0.0/langs/is.ini b/rainloop/v/0.0.0/langs/is.ini index a716bfb76..bdeab25e0 100644 --- a/rainloop/v/0.0.0/langs/is.ini +++ b/rainloop/v/0.0.0/langs/is.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Afflaggað" EMPTY_LIST = "Tómur listi." EMPTY_SEARCH_LIST = "Engin skilaboð stemmdu við leitina þína." SEARCH_RESULT_FOR = "Leitarniðurstöður fyrir \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Hleð" EMPTY_SUBJECT_TEXT = "(Ekkert viðfangsefni)" PUT_MESSAGE_HERE = "Settu skilaboðið hér til að skoða það í listanum" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Veldu bréf úr listanum til að skoða hér." PGP_PASSWORD_INPUT_PLACEHOLDER = "Password" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Return Receipt (displayed) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Sign" BUTTON_ENCRYPT = "Encrypt" BUTTON_SIGN_AND_ENCRYPT = "Sign and encrypt" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-Step verification test" LABEL_CODE = "Code" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Almennt" LABEL_LANGUAGE = "Tungumál" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Endurnefna möppu" DELETING_ASK = "Ertu viss?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Aðgangslisti" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generate OpenPGP Keys" TITLE_PRIVATE = "Private" TITLE_PUBLIC = "Public" DELETING_ASK = "Are you sure?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Keyboard shortcuts help" @@ -607,6 +625,7 @@ LABEL_HELP = "Help" LABEL_CHECK_ALL = "Select all messages" LABEL_ARCHIVE = "Archive" LABEL_DELETE = "Delete" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Move" LABEL_READ = "Read selected messages" LABEL_UNREAD = "Unread selected messages" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Köku stuðningur er ekki til staðar í vafranum þínum. Vinsamlegast gerðu JavaScript virkt í vafranum þínum og reyndu aftur." BAD_BROWSER_TITLE = "Vafrinn þinn er úreltur." BAD_BROWSER_DESC = "Til að geta notað alla valmöguleika í þessu forriti, -niðurhalaðu og settu upp einn af þessum vöfrum:" \ No newline at end of file +niðurhalaðu og settu upp einn af þessum vöfrum:" diff --git a/rainloop/v/0.0.0/langs/it.ini b/rainloop/v/0.0.0/langs/it.ini index ea795c3fb..a0152eb0b 100644 --- a/rainloop/v/0.0.0/langs/it.ini +++ b/rainloop/v/0.0.0/langs/it.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Non preferiti" EMPTY_LIST = "Lista vuota" EMPTY_SEARCH_LIST = "Nessun messaggio corrisponde alla tua ricerca" SEARCH_RESULT_FOR = "Risultati di ricerca per \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "ritorna alla lista dei messaggi" LIST_LOADING = "Caricamento..." EMPTY_SUBJECT_TEXT = "(Nessun oggetto)" PUT_MESSAGE_HERE = "Trascina il messaggio qui per vederlo nella lista" @@ -117,10 +118,10 @@ BUTTON_EDIT_AS_NEW = "Modifica come nuovo" BUTTON_SHOW_IMAGES = "Mostra immagini esterne" BUTTON_NOTIFY_READ_RECEIPT = "Chi ha inviato il messaggio ha richiesto di essere avvisato quando lo leggi." BUTTON_IN_NEW_WINDOW = "Leggi in una finestra separata" -BUTTON_THREAD_LIST = "Thread list" -BUTTON_THREAD_PREV = "Previous" -BUTTON_THREAD_NEXT = "Next" -BUTTON_THREAD_MORE = "More messages" +BUTTON_THREAD_LIST = "Messaggi in questa conversazione" +BUTTON_THREAD_PREV = "Messaggio precedente" +BUTTON_THREAD_NEXT = "Prossimo messaggio" +BUTTON_THREAD_MORE = "Più messaggi" MENU_HEADERS = "Mostra le intestazioni del messaggio" MENU_VIEW_ORIGINAL = "Visualizza l'orginale" MENU_DOWNLOAD_ORIGINAL = "Scarica come file .eml" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Seleziona un messaggio dalla lista per visualizzarlo qui" PGP_PASSWORD_INPUT_PLACEHOLDER = "Password" PGP_SIGNED_MESSAGE_DESC = "Messaggio firmato con OpenPGP (clicca qui per verificarlo)" PGP_ENCRYPTED_MESSAGE_DESC = "Messaggio cifrato con OpenPGP (clicca qui per decifrarlo)" +LINK_DOWNLOAD_AS_ZIP = "Scarica come archivio ZIP" +LINK_SAVE_TO_OWNCLOUD = "Salva su OwnCloud" +LINK_SAVE_TO_DROPBOX = "Salva su DropBox" [READ_RECEIPT] SUBJECT = "Avviso di lettura - %SUBJECT%" @@ -240,7 +244,7 @@ BUTTON_OPEN_PGP = "OpenPGP (Solo testo semplice)" BUTTON_REQUEST_DSN = "Richiedi conferma del ricevimento" [POPUPS_WELCOME_PAGE] -BUTTON_CLOSE = "Close" +BUTTON_CLOSE = "Chiudi" [POPUPS_ASK] BUTTON_YES = "Si" @@ -265,8 +269,8 @@ BUTTON_UPDATE_IDENTITY = "Aggiorna" LABEL_EMAIL = "Email" LABEL_NAME = "Nome" LABEL_REPLY_TO = "Rispondi a" -LABEL_SIGNATURE = "Signature" -LABEL_CC = "Cc" +LABEL_SIGNATURE = "Firma" +LABEL_CC = "CC" LABEL_BCC = "CCN" LABEL_SIGNATURE_INSERT_BEFORE = "Inserisci questa firma prima del messaggio citato nelle risposte" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Firma" BUTTON_ENCRYPT = "Cifra" BUTTON_SIGN_AND_ENCRYPT = "Firma e cifra" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "Verifica a 2 fattori" LABEL_CODE = "Codice" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Corrisponde Regexp" SELECT_TYPE_NOT_REGEXP = "Non corrisponde regexp" SELECT_TYPE_EQUAL_TO = "Uguale a" SELECT_TYPE_NOT_EQUAL_TO = "Non uguale a" +SELECT_TYPE_OVER = "Maggiore di" +SELECT_TYPE_UNDER = "Minore di" SELECT_MATCH_ANY = "Corrisponde ad una delle seguenti regole" SELECT_MATCH_ALL = "Corrisponde a tutte le seguenti regole" MARK_AS_READ_LABEL = "Marca come letto" @@ -357,6 +369,7 @@ STOP_LABEL = "Non interrompere l'elaborazione delle regole" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Oggetto (opzionale)" VACATION_MESSAGE_LABEL = "Messaggio" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Rifiuta messagio" ALL_INCOMING_MESSAGES_DESC = "Tutti i messaggi in ingresso" @@ -388,20 +401,20 @@ LABEL_TWO_FACTOR_STATUS = "Stato" LABEL_TWO_FACTOR_SECRET = "Codice segreto" LABEL_TWO_FACTOR_BACKUP_CODES = "Codici di riserva" BUTTON_CREATE = "Crea un nuovo codice segreto" -BUTTON_ACTIVATE = "Activate" -BUTTON_CLEAR = "Pulisci" -BUTTON_LOGOUT = "Logout" -BUTTON_DONE = "Done" -BUTTON_TEST = "Esegui test" +BUTTON_ACTIVATE = "Attiva" +BUTTON_CLEAR = "Disattiva" +BUTTON_LOGOUT = "Esci" +BUTTON_DONE = "Fatto" +BUTTON_TEST = "Esegui verifica" LINK_TEST = "test" BUTTON_SHOW_SECRET = "Mostra codice segreto" BUTTON_HIDE_SECRET = "Nascondi codice segreto" -TWO_FACTOR_REQUIRE_DESC = "Your account requires 2-Step verification configuration." +TWO_FACTOR_REQUIRE_DESC = "Il tuo account richiede l'autenticazione a due fattori." TWO_FACTOR_SECRET_CONFIGURED_DESC = "Configurato" TWO_FACTOR_SECRET_NOT_CONFIGURED_DESC = "Non configurato" TWO_FACTOR_SECRET_DESC = "Importa questo codice nel tuo client di Google Authenticator (o un altro client TOTP) usando il codice QR presente sotto o inserendo il codice manualmente." TWO_FACTOR_BACKUP_CODES_DESC = "Se non puoi ricevere codici da Google Authenticator, puoi usare i codici di riserva per entrare. Dopo aver usato un codice di riserva per entrare, esso si disattiverà." -TWO_FACTOR_SECRET_TEST_BEFORE_DESC = "You can't change this setting before test." +TWO_FACTOR_SECRET_TEST_BEFORE_DESC = "Non puoi salvare quest'impostazione senza prima verificarne il funzionamento." [TITLES] LOADING = "Caricamento..." @@ -467,7 +480,7 @@ LABEL_ADD_SIGNATURE_TO_ALL = "Aggiungi la firma a tutti i messaggi in uscita" [SETTINGS_SECURITY] LEGEND_SECURITY = "Sicurezza" -LABEL_CONFIGURATE_TWO_FACTOR = "Configurate 2-Step verification" +LABEL_CONFIGURATE_TWO_FACTOR = "Configura autenticazione a due fattori" LABEL_AUTOLOGOUT = "Disconnessione automatica" AUTOLOGIN_NEVER_OPTION_NAME = "Mai" AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minuti" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minuti" [SETTINGS_GENERAL] LEGEND_GENERAL = "Generali" LABEL_LANGUAGE = "Lingua" +LABEL_IDENTITY = "Identità" LABEL_LAYOUT = "Struttura" LABEL_LAYOUT_NO_SPLIT = "A pagina intera" LABEL_LAYOUT_VERTICAL_SPLIT = "Divisione verticale" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Rinomina cartella..." DELETING_ASK = "Sei sicuro?" TO_MANY_FOLDERS_DESC_1 = "Ci sono troppe cartelle!" TO_MANY_FOLDERS_DESC_2 = "Vengono visualizzate solo una parte per evitare problemi di performance." +HELP_DELETE_FOLDER = "Cancella cartella" +HELP_SHOW_HIDE_FOLDER = "Mostra/nascondi cartella" +HELP_CHECK_FOR_NEW_MESSAGES = "Controlla/non controlla la presenza di nuovi messaggi" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Lista degli account" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Genera chiave OpenPGP" TITLE_PRIVATE = "Privata" TITLE_PUBLIC = "Pubblica" DELETING_ASK = "Sei sicuro?" +GENERATE_ONLY_HTTPS = "solo tramite HTTPS" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Aiuto sulle scorciatoie da tastiera" @@ -607,6 +625,7 @@ LABEL_HELP = "Aiuto" LABEL_CHECK_ALL = "Seleziona tutti i messaggi" LABEL_ARCHIVE = "Archivia messaggio" LABEL_DELETE = "Elimina messaggio" +LABEL_OPEN_THREAD = "Apri la conversazione selezionata" LABEL_MOVE = "Sposta messaggio" LABEL_READ = "Marca come letti i messaggi selezionati" LABEL_UNREAD = "Marca come non letti i messaggi selezionati" @@ -619,8 +638,8 @@ LABEL_SWITCH_TO_MESSAGE = "Sposta la selezione sul messaggio corrente" LABEL_SWITCH_TO_FOLDER_LIST = "Sposta la selezione sulla lista delle cartelle" LABEL_FULLSCREEN_TOGGLE = "Attiva/disattiva la modalità a schermo intero" LABEL_BLOCKQUOTES_TOGGLE = "Mostra/nascondi le citazioni" -LABEL_THREAD_NEXT = "Next message in thread" -LABEL_THREAD_PREV = "Previous message in thread" +LABEL_THREAD_NEXT = "Prossimo messaggio nella conversazione" +LABEL_THREAD_PREV = "Messaggio precedente nella conversazione" LABEL_PRINT = "Stampa" LABEL_EXIT_FULLSCREEN = "Esci dalla modalità a schermo intero" LABEL_CLOSE_MESSAGE = "Chiudi messaggio (senza anteprima messaggi)" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "Nessuna chiave pubblica trovata" NO_PUBLIC_KEYS_FOUND_FOR = "Nessuna chiave pubblica trovata per l'indirizzo email \"%EMAIL%\"" NO_PRIVATE_KEY_FOUND = "Nessuna chiave privata trovata" NO_PRIVATE_KEY_FOUND_FOR = "Nessuna chiave privata trovata per l'indirizzo email \"%EMAIL%\"" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Firma non verificata" DECRYPTION_ERROR = "Decriptazione con OpenPGP fallita" GOOD_SIGNATURE = "Firma valida da %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Il supporto ai Cookie è disabilitato. Abilitare il supporto ai Cookie e riprovare." BAD_BROWSER_TITLE = "Il tuo browser è troppo vecchio" BAD_BROWSER_DESC = "Per usare tutte le funzionalità dell'applicazione, -scarica ed installa uno dei seguenti browser:" \ No newline at end of file +scarica ed installa uno dei seguenti browser:" diff --git a/rainloop/v/0.0.0/langs/ja-jp.ini b/rainloop/v/0.0.0/langs/ja-jp.ini index ebb6a2279..3ec6ea96c 100644 --- a/rainloop/v/0.0.0/langs/ja-jp.ini +++ b/rainloop/v/0.0.0/langs/ja-jp.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Unflagged" EMPTY_LIST = "メールは空です。おめでとう!" EMPTY_SEARCH_LIST = "検索条件に一致するメールは見つかりませんでした。高度な検索を試してみてください。" SEARCH_RESULT_FOR = "Search results for \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "読み込み中" EMPTY_SUBJECT_TEXT = "(件名なし)" PUT_MESSAGE_HERE = "Drop message here to view it in the list" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "選択したメールがここに表示されます。" PGP_PASSWORD_INPUT_PLACEHOLDER = "Password" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "開封確認メッセージ - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Sign" BUTTON_ENCRYPT = "Encrypt" BUTTON_SIGN_AND_ENCRYPT = "Sign and encrypt" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-Step verification test" LABEL_CODE = "Code" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "全般" LABEL_LANGUAGE = "言語" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Renaming a folder" DELETING_ASK = "Are you sure?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Account List" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generate OpenPGP Keys" TITLE_PRIVATE = "Private" TITLE_PUBLIC = "Public" DELETING_ASK = "Are you sure?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Keyboard shortcuts help" @@ -607,6 +625,7 @@ LABEL_HELP = "Help" LABEL_CHECK_ALL = "Select all messages" LABEL_ARCHIVE = "Archive" LABEL_DELETE = "Delete" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Move" LABEL_READ = "Read selected messages" LABEL_UNREAD = "Unread selected messages" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Cookies support is not available in your browser. Please enable Cookie support in your browser settings and retry." BAD_BROWSER_TITLE = "Your browser is outdated." BAD_BROWSER_DESC = "To use all the features of the application, -download and install one of these browsers:" \ No newline at end of file +download and install one of these browsers:" diff --git a/rainloop/v/0.0.0/langs/ko-kr.ini b/rainloop/v/0.0.0/langs/ko-kr.ini index 1d922c4e9..ad8f59480 100644 --- a/rainloop/v/0.0.0/langs/ko-kr.ini +++ b/rainloop/v/0.0.0/langs/ko-kr.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "일반" EMPTY_LIST = "Empty list." EMPTY_SEARCH_LIST = "검색 조건에 맞는 결과가 없습니다.." SEARCH_RESULT_FOR = "\"%SEARCH%\"에 대한 검색결과" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "로딩 중" EMPTY_SUBJECT_TEXT = "(제목 없음)" PUT_MESSAGE_HERE = "목록에서 표시할 메시지를 여기로 끌어 넣으세요." @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "목록에서 선택한 메시지가 여기에 표시됩니 PGP_PASSWORD_INPUT_PLACEHOLDER = "Password" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Return Receipt (displayed) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Sign" BUTTON_ENCRYPT = "Encrypt" BUTTON_SIGN_AND_ENCRYPT = "Sign and encrypt" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-Step verification test" LABEL_CODE = "Code" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -472,6 +485,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "일반" LABEL_LANGUAGE = "언어" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -548,6 +562,9 @@ RENAMING_PROCESS = "폴더명을 변경하고 있습니다." DELETING_ASK = "정말로 삭제하시겠습니까?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "계정 목록" @@ -588,6 +605,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generate OpenPGP Keys" TITLE_PRIVATE = "Private" TITLE_PUBLIC = "Public" DELETING_ASK = "Are you sure?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Keyboard shortcuts help" @@ -604,6 +622,7 @@ LABEL_HELP = "Help" LABEL_CHECK_ALL = "Select all messages" LABEL_ARCHIVE = "Archive" LABEL_DELETE = "Delete" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Move" LABEL_READ = "Read selected messages" LABEL_UNREAD = "Unread selected messages" @@ -633,6 +652,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -702,4 +722,4 @@ NO_SCRIPT_DESC = "사용 중인 브라우저가 자바스크립트를 지원하 NO_COOKIE_TITLE = "이 어플리케이션을 사용하려면 쿠키 사용이 지원되야 합니다." NO_COOKIE_DESC = "사용 중인 브라우저가 쿠키를 지원하지 않습니다. 브라우저 설정을 확인하여 쿠키 사용을 활성화하고 다시 시도해주세요." BAD_BROWSER_TITLE = "사용 중인 브라우저가 구버전입니다." -BAD_BROWSER_DESC = "이 어플리케이션을 정상적으로 사용하시려면 아래의 브라우저들 중 하나를 설치해주세요:" \ No newline at end of file +BAD_BROWSER_DESC = "이 어플리케이션을 정상적으로 사용하시려면 아래의 브라우저들 중 하나를 설치해주세요:" diff --git a/rainloop/v/0.0.0/langs/lt.ini b/rainloop/v/0.0.0/langs/lt.ini index c55b5203b..aa38a2768 100644 --- a/rainloop/v/0.0.0/langs/lt.ini +++ b/rainloop/v/0.0.0/langs/lt.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Nepažymėta" EMPTY_LIST = "Tuščias sąrašas." EMPTY_SEARCH_LIST = "Nėra pranešimų, atitinkančių jūsų paiešką." SEARCH_RESULT_FOR = "Ieškoti \"%SEARCH%\" rezultatuose" +BACK_TO_MESSAGE_LIST = "grįžti į sąrašą" LIST_LOADING = "Kraunasi" EMPTY_SUBJECT_TEXT = "(Be temos)" PUT_MESSAGE_HERE = "Įkelkite žinutę čia, kad matytumėte ją sąraše" @@ -120,7 +121,7 @@ BUTTON_IN_NEW_WINDOW = "Peržiūrėti atskirame lange" BUTTON_THREAD_LIST = "Temų sąrašas" BUTTON_THREAD_PREV = "Ankstesnis" BUTTON_THREAD_NEXT = "Kitas" -BUTTON_THREAD_MORE = "More messages" +BUTTON_THREAD_MORE = "Daugiau žinučių" MENU_HEADERS = "Rodyti pranešimų antraštės" MENU_VIEW_ORIGINAL = "Rodyti šaltinį" MENU_DOWNLOAD_ORIGINAL = "Atsisiųsti .eml failą" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Pasirinkite žinutę sąraše, kad matytumėte jos turinį PGP_PASSWORD_INPUT_PLACEHOLDER = "Slaptažodis" PGP_SIGNED_MESSAGE_DESC = "OpenPGP pasirašytas pranešimas (spustelkite patikrinimui)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP šifruotas pranešimas (spustelkite iššifravimui)" +LINK_DOWNLOAD_AS_ZIP = "Atsisiųsti zip archyvą" +LINK_SAVE_TO_OWNCLOUD = "Išsaugoti į ownCloud" +LINK_SAVE_TO_DROPBOX = "Išsaugoti į Dropbox" [READ_RECEIPT] SUBJECT = "Pristatymo patvirtinimas (laiškas parodytas) - %SUBJECT%" @@ -240,7 +244,7 @@ BUTTON_OPEN_PGP = "OpenPGP (Tik paprastas tekstas)" BUTTON_REQUEST_DSN = "Prašyti laiško gavimo pažymos" [POPUPS_WELCOME_PAGE] -BUTTON_CLOSE = "Close" +BUTTON_CLOSE = "Uždaryti" [POPUPS_ASK] BUTTON_YES = "Taip" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Pasirašyti" BUTTON_ENCRYPT = "Šifruoti" BUTTON_SIGN_AND_ENCRYPT = "Pasirašyti ir šifruoti" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-jų žingsnių patikrinimo bandymas" LABEL_CODE = "Kodas" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Ne Regexp" SELECT_TYPE_EQUAL_TO = "Tiksliai atitinka" SELECT_TYPE_NOT_EQUAL_TO = "Ne tiksliai" +SELECT_TYPE_OVER = "Daugiau kaip" +SELECT_TYPE_UNDER = "Mažiau nei" SELECT_MATCH_ANY = "Atitinka bet kurią iš šių taisyklių" SELECT_MATCH_ALL = "Atitinka visas šias taisykles" MARK_AS_READ_LABEL = "Žymėti skaitytu" @@ -357,6 +369,7 @@ STOP_LABEL = "Nesustoti vykdyti taisykles" EMAIL_LABEL = "E-paštas" VACATION_SUBJECT_LABEL = "Tema (nebūtina)" VACATION_MESSAGE_LABEL = "Žinutė" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Atmesti žinutę" ALL_INCOMING_MESSAGES_DESC = "Visi ateinantys laiškai" @@ -467,7 +480,7 @@ LABEL_ADD_SIGNATURE_TO_ALL = "Pridėti parašą visiems rašomiems laiškams" [SETTINGS_SECURITY] LEGEND_SECURITY = "Sauga" -LABEL_CONFIGURATE_TWO_FACTOR = "Configurate 2-Step verification" +LABEL_CONFIGURATE_TWO_FACTOR = "Konfiguruoti 2-žingsnių patikrinimą" LABEL_AUTOLOGOUT = "Automatinis atsijungimas" AUTOLOGIN_NEVER_OPTION_NAME = "Niekada" AUTOLOGIN_MINUTES_OPTION_NAME = "po %MINUTES% minučių" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "po %MINUTES% minučių" [SETTINGS_GENERAL] LEGEND_GENERAL = "Pagrindiniai" LABEL_LANGUAGE = "Kalba" +LABEL_IDENTITY = "Tapatybė" LABEL_LAYOUT = "Išdėstymas" LABEL_LAYOUT_NO_SPLIT = "Skaidymo nėra" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertikalus skaidymas" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Pervardinamas katalogas" DELETING_ASK = "Ar Jūs įsitikinę?" TO_MANY_FOLDERS_DESC_1 = "Pas jus per daug katalogų!" TO_MANY_FOLDERS_DESC_2 = "Mes rodome ne visus juos, kad išvengti našumo problemų." +HELP_DELETE_FOLDER = "Naikinti katalogą" +HELP_SHOW_HIDE_FOLDER = "Rodyti/Slėpti katalogą" +HELP_CHECK_FOR_NEW_MESSAGES = "Tikrinti/Netikrinti ar yra naujų laiškų" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Paskyrų sąrašas" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Sukurti OpenPGP raktus" TITLE_PRIVATE = "Privatus" TITLE_PUBLIC = "Viešas" DELETING_ASK = "Jūs įsitikinę?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Sparčiųjų klavišų pagalba" @@ -607,6 +625,7 @@ LABEL_HELP = "Pagalba" LABEL_CHECK_ALL = "Žymėti visus laiškus" LABEL_ARCHIVE = "Archyvuoti" LABEL_DELETE = "Šalinti" +LABEL_OPEN_THREAD = "Atidaryti pasirinktą giją" LABEL_MOVE = "Perkelti" LABEL_READ = "Pasirinktus žymėti kaip skaitytus" LABEL_UNREAD = "Pasirinktus žymėti kaip neskaitytus" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "Viešų raktų nerasta" NO_PUBLIC_KEYS_FOUND_FOR = "Viešų raktų nerasta \"%EMAIL%\" laiškui" NO_PRIVATE_KEY_FOUND = "Privačių raktų nerasta" NO_PRIVATE_KEY_FOUND_FOR = "Privačių raktų nerasta \"%EMAIL%\" laiškui" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Nepatikrintas parašas" DECRYPTION_ERROR = "OpenPGP dekodavimo klaida" GOOD_SIGNATURE = "Tinkamas parašas %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Slapukų paialikymas negalimas jūsų naršyklėje. Įjunkite slapukų palaikymą naršyklėje ir bandykite vėl." BAD_BROWSER_TITLE = "Jūsų naršyklė pasenusi." BAD_BROWSER_DESC = "Norint naudotis visais šios aplikacijos privalumais, -parsisiųskite ir įsidiekite vieną iš šių naršyklių:" \ No newline at end of file +parsisiųskite ir įsidiekite vieną iš šių naršyklių:" diff --git a/rainloop/v/0.0.0/langs/lv.ini b/rainloop/v/0.0.0/langs/lv.ini index 025b7fa95..8c99991e7 100644 --- a/rainloop/v/0.0.0/langs/lv.ini +++ b/rainloop/v/0.0.0/langs/lv.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Noņemtās atzīmes" EMPTY_LIST = "Tukšs saraksts." EMPTY_SEARCH_LIST = "Neviens ziņojums neatbilda jūsu meklētajiem kritērijiem." SEARCH_RESULT_FOR = "Meklēšanas rezultāti: \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Lādējas" EMPTY_SUBJECT_TEXT = "(Nav virsraksta)" PUT_MESSAGE_HERE = "Ievelciet ziņojumus šeit lai tos apskatītu." @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Izvēlaties ziņojumu no saraksta lai to apskatītu." PGP_PASSWORD_INPUT_PLACEHOLDER = "Password" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Return Receipt (displayed) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Sign" BUTTON_ENCRYPT = "Encrypt" BUTTON_SIGN_AND_ENCRYPT = "Sign and encrypt" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-Step verification test" LABEL_CODE = "Code" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Vispārējie" LABEL_LANGUAGE = "Valoda" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Pārsaukt mapi" DELETING_ASK = "Tiešām?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Kontu saraksts" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generate OpenPGP Keys" TITLE_PRIVATE = "Private" TITLE_PUBLIC = "Public" DELETING_ASK = "Are you sure?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Keyboard shortcuts help" @@ -607,6 +625,7 @@ LABEL_HELP = "Help" LABEL_CHECK_ALL = "Select all messages" LABEL_ARCHIVE = "Archive" LABEL_DELETE = "Delete" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Move" LABEL_READ = "Read selected messages" LABEL_UNREAD = "Unread selected messages" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Cookies atbalsts nav pieejams šai pārlūkprogrammai. Lūdzu ieslēdziet Cookies atbalstu." BAD_BROWSER_TITLE = "Jūsu pārlūkprogramma ir novecojusi." BAD_BROWSER_DESC = "Lai izmantotu pilnas šis aplikācijas iespējas, -lejupielādējat un uzinstalējas kādu no šīm pārlukprogrammām:" \ No newline at end of file +lejupielādējat un uzinstalējas kādu no šīm pārlukprogrammām:" diff --git a/rainloop/v/0.0.0/langs/nl.ini b/rainloop/v/0.0.0/langs/nl.ini index 04242608c..36626bd9b 100644 --- a/rainloop/v/0.0.0/langs/nl.ini +++ b/rainloop/v/0.0.0/langs/nl.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Zonder Vlag" EMPTY_LIST = "Geen berichten" EMPTY_SEARCH_LIST = "Geen items gevonden" SEARCH_RESULT_FOR = "Zoekresultaten voor\"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "terug naar berichtenlijst" LIST_LOADING = "Ophalen..." EMPTY_SUBJECT_TEXT = "(Geen onderwerp)" PUT_MESSAGE_HERE = "Sleep bericht hier om ze te bekijken in de lijst" @@ -135,12 +136,12 @@ LABEL_TO = "Naar" LABEL_TO_SHORT = "naar" LABEL_CC = "CC" LABEL_BCC = "BCC" -LABEL_REPLY_TO = "Reply-To" +LABEL_REPLY_TO = "Antwoordadres" PRINT_LABEL_FROM = "Van" PRINT_LABEL_TO = "Naar" PRINT_LABEL_CC = "CC" PRINT_LABEL_BCC = "BCC" -PRINT_LABEL_REPLY_TO = "Reply-To" +PRINT_LABEL_REPLY_TO = "Antwoordadres" PRINT_LABEL_DATE = "Datum" PRINT_LABEL_SUBJECT = "Onderwerp" PRINT_LABEL_ATTACHMENTS = "Bijlagen" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Selecteer een bericht in de lijst om hier te bekijken" PGP_PASSWORD_INPUT_PLACEHOLDER = "Wachtwoord" PGP_SIGNED_MESSAGE_DESC = "OpenPGP ondertekend bericht (klik om te verifiëren)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP versleuteld bericht (klik om te ontsleutelen)" +LINK_DOWNLOAD_AS_ZIP = "Download als zip" +LINK_SAVE_TO_OWNCLOUD = "Sla op in ownCloud" +LINK_SAVE_TO_DROPBOX = "Sla op in Dropbox" [READ_RECEIPT] SUBJECT = "Ontvangstbevestiging (weergegeven) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Ondertekenen" BUTTON_ENCRYPT = "Versleutelen" BUTTON_SIGN_AND_ENCRYPT = "Ondertekenen en versleutelen" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-Stap verificatie test" LABEL_CODE = "Code" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Reguliere expressie (Regexp)" SELECT_TYPE_NOT_REGEXP = "Niet reguliere expressie (Regexp)" SELECT_TYPE_EQUAL_TO = "Gelijk aan" SELECT_TYPE_NOT_EQUAL_TO = "Niet gelijk aan" +SELECT_TYPE_OVER = "Meer dan" +SELECT_TYPE_UNDER = "Minder dan" SELECT_MATCH_ANY = "Komt overeen met een van de volgende voorwaarden" SELECT_MATCH_ALL = "Komt overeen met alle voorwaarden" MARK_AS_READ_LABEL = "Markeer als gelezen" @@ -357,6 +369,7 @@ STOP_LABEL = "Stop niet met uitvoeren van volgende filters" EMAIL_LABEL = "E-mail" VACATION_SUBJECT_LABEL = "Onderwerp (optioneel)" VACATION_MESSAGE_LABEL = "Bericht" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Afwijsbericht" ALL_INCOMING_MESSAGES_DESC = "Alle inkomende berichten" @@ -391,17 +404,17 @@ BUTTON_CREATE = "Nieuwe geheime sleutel aanmaken" BUTTON_ACTIVATE = "Activate" BUTTON_CLEAR = "Wissen" BUTTON_LOGOUT = "Logout" -BUTTON_DONE = "Done" +BUTTON_DONE = "Klaar" BUTTON_TEST = "Test" LINK_TEST = "test" BUTTON_SHOW_SECRET = "Bekijk geheime sleutel" BUTTON_HIDE_SECRET = "Verberg geheime sleutel" -TWO_FACTOR_REQUIRE_DESC = "Your account requires 2-Step verification configuration." +TWO_FACTOR_REQUIRE_DESC = "Uw account vereist 2-Stap verificatie configuratie." TWO_FACTOR_SECRET_CONFIGURED_DESC = "Geconfigureerd" TWO_FACTOR_SECRET_NOT_CONFIGURED_DESC = "Niet geconfigureerd" TWO_FACTOR_SECRET_DESC = "Importeer deze informatie in uw Google Authenticator-client (of andere TOTP-client) door gebruik te maken van de QR code hier beneden of door de code handmatig in te voeren." -TWO_FACTOR_BACKUP_CODES_DESC = "Als u geen codes ontvangt via de Google Authenticator kan je de backup codes gebruiken om in te loggen. Na gebruik van de backup code wordt deze inactief." -TWO_FACTOR_SECRET_TEST_BEFORE_DESC = "You can't change this setting before test." +TWO_FACTOR_BACKUP_CODES_DESC = "Als u geen codes ontvangt via de Google Authenticator kunt u de backup codes gebruiken om in te loggen. Na gebruik van de backup code wordt deze inactief." +TWO_FACTOR_SECRET_TEST_BEFORE_DESC = "U kunt deze instelling niet wijzigen voor het testen." [TITLES] LOADING = "Ophalen..." @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minuten" [SETTINGS_GENERAL] LEGEND_GENERAL = "Algemeen" LABEL_LANGUAGE = "Taal" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Indeling" LABEL_LAYOUT_NO_SPLIT = "Geen splitsing" LABEL_LAYOUT_VERTICAL_SPLIT = "Verticale splitsing" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Map hernoemen" DELETING_ASK = "Weet u het zeker?" TO_MANY_FOLDERS_DESC_1 = "U heeft te veel mappen!" TO_MANY_FOLDERS_DESC_2 = "Er worden er maar een deel weergegeven om prestatieproblemen te voorkomen." +HELP_DELETE_FOLDER = "Verwijder map" +HELP_SHOW_HIDE_FOLDER = "Toon/verberg map" +HELP_CHECK_FOR_NEW_MESSAGES = "Controleer wel of niet op nieuwe berichten" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Account Lijst" @@ -591,11 +608,12 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Genereer OpenPGP sleutels" TITLE_PRIVATE = "Privé sleutel" TITLE_PUBLIC = "Publieke sleutel" DELETING_ASK = "Weet u het zeker?" +GENERATE_ONLY_HTTPS = "Alleen HTTPS" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Hulp bij toetsenbord sneltoetsen" TAB_MAILBOX = "Mailbox" -TAB_MESSAGE_LIST = "Berichten lijst" +TAB_MESSAGE_LIST = "Berichtenlijst" TAB_MESSAGE_VIEW = "Bericht leesvenster" TAB_COMPOSE = "Opstellen" LABEL_OPEN_USER_DROPDOWN = "Open gebruikers menu" @@ -607,16 +625,17 @@ LABEL_HELP = "Help" LABEL_CHECK_ALL = "Selecteer alle berichten" LABEL_ARCHIVE = "Archiveren" LABEL_DELETE = "Verwijderen" +LABEL_OPEN_THREAD = "Open geselecteerde berichtenlijst" LABEL_MOVE = "Verplaatsen" LABEL_READ = "Markeer geselecteerde berichten als gelezen" LABEL_UNREAD = "Markeer geselecteerde berichten als ongelezen" LABEL_IMPORTANT = "Belangrijk, vlag geselecteerde berichten" LABEL_SEARCH = "Zoeken" LABEL_CANCEL_SEARCH = "Zoekopdracht afbreken" -LABEL_FULLSCREEN_ENTER = "Bericht in volledig scherm lezen (leesvenster ingeschakeld)" +LABEL_FULLSCREEN_ENTER = "Bericht in volledig scherm lezen(leesvenster ingeschakeld)" LABEL_VIEW_MESSAGE_ENTER = "Bericht lezen (leesvenster uitgeschakeld)" LABEL_SWITCH_TO_MESSAGE = "Schakel focus naar bericht" -LABEL_SWITCH_TO_FOLDER_LIST = "Schakel focus naar berichten lijst" +LABEL_SWITCH_TO_FOLDER_LIST = "Schakel focus naar berichtenlijst" LABEL_FULLSCREEN_TOGGLE = "Schakel tussen normaal en lezen in volledig scherm" LABEL_BLOCKQUOTES_TOGGLE = "Schakel blok citaten aan of uit" LABEL_THREAD_NEXT = "Volgende bericht in groep" @@ -624,7 +643,7 @@ LABEL_THREAD_PREV = "Vorige bericht in groep" LABEL_PRINT = "Afdrukken" LABEL_EXIT_FULLSCREEN = "Volledig scherm sluiten" LABEL_CLOSE_MESSAGE = "Bericht sluiten (leesvenster uitgeschakeld)" -LABEL_SWITCH_TO_LIST = "Schakel focus terug naar berichten lijst" +LABEL_SWITCH_TO_LIST = "Schakel focus terug naar berichtenlijst" LABEL_OPEN_COMPOSE_POPUP = "Open nieuw bericht venster" LABEL_OPEN_IDENTITIES_DROPDOWN = "Open identiteiten menu" LABEL_SAVE_MESSAGE = "Concept opslaan" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "Geen publieke sleutels gevonden" NO_PUBLIC_KEYS_FOUND_FOR = "Geen publieke sleutels gevonden voor e-mail adres \"%EMAIL%\"" NO_PRIVATE_KEY_FOUND = "Geen geheime sleutel gevonden" NO_PRIVATE_KEY_FOUND_FOR = "Geen geheime sleutel gevonden voor e-mail adres \"%EMAIL%\"" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Ongeverifieerde handtekening" DECRYPTION_ERROR = "OpenPGP decryptie fout" GOOD_SIGNATURE = "Juiste handtekening van %USER%" @@ -662,7 +682,7 @@ NEW_PASSWORD_SHORT = "Wachtwoord is te kort" NEW_PASSWORD_WEAK = "Wachtwoord is te makkelijk" NEW_PASSWORD_FORBIDDENT = "Wachtwoord bevat verboden tekens" CONTACTS_SYNC_ERROR = "Contactpersonen synchronisatie fout" -CANT_GET_MESSAGE_LIST = "Berichten lijst kan niet worden opgehaald" +CANT_GET_MESSAGE_LIST = "Berichtenlijst kan niet worden opgehaald" CANT_GET_MESSAGE = "Bericht kan niet worden opgehaald" CANT_DELETE_MESSAGE = "Kan bericht niet verwijderen" CANT_MOVE_MESSAGE = "Kan bericht niet verplaatsen" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Cookies ondersteuning is niet beschikbaar in uw browser. Gelieve Cookies in te schakelen en opnieuw te proberen." BAD_BROWSER_TITLE = "Uw browser is verouderd" BAD_BROWSER_DESC = "Om alle functies van deze applicatie te gebruiken, -download en installeer een van de volgende browsers:" \ No newline at end of file +download en installeer een van de volgende browsers:" diff --git a/rainloop/v/0.0.0/langs/no.ini b/rainloop/v/0.0.0/langs/no.ini index a91b414d8..197fa8757 100644 --- a/rainloop/v/0.0.0/langs/no.ini +++ b/rainloop/v/0.0.0/langs/no.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Ikke markert" EMPTY_LIST = "Tom liste" EMPTY_SEARCH_LIST = "Ingen meldinger matchet søket ditt." SEARCH_RESULT_FOR = "Søkeresultater for \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Laster" EMPTY_SUBJECT_TEXT = "(tomt emne)" PUT_MESSAGE_HERE = "Dra melding her for å vise det i listen" @@ -117,10 +118,10 @@ BUTTON_EDIT_AS_NEW = "Endre som ny" BUTTON_SHOW_IMAGES = "Vis eksterne bilder" BUTTON_NOTIFY_READ_RECEIPT = "Avsender har bedt om lesebekreftelse" BUTTON_IN_NEW_WINDOW = "Vis i eget vindu" -BUTTON_THREAD_LIST = "Thread list" -BUTTON_THREAD_PREV = "Previous" -BUTTON_THREAD_NEXT = "Next" -BUTTON_THREAD_MORE = "More messages" +BUTTON_THREAD_LIST = "Trådliste" +BUTTON_THREAD_PREV = "Forrige" +BUTTON_THREAD_NEXT = "Neste" +BUTTON_THREAD_MORE = "Flere meldinger" MENU_HEADERS = "Vis meldingshoder" MENU_VIEW_ORIGINAL = "Vis original" MENU_DOWNLOAD_ORIGINAL = "Last ned som .eml-fil" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Klikk på en e-post for å lese" PGP_PASSWORD_INPUT_PLACEHOLDER = "Passord" PGP_SIGNED_MESSAGE_DESC = "OpenPGP-signert melding (klikk for å verifisere)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP-kryptert melding (klikk for å dekryptere)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Lage i ownCloud" +LINK_SAVE_TO_DROPBOX = "Lagre i Dropbox" [READ_RECEIPT] SUBJECT = "Lesebekreftelse (meldingen er lest) - %SUBJECT%" @@ -180,7 +184,7 @@ LABEL_PHONE = "Telefon" LABEL_WEB = "Web" LABEL_BIRTHDAY = "Bursdag" LINK_ADD_EMAIL = "Legg til en e-postadresse" -LINK_ADD_PHONE = "Legg til en telefon" +LINK_ADD_PHONE = "Legg til telefonnummer" LINK_BIRTHDAY = "Bursdag" PLACEHOLDER_ENTER_DISPLAY_NAME = "Visningsnavn" PLACEHOLDER_ENTER_LAST_NAME = "Etternavn" @@ -230,16 +234,16 @@ FORWARD_MESSAGE_TOP_CC = "CC" FORWARD_MESSAGE_TOP_SENT = "Sendt" FORWARD_MESSAGE_TOP_SUBJECT = "Emne" EMPTY_TO_ERROR_DESC = "Vennligst oppgi minst én mottaker" -NO_ATTACHMENTS_HERE_DESC = "No attachments here." -ATTACHMENTS_ERROR_DESC = "Warning! Not all attachments have been uploaded." +NO_ATTACHMENTS_HERE_DESC = "Ingen vedlegg her." +ATTACHMENTS_ERROR_DESC = "Advarsel! Alle vedleggene er ikke lastet opp ennå." ATTACHMENTS_UPLOAD_ERROR_DESC = "Alle vedleggene er ikke lastet opp ennå" BUTTON_REQUEST_READ_RECEIPT = "Be om en lesebekreftelse når meldingen er lest" -BUTTON_MARK_AS_IMPORTANT = "Mark as important" -BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" -BUTTON_REQUEST_DSN = "Request a delivery receipt" +BUTTON_MARK_AS_IMPORTANT = "Merk som viktig" +BUTTON_OPEN_PGP = "OpenPGP (Bare i ren tekst)" +BUTTON_REQUEST_DSN = "Be om leveringsbekreftelse" [POPUPS_WELCOME_PAGE] -BUTTON_CLOSE = "Close" +BUTTON_CLOSE = "Lukk" [POPUPS_ASK] BUTTON_YES = "Ja" @@ -253,8 +257,8 @@ TITLE_LANGUAGES = "Velg språk" [POPUPS_ADD_ACCOUNT] TITLE_ADD_ACCOUNT = "Legg til konto?" BUTTON_ADD_ACCOUNT = "Legg til" -TITLE_UPDATE_ACCOUNT = "Update Account?" -BUTTON_UPDATE_ACCOUNT = "Update" +TITLE_UPDATE_ACCOUNT = "Oppdatere konto?" +BUTTON_UPDATE_ACCOUNT = "Oppdater" [POPUPS_IDENTITY] TITLE_ADD_IDENTITY = "Legg til identitet?" @@ -264,10 +268,10 @@ BUTTON_UPDATE_IDENTITY = "Oppdater" LABEL_EMAIL = "E-post" LABEL_NAME = "Navn" LABEL_REPLY_TO = "Svar til" -LABEL_SIGNATURE = "Signature" +LABEL_SIGNATURE = "Signatur" LABEL_CC = "Cc" LABEL_BCC = "Blindkopi" -LABEL_SIGNATURE_INSERT_BEFORE = "Insert this signature before quoted text in replies" +LABEL_SIGNATURE_INSERT_BEFORE = "Legg til denne signaturen før sitert tekst" [POPUPS_CREATE_FOLDER] TITLE_CREATE_FOLDER = "Opprett en mappe ?" @@ -304,7 +308,7 @@ LABEL_EMAIL = "E-post" LABEL_NAME = "Navn" LABEL_PASSWORD = "Passord" LABEL_KEY_BIT_LENGTH = "Nøkkellengde" -BUTTON_GENERATE_OPEN_PGP_KEYS = "Generate" +BUTTON_GENERATE_OPEN_PGP_KEYS = "Generer" [POPUPS_COMPOSE_OPEN_PGP] TITLE_COMPOSE_OPEN_PGP = "OpenPGP signer/krypter" @@ -315,49 +319,58 @@ BUTTON_SIGN = "Signer" BUTTON_ENCRYPT = "Krypter" BUTTON_SIGN_AND_ENCRYPT = "Signer og krypter" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP dekrypter" +LABEL_KEY = "Private nøkkel" +LABEL_PASSWORD = "Passoord" +BUTTON_DECRYPT = "Dekrypter" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-stegs verifiseringstest" LABEL_CODE = "Kode" BUTTON_TEST = "Test" [POPUPS_FILTER] -TITLE_CREATE_FILTER = "Create a filter?" -TITLE_EDIT_FILTER = "Update filter?" -FILTER_NAME = "Name" -LEGEND_CONDITIONS = "Conditions" -LEGEND_ACTIONS = "Actions" -BUTTON_DONE = "Done" -BUTTON_ADD_CONDITION = "Add a Condition" -SELECT_ACTION_NONE = "None" -SELECT_ACTION_MOVE_TO = "Move to" -SELECT_ACTION_FORWARD_TO = "Forward to" -SELECT_ACTION_REJECT = "Reject" -SELECT_ACTION_VACATION_MESSAGE = "Vacation message" -SELECT_ACTION_DISCARD = "Discard" -SELECT_FIELD_FROM = "From" -SELECT_FIELD_RECIPIENTS = "Recipients (To or CC)" -SELECT_FIELD_SUBJECT = "Subject" -SELECT_FIELD_HEADER = "Header" -SELECT_FIELD_SIZE = "Size" -SELECT_TYPE_CONTAINS = "Contains" -SELECT_TYPE_NOT_CONTAINS = "Not Contains" -SELECT_TYPE_MATCHES = "Matches (* and ? supported)" -SELECT_TYPE_NOT_MATCHES = "Not Matches (* and ? supported)" +TITLE_CREATE_FILTER = "Opprette et filter?" +TITLE_EDIT_FILTER = "Oppdater filter?" +FILTER_NAME = "Navn" +LEGEND_CONDITIONS = "Betingelser" +LEGEND_ACTIONS = "Handlinger" +BUTTON_DONE = "Ferdig" +BUTTON_ADD_CONDITION = "Legg til en betingelse" +SELECT_ACTION_NONE = "Ingen" +SELECT_ACTION_MOVE_TO = "Flytt til" +SELECT_ACTION_FORWARD_TO = "Videresend til" +SELECT_ACTION_REJECT = "Avvis" +SELECT_ACTION_VACATION_MESSAGE = "Feriemelding" +SELECT_ACTION_DISCARD = "Forkast" +SELECT_FIELD_FROM = "Fra" +SELECT_FIELD_RECIPIENTS = "Mottakere (til eller CC)" +SELECT_FIELD_SUBJECT = "Emne" +SELECT_FIELD_HEADER = "Meldingshode" +SELECT_FIELD_SIZE = "Størrelse" +SELECT_TYPE_CONTAINS = "Inneholder" +SELECT_TYPE_NOT_CONTAINS = "Inneholder ikke" +SELECT_TYPE_MATCHES = "Matcher (støtte for * og ?)" +SELECT_TYPE_NOT_MATCHES = "Matcher ikke (støtte for * og ?)" SELECT_TYPE_REGEXP = "Regexp" -SELECT_TYPE_NOT_REGEXP = "Not Regexp" -SELECT_TYPE_EQUAL_TO = "Equal To" -SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" -SELECT_MATCH_ANY = "Matching any of the following rules" -SELECT_MATCH_ALL = "Matching all of the following rules" -MARK_AS_READ_LABEL = "Mark as read" -REPLY_INTERVAL_LABEL = "Reply interval (days)" -KEEP_LABEL = "Keep" -STOP_LABEL = "Don't stop processing rules" -EMAIL_LABEL = "Email" -VACATION_SUBJECT_LABEL = "Subject (optional)" -VACATION_MESSAGE_LABEL = "Message" -REJECT_MESSAGE_LABEL = "Reject message" -ALL_INCOMING_MESSAGES_DESC = "All incoming messages" +SELECT_TYPE_NOT_REGEXP = "Ikke Regexp" +SELECT_TYPE_EQUAL_TO = "Er lik" +SELECT_TYPE_NOT_EQUAL_TO = "Er ikke lik" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" +SELECT_MATCH_ANY = "Samsvarer med en av følgende regler" +SELECT_MATCH_ALL = "Samsvarer med alle følgende regler" +MARK_AS_READ_LABEL = "Merk som lest" +REPLY_INTERVAL_LABEL = "Svarintervall (dager)" +KEEP_LABEL = "Behold" +STOP_LABEL = "Ikke stopp bruk av regler" +EMAIL_LABEL = "E-post" +VACATION_SUBJECT_LABEL = "Emne (valgfritt)" +VACATION_MESSAGE_LABEL = "Melding" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" +REJECT_MESSAGE_LABEL = "Forkast melding" +ALL_INCOMING_MESSAGES_DESC = "Alle innkommende meldinger" [POPUPS_SYSTEM_FOLDERS] TITLE_SYSTEM_FOLDERS = "Velg systemmapper" @@ -387,20 +400,20 @@ LABEL_TWO_FACTOR_STATUS = "Status" LABEL_TWO_FACTOR_SECRET = "Secret" LABEL_TWO_FACTOR_BACKUP_CODES = "Backupkoder" BUTTON_CREATE = "Lag ny secret" -BUTTON_ACTIVATE = "Activate" +BUTTON_ACTIVATE = "Aktiver" BUTTON_CLEAR = "Tøm" -BUTTON_LOGOUT = "Logout" -BUTTON_DONE = "Done" +BUTTON_LOGOUT = "Logg ut" +BUTTON_DONE = "Ferdig" BUTTON_TEST = "Test" LINK_TEST = "test" -BUTTON_SHOW_SECRET = "Vis secret" +BUTTON_SHOW_SECRET = "Vis Secret" BUTTON_HIDE_SECRET = "Skjul Secret" -TWO_FACTOR_REQUIRE_DESC = "Your account requires 2-Step verification configuration." +TWO_FACTOR_REQUIRE_DESC = "Din konto krever 2-stegs verifisering." TWO_FACTOR_SECRET_CONFIGURED_DESC = "Konfigurert" TWO_FACTOR_SECRET_NOT_CONFIGURED_DESC = "Ikke konfigurert" TWO_FACTOR_SECRET_DESC = "Importer denne informasjonen til din Google Authenticator klient (eller andre klienter) ved å bruke QR-koden under, eller ved å skrive inn koden manuelt." -TWO_FACTOR_BACKUP_CODES_DESC = "Om du ikke mottar koder fra Google Authenticator, kan du brukeyou can use backupkodene for å logge inn. Disse kodene vil bli deaktivert etter bruk." -TWO_FACTOR_SECRET_TEST_BEFORE_DESC = "You can't change this setting before test." +TWO_FACTOR_BACKUP_CODES_DESC = "Om du ikke mottar koder fra Google Authenticator, kan du bruke backupkodene for å logge inn. Disse kodene vil bli deaktivert etter bruk." +TWO_FACTOR_SECRET_TEST_BEFORE_DESC = "Du kan ikke endre denne innstillingen før du tester." [TITLES] LOADING = "Laster" @@ -432,7 +445,7 @@ LABEL_ACCOUNTS_NAME = "Kontoer" LABEL_IDENTITY_NAME = "Identitet" LABEL_IDENTITIES_NAME = "Identiteter" LABEL_FILTERS_NAME = "Filters" -LABEL_TEMPLATES_NAME = "Templates" +LABEL_TEMPLATES_NAME = "Maler" LABEL_SECURITY_NAME = "Sikkerhet" LABEL_SOCIAL_NAME = "Sosialt" LABEL_THEMES_NAME = "Tema" @@ -441,21 +454,21 @@ LABEL_OPEN_PGP_NAME = "OpenPGP" BUTTON_BACK = "Tilbake" [SETTINGS_FILTERS] -LEGEND_FILTERS = "Filters" -BUTTON_SAVE = "Save" -BUTTON_ADD_FILTER = "Add a Filter" -BUTTON_DELETE = "Delete" -BUTTON_RAW_SCRIPT = "Use Custom User Script" -SUBNAME_NONE = "None" -SUBNAME_MOVE_TO = "Move to \"%FOLDER%\"" -SUBNAME_FORWARD_TO = "Forward to \"%EMAIL%\"" -SUBNAME_REJECT = "Reject" -SUBNAME_VACATION_MESSAGE = "Vacation message" -SUBNAME_DISCARD = "Discard" -CAPABILITY_LABEL = "Capability" -LOADING_PROCESS = "Updating filter list" -DELETING_ASK = "Are you sure?" -CHACHES_NEED_TO_BE_SAVED_DESC = "These changes need to be saved to the server." +LEGEND_FILTERS = "Filtre" +BUTTON_SAVE = "Lagre" +BUTTON_ADD_FILTER = "Legg til et filter" +BUTTON_DELETE = "Slett" +BUTTON_RAW_SCRIPT = "Bruk egendefinert script" +SUBNAME_NONE = "Ingen" +SUBNAME_MOVE_TO = "Flytt til \"%FOLDER%\"" +SUBNAME_FORWARD_TO = "Videresend til \"%EMAIL%\"" +SUBNAME_REJECT = "Avslå" +SUBNAME_VACATION_MESSAGE = "Feriemelding" +SUBNAME_DISCARD = "Forkast" +CAPABILITY_LABEL = "Evne" +LOADING_PROCESS = "Oppdater filterlisten" +DELETING_ASK = "Er du sikker?" +CHACHES_NEED_TO_BE_SAVED_DESC = "Disse endringene må lagres på serveren." [SETTINGS_IDENTITY] LEGEND_IDENTITY = "Identitet" @@ -465,24 +478,25 @@ LABEL_SIGNATURE = "Signatur" LABEL_ADD_SIGNATURE_TO_ALL = "Vil du legge til signatur i alle utgående meldinger?" [SETTINGS_SECURITY] -LEGEND_SECURITY = "Security" -LABEL_CONFIGURATE_TWO_FACTOR = "Configurate 2-Step verification" -LABEL_AUTOLOGOUT = "Auto Logout" -AUTOLOGIN_NEVER_OPTION_NAME = "Never" -AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" +LEGEND_SECURITY = "Sikkerhet" +LABEL_CONFIGURATE_TWO_FACTOR = "Konfiguer 2-stegs verifisering" +LABEL_AUTOLOGOUT = "Logg ut automatisk" +AUTOLOGIN_NEVER_OPTION_NAME = "Aldri" +AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minutt(er)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Generelt" LABEL_LANGUAGE = "Språk" -LABEL_LAYOUT = "Layout" -LABEL_LAYOUT_NO_SPLIT = "No Split" -LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" -LABEL_LAYOUT_HORIZONTAL_SPLIT = "Horizontal Split" +LABEL_IDENTITY = "Identitet" +LABEL_LAYOUT = "Utseende" +LABEL_LAYOUT_NO_SPLIT = "Ingen splitting" +LABEL_LAYOUT_VERTICAL_SPLIT = "Vertikal splitting" +LABEL_LAYOUT_HORIZONTAL_SPLIT = "Horisontal splitting" LABEL_EDITOR = "Standard teksteditor" LABEL_EDITOR_HTML = "Html" LABEL_EDITOR_PLAIN = "Ren tekst" -LABEL_EDITOR_HTML_FORCED = "Html (forced)" -LABEL_EDITOR_PLAIN_FORCED = "Plain (forced)" +LABEL_EDITOR_HTML_FORCED = "Html (tvungen)" +LABEL_EDITOR_PLAIN_FORCED = "Ren tekst (tvungen)" LABEL_ANIMATION = "Interface animasjon" LABEL_ANIMATION_FULL = "Full" LABEL_ANIMATION_NORMAL = "Normal" @@ -496,7 +510,7 @@ LABEL_SHOW_IMAGES = "Vis alltid eksterne bilder i meldingsteksten" LABEL_SHOW_ANIMATION = "Vis animasjon" LABEL_MESSAGE_PER_PAGE = "Meldinger på hver side" LABEL_NOTIFICATIONS = "Varsler" -LABEL_SOUND_NOTIFICATION = "Sound notification" +LABEL_SOUND_NOTIFICATION = "Lydvarsler" LABEL_CHROME_NOTIFICATION_DESC = "Vis popup-varsel når du mottar en ny melding" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Blokkert av nettleseren)" @@ -548,19 +562,22 @@ CREATING_PROCESS = "Oppretter mappen" DELETING_PROCESS = "Slette en mappe" RENAMING_PROCESS = "Endre navn på en mappe" DELETING_ASK = "Er du sikker?" -TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" -TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +TO_MANY_FOLDERS_DESC_1 = "Du har for mange mapper!" +TO_MANY_FOLDERS_DESC_2 = "Vi har bare vist en del av problemet for å unngå problemer med ytelsen." +HELP_DELETE_FOLDER = "Slett mappe" +HELP_SHOW_HIDE_FOLDER = "Vis/skjul mappe" +HELP_CHECK_FOR_NEW_MESSAGES = "Sjekk/ikke sjekk for nye meldinger" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Kontoer" -LEGEND_IDENTITIES = "Identities" -LEGEND_ACCOUNTS_AND_IDENTITIES = "Accounts and Identities" +LEGEND_IDENTITIES = "Identiteter" +LEGEND_ACCOUNTS_AND_IDENTITIES = "Kontoer og identiteter" BUTTON_ADD_ACCOUNT = "Legg til konto" -BUTTON_ADD_IDENTITY = "Add an Identity" +BUTTON_ADD_IDENTITY = "Legg til en identitet" BUTTON_DELETE = "Slett" LOADING_PROCESS = "Oppdaterer kontoer" DELETING_ASK = "Er du sikker?" -DEFAULT_IDENTITY_LABEL = "default" +DEFAULT_IDENTITY_LABEL = "Standard" [SETTINGS_IDENTITIES] LEGEND_IDENTITY = "Identitet" @@ -590,6 +607,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generer OpenPGP-nøkler" TITLE_PRIVATE = "Privat" TITLE_PUBLIC = "Offentlig" DELETING_ASK = "Er du sikker?" +GENERATE_ONLY_HTTPS = "Kun HTTPS" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Tastatursnarveier" @@ -601,11 +619,12 @@ LABEL_OPEN_USER_DROPDOWN = "Åpne brukerliste" LABEL_REPLY = "Svar" LABEL_REPLY_ALL = "Svar alle" LABEL_FORWARD = "Videresend" -LABEL_FORWARD_MULTIPLY = "Videresent (mange)" +LABEL_FORWARD_MULTIPLY = "Videresend som vedlegg" LABEL_HELP = "Hjelp" LABEL_CHECK_ALL = "Merk alle meldinger" LABEL_ARCHIVE = "Arkiver" LABEL_DELETE = "Slett" +LABEL_OPEN_THREAD = "Åpne valgt tråd" LABEL_MOVE = "Flytt" LABEL_READ = "Merk som lest" LABEL_UNREAD = "Merk som ulest" @@ -618,8 +637,8 @@ LABEL_SWITCH_TO_MESSAGE = "Flytt fokus til valgt melding" LABEL_SWITCH_TO_FOLDER_LIST = "Flytt fokus til mappeliste" LABEL_FULLSCREEN_TOGGLE = "Fullskjerm modus" LABEL_BLOCKQUOTES_TOGGLE = "Vis/skjul sitert melding" -LABEL_THREAD_NEXT = "Next message in thread" -LABEL_THREAD_PREV = "Previous message in thread" +LABEL_THREAD_NEXT = "Neste melding i tråd" +LABEL_THREAD_PREV = "Forrige melding i tråd" LABEL_PRINT = "Skriv ut" LABEL_EXIT_FULLSCREEN = "Avslutt fullskjerm modus" LABEL_CLOSE_MESSAGE = "Lukk melding" @@ -631,16 +650,17 @@ LABEL_SEND_MESSAGE = "Send melding" LABEL_CLOSE_COMPOSE = "Lukk ny melding" [PGP_NOTIFICATIONS] -NO_PUBLIC_KEYS_FOUND = "No public keys found" -NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" -NO_PRIVATE_KEY_FOUND = "No private key found" -NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" -UNVERIFIRED_SIGNATURE = "Unverified signature" -DECRYPTION_ERROR = "OpenPGP decryption error" -GOOD_SIGNATURE = "Good signature from %USER%" -PGP_ERROR = "OpenPGP error: %ERROR%" -SPECIFY_FROM_EMAIL = "Please specify FROM email address" -SPECIFY_AT_LEAST_ONE_RECIPIENT = "Please specify at least one recipient" +NO_PUBLIC_KEYS_FOUND = "Ingen offentlige nøkler funnet" +NO_PUBLIC_KEYS_FOUND_FOR = "Ingen offentlige nøkler ble funnet for \"%EMAIL%\" epost" +NO_PRIVATE_KEY_FOUND = "Ingen private nøkler funnet" +NO_PRIVATE_KEY_FOUND_FOR = "Ingen private nøkler ble funnet for \"%EMAIL%\" epost" +ADD_A_PUBLICK_KEY = "Add a public key" +UNVERIFIRED_SIGNATURE = "Uverifisert signatur" +DECRYPTION_ERROR = "Feil med OpenPGP dekryptering" +GOOD_SIGNATURE = "Godkjent signatur fra %USER%" +PGP_ERROR = "OpenPGP feil: %ERROR%" +SPECIFY_FROM_EMAIL = "Vennligst spesifieser en avsenderadresse" +SPECIFY_AT_LEAST_ONE_RECIPIENT = "Vennligst spesifiser minst én mottaker" [NOTIFICATIONS] INVALID_TOKEN = "Ugyldig token" @@ -668,9 +688,9 @@ CANT_MOVE_MESSAGE = "Kan ikke flytte meldingen" CANT_SAVE_MESSAGE = "Kan ikke lagre melding" CANT_SEND_MESSAGE = "Kan ikke sende melding" INVALID_RECIPIENTS = "Ugyldige mottakere" -CANT_SAVE_FILTERS = "Can't save filters" -CANT_GET_FILTERS = "Can't get filters" -FILTERS_ARE_NOT_CORRECT = "Filters are not correct" +CANT_SAVE_FILTERS = "Kan ikke lagre filtre" +CANT_GET_FILTERS = "Kan ikke hente filtre" +FILTERS_ARE_NOT_CORRECT = "Filtre er ikke korrekte" CANT_CREATE_FOLDER = "Kan ikke opprette mappe" CANT_RENAME_FOLDER = "Kan ikke endre navn på mappen" CANT_DELETE_FOLDER = "Kan ikke slette mappen" @@ -688,7 +708,7 @@ LICENSING_SERVER_IS_UNAVAILABLE = "Abonnement-server er utilgjengelig" LICENSING_DOMAIN_EXPIRED = "Abonnementet for dette domenet er utløpt." LICENSING_DOMAIN_BANNED = "Abonnementet for dette domenet er forbudt." DEMO_SEND_MESSAGE_ERROR = "For sikkerhets skyld, denne demo-konto kan ikke sende meldinger til eksterne e-postadresser!" -DEMO_ACCOUNT_ERROR = "For security purposes, this account is not allowed for this action!" +DEMO_ACCOUNT_ERROR = "For sikkerhetsårsaker er ikke dette valget mulig for denne kontoen" ACCOUNT_ALREADY_EXISTS = "Kontoen finnes allerede" MAIL_SERVER_ERROR = "Det har oppstått en feil under tilgang til e-postserver" INVALID_INPUT_ARGUMENT = "Ugyldig input argument" @@ -707,4 +727,4 @@ NO_COOKIE_DESC = "Cookies-støtte er ikke tilgjengelig i nettleseren din . Vennligst aktiver Cookie-støtte i nettleserens innstillinger, og prøv på nytt ." BAD_BROWSER_TITLE = "Nettleseren din er utdatert." BAD_BROWSER_DESC = "Hvis du vil bruke alle funksjonene i programmet, -last ned og installerer en av disse nettleserne:" \ No newline at end of file +last ned og installerer en av disse nettleserne:" diff --git a/rainloop/v/0.0.0/langs/pl.ini b/rainloop/v/0.0.0/langs/pl.ini index 6b3af5a81..627410425 100644 --- a/rainloop/v/0.0.0/langs/pl.ini +++ b/rainloop/v/0.0.0/langs/pl.ini @@ -1,6 +1,6 @@ [LOGIN] -LABEL_EMAIL = "E-mail" +LABEL_EMAIL = "Adres e-mail" LABEL_LOGIN = "Login" LABEL_PASSWORD = "Hasło" LABEL_SIGN_ME = "Zapamiętaj mnie" @@ -10,34 +10,34 @@ BUTTON_SIGN_IN = "Zaloguj" TITLE_SIGN_IN_GOOGLE = "Zaloguj się przez Google" TITLE_SIGN_IN_FACEBOOK = "Zaloguj się przez Facebook" TITLE_SIGN_IN_TWITTER = "Zaloguj się przez Twitter" -LABEL_FORGOT_PASSWORD = "Zapomniane hasło" +LABEL_FORGOT_PASSWORD = "Zapomniałem hasło" LABEL_REGISTRATION = "Rejestracja" [TOP_TOOLBAR] BUTTON_ADD_ACCOUNT = "Dodaj konto" BUTTON_SETTINGS = "Ustawienia" BUTTON_HELP = "Pomoc" -BUTTON_LOGOUT = "Wyloguj się" +BUTTON_LOGOUT = "Wyloguj" [SEARCH] MAIN_INPUT_PLACEHOLDER = "Szukaj" TITLE_ADV = "Wyszukiwanie zaawansowane" -LABEL_ADV_FROM = "Od" -LABEL_ADV_TO = "Do" -LABEL_ADV_SUBJECT = "Temat" -LABEL_ADV_TEXT = "Tekst" -LABEL_ADV_HAS_ATTACHMENT = "Z załącznikiem" -LABEL_ADV_HAS_ATTACHMENTS = "Z załącznikami" +LABEL_ADV_FROM = "Od:" +LABEL_ADV_TO = "Do:" +LABEL_ADV_SUBJECT = "Temat:" +LABEL_ADV_TEXT = "Tekst:" +LABEL_ADV_HAS_ATTACHMENT = "Załącznik" +LABEL_ADV_HAS_ATTACHMENTS = "Ma załączniki" LABEL_ADV_FLAGGED = "Oznaczona" LABEL_ADV_UNSEEN = "Nieprzeczytana" -LABEL_ADV_DATE = "Data" -LABEL_ADV_DATE_ALL = "Wszystkie" -LABEL_ADV_DATE_3_DAYS = "Do 3 dni" -LABEL_ADV_DATE_7_DAYS = "Do 1 tygodnia" -LABEL_ADV_DATE_MONTH = "Do 1 miesiąca" -LABEL_ADV_DATE_3_MONTHS = "Do 3 miesięcy" -LABEL_ADV_DATE_6_MONTHS = "Do 6 miesięcy" -LABEL_ADV_DATE_YEAR = "Do 1 roku" +LABEL_ADV_DATE = "Data:" +LABEL_ADV_DATE_ALL = "wszystkie" +LABEL_ADV_DATE_3_DAYS = "do 3 dni" +LABEL_ADV_DATE_7_DAYS = "do tygodnia" +LABEL_ADV_DATE_MONTH = "do miesiąca" +LABEL_ADV_DATE_3_MONTHS = "do 3 miesięcy" +LABEL_ADV_DATE_6_MONTHS = "do 6 miesięcy" +LABEL_ADV_DATE_YEAR = "do roku" BUTTON_ADV_SEARCH = "Szukaj" [PREVIEW_POPUP] @@ -47,9 +47,9 @@ CLOSE = "Zamknij (Esc)" LOADING = "Ładowanie..." GALLERY_PREV = "Poprzedni (strzałka w lewo)" GALLERY_NEXT = "Następny (strzałka w prawo)" -GALLERY_COUNTER = "%curr% z %total%" -IMAGE_ERROR = "Nie można było załadować obrazu." -AJAX_ERROR = "Nie można było załadować zawartości." +GALLERY_COUNTER = "%curr% z: %total%" +IMAGE_ERROR = "Nie można załadować obrazu." +AJAX_ERROR = "Nie można załadować zawartości." [FOLDER_LIST] BUTTON_COMPOSE = "Utwórz" @@ -57,23 +57,23 @@ BUTTON_CONTACTS = "Kontakty" INBOX_NAME = "Odebrane" SENT_NAME = "Wysłane" DRAFTS_NAME = "Wersje robocze" -SPAM_NAME = "Spam" +SPAM_NAME = "Niechciane" TRASH_NAME = "Kosz" ARCHIVE_NAME = "Archiwum" [QUOTA] -TITLE = "Wykorzystane miejsce" +TITLE = "Wykorzystanie miejsca" [MESSAGE_LIST] BUTTON_RELOAD = "Odśwież" -BUTTON_MOVE_TO = "Przenieś do" +BUTTON_MOVE_TO = "Przenieś" BUTTON_DELETE = "Usuń" -BUTTON_ARCHIVE = "Archiwum" -BUTTON_SPAM = "Oznacz jako spam" -BUTTON_NOT_SPAM = "Oznacz jako wiarygodną" -BUTTON_EMPTY_FOLDER = "Wyczyść folder" +BUTTON_ARCHIVE = "Archiwizuj" +BUTTON_SPAM = "Oznacz jako niechciane" +BUTTON_NOT_SPAM = "Oznacz jako pożądane" +BUTTON_EMPTY_FOLDER = "Usuń zawartość folderu" BUTTON_MULTY_FORWARD = "Przekaż dalej" -BUTTON_DELETE_WITHOUT_MOVE = "Usuń na stałe" +BUTTON_DELETE_WITHOUT_MOVE = "Usuń (pernamentnie)" BUTTON_MORE = "Więcej" MENU_SET_SEEN = "Oznacz jako przeczytane" MENU_SET_ALL_SEEN = "Oznacz wszystkie jako przeczytane" @@ -82,7 +82,7 @@ MENU_SET_FLAG = "Oznacz jako ważne" MENU_UNSET_FLAG = "Oznacz jako nieważne" MENU_SELECT_ALL = "Wszystkie" MENU_SELECT_NONE = "Żadne" -MENU_SELECT_INVERT = "Odwróć" +MENU_SELECT_INVERT = "Odwróć zaznaczenie" MENU_SELECT_UNSEEN = "Nieprzeczytane" MENU_SELECT_SEEN = "Przeczytane" MENU_SELECT_FLAGGED = "Oznaczone jako ważne" @@ -90,14 +90,15 @@ MENU_SELECT_UNFLAGGED = "Oznaczone jako nieważne" EMPTY_LIST = "Pusta lista" EMPTY_SEARCH_LIST = "Brak wiadomości spełniających kryteria wyszukiwania" SEARCH_RESULT_FOR = "Wyniki wyszukiwania dla: \"%SEARCH%\"" -LIST_LOADING = "Ładowanie" +BACK_TO_MESSAGE_LIST = "Powrót do listy wiadomości" +LIST_LOADING = "Ładowanie..." EMPTY_SUBJECT_TEXT = "(Brak tematu)" PUT_MESSAGE_HERE = "Przeciągnij tutaj wiadomość, żeby zobaczyć ją na liście" TODAY_AT = "Dzisiaj: %TIME%" YESTERDAY_AT = "Wczoraj: %TIME%" SEARCH_PLACEHOLDER = "Szukaj" NEW_MESSAGE_NOTIFICATION = "Masz: %COUNT% now(-ą,-e,-ych) wiadomości!" -QUOTA_SIZE = "Wykorzystano: %SIZE% (%PROC%%) z przyznanych: %LIMIT%" +QUOTA_SIZE = "Wykorzystano: %SIZE% (%PROC%%) z: %LIMIT%" [MESSAGE] BUTTON_EDIT = "Edytuj" @@ -105,15 +106,15 @@ BUTTON_BACK = "Wstecz" BUTTON_CLOSE = "Zamknij" BUTTON_DELETE = "Usuń" BUTTON_ARCHIVE = "Archiwizuj" -BUTTON_SPAM = "Oznacz jako spam" -BUTTON_NOT_SPAM = "Oznacz jako wiarygodną" -BUTTON_MOVE_TO = "Przenieś do" +BUTTON_SPAM = "Oznacz jako niechcianą" +BUTTON_NOT_SPAM = "Oznacz jako pożądaną" +BUTTON_MOVE_TO = "Przenieś" BUTTON_MORE = "Więcej" BUTTON_REPLY = "Odpowiedz" BUTTON_REPLY_ALL = "Odpowiedz wszystkim" BUTTON_FORWARD = "Przekaż dalej" BUTTON_FORWARD_AS_ATTACHMENT = "Przekaż jako załącznik" -BUTTON_EDIT_AS_NEW = "Edytuj jako nową wiadomość" +BUTTON_EDIT_AS_NEW = "Zredaguj jako nową wiadomość" BUTTON_SHOW_IMAGES = "Wyświetl obrazy" BUTTON_NOTIFY_READ_RECEIPT = "Nadawca prosi o potwierdzenie odczytania tej wiadomości" BUTTON_IN_NEW_WINDOW = "Wyświetl w osobnym oknie" @@ -122,8 +123,8 @@ BUTTON_THREAD_PREV = "Poprzedni" BUTTON_THREAD_NEXT = "Następny" BUTTON_THREAD_MORE = "Więcej wiadomości" MENU_HEADERS = "Pokaż nagłówki wiadomości" -MENU_VIEW_ORIGINAL = "Pokaż oryginał" -MENU_DOWNLOAD_ORIGINAL = "Pobież jako plik - .eml" +MENU_VIEW_ORIGINAL = "Pokaż zródło" +MENU_DOWNLOAD_ORIGINAL = "Pobież jako plik eml" MENU_FILTER_SIMILAR = "Filtruj podobne wiadomości" MENU_PRINT = "Drukuj" EMPTY_SUBJECT_TEXT = "(Brak tematu)" @@ -133,29 +134,32 @@ LABEL_FROM = "Od" LABEL_FROM_SHORT = "Od" LABEL_TO = "Do" LABEL_TO_SHORT = "Do" -LABEL_CC = "Kopia do" -LABEL_BCC = "Ukryci odbiorcy" -LABEL_REPLY_TO = "Reply-To" +LABEL_CC = "Kopia" +LABEL_BCC = "Ukr. kopia" +LABEL_REPLY_TO = "Zwrot" PRINT_LABEL_FROM = "Od" PRINT_LABEL_TO = "Do" -PRINT_LABEL_CC = "Kopia do" -PRINT_LABEL_BCC = "Ukryci odbiorcy" -PRINT_LABEL_REPLY_TO = "Reply-To" +PRINT_LABEL_CC = "Kopia" +PRINT_LABEL_BCC = "Ukr. kopia" +PRINT_LABEL_REPLY_TO = "Zwrot" PRINT_LABEL_DATE = "Data" PRINT_LABEL_SUBJECT = "Temat" PRINT_LABEL_ATTACHMENTS = "Załączniki" -MESSAGE_LOADING = "Ładowanie..." -MESSAGE_VIEW_DESC = "Wybierz wiadomość z listy w celu jej wyświetlenia" +MESSAGE_LOADING = "Ładowanie wiadomości..." +MESSAGE_VIEW_DESC = "Wybierz wiadomość do wyświetlenia" PGP_PASSWORD_INPUT_PLACEHOLDER = "Hasło" -PGP_SIGNED_MESSAGE_DESC = "Wiadomość podpisana za pomocą OpenPGP (kliknij, aby zweryfikować)" -PGP_ENCRYPTED_MESSAGE_DESC = "Wiadomość zaszyfrowana za pomocą OpenPGP (kliknij, aby odszyfrować)" +PGP_SIGNED_MESSAGE_DESC = "Podpisana" +PGP_ENCRYPTED_MESSAGE_DESC = "Zaszyfrowana" +LINK_DOWNLOAD_AS_ZIP = "Pobierz jako plik zip" +LINK_SAVE_TO_OWNCLOUD = "Zapisz w ownCloud" +LINK_SAVE_TO_DROPBOX = "Zapisz w Dropbox-ie" [READ_RECEIPT] -SUBJECT = "Potwierdzenie odbioru (wyświetlenia) - %SUBJECT%" -BODY = "To jest potwierdzenie odbioru wiadomości wysłanej do: %READ-RECEIPT%. +SUBJECT = "Potwierdzenie wyświetlenia wiadomości o tytule: %SUBJECT%" +BODY = "Potwierdzenie wyświetlenia wiadomości wysłanej na adres: %READ-RECEIPT%. -Uwaga: Potwierdzenie odbioru wiadomości przez odbiorcę informuję tylko o tym, że wiadomość została wyświetlona na komputerze odbiorcy. -Nie ma żadnej gwarancji, że odbiorca odczytał wiadomość i zapoznał się z jej treścią." +Uwaga: Otrzymanie tego potwierdzenia jest dowodem na to, że wiadomość została wyświetlona na komputerze odbiorcy. +Nie ma jednak żadnej gwarancji, że odbiorca faktycznie zapoznał się z jej treścią." [SUGGESTIONS] SEARCHING_DESC = "Wyszukiwanie..." @@ -170,20 +174,20 @@ BUTTON_IMPORT = "Importuj (csv, vcf, vCard)" BUTTON_EXPORT_VCARD = "Eksportuj (vcf, vCard)" BUTTON_EXPORT_CSV = "Eksportuj (csv)" ERROR_IMPORT_FILE = "Błąd importu (nieprawidłowy format pliku)" -LIST_LOADING = "Ładowanie" +LIST_LOADING = "Ładowanie..." EMPTY_LIST = "Brak kontaktów" EMPTY_SEARCH = "Nie znaleziono żadnych kontaktów" -CLEAR_SEARCH = "Wyczyść wyszukiwanie" -CONTACT_VIEW_DESC = "Wybierz kontakt z listy w celu jego wyświetlenia" -LABEL_DISPLAY_NAME = "Wyświetlana nazwa" -LABEL_EMAIL = "E-mail" -LABEL_PHONE = "Telefon" -LABEL_WEB = "Strona WWW" -LABEL_BIRTHDAY = "Urodziny" +CLEAR_SEARCH = "Wyczyść wyniki" +CONTACT_VIEW_DESC = "Wybierz kontakt do wyświetlenia" +LABEL_DISPLAY_NAME = "Nazwa:" +LABEL_EMAIL = "Adres e-mail:" +LABEL_PHONE = "Telefon:" +LABEL_WEB = "Strona WWW:" +LABEL_BIRTHDAY = "Urodziny:" LINK_ADD_EMAIL = "Dodaj adres e-mail" LINK_ADD_PHONE = "Dodaj nr telefonu" LINK_BIRTHDAY = "Urodziny" -PLACEHOLDER_ENTER_DISPLAY_NAME = "Nazwa wyświetlana" +PLACEHOLDER_ENTER_DISPLAY_NAME = "Nazwa" PLACEHOLDER_ENTER_LAST_NAME = "Nazwisko" PLACEHOLDER_ENTER_FIRST_NAME = "Imię" PLACEHOLDER_ENTER_NICK_NAME = "Pseudonim" @@ -192,9 +196,9 @@ LABEL_SHARE = "Udostępnij kontakt" ADD_MENU_LABEL = "Dodaj" ADD_MENU_NICKNAME = "Pseudonim" ADD_MENU_NOTES = "Notatki" -ADD_MENU_EMAIL = "E-mail" +ADD_MENU_EMAIL = "Adres e-mail" ADD_MENU_PHONE = "Telefon" -ADD_MENU_URL = "Adres URL" +ADD_MENU_URL = "Adres www" ADD_MENU_ADDRESS = "Adres" ADD_MENU_BIRTHDAY = "Urodziny" ADD_MENU_TAGS = "Tagi" @@ -205,9 +209,9 @@ BUTTON_SYNC = "Synchronizacja (CardDAV)" [COMPOSE] TITLE_FROM = "Od" TITLE_TO = "Do" -TITLE_CC = "DW" -TITLE_BCC = "UDW" -TITLE_REPLY_TO = "Odpowiedź do" +TITLE_CC = "Kopia" +TITLE_BCC = "Ukr. kopia" +TITLE_REPLY_TO = "Zwrot" TITLE_SUBJECT = "Temat" LINK_SHOW_INPUTS = "Pokaż wszystkie pola" BUTTON_SEND = "Wyślij" @@ -218,29 +222,29 @@ BUTTON_MINIMIZE = "Minimalizuj" SAVED_TIME = "Zapisane: %TIME%" SAVED_ERROR_ON_SEND = "Wiadomość została wysłana, ale nie została zapisana w folderze: Wysłane" DISCARD_UNSAVED_DATA = "Odrzucić niezapisane dane?" -ATTACH_FILES = "Dołącz pliki" +ATTACH_FILES = "Dodaj załącznik" ATTACH_DROP_FILES_DESC = "Przeciągnij pliki tutaj" ATTACH_ITEM_CANCEL = "Anuluj" DROPBOX = "Dropbox" GOOGLE_DRIVE = "Dysk Google" -REPLY_MESSAGE_TITLE = "%DATETIME% - %EMAIL%:" +REPLY_MESSAGE_TITLE = "%DATETIME% - %EMAIL%" FORWARD_MESSAGE_TOP_TITLE = "-------- Przekierowana wiadomość -------" -FORWARD_MESSAGE_TOP_FROM = "Od" -FORWARD_MESSAGE_TOP_TO = "Do" -FORWARD_MESSAGE_TOP_CC = "DW" -FORWARD_MESSAGE_TOP_SENT = "Wysłany" -FORWARD_MESSAGE_TOP_SUBJECT = "Temat" +FORWARD_MESSAGE_TOP_FROM = "Od:" +FORWARD_MESSAGE_TOP_TO = "Do:" +FORWARD_MESSAGE_TOP_CC = "Kopia do:" +FORWARD_MESSAGE_TOP_SENT = "Wysłany:" +FORWARD_MESSAGE_TOP_SUBJECT = "Temat:" EMPTY_TO_ERROR_DESC = "Wprowadź co najmniej jednego odbiorcę" -NO_ATTACHMENTS_HERE_DESC = "Brak załączników." -ATTACHMENTS_ERROR_DESC = "Ostrzeżenie! Nie wszystkie załaczniki zostały przesłane." +NO_ATTACHMENTS_HERE_DESC = "Brak załączników" +ATTACHMENTS_ERROR_DESC = "Ostrzeżenie! Nie wszystkie załaczniki zostały przesłane" ATTACHMENTS_UPLOAD_ERROR_DESC = "Nie przesłano jeszcze wszystkich załączników" -BUTTON_REQUEST_READ_RECEIPT = "Żądaj potwierdzenia odbioru" +BUTTON_REQUEST_READ_RECEIPT = "Potwierdzenie wyświetlenia wiadomości" BUTTON_MARK_AS_IMPORTANT = "Oznacz jako ważną" -BUTTON_OPEN_PGP = "OpenPGP (Tylko zwykły tekst)" -BUTTON_REQUEST_DSN = "Żądaj potwierdzenia dostarczenia" +BUTTON_OPEN_PGP = "OpenPGP (tylko wiadomości tekstowe)" +BUTTON_REQUEST_DSN = "Potwierdzenie dostarczenia wiadomości" [POPUPS_WELCOME_PAGE] -BUTTON_CLOSE = "Close" +BUTTON_CLOSE = "Zamknij" [POPUPS_ASK] BUTTON_YES = "Tak" @@ -254,7 +258,7 @@ TITLE_LANGUAGES = "Wybierz język" [POPUPS_ADD_ACCOUNT] TITLE_ADD_ACCOUNT = "Dodawanie konta" BUTTON_ADD_ACCOUNT = "Dodaj" -TITLE_UPDATE_ACCOUNT = "Zaktualizować konto?" +TITLE_UPDATE_ACCOUNT = "Aktualizacja konta" BUTTON_UPDATE_ACCOUNT = "Aktualizuj" [POPUPS_IDENTITY] @@ -262,32 +266,32 @@ TITLE_ADD_IDENTITY = "Dodawanie tożsamości" TITLE_UPDATE_IDENTITY = "Aktualizacja tożsamości" BUTTON_ADD_IDENTITY = "Dodaj" BUTTON_UPDATE_IDENTITY = "Aktualizuj" -LABEL_EMAIL = "E-mail" -LABEL_NAME = "Nazwa" -LABEL_REPLY_TO = "Odpowiedz do" -LABEL_SIGNATURE = "Podpis" -LABEL_CC = "DW" -LABEL_BCC = "Ukryci odbiorcy" -LABEL_SIGNATURE_INSERT_BEFORE = "Umieść podpis przed cytowanym tekstem w odpowiedziach" +LABEL_EMAIL = "Adres e-mail:" +LABEL_NAME = "Nazwa:" +LABEL_REPLY_TO = "Zwrot" +LABEL_SIGNATURE = "Podpis:" +LABEL_CC = "Kopia" +LABEL_BCC = "Ukr. kopia" +LABEL_SIGNATURE_INSERT_BEFORE = "Umieść podpis przed cytowanym tekstem" [POPUPS_CREATE_FOLDER] TITLE_CREATE_FOLDER = "Tworzenie folderu" SELECT_NO_PARENT = "" -LABEL_NAME = "Nazwa folderu" -LABEL_PARENT = "Folder nadrzędny" +LABEL_NAME = "Nazwa folderu:" +LABEL_PARENT = "Folder nadrzędny:" BUTTON_CREATE = "Utwórz" BUTTON_CANCEL = "Anuluj" BUTTON_CLOSE = "Zamknij" -TITLE_CREATING_PROCESS = "Trwa dodawanie folderu" +TITLE_CREATING_PROCESS = "Tworzenie folderu" [POPUPS_CLEAR_FOLDER] -TITLE_CLEAR_FOLDER = "Czy chcesz usunąć wszystkie wiadomości z folderu?" -BUTTON_CLEAR = "Usuń" +TITLE_CLEAR_FOLDER = "Usuwanie wszystkich wiadomości z folderu" +BUTTON_CLEAR = "Usuń wszystkie" BUTTON_CANCEL = "Anuluj" BUTTON_CLOSE = "Zamknij" DANGER_DESC_WARNING = "Ostrzeżenie!" DANGER_DESC_HTML_1 = "Wszystkie wiadomości w folderze: %FOLDER%, zostaną bezpowrotnie usunięte!" -DANGER_DESC_HTML_2 = "Po rozpoczęciu, proces nie może zostać przerwany lub anulowany." +DANGER_DESC_HTML_2 = "Po rozpoczęciu, nie można przerwać lub anulować zadania." TITLE_CLEARING_PROCESS = "Trwa usuwanie wszystkich wiadomości z folderu..." [POPUPS_IMPORT_OPEN_PGP_KEY] @@ -301,110 +305,119 @@ BUTTON_CLOSE = "Zamknij" [POPUPS_GENERATE_OPEN_PGP_KEYS] TITLE_GENERATE_OPEN_PGP_KEYS = "Generowanie klucza OpenPGP" -LABEL_EMAIL = "E-mail" -LABEL_NAME = "Imię i nazwisko" -LABEL_PASSWORD = "Hasło" -LABEL_KEY_BIT_LENGTH = "Długość klucza" +LABEL_EMAIL = "Adres e-mail:" +LABEL_NAME = "Imię i nazwisko:" +LABEL_PASSWORD = "Hasło:" +LABEL_KEY_BIT_LENGTH = "Długość klucza:" BUTTON_GENERATE_OPEN_PGP_KEYS = "Generuj" [POPUPS_COMPOSE_OPEN_PGP] -TITLE_COMPOSE_OPEN_PGP = "Podpisz/Zaszyfruj" +TITLE_COMPOSE_OPEN_PGP = "Podpisywanie/szyfrowanie" LABEL_SIGN = "Podpisz" -LABEL_ENCRYPT = "Zaszyfruj" -LABEL_PASSWORD = "Hasło" +LABEL_ENCRYPT = "Szyfruj" +LABEL_PASSWORD = "Hasło:" BUTTON_SIGN = "Podpisz" -BUTTON_ENCRYPT = "Zaszyfruj" -BUTTON_SIGN_AND_ENCRYPT = "Podpisz i zaszyfruj" +BUTTON_ENCRYPT = "Szyfruj" +BUTTON_SIGN_AND_ENCRYPT = "Podpisz i szyfruj" + +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" [POPUPS_TWO_FACTOR_TEST] -TITLE_TEST_CODE = "Test weryfikacji 2-stopniowej" +TITLE_TEST_CODE = "Test autoryzacji dwuskładnikowej" LABEL_CODE = "Kod" BUTTON_TEST = "Testuj" [POPUPS_FILTER] -TITLE_CREATE_FILTER = "Utwórz filtr?" -TITLE_EDIT_FILTER = "Zaktualizuj filtr?" +TITLE_CREATE_FILTER = "Tworzenie filtra" +TITLE_EDIT_FILTER = "Aktualizacja filtra" FILTER_NAME = "Nazwa" LEGEND_CONDITIONS = "Warunki" -LEGEND_ACTIONS = "Akcje" +LEGEND_ACTIONS = "Działania" BUTTON_DONE = "Gotowe" BUTTON_ADD_CONDITION = "Dodaj warunek" SELECT_ACTION_NONE = "Brak" -SELECT_ACTION_MOVE_TO = "Przenieś do" -SELECT_ACTION_FORWARD_TO = "Przekaż do" +SELECT_ACTION_MOVE_TO = "Przenieś" +SELECT_ACTION_FORWARD_TO = "Prześlij dalej" SELECT_ACTION_REJECT = "Odrzuć" -SELECT_ACTION_VACATION_MESSAGE = "Wiadomość o nieobecności" +SELECT_ACTION_VACATION_MESSAGE = "Wiadomość urlopowa" SELECT_ACTION_DISCARD = "Usuń" -SELECT_FIELD_FROM = "Od" -SELECT_FIELD_RECIPIENTS = "Odbiorcy (Do lub DW)" -SELECT_FIELD_SUBJECT = "Temat" +SELECT_FIELD_FROM = "Pole 'Od'" +SELECT_FIELD_RECIPIENTS = "Pole 'Kopia' lub 'Ukr. kopia'" +SELECT_FIELD_SUBJECT = "Pole 'Temat'" SELECT_FIELD_HEADER = "Nagłówek" SELECT_FIELD_SIZE = "Rozmiar" -SELECT_TYPE_CONTAINS = "Zawiera" -SELECT_TYPE_NOT_CONTAINS = "Nie zawiera" -SELECT_TYPE_MATCHES = "Pasuje (wspierane * oraz ?)" -SELECT_TYPE_NOT_MATCHES = "Nie pasuje (wspierane * oraz ?)" -SELECT_TYPE_REGEXP = "Regexp" -SELECT_TYPE_NOT_REGEXP = "Nie Regexp" -SELECT_TYPE_EQUAL_TO = "To" -SELECT_TYPE_NOT_EQUAL_TO = "To nie" +SELECT_TYPE_CONTAINS = "zawiera" +SELECT_TYPE_NOT_CONTAINS = "nie zawiera" +SELECT_TYPE_MATCHES = "zawiera (*,?)" +SELECT_TYPE_NOT_MATCHES = "nie zawiera (*,?)" +SELECT_TYPE_REGEXP = "Wyrażenie regularne:" +SELECT_TYPE_NOT_REGEXP = "Niepoprawne wyrażenie regularne:" +SELECT_TYPE_EQUAL_TO = "Zawiera:" +SELECT_TYPE_NOT_EQUAL_TO = "Nie zawiera:" +SELECT_TYPE_OVER = "powyżej" +SELECT_TYPE_UNDER = "poniżej" SELECT_MATCH_ANY = "Spełnia dowolny z warunków" SELECT_MATCH_ALL = "Spełnia wszystkie warunki" MARK_AS_READ_LABEL = "Oznacz jako przeczytane" -REPLY_INTERVAL_LABEL = "Odpowiedź po (dni)" +REPLY_INTERVAL_LABEL = "Liczba dni, po których wysłać odp." KEEP_LABEL = "Zachowaj" -STOP_LABEL = "Nie zatrzymuj wykonywania reguł" -EMAIL_LABEL = "Email" +STOP_LABEL = "Nie zatrzymuj przetwarzania reguł" +EMAIL_LABEL = "Adres e-mail" VACATION_SUBJECT_LABEL = "Temat (opcjonalnie)" VACATION_MESSAGE_LABEL = "Wiadomość" -REJECT_MESSAGE_LABEL = "Odrzuć wiadomość" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" +REJECT_MESSAGE_LABEL = "Powód odrzucenia" ALL_INCOMING_MESSAGES_DESC = "Wszystkie przychodzące wiadomości" [POPUPS_SYSTEM_FOLDERS] -TITLE_SYSTEM_FOLDERS = "Wybierz foldery systemowe" -SELECT_CHOOSE_ONE = "Wybierz" -SELECT_UNUSE_NAME = "Nie używaj" -LABEL_SENT = "Wysłane" -LABEL_DRAFTS = "Wersje robocze" -LABEL_SPAM = "Spam" -LABEL_TRASH = "Kosz" -LABEL_ARCHIVE = "Archiwum" +TITLE_SYSTEM_FOLDERS = "Wybieranie folderów systemowych" +SELECT_CHOOSE_ONE = "wybierz" +SELECT_UNUSE_NAME = "nie używaj" +LABEL_SENT = "Wysłane:" +LABEL_DRAFTS = "Wersje robocze:" +LABEL_SPAM = "Niechciane:" +LABEL_TRASH = "Kosz:" +LABEL_ARCHIVE = "Archiwum:" BUTTON_CANCEL = "Anuluj" BUTTON_CLOSE = "Zamknij" -NOTIFICATION_SENT = "Nie został wybrany folder \"Wysłane\", do którego przenoszone są wiadomości po wysłaniu. -Jeżeli wysłane wiadomości nie mają być przechowywane, proszę o zaznaczenie opcji: \"Nie używaj\"." -NOTIFICATION_DRAFTS = "Nie został wybrany folder \"Wersje robocze\", do którego są zapisywane wiadomości w trakcie ich tworzenia." -NOTIFICATION_SPAM = "Nie został wybrany folder \"Spam\", do którego przenoszone są wiadomości oznaczone jako SPAM. -Jeżeli wiadomości oznaczone jako spam mają być usuwane na stałe, proszę o zaznaczenie opcji: \"Nie używaj\"." -NOTIFICATION_TRASH = "Nie został wybrany folder \"Kosz\", do którego przenoszone są wszystkie usunięte wiadomości. -Jeżeli wiadomości usunięte mają być usuwane na stałe, proszę o zaznaczenie opcji: \"Nie używaj\"." -NOTIFICATION_ARCHIVE = "Nie został wybrany folder \"Archiwum\", zostanie użyty systemowy folder archiwizowanych wiadomości." +NOTIFICATION_SENT = "Nie wybrano folderu: \"Wysłane\", do którego przenoszone są wysłane wiadomości. +Jeżeli wysyłane wiadomości nie mają być przechowywane, proszę zaznaczyć opcję: \"Nie używaj\"." +NOTIFICATION_DRAFTS = "Nie wybrano folderu: \"Wersje robocze\", do którego są zapisywane wiadomości w trakcie ich tworzenia." +NOTIFICATION_SPAM = "Nie wybrano folderu: \"Niechciane\", do którego przenoszone są niepożadane wiadomości. +Jeżeli niechciane wiadomości mają być usuwane na stałe, proszę o zaznaczenie opcji: \"Nie używaj\"." +NOTIFICATION_TRASH = "Nie wybrano folderu: \"Kosz\", do którego przenoszone są wszystkie usunięte wiadomości. +Jeżeli wiadomości mają być usuwane na stałe, proszę o zaznaczenie opcji: \"Nie używaj\"." +NOTIFICATION_ARCHIVE = "Nie został wybrany folder \"Archiwum\", zostanie użyty systemowy folder archiwizacji wiadomości." [POPUPS_TWO_FACTOR_CFG] -LEGEND_TWO_FACTOR_AUTH = "Weryfikacja 2-stopniowa" -LABEL_ENABLE_TWO_FACTOR = "Włącz 2-stopniową weryfikację" -LABEL_TWO_FACTOR_USER = "Użytkownik" -LABEL_TWO_FACTOR_STATUS = "Status" -LABEL_TWO_FACTOR_SECRET = "Tajna fraza" -LABEL_TWO_FACTOR_BACKUP_CODES = "Kody zapasowe" +LEGEND_TWO_FACTOR_AUTH = "Dwuskładnikowa autoryzacja" +LABEL_ENABLE_TWO_FACTOR = "Włącz dwuskładnikową autoryzację" +LABEL_TWO_FACTOR_USER = "Użytkownik:" +LABEL_TWO_FACTOR_STATUS = "Status:" +LABEL_TWO_FACTOR_SECRET = "Tajna fraza:" +LABEL_TWO_FACTOR_BACKUP_CODES = "Kody zapasowe:" BUTTON_CREATE = "Utwórz nową frazę" -BUTTON_ACTIVATE = "Activate" +BUTTON_ACTIVATE = "Aktywuj" BUTTON_CLEAR = "Wyczyść" -BUTTON_LOGOUT = "Logout" -BUTTON_DONE = "Done" +BUTTON_LOGOUT = "Wyloguj" +BUTTON_DONE = "Zamknij" BUTTON_TEST = "Testuj" -LINK_TEST = "test" +LINK_TEST = "Test" BUTTON_SHOW_SECRET = "Pokaż frazę" BUTTON_HIDE_SECRET = "Ukryj frazę" -TWO_FACTOR_REQUIRE_DESC = "Your account requires 2-Step verification configuration." -TWO_FACTOR_SECRET_CONFIGURED_DESC = "Skonfigurowane" -TWO_FACTOR_SECRET_NOT_CONFIGURED_DESC = "Nie skonfigurowane" -TWO_FACTOR_SECRET_DESC = "Zaimportuj te informacje do swojego klienta usługi Google Authenticator (lub innego klienta TOTP), używając poniższego kodu QR lub wpisując kod ręcznie." -TWO_FACTOR_BACKUP_CODES_DESC = "Jeżeli nie możesz otrzymać kodu poprzez apikację Google Authenticator, możesz użyć kodów zapasowych. Po zużyciu kodów, opcja ta będzie nieaktywna." +TWO_FACTOR_REQUIRE_DESC = "Twoje konto wymaga skonfigurowania dwuskładnikowej autoryzacji ." +TWO_FACTOR_SECRET_CONFIGURED_DESC = "Skonfigurowana" +TWO_FACTOR_SECRET_NOT_CONFIGURED_DESC = "Nie skonfigurowana" +TWO_FACTOR_SECRET_DESC = "Użyj tych informacji w usłudze Google Authenticator (lub innym kliencie TOTP), używając poniższego kodu QR lub wpisując kod ręcznie." +TWO_FACTOR_BACKUP_CODES_DESC = "Jeżeli nie możesz otrzymać kodu poprzez usługę Google Authenticator, możesz użyć kodów zapasowych. Po zużyciu kodów, opcja ta będzie nieaktywna." TWO_FACTOR_SECRET_TEST_BEFORE_DESC = "Nie możesz zmienić tego ustawienia przed jego przetestowaniem." [TITLES] -LOADING = "Ładowanie" +LOADING = "Ładowanie..." LOGIN = "Login" MAILBOX = "Skrzynka Pocztowa" SETTINGS = "Ustawienia" @@ -436,7 +449,7 @@ LABEL_FILTERS_NAME = "Filtry" LABEL_TEMPLATES_NAME = "Szablony" LABEL_SECURITY_NAME = "Bezpieczeństwo" LABEL_SOCIAL_NAME = "Sieci społecznościowe" -LABEL_THEMES_NAME = "Skórki" +LABEL_THEMES_NAME = "Motywy" LABEL_CHANGE_PASSWORD_NAME = "Hasło" LABEL_OPEN_PGP_NAME = "OpenPGP" BUTTON_BACK = "Wstecz" @@ -447,55 +460,56 @@ BUTTON_SAVE = "Zapisz" BUTTON_ADD_FILTER = "Dodaj filtr" BUTTON_DELETE = "Usuń" BUTTON_RAW_SCRIPT = "Utwórz własny skrypt użytkownika" -SUBNAME_NONE = "None" +SUBNAME_NONE = "Brak" SUBNAME_MOVE_TO = "Przenieś do \"%FOLDER%\"" SUBNAME_FORWARD_TO = "Przekaż do \"%EMAIL%\"" SUBNAME_REJECT = "Odrzuć" -SUBNAME_VACATION_MESSAGE = "Wiadomość o nieobecności" +SUBNAME_VACATION_MESSAGE = "Wiadomość urlopowa" SUBNAME_DISCARD = "Usuń" CAPABILITY_LABEL = "Możliwości" LOADING_PROCESS = "Aktualizowanie listy filtrów" DELETING_ASK = "Czy jesteś pewny(a)?" -CHACHES_NEED_TO_BE_SAVED_DESC = "Zmiany muszą zostać zapisane na serwerze." +CHACHES_NEED_TO_BE_SAVED_DESC = "Zmiany te muszą zostać zapisane na serwerze." [SETTINGS_IDENTITY] LEGEND_IDENTITY = "Tożsamość" LABEL_DISPLAY_NAME = "Imię i nazwisko" -LABEL_REPLY_TO = "Zwrotny adres e-mail" +LABEL_REPLY_TO = "Zwrot do" LABEL_SIGNATURE = "Podpis" -LABEL_ADD_SIGNATURE_TO_ALL = "Dadawaj podpis do wszystkich wysyłanych wiadomości" +LABEL_ADD_SIGNATURE_TO_ALL = "Dadawaj podpis do wszystkich wiadomości" [SETTINGS_SECURITY] LEGEND_SECURITY = "Bezpieczeństwo" -LABEL_CONFIGURATE_TWO_FACTOR = "Configurate 2-Step verification" -LABEL_AUTOLOGOUT = "Automatyczne wylogowanie" +LABEL_CONFIGURATE_TWO_FACTOR = "Konfiguracja dwuskładnikowej autoryzacji" +LABEL_AUTOLOGOUT = "Auto. wylogowanie:" AUTOLOGIN_NEVER_OPTION_NAME = "Nidgy" AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minut" [SETTINGS_GENERAL] LEGEND_GENERAL = "Ogólne" -LABEL_LANGUAGE = "Język" -LABEL_LAYOUT = "Układ" -LABEL_LAYOUT_NO_SPLIT = "Bez podziału" -LABEL_LAYOUT_VERTICAL_SPLIT = "Podział w pionie" -LABEL_LAYOUT_HORIZONTAL_SPLIT = "Poział w poziomie" -LABEL_EDITOR = "Format wiadomości" +LABEL_LANGUAGE = "Język:" +LABEL_IDENTITY = "Tożsamość:" +LABEL_LAYOUT = "Układ:" +LABEL_LAYOUT_NO_SPLIT = "bez podziału" +LABEL_LAYOUT_VERTICAL_SPLIT = "podział w pionie" +LABEL_LAYOUT_HORIZONTAL_SPLIT = "podział w poziomie" +LABEL_EDITOR = "Format wiadomości:" LABEL_EDITOR_HTML = "HTML" -LABEL_EDITOR_PLAIN = "Zwykły tekst" +LABEL_EDITOR_PLAIN = "zwykły tekst" LABEL_EDITOR_HTML_FORCED = "HTML (wymuszony)" -LABEL_EDITOR_PLAIN_FORCED = "Zwykły tekst (wymuszony)" +LABEL_EDITOR_PLAIN_FORCED = "zwykły tekst (wymuszony)" LABEL_ANIMATION = "Animacja interfejsu" -LABEL_ANIMATION_FULL = "Pełna" -LABEL_ANIMATION_NORMAL = "Zwykła" -LABEL_ANIMATION_NONE = "Brak" +LABEL_ANIMATION_FULL = "pełna" +LABEL_ANIMATION_NORMAL = "zwykła" +LABEL_ANIMATION_NONE = "brak" LABEL_VIEW_OPTIONS = "Opcje wyświetlania" LABEL_USE_PREVIEW_PANE = "Wyświetl okno podglądu" LABEL_USE_CHECKBOXES_IN_LIST = "Wyświetl pola zaznaczenia w listach" LABEL_USE_THREADS = "Używaj wątków" -LABEL_REPLY_SAME_FOLDER = "Umieść odpowiedź w folderze wiadomości, na którą udzielana jest odpowiedź" +LABEL_REPLY_SAME_FOLDER = "Umieść odpowiedzi w folderach, z których pochodzą wiadomości" LABEL_SHOW_IMAGES = "Zawsze wyświetlaj obrazy w wiadomościach" -LABEL_SHOW_ANIMATION = "Odtwarzaj animacje" -LABEL_MESSAGE_PER_PAGE = "Wiadomości na stronie" +LABEL_SHOW_ANIMATION = "Użyj animacji" +LABEL_MESSAGE_PER_PAGE = "Wiad. na stronie:" LABEL_NOTIFICATIONS = "Powiadomienia" LABEL_SOUND_NOTIFICATION = "Powiadomienia dźwiękowe" LABEL_CHROME_NOTIFICATION_DESC = "Wyświetlaj powiadomienia o nowych wiadomościach" @@ -506,14 +520,14 @@ LEGEND_CONTACTS = "Kontakty" LABEL_CONTACTS_AUTOSAVE = "Automatycznie dodaj nieznanych nadawców i odbiorców do książki adresowej" LEGEND_CONTACTS_SYNC = "Zdalna synchronizacja (CardDAV)" LABEL_CONTACTS_SYNC_ENABLE = "Włącz zdalną synchronizację" -LABEL_CONTACTS_SYNC_SERVER = "Serwer" -LABEL_CONTACTS_SYNC_AB_URL = "Adres URL" -LABEL_CONTACTS_SYNC_USER = "Użytkownik" -LABEL_CONTACTS_SYNC_PASSWORD = "Hasło" +LABEL_CONTACTS_SYNC_SERVER = "Serwer:" +LABEL_CONTACTS_SYNC_AB_URL = "Adres URL:" +LABEL_CONTACTS_SYNC_USER = "Użytkownik:" +LABEL_CONTACTS_SYNC_PASSWORD = "Hasło:" [SETTINGS_THEMES] -LEGEND_THEMES = "Skórki" -LEGEND_THEMES_CUSTOM = "Konfiguracja indywidualnego wyglądu" +LEGEND_THEMES = "Motyw" +LEGEND_THEMES_CUSTOM = "Własny motyw" LABEL_CUSTOM_TYPE = "Typ" LABEL_CUSTOM_TYPE_LIGHT = "Jasny" LABEL_CUSTOM_TYPE_DARK = "Ciemny" @@ -527,15 +541,15 @@ ERROR_UNKNOWN = "Wystąpił nieznany błąd w trakcie przesyłania" LEGEND_GOOGLE = "Konto Google" BUTTON_GOOGLE_CONNECT = "Połącz z Google" BUTTON_GOOGLE_DISCONNECT = "Odłącz" -MAIN_GOOGLE_DESC = "Po zezwoleniu na logowanie przez Google, możesz zalogować się na to konto używając przycisku: \"Google\" w panelu logowania." +MAIN_GOOGLE_DESC = "Po zezwoleniu na logowanie przez: Google, możesz zalogować się na to konto używając przycisku: \"Google\" w panelu logowania." LEGEND_FACEBOOK = "Facebook" BUTTON_FACEBOOK_CONNECT = "Połącz z Facebook" BUTTON_FACEBOOK_DISCONNECT = "Odłącz" -MAIN_FACEBOOK_DESC = "Po zezwoleniu na logowanie przez Facebook, możesz zalogować się na to konto używając przycisku: \"Facebook\" w panelu logowania." +MAIN_FACEBOOK_DESC = "Po zezwoleniu na logowanie przez: Facebook, możesz zalogować się na to konto używając przycisku: \"Facebook\" w panelu logowania." LEGEND_TWITTER = "Twitter" BUTTON_TWITTER_CONNECT = "Połącz z Twitter" BUTTON_TWITTER_DISCONNECT = "Odłącz" -MAIN_TWITTER_DESC = "Po zezwoleniu na logowanie przez Twitter, możesz zalogować się na to konto używając przycisku: \"Twitter\" w panelu logowania." +MAIN_TWITTER_DESC = "Po zezwoleniu na logowanie przez: Twitter, możesz zalogować się na to konto używając przycisku: \"Twitter\" w panelu logowania." [SETTINGS_FOLDERS] LEGEND_FOLDERS = "Lista Folderów" @@ -544,16 +558,19 @@ BUTTON_SYSTEM = "Wybierz foldery systemowe" BUTTON_DELETE = "Usuń" BUTTON_SUBSCRIBE = "Subskrybuj" BUTTON_UNSUBSCRIBE = "Zrezygnuj z subskrypcji" -LOADING_PROCESS = "Trwa aktualizacja listy folderów" +LOADING_PROCESS = "Aktualizacja listy folderów" CREATING_PROCESS = "Tworzenie folderu" DELETING_PROCESS = "Usuwanie folderu" RENAMING_PROCESS = "Zmiana nazwy folderu" DELETING_ASK = "Czy na pewno usunąć?" TO_MANY_FOLDERS_DESC_1 = "Masz za dużo folderów!" TO_MANY_FOLDERS_DESC_2 = "Pokazaliśmy tylko część z nich aby uniknąć problemów z wydajnością." +HELP_DELETE_FOLDER = "Usuń folder" +HELP_SHOW_HIDE_FOLDER = "Pokaż/ukryj folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Sprawdzaj/nie sprawdzaj nowych wiadomości" [SETTINGS_ACCOUNTS] -LEGEND_ACCOUNTS = "Lista kont" +LEGEND_ACCOUNTS = "Konta" LEGEND_IDENTITIES = "Tożsamości" LEGEND_ACCOUNTS_AND_IDENTITIES = "Konta i tożsamości" BUTTON_ADD_ACCOUNT = "Dodaj konto" @@ -567,9 +584,9 @@ DEFAULT_IDENTITY_LABEL = "domyślna" LEGEND_IDENTITY = "Tożsamość" LEGEND_IDENTITIES = "Dodatkowe tożsamości" LABEL_DEFAULT = "Domyślna" -LABEL_DISPLAY_NAME = "Nazwa" -LABEL_REPLY_TO = "Odpowiedź do" -LABEL_SIGNATURE = "Podpis" +LABEL_DISPLAY_NAME = "Nazwa:" +LABEL_REPLY_TO = "Odpowiedź do:" +LABEL_SIGNATURE = "Podpis:" LABEL_ADD_SIGNATURE_TO_ALL = "Dodaj podpis do wszystkich wysyłanych wiadomości" BUTTON_ADD_IDENTITY = "Dodaj tożsamość" BUTTON_DELETE = "Usuń" @@ -578,9 +595,9 @@ DELETING_ASK = "Czy na pewno chcesz usunąć?" [SETTINGS_CHANGE_PASSWORD] LEGEND_CHANGE_PASSWORD = "Zmiana hasła" -LABEL_CURRENT_PASSWORD = "Aktualne hasło" -LABEL_NEW_PASSWORD = "Nowe hasło" -LABEL_REPEAT_PASSWORD = "Powtórz nowe hasło" +LABEL_CURRENT_PASSWORD = "Aktualne hasło:" +LABEL_NEW_PASSWORD = "Nowe hasło:" +LABEL_REPEAT_PASSWORD = "Powtórz nowe hasło:" BUTTON_UPDATE_PASSWORD = "Zmień hasło na nowe" ERROR_PASSWORD_MISMATCH = "Wpisane hasła nie pasują do siebie, proszę spróbować ponownie" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generuj klucz OpenPGP" TITLE_PRIVATE = "Prywatny" TITLE_PUBLIC = "Publiczny" DELETING_ASK = "Czy na pewno chcesz usunąć?" +GENERATE_ONLY_HTTPS = "Tylko HTTPS" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Skróty klawiaturowe" @@ -607,6 +625,7 @@ LABEL_HELP = "Pomoc" LABEL_CHECK_ALL = "Sprawdź wszystkie wiadomości" LABEL_ARCHIVE = "Archiwum" LABEL_DELETE = "Usuń" +LABEL_OPEN_THREAD = "Otwórz wybrany wątek" LABEL_MOVE = "Przenieś" LABEL_READ = "Oznacz zaznaczone wiadomości, jako przeczytane" LABEL_UNREAD = "Oznacz zaznaczone wiadomości, jako nieprzeczytane" @@ -632,13 +651,14 @@ LABEL_SEND_MESSAGE = "Wyślij wiadomość" LABEL_CLOSE_COMPOSE = "Zamknij okno tworzenia wiadomości" [PGP_NOTIFICATIONS] -NO_PUBLIC_KEYS_FOUND = "Nie znaleziono kluczy publicznych" -NO_PUBLIC_KEYS_FOUND_FOR = "Nie znaleziono kluczy publicznych dla adresu: \"%EMAIL%\"" -NO_PRIVATE_KEY_FOUND = "Nie znaleziono kluczy prywatnych" -NO_PRIVATE_KEY_FOUND_FOR = "Nie znaleziono kluczy prywatnych dla adresu: \"%EMAIL%\"" -UNVERIFIRED_SIGNATURE = "Niezweryfikowana sygnatura" +NO_PUBLIC_KEYS_FOUND = "Nie znaleziono klucza publicznego" +NO_PUBLIC_KEYS_FOUND_FOR = "Nie znaleziono klucza publicznego dla adresu: \"%EMAIL%\"" +NO_PRIVATE_KEY_FOUND = "Nie znaleziono klucza prywatnego" +NO_PRIVATE_KEY_FOUND_FOR = "Nie znaleziono klucza prywatnego dla adresu: \"%EMAIL%\"" +ADD_A_PUBLICK_KEY = "Add a public key" +UNVERIFIRED_SIGNATURE = "Niezweryfikowana" DECRYPTION_ERROR = "Błąd deszyfrowania OpenPGP" -GOOD_SIGNATURE = "Wiadomość podpisana przez: %USER%" +GOOD_SIGNATURE = "Podpisana przez: %USER%" PGP_ERROR = "Błąd OpenPGP: %ERROR%" SPECIFY_FROM_EMAIL = "Proszę podać adres e-mail w polu: OD" SPECIFY_AT_LEAST_ONE_RECIPIENT = "Proszę podać przynajmniej jednego odbiorcę" @@ -654,8 +674,8 @@ SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE = "To społecznościowe ID (Twitter), nie je SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE = "To społecznościowe ID (Konto Google), nie jest powiązane z żadnym kontem pocztowym. Zaloguj się używając danych swojego konta e-mail i skonfiguruj tę opcję w: Ustawienia > Sieci społecznościowe" DOMAIN_NOT_ALLOWED = "Domena niedozwolona" ACCOUNT_NOT_ALLOWED = "Konto nie jest dozwolone" -ACCOUNT_TWO_FACTOR_AUTH_REQUIRED = "Wymagana 2-stopniowa weryfikacja" -ACCOUNT_TWO_FACTOR_AUTH_ERROR = "Błąd 2-stopniowej weryfikacji" +ACCOUNT_TWO_FACTOR_AUTH_REQUIRED = "Wymagana dwuskładnikowa autoryzacja" +ACCOUNT_TWO_FACTOR_AUTH_ERROR = "Błąd dwuskładnikowej autoryzacji" COULD_NOT_SAVE_NEW_PASSWORD = "Nie można było zapisać nowego hasła" CURRENT_PASSWORD_INCORRECT = "Obecne hasło jest niepoprawne" NEW_PASSWORD_SHORT = "Hasło jest za krótkie" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Obsługa Cookies jest wyłączona w twojej przeglądarce Proszę o umożliwienie obsługi plików Cookie w przeglądarce oraz ponowne uruchomienie tej strony." BAD_BROWSER_TITLE = "Twoja przeglądarka jest przestarzała!" BAD_BROWSER_DESC = "W celu wykorzystania wszystkich funkcji tej aplikacji, -zaktualizuj aktualnie używaną lub pobierz i zainstaluj jedną z poniższych przeglądarek:" \ No newline at end of file +zaktualizuj aktualnie używaną lub pobierz i zainstaluj jedną z poniższych przeglądarek:" diff --git a/rainloop/v/0.0.0/langs/pt-br.ini b/rainloop/v/0.0.0/langs/pt-br.ini index 68e4045c5..b2b7289c9 100644 --- a/rainloop/v/0.0.0/langs/pt-br.ini +++ b/rainloop/v/0.0.0/langs/pt-br.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Não Sinalizadas" EMPTY_LIST = "Lista Vazia." EMPTY_SEARCH_LIST = "Nenhuma mensagem corresponde a sua pesquisa." SEARCH_RESULT_FOR = "Resultados de pesquisa para \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "Voltar para a lista de mensagens" LIST_LOADING = "Carregando" EMPTY_SUBJECT_TEXT = "(Sem assunto)" PUT_MESSAGE_HERE = "Coloque a mensagem aqui para vê-la na lista" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Selecione uma mensagem para visualizá-la aqui." PGP_PASSWORD_INPUT_PLACEHOLDER = "Senha" PGP_SIGNED_MESSAGE_DESC = "Mensagem assinada com OpenPGP (clique para verificar)" PGP_ENCRYPTED_MESSAGE_DESC = "Mensagem criptografada com OpenPGP (clique para descriptografar)" +LINK_DOWNLOAD_AS_ZIP = "Baixar como zip" +LINK_SAVE_TO_OWNCLOUD = "Salvar no ownCloud" +LINK_SAVE_TO_DROPBOX = "Salvar no Dropbox" [READ_RECEIPT] SUBJECT = "Aviso de recepção (Visualizada) - %SUBJECT%" @@ -240,7 +244,7 @@ BUTTON_OPEN_PGP = "OpenPGP (Somente Texto)" BUTTON_REQUEST_DSN = "Pedir recibo de entrega" [POPUPS_WELCOME_PAGE] -BUTTON_CLOSE = "Close" +BUTTON_CLOSE = "Fechar" [POPUPS_ASK] BUTTON_YES = "Sim" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Assinar" BUTTON_ENCRYPT = "Criptografar" BUTTON_SIGN_AND_ENCRYPT = "Assinar e criptografar" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "Testar verificação de duas etapas" LABEL_CODE = "Código" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Não Regexp" SELECT_TYPE_EQUAL_TO = "Igual à" SELECT_TYPE_NOT_EQUAL_TO = "Não é igual à" +SELECT_TYPE_OVER = "Maior que" +SELECT_TYPE_UNDER = "Menor que" SELECT_MATCH_ANY = "Corresponde à qualquer regra seguinte" SELECT_MATCH_ALL = "Corresponde à todas as regras seguintes" MARK_AS_READ_LABEL = "Marcar como Lida" @@ -357,6 +369,7 @@ STOP_LABEL = "Não parar o processamento das regras" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Assunto (opcional)" VACATION_MESSAGE_LABEL = "Mensagem" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Rejeitar mensagem" ALL_INCOMING_MESSAGES_DESC = "Todas as mensagens recebidas" @@ -388,12 +401,12 @@ LABEL_TWO_FACTOR_STATUS = "Status" LABEL_TWO_FACTOR_SECRET = "Segredo" LABEL_TWO_FACTOR_BACKUP_CODES = "Códigos de backup" BUTTON_CREATE = "Criar novo segredo" -BUTTON_ACTIVATE = "Activate" +BUTTON_ACTIVATE = "Ativar" BUTTON_CLEAR = "Limpar" -BUTTON_LOGOUT = "Logout" -BUTTON_DONE = "Done" +BUTTON_LOGOUT = "Sair" +BUTTON_DONE = "Completo" BUTTON_TEST = "Testar" -LINK_TEST = "test" +LINK_TEST = "teste" BUTTON_SHOW_SECRET = "Mostrar segredo" BUTTON_HIDE_SECRET = "Esconder segredo" TWO_FACTOR_REQUIRE_DESC = "Your account requires 2-Step verification configuration." @@ -467,14 +480,15 @@ LABEL_ADD_SIGNATURE_TO_ALL = "Adicionar sua assinatura em todas as mensagens de [SETTINGS_SECURITY] LEGEND_SECURITY = "Segurança" -LABEL_CONFIGURATE_TWO_FACTOR = "Configurate 2-Step verification" +LABEL_CONFIGURATE_TWO_FACTOR = "Configurar verificação de 2 etapas" LABEL_AUTOLOGOUT = "Deslogar Automaticamente" AUTOLOGIN_NEVER_OPTION_NAME = "Nunca" -AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minuto(s)" +AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minutos" [SETTINGS_GENERAL] LEGEND_GENERAL = "Geral" LABEL_LANGUAGE = "Idioma" +LABEL_IDENTITY = "Identidade" LABEL_LAYOUT = "Painel de Leitura" LABEL_LAYOUT_NO_SPLIT = "Sem divisão" LABEL_LAYOUT_VERTICAL_SPLIT = "Divisão Vertical" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Renomeando a pasta" DELETING_ASK = "Você tem certeza?" TO_MANY_FOLDERS_DESC_1 = "Você possui muitas pastas!" TO_MANY_FOLDERS_DESC_2 = "Mostraremos apenas uma parte delas, para evitar problemas de desempenho." +HELP_DELETE_FOLDER = "Deletar pasta" +HELP_SHOW_HIDE_FOLDER = "Mostrar/esconder pasta" +HELP_CHECK_FOR_NEW_MESSAGES = "Ativar/Desativar verificação por novas mensagens" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Lista de contas" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Gerar chave OpenPGP" TITLE_PRIVATE = "Privado" TITLE_PUBLIC = "Público" DELETING_ASK = "Você tem certeza?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Ajuda com os atalhos de teclado" @@ -607,6 +625,7 @@ LABEL_HELP = "Ajuda" LABEL_CHECK_ALL = "Selecionar todas as mensagens" LABEL_ARCHIVE = "Arquivar" LABEL_DELETE = "Excluir" +LABEL_OPEN_THREAD = "Abrir conversa selecionada" LABEL_MOVE = "Mover" LABEL_READ = "Marcar mensagens selecionadas como lidas" LABEL_UNREAD = "Marcar mensagens selecionadas como não lidas" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "Nenhuma chave pública encontrada" NO_PUBLIC_KEYS_FOUND_FOR = "Nenhuma chave pública encontrada para o e-mail \"%EMAIL%\"" NO_PRIVATE_KEY_FOUND = "Nenhuma chave privada encontrada" NO_PRIVATE_KEY_FOUND_FOR = "Nenhuma chave privada encontrada para o e-mail \"%EMAIL%\"" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Assinatura não verificada" DECRYPTION_ERROR = "Erro de decripitação de OpenPGP" GOOD_SIGNATURE = "Boa assinatura de %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Os Cookies não estão disponíveis em seu navegador. Por favor ative o suporte a Cookies nas configurações do seu navegador e tente novamente." BAD_BROWSER_TITLE = "Seu navegador está desatualizado." BAD_BROWSER_DESC = "Para usar todos os recursos do aplicativo, -baixe e instale um desses navegadores:" \ No newline at end of file +baixe e instale um desses navegadores:" diff --git a/rainloop/v/0.0.0/langs/pt-pt.ini b/rainloop/v/0.0.0/langs/pt-pt.ini index 231337e6e..ebc827efd 100644 --- a/rainloop/v/0.0.0/langs/pt-pt.ini +++ b/rainloop/v/0.0.0/langs/pt-pt.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Não sinalizada" EMPTY_LIST = "Lista vazia." EMPTY_SEARCH_LIST = "Nenhuma mensagem corresponde à sua pesquisa." SEARCH_RESULT_FOR = "Resultados de pesquisa para \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "voltar à lista de mensagens" LIST_LOADING = "A carregar" EMPTY_SUBJECT_TEXT = "(Sem assunto)" PUT_MESSAGE_HERE = "Coloque a mensagem aqui para vê-la na lista" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Selecione uma mensagem na lista para ver o conteúdo aqui." PGP_PASSWORD_INPUT_PLACEHOLDER = "Palavra-passe" PGP_SIGNED_MESSAGE_DESC = "Mensagem assinada com OpenPGP (clique para verificar)" PGP_ENCRYPTED_MESSAGE_DESC = "Mensagem encriptada com OpenPGP (clique para desencriptar)" +LINK_DOWNLOAD_AS_ZIP = "Transferir em arquivo zip" +LINK_SAVE_TO_OWNCLOUD = "Guardar no ownCloud" +LINK_SAVE_TO_DROPBOX = "Guardar no Dropbox" [READ_RECEIPT] SUBJECT = "Recibo de leitura (apresentado) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Assinar" BUTTON_ENCRYPT = "Encriptar" BUTTON_SIGN_AND_ENCRYPT = "Assinar e encriptar" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "Teste de verificação em 2-Etapas" LABEL_CODE = "Código" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Sem Regexp" SELECT_TYPE_EQUAL_TO = "Igual a" SELECT_TYPE_NOT_EQUAL_TO = "Não é igual a" +SELECT_TYPE_OVER = "Superior" +SELECT_TYPE_UNDER = "Inferior" SELECT_MATCH_ANY = "Correspondendo a qualquer uma das regras que se seguem" SELECT_MATCH_ALL = "Correspondendo a todas as regras que se seguem" MARK_AS_READ_LABEL = "Marcar como lida" @@ -357,6 +369,7 @@ STOP_LABEL = "Não parar de processar as regras" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Assunto (opcional)" VACATION_MESSAGE_LABEL = "Mensagem" +VACATION_RECIPIENTS_LABEL = "Destinatários (separados por vírgula)" REJECT_MESSAGE_LABEL = "Rejeitar mensagem" ALL_INCOMING_MESSAGES_DESC = "Todas as mensagens recebidas" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minuto(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Geral" LABEL_LANGUAGE = "Idioma" +LABEL_IDENTITY = "Identidade" LABEL_LAYOUT = "Apresentação" LABEL_LAYOUT_NO_SPLIT = "Sem separação" LABEL_LAYOUT_VERTICAL_SPLIT = "Separação vertical" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Renomear a pasta" DELETING_ASK = "Tem a certeza?" TO_MANY_FOLDERS_DESC_1 = "Você tem demasiadas pastas!" TO_MANY_FOLDERS_DESC_2 = "Apenas apresentámos parte delas, para evitar problemas de desempenho." +HELP_DELETE_FOLDER = "Eliminar pasta" +HELP_SHOW_HIDE_FOLDER = "Mostrar/ocultar pasta" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Lista de contas" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Gerar chaves OpenPGP" TITLE_PRIVATE = "Privada" TITLE_PUBLIC = "Pública" DELETING_ASK = "Tem a certeza?" +GENERATE_ONLY_HTTPS = "Apenas HTTPS" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Ajuda para atalhos de teclado" @@ -607,6 +625,7 @@ LABEL_HELP = "Ajuda" LABEL_CHECK_ALL = "Selecionar todas as mensagens" LABEL_ARCHIVE = "Arquivar" LABEL_DELETE = "Eliminar" +LABEL_OPEN_THREAD = "Abrir tópico selecionado" LABEL_MOVE = "Mover" LABEL_READ = "Ler as mensagens selecionadas" LABEL_UNREAD = "Marcar as mensagens selecionadas como não lidas" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "Nenhuma chave pública encontrada" NO_PUBLIC_KEYS_FOUND_FOR = "Nenhuma chave pública encontrada para o email \"%EMAIL%\"" NO_PRIVATE_KEY_FOUND = "Nenhuma chave privada encontrada" NO_PRIVATE_KEY_FOUND_FOR = "Nenhuma chave privada encontrada para o email \"%EMAIL%\"" +ADD_A_PUBLICK_KEY = "Adicionar uma chave pública" UNVERIFIRED_SIGNATURE = "Assinatura não verificada" DECRYPTION_ERROR = "Erro de desencriptação OpenPGP" GOOD_SIGNATURE = "Boa assinatura de %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "O suport de Cookies não está disponível no seu navegador. Por favor ative o suporte de Cookies nas definições do seu navegador e tente novamente." BAD_BROWSER_TITLE = "O seu navegador está desatualizado." BAD_BROWSER_DESC = "Para usar todas as funções da aplicação, -transfira e instale um destes navegadores:" \ No newline at end of file +transfira e instale um destes navegadores:" diff --git a/rainloop/v/0.0.0/langs/ro.ini b/rainloop/v/0.0.0/langs/ro.ini index 157555e6f..eba8053f2 100644 --- a/rainloop/v/0.0.0/langs/ro.ini +++ b/rainloop/v/0.0.0/langs/ro.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Neimportant" EMPTY_LIST = "Nimic aici, deocamdată" EMPTY_SEARCH_LIST = "Nu am găsit nimic." SEARCH_RESULT_FOR = "Rezultat căutare \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Caut..." EMPTY_SUBJECT_TEXT = "(nici un subiect)" PUT_MESSAGE_HERE = "EROARE CONTACTATI ADIMISTRATORUL!(trimite-ti un prt.scr)" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Selectați un mesaj pentru al vizualiza." PGP_PASSWORD_INPUT_PLACEHOLDER = "Password" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Mesajul dumneavoastră a fost citit - %SUBJECT%" @@ -315,6 +319,12 @@ BUTTON_SIGN = "Sign" BUTTON_ENCRYPT = "Encrypt" BUTTON_SIGN_AND_ENCRYPT = "Sign and encrypt" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-Step verification test" LABEL_CODE = "Code" @@ -347,6 +357,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -356,6 +368,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -474,6 +487,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Setări de bază" LABEL_LANGUAGE = "Limbă" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -550,6 +564,9 @@ RENAMING_PROCESS = "Redenumesc dosarul" DELETING_ASK = "Sunteți sigur?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Lista de Conturi" @@ -590,6 +607,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generate OpenPGP Keys" TITLE_PRIVATE = "Private" TITLE_PUBLIC = "Public" DELETING_ASK = "Are you sure?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Keyboard shortcuts help" @@ -606,6 +624,7 @@ LABEL_HELP = "Help" LABEL_CHECK_ALL = "Select all messages" LABEL_ARCHIVE = "Archive" LABEL_DELETE = "Delete" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Move" LABEL_READ = "Read selected messages" LABEL_UNREAD = "Unread selected messages" @@ -635,6 +654,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -707,4 +727,4 @@ NO_COOKIE_DESC = "Aparent, Cookie sau nu este acceptat de browser-ul dvs. sau op Întoarceți Cookie, schimband optiunile browserului dvs., apoi încercați din nou." BAD_BROWSER_TITLE = "Browser-ul dvs. este depășit." BAD_BROWSER_DESC = "Pentru a utiliza toate caracteristicile cererii, -descărcați și instalați unul dintre aceste browsere:" \ No newline at end of file +descărcați și instalați unul dintre aceste browsere:" diff --git a/rainloop/v/0.0.0/langs/ru.ini b/rainloop/v/0.0.0/langs/ru.ini index fe867ba1b..373cccaab 100644 --- a/rainloop/v/0.0.0/langs/ru.ini +++ b/rainloop/v/0.0.0/langs/ru.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Без пометок" EMPTY_LIST = "В папке нет писем." EMPTY_SEARCH_LIST = "Письма не найдены." SEARCH_RESULT_FOR = "Результат поиска \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Загрузка" EMPTY_SUBJECT_TEXT = "(Без темы)" PUT_MESSAGE_HERE = "Киньте сообщение сюда, чтобы посмотреть его в списке" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Выберите сообщение для просмотр PGP_PASSWORD_INPUT_PLACEHOLDER = "Пароль" PGP_SIGNED_MESSAGE_DESC = "OpenPGP подписанное сообщение (нажмите, чтобы подтвердить)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP шифрованное сообщение (нажмите, чтобы расшифровать)" +LINK_DOWNLOAD_AS_ZIP = "Сохранить как zip" +LINK_SAVE_TO_OWNCLOUD = "Сохранить в ownCloud" +LINK_SAVE_TO_DROPBOX = "Сохранить в Dropbox" [READ_RECEIPT] SUBJECT = "Уведомление о прочтении письма - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Подпись" BUTTON_ENCRYPT = "Шифрование" BUTTON_SIGN_AND_ENCRYPT = "Подпись и шифрование" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "Тест двухфакторной верификации" LABEL_CODE = "Код" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Не Regexp" SELECT_TYPE_EQUAL_TO = "Совпадает с" SELECT_TYPE_NOT_EQUAL_TO = "Не совпадает с" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Подходит под хотя бы одно из нижеперечисленных правил" SELECT_MATCH_ALL = "Подходит под все нижеперечисленные правила" MARK_AS_READ_LABEL = "Отметить как прочитанное" @@ -357,6 +369,7 @@ STOP_LABEL = "Не преращать обработку правил" EMAIL_LABEL = "Почтка" VACATION_SUBJECT_LABEL = "Тема (необязательно)" VACATION_MESSAGE_LABEL = "Сообщение" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Причина (будет послана отправителю)" ALL_INCOMING_MESSAGES_DESC = "Все входящие сообщения" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% минут(ы)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Основные Настройки" LABEL_LANGUAGE = "Язык" +LABEL_IDENTITY = "Профиль" LABEL_LAYOUT = "Разметка" LABEL_LAYOUT_NO_SPLIT = "Одна панель" LABEL_LAYOUT_VERTICAL_SPLIT = "Вертикальные панели" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Переименование папки" DELETING_ASK = "Точно?" TO_MANY_FOLDERS_DESC_1 = "У вас слишком много папок!" TO_MANY_FOLDERS_DESC_2 = "Мы показали только часть из них, чтобы избежать проблем с производительностью." +HELP_DELETE_FOLDER = "Удалить папку" +HELP_SHOW_HIDE_FOLDER = "Показывать/прятать папку" +HELP_CHECK_FOR_NEW_MESSAGES = "Проверять/не проверять новые сообщения" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Список Аккаунтов" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Новый OpenPGP ключ" TITLE_PRIVATE = "Приватный" TITLE_PUBLIC = "Публичный" DELETING_ASK = "Точно?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Сочетания клавиш" @@ -607,6 +625,7 @@ LABEL_HELP = "Помощь" LABEL_CHECK_ALL = "Выбрать все сообщения" LABEL_ARCHIVE = "Архивировать" LABEL_DELETE = "Удалить" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Переместить" LABEL_READ = "Пометить выбранные письма прочитанными" LABEL_UNREAD = "Пометить выбранные письма непрочитанными" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "Публичные ключи не найдены" NO_PUBLIC_KEYS_FOUND_FOR = "Публичные ключи для \"%EMAIL%\" не найдены" NO_PRIVATE_KEY_FOUND = "Приватный ключ не найден" NO_PRIVATE_KEY_FOUND_FOR = "Приватный ключ для \"%EMAIL%\" не найден" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Неподтвержденная сигнатура" DECRYPTION_ERROR = "OpenPGP ошибка расшифровки" GOOD_SIGNATURE = "Подтвержденная сигнатура для %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "По-видимому, Cookie либо не поддержив Включите Cookie, изменив настройки браузера, затем повторите попытку." BAD_BROWSER_TITLE = "Ваш браузер устарел." BAD_BROWSER_DESC = "Чтобы использовать все возможности приложения, -загрузите и установите один из этих браузеров:" \ No newline at end of file +загрузите и установите один из этих браузеров:" diff --git a/rainloop/v/0.0.0/langs/sk.ini b/rainloop/v/0.0.0/langs/sk.ini index ec6f1512b..10eac6d9a 100644 --- a/rainloop/v/0.0.0/langs/sk.ini +++ b/rainloop/v/0.0.0/langs/sk.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Neoznačené" EMPTY_LIST = "Zoznam je prázdny." EMPTY_SEARCH_LIST = "Vášmu vyhľadávaniu nezodpovedajú žiadne správy." SEARCH_RESULT_FOR = "Výsledky vyhľadávania pre \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Načítavam" EMPTY_SUBJECT_TEXT = "(Bez predmetu)" PUT_MESSAGE_HERE = "Pusťte správu tu pre jej zobrazenie v zozname" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Vyberte správu zo zoznamu pre jej zobrazenie tu." PGP_PASSWORD_INPUT_PLACEHOLDER = "Password" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Return Receipt (displayed) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Sign" BUTTON_ENCRYPT = "Encrypt" BUTTON_SIGN_AND_ENCRYPT = "Sign and encrypt" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-Step verification test" LABEL_CODE = "Code" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Všeobecné" LABEL_LANGUAGE = "Jazyk" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Premenovávam prečinok" DELETING_ASK = "Ste si istý?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Zoznam účtov" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Generate OpenPGP Keys" TITLE_PRIVATE = "Private" TITLE_PUBLIC = "Public" DELETING_ASK = "Are you sure?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Keyboard shortcuts help" @@ -607,6 +625,7 @@ LABEL_HELP = "Help" LABEL_CHECK_ALL = "Select all messages" LABEL_ARCHIVE = "Archive" LABEL_DELETE = "Delete" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Move" LABEL_READ = "Read selected messages" LABEL_UNREAD = "Unread selected messages" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Váš internetový prehliadač nepodporuje Cookies. Prosím povoľte podporu Cookies v nastaveniach vášho internetového prehliadača a skúste to znova." BAD_BROWSER_TITLE = "Používate zastaralý internetový prehliadač." BAD_BROWSER_DESC = "Aby ste mohli využívať všetky funkcie tejto aplikácie, -použite niektorý z nasledujúcich internetových prehliadačov:" \ No newline at end of file +použite niektorý z nasledujúcich internetových prehliadačov:" diff --git a/rainloop/v/0.0.0/langs/sv.ini b/rainloop/v/0.0.0/langs/sv.ini index bee76c80f..9c0ca8f1a 100644 --- a/rainloop/v/0.0.0/langs/sv.ini +++ b/rainloop/v/0.0.0/langs/sv.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Avflaggad" EMPTY_LIST = "Tom lista" EMPTY_SEARCH_LIST = "Inga meddelanden matchar din sökning." SEARCH_RESULT_FOR = "Sök resultat för \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Laddar" EMPTY_SUBJECT_TEXT = "(Inget ämne)" PUT_MESSAGE_HERE = "Släpp meddelandet för att se det i listan" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Välj meddelande i listan att visa här." PGP_PASSWORD_INPUT_PLACEHOLDER = "Lösenord" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signerat meddelande (klicka för att verifiera)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP krypterat meddelande (klicka för att dekryptera)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Mottagar kvitto (visad) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Singera" BUTTON_ENCRYPT = "Kryptera" BUTTON_SIGN_AND_ENCRYPT = "Signera och kryptera" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-Stegs verifikations test" LABEL_CODE = "Kod" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Allmänt" LABEL_LANGUAGE = "Språk" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Byter namn på en mapp" DELETING_ASK = "Är du säker?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Kontolista" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Skapa OpenPGP nycklar" TITLE_PRIVATE = "Privat" TITLE_PUBLIC = "Publik" DELETING_ASK = "Är du säker?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Tangentbordsgenvägar hjälp" @@ -607,6 +625,7 @@ LABEL_HELP = "Hjälp" LABEL_CHECK_ALL = "Kontrollera alla meddelanden" LABEL_ARCHIVE = "Arkiv" LABEL_DELETE = "Ta bort" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Flytta" LABEL_READ = "Markera valda meddelanden som lästa" LABEL_UNREAD = "Markera valda meddelanden som olästa" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "Inga publika nycklar funna" NO_PUBLIC_KEYS_FOUND_FOR = "Inga publika nycklar funna för \"%EMAIL%\" epost" NO_PRIVATE_KEY_FOUND = "Inga privata nycklar funna" NO_PRIVATE_KEY_FOUND_FOR = "Inga privata nycklar funna för \"%EMAIL%\" epost" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Overifierad signatur" DECRYPTION_ERROR = "OpenPGP dekrypterings fel" GOOD_SIGNATURE = "Godkänd signatur för %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Kakstöd är inte tillgängligt i webbläsaren. Aktivera kakstöd och försök igen." BAD_BROWSER_TITLE = "Webbläsaren är för gammal." BAD_BROWSER_DESC = "För att använda funktioner i denna applikation, -ladda ner och installera någon av följande webbläsare:" \ No newline at end of file +ladda ner och installera någon av följande webbläsare:" diff --git a/rainloop/v/0.0.0/langs/tr.ini b/rainloop/v/0.0.0/langs/tr.ini index 710626341..c51c31911 100644 --- a/rainloop/v/0.0.0/langs/tr.ini +++ b/rainloop/v/0.0.0/langs/tr.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "İşaretlenmemiş" EMPTY_LIST = "Herhangi Bir Sonuç Bulunamadı." EMPTY_SEARCH_LIST = "Arama sonuçlarına uyan herhangi bir mesaj bulunamadı." SEARCH_RESULT_FOR = "\"%SEARCH%\" için arama sonuçları" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Yükleniyor" EMPTY_SUBJECT_TEXT = "(Konu Yok)" PUT_MESSAGE_HERE = "Listede görüntülemek istediğiniz mesajı buraya sürükleyin." @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Burada görüntülemek için listeden mesaj seçin." PGP_PASSWORD_INPUT_PLACEHOLDER = "Şifre" PGP_SIGNED_MESSAGE_DESC = "OpenPGP imzalı mesaj (onay için tıklayın)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP şifreli mesaj (çözmek için tıklayın)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Return Receipt (displayed) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Giriş Yap" BUTTON_ENCRYPT = "Şifrele" BUTTON_SIGN_AND_ENCRYPT = "Giriş Yap and şifrele" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-Basamaklı doğrulama testi" LABEL_CODE = "Kod" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -473,6 +486,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Genel" LABEL_LANGUAGE = "Dil" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -549,6 +563,9 @@ RENAMING_PROCESS = "Klasör değiştiriliyor" DELETING_ASK = "Eminmisiniz?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Hesap Listesi" @@ -589,6 +606,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "OpenPGP Key Oluştur" TITLE_PRIVATE = "Private" TITLE_PUBLIC = "Public" DELETING_ASK = "Eminmisiniz?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Klavye kısayolları yardım" @@ -605,6 +623,7 @@ LABEL_HELP = "Yardım" LABEL_CHECK_ALL = "Tüm mesajları seç" LABEL_ARCHIVE = "Arşiv" LABEL_DELETE = "Sil" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Taşı" LABEL_READ = "Seçili mesajları oku" LABEL_UNREAD = "Seçili mesajları okuma" @@ -634,6 +653,7 @@ NO_PUBLIC_KEYS_FOUND = "Public key bulunamadı" NO_PUBLIC_KEYS_FOUND_FOR = "Public key bulunamadı %EMAIL%" NO_PRIVATE_KEY_FOUND = "Private key bulunamadı" NO_PRIVATE_KEY_FOUND_FOR = "Private key bulunamadı %EMAIL%" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Doğrulanmamış imza" DECRYPTION_ERROR = "OpenPGP çözme hatası" GOOD_SIGNATURE = "Geçerli imza %USER%" @@ -706,4 +726,4 @@ NO_COOKIE_DESC = "Çerezler destek tarayıcınızda mevcut değil. Tarayıcı ayarlarında Cookie desteği etkinleştirin ve yeniden deneyin." BAD_BROWSER_TITLE = "Tarayıcınız çok eski." BAD_BROWSER_DESC = "Uygulamanın tüm özelliklerini kullanmak için, -Bu tarayıcılardan birini indirmek ve yükleyin:" \ No newline at end of file +Bu tarayıcılardan birini indirmek ve yükleyin:" diff --git a/rainloop/v/0.0.0/langs/ua.ini b/rainloop/v/0.0.0/langs/ua.ini index 7968a966d..4fb9855e4 100644 --- a/rainloop/v/0.0.0/langs/ua.ini +++ b/rainloop/v/0.0.0/langs/ua.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "Без поміток" EMPTY_LIST = "В папці немає листів." EMPTY_SEARCH_LIST = "Листи не знайдено." SEARCH_RESULT_FOR = "Результат пошуку \"%SEARCH%\"" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "Завантаження" EMPTY_SUBJECT_TEXT = "(Без теми)" PUT_MESSAGE_HERE = "Киньте повідомлення сюди, щоб подивитися його в списку" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "Выберіть повідомлення для перег PGP_PASSWORD_INPUT_PLACEHOLDER = "Пароль" PGP_SIGNED_MESSAGE_DESC = "OpenPGP підписане повідомлення (натисніть, щоб підтвердити)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP шифроване повідомлення (натисніть, щоб розшифрувати)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Сповіщення про прочитання цього повідомлення - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Підпис" BUTTON_ENCRYPT = "Шифрування" BUTTON_SIGN_AND_ENCRYPT = "Підпис и шифрування" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "Тест двофакторної верифікації" LABEL_CODE = "Код" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "Основні Налаштування" LABEL_LANGUAGE = "Мова" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "Перейменування теки" DELETING_ASK = "Впевнені?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "Список акаунтів" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "Новий OpenPGP ключ" TITLE_PRIVATE = "Приватний" TITLE_PUBLIC = "Публічний" DELETING_ASK = "Впевнені?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Сполучення клавіш" @@ -607,6 +625,7 @@ LABEL_HELP = "Допомога" LABEL_CHECK_ALL = "Вибрати всі повідомлення" LABEL_ARCHIVE = "Архівувати" LABEL_DELETE = "Видалити" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "Перемістити" LABEL_READ = "Відмітити вибрані листи прочитаними" LABEL_UNREAD = "Відмітити вибрані листи непрочитаними" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "Публічні ключі не знайдено" NO_PUBLIC_KEYS_FOUND_FOR = "Публічні ключі для \"%EMAIL%\" не знайдено" NO_PRIVATE_KEY_FOUND = "Приватний ключ не знайдено" NO_PRIVATE_KEY_FOUND_FOR = "Приватний ключ для \"%EMAIL%\" не знайдено" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Непідтверджена сигнатура" DECRYPTION_ERROR = "OpenPGP помилка розшифрування" GOOD_SIGNATURE = "Підтверджена сигнатура для %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "Здається, Cookie або не підтримуютьс Увімкніть Cookie, змінив налаштівання браузера, і спробуйте знову." BAD_BROWSER_TITLE = "Ваш браузер застарів." BAD_BROWSER_DESC = "Щоб використовувати всі можливості додатку, -завантажте і встановіть один з цих браузерів:" \ No newline at end of file +завантажте і встановіть один з цих браузерів:" diff --git a/rainloop/v/0.0.0/langs/zh-cn.ini b/rainloop/v/0.0.0/langs/zh-cn.ini index 21ee3af13..a607ada0d 100644 --- a/rainloop/v/0.0.0/langs/zh-cn.ini +++ b/rainloop/v/0.0.0/langs/zh-cn.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "未加星标" EMPTY_LIST = "空列表。" EMPTY_SEARCH_LIST = "未找到您想要的。" SEARCH_RESULT_FOR = "搜索 \"%SEARCH%\" 的结果" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "加载中" EMPTY_SUBJECT_TEXT = "(无主题)" PUT_MESSAGE_HERE = "在这里查看邮件" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "在此查看列表中选中的邮件。" PGP_PASSWORD_INPUT_PLACEHOLDER = "Password" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Return Receipt (displayed) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Sign" BUTTON_ENCRYPT = "Encrypt" BUTTON_SIGN_AND_ENCRYPT = "Sign and encrypt" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "两步验证测试" LABEL_CODE = "代码" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "一般设置" LABEL_LANGUAGE = "语言" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "文件夹重命名" DELETING_ASK = "确定?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "账户列表" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "生成 OpenPGP 密匙" TITLE_PRIVATE = "私有" TITLE_PUBLIC = "公开" DELETING_ASK = "你确定吗?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Keyboard shortcuts help" @@ -607,6 +625,7 @@ LABEL_HELP = "帮助" LABEL_CHECK_ALL = "检查所有消息" LABEL_ARCHIVE = "存档" LABEL_DELETE = "删除" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "移动" LABEL_READ = "Read selected messages" LABEL_UNREAD = "Unread selected messages" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "您的浏览器不支持Cookies。 请启用浏览器的Cookies支持并重试。" BAD_BROWSER_TITLE = "您的浏览器过时了" BAD_BROWSER_DESC = "为了使用所有特性, -下载并安装其中一款浏览器:" \ No newline at end of file +下载并安装其中一款浏览器:" diff --git a/rainloop/v/0.0.0/langs/zh-tw.ini b/rainloop/v/0.0.0/langs/zh-tw.ini index f6b6ff4bd..0278c11bc 100644 --- a/rainloop/v/0.0.0/langs/zh-tw.ini +++ b/rainloop/v/0.0.0/langs/zh-tw.ini @@ -90,6 +90,7 @@ MENU_SELECT_UNFLAGGED = "未加星標" EMPTY_LIST = "空列表。" EMPTY_SEARCH_LIST = "未找到您想要的。" SEARCH_RESULT_FOR = "搜索 \"%SEARCH%\" 的結果" +BACK_TO_MESSAGE_LIST = "back to message list" LIST_LOADING = "載入中" EMPTY_SUBJECT_TEXT = "(無主題)" PUT_MESSAGE_HERE = "在這裡查看郵件" @@ -149,6 +150,9 @@ MESSAGE_VIEW_DESC = "在此查看列表中選中的郵件。" PGP_PASSWORD_INPUT_PLACEHOLDER = "Password" PGP_SIGNED_MESSAGE_DESC = "OpenPGP signed message (click to verify)" PGP_ENCRYPTED_MESSAGE_DESC = "OpenPGP encrypted message (click to decrypt)" +LINK_DOWNLOAD_AS_ZIP = "Download as zip" +LINK_SAVE_TO_OWNCLOUD = "Save to ownCloud" +LINK_SAVE_TO_DROPBOX = "Save to Dropbox" [READ_RECEIPT] SUBJECT = "Return Receipt (displayed) - %SUBJECT%" @@ -316,6 +320,12 @@ BUTTON_SIGN = "Sign" BUTTON_ENCRYPT = "Encrypt" BUTTON_SIGN_AND_ENCRYPT = "Sign and encrypt" +[POPUPS_MESSAGE_OPEN_PGP] +TITLE_MESSAGE_OPEN_PGP = "OpenPGP Decrypt" +LABEL_KEY = "Private Key" +LABEL_PASSWORD = "Password" +BUTTON_DECRYPT = "Decrypt" + [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "兩步驗證測試" LABEL_CODE = "代碼" @@ -348,6 +358,8 @@ SELECT_TYPE_REGEXP = "Regexp" SELECT_TYPE_NOT_REGEXP = "Not Regexp" SELECT_TYPE_EQUAL_TO = "Equal To" SELECT_TYPE_NOT_EQUAL_TO = "Not Equal To" +SELECT_TYPE_OVER = "Over" +SELECT_TYPE_UNDER = "Under" SELECT_MATCH_ANY = "Matching any of the following rules" SELECT_MATCH_ALL = "Matching all of the following rules" MARK_AS_READ_LABEL = "Mark as read" @@ -357,6 +369,7 @@ STOP_LABEL = "Don't stop processing rules" EMAIL_LABEL = "Email" VACATION_SUBJECT_LABEL = "Subject (optional)" VACATION_MESSAGE_LABEL = "Message" +VACATION_RECIPIENTS_LABEL = "Recipients (comma separated)" REJECT_MESSAGE_LABEL = "Reject message" ALL_INCOMING_MESSAGES_DESC = "All incoming messages" @@ -475,6 +488,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)" [SETTINGS_GENERAL] LEGEND_GENERAL = "一般設置" LABEL_LANGUAGE = "語言" +LABEL_IDENTITY = "Identity" LABEL_LAYOUT = "Layout" LABEL_LAYOUT_NO_SPLIT = "No Split" LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split" @@ -551,6 +565,9 @@ RENAMING_PROCESS = "資料夾重命名" DELETING_ASK = "確定?" TO_MANY_FOLDERS_DESC_1 = "You have too many folders!" TO_MANY_FOLDERS_DESC_2 = "We have shown only a part of them, to avoid performance problems." +HELP_DELETE_FOLDER = "Delete folder" +HELP_SHOW_HIDE_FOLDER = "Show/hide folder" +HELP_CHECK_FOR_NEW_MESSAGES = "Check/don't check for new messages" [SETTINGS_ACCOUNTS] LEGEND_ACCOUNTS = "帳戶列表" @@ -591,6 +608,7 @@ BUTTON_GENERATE_OPEN_PGP_KEYS = "生成 OpenPGP 密鑰" TITLE_PRIVATE = "私有" TITLE_PUBLIC = "公開" DELETING_ASK = "你確定嗎?" +GENERATE_ONLY_HTTPS = "HTTPS only" [SHORTCUTS_HELP] LEGEND_SHORTCUTS_HELP = "Keyboard shortcuts help" @@ -607,6 +625,7 @@ LABEL_HELP = "幫助" LABEL_CHECK_ALL = "檢查所有消息" LABEL_ARCHIVE = "存檔" LABEL_DELETE = "刪除" +LABEL_OPEN_THREAD = "Open selected thread" LABEL_MOVE = "移動" LABEL_READ = "Read selected messages" LABEL_UNREAD = "Unread selected messages" @@ -636,6 +655,7 @@ NO_PUBLIC_KEYS_FOUND = "No public keys found" NO_PUBLIC_KEYS_FOUND_FOR = "No public keys found for \"%EMAIL%\" email" NO_PRIVATE_KEY_FOUND = "No private key found" NO_PRIVATE_KEY_FOUND_FOR = "No private key found for \"%EMAIL%\" email" +ADD_A_PUBLICK_KEY = "Add a public key" UNVERIFIRED_SIGNATURE = "Unverified signature" DECRYPTION_ERROR = "OpenPGP decryption error" GOOD_SIGNATURE = "Good signature from %USER%" @@ -708,4 +728,4 @@ NO_COOKIE_DESC = "您的瀏覽器不支持Cookies。 請啟用瀏覽器的Cookies支持並重試。" BAD_BROWSER_TITLE = "您的瀏覽器過時了" BAD_BROWSER_DESC = "為了使用所有特性, -下載並安裝其中一款瀏覽器:" \ No newline at end of file +下載並安裝其中一款瀏覽器:" diff --git a/rainloop/v/0.0.0/static/ckeditor/plugins/signature/plugin.js b/rainloop/v/0.0.0/static/ckeditor/plugins/signature/plugin.js index 68777a7ae..31ff05e1d 100644 --- a/rainloop/v/0.0.0/static/ckeditor/plugins/signature/plugin.js +++ b/rainloop/v/0.0.0/static/ckeditor/plugins/signature/plugin.js @@ -4,50 +4,52 @@ rl_signature_replacer = function (editor, sText, sSignature, bHtml, bInsertBefor if (!bHtml) { sText = sText - .replace(/\u200C\u200C/g, '\u0002\u0002') - .replace(/\u200D\u200D/g, '\u0003\u0003') + .replace(/\u200C([\s\S]*)\u200C/g, '\u0002$1\u0002') + .replace(/\u200C/g, '') ; } var - sTextWithoutSignature = sText - .replace(/\u0002\u0002[\s\S]*\u0002\u0002/gm, '') - .replace(/\u0003\u0003[\s\S]*\u0003\u0003/gm, ''), - bEmptyText = '' === $.trim(sTextWithoutSignature), + sP = '~~~~@~~~~', + bEmptyText = false, sNewLine = (bHtml ? '
' : "\n") ; + sText = sText.replace(/\u0002([\s\S]*)\u0002/gm, sP + '$1' + sP); + + if (editor.__previos_signature) + { + sText = sText + .replace(sP + editor.__previos_signature + sP, '') + .replace(sP + editor.__previos_signature + sP, '') + .replace(sP + editor.__previos_signature + sP, '') + ; + } + + sText = sText.replace(sP, '').replace(sP, '').replace(sP, '').replace(sP, ''); + + bEmptyText = '' === $.trim(sText); if (!bEmptyText && bHtml) { - bEmptyText = '' !== $.trim(editor.__plainUtils.htmlToPlain(sTextWithoutSignature)); - } - - if (!/\u0002\u0002/gm.test(sText)) - { - sText = "\u0002\u0002\u0002\u0002" + sText; - } - - if (!/\u0003\u0003/gm.test(sText)) - { - sText = sText + "\u0003\u0003\u0003\u0003"; + bEmptyText = '' !== $.trim(editor.__plainUtils.htmlToPlain(sText)); } if (bInsertBefore) { - sText = sText.replace(/\u0002\u0002[\s\S]*\u0002\u0002/gm, "\u0002\u0002" + sSignature + (bEmptyText ? '' : sNewLine) + "\u0002\u0002"); - sText = sText.replace(/\u0003\u0003[\s\S]*\u0003\u0003/gm, "\u0003\u0003\u0003\u0003"); + sText = "\u0002" + sSignature + (bEmptyText ? '' : sNewLine) + "\u0002" + sText; + editor.__previos_signature = sSignature + (bEmptyText ? '' : sNewLine); } else { - sText = sText.replace(/\u0002\u0002[\s\S]*\u0002\u0002/gm, "\u0002\u0002\u0002\u0002"); - sText = sText.replace(/\u0003\u0003[\s\S]*\u0003\u0003/gm, "\u0003\u0003" + (bEmptyText ? '' : sNewLine) + sSignature + "\u0003\u0003"); + sText = sText + "\u0002" + (bEmptyText ? '' : sNewLine) + sSignature + "\u0002"; + editor.__previos_signature = (bEmptyText ? '' : sNewLine) + sSignature; } if (!bHtml) { sText = sText - .replace(/\u0002\u0002/g, '\u200C\u200C') - .replace(/\u0003\u0003/g, '\u200D\u200D') + .replace(/\u0002([\s\S]*)\u0002/g, '\u200C$1\u200C') + .replace(/\u0002/g, '') ; } @@ -90,8 +92,7 @@ CKEDITOR.plugins.add('signature', { } editor.__plain.setRawData( - rl_signature_replacer(editor, - editor.__plain.getRawData(), sResultSignature, false, bInsertBefore)); + rl_signature_replacer(editor, editor.__plain.getRawData(), sResultSignature, false, bInsertBefore)); } else @@ -105,8 +106,7 @@ CKEDITOR.plugins.add('signature', { } editor.setData( - rl_signature_replacer(editor, - editor.getData(), sResultSignature, true, bInsertBefore)); + rl_signature_replacer(editor, editor.getData(), sResultSignature, true, bInsertBefore)); } } catch (e) {} diff --git a/rainloop/v/0.0.0/static/css/fonts/.gitempty b/rainloop/v/0.0.0/static/css/fonts/.gitempty new file mode 100644 index 000000000..e69de29bb diff --git a/rainloop/v/0.0.0/static/css/fonts/rainloop.eot b/rainloop/v/0.0.0/static/css/fonts/rainloop.eot index cb64d4537..d2bf0d541 100644 Binary files a/rainloop/v/0.0.0/static/css/fonts/rainloop.eot and b/rainloop/v/0.0.0/static/css/fonts/rainloop.eot differ diff --git a/rainloop/v/0.0.0/static/css/fonts/rainloop.svg b/rainloop/v/0.0.0/static/css/fonts/rainloop.svg index 3357f3364..cc66a0e77 100644 --- a/rainloop/v/0.0.0/static/css/fonts/rainloop.svg +++ b/rainloop/v/0.0.0/static/css/fonts/rainloop.svg @@ -122,4 +122,5 @@ + diff --git a/rainloop/v/0.0.0/static/css/fonts/rainloop.ttf b/rainloop/v/0.0.0/static/css/fonts/rainloop.ttf index 3cc1d79cc..09186ead5 100644 Binary files a/rainloop/v/0.0.0/static/css/fonts/rainloop.ttf and b/rainloop/v/0.0.0/static/css/fonts/rainloop.ttf differ diff --git a/rainloop/v/0.0.0/static/css/fonts/rainloop.woff b/rainloop/v/0.0.0/static/css/fonts/rainloop.woff index 3ff6793d9..a7d4ab38c 100644 Binary files a/rainloop/v/0.0.0/static/css/fonts/rainloop.woff and b/rainloop/v/0.0.0/static/css/fonts/rainloop.woff differ diff --git a/rainloop/v/0.0.0/static/css/svg/.gitempty b/rainloop/v/0.0.0/static/css/svg/.gitempty new file mode 100644 index 000000000..e69de29bb diff --git a/rainloop/v/0.0.0/static/css/svg/icons.svg b/rainloop/v/0.0.0/static/css/svg/icons.svg new file mode 100644 index 000000000..b4b44d0c3 --- /dev/null +++ b/rainloop/v/0.0.0/static/css/svg/icons.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendors/bootstrap/less/tables.less b/vendors/bootstrap/less/tables.less index 853b97e39..ae17125b6 100644 --- a/vendors/bootstrap/less/tables.less +++ b/vendors/bootstrap/less/tables.less @@ -6,7 +6,8 @@ // BASE TABLES // ----------------- -table { +// table { +.table { max-width: 100%; background-color: @tableBackground; border-collapse: collapse; diff --git a/vendors/buzz/buzz.js b/vendors/buzz/buzz.js deleted file mode 100644 index 5bcd33ede..000000000 --- a/vendors/buzz/buzz.js +++ /dev/null @@ -1,719 +0,0 @@ - // ---------------------------------------------------------------------------- - // Buzz, a Javascript HTML5 Audio library - // v1.1.8 - Built 2015-01-12 11:08 - // Licensed under the MIT license. - // http://buzz.jaysalvat.com/ - // ---------------------------------------------------------------------------- - // Copyright (C) 2010-2015 Jay Salvat - // http://jaysalvat.com/ - // ---------------------------------------------------------------------------- - -(function(context, factory) { - "use strict"; - if (typeof module !== "undefined" && module.exports) { - module.exports = factory(); - } else if (typeof define === "function" && define.amd) { - define([], factory); - } else { - context.buzz = factory(); - } -})(this, function() { - "use strict"; - var AudioContext = window.AudioContext || window.webkitAudioContext; - var buzz = { - audioCtx: window.AudioContext ? new AudioContext() : null, - defaults: { - autoplay: false, - duration: 5e3, - formats: [], - loop: false, - placeholder: "--", - preload: "metadata", - volume: 80, - webAudioApi: false, - document: window.document - }, - types: { - mp3: "audio/mpeg", - ogg: "audio/ogg", - wav: "audio/wav", - aac: "audio/aac", - m4a: "audio/x-m4a" - }, - sounds: [], - el: document.createElement("audio"), - sound: function(src, options) { - options = options || {}; - var doc = options.document || buzz.defaults.document; - var pid = 0, events = [], eventsOnce = {}, supported = buzz.isSupported(); - this.load = function() { - if (!supported) { - return this; - } - this.sound.load(); - return this; - }; - this.play = function() { - if (!supported) { - return this; - } - this.sound.play(); - return this; - }; - this.togglePlay = function() { - if (!supported) { - return this; - } - if (this.sound.paused) { - this.sound.play(); - } else { - this.sound.pause(); - } - return this; - }; - this.pause = function() { - if (!supported) { - return this; - } - this.sound.pause(); - return this; - }; - this.isPaused = function() { - if (!supported) { - return null; - } - return this.sound.paused; - }; - this.stop = function() { - if (!supported) { - return this; - } - this.setTime(0); - this.sound.pause(); - return this; - }; - this.isEnded = function() { - if (!supported) { - return null; - } - return this.sound.ended; - }; - this.loop = function() { - if (!supported) { - return this; - } - this.sound.loop = "loop"; - this.bind("ended.buzzloop", function() { - this.currentTime = 0; - this.play(); - }); - return this; - }; - this.unloop = function() { - if (!supported) { - return this; - } - this.sound.removeAttribute("loop"); - this.unbind("ended.buzzloop"); - return this; - }; - this.mute = function() { - if (!supported) { - return this; - } - this.sound.muted = true; - return this; - }; - this.unmute = function() { - if (!supported) { - return this; - } - this.sound.muted = false; - return this; - }; - this.toggleMute = function() { - if (!supported) { - return this; - } - this.sound.muted = !this.sound.muted; - return this; - }; - this.isMuted = function() { - if (!supported) { - return null; - } - return this.sound.muted; - }; - this.setVolume = function(volume) { - if (!supported) { - return this; - } - if (volume < 0) { - volume = 0; - } - if (volume > 100) { - volume = 100; - } - this.volume = volume; - this.sound.volume = volume / 100; - return this; - }; - this.getVolume = function() { - if (!supported) { - return this; - } - return this.volume; - }; - this.increaseVolume = function(value) { - return this.setVolume(this.volume + (value || 1)); - }; - this.decreaseVolume = function(value) { - return this.setVolume(this.volume - (value || 1)); - }; - this.setTime = function(time) { - if (!supported) { - return this; - } - var set = true; - this.whenReady(function() { - if (set === true) { - set = false; - this.sound.currentTime = time; - } - }); - return this; - }; - this.getTime = function() { - if (!supported) { - return null; - } - var time = Math.round(this.sound.currentTime * 100) / 100; - return isNaN(time) ? buzz.defaults.placeholder : time; - }; - this.setPercent = function(percent) { - if (!supported) { - return this; - } - return this.setTime(buzz.fromPercent(percent, this.sound.duration)); - }; - this.getPercent = function() { - if (!supported) { - return null; - } - var percent = Math.round(buzz.toPercent(this.sound.currentTime, this.sound.duration)); - return isNaN(percent) ? buzz.defaults.placeholder : percent; - }; - this.setSpeed = function(duration) { - if (!supported) { - return this; - } - this.sound.playbackRate = duration; - return this; - }; - this.getSpeed = function() { - if (!supported) { - return null; - } - return this.sound.playbackRate; - }; - this.getDuration = function() { - if (!supported) { - return null; - } - var duration = Math.round(this.sound.duration * 100) / 100; - return isNaN(duration) ? buzz.defaults.placeholder : duration; - }; - this.getPlayed = function() { - if (!supported) { - return null; - } - return timerangeToArray(this.sound.played); - }; - this.getBuffered = function() { - if (!supported) { - return null; - } - return timerangeToArray(this.sound.buffered); - }; - this.getSeekable = function() { - if (!supported) { - return null; - } - return timerangeToArray(this.sound.seekable); - }; - this.getErrorCode = function() { - if (supported && this.sound.error) { - return this.sound.error.code; - } - return 0; - }; - this.getErrorMessage = function() { - if (!supported) { - return null; - } - switch (this.getErrorCode()) { - case 1: - return "MEDIA_ERR_ABORTED"; - - case 2: - return "MEDIA_ERR_NETWORK"; - - case 3: - return "MEDIA_ERR_DECODE"; - - case 4: - return "MEDIA_ERR_SRC_NOT_SUPPORTED"; - - default: - return null; - } - }; - this.getStateCode = function() { - if (!supported) { - return null; - } - return this.sound.readyState; - }; - this.getStateMessage = function() { - if (!supported) { - return null; - } - switch (this.getStateCode()) { - case 0: - return "HAVE_NOTHING"; - - case 1: - return "HAVE_METADATA"; - - case 2: - return "HAVE_CURRENT_DATA"; - - case 3: - return "HAVE_FUTURE_DATA"; - - case 4: - return "HAVE_ENOUGH_DATA"; - - default: - return null; - } - }; - this.getNetworkStateCode = function() { - if (!supported) { - return null; - } - return this.sound.networkState; - }; - this.getNetworkStateMessage = function() { - if (!supported) { - return null; - } - switch (this.getNetworkStateCode()) { - case 0: - return "NETWORK_EMPTY"; - - case 1: - return "NETWORK_IDLE"; - - case 2: - return "NETWORK_LOADING"; - - case 3: - return "NETWORK_NO_SOURCE"; - - default: - return null; - } - }; - this.set = function(key, value) { - if (!supported) { - return this; - } - this.sound[key] = value; - return this; - }; - this.get = function(key) { - if (!supported) { - return null; - } - return key ? this.sound[key] : this.sound; - }; - this.bind = function(types, func) { - if (!supported) { - return this; - } - types = types.split(" "); - var self = this, efunc = function(e) { - func.call(self, e); - }; - for (var t = 0; t < types.length; t++) { - var type = types[t], idx = type; - type = idx.split(".")[0]; - events.push({ - idx: idx, - func: efunc - }); - this.sound.addEventListener(type, efunc, true); - } - return this; - }; - this.unbind = function(types) { - if (!supported) { - return this; - } - types = types.split(" "); - for (var t = 0; t < types.length; t++) { - var idx = types[t], type = idx.split(".")[0]; - for (var i = 0; i < events.length; i++) { - var namespace = events[i].idx.split("."); - if (events[i].idx === idx || namespace[1] && namespace[1] === idx.replace(".", "")) { - this.sound.removeEventListener(type, events[i].func, true); - events.splice(i, 1); - } - } - } - return this; - }; - this.bindOnce = function(type, func) { - if (!supported) { - return this; - } - var self = this; - eventsOnce[pid++] = false; - this.bind(type + "." + pid, function() { - if (!eventsOnce[pid]) { - eventsOnce[pid] = true; - func.call(self); - } - self.unbind(type + "." + pid); - }); - return this; - }; - this.trigger = function(types, detail) { - if (!supported) { - return this; - } - types = types.split(" "); - for (var t = 0; t < types.length; t++) { - var idx = types[t]; - for (var i = 0; i < events.length; i++) { - var eventType = events[i].idx.split("."); - if (events[i].idx === idx || eventType[0] && eventType[0] === idx.replace(".", "")) { - var evt = doc.createEvent("HTMLEvents"); - evt.initEvent(eventType[0], false, true); - evt.originalEvent = detail; - this.sound.dispatchEvent(evt); - } - } - } - return this; - }; - this.fadeTo = function(to, duration, callback) { - if (!supported) { - return this; - } - if (duration instanceof Function) { - callback = duration; - duration = buzz.defaults.duration; - } else { - duration = duration || buzz.defaults.duration; - } - var from = this.volume, delay = duration / Math.abs(from - to), self = this; - this.play(); - function doFade() { - setTimeout(function() { - if (from < to && self.volume < to) { - self.setVolume(self.volume += 1); - doFade(); - } else if (from > to && self.volume > to) { - self.setVolume(self.volume -= 1); - doFade(); - } else if (callback instanceof Function) { - callback.apply(self); - } - }, delay); - } - this.whenReady(function() { - doFade(); - }); - return this; - }; - this.fadeIn = function(duration, callback) { - if (!supported) { - return this; - } - return this.setVolume(0).fadeTo(100, duration, callback); - }; - this.fadeOut = function(duration, callback) { - if (!supported) { - return this; - } - return this.fadeTo(0, duration, callback); - }; - this.fadeWith = function(sound, duration) { - if (!supported) { - return this; - } - this.fadeOut(duration, function() { - this.stop(); - }); - sound.play().fadeIn(duration); - return this; - }; - this.whenReady = function(func) { - if (!supported) { - return null; - } - var self = this; - if (this.sound.readyState === 0) { - this.bind("canplay.buzzwhenready", function() { - func.call(self); - }); - } else { - func.call(self); - } - }; - this.addSource = function(src) { - var self = this, source = doc.createElement("source"); - source.src = src; - if (buzz.types[getExt(src)]) { - source.type = buzz.types[getExt(src)]; - } - this.sound.appendChild(source); - source.addEventListener("error", function(e) { - self.sound.networkState = 3; - self.trigger("sourceerror", e); - }); - return source; - }; - function timerangeToArray(timeRange) { - var array = [], length = timeRange.length - 1; - for (var i = 0; i <= length; i++) { - array.push({ - start: timeRange.start(i), - end: timeRange.end(i) - }); - } - return array; - } - function getExt(filename) { - return filename.split(".").pop(); - } - if (supported && src) { - for (var i in buzz.defaults) { - if (buzz.defaults.hasOwnProperty(i)) { - if (options[i] === undefined) { - options[i] = buzz.defaults[i]; - } - } - } - this.sound = doc.createElement("audio"); - if (options.webAudioApi && buzz.audioCtx) { - this.source = buzz.audioCtx.createMediaElementSource(this.sound); - this.source.connect(buzz.audioCtx.destination); - } - if (src instanceof Array) { - for (var j in src) { - if (src.hasOwnProperty(j)) { - this.addSource(src[j]); - } - } - } else if (options.formats.length) { - for (var k in options.formats) { - if (options.formats.hasOwnProperty(k)) { - this.addSource(src + "." + options.formats[k]); - } - } - } else { - this.addSource(src); - } - if (options.loop) { - this.loop(); - } - if (options.autoplay) { - this.sound.autoplay = "autoplay"; - } - if (options.preload === true) { - this.sound.preload = "auto"; - } else if (options.preload === false) { - this.sound.preload = "none"; - } else { - this.sound.preload = options.preload; - } - this.setVolume(options.volume); - buzz.sounds.push(this); - } - }, - group: function(sounds) { - sounds = argsToArray(sounds, arguments); - this.getSounds = function() { - return sounds; - }; - this.add = function(soundArray) { - soundArray = argsToArray(soundArray, arguments); - for (var a = 0; a < soundArray.length; a++) { - sounds.push(soundArray[a]); - } - }; - this.remove = function(soundArray) { - soundArray = argsToArray(soundArray, arguments); - for (var a = 0; a < soundArray.length; a++) { - for (var i = 0; i < sounds.length; i++) { - if (sounds[i] === soundArray[a]) { - sounds.splice(i, 1); - break; - } - } - } - }; - this.load = function() { - fn("load"); - return this; - }; - this.play = function() { - fn("play"); - return this; - }; - this.togglePlay = function() { - fn("togglePlay"); - return this; - }; - this.pause = function(time) { - fn("pause", time); - return this; - }; - this.stop = function() { - fn("stop"); - return this; - }; - this.mute = function() { - fn("mute"); - return this; - }; - this.unmute = function() { - fn("unmute"); - return this; - }; - this.toggleMute = function() { - fn("toggleMute"); - return this; - }; - this.setVolume = function(volume) { - fn("setVolume", volume); - return this; - }; - this.increaseVolume = function(value) { - fn("increaseVolume", value); - return this; - }; - this.decreaseVolume = function(value) { - fn("decreaseVolume", value); - return this; - }; - this.loop = function() { - fn("loop"); - return this; - }; - this.unloop = function() { - fn("unloop"); - return this; - }; - this.setSpeed = function(speed) { - fn("setSpeed", speed); - return this; - }; - this.setTime = function(time) { - fn("setTime", time); - return this; - }; - this.set = function(key, value) { - fn("set", key, value); - return this; - }; - this.bind = function(type, func) { - fn("bind", type, func); - return this; - }; - this.unbind = function(type) { - fn("unbind", type); - return this; - }; - this.bindOnce = function(type, func) { - fn("bindOnce", type, func); - return this; - }; - this.trigger = function(type) { - fn("trigger", type); - return this; - }; - this.fade = function(from, to, duration, callback) { - fn("fade", from, to, duration, callback); - return this; - }; - this.fadeIn = function(duration, callback) { - fn("fadeIn", duration, callback); - return this; - }; - this.fadeOut = function(duration, callback) { - fn("fadeOut", duration, callback); - return this; - }; - function fn() { - var args = argsToArray(null, arguments), func = args.shift(); - for (var i = 0; i < sounds.length; i++) { - sounds[i][func].apply(sounds[i], args); - } - } - function argsToArray(array, args) { - return array instanceof Array ? array : Array.prototype.slice.call(args); - } - }, - all: function() { - return new buzz.group(buzz.sounds); - }, - isSupported: function() { - return !!buzz.el.canPlayType; - }, - isOGGSupported: function() { - return !!buzz.el.canPlayType && buzz.el.canPlayType('audio/ogg; codecs="vorbis"'); - }, - isWAVSupported: function() { - return !!buzz.el.canPlayType && buzz.el.canPlayType('audio/wav; codecs="1"'); - }, - isMP3Supported: function() { - return !!buzz.el.canPlayType && buzz.el.canPlayType("audio/mpeg;"); - }, - isAACSupported: function() { - return !!buzz.el.canPlayType && (buzz.el.canPlayType("audio/x-m4a;") || buzz.el.canPlayType("audio/aac;")); - }, - toTimer: function(time, withHours) { - var h, m, s; - h = Math.floor(time / 3600); - h = isNaN(h) ? "--" : h >= 10 ? h : "0" + h; - m = withHours ? Math.floor(time / 60 % 60) : Math.floor(time / 60); - m = isNaN(m) ? "--" : m >= 10 ? m : "0" + m; - s = Math.floor(time % 60); - s = isNaN(s) ? "--" : s >= 10 ? s : "0" + s; - return withHours ? h + ":" + m + ":" + s : m + ":" + s; - }, - fromTimer: function(time) { - var splits = time.toString().split(":"); - if (splits && splits.length === 3) { - time = parseInt(splits[0], 10) * 3600 + parseInt(splits[1], 10) * 60 + parseInt(splits[2], 10); - } - if (splits && splits.length === 2) { - time = parseInt(splits[0], 10) * 60 + parseInt(splits[1], 10); - } - return time; - }, - toPercent: function(value, total, decimal) { - var r = Math.pow(10, decimal || 0); - return Math.round(value * 100 / total * r) / r; - }, - fromPercent: function(percent, total, decimal) { - var r = Math.pow(10, decimal || 0); - return Math.round(total / 100 * percent * r) / r; - } - }; - return buzz; -}); \ No newline at end of file diff --git a/vendors/buzz/buzz.min.js b/vendors/buzz/buzz.min.js deleted file mode 100644 index 86cbfec4e..000000000 --- a/vendors/buzz/buzz.min.js +++ /dev/null @@ -1,11 +0,0 @@ - // ---------------------------------------------------------------------------- - // Buzz, a Javascript HTML5 Audio library - // v1.1.8 - Built 2015-01-12 11:08 - // Licensed under the MIT license. - // http://buzz.jaysalvat.com/ - // ---------------------------------------------------------------------------- - // Copyright (C) 2010-2015 Jay Salvat - // http://jaysalvat.com/ - // ---------------------------------------------------------------------------- - -(function(t,e){"use strict";"undefined"!=typeof module&&module.exports?module.exports=e():"function"==typeof define&&define.amd?define([],e):t.buzz=e()})(this,function(){"use strict";var t=window.AudioContext||window.webkitAudioContext,e={audioCtx:window.AudioContext?new t:null,defaults:{autoplay:!1,duration:5e3,formats:[],loop:!1,placeholder:"--",preload:"metadata",volume:80,webAudioApi:!1,document:window.document},types:{mp3:"audio/mpeg",ogg:"audio/ogg",wav:"audio/wav",aac:"audio/aac",m4a:"audio/x-m4a"},sounds:[],el:document.createElement("audio"),sound:function(t,n){function i(t){for(var e=[],n=t.length-1,i=0;n>=i;i++)e.push({start:t.start(i),end:t.end(i)});return e}function u(t){return t.split(".").pop()}n=n||{};var s=n.document||e.defaults.document,r=0,o=[],a={},h=e.isSupported();if(this.load=function(){return h?(this.sound.load(),this):this},this.play=function(){return h?(this.sound.play(),this):this},this.togglePlay=function(){return h?(this.sound.paused?this.sound.play():this.sound.pause(),this):this},this.pause=function(){return h?(this.sound.pause(),this):this},this.isPaused=function(){return h?this.sound.paused:null},this.stop=function(){return h?(this.setTime(0),this.sound.pause(),this):this},this.isEnded=function(){return h?this.sound.ended:null},this.loop=function(){return h?(this.sound.loop="loop",this.bind("ended.buzzloop",function(){this.currentTime=0,this.play()}),this):this},this.unloop=function(){return h?(this.sound.removeAttribute("loop"),this.unbind("ended.buzzloop"),this):this},this.mute=function(){return h?(this.sound.muted=!0,this):this},this.unmute=function(){return h?(this.sound.muted=!1,this):this},this.toggleMute=function(){return h?(this.sound.muted=!this.sound.muted,this):this},this.isMuted=function(){return h?this.sound.muted:null},this.setVolume=function(t){return h?(0>t&&(t=0),t>100&&(t=100),this.volume=t,this.sound.volume=t/100,this):this},this.getVolume=function(){return h?this.volume:this},this.increaseVolume=function(t){return this.setVolume(this.volume+(t||1))},this.decreaseVolume=function(t){return this.setVolume(this.volume-(t||1))},this.setTime=function(t){if(!h)return this;var e=!0;return this.whenReady(function(){e===!0&&(e=!1,this.sound.currentTime=t)}),this},this.getTime=function(){if(!h)return null;var t=Math.round(100*this.sound.currentTime)/100;return isNaN(t)?e.defaults.placeholder:t},this.setPercent=function(t){return h?this.setTime(e.fromPercent(t,this.sound.duration)):this},this.getPercent=function(){if(!h)return null;var t=Math.round(e.toPercent(this.sound.currentTime,this.sound.duration));return isNaN(t)?e.defaults.placeholder:t},this.setSpeed=function(t){return h?(this.sound.playbackRate=t,this):this},this.getSpeed=function(){return h?this.sound.playbackRate:null},this.getDuration=function(){if(!h)return null;var t=Math.round(100*this.sound.duration)/100;return isNaN(t)?e.defaults.placeholder:t},this.getPlayed=function(){return h?i(this.sound.played):null},this.getBuffered=function(){return h?i(this.sound.buffered):null},this.getSeekable=function(){return h?i(this.sound.seekable):null},this.getErrorCode=function(){return h&&this.sound.error?this.sound.error.code:0},this.getErrorMessage=function(){if(!h)return null;switch(this.getErrorCode()){case 1:return"MEDIA_ERR_ABORTED";case 2:return"MEDIA_ERR_NETWORK";case 3:return"MEDIA_ERR_DECODE";case 4:return"MEDIA_ERR_SRC_NOT_SUPPORTED";default:return null}},this.getStateCode=function(){return h?this.sound.readyState:null},this.getStateMessage=function(){if(!h)return null;switch(this.getStateCode()){case 0:return"HAVE_NOTHING";case 1:return"HAVE_METADATA";case 2:return"HAVE_CURRENT_DATA";case 3:return"HAVE_FUTURE_DATA";case 4:return"HAVE_ENOUGH_DATA";default:return null}},this.getNetworkStateCode=function(){return h?this.sound.networkState:null},this.getNetworkStateMessage=function(){if(!h)return null;switch(this.getNetworkStateCode()){case 0:return"NETWORK_EMPTY";case 1:return"NETWORK_IDLE";case 2:return"NETWORK_LOADING";case 3:return"NETWORK_NO_SOURCE";default:return null}},this.set=function(t,e){return h?(this.sound[t]=e,this):this},this.get=function(t){return h?t?this.sound[t]:this.sound:null},this.bind=function(t,e){if(!h)return this;t=t.split(" ");for(var n=this,i=function(t){e.call(n,t)},u=0;t.length>u;u++){var s=t[u],r=s;s=r.split(".")[0],o.push({idx:r,func:i}),this.sound.addEventListener(s,i,!0)}return this},this.unbind=function(t){if(!h)return this;t=t.split(" ");for(var e=0;t.length>e;e++)for(var n=t[e],i=n.split(".")[0],u=0;o.length>u;u++){var s=o[u].idx.split(".");(o[u].idx===n||s[1]&&s[1]===n.replace(".",""))&&(this.sound.removeEventListener(i,o[u].func,!0),o.splice(u,1))}return this},this.bindOnce=function(t,e){if(!h)return this;var n=this;return a[r++]=!1,this.bind(t+"."+r,function(){a[r]||(a[r]=!0,e.call(n)),n.unbind(t+"."+r)}),this},this.trigger=function(t,e){if(!h)return this;t=t.split(" ");for(var n=0;t.length>n;n++)for(var i=t[n],u=0;o.length>u;u++){var r=o[u].idx.split(".");if(o[u].idx===i||r[0]&&r[0]===i.replace(".","")){var a=s.createEvent("HTMLEvents");a.initEvent(r[0],!1,!0),a.originalEvent=e,this.sound.dispatchEvent(a)}}return this},this.fadeTo=function(t,n,i){function u(){setTimeout(function(){t>s&&t>o.volume?(o.setVolume(o.volume+=1),u()):s>t&&o.volume>t?(o.setVolume(o.volume-=1),u()):i instanceof Function&&i.apply(o)},r)}if(!h)return this;n instanceof Function?(i=n,n=e.defaults.duration):n=n||e.defaults.duration;var s=this.volume,r=n/Math.abs(s-t),o=this;return this.play(),this.whenReady(function(){u()}),this},this.fadeIn=function(t,e){return h?this.setVolume(0).fadeTo(100,t,e):this},this.fadeOut=function(t,e){return h?this.fadeTo(0,t,e):this},this.fadeWith=function(t,e){return h?(this.fadeOut(e,function(){this.stop()}),t.play().fadeIn(e),this):this},this.whenReady=function(t){if(!h)return null;var e=this;0===this.sound.readyState?this.bind("canplay.buzzwhenready",function(){t.call(e)}):t.call(e)},this.addSource=function(t){var n=this,i=s.createElement("source");return i.src=t,e.types[u(t)]&&(i.type=e.types[u(t)]),this.sound.appendChild(i),i.addEventListener("error",function(t){n.sound.networkState=3,n.trigger("sourceerror",t)}),i},h&&t){for(var d in e.defaults)e.defaults.hasOwnProperty(d)&&void 0===n[d]&&(n[d]=e.defaults[d]);if(this.sound=s.createElement("audio"),n.webAudioApi&&e.audioCtx&&(this.source=e.audioCtx.createMediaElementSource(this.sound),this.source.connect(e.audioCtx.destination)),t instanceof Array)for(var l in t)t.hasOwnProperty(l)&&this.addSource(t[l]);else if(n.formats.length)for(var c in n.formats)n.formats.hasOwnProperty(c)&&this.addSource(t+"."+n.formats[c]);else this.addSource(t);n.loop&&this.loop(),n.autoplay&&(this.sound.autoplay="autoplay"),this.sound.preload=n.preload===!0?"auto":n.preload===!1?"none":n.preload,this.setVolume(n.volume),e.sounds.push(this)}},group:function(t){function e(){for(var e=n(null,arguments),i=e.shift(),u=0;t.length>u;u++)t[u][i].apply(t[u],e)}function n(t,e){return t instanceof Array?t:Array.prototype.slice.call(e)}t=n(t,arguments),this.getSounds=function(){return t},this.add=function(e){e=n(e,arguments);for(var i=0;e.length>i;i++)t.push(e[i])},this.remove=function(e){e=n(e,arguments);for(var i=0;e.length>i;i++)for(var u=0;t.length>u;u++)if(t[u]===e[i]){t.splice(u,1);break}},this.load=function(){return e("load"),this},this.play=function(){return e("play"),this},this.togglePlay=function(){return e("togglePlay"),this},this.pause=function(t){return e("pause",t),this},this.stop=function(){return e("stop"),this},this.mute=function(){return e("mute"),this},this.unmute=function(){return e("unmute"),this},this.toggleMute=function(){return e("toggleMute"),this},this.setVolume=function(t){return e("setVolume",t),this},this.increaseVolume=function(t){return e("increaseVolume",t),this},this.decreaseVolume=function(t){return e("decreaseVolume",t),this},this.loop=function(){return e("loop"),this},this.unloop=function(){return e("unloop"),this},this.setSpeed=function(t){return e("setSpeed",t),this},this.setTime=function(t){return e("setTime",t),this},this.set=function(t,n){return e("set",t,n),this},this.bind=function(t,n){return e("bind",t,n),this},this.unbind=function(t){return e("unbind",t),this},this.bindOnce=function(t,n){return e("bindOnce",t,n),this},this.trigger=function(t){return e("trigger",t),this},this.fade=function(t,n,i,u){return e("fade",t,n,i,u),this},this.fadeIn=function(t,n){return e("fadeIn",t,n),this},this.fadeOut=function(t,n){return e("fadeOut",t,n),this}},all:function(){return new e.group(e.sounds)},isSupported:function(){return!!e.el.canPlayType},isOGGSupported:function(){return!!e.el.canPlayType&&e.el.canPlayType('audio/ogg; codecs="vorbis"')},isWAVSupported:function(){return!!e.el.canPlayType&&e.el.canPlayType('audio/wav; codecs="1"')},isMP3Supported:function(){return!!e.el.canPlayType&&e.el.canPlayType("audio/mpeg;")},isAACSupported:function(){return!!e.el.canPlayType&&(e.el.canPlayType("audio/x-m4a;")||e.el.canPlayType("audio/aac;"))},toTimer:function(t,e){var n,i,u;return n=Math.floor(t/3600),n=isNaN(n)?"--":n>=10?n:"0"+n,i=e?Math.floor(t/60%60):Math.floor(t/60),i=isNaN(i)?"--":i>=10?i:"0"+i,u=Math.floor(t%60),u=isNaN(u)?"--":u>=10?u:"0"+u,e?n+":"+i+":"+u:i+":"+u},fromTimer:function(t){var e=(""+t).split(":");return e&&3===e.length&&(t=3600*parseInt(e[0],10)+60*parseInt(e[1],10)+parseInt(e[2],10)),e&&2===e.length&&(t=60*parseInt(e[0],10)+parseInt(e[1],10)),t},toPercent:function(t,e,n){var i=Math.pow(10,n||0);return Math.round(100*t/e*i)/i},fromPercent:function(t,e,n){var i=Math.pow(10,n||0);return Math.round(e/100*t*i)/i}};return e}); \ No newline at end of file diff --git a/vendors/ckeditor-plugins/signature/plugin.js b/vendors/ckeditor-plugins/signature/plugin.js index 68777a7ae..31ff05e1d 100644 --- a/vendors/ckeditor-plugins/signature/plugin.js +++ b/vendors/ckeditor-plugins/signature/plugin.js @@ -4,50 +4,52 @@ rl_signature_replacer = function (editor, sText, sSignature, bHtml, bInsertBefor if (!bHtml) { sText = sText - .replace(/\u200C\u200C/g, '\u0002\u0002') - .replace(/\u200D\u200D/g, '\u0003\u0003') + .replace(/\u200C([\s\S]*)\u200C/g, '\u0002$1\u0002') + .replace(/\u200C/g, '') ; } var - sTextWithoutSignature = sText - .replace(/\u0002\u0002[\s\S]*\u0002\u0002/gm, '') - .replace(/\u0003\u0003[\s\S]*\u0003\u0003/gm, ''), - bEmptyText = '' === $.trim(sTextWithoutSignature), + sP = '~~~~@~~~~', + bEmptyText = false, sNewLine = (bHtml ? '
' : "\n") ; + sText = sText.replace(/\u0002([\s\S]*)\u0002/gm, sP + '$1' + sP); + + if (editor.__previos_signature) + { + sText = sText + .replace(sP + editor.__previos_signature + sP, '') + .replace(sP + editor.__previos_signature + sP, '') + .replace(sP + editor.__previos_signature + sP, '') + ; + } + + sText = sText.replace(sP, '').replace(sP, '').replace(sP, '').replace(sP, ''); + + bEmptyText = '' === $.trim(sText); if (!bEmptyText && bHtml) { - bEmptyText = '' !== $.trim(editor.__plainUtils.htmlToPlain(sTextWithoutSignature)); - } - - if (!/\u0002\u0002/gm.test(sText)) - { - sText = "\u0002\u0002\u0002\u0002" + sText; - } - - if (!/\u0003\u0003/gm.test(sText)) - { - sText = sText + "\u0003\u0003\u0003\u0003"; + bEmptyText = '' !== $.trim(editor.__plainUtils.htmlToPlain(sText)); } if (bInsertBefore) { - sText = sText.replace(/\u0002\u0002[\s\S]*\u0002\u0002/gm, "\u0002\u0002" + sSignature + (bEmptyText ? '' : sNewLine) + "\u0002\u0002"); - sText = sText.replace(/\u0003\u0003[\s\S]*\u0003\u0003/gm, "\u0003\u0003\u0003\u0003"); + sText = "\u0002" + sSignature + (bEmptyText ? '' : sNewLine) + "\u0002" + sText; + editor.__previos_signature = sSignature + (bEmptyText ? '' : sNewLine); } else { - sText = sText.replace(/\u0002\u0002[\s\S]*\u0002\u0002/gm, "\u0002\u0002\u0002\u0002"); - sText = sText.replace(/\u0003\u0003[\s\S]*\u0003\u0003/gm, "\u0003\u0003" + (bEmptyText ? '' : sNewLine) + sSignature + "\u0003\u0003"); + sText = sText + "\u0002" + (bEmptyText ? '' : sNewLine) + sSignature + "\u0002"; + editor.__previos_signature = (bEmptyText ? '' : sNewLine) + sSignature; } if (!bHtml) { sText = sText - .replace(/\u0002\u0002/g, '\u200C\u200C') - .replace(/\u0003\u0003/g, '\u200D\u200D') + .replace(/\u0002([\s\S]*)\u0002/g, '\u200C$1\u200C') + .replace(/\u0002/g, '') ; } @@ -90,8 +92,7 @@ CKEDITOR.plugins.add('signature', { } editor.__plain.setRawData( - rl_signature_replacer(editor, - editor.__plain.getRawData(), sResultSignature, false, bInsertBefore)); + rl_signature_replacer(editor, editor.__plain.getRawData(), sResultSignature, false, bInsertBefore)); } else @@ -105,8 +106,7 @@ CKEDITOR.plugins.add('signature', { } editor.setData( - rl_signature_replacer(editor, - editor.getData(), sResultSignature, true, bInsertBefore)); + rl_signature_replacer(editor, editor.getData(), sResultSignature, true, bInsertBefore)); } } catch (e) {} diff --git a/vendors/flags/flags-fixed.css b/vendors/flags/flags-fixed.css index 799431bbc..2402e12e0 100644 --- a/vendors/flags/flags-fixed.css +++ b/vendors/flags/flags-fixed.css @@ -17,6 +17,7 @@ .flag.flag-en-uk {background-position: -176px -44px} .flag.flag-en-ca {background-position: -48px -22px} +.flag.flag-ar, .flag.flag-ar-ar {background-position: -160px 0} .flag.flag-bg, .flag.flag-bg-bg {background-position: -80px -11px} .flag.flag-nl, .flag.flag-nl-nl {background-position: -80px -110px} .flag.flag-pl, .flag.flag-pl-pl {background-position: -32px -121px} diff --git a/vendors/fontastic/fonts/rainloop.eot b/vendors/fontastic/fonts/rainloop.eot index cb64d4537..d2bf0d541 100644 Binary files a/vendors/fontastic/fonts/rainloop.eot and b/vendors/fontastic/fonts/rainloop.eot differ diff --git a/vendors/fontastic/fonts/rainloop.svg b/vendors/fontastic/fonts/rainloop.svg index 3357f3364..cc66a0e77 100644 --- a/vendors/fontastic/fonts/rainloop.svg +++ b/vendors/fontastic/fonts/rainloop.svg @@ -122,4 +122,5 @@ + diff --git a/vendors/fontastic/fonts/rainloop.ttf b/vendors/fontastic/fonts/rainloop.ttf index 3cc1d79cc..09186ead5 100644 Binary files a/vendors/fontastic/fonts/rainloop.ttf and b/vendors/fontastic/fonts/rainloop.ttf differ diff --git a/vendors/fontastic/fonts/rainloop.woff b/vendors/fontastic/fonts/rainloop.woff index 3ff6793d9..a7d4ab38c 100644 Binary files a/vendors/fontastic/fonts/rainloop.woff and b/vendors/fontastic/fonts/rainloop.woff differ diff --git a/vendors/fontastic/icons-reference.html b/vendors/fontastic/icons-reference.html index 7132f5af8..94b3b7e95 100644 --- a/vendors/fontastic/icons-reference.html +++ b/vendors/fontastic/icons-reference.html @@ -505,6 +505,10 @@ h2{font-size:18px;padding:0 0 21px 5px;margin:45px 0 0 0;text-transform:uppercas
+
  • +
    + +
  • Character mapping

      @@ -968,6 +972,10 @@ h2{font-size:18px;padding:0 0 21px 5px;margin:45px 0 0 0;text-transform:uppercas
      +
    • +
      + +
    + + diff --git a/vendors/fontastic/svg/icons.svg b/vendors/fontastic/svg/icons.svg new file mode 100644 index 000000000..b4b44d0c3 --- /dev/null +++ b/vendors/fontastic/svg/icons.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendors/is.js/README.md b/vendors/is.js/README.md deleted file mode 100644 index b42f00deb..000000000 --- a/vendors/is.js/README.md +++ /dev/null @@ -1,2327 +0,0 @@ -is.js -===== -####This is a general-purpose check library. -- No dependencies -- AMD, Node & browser ready - -Node.js: -``` -npm install is_js -``` - -Bower: -``` -bower install is_js -``` - -Type checks -=========== - -is.arguments(value:any) ------------------------ -####Checks if the given value type is arguments. -interfaces: not, all, any - -```javascript -var getArguments = function() { - return arguments; -}; -var arguments = getArguments(); - -is.arguments(arguments); -=> true - -is.not.arguments({foo: 'bar'}); -=> true - -is.all.arguments(arguments, 'bar'); -=> false - -is.any.arguments(['foo'], arguments); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.arguments([arguments, 'foo', 'bar']); -=> false -``` - -is.array(value:any) -------------------- -####Checks if the given value type is array. -interfaces: not, all, any - -```javascript -is.array(['foo', 'bar', 'baz']); -=> true - -is.not.array({foo: 'bar'}); -=> true - -is.all.array(['foo'], 'bar'); -=> false - -is.any.array(['foo'], 'bar'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.array([[1, 2], 'foo', 'bar']); -=> false -``` - -is.boolean(value:any) ---------------------- -####Checks if the given value type is boolean. -interfaces: not, all, any - -```javascript -is.boolean(true); -=> true - -is.not.boolean({foo: 'bar'}); -=> true - -is.all.boolean(true, 'bar'); -=> false - -is.any.boolean(true, 'bar'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.boolean([true, 'foo', 'bar']); -=> false -``` - -is.date(value:any) ------------------- -####Checks if the given value type is date. -interfaces: not, all, any - -```javascript -is.date(new Date()); -=> true - -is.not.date({foo: 'bar'}); -=> true - -is.all.date(new Date(), 'bar'); -=> false - -is.any.date(new Date(), 'bar'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.date([new Date(), 'foo', 'bar']); -=> false -``` - -is.error(value:any) -------------------- -####Checks if the given value type is error. -interfaces: not, all, any - -```javascript -is.error(new Error()); -=> true - -is.not.error({foo: 'bar'}); -=> true - -is.all.error(new Error(), 'bar'); -=> false - -is.any.error(new Error(), 'bar'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.error([new Error(), 'foo', 'bar']); -=> false -``` - -is.function(value:any) ----------------------- -####Checks if the given value type is function. -interfaces: not, all, any - -```javascript -is.function(toString); -=> true - -is.not.function({foo: 'bar'}); -=> true - -is.all.function(toString, 'bar'); -=> false - -is.any.function(toString, 'bar'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.function([toString, 'foo', 'bar']); -=> false -``` - -is.nan(value:any) ------------------ -####Checks if the given value type is NaN. -interfaces: not, all, any - -```javascript -is.nan(NaN); -=> true - -is.not.nan(42); -=> true - -is.all.nan(NaN, 1); -=> false - -is.any.nan(NaN, 2); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.nan([NaN, 'foo', 1]); -=> false -``` - -is.null(value:any) ------------------- -####Checks if the given value type is null. -interfaces: not, all, any - -```javascript -is.null(null); -=> true - -is.not.null(42); -=> true - -is.all.null(null, 1); -=> false - -is.any.null(null, 2); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.null([null, 'foo', 1]); -=> false -``` - -is.number(value:any) --------------------- -####Checks if the given value type is number. -interfaces: not, all, any - -```javascript -is.number(42); -=> true - -is.not.number('42'); -=> true - -is.all.number('foo', 1); -=> false - -is.any.number({}, 2); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.number([42, 'foo', 1]); -=> false -``` - -is.object(value:any) --------------------- -####Checks if the given value type is object. -interfaces: not, all, any - -```javascript -is.object({foo: 'bar'}); -=> true - -// functions are also returning as true -is.object(toString); -=> true - -is.not.object('foo'); -=> true - -is.all.object({}, 1); -=> false - -is.any.object({}, 2); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.object([{}, new Object()]); -=> true -``` - -is.json(value:any) --------------------- -####Checks if the given value type is pure json object. -interfaces: not, all, any - -```javascript -is.json({foo: 'bar'}); -=> true - -// functions are returning as false -is.json(toString); -=> false - -is.not.json([]); -=> true - -is.all.json({}, 1); -=> false - -is.any.json({}, 2); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.json([{}, {foo: 'bar'}]); -=> true -``` - -is.regexp(value:any) --------------------- -####Checks if the given value type is RegExp. -interfaces: not, all, any - -```javascript -is.regexp(/test/); -=> true - -is.not.regexp(['foo']); -=> true - -is.all.regexp(/test/, 1); -=> false - -is.any.regexp(new RegExp('ab+c'), 2); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.regexp([{}, /test/]); -=> false -``` - -is.string(value:any) --------------------- -####Checks if the given value type is string. -interfaces: not, all, any - -```javascript -is.string('foo'); -=> true - -is.not.string(['foo']); -=> true - -is.all.string('foo', 1); -=> false - -is.any.string('foo', 2); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.string([{}, 'foo']); -=> false -``` - -is.char(value:any) --------------------- -####Checks if the given value type is char. -interfaces: not, all, any - -```javascript -is.char('f'); -=> true - -is.not.char(['foo']); -=> true - -is.all.char('f', 1); -=> false - -is.any.char('f', 2); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.char(['f', 'o', 'o']); -=> true -``` - -is.undefined(value:any) ------------------------ -####Checks if the given value type is undefined. -interfaces: not, all, any - -```javascript -is.undefined(undefined); -=> true - -is.not.undefined(null); -=> true - -is.all.undefined(undefined, 1); -=> false - -is.any.undefined(undefined, 2); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.undefined([{}, undefined]); -=> false -``` - -is.sameType(value:any, value:any) ---------------------------------- -####Checks if the given value types are same type. -interface: not - -```javascript -is.sameType(42, 7); -=> true - -is.sameType(42, '7'); -=> false - -is.not.sameType(42, 7); -=> false -``` - -Presence checks -=============== - -is.empty(value:object|array|string) ------------------------------------ -####Checks if the given value is empty. -interfaces: not, all, any - -```javascript -is.empty({}); -=> true - -is.empty([]); -=> true - -is.empty(''); -=> true - -is.not.empty(['foo']); -=> true - -is.all.empty('', {}, ['foo']); -=> false - -is.any.empty([], 42); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.empty([{}, 'foo']); -=> false -``` - -is.existy(value:any) --------------------- -####Checks if the given value is existy. (not null or undefined) -interfaces: not, all, any - -```javascript -is.existy({}); -=> true - -is.existy(null); -=> false - -is.not.existy(undefined); -=> true - -is.all.existy(null, ['foo']); -=> false - -is.any.existy(undefined, 42); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.existy([{}, 'foo']); -=> true -``` - -is.truthy(value:any) --------------------- -####Checks if the given value is truthy. (existy and not false) -interfaces: not, all, any - -```javascript -is.truthy(true); -=> true - -is.truthy(null); -=> false - -is.not.truthy(false); -=> true - -is.all.truthy(null, true); -=> false - -is.any.truthy(undefined, true); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.truthy([{}, true]); -=> true -``` - -is.falsy(value:any) -------------------- -####Checks if the given value is falsy. -interfaces: not, all, any - -```javascript -is.falsy(false); -=> true - -is.falsy(null); -=> true - -is.not.falsy(true); -=> true - -is.all.falsy(null, false); -=> true - -is.any.falsy(undefined, true); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.falsy([false, true, undefined]); -=> false -``` - -is.space(value:string) ----------------------- -####Checks if the given value is space. -interfaces: not, all, any - -```javascript -is.space(' '); -=> true - -is.space('foo'); -=> false - -is.not.space(true); -=> true - -is.all.space(' ', 'foo'); -=> false - -is.any.space(' ', true); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.space([' ', 'foo', undefined]); -=> false -``` - -RegExp checks -============= - -is.url(value:any) ------------------ -####Checks if the given value matches url regexp. -interfaces: not, all, any - -```javascript -is.url('http://www.test.com'); -=> true - -is.url('foo'); -=> false - -is.not.url(true); -=> true - -is.all.url('http://www.test.com', 'foo'); -=> false - -is.any.url('http://www.test.com', true); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.url(['http://www.test.com', 'foo', undefined]); -=> false -``` - -is.email(value:any) -------------------- -####Checks if the given value matches email regexp. -interfaces: not, all, any - -```javascript -is.email('test@test.com'); -=> true - -is.email('foo'); -=> false - -is.not.email('foo'); -=> true - -is.all.email('test@test.com', 'foo'); -=> false - -is.any.email('test@test.com', 'foo'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.email(['test@test.com', 'foo', undefined]); -=> false -``` - -is.creditCard(value:any) ------------------------- -####Checks if the given value matches credit card regexp. -interfaces: not, all, any - -```javascript -is.creditCard(378282246310005); -=> true - -is.creditCard(123); -=> false - -is.not.creditCard(123); -=> true - -is.all.creditCard(378282246310005, 123); -=> false - -is.any.creditCard(378282246310005, 123); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.creditCard([378282246310005, 123, undefined]); -=> false -``` - -is.alphaNumeric(value:any) --------------------------- -####Checks if the given value matches alpha numeric regexp. -interfaces: not, all, any - -```javascript -is.alphaNumeric('alphaNu3er1k'); -=> true - -is.alphaNumeric('*?'); -=> false - -is.not.alphaNumeric('*?'); -=> true - -is.all.alphaNumeric('alphaNu3er1k', '*?'); -=> false - -is.any.alphaNumeric('alphaNu3er1k', '*?'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.alphaNumeric(['alphaNu3er1k', '*?']); -=> false -``` - -is.timeString(value:any) ------------------------- -####Checks if the given value matches time string regexp. -interfaces: not, all, any - -```javascript -is.timeString('13:45:30'); -=> true - -is.timeString('90:90:90'); -=> false - -is.not.timeString('90:90:90'); -=> true - -is.all.timeString('13:45:30', '90:90:90'); -=> false - -is.any.timeString('13:45:30', '90:90:90'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.timeString(['13:45:30', '90:90:90']); -=> false -``` - -is.dateString(value:any) ------------------------- -####Checks if the given value matches date string regexp. -interfaces: not, all, any - -```javascript -is.dateString('11/11/2011'); -=> true - -is.dateString('90/11/2011'); -=> false - -is.not.dateString('90/11/2011'); -=> true - -is.all.dateString('11/11/2011', '90/11/2011'); -=> false - -is.any.dateString('11/11/2011', '90/11/2011'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.dateString(['11/11/2011', '90/11/2011']); -=> false -``` - -is.usZipCode(value:any) ------------------------ -####Checks if the given value matches US zip code regexp. -interfaces: not, all, any - -```javascript -is.usZipCode('02201-1020'); -=> true - -is.usZipCode('123'); -=> false - -is.not.usZipCode('123'); -=> true - -is.all.usZipCode('02201-1020', '123'); -=> false - -is.any.usZipCode('02201-1020', '123'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.usZipCode(['02201-1020', '123']); -=> false -``` - -is.caPostalCode(value:any) --------------------------- -####Checks if the given value matches Canada postal code regexp. -interfaces: not, all, any - -```javascript -is.caPostalCode('L8V3Y1'); -=> true - -is.caPostalCode('L8V 3Y1'); -=> true - -is.caPostalCode('123'); -=> false - -is.not.caPostalCode('123'); -=> true - -is.all.caPostalCode('L8V3Y1', '123'); -=> false - -is.any.caPostalCode('L8V3Y1', '123'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.caPostalCode(['L8V3Y1', '123']); -=> false -``` - -is.ukPostCode(value:any) ------------------------- -####Checks if the given value matches UK post code regexp. -interfaces: not, all, any - -```javascript -is.ukPostCode('B184BJ'); -=> true - -is.ukPostCode('123'); -=> false - -is.not.ukPostCode('123'); -=> true - -is.all.ukPostCode('B184BJ', '123'); -=> false - -is.any.ukPostCode('B184BJ', '123'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.ukPostCode(['B184BJ', '123']); -=> false -``` - -is.nanpPhone(value:any) ------------------------ -####Checks if the given value matches North American numbering plan phone regexp. -interfaces: not, all, any - -```javascript -is.nanpPhone('609-555-0175'); -=> true - -is.nanpPhone('123'); -=> false - -is.not.nanpPhone('123'); -=> true - -is.all.nanpPhone('609-555-0175', '123'); -=> false - -is.any.nanpPhone('609-555-0175', '123'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.nanpPhone(['609-555-0175', '123']); -=> false -``` - -is.eppPhone(value:any) ----------------------- -####Checks if the given value matches extensible provisioning protocol phone regexp. -interfaces: not, all, any - -```javascript -is.eppPhone('+90.2322456789'); -=> true - -is.eppPhone('123'); -=> false - -is.not.eppPhone('123'); -=> true - -is.all.eppPhone('+90.2322456789', '123'); -=> false - -is.any.eppPhone('+90.2322456789', '123'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.eppPhone(['+90.2322456789', '123']); -=> false -``` - -is.socialSecurityNumber(value:any) ----------------------------------- -####Checks if the given value matches social security number regexp. -interfaces: not, all, any - -```javascript -is.socialSecurityNumber('017-90-7890'); -=> true - -is.socialSecurityNumber('123'); -=> false - -is.not.socialSecurityNumber('123'); -=> true - -is.all.socialSecurityNumber('017-90-7890', '123'); -=> false - -is.any.socialSecurityNumber('017-90-7890', '123'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.socialSecurityNumber(['017-90-7890', '123']); -=> false -``` - -is.affirmative(value:any) -------------------------- -####Checks if the given value matches affirmative regexp. -interfaces: not, all, any - -```javascript -is.affirmative('yes'); -=> true - -is.affirmative('no'); -=> false - -is.not.affirmative('no'); -=> true - -is.all.affirmative('yes', 'no'); -=> false - -is.any.affirmative('yes', 'no'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.affirmative(['yes', 'y', 'true', 't', 'ok', 'okay']); -=> true -``` - -is.hexadecimal(value:any) -------------------------- -####Checks if the given value matches hexadecimal regexp. -interfaces: not, all, any - -```javascript -is.hexadecimal('f0f0f0'); -=> true - -is.hexadecimal(2.5); -=> false - -is.not.hexadecimal('string'); -=> true - -is.all.hexadecimal('ff', 'f50'); -=> true - -is.any.hexadecimal('ff5500', true); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.hexadecimal(['fff', '333', 'f50']); -=> true -``` - -is.hexColor(value:any) -------------------------- -####Checks if the given value matches hexcolor regexp. -interfaces: not, all, any - -```javascript -is.hexColor('#333'); -=> true - -is.hexColor('#3333'); -=> false - -is.not.hexColor(0.5); -=> true - -is.all.hexColor('fff', 'f50'); -=> true - -is.any.hexColor('ff5500', 0.5); -=> false - -// 'all' and 'any' interfaces can also take array parameter -is.all.hexColor(['fff', '333', 'f50']); -=> true -``` - -is.ip(value:string) -------------------------- -####Checks if the given value matches ip regexp -interfaces: not, all, any - -```javascript -is.ip('198.156.23.5'); -=> true - -is.ip('1.2..5'); -=> false - -is.not.ip('8:::::::7'); -=> true - -is.all.ip('0:1::4:ff5:54:987:C', '123.123.123.123'); -=> true - -is.any.ip('123.8.4.3', '0.0.0.0'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.ip(['123.123.23.12', 'A:B:C:D:E:F:0:0']); -=> true -``` - -is.ipv4(value:string) -------------------------- -####Checks if the given value matches ipv4 regexp -interfaces: not, all, any - -```javascript -is.ipv4('198.12.3.142'); -=> true - -is.ipv4('1.2..5'); -=> false - -is.not.ipv4('8:::::::7'); -=> true - -is.all.ipv4('198.12.3.142', '123.123.123.123'); -=> true - -is.any.ipv4('255.255.255.255', '850..1.4'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.ipv4(['198.12.3.142', '1.2.3']); -=> false - -``` - -is.ipv6(value:string) -------------------------- -####Checks if the given value matches ipv6 regexp -interfaces: not, all, any - -```javascript -is.ipv6('2001:DB8:0:0:1::1'); -=> true - -is.ipv6('985.12.3.4'); -=> true - -is.not.ipv6('8:::::::7'); -=> true - -is.all.ipv6('2001:DB8:0:0:1::1', '1:50:198:2::1:2:8'); -=> true - -is.any.ipv6('255.255.255.255', '2001:DB8:0:0:1::1'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.ipv6(['2001:DB8:0:0:1::1', '1.2.3']); -=> false -``` - -String checks -============= - -is.include(value:string, value:substring) ------------------------------------------ -####Checks if the given string contains a substring. -interface: not - -```javascript -is.include('Some text goes here', 'text'); -=> true - -is.include('test', 'text'); -=> false - -is.not.include('test', 'text'); -=> true -``` - -is.upperCase(value:string) --------------------------- -####Checks if the given string is UPPERCASE. -interfaces: not, all, any - -```javascript -is.upperCase('YEAP'); -=> true - -is.upperCase('nope'); -=> false - -is.not.upperCase('Nope'); -=> true - -is.all.upperCase('YEAP', 'nope'); -=> false - -is.any.upperCase('YEAP', 'nope'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.upperCase(['YEAP', 'ALL UPPERCASE']); -=> true -``` - - -is.lowerCase(value:string) --------------------------- -####Checks if the given string is lowercase. -interfaces: not, all, any - -```javascript -is.lowerCase('yeap'); -=> true - -is.lowerCase('NOPE'); -=> false - -is.not.lowerCase('Nope'); -=> true - -is.all.lowerCase('yeap', 'NOPE'); -=> false - -is.any.lowerCase('yeap', 'NOPE'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.lowerCase(['yeap', 'all lowercase']); -=> true -``` - -is.startWith(value:string, value:substring) -------------------------------------------- -####Checks if the given string starts with substring. -interface: not - -```javascript -is.startWith('yeap', 'ye'); -=> true - -is.startWith('nope', 'ye'); -=> false - -is.not.startWith('nope not that', 'not'); -=> true -``` - -is.endWith(value:string, value:substring) ------------------------------------------ -####Checks if the given string ends with substring. -interfaces: not - -```javascript -is.endWith('yeap', 'ap'); -=> true - -is.endWith('nope', 'no'); -=> false - -is.not.endWith('nope not that', 'not'); -=> true - -is.endWith('yeap that one', 'one'); -=> true -``` - -is.capitalized(value:string, value:substring) ---------------------------------------------- -####Checks if the given string is capitalized. -interfaces: not, all, any - -```javascript -is.capitalized('Yeap'); -=> true - -is.capitalized('nope'); -=> false - -is.not.capitalized('nope not capitalized'); -=> true - -is.not.capitalized('nope Capitalized'); -=> true - -is.all.capitalized('Yeap', 'All', 'Capitalized'); -=> true - -is.any.capitalized('Yeap', 'some', 'Capitalized'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.capitalized(['Nope', 'not']); -=> false -``` - -is.palindrome(value:string, value:substring) ---------------------------------------------- -####Checks if the given string is palindrome. -interfaces: not, all, any - -```javascript -is.palindrome('testset'); -=> true - -is.palindrome('nope'); -=> false - -is.not.palindrome('nope not palindrome'); -=> true - -is.not.palindrome('tt'); -=> false - -is.all.palindrome('testset', 'tt'); -=> true - -is.any.palindrome('Yeap', 'some', 'testset'); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.palindrome(['Nope', 'testset']); -=> false -``` - -Arithmetic checks -================= - -is.equal(value:any, value:any) ------------------------------- -####Checks if the given values are equal. -interfaces: not - -```javascript -is.equal(42, 40 + 2); -=> true - -is.equal('yeap', 'yeap'); -=> true - -is.equal(true, true); -=> true - -is.not.equal('yeap', 'nope'); -=> true -``` - -is.even(value:number) ---------------------- -####Checks if the given value is even. -interfaces: not, all, any - -```javascript -is.even(42); -=> true - -is.not.even(41); -=> true - -is.all.even(40, 42, 44); -=> true - -is.any.even(39, 42, 43); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.even([40, 42, 43]); -=> false -``` - -is.odd(value:number) --------------------- -####Checks if the given value is odd. -interfaces: not, all, any - -```javascript -is.odd(41); -=> true - -is.not.odd(42); -=> true - -is.all.odd(39, 41, 43); -=> true - -is.any.odd(39, 42, 44); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.odd([40, 42, 43]); -=> false -``` - -is.positive(value:number) -------------------------- -####Checks if the given value is positive. -interfaces: not, all, any - -```javascript -is.positive(41); -=> true - -is.not.positive(-42); -=> true - -is.all.positive(39, 41, 43); -=> true - -is.any.positive(-39, 42, -44); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.positive([40, 42, -43]); -=> false -``` - -is.negative(value:number) -------------------------- -####Checks if the given value is negative. -interfaces: not, all, any - -```javascript -is.negative(-41); -=> true - -is.not.negative(42); -=> true - -is.all.negative(-39, -41, -43); -=> true - -is.any.negative(-39, 42, 44); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.negative([40, 42, -43]); -=> false -``` - -is.above(value:number, min) ---------------------------- -####Checks if the given value is above minimum value. -interface: not - -```javascript -is.above(41, 30); -=> true - -is.not.above(42, 50); -=> true -``` - -is.under(value:number, min) ---------------------------- -####Checks if the given value is under maximum value. -interface: not - -```javascript -is.under(30, 35); -=> true - -is.not.under(42, 30); -=> true -``` - -is.within(value:number, min, max) ---------------------------------- -####Checks if the given value is within minimum and maximum values. -interface: not - -```javascript -is.within(30, 20, 40); -=> true - -is.not.within(40, 30, 35); -=> true -``` - -is.decimal(value:number) ------------------------- -####Checks if the given value is decimal. -interfaces: not, all, any - -```javascript -is.decimal(41.5); -=> true - -is.not.decimal(42); -=> true - -is.all.decimal(39.5, 41.5, -43.5); -=> true - -is.any.decimal(-39, 42.5, 44); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.decimal([40, 42.5, -43]); -=> false -``` - -is.integer(value:number) ------------------------- -####Checks if the given value is integer. -interfaces: not, all, any - -```javascript -is.integer(41); -=> true - -is.not.integer(42.5); -=> true - -is.all.integer(39, 41, -43); -=> true - -is.any.integer(-39, 42.5, 44); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.integer([40, 42.5, -43]); -=> false -``` - -is.finite(value:number) ------------------------ -####Checks if the given value is finite. -interfaces: not, all, any - -```javascript -is.finite(41); -=> true - -is.not.finite(42 / 0); -=> true - -is.all.finite(39, 41, -43); -=> true - -is.any.finite(-39, Infinity, 44); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.finite([Infinity, -Infinity, 42.5]); -=> false -``` - -is.infinite(value:number) -------------------------- -####Checks if the given value is infinite. -interfaces: not, all, any - -```javascript -is.infinite(Infinity); -=> true - -is.not.infinite(42); -=> true - -is.all.infinite(Infinity, -Infinity, -43 / 0); -=> true - -is.any.infinite(-39, Infinity, 44); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.infinite([Infinity, -Infinity, 42.5]); -=> false -``` - -Object checks -============= - -is.propertyCount(value:object, count) -------------------------------------- -####Checks if objects' property count is equal to given count. -interface: not - -```javascript -is.propertyCount({this: 'is', 'sample': object}, 2); -=> true - -is.propertyCount({this: 'is', 'sample': object}, 3); -=> false - -is.not.propertyCount({}, 2); -=> true -``` - -is.propertyDefined(value:object, property) ------------------------------------------- -####Checks if the given property is defined on object. -interface: not - -```javascript -is.propertyDefined({yeap: 'yeap'}, 'yeap'); -=> true - -is.propertyDefined({yeap: 'yeap'}, 'nope'); -=> false - -is.not.propertyDefined({}, 'nope'); -=> true -``` - -is.windowObject(value:window) ------------------------------ -####Checks if the given object is window object. -interfaces: not, all, any - -```javascript -is.windowObject(window); -=> true - -is.windowObject({nope: 'nope'}); -=> false - -is.not.windowObject({}); -=> true - -is.all.windowObject(window, {nope: 'nope'}); -=> false - -is.any.windowObject(window, {nope: 'nope'}); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.windowObject([window, {nope: 'nope'}]); -=> false -``` - -is.domNode(value:object) ------------------------------ -####Checks if the given object is a dom node. -interfaces: not, all, any - -```javascript -var obj = document.createElement('div'); -is.domNode(obj); -=> true - -is.domNode({nope: 'nope'}); -=> false - -is.not.domNode({}); -=> true - -is.all.domNode(obj, obj); -=> true - -is.any.domNode(obj, {nope: 'nope'}); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.domNode([obj, {nope: 'nope'}]); -=> false -``` - -Array checks -============ - -is.inArray(value:any, array) ---------------------- -####Checks if the given item is in array? -interface: not -```javascript -is.inArray(2, [1, 2, 3]); -=> true - -is.inArray(4, [1, 2, 3]); -=> false - -is.not.inArray(4, [1, 2, 3]); -=> true -``` - -is.sorted(value:array) ----------------------- -####Checks if the given array is sorted. -interfaces: not, all, any - -```javascript -is.sorted([1, 2, 3]); -=> true - -is.sorted([1, 2, 4, 3]); -=> false - -is.not.sorted([5, 4, 3]); -=> true - -is.all.sorted([1, 2], [3, 4]); -=> true - -is.any.sorted([1, 2], [5, 4]); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.sorted([[1, 2], [5, 4]]); -=> false -``` - -Environment checks -================== -####Environment checks are not available as node module. - -is.ie(value:number) -------------------- -####Checks if current browser is ie. Parameter is optional version number of browser. -interface: not - -```javascript -is.ie(); -=> true if current browser is ie - -is.ie(6); -=> hopefully false - -is.not.ie(); -=> false if current browser is ie -``` - -is.chrome() ------------ -####Checks if current browser is chrome. -interface: not - -```javascript -is.chrome(); -=> true if current browser is chrome - -is.not.chrome(); -=> false if current browser is chrome -``` - -is.firefox() ------------- -####Checks if current browser is firefox. -interface: not - -```javascript -is.firefox(); -=> true if current browser is firefox - -is.not.firefox(); -=> false if current browser is firefox -``` - -is.opera() ----------- -####Checks if current browser is opera. -interface: not - -```javascript -is.opera(); -=> true if current browser is opera - -is.not.opera(); -=> false if current browser is opera -``` - -is.safari() ------------ -####Checks if current browser is safari. -interface: not - -```javascript -is.safari(); -=> true if current browser is safari - -is.not.safari(); -=> false if current browser is safari -``` - -is.ios() --------- -####Checks if current device has ios. -interface: not - -```javascript -is.ios(); -=> true if current device is iPhone, iPad or iPod - -is.not.ios(); -=> true if current device is not iPhone, iPad or iPod -``` - -is.iphone() ------------ -####Checks if current device is iPhone. -interface: not - -```javascript -is.iphone(); -=> true if current device is iPhone - -is.not.iphone(); -=> true if current device is not iPhone -``` - -is.ipad() ---------- -####Checks if current device is iPad. -interface: not - -```javascript -is.ipad(); -=> true if current device is iPad - -is.not.ipad(); -=> true if current device is not iPad -``` - -is.ipod() ---------- -####Checks if current device is iPod. -interface: not - -```javascript -is.ipod(); -=> true if current device is iPod - -is.not.ipod(); -=> true if current device is not iPod -``` - -is.android() ------------- -####Checks if current device has Android. -interface: not - -```javascript -is.android(); -=> true if current device has Android OS - -is.not.android(); -=> true if current device has not Android OS -``` - -is.androidPhone() ------------------ -####Checks if current device is Android phone. -interface: not - -```javascript -is.androidPhone(); -=> true if current device is Android phone - -is.not.androidPhone(); -=> true if current device is not Android phone -``` - -is.androidTablet() ------------------- -####Checks if current device is Android tablet. -interface: not - -```javascript -is.androidTablet(); -=> true if current device is Android tablet - -is.not.androidTablet(); -=> true if current device is not Android tablet -``` - -is.blackberry() ---------------- -####Checks if current device is Blackberry. -interface: not - -```javascript -is.blackberry(); -=> true if current device is Blackberry - -is.not.blackberry(); -=> true if current device is not Blackberry -``` - -is.windowsPhone() ------------------ -####Checks if current device is Windows phone. -interface: not - -```javascript -is.windowsPhone(); -=> true if current device is Windows phone - -is.not.windowsPhone(); -=> true if current device is not Windows Phone -``` - -is.windowsTablet() ------------------- -####Checks if current device is Windows tablet. -interface: not - -```javascript -is.windowsTablet(); -=> true if current device is Windows tablet - -is.not.windowsTablet(); -=> true if current device is not Windows tablet -``` - -is.windows() ------------- -####Checks if current OS is Windows. -interface: not - -```javascript -is.windows(); -=> true if current OS is Windows - -is.not.windows(); -=> true if current OS is not Windows -``` - -is.mac() --------- -####Checks if current OS is Mac OS X. -interface: not - -```javascript -is.mac(); -=> true if current OS is Mac OS X - -is.not.mac(); -=> true if current OS is not Mac OS X -``` - -is.linux() ----------- -####Checks if current OS is linux. -interface: not - -```javascript -is.linux(); -=> true if current OS is linux - -is.not.linux(); -=> true if current OS is not linux -``` - -is.desktop() ------------- -####Checks if current device is desktop. -interface: not - -```javascript -is.desktop(); -=> true if current device is desktop - -is.not.desktop(); -=> true if current device is not desktop -``` - -is.mobile() ------------ -####Checks if current device is mobile. -interface: not -iPhone, iPod, Android Phone, Windows Phone, Blackberry. -```javascript - -is.mobile(); -=> true if current device is mobile - -is.not.mobile(); -=> true if current device is not mobile -``` - -is.tablet() ------------ -####Checks if current device is tablet. -interface: not -iPad, Android Tablet, Windows Tablet -```javascript - -is.tablet(); -=> true if current device is tablet - -is.not.tablet(); -=> true if current device is not tablet -``` - -is.online() ------------ -####Checks if current device is online. -interface: not - -```javascript -is.online(); -=> true if current device is online - -is.not.online(); -=> true if current device is not online -``` - -is.offline() ------------- -####Checks if current device is offline. -interface: not - -```javascript -is.offline(); -=> true if current device is offline - -is.not.offline(); -=> true if current device is not offline -``` - -Time checks -=========== - -is.today(value:object) ----------------------- -####Checks if the given date object indicate today. -interfaces: not, all, any - -```javascript -var today = new Date(); -is.today(today); -=> true - -var yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); -is.today(yesterday); -=> false - -is.not.today(yesterday); -=> true - -is.all.today(today, today); -=> true - -is.any.today(today, yesterday); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.today([today, yesterday]); -=> false -``` - -is.yesterday(value:object) --------------------------- -####Checks if the given date object indicate yesterday. -interfaces: not, all, any - -```javascript -var today = new Date(); -is.yesterday(today); -=> false - -var yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); -is.yesterday(yesterday); -=> true - -is.not.yesterday(today); -=> true - -is.all.yesterday(yesterday, today); -=> false - -is.any.yesterday(today, yesterday); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.yesterday([today, yesterday]); -=> false -``` - -is.tomorrow(value:object) -------------------------- -####Checks if the given date object indicate tomorrow. -interfaces: not, all, any - -```javascript -var today = new Date(); -is.tomorrow(today); -=> false - -var tomorrow = new Date(new Date().setDate(new Date().getDate() + 1)); -is.tomorrow(tomorrow); -=> true - -is.not.tomorrow(today); -=> true - -is.all.tomorrow(tomorrow, today); -=> false - -is.any.tomorrow(today, tomorrow); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.tomorrow([today, tomorrow]); -=> false -``` - -is.past(value:object) ---------------------- -####Checks if the given date object indicate past. -interfaces: not, all, any - -```javascript -var yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); -var tomorrow = new Date(new Date().setDate(new Date().getDate() + 1)); - -is.past(yesterday); -=> true - -is.past(tomorrow); -=> false - -is.not.past(tomorrow); -=> true - -is.all.past(tomorrow, yesterday); -=> false - -is.any.past(yesterday, tomorrow); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.past([yesterday, tomorrow]); -=> false -``` - -is.future(value:object) ------------------------ -####Checks if the given date object indicate future. -interfaces: not, all, any - -```javascript -var yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); -var tomorrow = new Date(new Date().setDate(new Date().getDate() + 1)); - -is.future(yesterday); -=> false - -is.future(tomorrow); -=> true - -is.not.future(yesterday); -=> true - -is.all.future(tomorrow, yesterday); -=> false - -is.any.future(yesterday, tomorrow); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.future([yesterday, tomorrow]); -=> false -``` - -is.day(value:object, dayString) -------------------------------- -####Checks if the given date objects' day equal given dayString parameter. -interface: not - -```javascript -var mondayObj = new Date('01/26/2015'); -var tuesdayObj = new Date('01/27/2015'); -is.day(mondayObj, 'monday'); -=> true - -is.day(mondayObj, 'tuesday'); -=> false - -is.not.day(mondayObj, 'tuesday'); -=> true -``` - -is.month(value:object, monthString) ------------------------------------ -####Checks if the given date objects' month equal given monthString parameter. -interface: not - -```javascript -var januaryObj = new Date('01/26/2015'); -var februaryObj = new Date('02/26/2015'); -is.month(januaryObj, 'january'); -=> true - -is.month(februaryObj, 'january'); -=> false - -is.not.month(februaryObj, 'january'); -=> true -``` - -is.year(value:object, yearNumber) ---------------------------------- -####Checks if the given date objects' year equal given yearNumber parameter. -interface: not - -```javascript -var year2015 = new Date('01/26/2015'); -var year2016 = new Date('01/26/2016'); -is.year(year2015, 2015); -=> true - -is.year(year2016, 2015); -=> false - -is.not.year(year2016, 2015); -=> true -``` - -is.leapYear(value:number) ---------------------------------- -####Checks if the given year number is a leap year -interfaces: not, all, any - -```javascript -is.leapYear(2016); -=> true - -is.leapYear(2015); -=> false - -is.not.leapYear(2015); -=> true - -is.all.leapYear(2015, 2016); -=> false - -is.any.leapYear(2015, 2016); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.leapYear([2016, 2080]); -=> true -``` - -is.weekend(value:object) ------------------------- -####Checks if the given date objects' day is weekend. -interfaces: not, all, any - -```javascript -var monday = new Date('01/26/2015'); -var sunday = new Date('01/25/2015'); -var saturday = new Date('01/24/2015'); -is.weekend(sunday); -=> true - -is.weekend(monday); -=> false - -is.not.weekend(monday); -=> true - -is.all.weekend(sunday, saturday); -=> true - -is.any.weekend(sunday, saturday, monday); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.weekend([sunday, saturday, monday]); -=> false -``` - -is.weekday(value:object) ------------------------- -####Checks if the given date objects' day is weekday. -interfaces: not, all, any - -```javascript -var monday = new Date('01/26/2015'); -var sunday = new Date('01/25/2015'); -var saturday = new Date('01/24/2015'); -is.weekday(monday); -=> true - -is.weekday(sunday); -=> false - -is.not.weekday(sunday); -=> true - -is.all.weekday(monday, saturday); -=> false - -is.any.weekday(sunday, saturday, monday); -=> true - -// 'all' and 'any' interfaces can also take array parameter -is.all.weekday([sunday, saturday, monday]); -=> false -``` - -is.inDateRange(value:object, startObject, endObject) ----------------------------------------------------- -####Checks if date is within given range. -interface: not - -```javascript -var saturday = new Date('01/24/2015'); -var sunday = new Date('01/25/2015'); -var monday = new Date('01/26/2015'); -is.inDateRange(sunday, saturday, monday); -=> true - -is.inDateRange(saturday, sunday, monday); -=> false - -is.not.inDateRange(saturday, sunday, monday); -=> true -``` - -is.inLastWeek(value:object) ---------------------------- -####Checks if the given date is between now and 7 days ago. -interface: not - -```javascript -var twoDaysAgo = new Date(new Date().setDate(new Date().getDate() - 2)); -var nineDaysAgo = new Date(new Date().setDate(new Date().getDate() - 9)); -is.inLastWeek(twoDaysAgo); -=> true - -is.inLastWeek(nineDaysAgo); -=> false - -is.not.inLastWeek(nineDaysAgo); -=> true -``` - -is.inLastMonth(value:object) ----------------------------- -####Checks if the given date is between now and a month ago. -interface: not - -```javascript -var tenDaysAgo = new Date(new Date().setDate(new Date().getDate() - 10)); -var fortyDaysAgo = new Date(new Date().setDate(new Date().getDate() - 40)); -is.inLastMonth(tenDaysAgo); -=> true - -is.inLastMonth(fortyDaysAgo); -=> false - -is.not.inLastMonth(fortyDaysAgo); -=> true -``` - -is.inLastYear(value:object) ---------------------------- -####Checks if the given date is between now and a year ago. -interface: not - -```javascript -var twoMonthsAgo = new Date(new Date().setMonth(new Date().getMonth() - 2)); -var thirteenMonthsAgo = new Date(new Date().setMonth(new Date().getMonth() - 13)); -is.inLastYear(twoMonthsAgo); -=> true - -is.inLastYear(thirteenMonthsAgo); -=> false - -is.not.inLastYear(thirteenMonthsAgo); -=> true -``` - -is.inNextWeek(value:object) ---------------------------- -####Checks if the given date is between now and 7 days later. -interface: not - -```javascript -var twoDaysLater = new Date(new Date().setDate(new Date().getDate() + 2)); -var nineDaysLater = new Date(new Date().setDate(new Date().getDate() + 9)); -is.inNextWeek(twoDaysLater); -=> true - -is.inNextWeek(nineDaysLater); -=> false - -is.not.inNextWeek(nineDaysLater); -=> true -``` - -is.inNextMonth(value:object) ----------------------------- -####Checks if the given date is between now and a month later. -interface: not - -```javascript -var tenDaysLater = new Date(new Date().setDate(new Date().getDate() + 10)); -var fortyDaysLater = new Date(new Date().setDate(new Date().getDate() + 40)); -is.inNextMonth(tenDaysLater); -=> true - -is.inNextMonth(fortyDaysLater); -=> false - -is.not.inNextMonth(fortyDaysLater); -=> true -``` - -is.inNextYear(value:object) ---------------------------- -####Checks if the given date is between now and a year later. -interface: not - -```javascript -var twoMonthsLater = new Date(new Date().setMonth(new Date().getMonth() + 2)); -var thirteenMonthsLater = new Date(new Date().setMonth(new Date().getMonth() + 13)); -is.inNextYear(twoMonthsLater); -=> true - -is.inNextYear(thirteenMonthsLater); -=> false - -is.not.inNextYear(thirteenMonthsLater); -=> true -``` - -is.quarterOfYear(value:object, quarterNumber) ---------------------------------------------- -####Checks if the given date is in the parameter quarter. -interface: not - -```javascript -var firstQuarter = new Date('01/26/2015'); -var secondQuarter = new Date('05/26/2015'); -is.quarterOfYear(firstQuarter, 1); -=> true - -is.quarterOfYear(secondQuarter, 1); -=> false - -is.not.quarterOfYear(secondQuarter, 1); -=> true -``` - -is.dayLightSavingTime(value:object, quarterNumber) --------------------------------------------------- -####Checks if the given date is in daylight saving time. -interface: not - -```javascript -// For Turkey Time Zone -var january1 = new Date('01/01/2015'); -var june1 = new Date('06/01/2015'); - -is.dayLightSavingTime(june1); -=> true - -is.dayLightSavingTime(january1); -=> false - -is.not.dayLightSavingTime(january1); -=> true -``` - -Configuration methods -===================== - -is.setRegexp(value:RegExp, regexpString) ----------------------------------------- -Override RegExps if you think they suck. - -```javascript -is.url('https://www.duckduckgo.com'); -=> true - -is.setRegexp(/quack/, 'url'); -is.url('quack'); -=> true -``` - -is.setNamespace() ------------------ -Change namespace of library to prevent name collisions. - -```javascript -var customName = is.setNamespace(); -customName.odd(3); -=> true -``` diff --git a/vendors/is.js/bower.json b/vendors/is.js/bower.json deleted file mode 100644 index 3ab0941d0..000000000 --- a/vendors/is.js/bower.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "is_js", - "main": "is.js", - "version": "0.6.0", - "homepage": "http://arasatasaygin.github.io/is.js/", - "authors": [ - "arasatasaygin " - ], - "description": "micro check library", - "moduleType": [ - "amd", - "globals", - "node" - ], - "keywords": [ - "type", - "presence", - "regexp", - "string", - "arithmetic", - "object", - "array", - "environment", - "time", - "configuration" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ] -} diff --git a/vendors/is.js/is.js b/vendors/is.js/is.js deleted file mode 100644 index 5c98e3298..000000000 --- a/vendors/is.js/is.js +++ /dev/null @@ -1,818 +0,0 @@ -// is.js 0.6.0 -// Author: Aras Atasaygin - -// AMD with global, Node, or global -;(function(root, factory) { - if(typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['is'], function(is) { - // Also create a global in case some scripts - // that are loaded still are looking for - // a global even when an AMD loader is in use. - return (root.is = factory(is)); - }); - } else if(typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like enviroments that support module.exports, - // like Node. - module.exports = factory(require('is_js')); - } else { - // Browser globals (root is window) - root.is = factory(root.is); - } -}(this, function(is) { - - // Baseline - /* -------------------------------------------------------------------------- */ - - var root = this; - var previousIs = root.is; - - // define 'is' object and current version - is = {}; - is.VERSION = '0.6.0'; - - // define interfaces - is.not = {}; - is.all = {}; - is.any = {}; - - // cache some methods to call later on - var toString = Object.prototype.toString; - var arraySlice = Array.prototype.slice; - var hasOwnProperty = Object.prototype.hasOwnProperty; - - // helper function which reverses the sense of predicate result - function not(func) { - return function() { - return !func.apply(null, arraySlice.call(arguments)); - }; - } - - // helper function which call predicate function per parameter and return true if all pass - function all(func) { - return function() { - var parameters = arraySlice.call(arguments); - var length = parameters.length; - if(length === 1 && is.array(parameters[0])) { // support array - parameters = parameters[0]; - length = parameters.length; - } - for (var i = 0; i < length; i++) { - if (!func.call(null, parameters[i])) { - return false; - } - } - return true; - }; - } - - // helper function which call predicate function per parameter and return true if any pass - function any(func) { - return function() { - var parameters = arraySlice.call(arguments); - var length = parameters.length; - if(length === 1 && is.array(parameters[0])) { // support array - parameters = parameters[0]; - length = parameters.length; - } - for (var i = 0; i < length; i++) { - if (func.call(null, parameters[i])) { - return true; - } - } - return false; - }; - } - - // Type checks - /* -------------------------------------------------------------------------- */ - - // is a given value Arguments? - is.arguments = function(value) { // fallback check is for IE - return is.not.null(value) && (toString.call(value) === '[object Arguments]' || (typeof value === 'object' && 'callee' in value)); - }; - - // is a given value Array? - is.array = Array.isArray || function(value) { // check native isArray first - return toString.call(value) === '[object Array]'; - }; - - // is a given value Boolean? - is.boolean = function(value) { - return value === true || value === false || toString.call(value) === '[object Boolean]'; - }; - - // is a given value Date Object? - is.date = function(value) { - return toString.call(value) === '[object Date]'; - }; - - // is a given value Error object? - is.error = function(value) { - return toString.call(value) === '[object Error]'; - }; - - // is a given value function? - is.function = function(value) { // fallback check is for IE - return toString.call(value) === '[object Function]' || typeof value === 'function'; - }; - - // is a given value NaN? - is.nan = function(value) { // NaN is number :) Also it is the only value which does not equal itself - return value !== value; - }; - - // is a given value null? - is.null = function(value) { - return value === null || toString.call(value) === '[object Null]'; - }; - - // is a given value number? - is.number = function(value) { - return toString.call(value) === '[object Number]'; - }; - - // is a given value object? - is.object = function(value) { - var type = typeof value; - return type === 'function' || type === 'object' && !!value; - }; - - // is given value a pure JSON object? - is.json = function(value) { - return toString.call(value) === '[object Object]'; - }; - - // is a given value RegExp? - is.regexp = function(value) { - return toString.call(value) === '[object RegExp]'; - }; - - // are given values same type? - // prevent NaN, Number same type check - is.sameType = function(value1, value2) { - if(is.nan(value1) || is.nan(value2)) { - return is.nan(value1) === is.nan(value2); - } - return toString.call(value1) === toString.call(value2); - }; - // sameType method does not support 'all' and 'any' interfaces - is.sameType.api = ['not']; - - // is a given value String? - is.string = function(value) { - return toString.call(value) === '[object String]'; - }; - - // is a given value Char? - is.char = function(value) { - return is.string(value) && value.length === 1; - }; - - // is a given value undefined? - is.undefined = function(value) { - return value === void 0; - }; - - // Presence checks - /* -------------------------------------------------------------------------- */ - - //is a given value empty? Objects, arrays, strings - is.empty = function(value) { - if(is.object(value)){ - var num = Object.getOwnPropertyNames(value).length; - if(num === 0 || (num === 1 && is.array(value)) || (num === 2 && is.arguments(value))){ - return true; - } - return false; - } else { - return value === ''; - } - }; - - // is a given value existy? - is.existy = function(value) { - return value !== null && value !== undefined; - }; - - // is a given value truthy? - is.truthy = function(value) { - return is.existy(value) && value !== false && is.not.nan(value) && value !== "" && value !== 0; - }; - - // is a given value falsy? - is.falsy = not(is.truthy); - - // is a given value space? - // horizantal tab: 9, line feed: 10, vertical tab: 11, form feed: 12, carriage return: 13, space: 32 - is.space = function(value) { - if(is.char(value)) { - var characterCode = value.charCodeAt(0); - return (characterCode > 8 && characterCode < 14) || characterCode === 32; - } else { - return false; - } - }; - - // Arithmetic checks - /* -------------------------------------------------------------------------- */ - - // are given values equal? supports numbers, strings, regexps, booleans - // TODO: Add object and array support - is.equal = function(value1, value2) { - // check 0 and -0 equity with Infinity and -Infinity - if(is.all.number(value1, value2)) { - return value1 === value2 && 1 / value1 === 1 / value2; - } - // check regexps as strings too - if(is.all.string(value1, value2) || is.all.regexp(value1, value2)) { - return '' + value1 === '' + value2; - } - if(is.all.boolean(value1, value2)) { - return value1 === value2; - } - return false; - }; - // equal method does not support 'all' and 'any' interfaces - is.equal.api = ['not']; - - // is a given number even? - is.even = function(numb) { - return is.number(numb) && numb % 2 === 0; - }; - - // is a given number odd? - is.odd = function(numb) { - return is.number(numb) && numb % 2 !== 0; - }; - - // is a given number positive? - is.positive = function(numb) { - return is.number(numb) && numb > 0; - }; - - // is a given number negative? - is.negative = function(numb) { - return is.number(numb) && numb < 0; - }; - - // is a given number above minimum parameter? - is.above = function(numb, min) { - return is.all.number(numb, min) && numb > min; - }; - // above method does not support 'all' and 'any' interfaces - is.above.api = ['not']; - - // is a given number above maximum parameter? - is.under = function(numb, max) { - return is.all.number(numb, max) && numb < max; - }; - // least method does not support 'all' and 'any' interfaces - is.under.api = ['not']; - - // is a given number within minimum and maximum parameters? - is.within = function(numb, min, max) { - return is.all.number(numb, min, max) && numb > min && numb < max; - }; - // within method does not support 'all' and 'any' interfaces - is.within.api = ['not']; - - // is a given number decimal? - is.decimal = function(numb) { - return is.number(numb) && numb % 1 !== 0; - }; - - // is a given number integer? - is.integer = function(numb) { - return is.number(numb) && numb % 1 === 0; - }; - - // is a given number finite? - is.finite = isFinite || function(numb) { - return numb !== Infinity && numb !== -Infinity && is.not.nan(numb); - }; - - // is a given number infinite? - is.infinite = not(is.finite); - - // Regexp checks - /* -------------------------------------------------------------------------- */ - // Steven Levithan, Jan Goyvaerts: Regular Expressions Cookbook - // Scott Gonzalez: Email address validation - - // eppPhone match extensible provisioning protocol format - // nanpPhone match north american number plan format - // dateString match m/d/yy and mm/dd/yyyy, allowing any combination of one or two digits for the day and month, and two or four digits for the year - // time match hours, minutes, and seconds, 24-hour clock - var regexps = { - url: /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/, - email: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i, - creditCard: /^(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))$/, - alphaNumeric: /^[A-Za-z0-9]+$/, - timeString: /^(2[0-3]|[01]?[0-9]):([0-5]?[0-9]):([0-5]?[0-9])$/, - dateString: /^(1[0-2]|0?[1-9])\/(3[01]|[12][0-9]|0?[1-9])\/(?:[0-9]{2})?[0-9]{2}$/, - usZipCode: /^[0-9]{5}(?:-[0-9]{4})?$/, - caPostalCode: /^(?!.*[DFIOQU])[A-VXY][0-9][A-Z]\s?[0-9][A-Z][0-9]$/, - ukPostCode: /^[A-Z]{1,2}[0-9RCHNQ][0-9A-Z]?\s?[0-9][ABD-HJLNP-UW-Z]{2}$|^[A-Z]{2}-?[0-9]{4}$/, - nanpPhone: /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/, - eppPhone: /^\+[0-9]{1,3}\.[0-9]{4,14}(?:x.+)?$/, - socialSecurityNumber: /^(?!000|666)[0-8][0-9]{2}-(?!00)[0-9]{2}-(?!0000)[0-9]{4}$/, - affirmative: /^(?:1|t(?:rue)?|y(?:es)?|ok(?:ay)?)$/, - hexadecimal: /^[0-9a-fA-F]+$/, - hexColor: /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, - ipv4: /^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/, - ipv6: /^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/, - ip: /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/ - }; - - // create regexp checks methods from 'regexp' object - for(var regexp in regexps) { - if(regexps.hasOwnProperty(regexp)) { - regexpCheck(regexp, regexps); - } - } - - function regexpCheck(regexp, regexps) { - is[regexp] = function(value) { - return regexps[regexp].test(value); - }; - } - - // String checks - /* -------------------------------------------------------------------------- */ - - // is a given string include parameter substring? - is.include = String.prototype.includes || function(str, substr) { - return str.indexOf(substr) > -1; - }; - // include method does not support 'all' and 'any' interfaces - is.include.api = ['not']; - - // is a given string all uppercase? - is.upperCase = function(str) { - return is.string(str) && str === str.toUpperCase(); - }; - - // is a given string all lowercase? - is.lowerCase = function(str) { - return is.string(str) && str === str.toLowerCase(); - }; - - // is string start with a given startWith parameter? - is.startWith = function(str, startWith) { - return is.string(str) && str.indexOf(startWith) === 0; - }; - // startWith method does not support 'all' and 'any' interfaces - is.startWith.api = ['not']; - - // is string end with a given endWith parameter? - is.endWith = function(str, endWith) { - return is.string(str) && str.indexOf(endWith) > -1 && str.indexOf(endWith) === str.length - endWith.length; - }; - // endWith method does not support 'all' and 'any' interfaces - is.endWith.api = ['not']; - - // is a given string or sentence capitalized? - is.capitalized = function(str) { - if(is.not.string(str)) { - return false; - } - var words = str.split(' '); - var capitalized = []; - for(var i = 0; i < words.length; i++) { - capitalized.push(words[i][0] === words[i][0].toUpperCase()); - } - return is.all.truthy.apply(null, capitalized); - }; - - // is a given string palindrome? - is.palindrome = function(str) { - return is.string(str) && str == str.split('').reverse().join(''); - }; - - // Time checks - /* -------------------------------------------------------------------------- */ - - var days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']; - var months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december']; - - // is a given date indicate today? - is.today = function(obj) { - var now = new Date(); - var todayString = now.toDateString(); - return is.date(obj) && obj.toDateString() === todayString; - }; - - // is a given date indicate yesterday? - is.yesterday = function(obj) { - var now = new Date(); - var yesterdayString = new Date(now.setDate(now.getDate() - 1)).toDateString(); - return is.date(obj) && obj.toDateString() === yesterdayString; - }; - - // is a given date indicate tomorrow? - is.tomorrow = function(obj) { - var now = new Date(); - var tomorrowString = new Date(now.setDate(now.getDate() + 1)).toDateString(); - return is.date(obj) && obj.toDateString() === tomorrowString; - }; - - // is a given date past? - is.past = function(obj) { - var now = new Date(); - return is.date(obj) && obj.getTime() < now.getTime(); - }; - - // is a given date future? - is.future = not(is.past); - - // is a given dates day equal given dayString parameter? - is.day = function(obj, dayString) { - return is.date(obj) && dayString.toLowerCase() === days[obj.getDay()]; - }; - // day method does not support 'all' and 'any' interfaces - is.day.api = ['not']; - - // is a given dates month equal given monthString parameter? - is.month = function(obj, monthString) { - return is.date(obj) && monthString.toLowerCase() === months[obj.getMonth()]; - }; - // month method does not support 'all' and 'any' interfaces - is.month.api = ['not']; - - // is a given dates year equal given year parameter? - is.year = function(obj, year) { - return is.date(obj) && is.number(year) && year === obj.getFullYear(); - }; - // year method does not support 'all' and 'any' interfaces - is.year.api = ['not']; - - // is the given year a leap year? - is.leapYear = function(year) { - return is.number(year) && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); - }; - - // is a given date weekend? - // 6: Saturday, 0: Sunday - is.weekend = function(obj) { - return is.date(obj) && (obj.getDay() === 6 || obj.getDay() === 0); - }; - - // is a given date weekday? - is.weekday = not(is.weekend); - - // is date within given range? - is.inDateRange = function(obj, startObj, endObj) { - if(is.not.date(obj) || is.not.date(startObj) || is.not.date(endObj)) { - return false; - } - var givenDate = obj.getTime(); - var start = startObj.getTime(); - var end = endObj.getTime(); - return givenDate > start && givenDate < end; - }; - // inDateRange method does not support 'all' and 'any' interfaces - is.inDateRange.api = ['not']; - - // is a given date in last week range? - is.inLastWeek = function(obj) { - return is.inDateRange(obj, new Date(new Date().setDate(new Date().getDate() - 7)), new Date()); - }; - - // is a given date in last month range? - is.inLastMonth = function(obj) { - return is.inDateRange(obj, new Date(new Date().setMonth(new Date().getMonth() - 1)), new Date()); - }; - - // is a given date in last year range? - is.inLastYear = function(obj) { - return is.inDateRange(obj, new Date(new Date().setFullYear(new Date().getFullYear() - 1)), new Date()); - }; - - // is a given date in next week range? - is.inNextWeek = function(obj) { - return is.inDateRange(obj, new Date(), new Date(new Date().setDate(new Date().getDate() + 7))); - }; - - // is a given date in next month range? - is.inNextMonth = function(obj) { - return is.inDateRange(obj, new Date(), new Date(new Date().setMonth(new Date().getMonth() + 1))); - }; - - // is a given date in next year range? - is.inNextYear = function(obj) { - return is.inDateRange(obj, new Date(), new Date(new Date().setFullYear(new Date().getFullYear() + 1))); - }; - - // is a given date in the parameter quarter? - is.quarterOfYear = function(obj, quarterNumber) { - return is.date(obj) && is.number(quarterNumber) && quarterNumber === Math.floor((obj.getMonth() + 3) / 3); - }; - // quarterOfYear method does not support 'all' and 'any' interfaces - is.quarterOfYear.api = ['not']; - - // is a given date in daylight saving time? - is.dayLightSavingTime = function(obj) { - var january = new Date(obj.getFullYear(), 0, 1); - var july = new Date(obj.getFullYear(), 6, 1); - var stdTimezoneOffset = Math.max(january.getTimezoneOffset(), july.getTimezoneOffset()); - return obj.getTimezoneOffset() < stdTimezoneOffset; - }; - - // Environment checks - /* -------------------------------------------------------------------------- */ - - // check if library is used as a Node.js module - if(typeof window !== 'undefined') { - - // store navigator properties to use later - var userAgent = 'navigator' in window && 'userAgent' in navigator && navigator.userAgent.toLowerCase() || ''; - var vendor = 'navigator' in window && 'vendor' in navigator && navigator.vendor.toLowerCase() || ''; - var appVersion = 'navigator' in window && 'appVersion' in navigator && navigator.appVersion.toLowerCase() || ''; - - // is current browser chrome? - is.chrome = function() { - return /chrome|chromium/i.test(userAgent) && /google inc/.test(vendor); - }; - // chrome method does not support 'all' and 'any' interfaces - is.chrome.api = ['not']; - - // is current browser firefox? - is.firefox = function() { - return /firefox/i.test(userAgent); - }; - // firefox method does not support 'all' and 'any' interfaces - is.firefox.api = ['not']; - - // is current browser internet explorer? - // parameter is optional - is.ie = function(version) { - if(!version) { - return /msie/i.test(userAgent) || "ActiveXObject" in window; - } - if(version >= 11) { - return "ActiveXObject" in window; - } - return new RegExp('msie ' + version).test(userAgent); - }; - // ie method does not support 'all' and 'any' interfaces - is.ie.api = ['not']; - - // is current browser opera? - is.opera = function() { - return /^Opera\//.test(userAgent) || // Opera 12 and older versions - /\x20OPR\//.test(userAgent); // Opera 15+ - }; - // opera method does not support 'all' and 'any' interfaces - is.opera.api = ['not']; - - // is current browser safari? - is.safari = function() { - return /safari/i.test(userAgent) && /apple computer/i.test(vendor); - }; - // safari method does not support 'all' and 'any' interfaces - is.safari.api = ['not']; - - // is current device ios? - is.ios = function() { - return is.iphone() || is.ipad() || is.ipod(); - }; - // ios method does not support 'all' and 'any' interfaces - is.ios.api = ['not']; - - // is current device iphone? - is.iphone = function() { - return /iphone/i.test(userAgent); - }; - // iphone method does not support 'all' and 'any' interfaces - is.iphone.api = ['not']; - - // is current device ipad? - is.ipad = function() { - return /ipad/i.test(userAgent); - }; - // ipad method does not support 'all' and 'any' interfaces - is.ipad.api = ['not']; - - // is current device ipod? - is.ipod = function() { - return /ipod/i.test(userAgent); - }; - // ipod method does not support 'all' and 'any' interfaces - is.ipod.api = ['not']; - - // is current device android? - is.android = function() { - return /android/i.test(userAgent); - }; - // android method does not support 'all' and 'any' interfaces - is.android.api = ['not']; - - // is current device android phone? - is.androidPhone = function() { - return /android/i.test(userAgent) && /mobile/i.test(userAgent); - }; - // androidPhone method does not support 'all' and 'any' interfaces - is.androidPhone.api = ['not']; - - // is current device android tablet? - is.androidTablet = function() { - return /android/i.test(userAgent) && !/mobile/i.test(userAgent); - }; - // androidTablet method does not support 'all' and 'any' interfaces - is.androidTablet.api = ['not']; - - // is current device blackberry? - is.blackberry = function() { - return /blackberry/i.test(userAgent); - }; - // blackberry method does not support 'all' and 'any' interfaces - is.blackberry.api = ['not']; - - // is current device desktop? - is.desktop = function() { - return is.not.mobile() && is.not.tablet(); - }; - // desktop method does not support 'all' and 'any' interfaces - is.desktop.api = ['not']; - - // is current operating system linux? - is.linux = function() { - return /linux/i.test(appVersion); - }; - // linux method does not support 'all' and 'any' interfaces - is.linux.api = ['not']; - - // is current operating system mac? - is.mac = function() { - return /mac/i.test(appVersion); - }; - // mac method does not support 'all' and 'any' interfaces - is.mac.api = ['not']; - - // is current operating system windows? - is.windows = function() { - return /win/i.test(appVersion); - }; - // windows method does not support 'all' and 'any' interfaces - is.windows.api = ['not']; - - // is current device windows phone? - is.windowsPhone = function() { - return is.windows() && /phone/i.test(userAgent); - }; - // windowsPhone method does not support 'all' and 'any' interfaces - is.windowsPhone.api = ['not']; - - // is current device windows tablet? - is.windowsTablet = function() { - return is.windows() && is.not.windowsPhone() && /touch/i.test(userAgent); - }; - // windowsTablet method does not support 'all' and 'any' interfaces - is.windowsTablet.api = ['not']; - - // is current device mobile? - is.mobile = function() { - return is.iphone() || is.ipod() || is.androidPhone() || is.blackberry() || is.windowsPhone(); - }; - // mobile method does not support 'all' and 'any' interfaces - is.mobile.api = ['not']; - - // is current device tablet? - is.tablet = function() { - return is.ipad() || is.androidTablet() || is.windowsTablet(); - }; - // tablet method does not support 'all' and 'any' interfaces - is.tablet.api = ['not']; - - // is current state online? - is.online = function() { - return navigator.onLine; - }; - // online method does not support 'all' and 'any' interfaces - is.online.api = ['not']; - - // is current state offline? - is.offline = not(is.online); - // offline method does not support 'all' and 'any' interfaces - is.offline.api = ['not']; - } - - // Object checks - /* -------------------------------------------------------------------------- */ - - // has a given object got parameterized count property? - is.propertyCount = function(obj, count) { - if(!is.object(obj) || !is.number(count)) { - return false; - } - if(Object.keys) { - return Object.keys(obj).length === count; - } - var properties = [], - property; - for(property in obj) { - if (hasOwnProperty.call(obj, property)) { - properties.push(property); - } - } - return properties.length === count; - }; - // propertyCount method does not support 'all' and 'any' interfaces - is.propertyCount.api = ['not']; - - // is given object has parameterized property? - is.propertyDefined = function(obj, property) { - return is.object(obj) && is.string(property) && property in obj; - }; - // propertyDefined method does not support 'all' and 'any' interfaces - is.propertyDefined.api = ['not']; - - // is a given object window? - // setInterval method is only available for window object - is.windowObject = function(obj) { - return typeof obj === 'object' && 'setInterval' in obj; - }; - - // is a given object a DOM node? - is.domNode = function(obj) { - return is.object(obj) && obj.nodeType > 0; - }; - - // Array checks - /* -------------------------------------------------------------------------- */ - - // is a given item in an array? - is.inArray = function(val, arr){ - if(is.not.array(arr)) { - return false; - } - for(var i = 0; i < arr.length; i++) { - if (arr[i] === val) return true; - } - return false; - }; - // inArray method does not support 'all' and 'any' interfaces - is.inArray.api = ['not']; - - // is a given array sorted? - is.sorted = function(arr) { - if(is.not.array(arr)) { - return false; - } - for(var i = 0; i < arr.length; i++) { - if(arr[i] > arr[i + 1]) return false; - } - return true; - }; - - // API - // Set 'not', 'all' and 'any' interfaces to methods based on their api property - /* -------------------------------------------------------------------------- */ - - function setInterfaces() { - var options = is; - for(var option in options) { - if(hasOwnProperty.call(options, option) && is.function(options[option])) { - var interfaces = options[option].api || ['not', 'all', 'any']; - for (var i = 0; i < interfaces.length; i++) { - if(interfaces[i] === 'not') { - is.not[option] = not(is[option]); - } - if(interfaces[i] === 'all') { - is.all[option] = all(is[option]); - } - if(interfaces[i] === 'any') { - is.any[option] = any(is[option]); - } - } - } - } - } - setInterfaces(); - - // Configuration methods - // Intentionally added after setInterfaces function - /* -------------------------------------------------------------------------- */ - - // set optional regexps to methods if you think they suck - is.setRegexp = function(regexp, regexpName) { - for(var r in regexps) { - if(hasOwnProperty.call(regexps, r) && (regexpName === r)) { - regexps[r] = regexp; - } - } - }; - - // change namespace of library to prevent name collisions - // var preferredName = is.setNamespace(); - // preferredName.odd(3); - // => true - is.setNamespace = function() { - root.is = previousIs; - return this; - }; - - return is; -})); diff --git a/vendors/is.js/is.min.js b/vendors/is.js/is.min.js deleted file mode 100644 index 3aa617a79..000000000 --- a/vendors/is.js/is.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(a,b){"function"==typeof define&&define.amd?define(["is"],function(c){return a.is=b(c)}):"object"==typeof exports?module.exports=b(require("is_js")):a.is=b(a.is)}(this,function(a){function b(a){return function(){return!a.apply(null,j.call(arguments))}}function c(b){return function(){var c=j.call(arguments),d=c.length;1===d&&a.array(c[0])&&(c=c[0],d=c.length);for(var e=0;d>e;e++)if(!b.call(null,c[e]))return!1;return!0}}function d(b){return function(){var c=j.call(arguments),d=c.length;1===d&&a.array(c[0])&&(c=c[0],d=c.length);for(var e=0;d>e;e++)if(b.call(null,c[e]))return!0;return!1}}function e(b,c){a[b]=function(a){return c[b].test(a)}}function f(){var e=a;for(var f in e)if(k.call(e,f)&&a["function"](e[f]))for(var g=e[f].api||["not","all","any"],h=0;h8&&14>c||32===c}return!1},a.equal=function(b,c){return a.all.number(b,c)?b===c&&1/b===1/c:a.all.string(b,c)||a.all.regexp(b,c)?""+b==""+c:a.all["boolean"](b,c)?b===c:!1},a.equal.api=["not"],a.even=function(b){return a.number(b)&&b%2===0},a.odd=function(b){return a.number(b)&&b%2!==0},a.positive=function(b){return a.number(b)&&b>0},a.negative=function(b){return a.number(b)&&0>b},a.above=function(b,c){return a.all.number(b,c)&&b>c},a.above.api=["not"],a.under=function(b,c){return a.all.number(b,c)&&c>b},a.under.api=["not"],a.within=function(b,c,d){return a.all.number(b,c,d)&&b>c&&d>b},a.within.api=["not"],a.decimal=function(b){return a.number(b)&&b%1!==0},a.integer=function(b){return a.number(b)&&b%1===0},a.finite=isFinite||function(b){return 1/0!==b&&b!==-1/0&&a.not.nan(b)},a.infinite=b(a.finite);var l={url:/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/,email:/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,creditCard:/^(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))$/,alphaNumeric:/^[A-Za-z0-9]+$/,timeString:/^(2[0-3]|[01]?[0-9]):([0-5]?[0-9]):([0-5]?[0-9])$/,dateString:/^(1[0-2]|0?[1-9])\/(3[01]|[12][0-9]|0?[1-9])\/(?:[0-9]{2})?[0-9]{2}$/,usZipCode:/^[0-9]{5}(?:-[0-9]{4})?$/,caPostalCode:/^(?!.*[DFIOQU])[A-VXY][0-9][A-Z]\s?[0-9][A-Z][0-9]$/,ukPostCode:/^[A-Z]{1,2}[0-9RCHNQ][0-9A-Z]?\s?[0-9][ABD-HJLNP-UW-Z]{2}$|^[A-Z]{2}-?[0-9]{4}$/,nanpPhone:/^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/,eppPhone:/^\+[0-9]{1,3}\.[0-9]{4,14}(?:x.+)?$/,socialSecurityNumber:/^(?!000|666)[0-8][0-9]{2}-(?!00)[0-9]{2}-(?!0000)[0-9]{4}$/,affirmative:/^(?:1|t(?:rue)?|y(?:es)?|ok(?:ay)?)$/,hexadecimal:/^[0-9a-fA-F]+$/,hexColor:/^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/,ipv4:/^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/,ipv6:/^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,ip:/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/};for(var m in l)l.hasOwnProperty(m)&&e(m,l);a.include=String.prototype.includes||function(a,b){return a.indexOf(b)>-1},a.include.api=["not"],a.upperCase=function(b){return a.string(b)&&b===b.toUpperCase()},a.lowerCase=function(b){return a.string(b)&&b===b.toLowerCase()},a.startWith=function(b,c){return a.string(b)&&0===b.indexOf(c)},a.startWith.api=["not"],a.endWith=function(b,c){return a.string(b)&&b.indexOf(c)>-1&&b.indexOf(c)===b.length-c.length},a.endWith.api=["not"],a.capitalized=function(b){if(a.not.string(b))return!1;for(var c=b.split(" "),d=[],e=0;ef&&g>e},a.inDateRange.api=["not"],a.inLastWeek=function(b){return a.inDateRange(b,new Date((new Date).setDate((new Date).getDate()-7)),new Date)},a.inLastMonth=function(b){return a.inDateRange(b,new Date((new Date).setMonth((new Date).getMonth()-1)),new Date)},a.inLastYear=function(b){return a.inDateRange(b,new Date((new Date).setFullYear((new Date).getFullYear()-1)),new Date)},a.inNextWeek=function(b){return a.inDateRange(b,new Date,new Date((new Date).setDate((new Date).getDate()+7)))},a.inNextMonth=function(b){return a.inDateRange(b,new Date,new Date((new Date).setMonth((new Date).getMonth()+1)))},a.inNextYear=function(b){return a.inDateRange(b,new Date,new Date((new Date).setFullYear((new Date).getFullYear()+1)))},a.quarterOfYear=function(b,c){return a.date(b)&&a.number(c)&&c===Math.floor((b.getMonth()+3)/3)},a.quarterOfYear.api=["not"],a.dayLightSavingTime=function(a){var b=new Date(a.getFullYear(),0,1),c=new Date(a.getFullYear(),6,1),d=Math.max(b.getTimezoneOffset(),c.getTimezoneOffset());return a.getTimezoneOffset()=11?"ActiveXObject"in window:new RegExp("msie "+a).test(p):/msie/i.test(p)||"ActiveXObject"in window},a.ie.api=["not"],a.opera=function(){return/^Opera\//.test(p)||/\x20OPR\//.test(p)},a.opera.api=["not"],a.safari=function(){return/safari/i.test(p)&&/apple computer/i.test(q)},a.safari.api=["not"],a.ios=function(){return a.iphone()||a.ipad()||a.ipod()},a.ios.api=["not"],a.iphone=function(){return/iphone/i.test(p)},a.iphone.api=["not"],a.ipad=function(){return/ipad/i.test(p)},a.ipad.api=["not"],a.ipod=function(){return/ipod/i.test(p)},a.ipod.api=["not"],a.android=function(){return/android/i.test(p)},a.android.api=["not"],a.androidPhone=function(){return/android/i.test(p)&&/mobile/i.test(p)},a.androidPhone.api=["not"],a.androidTablet=function(){return/android/i.test(p)&&!/mobile/i.test(p)},a.androidTablet.api=["not"],a.blackberry=function(){return/blackberry/i.test(p)},a.blackberry.api=["not"],a.desktop=function(){return a.not.mobile()&&a.not.tablet()},a.desktop.api=["not"],a.linux=function(){return/linux/i.test(r)},a.linux.api=["not"],a.mac=function(){return/mac/i.test(r)},a.mac.api=["not"],a.windows=function(){return/win/i.test(r)},a.windows.api=["not"],a.windowsPhone=function(){return a.windows()&&/phone/i.test(p)},a.windowsPhone.api=["not"],a.windowsTablet=function(){return a.windows()&&a.not.windowsPhone()&&/touch/i.test(p)},a.windowsTablet.api=["not"],a.mobile=function(){return a.iphone()||a.ipod()||a.androidPhone()||a.blackberry()||a.windowsPhone()},a.mobile.api=["not"],a.tablet=function(){return a.ipad()||a.androidTablet()||a.windowsTablet()},a.tablet.api=["not"],a.online=function(){return navigator.onLine},a.online.api=["not"],a.offline=b(a.online),a.offline.api=["not"]}return a.propertyCount=function(b,c){if(!a.object(b)||!a.number(c))return!1;if(Object.keys)return Object.keys(b).length===c;var d,e=[];for(d in b)k.call(b,d)&&e.push(d);return e.length===c},a.propertyCount.api=["not"],a.propertyDefined=function(b,c){return a.object(b)&&a.string(c)&&c in b},a.propertyDefined.api=["not"],a.windowObject=function(a){return"object"==typeof a&&"setInterval"in a},a.domNode=function(b){return a.object(b)&&b.nodeType>0},a.inArray=function(b,c){if(a.not.array(c))return!1;for(var d=0;db[c+1])return!1;return!0},f(),a.setRegexp=function(a,b){for(var c in l)k.call(l,c)&&b===c&&(l[c]=a)},a.setNamespace=function(){return g.is=h,this},a}); \ No newline at end of file diff --git a/vendors/is.js/package.json b/vendors/is.js/package.json deleted file mode 100644 index d179a84c7..000000000 --- a/vendors/is.js/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "is_js", - "version": "0.6.0", - "main": "is.js", - "license": "MIT", - "devDependencies": { - "grunt": "~0.4.5", - "grunt-contrib-jshint": "~0.10.0", - "grunt-contrib-uglify": "~0.5.0", - "grunt-mocha-phantomjs": "0.6.0" - } -} diff --git a/vendors/jquery-magnific-popup/README.md b/vendors/jquery-magnific-popup/README.md deleted file mode 100644 index 3254c223d..000000000 --- a/vendors/jquery-magnific-popup/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# Magnific Popup Repository - -[![Build Status](https://travis-ci.org/dimsemenov/Magnific-Popup.png)](https://travis-ci.org/dimsemenov/Magnific-Popup) - -Fast, light and responsive lightbox plugin, for jQuery and Zepto.js. - -- [Documentation and getting started guide](http://dimsemenov.com/plugins/magnific-popup/documentation.html). -- [Examples and plugin home page](http://dimsemenov.com/plugins/magnific-popup/). -- More examples in [CodePen collection](http://codepen.io/collection/nLcqo). - -Optionally, install via Bower: `bower install magnific-popup`. -[Ruby gem](https://rubygems.org/gems/magnific-popup-rails), `gem install magnific-popup-rails`. - -## Extensions - -- WordPress plugin - [under development](http://dimsemenov.com/plugins/magnific-popup/wordpress.html). -- [Drupal module](https://drupal.org/project/magnific_popup). -- [Concrete5 add-on](https://github.com/cdowdy/concrete5-Magnific-Popup). -- [Redaxo add-on](http://www.redaxo.org/de/download/addons/?addon_id=1131). -- [Contao extension](https://github.com/fritzmg/contao-magnific-popup). - -If you created an extension for some CMS, email me and I'll add it to this list. - -## Location of stuff - -- Generated popup JS and CSS files are in folder [dist/](https://github.com/dimsemenov/Magnific-Popup/tree/master/dist). (Online build tool is on [documentation page](http://dimsemenov.com/plugins/magnific-popup/documentation.html)). -- Source files are in folder [src/](https://github.com/dimsemenov/Magnific-Popup/tree/master/src). They include [Sass CSS file](https://github.com/dimsemenov/Magnific-Popup/blob/master/src/css/main.scss) and js parts (edit them if you wish to submit commit). -- Website (examples & documentation) is in folder [website/](https://github.com/dimsemenov/Magnific-Popup/tree/master/website). -- Documentation page itself is in [website/documentation.md](https://github.com/dimsemenov/Magnific-Popup/blob/master/website/documentation.md) (contributions to it are very welcome). - - - -## Using Magnific Popup? - -If you used Magnific Popup in some interesting way, or on site of popular brand, I'd be very grateful if you shoot me a link to it. - - -## Build - -To compile Magnific Popup by yourself, first of make sure that you have [Node.js](http://nodejs.org/), [Grunt.js](https://github.com/cowboy/grunt), [Ruby](http://www.ruby-lang.org/) and [Jekyll](https://github.com/mojombo/jekyll/) installed, then: - -1) Copy repository - - git clone https://github.com/dimsemenov/Magnific-Popup.git - -2) Go inside Magnific Popup folder that you fetched and install Node dependencies - - cd Magnific-Popup && npm install - -3) Now simply run `grunt` to generate JS and CSS in folder `dist` and site in folder `_site/`. - - grunt - -Optionally: - -- Run `grunt watch` to automatically rebuild script when you change files in `src/` or in `website/`. -- If you don't have and don't want to install Jekyll, run `grunt nosite` to just build JS and CSS files related to popup in `dist/`. - - - -## [Changelog](https://github.com/dimsemenov/Magnific-Popup/releases) - -## License - -Script is MIT licensed and free and will always be kept this way. But has a small restriction from me - please do not create public WordPress plugin based on it(or at least contact me before creating it), because I will make it and it'll be open source too ([want to get notified?](http://dimsemenov.com/subscribe.html)). - -Created by [@dimsemenov](http://twitter.com/dimsemenov) & [contributors](https://github.com/dimsemenov/Magnific-Popup/contributors). - -[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/dimsemenov/magnific-popup/trend.png)](https://bitdeli.com/free "Bitdeli Badge") diff --git a/vendors/jquery-magnific-popup/bower.json b/vendors/jquery-magnific-popup/bower.json deleted file mode 100644 index 0c84a6bd3..000000000 --- a/vendors/jquery-magnific-popup/bower.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "magnific-popup", - "version": "0.9.9", - "main": [ - "dist/jquery.magnific-popup.js", - "dist/magnific-popup.css" - ], - "dependencies": { - "jquery": ">=1.8.0" - }, - "ignore": [ - "node_modules/", - "components/", - "website/", - "libs/" - ] -} \ No newline at end of file diff --git a/vendors/jquery-magnific-popup/jquery.magnific-popup.js b/vendors/jquery-magnific-popup/jquery.magnific-popup.js deleted file mode 100644 index 4d6985477..000000000 --- a/vendors/jquery-magnific-popup/jquery.magnific-popup.js +++ /dev/null @@ -1,2048 +0,0 @@ -/*! Magnific Popup - v0.9.9 - 2014-09-06 -* http://dimsemenov.com/plugins/magnific-popup/ -* Copyright (c) 2014 Dmitry Semenov; */ -;(function($) { - -/*>>core*/ -/** - * - * Magnific Popup Core JS file - * - */ - - -/** - * Private static constants - */ -var CLOSE_EVENT = 'Close', - BEFORE_CLOSE_EVENT = 'BeforeClose', - AFTER_CLOSE_EVENT = 'AfterClose', - BEFORE_APPEND_EVENT = 'BeforeAppend', - MARKUP_PARSE_EVENT = 'MarkupParse', - OPEN_EVENT = 'Open', - CHANGE_EVENT = 'Change', - NS = 'mfp', - EVENT_NS = '.' + NS, - READY_CLASS = 'mfp-ready', - REMOVING_CLASS = 'mfp-removing', - PREVENT_CLOSE_CLASS = 'mfp-prevent-close'; - - -/** - * Private vars - */ -var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this' - MagnificPopup = function(){}, - _isJQ = !!(window.jQuery), - _prevStatus, - _window = $(window), - _body, - _document, - _prevContentType, - _wrapClasses, - _currPopupType; - - -/** - * Private functions - */ -var _mfpOn = function(name, f) { - mfp.ev.on(NS + name + EVENT_NS, f); - }, - _getEl = function(className, appendTo, html, raw) { - var el = document.createElement('div'); - el.className = 'mfp-'+className; - if(html) { - el.innerHTML = html; - } - if(!raw) { - el = $(el); - if(appendTo) { - el.appendTo(appendTo); - } - } else if(appendTo) { - appendTo.appendChild(el); - } - return el; - }, - _mfpTrigger = function(e, data) { - mfp.ev.triggerHandler(NS + e, data); - - if(mfp.st.callbacks) { - // converts "mfpEventName" to "eventName" callback and triggers it if it's present - e = e.charAt(0).toLowerCase() + e.slice(1); - if(mfp.st.callbacks[e]) { - mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]); - } - } - }, - _getCloseBtn = function(type) { - if(type !== _currPopupType || !mfp.currTemplate.closeBtn) { - mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) ); - _currPopupType = type; - } - return mfp.currTemplate.closeBtn; - }, - // Initialize Magnific Popup only when called at least once - _checkInstance = function() { - if(!$.magnificPopup.instance) { - mfp = new MagnificPopup(); - mfp.init(); - $.magnificPopup.instance = mfp; - } - }, - // CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr - supportsTransitions = function() { - var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist - v = ['ms','O','Moz','Webkit']; // 'v' for vendor - - if( s['transition'] !== undefined ) { - return true; - } - - while( v.length ) { - if( v.pop() + 'Transition' in s ) { - return true; - } - } - - return false; - }; - - - -/** - * Public functions - */ -MagnificPopup.prototype = { - - constructor: MagnificPopup, - - /** - * Initializes Magnific Popup plugin. - * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed - */ - init: function() { - var appVersion = navigator.appVersion; - mfp.isIE7 = appVersion.indexOf("MSIE 7.") !== -1; - mfp.isIE8 = appVersion.indexOf("MSIE 8.") !== -1; - mfp.isLowIE = mfp.isIE7 || mfp.isIE8; - mfp.isAndroid = (/android/gi).test(appVersion); - mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion); - mfp.supportsTransition = supportsTransitions(); - - // We disable fixed positioned lightbox on devices that don't handle it nicely. - // If you know a better way of detecting this - let me know. - mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) ); - _document = $(document); - - mfp.popupsCache = {}; - }, - - /** - * Opens popup - * @param data [description] - */ - open: function(data) { - - if(!_body) { - _body = $(document.body); - } - - var i; - - if(data.isObj === false) { - // convert jQuery collection to array to avoid conflicts later - mfp.items = data.items.toArray(); - - mfp.index = 0; - var items = data.items, - item; - for(i = 0; i < items.length; i++) { - item = items[i]; - if(item.parsed) { - item = item.el[0]; - } - if(item === data.el[0]) { - mfp.index = i; - break; - } - } - } else { - mfp.items = $.isArray(data.items) ? data.items : [data.items]; - mfp.index = data.index || 0; - } - - // if popup is already opened - we just update the content - if(mfp.isOpen) { - mfp.updateItemHTML(); - return; - } - - mfp.types = []; - _wrapClasses = ''; - if(data.mainEl && data.mainEl.length) { - mfp.ev = data.mainEl.eq(0); - } else { - mfp.ev = _document; - } - - if(data.key) { - if(!mfp.popupsCache[data.key]) { - mfp.popupsCache[data.key] = {}; - } - mfp.currTemplate = mfp.popupsCache[data.key]; - } else { - mfp.currTemplate = {}; - } - - - - mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data ); - mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos; - - if(mfp.st.modal) { - mfp.st.closeOnContentClick = false; - mfp.st.closeOnBgClick = false; - mfp.st.showCloseBtn = false; - mfp.st.enableEscapeKey = false; - } - - - // Building markup - // main containers are created only once - if(!mfp.bgOverlay) { - - // Dark overlay - mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() { - mfp.close(); - }); - - mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) { - if(mfp._checkIfClose(e.target)) { - mfp.close(); - } - }); - - mfp.container = _getEl('container', mfp.wrap); - } - - mfp.contentContainer = _getEl('content'); - if(mfp.st.preloader) { - mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading); - } - - - // Initializing modules - var modules = $.magnificPopup.modules; - for(i = 0; i < modules.length; i++) { - var n = modules[i]; - n = n.charAt(0).toUpperCase() + n.slice(1); - mfp['init'+n].call(mfp); - } - _mfpTrigger('BeforeOpen'); - - - if(mfp.st.showCloseBtn) { - // Close button - if(!mfp.st.closeBtnInside) { - mfp.wrap.append( _getCloseBtn() ); - } else { - _mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) { - values.close_replaceWith = _getCloseBtn(item.type); - }); - _wrapClasses += ' mfp-close-btn-in'; - } - } - - if(mfp.st.alignTop) { - _wrapClasses += ' mfp-align-top'; - } - - - - if(mfp.fixedContentPos) { - mfp.wrap.css({ - overflow: mfp.st.overflowY, - overflowX: 'hidden', - overflowY: mfp.st.overflowY - }); - } else { - mfp.wrap.css({ - top: _window.scrollTop(), - position: 'absolute' - }); - } - if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) { - mfp.bgOverlay.css({ - height: _document.height(), - position: 'absolute' - }); - } - - - - if(mfp.st.enableEscapeKey) { - // Close on ESC key - _document.on('keyup' + EVENT_NS, function(e) { - if(e.keyCode === 27) { - mfp.close(); - } - }); - } - - _window.on('resize' + EVENT_NS, function() { - mfp.updateSize(); - }); - - - if(!mfp.st.closeOnContentClick) { - _wrapClasses += ' mfp-auto-cursor'; - } - - if(_wrapClasses) - mfp.wrap.addClass(_wrapClasses); - - - // this triggers recalculation of layout, so we get it once to not to trigger twice - var windowHeight = mfp.wH = _window.height(); - - - var windowStyles = {}; - - if( mfp.fixedContentPos ) { - if(mfp._hasScrollBar(windowHeight)){ - var s = mfp._getScrollbarSize(); - if(s) { - windowStyles.marginRight = s; - } - } - } - - if(mfp.fixedContentPos) { - if(!mfp.isIE7) { - windowStyles.overflow = 'hidden'; - } else { - // ie7 double-scroll bug - $('body, html').css('overflow', 'hidden'); - } - } - - - - var classesToadd = mfp.st.mainClass; - if(mfp.isIE7) { - classesToadd += ' mfp-ie7'; - } - if(classesToadd) { - mfp._addClassToMFP( classesToadd ); - } - - // add content - mfp.updateItemHTML(); - - _mfpTrigger('BuildControls'); - - // remove scrollbar, add margin e.t.c - $('html').css(windowStyles); - - // add everything to DOM - mfp.bgOverlay.add(mfp.wrap).prependTo( mfp.st.prependTo || _body ); - - // Save last focused element - mfp._lastFocusedEl = document.activeElement; - - // Wait for next cycle to allow CSS transition - setTimeout(function() { - - if(mfp.content) { - mfp._addClassToMFP(READY_CLASS); - mfp._setFocus(); - } else { - // if content is not defined (not loaded e.t.c) we add class only for BG - mfp.bgOverlay.addClass(READY_CLASS); - } - - // Trap the focus in popup - _document.on('focusin' + EVENT_NS, mfp._onFocusIn); - - }, 16); - - mfp.isOpen = true; - mfp.updateSize(windowHeight); - _mfpTrigger(OPEN_EVENT); - - return data; - }, - - /** - * Closes the popup - */ - close: function() { - if(!mfp.isOpen) return; - _mfpTrigger(BEFORE_CLOSE_EVENT); - - mfp.isOpen = false; - // for CSS3 animation - if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition ) { - mfp._addClassToMFP(REMOVING_CLASS); - setTimeout(function() { - mfp._close(); - }, mfp.st.removalDelay); - } else { - mfp._close(); - } - }, - - /** - * Helper for close() function - */ - _close: function() { - _mfpTrigger(CLOSE_EVENT); - - var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' '; - - mfp.bgOverlay.detach(); - mfp.wrap.detach(); - mfp.container.empty(); - - if(mfp.st.mainClass) { - classesToRemove += mfp.st.mainClass + ' '; - } - - mfp._removeClassFromMFP(classesToRemove); - - if(mfp.fixedContentPos) { - var windowStyles = {marginRight: ''}; - if(mfp.isIE7) { - $('body, html').css('overflow', ''); - } else { - windowStyles.overflow = ''; - } - $('html').css(windowStyles); - } - - _document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS); - mfp.ev.off(EVENT_NS); - - // clean up DOM elements that aren't removed - mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style'); - mfp.bgOverlay.attr('class', 'mfp-bg'); - mfp.container.attr('class', 'mfp-container'); - - // remove close button from target element - if(mfp.st.showCloseBtn && - (!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) { - if(mfp.currTemplate.closeBtn) - mfp.currTemplate.closeBtn.detach(); - } - - - if(mfp._lastFocusedEl) { - $(mfp._lastFocusedEl).focus(); // put tab focus back - } - mfp.currItem = null; - mfp.content = null; - mfp.currTemplate = null; - mfp.prevHeight = 0; - - _mfpTrigger(AFTER_CLOSE_EVENT); - }, - - updateSize: function(winHeight) { - - if(mfp.isIOS) { - // fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2 - var zoomLevel = document.documentElement.clientWidth / window.innerWidth; - var height = window.innerHeight * zoomLevel; - mfp.wrap.css('height', height); - mfp.wH = height; - } else { - mfp.wH = winHeight || _window.height(); - } - // Fixes #84: popup incorrectly positioned with position:relative on body - if(!mfp.fixedContentPos) { - mfp.wrap.css('height', mfp.wH); - } - - _mfpTrigger('Resize'); - - }, - - /** - * Set content of popup based on current index - */ - updateItemHTML: function() { - var item = mfp.items[mfp.index]; - - // Detach and perform modifications - mfp.contentContainer.detach(); - - if(mfp.content) - mfp.content.detach(); - - if(!item.parsed) { - item = mfp.parseEl( mfp.index ); - } - - var type = item.type; - - _mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]); - // BeforeChange event works like so: - // _mfpOn('BeforeChange', function(e, prevType, newType) { }); - - mfp.currItem = item; - - - - - - if(!mfp.currTemplate[type]) { - var markup = mfp.st[type] ? mfp.st[type].markup : false; - - // allows to modify markup - _mfpTrigger('FirstMarkupParse', markup); - - if(markup) { - mfp.currTemplate[type] = $(markup); - } else { - // if there is no markup found we just define that template is parsed - mfp.currTemplate[type] = true; - } - } - - if(_prevContentType && _prevContentType !== item.type) { - mfp.container.removeClass('mfp-'+_prevContentType+'-holder'); - } - - var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]); - mfp.appendContent(newContent, type); - - item.preloaded = true; - - _mfpTrigger(CHANGE_EVENT, item); - _prevContentType = item.type; - - // Append container back after its content changed - mfp.container.prepend(mfp.contentContainer); - - _mfpTrigger('AfterChange'); - }, - - - /** - * Set HTML content of popup - */ - appendContent: function(newContent, type) { - mfp.content = newContent; - - if(newContent) { - if(mfp.st.showCloseBtn && mfp.st.closeBtnInside && - mfp.currTemplate[type] === true) { - // if there is no markup, we just append close button element inside - if(!mfp.content.find('.mfp-close').length) { - mfp.content.append(_getCloseBtn()); - } - } else { - mfp.content = newContent; - } - } else { - mfp.content = ''; - } - - _mfpTrigger(BEFORE_APPEND_EVENT); - mfp.container.addClass('mfp-'+type+'-holder'); - - mfp.contentContainer.append(mfp.content); - }, - - - - - /** - * Creates Magnific Popup data object based on given data - * @param {int} index Index of item to parse - */ - parseEl: function(index) { - var item = mfp.items[index], - type; - - if(item.tagName) { - item = { el: $(item) }; - } else { - type = item.type; - item = { data: item, src: item.src }; - } - - if(item.el) { - var types = mfp.types; - - // check for 'mfp-TYPE' class - for(var i = 0; i < types.length; i++) { - if( item.el.hasClass('mfp-'+types[i]) ) { - type = types[i]; - break; - } - } - - item.src = item.el.attr('data-mfp-src'); - if(!item.src) { - item.src = item.el.attr('href'); - } - } - - item.type = type || mfp.st.type || 'inline'; - item.index = index; - item.parsed = true; - mfp.items[index] = item; - _mfpTrigger('ElementParse', item); - - return mfp.items[index]; - }, - - - /** - * Initializes single popup or a group of popups - */ - addGroup: function(el, options) { - var eHandler = function(e) { - e.mfpEl = this; - mfp._openClick(e, el, options); - }; - - if(!options) { - options = {}; - } - - var eName = 'click.magnificPopup'; - options.mainEl = el; - - if(options.items) { - options.isObj = true; - el.off(eName).on(eName, eHandler); - } else { - options.isObj = false; - if(options.delegate) { - el.off(eName).on(eName, options.delegate , eHandler); - } else { - options.items = el; - el.off(eName).on(eName, eHandler); - } - } - }, - _openClick: function(e, el, options) { - var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick; - - - if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey ) ) { - return; - } - - var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn; - - if(disableOn) { - if($.isFunction(disableOn)) { - if( !disableOn.call(mfp) ) { - return true; - } - } else { // else it's number - if( _window.width() < disableOn ) { - return true; - } - } - } - - if(e.type) { - e.preventDefault(); - - // This will prevent popup from closing if element is inside and popup is already opened - if(mfp.isOpen) { - e.stopPropagation(); - } - } - - - options.el = $(e.mfpEl); - if(options.delegate) { - options.items = el.find(options.delegate); - } - mfp.open(options); - }, - - - /** - * Updates text on preloader - */ - updateStatus: function(status, text) { - - if(mfp.preloader) { - if(_prevStatus !== status) { - mfp.container.removeClass('mfp-s-'+_prevStatus); - } - - if(!text && status === 'loading') { - text = mfp.st.tLoading; - } - - var data = { - status: status, - text: text - }; - // allows to modify status - _mfpTrigger('UpdateStatus', data); - - status = data.status; - text = data.text; - - mfp.preloader.html(text); - - mfp.preloader.find('a').on('click', function(e) { - e.stopImmediatePropagation(); - }); - - mfp.container.addClass('mfp-s-'+status); - _prevStatus = status; - } - }, - - - /* - "Private" helpers that aren't private at all - */ - // Check to close popup or not - // "target" is an element that was clicked - _checkIfClose: function(target) { - - if($(target).hasClass(PREVENT_CLOSE_CLASS)) { - return; - } - - var closeOnContent = mfp.st.closeOnContentClick; - var closeOnBg = mfp.st.closeOnBgClick; - - if(closeOnContent && closeOnBg) { - return true; - } else { - - // We close the popup if click is on close button or on preloader. Or if there is no content. - if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) { - return true; - } - - // if click is outside the content - if( (target !== mfp.content[0] && !$.contains(mfp.content[0], target)) ) { - if(closeOnBg) { - // last check, if the clicked element is in DOM, (in case it's removed onclick) - if( $.contains(document, target) ) { - return true; - } - } - } else if(closeOnContent) { - return true; - } - - } - return false; - }, - _addClassToMFP: function(cName) { - mfp.bgOverlay.addClass(cName); - mfp.wrap.addClass(cName); - }, - _removeClassFromMFP: function(cName) { - this.bgOverlay.removeClass(cName); - mfp.wrap.removeClass(cName); - }, - _hasScrollBar: function(winHeight) { - return ( (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) ); - }, - _setFocus: function() { - (mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus(); - }, - _onFocusIn: function(e) { - if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) { - mfp._setFocus(); - return false; - } - }, - _parseMarkup: function(template, values, item) { - var arr; - if(item.data) { - values = $.extend(item.data, values); - } - _mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] ); - - $.each(values, function(key, value) { - if(value === undefined || value === false) { - return true; - } - arr = key.split('_'); - if(arr.length > 1) { - var el = template.find(EVENT_NS + '-'+arr[0]); - - if(el.length > 0) { - var attr = arr[1]; - if(attr === 'replaceWith') { - if(el[0] !== value[0]) { - el.replaceWith(value); - } - } else if(attr === 'img') { - if(el.is('img')) { - el.attr('src', value); - } else { - el.replaceWith( '' ); - } - } else { - el.attr(arr[1], value); - } - } - - } else { - template.find(EVENT_NS + '-'+key).html(value); - } - }); - }, - - _getScrollbarSize: function() { - // thx David - if(mfp.scrollbarSize === undefined) { - var scrollDiv = document.createElement("div"); - scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;'; - document.body.appendChild(scrollDiv); - mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth; - document.body.removeChild(scrollDiv); - } - return mfp.scrollbarSize; - } - -}; /* MagnificPopup core prototype end */ - - - - -/** - * Public static functions - */ -$.magnificPopup = { - instance: null, - proto: MagnificPopup.prototype, - modules: [], - - open: function(options, index) { - _checkInstance(); - - if(!options) { - options = {}; - } else { - options = $.extend(true, {}, options); - } - - - options.isObj = true; - options.index = index || 0; - return this.instance.open(options); - }, - - close: function() { - return $.magnificPopup.instance && $.magnificPopup.instance.close(); - }, - - registerModule: function(name, module) { - if(module.options) { - $.magnificPopup.defaults[name] = module.options; - } - $.extend(this.proto, module.proto); - this.modules.push(name); - }, - - defaults: { - - // Info about options is in docs: - // http://dimsemenov.com/plugins/magnific-popup/documentation.html#options - - disableOn: 0, - - key: null, - - midClick: false, - - mainClass: '', - - preloader: true, - - focus: '', // CSS selector of input to focus after popup is opened - - closeOnContentClick: false, - - closeOnBgClick: true, - - closeBtnInside: true, - - showCloseBtn: true, - - enableEscapeKey: true, - - modal: false, - - alignTop: false, - - removalDelay: 0, - - prependTo: null, - - fixedContentPos: 'auto', - - fixedBgPos: 'auto', - - overflowY: 'auto', - - closeMarkup: '', - - tClose: 'Close (Esc)', - - tLoading: 'Loading...' - - } -}; - - - -$.fn.magnificPopup = function(options) { - _checkInstance(); - - var jqEl = $(this); - - // We call some API method of first param is a string - if (typeof options === "string" ) { - - if(options === 'open') { - var items, - itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup, - index = parseInt(arguments[1], 10) || 0; - - if(itemOpts.items) { - items = itemOpts.items[index]; - } else { - items = jqEl; - if(itemOpts.delegate) { - items = items.find(itemOpts.delegate); - } - items = items.eq( index ); - } - mfp._openClick({mfpEl:items}, jqEl, itemOpts); - } else { - if(mfp.isOpen) - mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1)); - } - - } else { - // clone options obj - options = $.extend(true, {}, options); - - /* - * As Zepto doesn't support .data() method for objects - * and it works only in normal browsers - * we assign "options" object directly to the DOM element. FTW! - */ - if(_isJQ) { - jqEl.data('magnificPopup', options); - } else { - jqEl[0].magnificPopup = options; - } - - mfp.addGroup(jqEl, options); - - } - return jqEl; -}; - - -//Quick benchmark -/* -var start = performance.now(), - i, - rounds = 1000; - -for(i = 0; i < rounds; i++) { - -} -console.log('Test #1:', performance.now() - start); - -start = performance.now(); -for(i = 0; i < rounds; i++) { - -} -console.log('Test #2:', performance.now() - start); -*/ - - -/*>>core*/ - -/*>>inline*/ - -var INLINE_NS = 'inline', - _hiddenClass, - _inlinePlaceholder, - _lastInlineElement, - _putInlineElementsBack = function() { - if(_lastInlineElement) { - _inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach(); - _lastInlineElement = null; - } - }; - -$.magnificPopup.registerModule(INLINE_NS, { - options: { - hiddenClass: 'hide', // will be appended with `mfp-` prefix - markup: '', - tNotFound: 'Content not found' - }, - proto: { - - initInline: function() { - mfp.types.push(INLINE_NS); - - _mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() { - _putInlineElementsBack(); - }); - }, - - getInline: function(item, template) { - - _putInlineElementsBack(); - - if(item.src) { - var inlineSt = mfp.st.inline, - el = $(item.src); - - if(el.length) { - - // If target element has parent - we replace it with placeholder and put it back after popup is closed - var parent = el[0].parentNode; - if(parent && parent.tagName) { - if(!_inlinePlaceholder) { - _hiddenClass = inlineSt.hiddenClass; - _inlinePlaceholder = _getEl(_hiddenClass); - _hiddenClass = 'mfp-'+_hiddenClass; - } - // replace target inline element with placeholder - _lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass); - } - - mfp.updateStatus('ready'); - } else { - mfp.updateStatus('error', inlineSt.tNotFound); - el = $('
    '); - } - - item.inlineElement = el; - return el; - } - - mfp.updateStatus('ready'); - mfp._parseMarkup(template, {}, item); - return template; - } - } -}); - -/*>>inline*/ - -/*>>ajax*/ -var AJAX_NS = 'ajax', - _ajaxCur, - _removeAjaxCursor = function() { - if(_ajaxCur) { - _body.removeClass(_ajaxCur); - } - }, - _destroyAjaxRequest = function() { - _removeAjaxCursor(); - if(mfp.req) { - mfp.req.abort(); - } - }; - -$.magnificPopup.registerModule(AJAX_NS, { - - options: { - settings: null, - cursor: 'mfp-ajax-cur', - tError: 'The content could not be loaded.' - }, - - proto: { - initAjax: function() { - mfp.types.push(AJAX_NS); - _ajaxCur = mfp.st.ajax.cursor; - - _mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest); - _mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest); - }, - getAjax: function(item) { - - if(_ajaxCur) - _body.addClass(_ajaxCur); - - mfp.updateStatus('loading'); - - var opts = $.extend({ - url: item.src, - success: function(data, textStatus, jqXHR) { - var temp = { - data:data, - xhr:jqXHR - }; - - _mfpTrigger('ParseAjax', temp); - - mfp.appendContent( $(temp.data), AJAX_NS ); - - item.finished = true; - - _removeAjaxCursor(); - - mfp._setFocus(); - - setTimeout(function() { - mfp.wrap.addClass(READY_CLASS); - }, 16); - - mfp.updateStatus('ready'); - - _mfpTrigger('AjaxContentAdded'); - }, - error: function() { - _removeAjaxCursor(); - item.finished = item.loadError = true; - mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src)); - } - }, mfp.st.ajax.settings); - - mfp.req = $.ajax(opts); - - return ''; - } - } -}); - - - - - - - -/*>>ajax*/ - -/*>>image*/ -var _imgInterval, - _getTitle = function(item) { - if(item.data && item.data.title !== undefined) - return item.data.title; - - var src = mfp.st.image.titleSrc; - - if(src) { - if($.isFunction(src)) { - return src.call(mfp, item); - } else if(item.el) { - return item.el.attr(src) || ''; - } - } - return ''; - }; - -$.magnificPopup.registerModule('image', { - - options: { - markup: '
    '+ - '
    '+ - '
    '+ - '
    '+ - '
    '+ - '
    '+ - '
    '+ - '
    '+ - '
    '+ - '
    '+ - '
    '+ - '
    ', - cursor: 'mfp-zoom-out-cur', - titleSrc: 'title', - verticalFit: true, - tError: 'The image could not be loaded.' - }, - - proto: { - initImage: function() { - var imgSt = mfp.st.image, - ns = '.image'; - - mfp.types.push('image'); - - _mfpOn(OPEN_EVENT+ns, function() { - if(mfp.currItem.type === 'image' && imgSt.cursor) { - _body.addClass(imgSt.cursor); - } - }); - - _mfpOn(CLOSE_EVENT+ns, function() { - if(imgSt.cursor) { - _body.removeClass(imgSt.cursor); - } - _window.off('resize' + EVENT_NS); - }); - - _mfpOn('Resize'+ns, mfp.resizeImage); - if(mfp.isLowIE) { - _mfpOn('AfterChange', mfp.resizeImage); - } - }, - resizeImage: function() { - var item = mfp.currItem; - if(!item || !item.img) return; - - if(mfp.st.image.verticalFit) { - var decr = 0; - // fix box-sizing in ie7/8 - if(mfp.isLowIE) { - decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10); - } - item.img.css('max-height', mfp.wH-decr); - } - }, - _onImageHasSize: function(item) { - if(item.img) { - - item.hasSize = true; - - if(_imgInterval) { - clearInterval(_imgInterval); - } - - item.isCheckingImgSize = false; - - _mfpTrigger('ImageHasSize', item); - - if(item.imgHidden) { - if(mfp.content) - mfp.content.removeClass('mfp-loading'); - - item.imgHidden = false; - } - - } - }, - - /** - * Function that loops until the image has size to display elements that rely on it asap - */ - findImageSize: function(item) { - - var counter = 0, - img = item.img[0], - mfpSetInterval = function(delay) { - - if(_imgInterval) { - clearInterval(_imgInterval); - } - // decelerating interval that checks for size of an image - _imgInterval = setInterval(function() { - if(img.naturalWidth > 0) { - mfp._onImageHasSize(item); - return; - } - - if(counter > 200) { - clearInterval(_imgInterval); - } - - counter++; - if(counter === 3) { - mfpSetInterval(10); - } else if(counter === 40) { - mfpSetInterval(50); - } else if(counter === 100) { - mfpSetInterval(500); - } - }, delay); - }; - - mfpSetInterval(1); - }, - - getImage: function(item, template) { - - var guard = 0, - - // image load complete handler - onLoadComplete = function() { - if(item) { - if (item.img[0].complete) { - item.img.off('.mfploader'); - - if(item === mfp.currItem){ - mfp._onImageHasSize(item); - - mfp.updateStatus('ready'); - } - - item.hasSize = true; - item.loaded = true; - - _mfpTrigger('ImageLoadComplete'); - - } - else { - // if image complete check fails 200 times (20 sec), we assume that there was an error. - guard++; - if(guard < 200) { - setTimeout(onLoadComplete,100); - } else { - onLoadError(); - } - } - } - }, - - // image error handler - onLoadError = function() { - if(item) { - item.img.off('.mfploader'); - if(item === mfp.currItem){ - mfp._onImageHasSize(item); - mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); - } - - item.hasSize = true; - item.loaded = true; - item.loadError = true; - } - }, - imgSt = mfp.st.image; - - - var el = template.find('.mfp-img'); - if(el.length) { - var img = document.createElement('img'); - img.className = 'mfp-img'; - item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError); - img.src = item.src; - - // without clone() "error" event is not firing when IMG is replaced by new IMG - // TODO: find a way to avoid such cloning - if(el.is('img')) { - item.img = item.img.clone(); - } - - img = item.img[0]; - if(img.naturalWidth > 0) { - item.hasSize = true; - } else if(!img.width) { - item.hasSize = false; - } - } - - mfp._parseMarkup(template, { - title: _getTitle(item), - img_replaceWith: item.img - }, item); - - mfp.resizeImage(); - - if(item.hasSize) { - if(_imgInterval) clearInterval(_imgInterval); - - if(item.loadError) { - template.addClass('mfp-loading'); - mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); - } else { - template.removeClass('mfp-loading'); - mfp.updateStatus('ready'); - } - return template; - } - - mfp.updateStatus('loading'); - item.loading = true; - - if(!item.hasSize) { - item.imgHidden = true; - template.addClass('mfp-loading'); - mfp.findImageSize(item); - } - - return template; - } - } -}); - - - -/*>>image*/ - -/*>>zoom*/ -var hasMozTransform, - getHasMozTransform = function() { - if(hasMozTransform === undefined) { - hasMozTransform = document.createElement('p').style.MozTransform !== undefined; - } - return hasMozTransform; - }; - -$.magnificPopup.registerModule('zoom', { - - options: { - enabled: false, - easing: 'ease-in-out', - duration: 300, - opener: function(element) { - return element.is('img') ? element : element.find('img'); - } - }, - - proto: { - - initZoom: function() { - var zoomSt = mfp.st.zoom, - ns = '.zoom', - image; - - if(!zoomSt.enabled || !mfp.supportsTransition) { - return; - } - - var duration = zoomSt.duration, - getElToAnimate = function(image) { - var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'), - transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing, - cssObj = { - position: 'fixed', - zIndex: 9999, - left: 0, - top: 0, - '-webkit-backface-visibility': 'hidden' - }, - t = 'transition'; - - cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition; - - newImg.css(cssObj); - return newImg; - }, - showMainContent = function() { - mfp.content.css('visibility', 'visible'); - }, - openTimeout, - animatedImg; - - _mfpOn('BuildControls'+ns, function() { - if(mfp._allowZoom()) { - - clearTimeout(openTimeout); - mfp.content.css('visibility', 'hidden'); - - // Basically, all code below does is clones existing image, puts in on top of the current one and animated it - - image = mfp._getItemToZoom(); - - if(!image) { - showMainContent(); - return; - } - - animatedImg = getElToAnimate(image); - - animatedImg.css( mfp._getOffset() ); - - mfp.wrap.append(animatedImg); - - openTimeout = setTimeout(function() { - animatedImg.css( mfp._getOffset( true ) ); - openTimeout = setTimeout(function() { - - showMainContent(); - - setTimeout(function() { - animatedImg.remove(); - image = animatedImg = null; - _mfpTrigger('ZoomAnimationEnded'); - }, 16); // avoid blink when switching images - - }, duration); // this timeout equals animation duration - - }, 16); // by adding this timeout we avoid short glitch at the beginning of animation - - - // Lots of timeouts... - } - }); - _mfpOn(BEFORE_CLOSE_EVENT+ns, function() { - if(mfp._allowZoom()) { - - clearTimeout(openTimeout); - - mfp.st.removalDelay = duration; - - if(!image) { - image = mfp._getItemToZoom(); - if(!image) { - return; - } - animatedImg = getElToAnimate(image); - } - - - animatedImg.css( mfp._getOffset(true) ); - mfp.wrap.append(animatedImg); - mfp.content.css('visibility', 'hidden'); - - setTimeout(function() { - animatedImg.css( mfp._getOffset() ); - }, 16); - } - - }); - - _mfpOn(CLOSE_EVENT+ns, function() { - if(mfp._allowZoom()) { - showMainContent(); - if(animatedImg) { - animatedImg.remove(); - } - image = null; - } - }); - }, - - _allowZoom: function() { - return mfp.currItem.type === 'image'; - }, - - _getItemToZoom: function() { - if(mfp.currItem.hasSize) { - return mfp.currItem.img; - } else { - return false; - } - }, - - // Get element postion relative to viewport - _getOffset: function(isLarge) { - var el; - if(isLarge) { - el = mfp.currItem.img; - } else { - el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem); - } - - var offset = el.offset(); - var paddingTop = parseInt(el.css('padding-top'),10); - var paddingBottom = parseInt(el.css('padding-bottom'),10); - offset.top -= ( $(window).scrollTop() - paddingTop ); - - - /* - - Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa. - - */ - var obj = { - width: el.width(), - // fix Zepto height+padding issue - height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop - }; - - // I hate to do this, but there is no another option - if( getHasMozTransform() ) { - obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)'; - } else { - obj.left = offset.left; - obj.top = offset.top; - } - return obj; - } - - } -}); - - - -/*>>zoom*/ - -/*>>iframe*/ - -var IFRAME_NS = 'iframe', - _emptyPage = '//about:blank', - - _fixIframeBugs = function(isShowing) { - if(mfp.currTemplate[IFRAME_NS]) { - var el = mfp.currTemplate[IFRAME_NS].find('iframe'); - if(el.length) { - // reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug - if(!isShowing) { - el[0].src = _emptyPage; - } - - // IE8 black screen bug fix - if(mfp.isIE8) { - el.css('display', isShowing ? 'block' : 'none'); - } - } - } - }; - -$.magnificPopup.registerModule(IFRAME_NS, { - - options: { - markup: '
    '+ - '
    '+ - ''+ - '
    ', - - srcAction: 'iframe_src', - - // we don't care and support only one default type of URL by default - patterns: { - youtube: { - index: 'youtube.com', - id: 'v=', - src: '//www.youtube.com/embed/%id%?autoplay=1' - }, - vimeo: { - index: 'vimeo.com/', - id: '/', - src: '//player.vimeo.com/video/%id%?autoplay=1' - }, - gmaps: { - index: '//maps.google.', - src: '%id%&output=embed' - } - } - }, - - proto: { - initIframe: function() { - mfp.types.push(IFRAME_NS); - - _mfpOn('BeforeChange', function(e, prevType, newType) { - if(prevType !== newType) { - if(prevType === IFRAME_NS) { - _fixIframeBugs(); // iframe if removed - } else if(newType === IFRAME_NS) { - _fixIframeBugs(true); // iframe is showing - } - }// else { - // iframe source is switched, don't do anything - //} - }); - - _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() { - _fixIframeBugs(); - }); - }, - - getIframe: function(item, template) { - var embedSrc = item.src; - var iframeSt = mfp.st.iframe; - - $.each(iframeSt.patterns, function() { - if(embedSrc.indexOf( this.index ) > -1) { - if(this.id) { - if(typeof this.id === 'string') { - embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length); - } else { - embedSrc = this.id.call( this, embedSrc ); - } - } - embedSrc = this.src.replace('%id%', embedSrc ); - return false; // break; - } - }); - - var dataObj = {}; - if(iframeSt.srcAction) { - dataObj[iframeSt.srcAction] = embedSrc; - } - mfp._parseMarkup(template, dataObj, item); - - mfp.updateStatus('ready'); - - return template; - } - } -}); - - - -/*>>iframe*/ - -/*>>gallery*/ -/** - * Get looped index depending on number of slides - */ -var _getLoopedId = function(index) { - var numSlides = mfp.items.length; - if(index > numSlides - 1) { - return index - numSlides; - } else if(index < 0) { - return numSlides + index; - } - return index; - }, - _replaceCurrTotal = function(text, curr, total) { - return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total); - }; - -$.magnificPopup.registerModule('gallery', { - - options: { - enabled: false, - arrowMarkup: '', - preload: [0,2], - navigateByImgClick: true, - arrows: true, - - tPrev: 'Previous (Left arrow key)', - tNext: 'Next (Right arrow key)', - tCounter: '%curr% of %total%' - }, - - proto: { - initGallery: function() { - - var gSt = mfp.st.gallery, - ns = '.mfp-gallery', - supportsFastClick = Boolean($.fn.mfpFastClick); - - mfp.direction = true; // true - next, false - prev - - if(!gSt || !gSt.enabled ) return false; - - _wrapClasses += ' mfp-gallery'; - - _mfpOn(OPEN_EVENT+ns, function() { - - if(gSt.navigateByImgClick) { - mfp.wrap.on('click'+ns, '.mfp-img', function() { - if(mfp.items.length > 1) { - mfp.next(); - return false; - } - }); - } - - _document.on('keydown'+ns, function(e) { - if (e.keyCode === 37) { - mfp.prev(); - } else if (e.keyCode === 39) { - mfp.next(); - } - }); - }); - - _mfpOn('UpdateStatus'+ns, function(e, data) { - if(data.text) { - data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length); - } - }); - - _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) { - var l = mfp.items.length; - values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : ''; - }); - - _mfpOn('BuildControls' + ns, function() { - if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) { - var markup = gSt.arrowMarkup, - arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS), - arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS); - - var eName = supportsFastClick ? 'mfpFastClick' : 'click'; - arrowLeft[eName](function() { - mfp.prev(); - }); - arrowRight[eName](function() { - mfp.next(); - }); - - // Polyfill for :before and :after (adds elements with classes mfp-a and mfp-b) - if(mfp.isIE7) { - _getEl('b', arrowLeft[0], false, true); - _getEl('a', arrowLeft[0], false, true); - _getEl('b', arrowRight[0], false, true); - _getEl('a', arrowRight[0], false, true); - } - - mfp.container.append(arrowLeft.add(arrowRight)); - } - }); - - _mfpOn(CHANGE_EVENT+ns, function() { - if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout); - - mfp._preloadTimeout = setTimeout(function() { - mfp.preloadNearbyImages(); - mfp._preloadTimeout = null; - }, 16); - }); - - - _mfpOn(CLOSE_EVENT+ns, function() { - _document.off(ns); - mfp.wrap.off('click'+ns); - - if(mfp.arrowLeft && supportsFastClick) { - mfp.arrowLeft.add(mfp.arrowRight).destroyMfpFastClick(); - } - mfp.arrowRight = mfp.arrowLeft = null; - }); - - }, - next: function() { - mfp.direction = true; - mfp.index = _getLoopedId(mfp.index + 1); - mfp.updateItemHTML(); - }, - prev: function() { - mfp.direction = false; - mfp.index = _getLoopedId(mfp.index - 1); - mfp.updateItemHTML(); - }, - goTo: function(newIndex) { - mfp.direction = (newIndex >= mfp.index); - mfp.index = newIndex; - mfp.updateItemHTML(); - }, - preloadNearbyImages: function() { - var p = mfp.st.gallery.preload, - preloadBefore = Math.min(p[0], mfp.items.length), - preloadAfter = Math.min(p[1], mfp.items.length), - i; - - for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) { - mfp._preloadItem(mfp.index+i); - } - for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) { - mfp._preloadItem(mfp.index-i); - } - }, - _preloadItem: function(index) { - index = _getLoopedId(index); - - if(mfp.items[index].preloaded) { - return; - } - - var item = mfp.items[index]; - if(!item.parsed) { - item = mfp.parseEl( index ); - } - - _mfpTrigger('LazyLoad', item); - - if(item.type === 'image') { - item.img = $('').on('load.mfploader', function() { - item.hasSize = true; - }).on('error.mfploader', function() { - item.hasSize = true; - item.loadError = true; - _mfpTrigger('LazyLoadError', item); - }).attr('src', item.src); - } - - - item.preloaded = true; - } - } -}); - -/* -Touch Support that might be implemented some day - -addSwipeGesture: function() { - var startX, - moved, - multipleTouches; - - return; - - var namespace = '.mfp', - addEventNames = function(pref, down, move, up, cancel) { - mfp._tStart = pref + down + namespace; - mfp._tMove = pref + move + namespace; - mfp._tEnd = pref + up + namespace; - mfp._tCancel = pref + cancel + namespace; - }; - - if(window.navigator.msPointerEnabled) { - addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel'); - } else if('ontouchstart' in window) { - addEventNames('touch', 'start', 'move', 'end', 'cancel'); - } else { - return; - } - _window.on(mfp._tStart, function(e) { - var oE = e.originalEvent; - multipleTouches = moved = false; - startX = oE.pageX || oE.changedTouches[0].pageX; - }).on(mfp._tMove, function(e) { - if(e.originalEvent.touches.length > 1) { - multipleTouches = e.originalEvent.touches.length; - } else { - //e.preventDefault(); - moved = true; - } - }).on(mfp._tEnd + ' ' + mfp._tCancel, function(e) { - if(moved && !multipleTouches) { - var oE = e.originalEvent, - diff = startX - (oE.pageX || oE.changedTouches[0].pageX); - - if(diff > 20) { - mfp.next(); - } else if(diff < -20) { - mfp.prev(); - } - } - }); -}, -*/ - - -/*>>gallery*/ - -/*>>retina*/ - -var RETINA_NS = 'retina'; - -$.magnificPopup.registerModule(RETINA_NS, { - options: { - replaceSrc: function(item) { - return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; }); - }, - ratio: 1 // Function or number. Set to 1 to disable. - }, - proto: { - initRetina: function() { - if(window.devicePixelRatio > 1) { - - var st = mfp.st.retina, - ratio = st.ratio; - - ratio = !isNaN(ratio) ? ratio : ratio(); - - if(ratio > 1) { - _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) { - item.img.css({ - 'max-width': item.img[0].naturalWidth / ratio, - 'width': '100%' - }); - }); - _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) { - item.src = st.replaceSrc(item, ratio); - }); - } - } - - } - } -}); - -/*>>retina*/ - -/*>>fastclick*/ -/** - * FastClick event implementation. (removes 300ms delay on touch devices) - * Based on https://developers.google.com/mobile/articles/fast_buttons - * - * You may use it outside the Magnific Popup by calling just: - * - * $('.your-el').mfpFastClick(function() { - * console.log('Clicked!'); - * }); - * - * To unbind: - * $('.your-el').destroyMfpFastClick(); - * - * - * Note that it's a very basic and simple implementation, it blocks ghost click on the same element where it was bound. - * If you need something more advanced, use plugin by FT Labs https://github.com/ftlabs/fastclick - * - */ - -(function() { - var ghostClickDelay = 1000, - supportsTouch = 'ontouchstart' in window, - unbindTouchMove = function() { - _window.off('touchmove'+ns+' touchend'+ns); - }, - eName = 'mfpFastClick', - ns = '.'+eName; - - - // As Zepto.js doesn't have an easy way to add custom events (like jQuery), so we implement it in this way - $.fn.mfpFastClick = function(callback) { - - return $(this).each(function() { - - var elem = $(this), - lock; - - if( supportsTouch ) { - - var timeout, - startX, - startY, - pointerMoved, - point, - numPointers; - - elem.on('touchstart' + ns, function(e) { - pointerMoved = false; - numPointers = 1; - - point = e.originalEvent ? e.originalEvent.touches[0] : e.touches[0]; - startX = point.clientX; - startY = point.clientY; - - _window.on('touchmove'+ns, function(e) { - point = e.originalEvent ? e.originalEvent.touches : e.touches; - numPointers = point.length; - point = point[0]; - if (Math.abs(point.clientX - startX) > 10 || - Math.abs(point.clientY - startY) > 10) { - pointerMoved = true; - unbindTouchMove(); - } - }).on('touchend'+ns, function(e) { - unbindTouchMove(); - if(pointerMoved || numPointers > 1) { - return; - } - lock = true; - e.preventDefault(); - clearTimeout(timeout); - timeout = setTimeout(function() { - lock = false; - }, ghostClickDelay); - callback(); - }); - }); - - } - - elem.on('click' + ns, function() { - if(!lock) { - callback(); - } - }); - }); - }; - - $.fn.destroyMfpFastClick = function() { - $(this).off('touchstart' + ns + ' click' + ns); - if(supportsTouch) _window.off('touchmove'+ns+' touchend'+ns); - }; -})(); - -/*>>fastclick*/ - _checkInstance(); })(window.jQuery || window.Zepto); \ No newline at end of file diff --git a/vendors/jquery-magnific-popup/jquery.magnific-popup.min.js b/vendors/jquery-magnific-popup/jquery.magnific-popup.min.js deleted file mode 100644 index 4e3e16ffd..000000000 --- a/vendors/jquery-magnific-popup/jquery.magnific-popup.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! Magnific Popup - v0.9.9 - 2014-09-06 -* http://dimsemenov.com/plugins/magnific-popup/ -* Copyright (c) 2014 Dmitry Semenov; */ -(function(e){var t,n,i,o,r,a,s,l="Close",c="BeforeClose",d="AfterClose",u="BeforeAppend",p="MarkupParse",f="Open",m="Change",g="mfp",h="."+g,v="mfp-ready",C="mfp-removing",y="mfp-prevent-close",w=function(){},b=!!window.jQuery,I=e(window),x=function(e,n){t.ev.on(g+e+h,n)},k=function(t,n,i,o){var r=document.createElement("div");return r.className="mfp-"+t,i&&(r.innerHTML=i),o?n&&n.appendChild(r):(r=e(r),n&&r.appendTo(n)),r},T=function(n,i){t.ev.triggerHandler(g+n,i),t.st.callbacks&&(n=n.charAt(0).toLowerCase()+n.slice(1),t.st.callbacks[n]&&t.st.callbacks[n].apply(t,e.isArray(i)?i:[i]))},E=function(n){return n===s&&t.currTemplate.closeBtn||(t.currTemplate.closeBtn=e(t.st.closeMarkup.replace("%title%",t.st.tClose)),s=n),t.currTemplate.closeBtn},_=function(){e.magnificPopup.instance||(t=new w,t.init(),e.magnificPopup.instance=t)},S=function(){var e=document.createElement("p").style,t=["ms","O","Moz","Webkit"];if(void 0!==e.transition)return!0;for(;t.length;)if(t.pop()+"Transition"in e)return!0;return!1};w.prototype={constructor:w,init:function(){var n=navigator.appVersion;t.isIE7=-1!==n.indexOf("MSIE 7."),t.isIE8=-1!==n.indexOf("MSIE 8."),t.isLowIE=t.isIE7||t.isIE8,t.isAndroid=/android/gi.test(n),t.isIOS=/iphone|ipad|ipod/gi.test(n),t.supportsTransition=S(),t.probablyMobile=t.isAndroid||t.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),o=e(document),t.popupsCache={}},open:function(n){i||(i=e(document.body));var r;if(n.isObj===!1){t.items=n.items.toArray(),t.index=0;var s,l=n.items;for(r=0;l.length>r;r++)if(s=l[r],s.parsed&&(s=s.el[0]),s===n.el[0]){t.index=r;break}}else t.items=e.isArray(n.items)?n.items:[n.items],t.index=n.index||0;if(t.isOpen)return t.updateItemHTML(),void 0;t.types=[],a="",t.ev=n.mainEl&&n.mainEl.length?n.mainEl.eq(0):o,n.key?(t.popupsCache[n.key]||(t.popupsCache[n.key]={}),t.currTemplate=t.popupsCache[n.key]):t.currTemplate={},t.st=e.extend(!0,{},e.magnificPopup.defaults,n),t.fixedContentPos="auto"===t.st.fixedContentPos?!t.probablyMobile:t.st.fixedContentPos,t.st.modal&&(t.st.closeOnContentClick=!1,t.st.closeOnBgClick=!1,t.st.showCloseBtn=!1,t.st.enableEscapeKey=!1),t.bgOverlay||(t.bgOverlay=k("bg").on("click"+h,function(){t.close()}),t.wrap=k("wrap").attr("tabindex",-1).on("click"+h,function(e){t._checkIfClose(e.target)&&t.close()}),t.container=k("container",t.wrap)),t.contentContainer=k("content"),t.st.preloader&&(t.preloader=k("preloader",t.container,t.st.tLoading));var c=e.magnificPopup.modules;for(r=0;c.length>r;r++){var d=c[r];d=d.charAt(0).toUpperCase()+d.slice(1),t["init"+d].call(t)}T("BeforeOpen"),t.st.showCloseBtn&&(t.st.closeBtnInside?(x(p,function(e,t,n,i){n.close_replaceWith=E(i.type)}),a+=" mfp-close-btn-in"):t.wrap.append(E())),t.st.alignTop&&(a+=" mfp-align-top"),t.fixedContentPos?t.wrap.css({overflow:t.st.overflowY,overflowX:"hidden",overflowY:t.st.overflowY}):t.wrap.css({top:I.scrollTop(),position:"absolute"}),(t.st.fixedBgPos===!1||"auto"===t.st.fixedBgPos&&!t.fixedContentPos)&&t.bgOverlay.css({height:o.height(),position:"absolute"}),t.st.enableEscapeKey&&o.on("keyup"+h,function(e){27===e.keyCode&&t.close()}),I.on("resize"+h,function(){t.updateSize()}),t.st.closeOnContentClick||(a+=" mfp-auto-cursor"),a&&t.wrap.addClass(a);var u=t.wH=I.height(),m={};if(t.fixedContentPos&&t._hasScrollBar(u)){var g=t._getScrollbarSize();g&&(m.marginRight=g)}t.fixedContentPos&&(t.isIE7?e("body, html").css("overflow","hidden"):m.overflow="hidden");var C=t.st.mainClass;return t.isIE7&&(C+=" mfp-ie7"),C&&t._addClassToMFP(C),t.updateItemHTML(),T("BuildControls"),e("html").css(m),t.bgOverlay.add(t.wrap).prependTo(t.st.prependTo||i),t._lastFocusedEl=document.activeElement,setTimeout(function(){t.content?(t._addClassToMFP(v),t._setFocus()):t.bgOverlay.addClass(v),o.on("focusin"+h,t._onFocusIn)},16),t.isOpen=!0,t.updateSize(u),T(f),n},close:function(){t.isOpen&&(T(c),t.isOpen=!1,t.st.removalDelay&&!t.isLowIE&&t.supportsTransition?(t._addClassToMFP(C),setTimeout(function(){t._close()},t.st.removalDelay)):t._close())},_close:function(){T(l);var n=C+" "+v+" ";if(t.bgOverlay.detach(),t.wrap.detach(),t.container.empty(),t.st.mainClass&&(n+=t.st.mainClass+" "),t._removeClassFromMFP(n),t.fixedContentPos){var i={marginRight:""};t.isIE7?e("body, html").css("overflow",""):i.overflow="",e("html").css(i)}o.off("keyup"+h+" focusin"+h),t.ev.off(h),t.wrap.attr("class","mfp-wrap").removeAttr("style"),t.bgOverlay.attr("class","mfp-bg"),t.container.attr("class","mfp-container"),!t.st.showCloseBtn||t.st.closeBtnInside&&t.currTemplate[t.currItem.type]!==!0||t.currTemplate.closeBtn&&t.currTemplate.closeBtn.detach(),t._lastFocusedEl&&e(t._lastFocusedEl).focus(),t.currItem=null,t.content=null,t.currTemplate=null,t.prevHeight=0,T(d)},updateSize:function(e){if(t.isIOS){var n=document.documentElement.clientWidth/window.innerWidth,i=window.innerHeight*n;t.wrap.css("height",i),t.wH=i}else t.wH=e||I.height();t.fixedContentPos||t.wrap.css("height",t.wH),T("Resize")},updateItemHTML:function(){var n=t.items[t.index];t.contentContainer.detach(),t.content&&t.content.detach(),n.parsed||(n=t.parseEl(t.index));var i=n.type;if(T("BeforeChange",[t.currItem?t.currItem.type:"",i]),t.currItem=n,!t.currTemplate[i]){var o=t.st[i]?t.st[i].markup:!1;T("FirstMarkupParse",o),t.currTemplate[i]=o?e(o):!0}r&&r!==n.type&&t.container.removeClass("mfp-"+r+"-holder");var a=t["get"+i.charAt(0).toUpperCase()+i.slice(1)](n,t.currTemplate[i]);t.appendContent(a,i),n.preloaded=!0,T(m,n),r=n.type,t.container.prepend(t.contentContainer),T("AfterChange")},appendContent:function(e,n){t.content=e,e?t.st.showCloseBtn&&t.st.closeBtnInside&&t.currTemplate[n]===!0?t.content.find(".mfp-close").length||t.content.append(E()):t.content=e:t.content="",T(u),t.container.addClass("mfp-"+n+"-holder"),t.contentContainer.append(t.content)},parseEl:function(n){var i,o=t.items[n];if(o.tagName?o={el:e(o)}:(i=o.type,o={data:o,src:o.src}),o.el){for(var r=t.types,a=0;r.length>a;a++)if(o.el.hasClass("mfp-"+r[a])){i=r[a];break}o.src=o.el.attr("data-mfp-src"),o.src||(o.src=o.el.attr("href"))}return o.type=i||t.st.type||"inline",o.index=n,o.parsed=!0,t.items[n]=o,T("ElementParse",o),t.items[n]},addGroup:function(e,n){var i=function(i){i.mfpEl=this,t._openClick(i,e,n)};n||(n={});var o="click.magnificPopup";n.mainEl=e,n.items?(n.isObj=!0,e.off(o).on(o,i)):(n.isObj=!1,n.delegate?e.off(o).on(o,n.delegate,i):(n.items=e,e.off(o).on(o,i)))},_openClick:function(n,i,o){var r=void 0!==o.midClick?o.midClick:e.magnificPopup.defaults.midClick;if(r||2!==n.which&&!n.ctrlKey&&!n.metaKey){var a=void 0!==o.disableOn?o.disableOn:e.magnificPopup.defaults.disableOn;if(a)if(e.isFunction(a)){if(!a.call(t))return!0}else if(a>I.width())return!0;n.type&&(n.preventDefault(),t.isOpen&&n.stopPropagation()),o.el=e(n.mfpEl),o.delegate&&(o.items=i.find(o.delegate)),t.open(o)}},updateStatus:function(e,i){if(t.preloader){n!==e&&t.container.removeClass("mfp-s-"+n),i||"loading"!==e||(i=t.st.tLoading);var o={status:e,text:i};T("UpdateStatus",o),e=o.status,i=o.text,t.preloader.html(i),t.preloader.find("a").on("click",function(e){e.stopImmediatePropagation()}),t.container.addClass("mfp-s-"+e),n=e}},_checkIfClose:function(n){if(!e(n).hasClass(y)){var i=t.st.closeOnContentClick,o=t.st.closeOnBgClick;if(i&&o)return!0;if(!t.content||e(n).hasClass("mfp-close")||t.preloader&&n===t.preloader[0])return!0;if(n===t.content[0]||e.contains(t.content[0],n)){if(i)return!0}else if(o&&e.contains(document,n))return!0;return!1}},_addClassToMFP:function(e){t.bgOverlay.addClass(e),t.wrap.addClass(e)},_removeClassFromMFP:function(e){this.bgOverlay.removeClass(e),t.wrap.removeClass(e)},_hasScrollBar:function(e){return(t.isIE7?o.height():document.body.scrollHeight)>(e||I.height())},_setFocus:function(){(t.st.focus?t.content.find(t.st.focus).eq(0):t.wrap).focus()},_onFocusIn:function(n){return n.target===t.wrap[0]||e.contains(t.wrap[0],n.target)?void 0:(t._setFocus(),!1)},_parseMarkup:function(t,n,i){var o;i.data&&(n=e.extend(i.data,n)),T(p,[t,n,i]),e.each(n,function(e,n){if(void 0===n||n===!1)return!0;if(o=e.split("_"),o.length>1){var i=t.find(h+"-"+o[0]);if(i.length>0){var r=o[1];"replaceWith"===r?i[0]!==n[0]&&i.replaceWith(n):"img"===r?i.is("img")?i.attr("src",n):i.replaceWith(''):i.attr(o[1],n)}}else t.find(h+"-"+e).html(n)})},_getScrollbarSize:function(){if(void 0===t.scrollbarSize){var e=document.createElement("div");e.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(e),t.scrollbarSize=e.offsetWidth-e.clientWidth,document.body.removeChild(e)}return t.scrollbarSize}},e.magnificPopup={instance:null,proto:w.prototype,modules:[],open:function(t,n){return _(),t=t?e.extend(!0,{},t):{},t.isObj=!0,t.index=n||0,this.instance.open(t)},close:function(){return e.magnificPopup.instance&&e.magnificPopup.instance.close()},registerModule:function(t,n){n.options&&(e.magnificPopup.defaults[t]=n.options),e.extend(this.proto,n.proto),this.modules.push(t)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'',tClose:"Close (Esc)",tLoading:"Loading..."}},e.fn.magnificPopup=function(n){_();var i=e(this);if("string"==typeof n)if("open"===n){var o,r=b?i.data("magnificPopup"):i[0].magnificPopup,a=parseInt(arguments[1],10)||0;r.items?o=r.items[a]:(o=i,r.delegate&&(o=o.find(r.delegate)),o=o.eq(a)),t._openClick({mfpEl:o},i,r)}else t.isOpen&&t[n].apply(t,Array.prototype.slice.call(arguments,1));else n=e.extend(!0,{},n),b?i.data("magnificPopup",n):i[0].magnificPopup=n,t.addGroup(i,n);return i};var P,O,z,M="inline",B=function(){z&&(O.after(z.addClass(P)).detach(),z=null)};e.magnificPopup.registerModule(M,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){t.types.push(M),x(l+"."+M,function(){B()})},getInline:function(n,i){if(B(),n.src){var o=t.st.inline,r=e(n.src);if(r.length){var a=r[0].parentNode;a&&a.tagName&&(O||(P=o.hiddenClass,O=k(P),P="mfp-"+P),z=r.after(O).detach().removeClass(P)),t.updateStatus("ready")}else t.updateStatus("error",o.tNotFound),r=e("
    ");return n.inlineElement=r,r}return t.updateStatus("ready"),t._parseMarkup(i,{},n),i}}});var F,H="ajax",L=function(){F&&i.removeClass(F)},A=function(){L(),t.req&&t.req.abort()};e.magnificPopup.registerModule(H,{options:{settings:null,cursor:"mfp-ajax-cur",tError:'The content could not be loaded.'},proto:{initAjax:function(){t.types.push(H),F=t.st.ajax.cursor,x(l+"."+H,A),x("BeforeChange."+H,A)},getAjax:function(n){F&&i.addClass(F),t.updateStatus("loading");var o=e.extend({url:n.src,success:function(i,o,r){var a={data:i,xhr:r};T("ParseAjax",a),t.appendContent(e(a.data),H),n.finished=!0,L(),t._setFocus(),setTimeout(function(){t.wrap.addClass(v)},16),t.updateStatus("ready"),T("AjaxContentAdded")},error:function(){L(),n.finished=n.loadError=!0,t.updateStatus("error",t.st.ajax.tError.replace("%url%",n.src))}},t.st.ajax.settings);return t.req=e.ajax(o),""}}});var j,N=function(n){if(n.data&&void 0!==n.data.title)return n.data.title;var i=t.st.image.titleSrc;if(i){if(e.isFunction(i))return i.call(t,n);if(n.el)return n.el.attr(i)||""}return""};e.magnificPopup.registerModule("image",{options:{markup:'
    ',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'The image could not be loaded.'},proto:{initImage:function(){var e=t.st.image,n=".image";t.types.push("image"),x(f+n,function(){"image"===t.currItem.type&&e.cursor&&i.addClass(e.cursor)}),x(l+n,function(){e.cursor&&i.removeClass(e.cursor),I.off("resize"+h)}),x("Resize"+n,t.resizeImage),t.isLowIE&&x("AfterChange",t.resizeImage)},resizeImage:function(){var e=t.currItem;if(e&&e.img&&t.st.image.verticalFit){var n=0;t.isLowIE&&(n=parseInt(e.img.css("padding-top"),10)+parseInt(e.img.css("padding-bottom"),10)),e.img.css("max-height",t.wH-n)}},_onImageHasSize:function(e){e.img&&(e.hasSize=!0,j&&clearInterval(j),e.isCheckingImgSize=!1,T("ImageHasSize",e),e.imgHidden&&(t.content&&t.content.removeClass("mfp-loading"),e.imgHidden=!1))},findImageSize:function(e){var n=0,i=e.img[0],o=function(r){j&&clearInterval(j),j=setInterval(function(){return i.naturalWidth>0?(t._onImageHasSize(e),void 0):(n>200&&clearInterval(j),n++,3===n?o(10):40===n?o(50):100===n&&o(500),void 0)},r)};o(1)},getImage:function(n,i){var o=0,r=function(){n&&(n.img[0].complete?(n.img.off(".mfploader"),n===t.currItem&&(t._onImageHasSize(n),t.updateStatus("ready")),n.hasSize=!0,n.loaded=!0,T("ImageLoadComplete")):(o++,200>o?setTimeout(r,100):a()))},a=function(){n&&(n.img.off(".mfploader"),n===t.currItem&&(t._onImageHasSize(n),t.updateStatus("error",s.tError.replace("%url%",n.src))),n.hasSize=!0,n.loaded=!0,n.loadError=!0)},s=t.st.image,l=i.find(".mfp-img");if(l.length){var c=document.createElement("img");c.className="mfp-img",n.img=e(c).on("load.mfploader",r).on("error.mfploader",a),c.src=n.src,l.is("img")&&(n.img=n.img.clone()),c=n.img[0],c.naturalWidth>0?n.hasSize=!0:c.width||(n.hasSize=!1)}return t._parseMarkup(i,{title:N(n),img_replaceWith:n.img},n),t.resizeImage(),n.hasSize?(j&&clearInterval(j),n.loadError?(i.addClass("mfp-loading"),t.updateStatus("error",s.tError.replace("%url%",n.src))):(i.removeClass("mfp-loading"),t.updateStatus("ready")),i):(t.updateStatus("loading"),n.loading=!0,n.hasSize||(n.imgHidden=!0,i.addClass("mfp-loading"),t.findImageSize(n)),i)}}});var W,R=function(){return void 0===W&&(W=void 0!==document.createElement("p").style.MozTransform),W};e.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(e){return e.is("img")?e:e.find("img")}},proto:{initZoom:function(){var e,n=t.st.zoom,i=".zoom";if(n.enabled&&t.supportsTransition){var o,r,a=n.duration,s=function(e){var t=e.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),i="all "+n.duration/1e3+"s "+n.easing,o={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},r="transition";return o["-webkit-"+r]=o["-moz-"+r]=o["-o-"+r]=o[r]=i,t.css(o),t},d=function(){t.content.css("visibility","visible")};x("BuildControls"+i,function(){if(t._allowZoom()){if(clearTimeout(o),t.content.css("visibility","hidden"),e=t._getItemToZoom(),!e)return d(),void 0;r=s(e),r.css(t._getOffset()),t.wrap.append(r),o=setTimeout(function(){r.css(t._getOffset(!0)),o=setTimeout(function(){d(),setTimeout(function(){r.remove(),e=r=null,T("ZoomAnimationEnded")},16)},a)},16)}}),x(c+i,function(){if(t._allowZoom()){if(clearTimeout(o),t.st.removalDelay=a,!e){if(e=t._getItemToZoom(),!e)return;r=s(e)}r.css(t._getOffset(!0)),t.wrap.append(r),t.content.css("visibility","hidden"),setTimeout(function(){r.css(t._getOffset())},16)}}),x(l+i,function(){t._allowZoom()&&(d(),r&&r.remove(),e=null)})}},_allowZoom:function(){return"image"===t.currItem.type},_getItemToZoom:function(){return t.currItem.hasSize?t.currItem.img:!1},_getOffset:function(n){var i;i=n?t.currItem.img:t.st.zoom.opener(t.currItem.el||t.currItem);var o=i.offset(),r=parseInt(i.css("padding-top"),10),a=parseInt(i.css("padding-bottom"),10);o.top-=e(window).scrollTop()-r;var s={width:i.width(),height:(b?i.innerHeight():i[0].offsetHeight)-a-r};return R()?s["-moz-transform"]=s.transform="translate("+o.left+"px,"+o.top+"px)":(s.left=o.left,s.top=o.top),s}}});var Z="iframe",q="//about:blank",D=function(e){if(t.currTemplate[Z]){var n=t.currTemplate[Z].find("iframe");n.length&&(e||(n[0].src=q),t.isIE8&&n.css("display",e?"block":"none"))}};e.magnificPopup.registerModule(Z,{options:{markup:'
    ',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){t.types.push(Z),x("BeforeChange",function(e,t,n){t!==n&&(t===Z?D():n===Z&&D(!0))}),x(l+"."+Z,function(){D()})},getIframe:function(n,i){var o=n.src,r=t.st.iframe;e.each(r.patterns,function(){return o.indexOf(this.index)>-1?(this.id&&(o="string"==typeof this.id?o.substr(o.lastIndexOf(this.id)+this.id.length,o.length):this.id.call(this,o)),o=this.src.replace("%id%",o),!1):void 0});var a={};return r.srcAction&&(a[r.srcAction]=o),t._parseMarkup(i,a,n),t.updateStatus("ready"),i}}});var K=function(e){var n=t.items.length;return e>n-1?e-n:0>e?n+e:e},Y=function(e,t,n){return e.replace(/%curr%/gi,t+1).replace(/%total%/gi,n)};e.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var n=t.st.gallery,i=".mfp-gallery",r=Boolean(e.fn.mfpFastClick);return t.direction=!0,n&&n.enabled?(a+=" mfp-gallery",x(f+i,function(){n.navigateByImgClick&&t.wrap.on("click"+i,".mfp-img",function(){return t.items.length>1?(t.next(),!1):void 0}),o.on("keydown"+i,function(e){37===e.keyCode?t.prev():39===e.keyCode&&t.next()})}),x("UpdateStatus"+i,function(e,n){n.text&&(n.text=Y(n.text,t.currItem.index,t.items.length))}),x(p+i,function(e,i,o,r){var a=t.items.length;o.counter=a>1?Y(n.tCounter,r.index,a):""}),x("BuildControls"+i,function(){if(t.items.length>1&&n.arrows&&!t.arrowLeft){var i=n.arrowMarkup,o=t.arrowLeft=e(i.replace(/%title%/gi,n.tPrev).replace(/%dir%/gi,"left")).addClass(y),a=t.arrowRight=e(i.replace(/%title%/gi,n.tNext).replace(/%dir%/gi,"right")).addClass(y),s=r?"mfpFastClick":"click";o[s](function(){t.prev()}),a[s](function(){t.next()}),t.isIE7&&(k("b",o[0],!1,!0),k("a",o[0],!1,!0),k("b",a[0],!1,!0),k("a",a[0],!1,!0)),t.container.append(o.add(a))}}),x(m+i,function(){t._preloadTimeout&&clearTimeout(t._preloadTimeout),t._preloadTimeout=setTimeout(function(){t.preloadNearbyImages(),t._preloadTimeout=null},16)}),x(l+i,function(){o.off(i),t.wrap.off("click"+i),t.arrowLeft&&r&&t.arrowLeft.add(t.arrowRight).destroyMfpFastClick(),t.arrowRight=t.arrowLeft=null}),void 0):!1},next:function(){t.direction=!0,t.index=K(t.index+1),t.updateItemHTML()},prev:function(){t.direction=!1,t.index=K(t.index-1),t.updateItemHTML()},goTo:function(e){t.direction=e>=t.index,t.index=e,t.updateItemHTML()},preloadNearbyImages:function(){var e,n=t.st.gallery.preload,i=Math.min(n[0],t.items.length),o=Math.min(n[1],t.items.length);for(e=1;(t.direction?o:i)>=e;e++)t._preloadItem(t.index+e);for(e=1;(t.direction?i:o)>=e;e++)t._preloadItem(t.index-e)},_preloadItem:function(n){if(n=K(n),!t.items[n].preloaded){var i=t.items[n];i.parsed||(i=t.parseEl(n)),T("LazyLoad",i),"image"===i.type&&(i.img=e('').on("load.mfploader",function(){i.hasSize=!0}).on("error.mfploader",function(){i.hasSize=!0,i.loadError=!0,T("LazyLoadError",i)}).attr("src",i.src)),i.preloaded=!0}}}});var U="retina";e.magnificPopup.registerModule(U,{options:{replaceSrc:function(e){return e.src.replace(/\.\w+$/,function(e){return"@2x"+e})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var e=t.st.retina,n=e.ratio;n=isNaN(n)?n():n,n>1&&(x("ImageHasSize."+U,function(e,t){t.img.css({"max-width":t.img[0].naturalWidth/n,width:"100%"})}),x("ElementParse."+U,function(t,i){i.src=e.replaceSrc(i,n)}))}}}}),function(){var t=1e3,n="ontouchstart"in window,i=function(){I.off("touchmove"+r+" touchend"+r)},o="mfpFastClick",r="."+o;e.fn.mfpFastClick=function(o){return e(this).each(function(){var a,s=e(this);if(n){var l,c,d,u,p,f;s.on("touchstart"+r,function(e){u=!1,f=1,p=e.originalEvent?e.originalEvent.touches[0]:e.touches[0],c=p.clientX,d=p.clientY,I.on("touchmove"+r,function(e){p=e.originalEvent?e.originalEvent.touches:e.touches,f=p.length,p=p[0],(Math.abs(p.clientX-c)>10||Math.abs(p.clientY-d)>10)&&(u=!0,i())}).on("touchend"+r,function(e){i(),u||f>1||(a=!0,e.preventDefault(),clearTimeout(l),l=setTimeout(function(){a=!1},t),o())})})}s.on("click"+r,function(){a||o()})})},e.fn.destroyMfpFastClick=function(){e(this).off("touchstart"+r+" click"+r),n&&I.off("touchmove"+r+" touchend"+r)}}(),_()})(window.jQuery||window.Zepto); \ No newline at end of file diff --git a/vendors/jquery-magnific-popup/magnific-popup-animations.css b/vendors/jquery-magnific-popup/magnific-popup-animations.css deleted file mode 100644 index 3dfd27a65..000000000 --- a/vendors/jquery-magnific-popup/magnific-popup-animations.css +++ /dev/null @@ -1,45 +0,0 @@ - -/* overlay at start */ -.mfp-fade.mfp-bg { - opacity: 0; - - -webkit-transition: all 0.2s ease-out; - -moz-transition: all 0.2s ease-out; - transition: all 0.2s ease-out; -} -/* overlay animate in */ -.mfp-fade.mfp-bg.mfp-ready { - opacity: 0.8; -} -/* overlay animate out */ -.mfp-fade.mfp-bg.mfp-removing { - opacity: 0; -} - -/* content at start */ -.mfp-fade.mfp-wrap .mfp-content { - opacity: 0; - - -webkit-transition: all 0.15s ease-out; - -moz-transition: all 0.15s ease-out; - transition: all 0.15s ease-out; - - -webkit-transform: translateX(-50px); - -moz-transform: translateX(-50px); - transform: translateX(-50px); -} - -/* content animate it */ -.mfp-fade.mfp-wrap.mfp-ready .mfp-content { - opacity: 1; - -webkit-transform: translateX(0); - -moz-transform: translateX(0); - transform: translateX(0); -} -/* content animate out */ -.mfp-fade.mfp-wrap.mfp-removing .mfp-content { - opacity: 0; - -webkit-transform: translateX(50px); - -moz-transform: translateX(50px); - transform: translateX(50px); -} diff --git a/vendors/jquery-magnific-popup/magnific-popup.css b/vendors/jquery-magnific-popup/magnific-popup.css deleted file mode 100644 index 798ac9d8f..000000000 --- a/vendors/jquery-magnific-popup/magnific-popup.css +++ /dev/null @@ -1,368 +0,0 @@ -/* Magnific Popup CSS */ -.mfp-bg { - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 1042; - overflow: hidden; - position: fixed; - background: #0b0b0b; - opacity: 0.8; - filter: alpha(opacity=80); } - -.mfp-wrap { - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 1043; - position: fixed; - outline: none !important; - -webkit-backface-visibility: hidden; } - -.mfp-container { - text-align: center; - position: absolute; - width: 100%; - height: 100%; - left: 0; - top: 0; - padding: 0 8px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; } - -.mfp-container:before { - content: ''; - display: inline-block; - height: 100%; - vertical-align: middle; } - -.mfp-align-top .mfp-container:before { - display: none; } - -.mfp-content { - position: relative; - display: inline-block; - vertical-align: middle; - margin: 0 auto; - text-align: left; - z-index: 1045; } - -.mfp-inline-holder .mfp-content, .mfp-ajax-holder .mfp-content { - width: 100%; - cursor: auto; } - -.mfp-ajax-cur { - cursor: progress; } - -.mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close { - cursor: -moz-zoom-out; - cursor: -webkit-zoom-out; - cursor: zoom-out; } - -.mfp-zoom { - cursor: pointer; - cursor: -webkit-zoom-in; - cursor: -moz-zoom-in; - cursor: zoom-in; } - -.mfp-auto-cursor .mfp-content { - cursor: auto; } - -.mfp-close, .mfp-arrow, .mfp-preloader, .mfp-counter { - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; } - -.mfp-loading.mfp-figure { - display: none; } - -.mfp-hide { - display: none !important; } - -.mfp-preloader { - color: #cccccc; - position: absolute; - top: 50%; - width: auto; - text-align: center; - margin-top: -0.8em; - left: 8px; - right: 8px; - z-index: 1044; } - .mfp-preloader a { - color: #cccccc; } - .mfp-preloader a:hover { - color: white; } - -.mfp-s-ready .mfp-preloader { - display: none; } - -.mfp-s-error .mfp-content { - display: none; } - -button.mfp-close, button.mfp-arrow { - overflow: visible; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; - display: block; - outline: none; - padding: 0; - z-index: 1046; - -webkit-box-shadow: none; - box-shadow: none; } -button::-moz-focus-inner { - padding: 0; - border: 0; } - -.mfp-close { - width: 44px; - height: 44px; - line-height: 44px; - position: absolute; - right: 0; - top: 0; - text-decoration: none; - text-align: center; - opacity: 0.65; - filter: alpha(opacity=65); - padding: 0 0 18px 10px; - color: white; - font-style: normal; - font-size: 28px; - font-family: Arial, Baskerville, monospace; } - .mfp-close:hover, .mfp-close:focus { - opacity: 1; - filter: alpha(opacity=100); } - .mfp-close:active { - top: 1px; } - -.mfp-close-btn-in .mfp-close { - color: #333333; } - -.mfp-image-holder .mfp-close, .mfp-iframe-holder .mfp-close { - color: white; - right: -6px; - text-align: right; - padding-right: 6px; - width: 100%; } - -.mfp-counter { - position: absolute; - top: 0; - right: 0; - color: #cccccc; - font-size: 12px; - line-height: 18px; } - -.mfp-arrow { - position: absolute; - opacity: 0.65; - filter: alpha(opacity=65); - margin: 0; - top: 50%; - margin-top: -55px; - padding: 0; - width: 90px; - height: 110px; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } - .mfp-arrow:active { - margin-top: -54px; } - .mfp-arrow:hover, .mfp-arrow:focus { - opacity: 1; - filter: alpha(opacity=100); } - .mfp-arrow:before, .mfp-arrow:after, .mfp-arrow .mfp-b, .mfp-arrow .mfp-a { - content: ''; - display: block; - width: 0; - height: 0; - position: absolute; - left: 0; - top: 0; - margin-top: 35px; - margin-left: 35px; - border: medium inset transparent; } - .mfp-arrow:after, .mfp-arrow .mfp-a { - border-top-width: 13px; - border-bottom-width: 13px; - top: 8px; } - .mfp-arrow:before, .mfp-arrow .mfp-b { - border-top-width: 21px; - border-bottom-width: 21px; - opacity: 0.7; } - -.mfp-arrow-left { - left: 0; } - .mfp-arrow-left:after, .mfp-arrow-left .mfp-a { - border-right: 17px solid white; - margin-left: 31px; } - .mfp-arrow-left:before, .mfp-arrow-left .mfp-b { - margin-left: 25px; - border-right: 27px solid #3f3f3f; } - -.mfp-arrow-right { - right: 0; } - .mfp-arrow-right:after, .mfp-arrow-right .mfp-a { - border-left: 17px solid white; - margin-left: 39px; } - .mfp-arrow-right:before, .mfp-arrow-right .mfp-b { - border-left: 27px solid #3f3f3f; } - -.mfp-iframe-holder { - padding-top: 40px; - padding-bottom: 40px; } - .mfp-iframe-holder .mfp-content { - line-height: 0; - width: 100%; - max-width: 900px; } - .mfp-iframe-holder .mfp-close { - top: -40px; } - -.mfp-iframe-scaler { - width: 100%; - height: 0; - overflow: hidden; - padding-top: 56.25%; } - .mfp-iframe-scaler iframe { - position: absolute; - display: block; - top: 0; - left: 0; - width: 100%; - height: 100%; - box-shadow: 0 0 8px rgba(0, 0, 0, 0.6); - background: black; } - -/* Main image in popup */ -img.mfp-img { - width: auto; - max-width: 100%; - height: auto; - display: block; - line-height: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 40px 0 40px; - margin: 0 auto; } - -/* The shadow behind the image */ -.mfp-figure { - line-height: 0; } - .mfp-figure:after { - content: ''; - position: absolute; - left: 0; - top: 40px; - bottom: 40px; - display: block; - right: 0; - width: auto; - height: auto; - z-index: -1; - box-shadow: 0 0 8px rgba(0, 0, 0, 0.6); - background: #444444; } - .mfp-figure small { - color: #bdbdbd; - display: block; - font-size: 12px; - line-height: 14px; } - .mfp-figure figure { - margin: 0; } - -.mfp-bottom-bar { - margin-top: -36px; - position: absolute; - top: 100%; - left: 0; - width: 100%; - cursor: auto; } - -.mfp-title { - text-align: left; - line-height: 18px; - color: #f3f3f3; - word-wrap: break-word; - padding-right: 36px; } - -.mfp-image-holder .mfp-content { - max-width: 100%; } - -.mfp-gallery .mfp-image-holder .mfp-figure { - cursor: pointer; } - -@media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) { - /** - * Remove all paddings around the image on small screen - */ - .mfp-img-mobile .mfp-image-holder { - padding-left: 0; - padding-right: 0; } - .mfp-img-mobile img.mfp-img { - padding: 0; } - .mfp-img-mobile .mfp-figure:after { - top: 0; - bottom: 0; } - .mfp-img-mobile .mfp-figure small { - display: inline; - margin-left: 5px; } - .mfp-img-mobile .mfp-bottom-bar { - background: rgba(0, 0, 0, 0.6); - bottom: 0; - margin: 0; - top: auto; - padding: 3px 5px; - position: fixed; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; } - .mfp-img-mobile .mfp-bottom-bar:empty { - padding: 0; } - .mfp-img-mobile .mfp-counter { - right: 5px; - top: 3px; } - .mfp-img-mobile .mfp-close { - top: 0; - right: 0; - width: 35px; - height: 35px; - line-height: 35px; - background: rgba(0, 0, 0, 0.6); - position: fixed; - text-align: center; - padding: 0; } } - -@media all and (max-width: 900px) { - .mfp-arrow { - -webkit-transform: scale(0.75); - transform: scale(0.75); } - .mfp-arrow-left { - -webkit-transform-origin: 0; - transform-origin: 0; } - .mfp-arrow-right { - -webkit-transform-origin: 100%; - transform-origin: 100%; } - .mfp-container { - padding-left: 6px; - padding-right: 6px; } } - -.mfp-ie7 .mfp-img { - padding: 0; } -.mfp-ie7 .mfp-bottom-bar { - width: 600px; - left: 50%; - margin-left: -300px; - margin-top: 5px; - padding-bottom: 5px; } -.mfp-ie7 .mfp-container { - padding: 0; } -.mfp-ie7 .mfp-content { - padding-top: 44px; } -.mfp-ie7 .mfp-close { - top: 0; - right: 0; - padding-top: 0; } diff --git a/vendors/jquery-magnific-popup/magnific-popup.jquery.json b/vendors/jquery-magnific-popup/magnific-popup.jquery.json deleted file mode 100644 index a7de75fb2..000000000 --- a/vendors/jquery-magnific-popup/magnific-popup.jquery.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "magnific-popup", - "title": "Magnific Popup", - "description": "Fast, light, mobile-friendly and responsive lightbox and modal dialog plugin. Open inline HTML, ajax loaded content, image, form, iframe (YouTube video, Vimeo, Google Maps), photo gallery. Animation effects added with CSS3 transitions. For jQuery or Zepto.", - "version": "0.9.9", - "homepage": "http://dimsemenov.com/plugins/magnific-popup/", - "demo": "http://dimsemenov.com/plugins/magnific-popup/", - "docs": "http://dimsemenov.com/plugins/magnific-popup/documentation.html", - "author": { - "name": "Dmitry Semenov", - "email": "diiiimaaaa@gmail.com", - "url": "http://dimsemenov.com" - }, - "repository": { - "type": "git", - "url": "https://github.com/dimsemenov/Magnific-Popup.git" - }, - "bugs": "https://github.com/dimsemenov/Magnific-Popup/issues", - "dependencies": { - "jquery": ">=1.7.2" - }, - "keywords": ["lightbox","popup","modal","window","dialog","ui","gallery","slideshow","video","image","ajax","html5","animation","jquery","photo","responsive","mobile"], - "licenses": [ - { - "type": "MIT", - "url": "http://www.opensource.org/licenses/mit-license.php" - } - ] -} \ No newline at end of file diff --git a/vendors/jquery-magnific-popup/package.json b/vendors/jquery-magnific-popup/package.json deleted file mode 100644 index b2b4984a4..000000000 --- a/vendors/jquery-magnific-popup/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "magnific-popup", - - "version": "0.9.9", - "title": "Magnific Popup", - "description": "Lightbox and modal dialog plugin. Can display inline HTML, iframes (YouTube video, Vimeo, Google Maps), or an image gallery. Animation effects are added with CSS3 transitions. For jQuery or Zepto.", - "keywords": ["lightbox","popup","modal","window","dialog","gallery","jquery","photo","responsive","mobile"], - "author": { - "name": "Dmitry Semenov", - "email": "diiiimaaaa@gmail.com", - "web": "http://dimsemenov.com" - }, - "license": "MIT", - "bugs": { - "url": "https://github.com/dimsemenov/Magnific-Popup/issues" - }, - "main": "dist/jquery.magnific-popup.js", - "homepage": "http://dimsemenov.com/plugins/magnific-popup/", - - - - "engines": { - "node": ">= 0.8.0" - }, - "scripts": { - "test": "grunt jshint" - }, - "devDependencies": { - "grunt-contrib-jshint": "~0.1.1", - "grunt-contrib-concat": "~0.1.2", - "grunt-contrib-uglify": "~0.1.1", - "grunt-contrib-watch": "~0.2.0", - "grunt-contrib-clean": "~0.4.0", - "grunt": "~0.4.0", - "grunt-contrib-cssmin": "~0.4.1", - "grunt-contrib-copy": "~0.4.0", - "grunt-jekyll": "~0.3.9", - "grunt-sass": "~0.6.1" - }, - "repository": { - "type": "git", - "url": "https://github.com/dimsemenov/Magnific-Popup.git" - } -} diff --git a/vendors/jquery-ui.touch-punch/jquery.ui.touch-punch.min.js b/vendors/jquery-ui.touch-punch/jquery.ui.touch-punch.min.js deleted file mode 100644 index 31272ce6f..000000000 --- a/vendors/jquery-ui.touch-punch/jquery.ui.touch-punch.min.js +++ /dev/null @@ -1,11 +0,0 @@ -/*! - * jQuery UI Touch Punch 0.2.3 - * - * Copyright 2011–2014, Dave Furfero - * Dual licensed under the MIT or GPL Version 2 licenses. - * - * Depends: - * jquery.ui.widget.js - * jquery.ui.mouse.js - */ -!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery); \ No newline at end of file diff --git a/vendors/knockout-punches/knockout.punches.js b/vendors/knockout-punches/knockout.punches.js deleted file mode 100644 index 62d50297c..000000000 --- a/vendors/knockout-punches/knockout.punches.js +++ /dev/null @@ -1,589 +0,0 @@ -/** - * @license Knockout.Punches - * Enhanced binding syntaxes for Knockout 3+ - * (c) Michael Best - * License: MIT (http://www.opensource.org/licenses/mit-license.php) - * Version 0.5.0 - */ -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['knockout'], factory); - } else { - // Browser globals - factory(ko); - } -}(function(ko) { - -// Add a preprocess function to a binding handler. -function addBindingPreprocessor(bindingKeyOrHandler, preprocessFn) { - return chainPreprocessor(getOrCreateHandler(bindingKeyOrHandler), 'preprocess', preprocessFn); -} - -// These utility functions are separated out because they're also used by -// preprocessBindingProperty - -// Get the binding handler or create a new, empty one -function getOrCreateHandler(bindingKeyOrHandler) { - return typeof bindingKeyOrHandler === 'object' ? bindingKeyOrHandler : - (ko.getBindingHandler(bindingKeyOrHandler) || (ko.bindingHandlers[bindingKeyOrHandler] = {})); -} -// Add a preprocess function -function chainPreprocessor(obj, prop, fn) { - if (obj[prop]) { - // If the handler already has a preprocess function, chain the new - // one after the existing one. If the previous function in the chain - // returns a falsy value (to remove the binding), the chain ends. This - // method allows each function to modify and return the binding value. - var previousFn = obj[prop]; - obj[prop] = function(value, binding, addBinding) { - value = previousFn.call(this, value, binding, addBinding); - if (value) - return fn.call(this, value, binding, addBinding); - }; - } else { - obj[prop] = fn; - } - return obj; -} - -// Add a preprocessNode function to the binding provider. If a -// function already exists, chain the new one after it. This calls -// each function in the chain until one modifies the node. This -// method allows only one function to modify the node. -function addNodePreprocessor(preprocessFn) { - var provider = ko.bindingProvider.instance; - if (provider.preprocessNode) { - var previousPreprocessFn = provider.preprocessNode; - provider.preprocessNode = function(node) { - var newNodes = previousPreprocessFn.call(this, node); - if (!newNodes) - newNodes = preprocessFn.call(this, node); - return newNodes; - }; - } else { - provider.preprocessNode = preprocessFn; - } -} - -function addBindingHandlerCreator(matchRegex, callbackFn) { - var oldGetHandler = ko.getBindingHandler; - ko.getBindingHandler = function(bindingKey) { - var match; - return oldGetHandler(bindingKey) || ((match = bindingKey.match(matchRegex)) && callbackFn(match, bindingKey)); - }; -} - -// Create shortcuts to commonly used ko functions -var ko_unwrap = ko.unwrap; - -// Create "punches" object and export utility functions -var ko_punches = ko.punches = { - utils: { - addBindingPreprocessor: addBindingPreprocessor, - addNodePreprocessor: addNodePreprocessor, - addBindingHandlerCreator: addBindingHandlerCreator, - - // previous names retained for backwards compitibility - setBindingPreprocessor: addBindingPreprocessor, - setNodePreprocessor: addNodePreprocessor - } -}; - -ko_punches.enableAll = function () { - // Enable interpolation markup - enableInterpolationMarkup(); - enableAttributeInterpolationMarkup(); - - // Enable auto-namspacing of attr, css, event, and style - enableAutoNamespacedSyntax('attr'); - enableAutoNamespacedSyntax('css'); - enableAutoNamespacedSyntax('event'); - enableAutoNamespacedSyntax('style'); - - // Enable filter syntax for text, html, and attr - enableTextFilter('text'); - enableTextFilter('html'); - addDefaultNamespacedBindingPreprocessor('attr', filterPreprocessor); - - // Enable wrapped callbacks for click, submit, event, optionsAfterRender, and template options - enableWrappedCallback('click'); - enableWrappedCallback('submit'); - enableWrappedCallback('optionsAfterRender'); - addDefaultNamespacedBindingPreprocessor('event', wrappedCallbackPreprocessor); - addBindingPropertyPreprocessor('template', 'beforeRemove', wrappedCallbackPreprocessor); - addBindingPropertyPreprocessor('template', 'afterAdd', wrappedCallbackPreprocessor); - addBindingPropertyPreprocessor('template', 'afterRender', wrappedCallbackPreprocessor); -}; -// Convert input in the form of `expression | filter1 | filter2:arg1:arg2` to a function call format -// with filters accessed as ko.filters.filter1, etc. -function filterPreprocessor(input) { - // Check if the input contains any | characters; if not, just return - if (input.indexOf('|') === -1) - return input; - - // Split the input into tokens, in which | and : are individual tokens, quoted strings are ignored, and all tokens are space-trimmed - var tokens = input.match(/"([^"\\]|\\.)*"|'([^'\\]|\\.)*'|\|\||[|:]|[^\s|:"'][^|:"']*[^\s|:"']|[^\s|:"']/g); - if (tokens && tokens.length > 1) { - // Append a line so that we don't need a separate code block to deal with the last item - tokens.push('|'); - input = tokens[0]; - var lastToken, token, inFilters = false, nextIsFilter = false; - for (var i = 1, token; token = tokens[i]; ++i) { - if (token === '|') { - if (inFilters) { - if (lastToken === ':') - input += "undefined"; - input += ')'; - } - nextIsFilter = true; - inFilters = true; - } else { - if (nextIsFilter) { - input = "ko.filters['" + token + "'](" + input; - } else if (inFilters && token === ':') { - if (lastToken === ':') - input += "undefined"; - input += ","; - } else { - input += token; - } - nextIsFilter = false; - } - lastToken = token; - } - } - return input; -} - -// Set the filter preprocessor for a specific binding -function enableTextFilter(bindingKeyOrHandler) { - addBindingPreprocessor(bindingKeyOrHandler, filterPreprocessor); -} - -var filters = {}; - -// Convert value to uppercase -filters.uppercase = function(value) { - return String.prototype.toUpperCase.call(ko_unwrap(value)); -}; - -// Convert value to lowercase -filters.lowercase = function(value) { - return String.prototype.toLowerCase.call(ko_unwrap(value)); -}; - -// Return default value if the input value is empty or null -filters['default'] = function (value, defaultValue) { - value = ko_unwrap(value); - if (typeof value === "function") { - return value; - } - if (typeof value === "string") { - return trim(value) === '' ? defaultValue : value; - } - return value == null || value.length == 0 ? defaultValue : value; -}; - -// Return the value with the search string replaced with the replacement string -filters.replace = function(value, search, replace) { - return String.prototype.replace.call(ko_unwrap(value), search, replace); -}; - -filters.fit = function(value, length, replacement, trimWhere) { - value = ko_unwrap(value); - if (length && ('' + value).length > length) { - replacement = '' + (replacement || '...'); - length = length - replacement.length; - value = '' + value; - switch (trimWhere) { - case 'left': - return replacement + value.slice(-length); - case 'middle': - var leftLen = Math.ceil(length / 2); - return value.substr(0, leftLen) + replacement + value.slice(leftLen-length); - default: - return value.substr(0, length) + replacement; - } - } else { - return value; - } -}; - -// Convert a model object to JSON -filters.json = function(rootObject, space, replacer) { // replacer and space are optional - return ko.toJSON(rootObject, replacer, space); -}; - -// Format a number using the browser's toLocaleString -filters.number = function(value) { - return (+ko_unwrap(value)).toLocaleString(); -}; - -// Export the filters object for general access -ko.filters = filters; - -// Export the preprocessor functions -ko_punches.textFilter = { - preprocessor: filterPreprocessor, - enableForBinding: enableTextFilter -}; -// Support dynamically-created, namespaced bindings. The binding key syntax is -// "namespace.binding". Within a certain namespace, we can dynamically create the -// handler for any binding. This is particularly useful for bindings that work -// the same way, but just set a different named value, such as for element -// attributes or CSS classes. -var namespacedBindingMatch = /([^\.]+)\.(.+)/, namespaceDivider = '.'; -addBindingHandlerCreator(namespacedBindingMatch, function (match, bindingKey) { - var namespace = match[1], - namespaceHandler = ko.bindingHandlers[namespace]; - if (namespaceHandler) { - var bindingName = match[2], - handlerFn = namespaceHandler.getNamespacedHandler || defaultGetNamespacedHandler, - handler = handlerFn.call(namespaceHandler, bindingName, namespace, bindingKey); - ko.bindingHandlers[bindingKey] = handler; - return handler; - } -}); - -// Knockout's built-in bindings "attr", "event", "css" and "style" include the idea of -// namespaces, representing it using a single binding that takes an object map of names -// to values. This default handler translates a binding of "namespacedName: value" -// to "namespace: {name: value}" to automatically support those built-in bindings. -function defaultGetNamespacedHandler(name, namespace, namespacedName) { - var handler = ko.utils.extend({}, this); - function setHandlerFunction(funcName) { - if (handler[funcName]) { - handler[funcName] = function(element, valueAccessor) { - function subValueAccessor() { - var result = {}; - result[name] = valueAccessor(); - return result; - } - var args = Array.prototype.slice.call(arguments, 0); - args[1] = subValueAccessor; - return ko.bindingHandlers[namespace][funcName].apply(this, args); - }; - } - } - // Set new init and update functions that wrap the originals - setHandlerFunction('init'); - setHandlerFunction('update'); - // Clear any preprocess function since preprocessing of the new binding would need to be different - if (handler.preprocess) - handler.preprocess = null; - if (ko.virtualElements.allowedBindings[namespace]) - ko.virtualElements.allowedBindings[namespacedName] = true; - return handler; -} - -// Adds a preprocess function for every generated namespace.x binding. This can -// be called multiple times for the same binding, and the preprocess functions will -// be chained. If the binding has a custom getNamespacedHandler method, make sure that -// it's set before this function is used. -function addDefaultNamespacedBindingPreprocessor(namespace, preprocessFn) { - var handler = ko.getBindingHandler(namespace); - if (handler) { - var previousHandlerFn = handler.getNamespacedHandler || defaultGetNamespacedHandler; - handler.getNamespacedHandler = function() { - return addBindingPreprocessor(previousHandlerFn.apply(this, arguments), preprocessFn); - }; - } -} - -function autoNamespacedPreprocessor(value, binding, addBinding) { - if (value.charAt(0) !== "{") - return value; - - // Handle two-level binding specified as "binding: {key: value}" by parsing inner - // object and converting to "binding.key: value" - var subBindings = ko.expressionRewriting.parseObjectLiteral(value); - ko.utils.arrayForEach(subBindings, function(keyValue) { - addBinding(binding + namespaceDivider + keyValue.key, keyValue.value); - }); -} - -// Set the namespaced preprocessor for a specific binding -function enableAutoNamespacedSyntax(bindingKeyOrHandler) { - addBindingPreprocessor(bindingKeyOrHandler, autoNamespacedPreprocessor); -} - -// Export the preprocessor functions -ko_punches.namespacedBinding = { - defaultGetHandler: defaultGetNamespacedHandler, - setDefaultBindingPreprocessor: addDefaultNamespacedBindingPreprocessor, // for backwards compat. - addDefaultBindingPreprocessor: addDefaultNamespacedBindingPreprocessor, - preprocessor: autoNamespacedPreprocessor, - enableForBinding: enableAutoNamespacedSyntax -}; -// Wrap a callback function in an anonymous function so that it is called with the appropriate -// "this" value. -function wrappedCallbackPreprocessor(val) { - // Matches either an isolated identifier or something ending with a property accessor - if (/^([$_a-z][$\w]*|.+(\.\s*[$_a-z][$\w]*|\[.+\]))$/i.test(val)) { - return 'function(_x,_y,_z){return(' + val + ')(_x,_y,_z);}'; - } else { - return val; - } -} - -// Set the wrappedCallback preprocessor for a specific binding -function enableWrappedCallback(bindingKeyOrHandler) { - addBindingPreprocessor(bindingKeyOrHandler, wrappedCallbackPreprocessor); -} - -// Export the preprocessor functions -ko_punches.wrappedCallback = { - preprocessor: wrappedCallbackPreprocessor, - enableForBinding: enableWrappedCallback -}; -// Attach a preprocess function to a specific property of a binding. This allows you to -// preprocess binding "options" using the same preprocess functions that work for bindings. -function addBindingPropertyPreprocessor(bindingKeyOrHandler, property, preprocessFn) { - var handler = getOrCreateHandler(bindingKeyOrHandler); - if (!handler._propertyPreprocessors) { - // Initialize the binding preprocessor - chainPreprocessor(handler, 'preprocess', propertyPreprocessor); - handler._propertyPreprocessors = {}; - } - // Add the property preprocess function - chainPreprocessor(handler._propertyPreprocessors, property, preprocessFn); -} - -// In order to preprocess a binding property, we have to preprocess the binding itself. -// This preprocess function splits up the binding value and runs each property's preprocess -// function if it's set. -function propertyPreprocessor(value, binding, addBinding) { - if (value.charAt(0) !== "{") - return value; - - var subBindings = ko.expressionRewriting.parseObjectLiteral(value), - resultStrings = [], - propertyPreprocessors = this._propertyPreprocessors || {}; - ko.utils.arrayForEach(subBindings, function(keyValue) { - var prop = keyValue.key, propVal = keyValue.value; - if (propertyPreprocessors[prop]) { - propVal = propertyPreprocessors[prop](propVal, prop, addBinding); - } - if (propVal) { - resultStrings.push("'" + prop + "':" + propVal); - } - }); - return "{" + resultStrings.join(",") + "}"; -} - -// Export the preprocessor functions -ko_punches.preprocessBindingProperty = { - setPreprocessor: addBindingPropertyPreprocessor, // for backwards compat. - addPreprocessor: addBindingPropertyPreprocessor -}; -// Wrap an expression in an anonymous function so that it is called when the event happens -function makeExpressionCallbackPreprocessor(args) { - return function expressionCallbackPreprocessor(val) { - return 'function('+args+'){return(' + val + ');}'; - }; -} - -var eventExpressionPreprocessor = makeExpressionCallbackPreprocessor("$data,$event"); - -// Set the expressionCallback preprocessor for a specific binding -function enableExpressionCallback(bindingKeyOrHandler, args) { - var args = Array.prototype.slice.call(arguments, 1).join(); - addBindingPreprocessor(bindingKeyOrHandler, makeExpressionCallbackPreprocessor(args)); -} - -// Export the preprocessor functions -ko_punches.expressionCallback = { - makePreprocessor: makeExpressionCallbackPreprocessor, - eventPreprocessor: eventExpressionPreprocessor, - enableForBinding: enableExpressionCallback -}; - -// Create an "on" namespace for events to use the expression method -ko.bindingHandlers.on = { - getNamespacedHandler: function(eventName) { - var handler = ko.getBindingHandler('event' + namespaceDivider + eventName); - return addBindingPreprocessor(handler, eventExpressionPreprocessor); - } -}; -// Performance comparison at http://jsperf.com/markup-interpolation-comparison -function parseInterpolationMarkup(textToParse, outerTextCallback, expressionCallback) { - function innerParse(text) { - var innerMatch = text.match(/^([\s\S]*)}}([\s\S]*?)\{\{([\s\S]*)$/); - if (innerMatch) { - innerParse(innerMatch[1]); - outerTextCallback(innerMatch[2]); - expressionCallback(innerMatch[3]); - } else { - expressionCallback(text); - } - } - var outerMatch = textToParse.match(/^([\s\S]*?)\{\{([\s\S]*)}}([\s\S]*)$/); - if (outerMatch) { - outerTextCallback(outerMatch[1]); - innerParse(outerMatch[2]); - outerTextCallback(outerMatch[3]); - } -} - -function trim(string) { - return string == null ? '' : - string.trim ? - string.trim() : - string.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''); -} - -function interpolationMarkupPreprocessor(node) { - // only needs to work with text nodes - if (node.nodeType === 3 && node.nodeValue && node.nodeValue.indexOf('{{') !== -1 && (node.parentNode || {}).nodeName != "TEXTAREA") { - var nodes = []; - function addTextNode(text) { - if (text) - nodes.push(document.createTextNode(text)); - } - function wrapExpr(expressionText) { - if (expressionText) - nodes.push.apply(nodes, ko_punches_interpolationMarkup.wrapExpression(expressionText, node)); - } - parseInterpolationMarkup(node.nodeValue, addTextNode, wrapExpr) - - if (nodes.length) { - if (node.parentNode) { - for (var i = 0, n = nodes.length, parent = node.parentNode; i < n; ++i) { - parent.insertBefore(nodes[i], node); - } - parent.removeChild(node); - } - return nodes; - } - } -} - -if (!ko.virtualElements.allowedBindings.html) { - // Virtual html binding - // SO Question: http://stackoverflow.com/a/15348139 - var overridden = ko.bindingHandlers.html.update; - ko.bindingHandlers.html.update = function (element, valueAccessor) { - if (element.nodeType === 8) { - var html = ko_unwrap(valueAccessor()); - if (html != null) { - var parsedNodes = ko.utils.parseHtmlFragment('' + html); - ko.virtualElements.setDomNodeChildren(element, parsedNodes); - } else { - ko.virtualElements.emptyNode(element); - } - } else { - overridden(element, valueAccessor); - } - }; - ko.virtualElements.allowedBindings.html = true; -} - -function wrapExpression(expressionText, node) { - var ownerDocument = node ? node.ownerDocument : document, - closeComment = true, - binding, - firstChar = expressionText[0], - lastChar = expressionText[expressionText.length - 1], - result = [], - matches; - - if (firstChar === '#') { - if (lastChar === '/') { - binding = expressionText.slice(1, -1); - } else { - binding = expressionText.slice(1); - closeComment = false; - } - if (matches = binding.match(/^([^,"'{}()\/:[\]\s]+)\s+([^\s:].*)/)) { - binding = matches[1] + ':' + matches[2]; - } - } else if (firstChar === '/') { - // replace only with a closing comment - } else if (firstChar === '{' && lastChar === '}') { - binding = "html:" + trim(expressionText.slice(1, -1)); - } else { - binding = "text:" + trim(expressionText); - } - - if (binding) - result.push(ownerDocument.createComment("ko " + binding)); - if (closeComment) - result.push(ownerDocument.createComment("/ko")); - return result; -}; - -function enableInterpolationMarkup() { - addNodePreprocessor(interpolationMarkupPreprocessor); -} - -// Export the preprocessor functions -var ko_punches_interpolationMarkup = ko_punches.interpolationMarkup = { - preprocessor: interpolationMarkupPreprocessor, - enable: enableInterpolationMarkup, - wrapExpression: wrapExpression -}; - - -var dataBind = 'data-bind'; -function attributeInterpolationMarkerPreprocessor(node) { - if (node.nodeType === 1 && node.attributes.length) { - var dataBindAttribute = node.getAttribute(dataBind); - for (var attrs = ko.utils.arrayPushAll([], node.attributes), n = attrs.length, i = 0; i < n; ++i) { - var attr = attrs[i]; - if (attr.specified && attr.name != dataBind && attr.value.indexOf('{{') !== -1) { - var parts = [], attrValue = ''; - function addText(text) { - if (text) - parts.push('"' + text.replace(/"/g, '\\"') + '"'); - } - function addExpr(expressionText) { - if (expressionText) { - attrValue = expressionText; - parts.push('ko.unwrap(' + expressionText + ')'); - } - } - parseInterpolationMarkup(attr.value, addText, addExpr); - - if (parts.length > 1) { - attrValue = '""+' + parts.join('+'); - } - - if (attrValue) { - var attrName = attr.name.toLowerCase(); - var attrBinding = ko_punches_attributeInterpolationMarkup.attributeBinding(attrName, attrValue, node) || attributeBinding(attrName, attrValue, node); - if (!dataBindAttribute) { - dataBindAttribute = attrBinding - } else { - dataBindAttribute += ',' + attrBinding; - } - node.setAttribute(dataBind, dataBindAttribute); - // Using removeAttribute instead of removeAttributeNode because IE clears the - // class if you use removeAttributeNode to remove the id. - node.removeAttribute(attr.name); - } - } - } - } -} - -function attributeBinding(name, value, node) { - if (ko.getBindingHandler(name)) { - return name + ':' + value; - } else { - return 'attr.' + name + ':' + value; - } -} - -function enableAttributeInterpolationMarkup() { - addNodePreprocessor(attributeInterpolationMarkerPreprocessor); -} - -var ko_punches_attributeInterpolationMarkup = ko_punches.attributeInterpolationMarkup = { - preprocessor: attributeInterpolationMarkerPreprocessor, - enable: enableAttributeInterpolationMarkup, - attributeBinding: attributeBinding -}; - - return ko_punches; -})); diff --git a/vendors/knockout-punches/knockout.punches.min.js b/vendors/knockout-punches/knockout.punches.min.js deleted file mode 100644 index 215664da9..000000000 --- a/vendors/knockout-punches/knockout.punches.min.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - Knockout.Punches - Enhanced binding syntaxes for Knockout 3+ - (c) Michael Best - License: MIT (http://www.opensource.org/licenses/mit-license.php) - Version 0.5.0 -*/ -(function(c){"function"===typeof define&&define.amd?define(["knockout"],c):c(ko)})(function(c){function k(a,b){return u(B(a),"preprocess",b)}function B(a){return"object"===typeof a?a:c.getBindingHandler(a)||(c.bindingHandlers[a]={})}function u(a,b,d){if(a[b]){var g=a[b];a[b]=function(a,b,c){if(a=g.call(this,a,b,c))return d.call(this,a,b,c)}}else a[b]=d;return a}function r(a){var b=c.bindingProvider.instance;if(b.preprocessNode){var d=b.preprocessNode;b.preprocessNode=function(b){var c=d.call(this, -b);c||(c=a.call(this,b));return c}}else b.preprocessNode=a}function D(a,b){var d=c.getBindingHandler;c.getBindingHandler=function(g){var c;return d(g)||(c=g.match(a))&&b(c,g)}}function v(a){if(-1===a.indexOf("|"))return a;var b=a.match(/"([^"\\]|\\.)*"|'([^'\\]|\\.)*'|\|\||[|:]|[^\s|:"'][^|:"']*[^\s|:"']|[^\s|:"']/g);if(b&&1b)switch(d=""+(d||"..."),b-=d.length,a=""+a,c){case "left":return d+a.slice(-b);case "middle":return c=Math.ceil(b/ -2),a.substr(0,c)+d+a.slice(c-b);default:return a.substr(0,b)+d}else return a},json:function(a,b,d){return c.toJSON(a,d,b)},number:function(a){return(+l(a)).toLocaleString()}};h.textFilter={preprocessor:v,enableForBinding:w};var F=".";D(/([^\.]+)\.(.+)/,function(a,b){var d=a[1],g=c.bindingHandlers[d];if(g)return d=(g.getNamespacedHandler||x).call(g,a[2],d,b),c.bindingHandlers[b]=d});h.namespacedBinding={defaultGetHandler:x,setDefaultBindingPreprocessor:s,addDefaultBindingPreprocessor:s,preprocessor:E, -enableForBinding:p};h.wrappedCallback={preprocessor:m,enableForBinding:t};h.preprocessBindingProperty={setPreprocessor:q,addPreprocessor:q};var M=y("$data,$event");h.expressionCallback={makePreprocessor:y,eventPreprocessor:M,enableForBinding:function(a,b){b=Array.prototype.slice.call(arguments,1).join();k(a,y(b))}};c.bindingHandlers.on={getNamespacedHandler:function(a){a=c.getBindingHandler("event"+F+a);return k(a,M)}};if(!c.virtualElements.allowedBindings.html){var Q=c.bindingHandlers.html.update; -c.bindingHandlers.html.update=function(a,b){if(8===a.nodeType){var d=l(b());null!=d?(d=c.utils.parseHtmlFragment(""+d),c.virtualElements.setDomNodeChildren(a,d)):c.virtualElements.emptyNode(a)}else Q(a,b)};c.virtualElements.allowedBindings.html=!0}var O=h.interpolationMarkup={preprocessor:H,enable:I,wrapExpression:function(a,b){var d=b?b.ownerDocument:document,c=!0,e,f=a[0],h=a[a.length-1],k=[];if("#"===f){if("/"===h?e=a.slice(1,-1):(e=a.slice(1),c=!1),f=e.match(/^([^,"'{}()\/:[\]\s]+)\s+([^\s:].*)/))e= -f[1]+":"+f[2]}else"/"!==f&&(e="{"===f&&"}"===h?"html:"+z(a.slice(1,-1)):"text:"+z(a));e&&k.push(d.createComment("ko "+e));c&&k.push(d.createComment("/ko"));return k}},A="data-bind",P=h.attributeInterpolationMarkup={preprocessor:J,enable:L,attributeBinding:K};return h}); diff --git a/vendors/normalize/normalize.css b/vendors/normalize/normalize.css index 4474dee25..7bb20c110 100644 --- a/vendors/normalize/normalize.css +++ b/vendors/normalize/normalize.css @@ -498,7 +498,10 @@ textarea { * Remove most spacing between table cells */ +/* table { border-collapse: collapse; border-spacing: 0; } +*/ + diff --git a/vendors/openpgp/openpgp-0.10.1.worker.min.js b/vendors/openpgp/openpgp-0.10.1.worker.min.js new file mode 100644 index 000000000..91e75f58e --- /dev/null +++ b/vendors/openpgp/openpgp-0.10.1.worker.min.js @@ -0,0 +1 @@ +/*! OpenPGPjs.org this is LGPL licensed code, see LICENSE/our website for more information.- v0.10.1 - 2015-02-13 */!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g0)){var d=c.shift();d()}},!0),function(a){c.push(a),window.postMessage("process-tick","*")}}return function(a){setTimeout(a,0)}}(),c.title="browser",c.browser=!0,c.env={},c.argv=[],c.binding=function(){throw new Error("process.binding is not supported")},c.cwd=function(){return"/"},c.chdir=function(){throw new Error("process.chdir is not supported")}},{}],2:[function(a,b,c){"use strict";var d=a("./promise/promise").Promise,e=a("./promise/polyfill").polyfill;c.Promise=d,c.polyfill=e},{"./promise/polyfill":6,"./promise/promise":7}],3:[function(a,b,c){"use strict";function d(a){var b=this;if(!e(a))throw new TypeError("You must pass an array to all.");return new b(function(b,c){function d(a){return function(b){e(a,b)}}function e(a,c){h[a]=c,0===--i&&b(h)}var g,h=[],i=a.length;0===i&&b([]);for(var j=0;jb;++b)e[b]=c[b];return a.buffer=e}function d(a){this.buffer=new(o?Uint16Array:Array)(2*a),this.length=0}function e(a,b){this.e=w,this.f=0,this.input=o&&a instanceof Array?new Uint8Array(a):a,this.c=0,b&&(b.lazy&&(this.f=b.lazy),"number"==typeof b.compressionType&&(this.e=b.compressionType),b.outputBuffer&&(this.b=o&&b.outputBuffer instanceof Array?new Uint8Array(b.outputBuffer):b.outputBuffer),"number"==typeof b.outputIndex&&(this.c=b.outputIndex)),this.b||(this.b=new(o?Uint8Array:Array)(32768))}function f(a,b){this.length=a,this.g=b}function g(a,b){function c(a,b){var c,d=a.g,e=[],f=0;c=z[a.length],e[f++]=65535&c,e[f++]=c>>16&255,e[f++]=c>>24;var g;switch(m){case 1===d:g=[0,d-1,0];break;case 2===d:g=[1,d-2,0];break;case 3===d:g=[2,d-3,0];break;case 4===d:g=[3,d-4,0];break;case 6>=d:g=[4,d-5,1];break;case 8>=d:g=[5,d-7,1];break;case 12>=d:g=[6,d-9,2];break;case 16>=d:g=[7,d-13,2];break;case 24>=d:g=[8,d-17,3];break;case 32>=d:g=[9,d-25,3];break;case 48>=d:g=[10,d-33,4];break;case 64>=d:g=[11,d-49,4];break;case 96>=d:g=[12,d-65,5];break;case 128>=d:g=[13,d-97,5];break;case 192>=d:g=[14,d-129,6];break;case 256>=d:g=[15,d-193,6];break;case 384>=d:g=[16,d-257,7];break;case 512>=d:g=[17,d-385,7];break;case 768>=d:g=[18,d-513,8];break;case 1024>=d:g=[19,d-769,8];break;case 1536>=d:g=[20,d-1025,9];break;case 2048>=d:g=[21,d-1537,9];break;case 3072>=d:g=[22,d-2049,10];break;case 4096>=d:g=[23,d-3073,10];break;case 6144>=d:g=[24,d-4097,11];break;case 8192>=d:g=[25,d-6145,11];break;case 12288>=d:g=[26,d-8193,12];break;case 16384>=d:g=[27,d-12289,12];break;case 24576>=d:g=[28,d-16385,13];break;case 32768>=d:g=[29,d-24577,13];break;default:throw"invalid distance"}c=g,e[f++]=c[0],e[f++]=c[1],e[f++]=c[2];var h,i;for(h=0,i=e.length;i>h;++h)r[s++]=e[h];u[e[0]]++,v[e[3]]++,t=a.length+b-1,n=null}var d,e,f,g,i,j,k,n,p,q={},r=o?new Uint16Array(2*b.length):[],s=0,t=0,u=new(o?Uint32Array:Array)(286),v=new(o?Uint32Array:Array)(30),w=a.f;if(!o){for(f=0;285>=f;)u[f++]=0;for(f=0;29>=f;)v[f++]=0}for(u[256]=1,d=0,e=b.length;e>d;++d){for(f=i=0,g=3;g>f&&d+f!==e;++f)i=i<<8|b[d+f];if(q[i]===l&&(q[i]=[]),j=q[i],!(0=e){for(n&&c(n,-1),f=0,g=e-d;g>f;++f)p=b[d+f],r[s++]=p,++u[p];break}0h;h++){if(d=c[j-h-1],g=3,k>3){for(i=k;i>3;i--)if(a[d+i-1]!==a[b+i-1])continue a;g=k}for(;258>g&&l>b+g&&a[d+g]===a[b+g];)++g;if(g>k&&(e=d,k=g),258===g)break}return new f(k,b-e)}function i(a,b){var c,e,f,g,h,i=a.length,k=new d(572),l=new(o?Uint8Array:Array)(i);if(!o)for(g=0;i>g;g++)l[g]=0;for(g=0;i>g;++g)0g;++g)c[g]=k.pop(),e[g]=c[g].value;for(f=j(e,e.length,b),g=0,h=c.length;h>g;++g)l[c[g].index]=f[g];return l}function j(a,b,c){function d(a){var c=n[a][p[a]];c===b?(d(a+1),d(a+1)):--l[c],++p[a]}var e,f,g,h,i,j=new(o?Uint16Array:Array)(c),k=new(o?Uint8Array:Array)(c),l=new(o?Uint8Array:Array)(b),m=Array(c),n=Array(c),p=Array(c),q=(1<f;++f)r>q?k[f]=0:(k[f]=1,q-=r),q<<=1,j[c-2-f]=(j[c-1-f]/2|0)+b;for(j[0]=k[0],m[0]=Array(j[0]),n[0]=Array(j[0]),f=1;c>f;++f)j[f]>2*j[f-1]+k[f]&&(j[f]=2*j[f-1]+k[f]),m[f]=Array(j[f]),n[f]=Array(j[f]);for(e=0;b>e;++e)l[e]=c;for(g=0;ge;++e)p[e]=0;for(1===k[c-1]&&(--l[0],++p[c-1]),f=c-2;f>=0;--f){for(h=e=0,i=p[f+1],g=0;ga[e]?(m[f][g]=h,n[f][g]=b,i+=2):(m[f][g]=a[e],n[f][g]=e,++e);p[f]=0,1===k[f]&&d(f)}return l}function k(a){var b,c,d,e,f=new(o?Uint16Array:Array)(a.length),g=[],h=[],i=0;for(b=0,c=a.length;c>b;b++)g[a[b]]=(0|g[a[b]])+1;for(b=1,c=16;c>=b;b++)h[b]=i,i+=0|g[b],i<<=1;for(b=0,c=a.length;c>b;b++)for(i=h[a[b]],h[a[b]]+=1,d=f[b]=0,e=a[b];e>d;d++)f[b]=f[b]<<1|1&i,i>>>=1;return f}var l=void 0,m=!0,n=this,o="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array&&"undefined"!=typeof DataView;b.prototype.a=function(a,b,d){var e,f=this.buffer,g=this.index,h=this.d,i=f[g];if(d&&b>1&&(a=b>8?(u[255&a]<<24|u[a>>>8&255]<<16|u[a>>>16&255]<<8|u[a>>>24&255])>>32-b:u[a]>>8-b),8>b+h)i=i<e;++e)i=i<<1|a>>b-e-1&1,8===++h&&(h=0,f[g++]=u[i],i=0,g===f.length&&(f=c(this)));f[g]=i,this.buffer=f,this.d=h,this.index=g},b.prototype.finish=function(){var a,b=this.buffer,c=this.index;return 0p;++p){for(var r=p,s=r,t=7,r=r>>>1;r;r>>>=1)s<<=1,s|=1&r,--t;q[p]=(s<>>0}var u=q;d.prototype.getParent=function(a){return 2*((a-2)/4|0)},d.prototype.push=function(a,b){var c,d,e,f=this.buffer;for(c=this.length,f[this.length++]=b,f[this.length++]=a;c>0&&(d=this.getParent(c),f[c]>f[d]);)e=f[c],f[c]=f[d],f[d]=e,e=f[c+1],f[c+1]=f[d+1],f[d+1]=e,c=d;return this.length},d.prototype.pop=function(){var a,b,c,d,e,f=this.buffer;for(b=f[0],a=f[1],this.length-=2,f[0]=f[this.length],f[1]=f[this.length+1],e=0;(d=2*e+2,!(d>=this.length))&&(d+2f[d]&&(d+=2),f[d]>f[e]);)c=f[e],f[e]=f[d],f[d]=c,c=f[e+1],f[e+1]=f[d+1],f[d+1]=c,e=d;return{index:a,value:b,length:this.length}};var v,w=2,x=[];for(v=0;288>v;v++)switch(m){case 143>=v:x.push([v+48,8]);break;case 255>=v:x.push([v-144+400,9]);break;case 279>=v:x.push([v-256+0,7]);break;case 287>=v:x.push([v-280+192,8]);break;default:throw"invalid literal: "+v}e.prototype.h=function(){var a,c,d,e,f=this.input;switch(this.e){case 0:for(d=0,e=f.length;e>d;){c=o?f.subarray(d,d+65535):f.slice(d,d+65535),d+=c.length;var h=c,j=d===e,n=l,p=l,q=l,r=l,s=l,t=this.b,u=this.c;if(o){for(t=new Uint8Array(this.b.buffer);t.length<=u+h.length+5;)t=new Uint8Array(t.length<<1);t.set(this.b)}if(n=j?1:0,t[u++]=0|n,p=h.length,q=~p+65536&65535,t[u++]=255&p,t[u++]=p>>>8&255,t[u++]=255&q,t[u++]=q>>>8&255,o)t.set(h,u),u+=h.length,t=t.subarray(0,u);else{for(r=0,s=h.length;s>r;++r)t[u++]=h[r];t.length=u}this.c=u,this.b=t}break;case 1:var v=new b(o?new Uint8Array(this.b.buffer):this.b,this.c);v.a(1,1,m),v.a(1,2,m);var y,z,A,B=g(this,f);for(y=0,z=B.length;z>y;y++)if(A=B[y],b.prototype.a.apply(v,x[A]),A>256)v.a(B[++y],B[++y],m),v.a(B[++y],5),v.a(B[++y],B[++y],m);else if(256===A)break;this.b=v.finish(),this.c=this.b.length;break;case w:var C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R=new b(o?new Uint8Array(this.b.buffer):this.b,this.c),S=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],T=Array(19);for(C=w,R.a(1,1,m),R.a(C,2,m),D=g(this,f),H=i(this.j,15),I=k(H),J=i(this.i,7),K=k(J),E=286;E>257&&0===H[E-1];E--);for(F=30;F>1&&0===J[F-1];F--);var U,V,W,X,Y,Z,$=E,_=F,ab=new(o?Uint32Array:Array)($+_),bb=new(o?Uint32Array:Array)(316),cb=new(o?Uint8Array:Array)(19);for(U=V=0;$>U;U++)ab[V++]=H[U];for(U=0;_>U;U++)ab[V++]=J[U];if(!o)for(U=0,X=cb.length;X>U;++U)cb[U]=0;for(U=Y=0,X=ab.length;X>U;U+=V){for(V=1;X>U+V&&ab[U+V]===ab[U];++V);if(W=V,0===ab[U])if(3>W)for(;00;)Z=138>W?W:138,Z>W-3&&W>Z&&(Z=W-3),10>=Z?(bb[Y++]=17,bb[Y++]=Z-3,cb[17]++):(bb[Y++]=18,bb[Y++]=Z-11,cb[18]++),W-=Z;else if(bb[Y++]=ab[U],cb[ab[U]]++,W--,3>W)for(;00;)Z=6>W?W:6,Z>W-3&&W>Z&&(Z=W-3),bb[Y++]=16,bb[Y++]=Z-3,cb[16]++,W-=Z}for(a=o?bb.subarray(0,Y):bb.slice(0,Y),L=i(cb,7),P=0;19>P;P++)T[P]=L[S[P]];for(G=19;G>4&&0===T[G-1];G--);for(M=k(L),R.a(E-257,5,m),R.a(F-1,5,m),R.a(G-4,4,m),P=0;G>P;P++)R.a(T[P],3,m);for(P=0,Q=a.length;Q>P;P++)if(N=a[P],R.a(M[N],L[N],m),N>=16){switch(P++,N){case 16:O=2;break;case 17:O=3;break;case 18:O=7;break;default:throw"invalid code: "+N}R.a(a[P],O,m)}var db,eb,fb,gb,hb,ib,jb,kb,lb=[I,H],mb=[K,J];for(hb=lb[0],ib=lb[1],jb=mb[0],kb=mb[1],db=0,eb=D.length;eb>db;++db)if(fb=D[db],R.a(hb[fb],ib[fb],m),fb>256)R.a(D[++db],D[++db],m),gb=D[++db],R.a(jb[gb],kb[gb],m),R.a(D[++db],D[++db],m);else if(256===fb)break;this.b=R.finish(),this.c=this.b.length;break;default:throw"invalid compression type"}return this.b};var y=function(){function a(a){switch(m){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:throw"invalid length: "+a}}var b,c,d=[];for(b=3;258>=b;b++)c=a(b),d[b]=c[2]<<24|c[1]<<16|c[0];return d}(),z=o?new Uint32Array(y):y;a("Zlib.RawDeflate",e),a("Zlib.RawDeflate.prototype.compress",e.prototype.h);var A,B,C,D,E={NONE:0,FIXED:1,DYNAMIC:w};if(Object.keys)A=Object.keys(E);else for(B in A=[],C=0,E)A[C++]=B;for(C=0,D=A.length;D>C;++C)B=A[C],a("Zlib.RawDeflate.CompressionType."+B,E[B])}).call(this)},{}],14:[function(){(function(){"use strict";function a(a,b){var c=a.split("."),d=g;!(c[0]in d)&&d.execScript&&d.execScript("var "+c[0]);for(var e;c.length&&(e=c.shift());)c.length||void 0===b?d=d[e]?d[e]:d[e]={}:d[e]=b}function b(a){var b,c,d,e,f,g,i,j,k,l,m=a.length,n=0,o=Number.POSITIVE_INFINITY;for(j=0;m>j;++j)a[j]>n&&(n=a[j]),a[j]=d;){for(j=0;m>j;++j)if(a[j]===d){for(g=0,i=e,k=0;d>k;++k)g=g<<1|1&i,i>>=1;for(l=d<<16|j,k=g;b>k;k+=f)c[k]=l;++e}++d,e<<=1,f<<=1}return[c,n,o]}function c(a,b){switch(this.g=[],this.h=32768,this.c=this.f=this.d=this.k=0,this.input=h?new Uint8Array(a):a,this.l=!1,this.i=j,this.q=!1,(b||!(b={}))&&(b.index&&(this.d=b.index),b.bufferSize&&(this.h=b.bufferSize),b.bufferType&&(this.i=b.bufferType),b.resize&&(this.q=b.resize)),this.i){case i:this.a=32768,this.b=new(h?Uint8Array:Array)(32768+this.h+258);break;case j:this.a=0,this.b=new(h?Uint8Array:Array)(this.h),this.e=this.v,this.m=this.s,this.j=this.t;break;default:throw Error("invalid inflate mode")}}function d(a,b){for(var c,d=a.f,e=a.c,f=a.input,g=a.d,h=f.length;b>e;){if(g>=h)throw Error("input buffer is broken");d|=f[g++]<>>b,a.c=e-b,a.d=g,c}function e(a,b){for(var c,d,e=a.f,f=a.c,g=a.input,h=a.d,i=g.length,j=b[0],k=b[1];k>f&&!(h>=i);)e|=g[h++]<>>16,a.f=e>>d,a.c=f-d,a.d=h,65535&c}function f(a){function c(a,b,c){var f,g,h,i=this.p;for(h=0;a>h;)switch(f=e(this,b)){case 16:for(g=3+d(this,2);g--;)c[h++]=i;break;case 17:for(g=3+d(this,3);g--;)c[h++]=0;i=0;break;case 18:for(g=11+d(this,7);g--;)c[h++]=0;i=0;break;default:i=c[h++]=f}return this.p=i,c}var f,g,i,j,k=d(a,5)+257,l=d(a,5)+1,m=d(a,4)+4,o=new(h?Uint8Array:Array)(n.length);for(j=0;m>j;++j)o[n[j]]=d(a,3);if(!h)for(j=m,m=o.length;m>j;++j)o[n[j]]=0;f=b(o),g=new(h?Uint8Array:Array)(k),i=new(h?Uint8Array:Array)(l),a.p=0,a.j(b(c.call(a,k,f,g)),b(c.call(a,l,f,i)))}var g=this,h="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array&&"undefined"!=typeof DataView,i=0,j=1;c.prototype.u=function(){for(;!this.l;){var a=d(this,3);switch(1&a&&(this.l=!0),a>>>=1){case 0:var b=this.input,c=this.d,e=this.b,g=this.a,k=b.length,l=void 0,m=void 0,n=e.length,o=void 0;if(this.c=this.f=0,c+1>=k)throw Error("invalid uncompressed block header: LEN");if(l=b[c++]|b[c++]<<8,c+1>=k)throw Error("invalid uncompressed block header: NLEN");if(m=b[c++]|b[c++]<<8,l===~m)throw Error("invalid uncompressed block header: length verify");if(c+l>b.length)throw Error("input buffer is broken");switch(this.i){case i:for(;g+l>e.length;){if(o=n-g,l-=o,h)e.set(b.subarray(c,c+o),g),g+=o,c+=o;else for(;o--;)e[g++]=b[c++];this.a=g,e=this.e(),g=this.a}break;case j:for(;g+l>e.length;)e=this.e({o:2});break;default:throw Error("invalid inflate mode")}if(h)e.set(b.subarray(c,c+l),g),g+=l,c+=l;else for(;l--;)e[g++]=b[c++];this.d=c,this.a=g,this.b=e;break;case 1:this.j(z,B);break;case 2:f(this);break;default:throw Error("unknown BTYPE: "+a)}}return this.m()};var k,l,m=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],n=h?new Uint16Array(m):m,o=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],p=h?new Uint16Array(o):o,q=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],r=h?new Uint8Array(q):q,s=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],t=h?new Uint16Array(s):s,u=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],v=h?new Uint8Array(u):u,w=new(h?Uint8Array:Array)(288);for(k=0,l=w.length;l>k;++k)w[k]=143>=k?8:255>=k?9:279>=k?7:8;var x,y,z=b(w),A=new(h?Uint8Array:Array)(30);for(x=0,y=A.length;y>x;++x)A[x]=5;var B=b(A);c.prototype.j=function(a,b){var c=this.b,f=this.a;this.n=a;for(var g,h,i,j,k=c.length-258;256!==(g=e(this,a));)if(256>g)f>=k&&(this.a=f,c=this.e(),f=this.a),c[f++]=g;else for(h=g-257,j=p[h],0=k&&(this.a=f,c=this.e(),f=this.a);j--;)c[f]=c[f++-i];for(;8<=this.c;)this.c-=8,this.d--;this.a=f},c.prototype.t=function(a,b){var c=this.b,f=this.a;this.n=a;for(var g,h,i,j,k=c.length;256!==(g=e(this,a));)if(256>g)f>=k&&(c=this.e(),k=c.length),c[f++]=g;else for(h=g-257,j=p[h],0k&&(c=this.e(),k=c.length);j--;)c[f]=c[f++-i];for(;8<=this.c;)this.c-=8,this.d--;this.a=f},c.prototype.e=function(){var a,b,c=new(h?Uint8Array:Array)(this.a-32768),d=this.a-32768,e=this.b;if(h)c.set(e.subarray(32768,c.length));else for(a=0,b=c.length;b>a;++a)c[a]=e[a+32768];if(this.g.push(c),this.k+=c.length,h)e.set(e.subarray(d,d+32768));else for(a=0;32768>a;++a)e[a]=e[d+a];return this.a=32768,e},c.prototype.v=function(a){var b,c,d,e,f=this.input.length/this.d+1|0,g=this.input,i=this.b;return a&&("number"==typeof a.o&&(f=a.o),"number"==typeof a.r&&(f+=a.r)),2>f?(c=(g.length-this.d)/this.n[2],e=258*(c/2)|0,d=eb;++b)for(a=i[b],d=0,e=a.length;e>d;++d)j[f++]=a[d];for(b=32768,c=this.a;c>b;++b)j[f++]=g[b];return this.g=[],this.buffer=j},c.prototype.s=function(){var a,b=this.a;return h?this.q?(a=new Uint8Array(b),a.set(this.b.subarray(0,b))):a=this.b.subarray(0,b):(this.b.length>b&&(this.b.length=b),a=this.b),this.buffer=a},a("Zlib.RawInflate",c),a("Zlib.RawInflate.prototype.decompress",c.prototype.u);var C,D,E,F,G={ADAPTIVE:j,BLOCK:i};if(Object.keys)C=Object.keys(G);else for(D in C=[],E=0,G)C[E++]=D;for(E=0,F=C.length;F>E;++E)D=C[E],a("Zlib.RawInflate.BufferType."+D,G[D])}).call(this)},{}],15:[function(){(function(){"use strict";function a(a){throw a}function b(a,b){var c=a.split("."),d=w;!(c[0]in d)&&d.execScript&&d.execScript("var "+c[0]);for(var e;c.length&&(e=c.shift());)c.length||b===u?d=d[e]?d[e]:d[e]={}:d[e]=b}function c(b,c){this.index="number"==typeof c?c:0,this.i=0,this.buffer=b instanceof(x?Uint8Array:Array)?b:new(x?Uint8Array:Array)(32768),2*this.buffer.length<=this.index&&a(Error("invalid index")),this.buffer.length<=this.index&&this.f()}function d(a){this.buffer=new(x?Uint16Array:Array)(2*a),this.length=0}function e(a){var b,c,d,e,f,g,h,i,j,k,l=a.length,m=0,n=Number.POSITIVE_INFINITY;for(i=0;l>i;++i)a[i]>m&&(m=a[i]),a[i]=d;){for(i=0;l>i;++i)if(a[i]===d){for(g=0,h=e,j=0;d>j;++j)g=g<<1|1&h,h>>=1;for(k=d<<16|i,j=g;b>j;j+=f)c[j]=k;++e}++d,e<<=1,f<<=1}return[c,m,n]}function f(a,b){this.h=F,this.w=0,this.input=x&&a instanceof Array?new Uint8Array(a):a,this.b=0,b&&(b.lazy&&(this.w=b.lazy),"number"==typeof b.compressionType&&(this.h=b.compressionType),b.outputBuffer&&(this.a=x&&b.outputBuffer instanceof Array?new Uint8Array(b.outputBuffer):b.outputBuffer),"number"==typeof b.outputIndex&&(this.b=b.outputIndex)),this.a||(this.a=new(x?Uint8Array:Array)(32768))}function g(a,b){this.length=a,this.H=b}function h(b,c){function d(b,c){var d,e=b.H,f=[],g=0;d=J[b.length],f[g++]=65535&d,f[g++]=d>>16&255,f[g++]=d>>24;var h;switch(v){case 1===e:h=[0,e-1,0];break;case 2===e:h=[1,e-2,0];break;case 3===e:h=[2,e-3,0];break;case 4===e:h=[3,e-4,0];break;case 6>=e:h=[4,e-5,1];break;case 8>=e:h=[5,e-7,1];break;case 12>=e:h=[6,e-9,2];break;case 16>=e:h=[7,e-13,2];break;case 24>=e:h=[8,e-17,3];break;case 32>=e:h=[9,e-25,3];break;case 48>=e:h=[10,e-33,4];break;case 64>=e:h=[11,e-49,4];break;case 96>=e:h=[12,e-65,5];break;case 128>=e:h=[13,e-97,5];break;case 192>=e:h=[14,e-129,6];break;case 256>=e:h=[15,e-193,6];break;case 384>=e:h=[16,e-257,7];break;case 512>=e:h=[17,e-385,7];break;case 768>=e:h=[18,e-513,8];break;case 1024>=e:h=[19,e-769,8];break;case 1536>=e:h=[20,e-1025,9];break;case 2048>=e:h=[21,e-1537,9];break;case 3072>=e:h=[22,e-2049,10];break;case 4096>=e:h=[23,e-3073,10];break;case 6144>=e:h=[24,e-4097,11];break;case 8192>=e:h=[25,e-6145,11];break;case 12288>=e:h=[26,e-8193,12];break;case 16384>=e:h=[27,e-12289,12];break;case 24576>=e:h=[28,e-16385,13];break;case 32768>=e:h=[29,e-24577,13];break;default:a("invalid distance")}d=h,f[g++]=d[0],f[g++]=d[1],f[g++]=d[2];var i,j;for(i=0,j=f.length;j>i;++i)p[q++]=f[i];s[f[0]]++,t[f[3]]++,r=b.length+c-1,m=null}var e,f,g,h,j,k,l,m,n,o={},p=x?new Uint16Array(2*c.length):[],q=0,r=0,s=new(x?Uint32Array:Array)(286),t=new(x?Uint32Array:Array)(30),w=b.w;if(!x){for(g=0;285>=g;)s[g++]=0;for(g=0;29>=g;)t[g++]=0}for(s[256]=1,e=0,f=c.length;f>e;++e){for(g=j=0,h=3;h>g&&e+g!==f;++g)j=j<<8|c[e+g];if(o[j]===u&&(o[j]=[]),k=o[j],!(0=f){for(m&&d(m,-1),g=0,h=f-e;h>g;++g)n=c[e+g],p[q++]=n,++s[n];break}0h;h++){if(d=c[j-h-1],f=3,k>3){for(i=k;i>3;i--)if(a[d+i-1]!==a[b+i-1])continue a;f=k}for(;258>f&&l>b+f&&a[d+f]===a[b+f];)++f;if(f>k&&(e=d,k=f),258===f)break}return new g(k,b-e)}function j(a,b){var c,e,f,g,h,i=a.length,j=new d(572),l=new(x?Uint8Array:Array)(i);if(!x)for(g=0;i>g;g++)l[g]=0;for(g=0;i>g;++g)0g;++g)c[g]=j.pop(),e[g]=c[g].value;for(f=k(e,e.length,b),g=0,h=c.length;h>g;++g)l[c[g].index]=f[g];return l}function k(a,b,c){function d(a){var c=n[a][o[a]];c===b?(d(a+1),d(a+1)):--l[c],++o[a]}var e,f,g,h,i,j=new(x?Uint16Array:Array)(c),k=new(x?Uint8Array:Array)(c),l=new(x?Uint8Array:Array)(b),m=Array(c),n=Array(c),o=Array(c),p=(1<f;++f)q>p?k[f]=0:(k[f]=1,p-=q),p<<=1,j[c-2-f]=(j[c-1-f]/2|0)+b;for(j[0]=k[0],m[0]=Array(j[0]),n[0]=Array(j[0]),f=1;c>f;++f)j[f]>2*j[f-1]+k[f]&&(j[f]=2*j[f-1]+k[f]),m[f]=Array(j[f]),n[f]=Array(j[f]);for(e=0;b>e;++e)l[e]=c;for(g=0;ge;++e)o[e]=0;for(1===k[c-1]&&(--l[0],++o[c-1]),f=c-2;f>=0;--f){for(h=e=0,i=o[f+1],g=0;ga[e]?(m[f][g]=h,n[f][g]=b,i+=2):(m[f][g]=a[e],n[f][g]=e,++e);o[f]=0,1===k[f]&&d(f)}return l}function l(a){var b,c,d,e,f=new(x?Uint16Array:Array)(a.length),g=[],h=[],i=0;for(b=0,c=a.length;c>b;b++)g[a[b]]=(0|g[a[b]])+1;for(b=1,c=16;c>=b;b++)h[b]=i,i+=0|g[b],i<<=1;for(b=0,c=a.length;c>b;b++)for(i=h[a[b]],h[a[b]]+=1,d=f[b]=0,e=a[b];e>d;d++)f[b]=f[b]<<1|1&i,i>>>=1;return f}function m(b,c){switch(this.l=[],this.m=32768,this.e=this.g=this.c=this.q=0,this.input=x?new Uint8Array(b):b,this.s=!1,this.n=L,this.C=!1,(c||!(c={}))&&(c.index&&(this.c=c.index),c.bufferSize&&(this.m=c.bufferSize),c.bufferType&&(this.n=c.bufferType),c.resize&&(this.C=c.resize)),this.n){case K:this.b=32768,this.a=new(x?Uint8Array:Array)(32768+this.m+258);break;case L:this.b=0,this.a=new(x?Uint8Array:Array)(this.m),this.f=this.K,this.t=this.I,this.o=this.J;break;default:a(Error("invalid inflate mode"))}}function n(b,c){for(var d,e=b.g,f=b.e,g=b.input,h=b.c,i=g.length;c>f;)h>=i&&a(Error("input buffer is broken")),e|=g[h++]<>>c,b.e=f-c,b.c=h,d}function o(a,b){for(var c,d,e=a.g,f=a.e,g=a.input,h=a.c,i=g.length,j=b[0],k=b[1];k>f&&!(h>=i);)e|=g[h++]<>>16,a.g=e>>d,a.e=f-d,a.c=h,65535&c}function p(a){function b(a,b,c){var d,e,f,g=this.z;for(f=0;a>f;)switch(d=o(this,b)){case 16:for(e=3+n(this,2);e--;)c[f++]=g;break;case 17:for(e=3+n(this,3);e--;)c[f++]=0;g=0;break;case 18:for(e=11+n(this,7);e--;)c[f++]=0;g=0;break;default:g=c[f++]=d}return this.z=g,c}var c,d,f,g,h=n(a,5)+257,i=n(a,5)+1,j=n(a,4)+4,k=new(x?Uint8Array:Array)(Q.length);for(g=0;j>g;++g)k[Q[g]]=n(a,3);if(!x)for(g=j,j=k.length;j>g;++g)k[Q[g]]=0;c=e(k),d=new(x?Uint8Array:Array)(h),f=new(x?Uint8Array:Array)(i),a.z=0,a.o(e(b.call(a,h,c,d)),e(b.call(a,i,c,f)))}function q(a){if("string"==typeof a){var b,c,d=a.split("");for(b=0,c=d.length;c>b;b++)d[b]=(255&d[b].charCodeAt(0))>>>0;a=d}for(var e,f=1,g=0,h=a.length,i=0;h>0;){e=h>1024?1024:h,h-=e;do f+=a[i++],g+=f;while(--e);f%=65521,g%=65521}return(g<<16|f)>>>0}function r(b,c){var d,e;switch(this.input=b,this.c=0,(c||!(c={}))&&(c.index&&(this.c=c.index),c.verify&&(this.N=c.verify)),d=b[this.c++],e=b[this.c++],15&d){case db:this.method=db;break;default:a(Error("unsupported compression method"))}0!==((d<<8)+e)%31&&a(Error("invalid fcheck flag:"+((d<<8)+e)%31)),32&e&&a(Error("fdict flag is not supported")),this.B=new m(b,{index:this.c,bufferSize:c.bufferSize,bufferType:c.bufferType,resize:c.resize})}function s(a,b){this.input=a,this.a=new(x?Uint8Array:Array)(32768),this.h=eb.k;var c,d={};!b&&(b={})||"number"!=typeof b.compressionType||(this.h=b.compressionType);for(c in b)d[c]=b[c];d.outputBuffer=this.a,this.A=new f(this.input,d)}function t(a,c){var d,e,f,g;if(Object.keys)d=Object.keys(c); -else for(e in d=[],f=0,c)d[f++]=e;for(f=0,g=d.length;g>f;++f)e=d[f],b(a+"."+e,c[e])}var u=void 0,v=!0,w=this,x="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array&&"undefined"!=typeof DataView;c.prototype.f=function(){var a,b=this.buffer,c=b.length,d=new(x?Uint8Array:Array)(c<<1);if(x)d.set(b);else for(a=0;c>a;++a)d[a]=b[a];return this.buffer=d},c.prototype.d=function(a,b,c){var d,e=this.buffer,f=this.index,g=this.i,h=e[f];if(c&&b>1&&(a=b>8?(D[255&a]<<24|D[a>>>8&255]<<16|D[a>>>16&255]<<8|D[a>>>24&255])>>32-b:D[a]>>8-b),8>b+g)h=h<d;++d)h=h<<1|a>>b-d-1&1,8===++g&&(g=0,e[f++]=D[h],h=0,f===e.length&&(e=this.f()));e[f]=h,this.buffer=e,this.i=g,this.index=f},c.prototype.finish=function(){var a,b=this.buffer,c=this.index;return 0y;++y){for(var A=y,B=A,C=7,A=A>>>1;A;A>>>=1)B<<=1,B|=1&A,--C;z[y]=(B<>>0}var D=z;d.prototype.getParent=function(a){return 2*((a-2)/4|0)},d.prototype.push=function(a,b){var c,d,e,f=this.buffer;for(c=this.length,f[this.length++]=b,f[this.length++]=a;c>0&&(d=this.getParent(c),f[c]>f[d]);)e=f[c],f[c]=f[d],f[d]=e,e=f[c+1],f[c+1]=f[d+1],f[d+1]=e,c=d;return this.length},d.prototype.pop=function(){var a,b,c,d,e,f=this.buffer;for(b=f[0],a=f[1],this.length-=2,f[0]=f[this.length],f[1]=f[this.length+1],e=0;(d=2*e+2,!(d>=this.length))&&(d+2f[d]&&(d+=2),f[d]>f[e]);)c=f[e],f[e]=f[d],f[d]=c,c=f[e+1],f[e+1]=f[d+1],f[d+1]=c,e=d;return{index:a,value:b,length:this.length}};var E,F=2,G={NONE:0,r:1,k:F,O:3},H=[];for(E=0;288>E;E++)switch(v){case 143>=E:H.push([E+48,8]);break;case 255>=E:H.push([E-144+400,9]);break;case 279>=E:H.push([E-256+0,7]);break;case 287>=E:H.push([E-280+192,8]);break;default:a("invalid literal: "+E)}f.prototype.j=function(){var b,d,e,f,g=this.input;switch(this.h){case 0:for(e=0,f=g.length;f>e;){d=x?g.subarray(e,e+65535):g.slice(e,e+65535),e+=d.length;var i=d,k=e===f,m=u,n=u,o=u,p=u,q=u,r=this.a,s=this.b;if(x){for(r=new Uint8Array(this.a.buffer);r.length<=s+i.length+5;)r=new Uint8Array(r.length<<1);r.set(this.a)}if(m=k?1:0,r[s++]=0|m,n=i.length,o=~n+65536&65535,r[s++]=255&n,r[s++]=n>>>8&255,r[s++]=255&o,r[s++]=o>>>8&255,x)r.set(i,s),s+=i.length,r=r.subarray(0,s);else{for(p=0,q=i.length;q>p;++p)r[s++]=i[p];r.length=s}this.b=s,this.a=r}break;case 1:var t=new c(x?new Uint8Array(this.a.buffer):this.a,this.b);t.d(1,1,v),t.d(1,2,v);var w,y,z,A=h(this,g);for(w=0,y=A.length;y>w;w++)if(z=A[w],c.prototype.d.apply(t,H[z]),z>256)t.d(A[++w],A[++w],v),t.d(A[++w],5),t.d(A[++w],A[++w],v);else if(256===z)break;this.a=t.finish(),this.b=this.a.length;break;case F:var B,C,D,E,G,I,J,K,L,M,N,O,P,Q,R,S=new c(x?new Uint8Array(this.a.buffer):this.a,this.b),T=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],U=Array(19);for(B=F,S.d(1,1,v),S.d(B,2,v),C=h(this,g),I=j(this.M,15),J=l(I),K=j(this.L,7),L=l(K),D=286;D>257&&0===I[D-1];D--);for(E=30;E>1&&0===K[E-1];E--);var V,W,X,Y,Z,$,_=D,ab=E,bb=new(x?Uint32Array:Array)(_+ab),cb=new(x?Uint32Array:Array)(316),db=new(x?Uint8Array:Array)(19);for(V=W=0;_>V;V++)bb[W++]=I[V];for(V=0;ab>V;V++)bb[W++]=K[V];if(!x)for(V=0,Y=db.length;Y>V;++V)db[V]=0;for(V=Z=0,Y=bb.length;Y>V;V+=W){for(W=1;Y>V+W&&bb[V+W]===bb[V];++W);if(X=W,0===bb[V])if(3>X)for(;00;)$=138>X?X:138,$>X-3&&X>$&&($=X-3),10>=$?(cb[Z++]=17,cb[Z++]=$-3,db[17]++):(cb[Z++]=18,cb[Z++]=$-11,db[18]++),X-=$;else if(cb[Z++]=bb[V],db[bb[V]]++,X--,3>X)for(;00;)$=6>X?X:6,$>X-3&&X>$&&($=X-3),cb[Z++]=16,cb[Z++]=$-3,db[16]++,X-=$}for(b=x?cb.subarray(0,Z):cb.slice(0,Z),M=j(db,7),Q=0;19>Q;Q++)U[Q]=M[T[Q]];for(G=19;G>4&&0===U[G-1];G--);for(N=l(M),S.d(D-257,5,v),S.d(E-1,5,v),S.d(G-4,4,v),Q=0;G>Q;Q++)S.d(U[Q],3,v);for(Q=0,R=b.length;R>Q;Q++)if(O=b[Q],S.d(N[O],M[O],v),O>=16){switch(Q++,O){case 16:P=2;break;case 17:P=3;break;case 18:P=7;break;default:a("invalid code: "+O)}S.d(b[Q],P,v)}var eb,fb,gb,hb,ib,jb,kb,lb,mb=[J,I],nb=[L,K];for(ib=mb[0],jb=mb[1],kb=nb[0],lb=nb[1],eb=0,fb=C.length;fb>eb;++eb)if(gb=C[eb],S.d(ib[gb],jb[gb],v),gb>256)S.d(C[++eb],C[++eb],v),hb=C[++eb],S.d(kb[hb],lb[hb],v),S.d(C[++eb],C[++eb],v);else if(256===gb)break;this.a=S.finish(),this.b=this.a.length;break;default:a("invalid compression type")}return this.a};var I=function(){function b(b){switch(v){case 3===b:return[257,b-3,0];case 4===b:return[258,b-4,0];case 5===b:return[259,b-5,0];case 6===b:return[260,b-6,0];case 7===b:return[261,b-7,0];case 8===b:return[262,b-8,0];case 9===b:return[263,b-9,0];case 10===b:return[264,b-10,0];case 12>=b:return[265,b-11,1];case 14>=b:return[266,b-13,1];case 16>=b:return[267,b-15,1];case 18>=b:return[268,b-17,1];case 22>=b:return[269,b-19,2];case 26>=b:return[270,b-23,2];case 30>=b:return[271,b-27,2];case 34>=b:return[272,b-31,2];case 42>=b:return[273,b-35,3];case 50>=b:return[274,b-43,3];case 58>=b:return[275,b-51,3];case 66>=b:return[276,b-59,3];case 82>=b:return[277,b-67,4];case 98>=b:return[278,b-83,4];case 114>=b:return[279,b-99,4];case 130>=b:return[280,b-115,4];case 162>=b:return[281,b-131,5];case 194>=b:return[282,b-163,5];case 226>=b:return[283,b-195,5];case 257>=b:return[284,b-227,5];case 258===b:return[285,b-258,0];default:a("invalid length: "+b)}}var c,d,e=[];for(c=3;258>=c;c++)d=b(c),e[c]=d[2]<<24|d[1]<<16|d[0];return e}(),J=x?new Uint32Array(I):I,K=0,L=1,M={F:K,D:L};m.prototype.p=function(){for(;!this.s;){var b=n(this,3);switch(1&b&&(this.s=v),b>>>=1){case 0:var c=this.input,d=this.c,e=this.a,f=this.b,g=c.length,h=u,i=u,j=e.length,k=u;switch(this.e=this.g=0,d+1>=g&&a(Error("invalid uncompressed block header: LEN")),h=c[d++]|c[d++]<<8,d+1>=g&&a(Error("invalid uncompressed block header: NLEN")),i=c[d++]|c[d++]<<8,h===~i&&a(Error("invalid uncompressed block header: length verify")),d+h>c.length&&a(Error("input buffer is broken")),this.n){case K:for(;f+h>e.length;){if(k=j-f,h-=k,x)e.set(c.subarray(d,d+k),f),f+=k,d+=k;else for(;k--;)e[f++]=c[d++];this.b=f,e=this.f(),f=this.b}break;case L:for(;f+h>e.length;)e=this.f({v:2});break;default:a(Error("invalid inflate mode"))}if(x)e.set(c.subarray(d,d+h),f),f+=h,d+=h;else for(;h--;)e[f++]=c[d++];this.c=d,this.b=f,this.a=e;break;case 1:this.o(ab,cb);break;case 2:p(this);break;default:a(Error("unknown BTYPE: "+b))}}return this.t()};var N,O,P=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],Q=x?new Uint16Array(P):P,R=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],S=x?new Uint16Array(R):R,T=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],U=x?new Uint8Array(T):T,V=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],W=x?new Uint16Array(V):V,X=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],Y=x?new Uint8Array(X):X,Z=new(x?Uint8Array:Array)(288);for(N=0,O=Z.length;O>N;++N)Z[N]=143>=N?8:255>=N?9:279>=N?7:8;var $,_,ab=e(Z),bb=new(x?Uint8Array:Array)(30);for($=0,_=bb.length;_>$;++$)bb[$]=5;var cb=e(bb);m.prototype.o=function(a,b){var c=this.a,d=this.b;this.u=a;for(var e,f,g,h,i=c.length-258;256!==(e=o(this,a));)if(256>e)d>=i&&(this.b=d,c=this.f(),d=this.b),c[d++]=e;else for(f=e-257,h=S[f],0=i&&(this.b=d,c=this.f(),d=this.b);h--;)c[d]=c[d++-g];for(;8<=this.e;)this.e-=8,this.c--;this.b=d},m.prototype.J=function(a,b){var c=this.a,d=this.b;this.u=a;for(var e,f,g,h,i=c.length;256!==(e=o(this,a));)if(256>e)d>=i&&(c=this.f(),i=c.length),c[d++]=e;else for(f=e-257,h=S[f],0i&&(c=this.f(),i=c.length);h--;)c[d]=c[d++-g];for(;8<=this.e;)this.e-=8,this.c--;this.b=d},m.prototype.f=function(){var a,b,c=new(x?Uint8Array:Array)(this.b-32768),d=this.b-32768,e=this.a;if(x)c.set(e.subarray(32768,c.length));else for(a=0,b=c.length;b>a;++a)c[a]=e[a+32768];if(this.l.push(c),this.q+=c.length,x)e.set(e.subarray(d,d+32768));else for(a=0;32768>a;++a)e[a]=e[d+a];return this.b=32768,e},m.prototype.K=function(a){var b,c,d,e,f=this.input.length/this.c+1|0,g=this.input,h=this.a;return a&&("number"==typeof a.v&&(f=a.v),"number"==typeof a.G&&(f+=a.G)),2>f?(c=(g.length-this.c)/this.u[2],e=258*(c/2)|0,d=eb;++b)for(a=h[b],d=0,e=a.length;e>d;++d)i[f++]=a[d];for(b=32768,c=this.b;c>b;++b)i[f++]=g[b];return this.l=[],this.buffer=i},m.prototype.I=function(){var a,b=this.b;return x?this.C?(a=new Uint8Array(b),a.set(this.a.subarray(0,b))):a=this.a.subarray(0,b):(this.a.length>b&&(this.a.length=b),a=this.a),this.buffer=a},r.prototype.p=function(){var b,c,d=this.input;return b=this.B.p(),this.c=this.B.c,this.N&&(c=(d[this.c++]<<24|d[this.c++]<<16|d[this.c++]<<8|d[this.c++])>>>0,c!==q(b)&&a(Error("invalid adler-32 checksum"))),b};var db=8,eb=G;s.prototype.j=function(){var b,c,d,e,f,g,h,i=0;switch(h=this.a,b=db){case db:c=Math.LOG2E*Math.log(32768)-8;break;default:a(Error("invalid compression method"))}switch(d=c<<4|b,h[i++]=d,b){case db:switch(this.h){case eb.NONE:f=0;break;case eb.r:f=1;break;case eb.k:f=2;break;default:a(Error("unsupported compression type"))}break;default:a(Error("invalid compression method"))}return e=f<<6|0,h[i++]=e|31-(256*d+e)%31,g=q(this.input),this.A.b=i,h=this.A.j(),i=h.length,x&&(h=new Uint8Array(h.buffer),h.length<=i+4&&(this.a=new Uint8Array(h.length+4),this.a.set(h),h=this.a),h=h.subarray(0,i+4)),h[i++]=g>>24&255,h[i++]=g>>16&255,h[i++]=g>>8&255,h[i++]=255&g,h},b("Zlib.Inflate",r),b("Zlib.Inflate.prototype.decompress",r.prototype.p),t("Zlib.Inflate.BufferType",{ADAPTIVE:M.D,BLOCK:M.F}),b("Zlib.Deflate",s),b("Zlib.Deflate.compress",function(a,b){return new s(a,b).j()}),b("Zlib.Deflate.prototype.compress",s.prototype.j),t("Zlib.Deflate.CompressionType",{NONE:eb.NONE,FIXED:eb.r,DYNAMIC:eb.k})}).call(this)},{}],16:[function(a,b){var c=a("../enums.js");b.exports={prefer_hash_algorithm:c.hash.sha256,encryption_cipher:c.symmetric.aes256,compression:c.compression.zip,integrity_protect:!0,rsa_blinding:!0,show_version:!0,show_comment:!0,versionstring:"OpenPGP.js v0.9.0",commentstring:"http://openpgpjs.org",keyserver:"keyserver.linux.it",node_store:"./openpgp.store",debug:!1}},{"../enums.js":43}],17:[function(a,b){b.exports=a("./config.js")},{"./config.js":16}],18:[function(a,b){"use strict";var c=a("../util.js"),d=a("./cipher");b.exports={encrypt:function(a,b,e,f,g){b=new d[b](f);var h=b.blockSize,i=new Uint8Array(h),j=new Uint8Array(h);a=a+a.charAt(h-2)+a.charAt(h-1);var k,l,m,n=new Uint8Array(e.length+2+2*h),o=g?0:2;for(k=0;h>k;k++)i[k]=0;for(j=b.encrypt(i),k=0;h>k;k++)n[k]=j[k]^a.charCodeAt(k);for(i.set(n.subarray(0,h)),j=b.encrypt(i),n[h]=j[0]^a.charCodeAt(h),n[h+1]=j[1]^a.charCodeAt(h+1),i.set(g?n.subarray(2,h+2):n.subarray(0,h)),j=b.encrypt(i),k=0;h>k;k++)n[h+2+k]=j[k+o]^e.charCodeAt(k);for(l=h;lk;k++)n[h+m+k]=j[k]^e.charCodeAt(l+k-o);return n=n.subarray(0,e.length+2+h),c.Uint8Array2str(n)},mdc:function(a,b,e){a=new d[a](b);var f,g=a.blockSize,h=new Uint8Array(g),i=new Uint8Array(g);for(f=0;g>f;f++)h[f]=0;for(h=a.encrypt(h),f=0;g>f;f++)i[f]=e.charCodeAt(f),h[f]^=i[f];return i=a.encrypt(i),c.bin2str(h)+String.fromCharCode(i[0]^e.charCodeAt(g))+String.fromCharCode(i[1]^e.charCodeAt(g+1))},decrypt:function(a,b,c,e){a=new d[a](b);var f,g=a.blockSize,h=new Uint8Array(g),i=new Uint8Array(g),j="",k="";for(f=0;g>f;f++)h[f]=0;for(h=a.encrypt(h),f=0;g>f;f++)i[f]=c.charCodeAt(f),h[f]^=i[f];if(i=a.encrypt(i),h[g-2]!=(i[0]^c.charCodeAt(g))||h[g-1]!=(i[1]^c.charCodeAt(g+1)))throw new Error("CFB decrypt: invalid key");if(e){for(f=0;g>f;f++)h[f]=c.charCodeAt(f+2);for(j=g+2;jf&&f+jf;f++)h[f]=c.charCodeAt(f);for(j=g;jf&&f+jg*j;){var m=a.encrypt(c.str2bin(i));h=e.substring(j*g,j*g+g);for(var n=0;ng;g++)i+=String.fromCharCode(0);else i=f.substring(0,h);for(;e.length>h*j;){var m=a.encrypt(c.str2bin(i));for(i=e.substring(j*h+l,j*h+h+l),g=0;g>8&255}function e(a){return a>>16&255}function f(a){return a>>24&255}function g(a,b,c,e){return d(o[255&a])|d(o[b>>8&255])<<8|d(o[c>>16&255])<<16|d(o[e>>>24])<<24}function h(a){var b,c,d=a.length,e=new Array(d/4);if(a&&!(d%4)){for(b=0,c=0;d>c;c+=4)e[b++]=a[c]|a[c+1]<<8|a[c+2]<<16|a[c+3]<<24;return e}}function i(a){var b,g=0,h=a.length,i=new Array(4*h);for(b=0;h>b;b++)i[g++]=c(a[b]),i[g++]=d(a[b]),i[g++]=e(a[b]),i[g++]=f(a[b]);return i}function j(a){var b,g,h,i,j,k,l=new Array(t+1),o=a.length,p=new Array(s),q=new Array(s),r=0;if(16==o)k=10,b=4;else if(24==o)k=12,b=6;else{if(32!=o)throw new Error("Invalid key-length for AES key:"+o);k=14,b=8}for(g=0;t+1>g;g++)l[g]=new Uint32Array(4);for(g=0,h=0;o>h;h++,g+=4)p[h]=a.charCodeAt(g)|a.charCodeAt(g+1)<<8|a.charCodeAt(g+2)<<16|a.charCodeAt(g+3)<<24;for(h=b-1;h>=0;h--)q[h]=p[h];for(i=0,j=0,h=0;b>h&&k+1>i;){for(;b>h&&4>j;h++,j++)l[i][j]=q[h];4==j&&(i++,j=0)}for(;k+1>i;){var u=q[b-1];if(q[0]^=n[d(u)]|n[e(u)]<<8|n[f(u)]<<16|n[c(u)]<<24,q[0]^=m[r++],8!=b)for(h=1;b>h;h++)q[h]^=q[h-1];else{for(h=1;b/2>h;h++)q[h]^=q[h-1];for(u=q[b/2-1],q[b/2]^=n[c(u)]|n[d(u)]<<8|n[e(u)]<<16|n[f(u)]<<24,h=b/2+1;b>h;h++)q[h]^=q[h-1]}for(h=0;b>h&&k+1>i;){for(;b>h&&4>j;h++,j++)l[i][j]=q[h];4==j&&(i++,j=0)}}return{rounds:k,rk:l}}function k(a,b,c){var d,e,f;for(f=h(a),e=b.rounds,d=0;e-1>d;d++)c[0]=f[0]^b.rk[d][0],c[1]=f[1]^b.rk[d][1],c[2]=f[2]^b.rk[d][2],c[3]=f[3]^b.rk[d][3],f[0]=o[255&c[0]]^p[c[1]>>8&255]^q[c[2]>>16&255]^r[c[3]>>>24],f[1]=o[255&c[1]]^p[c[2]>>8&255]^q[c[3]>>16&255]^r[c[0]>>>24],f[2]=o[255&c[2]]^p[c[3]>>8&255]^q[c[0]>>16&255]^r[c[1]>>>24],f[3]=o[255&c[3]]^p[c[0]>>8&255]^q[c[1]>>16&255]^r[c[2]>>>24];return d=e-1,c[0]=f[0]^b.rk[d][0],c[1]=f[1]^b.rk[d][1],c[2]=f[2]^b.rk[d][2],c[3]=f[3]^b.rk[d][3],f[0]=g(c[0],c[1],c[2],c[3])^b.rk[e][0],f[1]=g(c[1],c[2],c[3],c[0])^b.rk[e][1],f[2]=g(c[2],c[3],c[0],c[1])^b.rk[e][2],f[3]=g(c[3],c[0],c[1],c[2])^b.rk[e][3],i(f)}function l(a){var b=function(a){this.key=j(a),this._temp=new Uint32Array(this.blockSize/4),this.encrypt=function(a){return k(a,this.key,this._temp)}};return b.blockSize=b.prototype.blockSize=16,b.keySize=b.prototype.keySize=a/8,b}var m=(a("../../util.js"),new Uint8Array([1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145])),n=new Uint8Array([99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22]),o=new Uint32Array([2774754246,2222750968,2574743534,2373680118,234025727,3177933782,2976870366,1422247313,1345335392,50397442,2842126286,2099981142,436141799,1658312629,3870010189,2591454956,1170918031,2642575903,1086966153,2273148410,368769775,3948501426,3376891790,200339707,3970805057,1742001331,4255294047,3937382213,3214711843,4154762323,2524082916,1539358875,3266819957,486407649,2928907069,1780885068,1513502316,1094664062,49805301,1338821763,1546925160,4104496465,887481809,150073849,2473685474,1943591083,1395732834,1058346282,201589768,1388824469,1696801606,1589887901,672667696,2711000631,251987210,3046808111,151455502,907153956,2608889883,1038279391,652995533,1764173646,3451040383,2675275242,453576978,2659418909,1949051992,773462580,756751158,2993581788,3998898868,4221608027,4132590244,1295727478,1641469623,3467883389,2066295122,1055122397,1898917726,2542044179,4115878822,1758581177,0,753790401,1612718144,536673507,3367088505,3982187446,3194645204,1187761037,3653156455,1262041458,3729410708,3561770136,3898103984,1255133061,1808847035,720367557,3853167183,385612781,3309519750,3612167578,1429418854,2491778321,3477423498,284817897,100794884,2172616702,4031795360,1144798328,3131023141,3819481163,4082192802,4272137053,3225436288,2324664069,2912064063,3164445985,1211644016,83228145,3753688163,3249976951,1977277103,1663115586,806359072,452984805,250868733,1842533055,1288555905,336333848,890442534,804056259,3781124030,2727843637,3427026056,957814574,1472513171,4071073621,2189328124,1195195770,2892260552,3881655738,723065138,2507371494,2690670784,2558624025,3511635870,2145180835,1713513028,2116692564,2878378043,2206763019,3393603212,703524551,3552098411,1007948840,2044649127,3797835452,487262998,1994120109,1004593371,1446130276,1312438900,503974420,3679013266,168166924,1814307912,3831258296,1573044895,1859376061,4021070915,2791465668,2828112185,2761266481,937747667,2339994098,854058965,1137232011,1496790894,3077402074,2358086913,1691735473,3528347292,3769215305,3027004632,4199962284,133494003,636152527,2942657994,2390391540,3920539207,403179536,3585784431,2289596656,1864705354,1915629148,605822008,4054230615,3350508659,1371981463,602466507,2094914977,2624877800,555687742,3712699286,3703422305,2257292045,2240449039,2423288032,1111375484,3300242801,2858837708,3628615824,84083462,32962295,302911004,2741068226,1597322602,4183250862,3501832553,2441512471,1489093017,656219450,3114180135,954327513,335083755,3013122091,856756514,3144247762,1893325225,2307821063,2811532339,3063651117,572399164,2458355477,552200649,1238290055,4283782570,2015897680,2061492133,2408352771,4171342169,2156497161,386731290,3669999461,837215959,3326231172,3093850320,3275833730,2962856233,1999449434,286199582,3417354363,4233385128,3602627437,974525996]),p=new Uint32Array([1667483301,2088564868,2004348569,2071721613,4076011277,1802229437,1869602481,3318059348,808476752,16843267,1734856361,724260477,4278118169,3621238114,2880130534,1987505306,3402272581,2189565853,3385428288,2105408135,4210749205,1499050731,1195871945,4042324747,2913812972,3570709351,2728550397,2947499498,2627478463,2762232823,1920132246,3233848155,3082253762,4261273884,2475900334,640044138,909536346,1061125697,4160222466,3435955023,875849820,2779075060,3857043764,4059166984,1903288979,3638078323,825320019,353708607,67373068,3351745874,589514341,3284376926,404238376,2526427041,84216335,2593796021,117902857,303178806,2155879323,3806519101,3958099238,656887401,2998042573,1970662047,151589403,2206408094,741103732,437924910,454768173,1852759218,1515893998,2694863867,1381147894,993752653,3604395873,3014884814,690573947,3823361342,791633521,2223248279,1397991157,3520182632,0,3991781676,538984544,4244431647,2981198280,1532737261,1785386174,3419114822,3200149465,960066123,1246401758,1280088276,1482207464,3486483786,3503340395,4025468202,2863288293,4227591446,1128498885,1296931543,859006549,2240090516,1162185423,4193904912,33686534,2139094657,1347461360,1010595908,2678007226,2829601763,1364304627,2745392638,1077969088,2408514954,2459058093,2644320700,943222856,4126535940,3166462943,3065411521,3671764853,555827811,269492272,4294960410,4092853518,3537026925,3452797260,202119188,320022069,3974939439,1600110305,2543269282,1145342156,387395129,3301217111,2812761586,2122251394,1027439175,1684326572,1566423783,421081643,1936975509,1616953504,2172721560,1330618065,3705447295,572671078,707417214,2425371563,2290617219,1179028682,4008625961,3099093971,336865340,3739133817,1583267042,185275933,3688607094,3772832571,842163286,976909390,168432670,1229558491,101059594,606357612,1549580516,3267534685,3553869166,2896970735,1650640038,2442213800,2509582756,3840201527,2038035083,3890730290,3368586051,926379609,1835915959,2374828428,3587551588,1313774802,2846444e3,1819072692,1448520954,4109693703,3941256997,1701169839,2054878350,2930657257,134746136,3132780501,2021191816,623200879,774790258,471611428,2795919345,3031724999,3334903633,3907570467,3722289532,1953818780,522141217,1263245021,3183305180,2341145990,2324303749,1886445712,1044282434,3048567236,1718013098,1212715224,50529797,4143380225,235805714,1633796771,892693087,1465364217,3115936208,2256934801,3250690392,488454695,2661164985,3789674808,4177062675,2560109491,286335539,1768542907,3654920560,2391672713,2492740519,2610638262,505297954,2273777042,3924412704,3469641545,1431677695,673730680,3755976058,2357986191,2711706104,2307459456,218962455,3216991706,3873888049,1111655622,1751699640,1094812355,2576951728,757946999,252648977,2964356043,1414834428,3149622742,370551866]),q=new Uint32Array([1673962851,2096661628,2012125559,2079755643,4076801522,1809235307,1876865391,3314635973,811618352,16909057,1741597031,727088427,4276558334,3618988759,2874009259,1995217526,3398387146,2183110018,3381215433,2113570685,4209972730,1504897881,1200539975,4042984432,2906778797,3568527316,2724199842,2940594863,2619588508,2756966308,1927583346,3231407040,3077948087,4259388669,2470293139,642542118,913070646,1065238847,4160029431,3431157708,879254580,2773611685,3855693029,4059629809,1910674289,3635114968,828527409,355090197,67636228,3348452039,591815971,3281870531,405809176,2520228246,84545285,2586817946,118360327,304363026,2149292928,3806281186,3956090603,659450151,2994720178,1978310517,152181513,2199756419,743994412,439627290,456535323,1859957358,1521806938,2690382752,1386542674,997608763,3602342358,3011366579,693271337,3822927587,794718511,2215876484,1403450707,3518589137,0,3988860141,541089824,4242743292,2977548465,1538714971,1792327274,3415033547,3194476990,963791673,1251270218,1285084236,1487988824,3481619151,3501943760,4022676207,2857362858,4226619131,1132905795,1301993293,862344499,2232521861,1166724933,4192801017,33818114,2147385727,1352724560,1014514748,2670049951,2823545768,1369633617,2740846243,1082179648,2399505039,2453646738,2636233885,946882616,4126213365,3160661948,3061301686,3668932058,557998881,270544912,4293204735,4093447923,3535760850,3447803085,202904588,321271059,3972214764,1606345055,2536874647,1149815876,388905239,3297990596,2807427751,2130477694,1031423805,1690872932,1572530013,422718233,1944491379,1623236704,2165938305,1335808335,3701702620,574907938,710180394,2419829648,2282455944,1183631942,4006029806,3094074296,338181140,3735517662,1589437022,185998603,3685578459,3772464096,845436466,980700730,169090570,1234361161,101452294,608726052,1555620956,3265224130,3552407251,2890133420,1657054818,2436475025,2503058581,3839047652,2045938553,3889509095,3364570056,929978679,1843050349,2365688973,3585172693,1318900302,2840191145,1826141292,1454176854,4109567988,3939444202,1707781989,2062847610,2923948462,135272456,3127891386,2029029496,625635109,777810478,473441308,2790781350,3027486644,3331805638,3905627112,3718347997,1961401460,524165407,1268178251,3177307325,2332919435,2316273034,1893765232,1048330814,3044132021,1724688998,1217452104,50726147,4143383030,236720654,1640145761,896163637,1471084887,3110719673,2249691526,3248052417,490350365,2653403550,3789109473,4176155640,2553000856,287453969,1775418217,3651760345,2382858638,2486413204,2603464347,507257374,2266337927,3922272489,3464972750,1437269845,676362280,3752164063,2349043596,2707028129,2299101321,219813645,3211123391,3872862694,1115997762,1758509160,1099088705,2569646233,760903469,253628687,2960903088,1420360788,3144537787,371997206]),r=new Uint32Array([3332727651,4169432188,4003034999,4136467323,4279104242,3602738027,3736170351,2438251973,1615867952,33751297,3467208551,1451043627,3877240574,3043153879,1306962859,3969545846,2403715786,530416258,2302724553,4203183485,4011195130,3001768281,2395555655,4211863792,1106029997,3009926356,1610457762,1173008303,599760028,1408738468,3835064946,2606481600,1975695287,3776773629,1034851219,1282024998,1817851446,2118205247,4110612471,2203045068,1750873140,1374987685,3509904869,4178113009,3801313649,2876496088,1649619249,708777237,135005188,2505230279,1181033251,2640233411,807933976,933336726,168756485,800430746,235472647,607523346,463175808,3745374946,3441880043,1315514151,2144187058,3936318837,303761673,496927619,1484008492,875436570,908925723,3702681198,3035519578,1543217312,2767606354,1984772923,3076642518,2110698419,1383803177,3711886307,1584475951,328696964,2801095507,3110654417,0,3240947181,1080041504,3810524412,2043195825,3069008731,3569248874,2370227147,1742323390,1917532473,2497595978,2564049996,2968016984,2236272591,3144405200,3307925487,1340451498,3977706491,2261074755,2597801293,1716859699,294946181,2328839493,3910203897,67502594,4269899647,2700103760,2017737788,632987551,1273211048,2733855057,1576969123,2160083008,92966799,1068339858,566009245,1883781176,4043634165,1675607228,2009183926,2943736538,1113792801,540020752,3843751935,4245615603,3211645650,2169294285,403966988,641012499,3274697964,3202441055,899848087,2295088196,775493399,2472002756,1441965991,4236410494,2051489085,3366741092,3135724893,841685273,3868554099,3231735904,429425025,2664517455,2743065820,1147544098,1417554474,1001099408,193169544,2362066502,3341414126,1809037496,675025940,2809781982,3168951902,371002123,2910247899,3678134496,1683370546,1951283770,337512970,2463844681,201983494,1215046692,3101973596,2673722050,3178157011,1139780780,3299238498,967348625,832869781,3543655652,4069226873,3576883175,2336475336,1851340599,3669454189,25988493,2976175573,2631028302,1239460265,3635702892,2902087254,4077384948,3475368682,3400492389,4102978170,1206496942,270010376,1876277946,4035475576,1248797989,1550986798,941890588,1475454630,1942467764,2538718918,3408128232,2709315037,3902567540,1042358047,2531085131,1641856445,226921355,260409994,3767562352,2084716094,1908716981,3433719398,2430093384,100991747,4144101110,470945294,3265487201,1784624437,2935576407,1775286713,395413126,2572730817,975641885,666476190,3644383713,3943954680,733190296,573772049,3535497577,2842745305,126455438,866620564,766942107,1008868894,361924487,3374377449,2269761230,2868860245,1350051880,2776293343,59739276,1509466529,159418761,437718285,1708834751,3610371814,2227585602,3501746280,2193834305,699439513,1517759789,504434447,2076946608,2835108948,1842789307,742004246]),s=8,t=14;b.exports={};var u=[128,192,256];for(var v in u)b.exports[u[v]]=l(u[v])},{"../../util.js":74}],20:[function(a,b){function c(){}function d(a){this.bf=new c,this.bf.init(e.str2bin(a)),this.encrypt=function(a){return this.bf.encrypt_block(a)}}c.prototype.BLOCKSIZE=8,c.prototype.SBOXES=[[3509652390,2564797868,805139163,3491422135,3101798381,1780907670,3128725573,4046225305,614570311,3012652279,134345442,2240740374,1667834072,1901547113,2757295779,4103290238,227898511,1921955416,1904987480,2182433518,2069144605,3260701109,2620446009,720527379,3318853667,677414384,3393288472,3101374703,2390351024,1614419982,1822297739,2954791486,3608508353,3174124327,2024746970,1432378464,3864339955,2857741204,1464375394,1676153920,1439316330,715854006,3033291828,289532110,2706671279,2087905683,3018724369,1668267050,732546397,1947742710,3462151702,2609353502,2950085171,1814351708,2050118529,680887927,999245976,1800124847,3300911131,1713906067,1641548236,4213287313,1216130144,1575780402,4018429277,3917837745,3693486850,3949271944,596196993,3549867205,258830323,2213823033,772490370,2760122372,1774776394,2652871518,566650946,4142492826,1728879713,2882767088,1783734482,3629395816,2517608232,2874225571,1861159788,326777828,3124490320,2130389656,2716951837,967770486,1724537150,2185432712,2364442137,1164943284,2105845187,998989502,3765401048,2244026483,1075463327,1455516326,1322494562,910128902,469688178,1117454909,936433444,3490320968,3675253459,1240580251,122909385,2157517691,634681816,4142456567,3825094682,3061402683,2540495037,79693498,3249098678,1084186820,1583128258,426386531,1761308591,1047286709,322548459,995290223,1845252383,2603652396,3431023940,2942221577,3202600964,3727903485,1712269319,422464435,3234572375,1170764815,3523960633,3117677531,1434042557,442511882,3600875718,1076654713,1738483198,4213154764,2393238008,3677496056,1014306527,4251020053,793779912,2902807211,842905082,4246964064,1395751752,1040244610,2656851899,3396308128,445077038,3742853595,3577915638,679411651,2892444358,2354009459,1767581616,3150600392,3791627101,3102740896,284835224,4246832056,1258075500,768725851,2589189241,3069724005,3532540348,1274779536,3789419226,2764799539,1660621633,3471099624,4011903706,913787905,3497959166,737222580,2514213453,2928710040,3937242737,1804850592,3499020752,2949064160,2386320175,2390070455,2415321851,4061277028,2290661394,2416832540,1336762016,1754252060,3520065937,3014181293,791618072,3188594551,3933548030,2332172193,3852520463,3043980520,413987798,3465142937,3030929376,4245938359,2093235073,3534596313,375366246,2157278981,2479649556,555357303,3870105701,2008414854,3344188149,4221384143,3956125452,2067696032,3594591187,2921233993,2428461,544322398,577241275,1471733935,610547355,4027169054,1432588573,1507829418,2025931657,3646575487,545086370,48609733,2200306550,1653985193,298326376,1316178497,3007786442,2064951626,458293330,2589141269,3591329599,3164325604,727753846,2179363840,146436021,1461446943,4069977195,705550613,3059967265,3887724982,4281599278,3313849956,1404054877,2845806497,146425753,1854211946],[1266315497,3048417604,3681880366,3289982499,290971e4,1235738493,2632868024,2414719590,3970600049,1771706367,1449415276,3266420449,422970021,1963543593,2690192192,3826793022,1062508698,1531092325,1804592342,2583117782,2714934279,4024971509,1294809318,4028980673,1289560198,2221992742,1669523910,35572830,157838143,1052438473,1016535060,1802137761,1753167236,1386275462,3080475397,2857371447,1040679964,2145300060,2390574316,1461121720,2956646967,4031777805,4028374788,33600511,2920084762,1018524850,629373528,3691585981,3515945977,2091462646,2486323059,586499841,988145025,935516892,3367335476,2599673255,2839830854,265290510,3972581182,2759138881,3795373465,1005194799,847297441,406762289,1314163512,1332590856,1866599683,4127851711,750260880,613907577,1450815602,3165620655,3734664991,3650291728,3012275730,3704569646,1427272223,778793252,1343938022,2676280711,2052605720,1946737175,3164576444,3914038668,3967478842,3682934266,1661551462,3294938066,4011595847,840292616,3712170807,616741398,312560963,711312465,1351876610,322626781,1910503582,271666773,2175563734,1594956187,70604529,3617834859,1007753275,1495573769,4069517037,2549218298,2663038764,504708206,2263041392,3941167025,2249088522,1514023603,1998579484,1312622330,694541497,2582060303,2151582166,1382467621,776784248,2618340202,3323268794,2497899128,2784771155,503983604,4076293799,907881277,423175695,432175456,1378068232,4145222326,3954048622,3938656102,3820766613,2793130115,2977904593,26017576,3274890735,3194772133,1700274565,1756076034,4006520079,3677328699,720338349,1533947780,354530856,688349552,3973924725,1637815568,332179504,3949051286,53804574,2852348879,3044236432,1282449977,3583942155,3416972820,4006381244,1617046695,2628476075,3002303598,1686838959,431878346,2686675385,1700445008,1080580658,1009431731,832498133,3223435511,2605976345,2271191193,2516031870,1648197032,4164389018,2548247927,300782431,375919233,238389289,3353747414,2531188641,2019080857,1475708069,455242339,2609103871,448939670,3451063019,1395535956,2413381860,1841049896,1491858159,885456874,4264095073,4001119347,1565136089,3898914787,1108368660,540939232,1173283510,2745871338,3681308437,4207628240,3343053890,4016749493,1699691293,1103962373,3625875870,2256883143,3830138730,1031889488,3479347698,1535977030,4236805024,3251091107,2132092099,1774941330,1199868427,1452454533,157007616,2904115357,342012276,595725824,1480756522,206960106,497939518,591360097,863170706,2375253569,3596610801,1814182875,2094937945,3421402208,1082520231,3463918190,2785509508,435703966,3908032597,1641649973,2842273706,3305899714,1510255612,2148256476,2655287854,3276092548,4258621189,236887753,3681803219,274041037,1734335097,3815195456,3317970021,1899903192,1026095262,4050517792,356393447,2410691914,3873677099,3682840055],[3913112168,2491498743,4132185628,2489919796,1091903735,1979897079,3170134830,3567386728,3557303409,857797738,1136121015,1342202287,507115054,2535736646,337727348,3213592640,1301675037,2528481711,1895095763,1721773893,3216771564,62756741,2142006736,835421444,2531993523,1442658625,3659876326,2882144922,676362277,1392781812,170690266,3921047035,1759253602,3611846912,1745797284,664899054,1329594018,3901205900,3045908486,2062866102,2865634940,3543621612,3464012697,1080764994,553557557,3656615353,3996768171,991055499,499776247,1265440854,648242737,3940784050,980351604,3713745714,1749149687,3396870395,4211799374,3640570775,1161844396,3125318951,1431517754,545492359,4268468663,3499529547,1437099964,2702547544,3433638243,2581715763,2787789398,1060185593,1593081372,2418618748,4260947970,69676912,2159744348,86519011,2512459080,3838209314,1220612927,3339683548,133810670,1090789135,1078426020,1569222167,845107691,3583754449,4072456591,1091646820,628848692,1613405280,3757631651,526609435,236106946,48312990,2942717905,3402727701,1797494240,859738849,992217954,4005476642,2243076622,3870952857,3732016268,765654824,3490871365,2511836413,1685915746,3888969200,1414112111,2273134842,3281911079,4080962846,172450625,2569994100,980381355,4109958455,2819808352,2716589560,2568741196,3681446669,3329971472,1835478071,660984891,3704678404,4045999559,3422617507,3040415634,1762651403,1719377915,3470491036,2693910283,3642056355,3138596744,1364962596,2073328063,1983633131,926494387,3423689081,2150032023,4096667949,1749200295,3328846651,309677260,2016342300,1779581495,3079819751,111262694,1274766160,443224088,298511866,1025883608,3806446537,1145181785,168956806,3641502830,3584813610,1689216846,3666258015,3200248200,1692713982,2646376535,4042768518,1618508792,1610833997,3523052358,4130873264,2001055236,3610705100,2202168115,4028541809,2961195399,1006657119,2006996926,3186142756,1430667929,3210227297,1314452623,4074634658,4101304120,2273951170,1399257539,3367210612,3027628629,1190975929,2062231137,2333990788,2221543033,2438960610,1181637006,548689776,2362791313,3372408396,3104550113,3145860560,296247880,1970579870,3078560182,3769228297,1714227617,3291629107,3898220290,166772364,1251581989,493813264,448347421,195405023,2709975567,677966185,3703036547,1463355134,2715995803,1338867538,1343315457,2802222074,2684532164,233230375,2599980071,2000651841,3277868038,1638401717,4028070440,3237316320,6314154,819756386,300326615,590932579,1405279636,3267499572,3150704214,2428286686,3959192993,3461946742,1862657033,1266418056,963775037,2089974820,2263052895,1917689273,448879540,3550394620,3981727096,150775221,3627908307,1303187396,508620638,2975983352,2726630617,1817252668,1876281319,1457606340,908771278,3720792119,3617206836,2455994898,1729034894,1080033504],[976866871,3556439503,2881648439,1522871579,1555064734,1336096578,3548522304,2579274686,3574697629,3205460757,3593280638,3338716283,3079412587,564236357,2993598910,1781952180,1464380207,3163844217,3332601554,1699332808,1393555694,1183702653,3581086237,1288719814,691649499,2847557200,2895455976,3193889540,2717570544,1781354906,1676643554,2592534050,3230253752,1126444790,2770207658,2633158820,2210423226,2615765581,2414155088,3127139286,673620729,2805611233,1269405062,4015350505,3341807571,4149409754,1057255273,2012875353,2162469141,2276492801,2601117357,993977747,3918593370,2654263191,753973209,36408145,2530585658,25011837,3520020182,2088578344,530523599,2918365339,1524020338,1518925132,3760827505,3759777254,1202760957,3985898139,3906192525,674977740,4174734889,2031300136,2019492241,3983892565,4153806404,3822280332,352677332,2297720250,60907813,90501309,3286998549,1016092578,2535922412,2839152426,457141659,509813237,4120667899,652014361,1966332200,2975202805,55981186,2327461051,676427537,3255491064,2882294119,3433927263,1307055953,942726286,933058658,2468411793,3933900994,4215176142,1361170020,2001714738,2830558078,3274259782,1222529897,1679025792,2729314320,3714953764,1770335741,151462246,3013232138,1682292957,1483529935,471910574,1539241949,458788160,3436315007,1807016891,3718408830,978976581,1043663428,3165965781,1927990952,4200891579,2372276910,3208408903,3533431907,1412390302,2931980059,4132332400,1947078029,3881505623,4168226417,2941484381,1077988104,1320477388,886195818,18198404,3786409e3,2509781533,112762804,3463356488,1866414978,891333506,18488651,661792760,1628790961,3885187036,3141171499,876946877,2693282273,1372485963,791857591,2686433993,3759982718,3167212022,3472953795,2716379847,445679433,3561995674,3504004811,3574258232,54117162,3331405415,2381918588,3769707343,4154350007,1140177722,4074052095,668550556,3214352940,367459370,261225585,2610173221,4209349473,3468074219,3265815641,314222801,3066103646,3808782860,282218597,3406013506,3773591054,379116347,1285071038,846784868,2669647154,3771962079,3550491691,2305946142,453669953,1268987020,3317592352,3279303384,3744833421,2610507566,3859509063,266596637,3847019092,517658769,3462560207,3443424879,370717030,4247526661,2224018117,4143653529,4112773975,2788324899,2477274417,1456262402,2901442914,1517677493,1846949527,2295493580,3734397586,2176403920,1280348187,1908823572,3871786941,846861322,1172426758,3287448474,3383383037,1655181056,3139813346,901632758,1897031941,2986607138,3066810236,3447102507,1393639104,373351379,950779232,625454576,3124240540,4148612726,2007998917,544563296,2244738638,2330496472,2058025392,1291430526,424198748,50039436,29584100,3605783033,2429876329,2791104160,1057563949,3255363231,3075367218,3463963227,1469046755,985887462]],c.prototype.PARRAY=[608135816,2242054355,320440878,57701188,2752067618,698298832,137296536,3964562569,1160258022,953160567,3193202383,887688300,3232508343,3380367581,1065670069,3041331479,2450970073,2306472731],c.prototype.NN=16,c.prototype._clean=function(a){if(0>a){var b=2147483647&a; -a=b+2147483648}return a},c.prototype._F=function(a){var b,c,d,e,f;return e=255&a,a>>>=8,d=255&a,a>>>=8,c=255&a,a>>>=8,b=255&a,f=this.sboxes[0][b]+this.sboxes[1][c],f^=this.sboxes[2][d],f+=this.sboxes[3][e]},c.prototype._encrypt_block=function(a){var b,c=a[0],d=a[1];for(b=0;b>>24-8*b&255,e[b+d]=c[1]>>>24-8*b&255;return e},c.prototype._decrypt_block=function(a){var b,c=a[0],d=a[1];for(b=this.NN+1;b>1;--b){c^=this.parray[b],d=this._F(c)^d;var e=c;c=d,d=e}c^=this.parray[1],d^=this.parray[0],a[0]=this._clean(d),a[1]=this._clean(c)},c.prototype.init=function(a){var b,c=0;for(this.parray=[],b=0;bd;++d)e=e<<8|255&a[c],++c>=a.length&&(c=0);this.parray[b]=this.PARRAY[b]^e}for(this.sboxes=[],b=0;4>b;++b)for(this.sboxes[b]=[],c=0;256>c;++c)this.sboxes[b][c]=this.SBOXES[b][c];var f=[0,0];for(b=0;bb;++b)for(c=0;256>c;c+=2)this._encrypt_block(f),this.sboxes[b][c+0]=f[0],this.sboxes[b][c+1]=f[1]};var e=a("../../util.js");b.exports=d,b.exports.keySize=d.prototype.keySize=16,b.exports.blockSize=d.prototype.blockSize=16},{"../../util.js":74}],21:[function(a,b){function c(){function a(a,b,c){var d=b+a,e=d<>>32-c;return(f[0][e>>>24]^f[1][e>>>16&255])-f[2][e>>>8&255]+f[3][255&e]}function b(a,b,c){var d=b^a,e=d<>>32-c;return f[0][e>>>24]-f[1][e>>>16&255]+f[2][e>>>8&255]^f[3][255&e]}function c(a,b,c){var d=b-a,e=d<>>32-c;return(f[0][e>>>24]+f[1][e>>>16&255]^f[2][e>>>8&255])-f[3][255&e]}this.BlockSize=8,this.KeySize=16,this.setKey=function(a){if(this.masking=new Array(16),this.rotate=new Array(16),this.reset(),a.length!=this.KeySize)throw new Error("CAST-128: keys must be 16 bytes");return this.keySchedule(a),!0},this.reset=function(){for(var a=0;16>a;a++)this.masking[a]=0,this.rotate[a]=0},this.getBlockSize=function(){return BlockSize},this.encrypt=function(d){for(var e=new Array(d.length),f=0;f>>24&255,e[f+1]=i>>>16&255,e[f+2]=i>>>8&255,e[f+3]=255&i,e[f+4]=h>>>24&255,e[f+5]=h>>>16&255,e[f+6]=h>>>8&255,e[f+7]=255&h}return e},this.decrypt=function(d){for(var e=new Array(d.length),f=0;f>>24&255,e[f+1]=i>>>16&255,e[f+2]=i>>>8&255,e[f+3]=255&i,e[f+4]=h>>>24&255,e[f+5]=h>>16&255,e[f+6]=h>>8&255,e[f+7]=255&h}return e};var d=new Array(4);d[0]=new Array(4),d[0][0]=new Array(4,0,13,15,12,14,8),d[0][1]=new Array(5,2,16,18,17,19,10),d[0][2]=new Array(6,3,23,22,21,20,9),d[0][3]=new Array(7,1,26,25,27,24,11),d[1]=new Array(4),d[1][0]=new Array(0,6,21,23,20,22,16),d[1][1]=new Array(1,4,0,2,1,3,18),d[1][2]=new Array(2,5,7,6,5,4,17),d[1][3]=new Array(3,7,10,9,11,8,19),d[2]=new Array(4),d[2][0]=new Array(4,0,13,15,12,14,8),d[2][1]=new Array(5,2,16,18,17,19,10),d[2][2]=new Array(6,3,23,22,21,20,9),d[2][3]=new Array(7,1,26,25,27,24,11),d[3]=new Array(4),d[3][0]=new Array(0,6,21,23,20,22,16),d[3][1]=new Array(1,4,0,2,1,3,18),d[3][2]=new Array(2,5,7,6,5,4,17),d[3][3]=new Array(3,7,10,9,11,8,19);var e=new Array(4);e[0]=new Array(4),e[0][0]=new Array(24,25,23,22,18),e[0][1]=new Array(26,27,21,20,22),e[0][2]=new Array(28,29,19,18,25),e[0][3]=new Array(30,31,17,16,28),e[1]=new Array(4),e[1][0]=new Array(3,2,12,13,8),e[1][1]=new Array(1,0,14,15,13),e[1][2]=new Array(7,6,8,9,3),e[1][3]=new Array(5,4,10,11,7),e[2]=new Array(4),e[2][0]=new Array(19,18,28,29,25),e[2][1]=new Array(17,16,30,31,28),e[2][2]=new Array(23,22,24,25,18),e[2][3]=new Array(21,20,26,27,22),e[3]=new Array(4),e[3][0]=new Array(8,9,7,6,3),e[3][1]=new Array(10,11,5,4,7),e[3][2]=new Array(12,13,3,2,8),e[3][3]=new Array(14,15,1,0,13),this.keySchedule=function(a){var b,c,g=new Array(8),h=new Array(32);for(b=0;4>b;b++)c=4*b,g[b]=a[c]<<24|a[c+1]<<16|a[c+2]<<8|a[c+3];for(var i,j=[6,7,4,5],k=0,l=0;2>l;l++)for(var m=0;4>m;m++){for(c=0;4>c;c++){var n=d[m][c];i=g[n[1]],i^=f[4][g[n[2]>>>2]>>>24-8*(3&n[2])&255],i^=f[5][g[n[3]>>>2]>>>24-8*(3&n[3])&255],i^=f[6][g[n[4]>>>2]>>>24-8*(3&n[4])&255],i^=f[7][g[n[5]>>>2]>>>24-8*(3&n[5])&255],i^=f[j[c]][g[n[6]>>>2]>>>24-8*(3&n[6])&255],g[n[0]]=i}for(c=0;4>c;c++){var o=e[m][c];i=f[4][g[o[0]>>>2]>>>24-8*(3&o[0])&255],i^=f[5][g[o[1]>>>2]>>>24-8*(3&o[1])&255],i^=f[6][g[o[2]>>>2]>>>24-8*(3&o[2])&255],i^=f[7][g[o[3]>>>2]>>>24-8*(3&o[3])&255],i^=f[4+c][g[o[4]>>>2]>>>24-8*(3&o[4])&255],h[k]=i,k++}}for(b=0;16>b;b++)this.masking[b]=h[b],this.rotate[b]=31&h[16+b]};var f=new Array(8);f[0]=new Array(821772500,2678128395,1810681135,1059425402,505495343,2617265619,1610868032,3483355465,3218386727,2294005173,3791863952,2563806837,1852023008,365126098,3269944861,584384398,677919599,3229601881,4280515016,2002735330,1136869587,3744433750,2289869850,2731719981,2714362070,879511577,1639411079,575934255,717107937,2857637483,576097850,2731753936,1725645e3,2810460463,5111599,767152862,2543075244,1251459544,1383482551,3052681127,3089939183,3612463449,1878520045,1510570527,2189125840,2431448366,582008916,3163445557,1265446783,1354458274,3529918736,3202711853,3073581712,3912963487,3029263377,1275016285,4249207360,2905708351,3304509486,1442611557,3585198765,2712415662,2731849581,3248163920,2283946226,208555832,2766454743,1331405426,1447828783,3315356441,3108627284,2957404670,2981538698,3339933917,1669711173,286233437,1465092821,1782121619,3862771680,710211251,980974943,1651941557,430374111,2051154026,704238805,4128970897,3144820574,2857402727,948965521,3333752299,2227686284,718756367,2269778983,2731643755,718440111,2857816721,3616097120,1113355533,2478022182,410092745,1811985197,1944238868,2696854588,1415722873,1682284203,1060277122,1998114690,1503841958,82706478,2315155686,1068173648,845149890,2167947013,1768146376,1993038550,3566826697,3390574031,940016341,3355073782,2328040721,904371731,1205506512,4094660742,2816623006,825647681,85914773,2857843460,1249926541,1417871568,3287612,3211054559,3126306446,1975924523,1353700161,2814456437,2438597621,1800716203,722146342,2873936343,1151126914,4160483941,2877670899,458611604,2866078500,3483680063,770352098,2652916994,3367839148,3940505011,3585973912,3809620402,718646636,2504206814,2914927912,3631288169,2857486607,2860018678,575749918,2857478043,718488780,2069512688,3548183469,453416197,1106044049,3032691430,52586708,3378514636,3459808877,3211506028,1785789304,218356169,3571399134,3759170522,1194783844,1523787992,3007827094,1975193539,2555452411,1341901877,3045838698,3776907964,3217423946,2802510864,2889438986,1057244207,1636348243,3761863214,1462225785,2632663439,481089165,718503062,24497053,3332243209,3344655856,3655024856,3960371065,1195698900,2971415156,3710176158,2115785917,4027663609,3525578417,2524296189,2745972565,3564906415,1372086093,1452307862,2780501478,1476592880,3389271281,18495466,2378148571,901398090,891748256,3279637769,3157290713,2560960102,1447622437,4284372637,216884176,2086908623,1879786977,3588903153,2242455666,2938092967,3559082096,2810645491,758861177,1121993112,215018983,642190776,4169236812,1196255959,2081185372,3508738393,941322904,4124243163,2877523539,1848581667,2205260958,3180453958,2589345134,3694731276,550028657,2519456284,3789985535,2973870856,2093648313,443148163,46942275,2734146937,1117713533,1115362972,1523183689,3717140224,1551984063),f[1]=new Array(522195092,4010518363,1776537470,960447360,4267822970,4005896314,1435016340,1929119313,2913464185,1310552629,3579470798,3724818106,2579771631,1594623892,417127293,2715217907,2696228731,1508390405,3994398868,3925858569,3695444102,4019471449,3129199795,3770928635,3520741761,990456497,4187484609,2783367035,21106139,3840405339,631373633,3783325702,532942976,396095098,3548038825,4267192484,2564721535,2011709262,2039648873,620404603,3776170075,2898526339,3612357925,4159332703,1645490516,223693667,1567101217,3362177881,1029951347,3470931136,3570957959,1550265121,119497089,972513919,907948164,3840628539,1613718692,3594177948,465323573,2659255085,654439692,2575596212,2699288441,3127702412,277098644,624404830,4100943870,2717858591,546110314,2403699828,3655377447,1321679412,4236791657,1045293279,4010672264,895050893,2319792268,494945126,1914543101,2777056443,3894764339,2219737618,311263384,4275257268,3458730721,669096869,3584475730,3835122877,3319158237,3949359204,2005142349,2713102337,2228954793,3769984788,569394103,3855636576,1425027204,108000370,2736431443,3671869269,3043122623,1750473702,2211081108,762237499,3972989403,2798899386,3061857628,2943854345,867476300,964413654,1591880597,1594774276,2179821409,552026980,3026064248,3726140315,2283577634,3110545105,2152310760,582474363,1582640421,1383256631,2043843868,3322775884,1217180674,463797851,2763038571,480777679,2718707717,2289164131,3118346187,214354409,200212307,3810608407,3025414197,2674075964,3997296425,1847405948,1342460550,510035443,4080271814,815934613,833030224,1620250387,1945732119,2703661145,3966000196,1388869545,3456054182,2687178561,2092620194,562037615,1356438536,3409922145,3261847397,1688467115,2150901366,631725691,3840332284,549916902,3455104640,394546491,837744717,2114462948,751520235,2221554606,2415360136,3999097078,2063029875,803036379,2702586305,821456707,3019566164,360699898,4018502092,3511869016,3677355358,2402471449,812317050,49299192,2570164949,3259169295,2816732080,3331213574,3101303564,2156015656,3705598920,3546263921,143268808,3200304480,1638124008,3165189453,3341807610,578956953,2193977524,3638120073,2333881532,807278310,658237817,2969561766,1641658566,11683945,3086995007,148645947,1138423386,4158756760,1981396783,2401016740,3699783584,380097457,2680394679,2803068651,3334260286,441530178,4016580796,1375954390,761952171,891809099,2183123478,157052462,3683840763,1592404427,341349109,2438483839,1417898363,644327628,2233032776,2353769706,2201510100,220455161,1815641738,182899273,2995019788,3627381533,3702638151,2890684138,1052606899,588164016,1681439879,4038439418,2405343923,4229449282,167996282,1336969661,1688053129,2739224926,1543734051,1046297529,1138201970,2121126012,115334942,1819067631,1902159161,1941945968,2206692869,1159982321),f[2]=new Array(2381300288,637164959,3952098751,3893414151,1197506559,916448331,2350892612,2932787856,3199334847,4009478890,3905886544,1373570990,2450425862,4037870920,3778841987,2456817877,286293407,124026297,3001279700,1028597854,3115296800,4208886496,2691114635,2188540206,1430237888,1218109995,3572471700,308166588,570424558,2187009021,2455094765,307733056,1310360322,3135275007,1384269543,2388071438,863238079,2359263624,2801553128,3380786597,2831162807,1470087780,1728663345,4072488799,1090516929,532123132,2389430977,1132193179,2578464191,3051079243,1670234342,1434557849,2711078940,1241591150,3314043432,3435360113,3091448339,1812415473,2198440252,267246943,796911696,3619716990,38830015,1526438404,2806502096,374413614,2943401790,1489179520,1603809326,1920779204,168801282,260042626,2358705581,1563175598,2397674057,1356499128,2217211040,514611088,2037363785,2186468373,4022173083,2792511869,2913485016,1173701892,4200428547,3896427269,1334932762,2455136706,602925377,2835607854,1613172210,41346230,2499634548,2457437618,2188827595,41386358,4172255629,1313404830,2405527007,3801973774,2217704835,873260488,2528884354,2478092616,4012915883,2555359016,2006953883,2463913485,575479328,2218240648,2099895446,660001756,2341502190,3038761536,3888151779,3848713377,3286851934,1022894237,1620365795,3449594689,1551255054,15374395,3570825345,4249311020,4151111129,3181912732,310226346,1133119310,530038928,136043402,2476768958,3107506709,2544909567,1036173560,2367337196,1681395281,1758231547,3641649032,306774401,1575354324,3716085866,1990386196,3114533736,2455606671,1262092282,3124342505,2768229131,4210529083,1833535011,423410938,660763973,2187129978,1639812e3,3508421329,3467445492,310289298,272797111,2188552562,2456863912,310240523,677093832,1013118031,901835429,3892695601,1116285435,3036471170,1337354835,243122523,520626091,277223598,4244441197,4194248841,1766575121,594173102,316590669,742362309,3536858622,4176435350,3838792410,2501204839,1229605004,3115755532,1552908988,2312334149,979407927,3959474601,1148277331,176638793,3614686272,2083809052,40992502,1340822838,2731552767,3535757508,3560899520,1354035053,122129617,7215240,2732932949,3118912700,2718203926,2539075635,3609230695,3725561661,1928887091,2882293555,1988674909,2063640240,2491088897,1459647954,4189817080,2302804382,1113892351,2237858528,1927010603,4002880361,1856122846,1594404395,2944033133,3855189863,3474975698,1643104450,4054590833,3431086530,1730235576,2984608721,3084664418,2131803598,4178205752,267404349,1617849798,1616132681,1462223176,736725533,2327058232,551665188,2945899023,1749386277,2575514597,1611482493,674206544,2201269090,3642560800,728599968,1680547377,2620414464,1388111496,453204106,4156223445,1094905244,2754698257,2201108165,3757000246,2704524545,3922940700,3996465027),f[3]=new Array(2645754912,532081118,2814278639,3530793624,1246723035,1689095255,2236679235,4194438865,2116582143,3859789411,157234593,2045505824,4245003587,1687664561,4083425123,605965023,672431967,1336064205,3376611392,214114848,4258466608,3232053071,489488601,605322005,3998028058,264917351,1912574028,756637694,436560991,202637054,135989450,85393697,2152923392,3896401662,2895836408,2145855233,3535335007,115294817,3147733898,1922296357,3464822751,4117858305,1037454084,2725193275,2127856640,1417604070,1148013728,1827919605,642362335,2929772533,909348033,1346338451,3547799649,297154785,1917849091,4161712827,2883604526,3968694238,1469521537,3780077382,3375584256,1763717519,136166297,4290970789,1295325189,2134727907,2798151366,1566297257,3672928234,2677174161,2672173615,965822077,2780786062,289653839,1133871874,3491843819,35685304,1068898316,418943774,672553190,642281022,2346158704,1954014401,3037126780,4079815205,2030668546,3840588673,672283427,1776201016,359975446,3750173538,555499703,2769985273,1324923,69110472,152125443,3176785106,3822147285,1340634837,798073664,1434183902,15393959,216384236,1303690150,3881221631,3711134124,3960975413,106373927,2578434224,1455997841,1801814300,1578393881,1854262133,3188178946,3258078583,2302670060,1539295533,3505142565,3078625975,2372746020,549938159,3278284284,2620926080,181285381,2865321098,3970029511,68876850,488006234,1728155692,2608167508,836007927,2435231793,919367643,3339422534,3655756360,1457871481,40520939,1380155135,797931188,234455205,2255801827,3990488299,397000196,739833055,3077865373,2871719860,4022553888,772369276,390177364,3853951029,557662966,740064294,1640166671,1699928825,3535942136,622006121,3625353122,68743880,1742502,219489963,1664179233,1577743084,1236991741,410585305,2366487942,823226535,1050371084,3426619607,3586839478,212779912,4147118561,1819446015,1911218849,530248558,3486241071,3252585495,2886188651,3410272728,2342195030,20547779,2982490058,3032363469,3631753222,312714466,1870521650,1493008054,3491686656,615382978,4103671749,2534517445,1932181,2196105170,278426614,6369430,3274544417,2913018367,697336853,2143000447,2946413531,701099306,1558357093,2805003052,3500818408,2321334417,3567135975,216290473,3591032198,23009561,1996984579,3735042806,2024298078,3739440863,569400510,2339758983,3016033873,3097871343,3639523026,3844324983,3256173865,795471839,2951117563,4101031090,4091603803,3603732598,971261452,534414648,428311343,3389027175,2844869880,694888862,1227866773,2456207019,3043454569,2614353370,3749578031,3676663836,459166190,4132644070,1794958188,51825668,2252611902,3084671440,2036672799,3436641603,1099053433,2469121526,3059204941,1323291266,2061838604,1018778475,2233344254,2553501054,334295216,3556750194,1065731521,183467730),f[4]=new Array(2127105028,745436345,2601412319,2788391185,3093987327,500390133,1155374404,389092991,150729210,3891597772,3523549952,1935325696,716645080,946045387,2901812282,1774124410,3869435775,4039581901,3293136918,3438657920,948246080,363898952,3867875531,1286266623,1598556673,68334250,630723836,1104211938,1312863373,613332731,2377784574,1101634306,441780740,3129959883,1917973735,2510624549,3238456535,2544211978,3308894634,1299840618,4076074851,1756332096,3977027158,297047435,3790297736,2265573040,3621810518,1311375015,1667687725,47300608,3299642885,2474112369,201668394,1468347890,576830978,3594690761,3742605952,1958042578,1747032512,3558991340,1408974056,3366841779,682131401,1033214337,1545599232,4265137049,206503691,103024618,2855227313,1337551222,2428998917,2963842932,4015366655,3852247746,2796956967,3865723491,3747938335,247794022,3755824572,702416469,2434691994,397379957,851939612,2314769512,218229120,1380406772,62274761,214451378,3170103466,2276210409,3845813286,28563499,446592073,1693330814,3453727194,29968656,3093872512,220656637,2470637031,77972100,1667708854,1358280214,4064765667,2395616961,325977563,4277240721,4220025399,3605526484,3355147721,811859167,3069544926,3962126810,652502677,3075892249,4132761541,3498924215,1217549313,3250244479,3858715919,3053989961,1538642152,2279026266,2875879137,574252750,3324769229,2651358713,1758150215,141295887,2719868960,3515574750,4093007735,4194485238,1082055363,3417560400,395511885,2966884026,179534037,3646028556,3738688086,1092926436,2496269142,257381841,3772900718,1636087230,1477059743,2499234752,3811018894,2675660129,3285975680,90732309,1684827095,1150307763,1723134115,3237045386,1769919919,1240018934,815675215,750138730,2239792499,1234303040,1995484674,138143821,675421338,1145607174,1936608440,3238603024,2345230278,2105974004,323969391,779555213,3004902369,2861610098,1017501463,2098600890,2628620304,2940611490,2682542546,1171473753,3656571411,3687208071,4091869518,393037935,159126506,1662887367,1147106178,391545844,3452332695,1891500680,3016609650,1851642611,546529401,1167818917,3194020571,2848076033,3953471836,575554290,475796850,4134673196,450035699,2351251534,844027695,1080539133,86184846,1554234488,3692025454,1972511363,2018339607,1491841390,1141460869,1061690759,4244549243,2008416118,2351104703,2868147542,1598468138,722020353,1027143159,212344630,1387219594,1725294528,3745187956,2500153616,458938280,4129215917,1828119673,544571780,3503225445,2297937496,1241802790,267843827,2694610800,1397140384,1558801448,3782667683,1806446719,929573330,2234912681,400817706,616011623,4121520928,3603768725,1761550015,1968522284,4053731006,4192232858,4005120285,872482584,3140537016,3894607381,2287405443,1963876937,3663887957,1584857e3,2975024454,1833426440,4025083860),f[5]=new Array(4143615901,749497569,1285769319,3795025788,2514159847,23610292,3974978748,844452780,3214870880,3751928557,2213566365,1676510905,448177848,3730751033,4086298418,2307502392,871450977,3222878141,4110862042,3831651966,2735270553,1310974780,2043402188,1218528103,2736035353,4274605013,2702448458,3936360550,2693061421,162023535,2827510090,687910808,23484817,3784910947,3371371616,779677500,3503626546,3473927188,4157212626,3500679282,4248902014,2466621104,3899384794,1958663117,925738300,1283408968,3669349440,1840910019,137959847,2679828185,1239142320,1315376211,1547541505,1690155329,739140458,3128809933,3933172616,3876308834,905091803,1548541325,4040461708,3095483362,144808038,451078856,676114313,2861728291,2469707347,993665471,373509091,2599041286,4025009006,4170239449,2149739950,3275793571,3749616649,2794760199,1534877388,572371878,2590613551,1753320020,3467782511,1405125690,4270405205,633333386,3026356924,3475123903,632057672,2846462855,1404951397,3882875879,3915906424,195638627,2385783745,3902872553,1233155085,3355999740,2380578713,2702246304,2144565621,3663341248,3894384975,2502479241,4248018925,3094885567,1594115437,572884632,3385116731,767645374,1331858858,1475698373,3793881790,3532746431,1321687957,619889600,1121017241,3440213920,2070816767,2833025776,1933951238,4095615791,890643334,3874130214,859025556,360630002,925594799,1764062180,3920222280,4078305929,979562269,2810700344,4087740022,1949714515,546639971,1165388173,3069891591,1495988560,922170659,1291546247,2107952832,1813327274,3406010024,3306028637,4241950635,153207855,2313154747,1608695416,1150242611,1967526857,721801357,1220138373,3691287617,3356069787,2112743302,3281662835,1111556101,1778980689,250857638,2298507990,673216130,2846488510,3207751581,3562756981,3008625920,3417367384,2198807050,529510932,3547516680,3426503187,2364944742,102533054,2294910856,1617093527,1204784762,3066581635,1019391227,1069574518,1317995090,1691889997,3661132003,510022745,3238594800,1362108837,1817929911,2184153760,805817662,1953603311,3699844737,120799444,2118332377,207536705,2282301548,4120041617,145305846,2508124933,3086745533,3261524335,1877257368,2977164480,3160454186,2503252186,4221677074,759945014,254147243,2767453419,3801518371,629083197,2471014217,907280572,3900796746,940896768,2751021123,2625262786,3161476951,3661752313,3260732218,1425318020,2977912069,1496677566,3988592072,2140652971,3126511541,3069632175,977771578,1392695845,1698528874,1411812681,1369733098,1343739227,3620887944,1142123638,67414216,3102056737,3088749194,1626167401,2546293654,3941374235,697522451,33404913,143560186,2595682037,994885535,1247667115,3859094837,2699155541,3547024625,4114935275,2968073508,3199963069,2732024527,1237921620,951448369,1898488916,1211705605,2790989240,2233243581,3598044975),f[6]=new Array(2246066201,858518887,1714274303,3485882003,713916271,2879113490,3730835617,539548191,36158695,1298409750,419087104,1358007170,749914897,2989680476,1261868530,2995193822,2690628854,3443622377,3780124940,3796824509,2976433025,4259637129,1551479e3,512490819,1296650241,951993153,2436689437,2460458047,144139966,3136204276,310820559,3068840729,643875328,1969602020,1680088954,2185813161,3283332454,672358534,198762408,896343282,276269502,3014846926,84060815,197145886,376173866,3943890818,3813173521,3545068822,1316698879,1598252827,2633424951,1233235075,859989710,2358460855,3503838400,3409603720,1203513385,1193654839,2792018475,2060853022,207403770,1144516871,3068631394,1121114134,177607304,3785736302,326409831,1929119770,2983279095,4183308101,3474579288,3200513878,3228482096,119610148,1170376745,3378393471,3163473169,951863017,3337026068,3135789130,2907618374,1183797387,2015970143,4045674555,2182986399,2952138740,3928772205,384012900,2454997643,10178499,2879818989,2596892536,111523738,2995089006,451689641,3196290696,235406569,1441906262,3890558523,3013735005,4158569349,1644036924,376726067,1006849064,3664579700,2041234796,1021632941,1374734338,2566452058,371631263,4007144233,490221539,206551450,3140638584,1053219195,1853335209,3412429660,3562156231,735133835,1623211703,3104214392,2738312436,4096837757,3366392578,3110964274,3956598718,3196820781,2038037254,3877786376,2339753847,300912036,3766732888,2372630639,1516443558,4200396704,1574567987,4069441456,4122592016,2699739776,146372218,2748961456,2043888151,35287437,2596680554,655490400,1132482787,110692520,1031794116,2188192751,1324057718,1217253157,919197030,686247489,3261139658,1028237775,3135486431,3059715558,2460921700,986174950,2661811465,4062904701,2752986992,3709736643,367056889,1353824391,731860949,1650113154,1778481506,784341916,357075625,3608602432,1074092588,2480052770,3811426202,92751289,877911070,3600361838,1231880047,480201094,3756190983,3094495953,434011822,87971354,363687820,1717726236,1901380172,3926403882,2481662265,400339184,1490350766,2661455099,1389319756,2558787174,784598401,1983468483,30828846,3550527752,2716276238,3841122214,1765724805,1955612312,1277890269,1333098070,1564029816,2704417615,1026694237,3287671188,1260819201,3349086767,1016692350,1582273796,1073413053,1995943182,694588404,1025494639,3323872702,3551898420,4146854327,453260480,1316140391,1435673405,3038941953,3486689407,1622062951,403978347,817677117,950059133,4246079218,3278066075,1486738320,1417279718,481875527,2549965225,3933690356,760697757,1452955855,3897451437,1177426808,1702951038,4085348628,2447005172,1084371187,3516436277,3068336338,1073369276,1027665953,3284188590,1230553676,1368340146,2226246512,267243139,2274220762,4070734279,2497715176,2423353163,2504755875),f[7]=new Array(3793104909,3151888380,2817252029,895778965,2005530807,3871412763,237245952,86829237,296341424,3851759377,3974600970,2475086196,709006108,1994621201,2972577594,937287164,3734691505,168608556,3189338153,2225080640,3139713551,3033610191,3025041904,77524477,185966941,1208824168,2344345178,1721625922,3354191921,1066374631,1927223579,1971335949,2483503697,1551748602,2881383779,2856329572,3003241482,48746954,1398218158,2050065058,313056748,4255789917,393167848,1912293076,940740642,3465845460,3091687853,2522601570,2197016661,1727764327,364383054,492521376,1291706479,3264136376,1474851438,1685747964,2575719748,1619776915,1814040067,970743798,1561002147,2925768690,2123093554,1880132620,3151188041,697884420,2550985770,2607674513,2659114323,110200136,1489731079,997519150,1378877361,3527870668,478029773,2766872923,1022481122,431258168,1112503832,897933369,2635587303,669726182,3383752315,918222264,163866573,3246985393,3776823163,114105080,1903216136,761148244,3571337562,1690750982,3166750252,1037045171,1888456500,2010454850,642736655,616092351,365016990,1185228132,4174898510,1043824992,2023083429,2241598885,3863320456,3279669087,3674716684,108438443,2132974366,830746235,606445527,4173263986,2204105912,1844756978,2532684181,4245352700,2969441100,3796921661,1335562986,4061524517,2720232303,2679424040,634407289,885462008,3294724487,3933892248,2094100220,339117932,4048830727,3202280980,1458155303,2689246273,1022871705,2464987878,3714515309,353796843,2822958815,4256850100,4052777845,551748367,618185374,3778635579,4020649912,1904685140,3069366075,2670879810,3407193292,2954511620,4058283405,2219449317,3135758300,1120655984,3447565834,1474845562,3577699062,550456716,3466908712,2043752612,881257467,869518812,2005220179,938474677,3305539448,3850417126,1315485940,3318264702,226533026,965733244,321539988,1136104718,804158748,573969341,3708209826,937399083,3290727049,2901666755,1461057207,4013193437,4066861423,3242773476,2421326174,1581322155,3028952165,786071460,3900391652,3918438532,1485433313,4023619836,3708277595,3678951060,953673138,1467089153,1930354364,1533292819,2492563023,1346121658,1685000834,1965281866,3765933717,4190206607,2052792609,3515332758,690371149,3125873887,2180283551,2903598061,3933952357,436236910,289419410,14314871,1242357089,2904507907,1616633776,2666382180,585885352,3471299210,2699507360,1432659641,277164553,3354103607,770115018,2303809295,3741942315,3177781868,2853364978,2269453327,3774259834,987383833,1290892879,225909803,1741533526,890078084,1496906255,1111072499,916028167,243534141,1252605537,2204162171,531204876,290011180,3916834213,102027703,237315147,209093447,1486785922,220223953,2758195998,4175039106,82940208,3127791296,2569425252,518464269,1353887104,3941492737,2377294467,3935040926)}function d(a){this.cast5=new c,this.cast5.setKey(e.str2bin(a)),this.encrypt=function(a){return this.cast5.encrypt(a)}}var e=a("../../util.js");b.exports=d,b.exports.blockSize=d.prototype.blockSize=8,b.exports.keySize=d.prototype.keySize=16},{"../../util.js":74}],22:[function(a,b){function c(a,b,c,d,g,h){var i,j,k,l,m,n,o,p,q,r,s,t,u,v,w=new Array(16843776,0,65536,16843780,16842756,66564,4,65536,1024,16843776,16843780,1024,16778244,16842756,16777216,4,1028,16778240,16778240,66560,66560,16842752,16842752,16778244,65540,16777220,16777220,65540,0,1028,66564,16777216,65536,16843780,4,16842752,16843776,16777216,16777216,1024,16842756,65536,66560,16777220,1024,4,16778244,66564,16843780,65540,16842752,16778244,16777220,1028,66564,16843776,1028,16778240,16778240,0,65540,66560,0,16842756),x=new Array(-2146402272,-2147450880,32768,1081376,1048576,32,-2146435040,-2147450848,-2147483616,-2146402272,-2146402304,-2147483648,-2147450880,1048576,32,-2146435040,1081344,1048608,-2147450848,0,-2147483648,32768,1081376,-2146435072,1048608,-2147483616,0,1081344,32800,-2146402304,-2146435072,32800,0,1081376,-2146435040,1048576,-2147450848,-2146435072,-2146402304,32768,-2146435072,-2147450880,32,-2146402272,1081376,32,32768,-2147483648,32800,-2146402304,1048576,-2147483616,1048608,-2147450848,-2147483616,1048608,1081344,0,-2147450880,32800,-2147483648,-2146435040,-2146402272,1081344),y=new Array(520,134349312,0,134348808,134218240,0,131592,134218240,131080,134217736,134217736,131072,134349320,131080,134348800,520,134217728,8,134349312,512,131584,134348800,134348808,131592,134218248,131584,131072,134218248,8,134349320,512,134217728,134349312,134217728,131080,520,131072,134349312,134218240,0,512,131080,134349320,134218240,134217736,512,0,134348808,134218248,131072,134217728,134349320,8,131592,131584,134217736,134348800,134218248,520,134348800,131592,8,134348808,131584),z=new Array(8396801,8321,8321,128,8396928,8388737,8388609,8193,0,8396800,8396800,8396929,129,0,8388736,8388609,1,8192,8388608,8396801,128,8388608,8193,8320,8388737,1,8320,8388736,8192,8396928,8396929,129,8388736,8388609,8396800,8396929,129,0,0,8396800,8320,8388736,8388737,1,8396801,8321,8321,128,8396929,129,1,8192,8388609,8193,8396928,8388737,8193,8320,8388608,8396801,128,8388608,8192,8396928),A=new Array(256,34078976,34078720,1107296512,524288,256,1073741824,34078720,1074266368,524288,33554688,1074266368,1107296512,1107820544,524544,1073741824,33554432,1074266112,1074266112,0,1073742080,1107820800,1107820800,33554688,1107820544,1073742080,0,1107296256,34078976,33554432,1107296256,524544,524288,1107296512,256,33554432,1073741824,34078720,1107296512,1074266368,33554688,1073741824,1107820544,34078976,1074266368,256,33554432,1107820544,1107820800,524544,1107296256,1107820800,34078720,0,1074266112,1107296256,524544,33554688,1073742080,524288,0,1074266112,34078976,1073742080),B=new Array(536870928,541065216,16384,541081616,541065216,16,541081616,4194304,536887296,4210704,4194304,536870928,4194320,536887296,536870912,16400,0,4194320,536887312,16384,4210688,536887312,16,541065232,541065232,0,4210704,541081600,16400,4210688,541081600,536870912,536887296,16,541065232,4210688,541081616,4194304,16400,536870928,4194304,536887296,536870912,16400,536870928,541081616,4210688,541065216,4210704,541081600,0,541065232,16,16384,541065216,4210704,16384,4194320,536887312,0,541081600,536870912,4194320,536887312),C=new Array(2097152,69206018,67110914,0,2048,67110914,2099202,69208064,69208066,2097152,0,67108866,2,67108864,69206018,2050,67110912,2099202,2097154,67110912,67108866,69206016,69208064,2097154,69206016,2048,2050,69208066,2099200,2,67108864,2099200,67108864,2099200,2097152,67110914,67110914,69206018,69206018,2,2097154,67108864,67110912,2097152,69208064,2050,2099202,69208064,2050,67108866,69208066,69206016,2099200,0,2,69208066,0,2099202,69206016,2048,67108866,67110912,2048,2097154),D=new Array(268439616,4096,262144,268701760,268435456,268439616,64,268435456,262208,268697600,268701760,266240,268701696,266304,4096,64,268697600,268435520,268439552,4160,266240,262208,268697664,268701696,4160,0,0,268697664,268435520,268439552,266304,262144,266304,262144,268701696,4096,64,268697664,4096,266304,268439552,64,268435520,268697600,268697664,268435456,262144,268439616,0,268701760,262208,268435520,268697600,268439552,268439616,0,268701760,266240,266240,4160,4160,262208,268435456,268701696),E=0,F=b.length,G=0,H=32==a.length?3:9; -for(p=3==H?c?new Array(0,32,2):new Array(30,-2,-2):c?new Array(0,32,2,62,30,-2,64,96,2):new Array(94,62,-2,32,64,2,30,-2,-2),c&&(b=e(b,h),F=b.length),result="",tempresult="",1==d&&(q=g.charCodeAt(E++)<<24|g.charCodeAt(E++)<<16|g.charCodeAt(E++)<<8|g.charCodeAt(E++),s=g.charCodeAt(E++)<<24|g.charCodeAt(E++)<<16|g.charCodeAt(E++)<<8|g.charCodeAt(E++),E=0);F>E;){for(n=b.charCodeAt(E++)<<24|b.charCodeAt(E++)<<16|b.charCodeAt(E++)<<8|b.charCodeAt(E++),o=b.charCodeAt(E++)<<24|b.charCodeAt(E++)<<16|b.charCodeAt(E++)<<8|b.charCodeAt(E++),1==d&&(c?(n^=q,o^=s):(r=q,t=s,q=n,s=o)),k=252645135&(n>>>4^o),o^=k,n^=k<<4,k=65535&(n>>>16^o),o^=k,n^=k<<16,k=858993459&(o>>>2^n),n^=k,o^=k<<2,k=16711935&(o>>>8^n),n^=k,o^=k<<8,k=1431655765&(n>>>1^o),o^=k,n^=k<<1,n=n<<1|n>>>31,o=o<<1|o>>>31,j=0;H>j;j+=3){for(u=p[j+1],v=p[j+2],i=p[j];i!=u;i+=v)l=o^a[i],m=(o>>>4|o<<28)^a[i+1],k=n,n=o,o=k^(x[l>>>24&63]|z[l>>>16&63]|B[l>>>8&63]|D[63&l]|w[m>>>24&63]|y[m>>>16&63]|A[m>>>8&63]|C[63&m]);k=n,n=o,o=k}n=n>>>1|n<<31,o=o>>>1|o<<31,k=1431655765&(n>>>1^o),o^=k,n^=k<<1,k=16711935&(o>>>8^n),n^=k,o^=k<<8,k=858993459&(o>>>2^n),n^=k,o^=k<<2,k=65535&(n>>>16^o),o^=k,n^=k<<16,k=252645135&(n>>>4^o),o^=k,n^=k<<4,1==d&&(c?(q=n,s=o):(n^=r,o^=t)),tempresult+=String.fromCharCode(n>>>24,n>>>16&255,n>>>8&255,255&n,o>>>24,o>>>16&255,o>>>8&255,255&o),G+=8,512==G&&(result+=tempresult,tempresult="",G=0)}return result+=tempresult,c||(result=f(result,h)),result}function d(a){pc2bytes0=new Array(0,4,536870912,536870916,65536,65540,536936448,536936452,512,516,536871424,536871428,66048,66052,536936960,536936964),pc2bytes1=new Array(0,1,1048576,1048577,67108864,67108865,68157440,68157441,256,257,1048832,1048833,67109120,67109121,68157696,68157697),pc2bytes2=new Array(0,8,2048,2056,16777216,16777224,16779264,16779272,0,8,2048,2056,16777216,16777224,16779264,16779272),pc2bytes3=new Array(0,2097152,134217728,136314880,8192,2105344,134225920,136323072,131072,2228224,134348800,136445952,139264,2236416,134356992,136454144),pc2bytes4=new Array(0,262144,16,262160,0,262144,16,262160,4096,266240,4112,266256,4096,266240,4112,266256),pc2bytes5=new Array(0,1024,32,1056,0,1024,32,1056,33554432,33555456,33554464,33555488,33554432,33555456,33554464,33555488),pc2bytes6=new Array(0,268435456,524288,268959744,2,268435458,524290,268959746,0,268435456,524288,268959744,2,268435458,524290,268959746),pc2bytes7=new Array(0,65536,2048,67584,536870912,536936448,536872960,536938496,131072,196608,133120,198656,537001984,537067520,537004032,537069568),pc2bytes8=new Array(0,262144,0,262144,2,262146,2,262146,33554432,33816576,33554432,33816576,33554434,33816578,33554434,33816578),pc2bytes9=new Array(0,268435456,8,268435464,0,268435456,8,268435464,1024,268436480,1032,268436488,1024,268436480,1032,268436488),pc2bytes10=new Array(0,32,0,32,1048576,1048608,1048576,1048608,8192,8224,8192,8224,1056768,1056800,1056768,1056800),pc2bytes11=new Array(0,16777216,512,16777728,2097152,18874368,2097664,18874880,67108864,83886080,67109376,83886592,69206016,85983232,69206528,85983744),pc2bytes12=new Array(0,4096,134217728,134221824,524288,528384,134742016,134746112,16,4112,134217744,134221840,524304,528400,134742032,134746128),pc2bytes13=new Array(0,4,256,260,0,4,256,260,1,5,257,261,1,5,257,261);for(var b,c,d,e=a.length>8?3:1,f=new Array(32*e),g=new Array(0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0),h=0,j=0,k=0;e>k;k++)for(left=a.charCodeAt(h++)<<24|a.charCodeAt(h++)<<16|a.charCodeAt(h++)<<8|a.charCodeAt(h++),right=a.charCodeAt(h++)<<24|a.charCodeAt(h++)<<16|a.charCodeAt(h++)<<8|a.charCodeAt(h++),d=252645135&(left>>>4^right),right^=d,left^=d<<4,d=65535&(right>>>-16^left),left^=d,right^=d<<-16,d=858993459&(left>>>2^right),right^=d,left^=d<<2,d=65535&(right>>>-16^left),left^=d,right^=d<<-16,d=1431655765&(left>>>1^right),right^=d,left^=d<<1,d=16711935&(right>>>8^left),left^=d,right^=d<<8,d=1431655765&(left>>>1^right),right^=d,left^=d<<1,d=left<<8|right>>>20&240,left=right<<24|right<<8&16711680|right>>>8&65280|right>>>24&240,right=d,i=0;i>>26,right=right<<2|right>>>26):(left=left<<1|left>>>27,right=right<<1|right>>>27),left&=-15,right&=-15,b=pc2bytes0[left>>>28]|pc2bytes1[left>>>24&15]|pc2bytes2[left>>>20&15]|pc2bytes3[left>>>16&15]|pc2bytes4[left>>>12&15]|pc2bytes5[left>>>8&15]|pc2bytes6[left>>>4&15],c=pc2bytes7[right>>>28]|pc2bytes8[right>>>24&15]|pc2bytes9[right>>>20&15]|pc2bytes10[right>>>16&15]|pc2bytes11[right>>>12&15]|pc2bytes12[right>>>8&15]|pc2bytes13[right>>>4&15],d=65535&(c>>>16^b),f[j++]=b^d,f[j++]=c^d<<16;return f}function e(a,b){var c=8-a.length%8;return 2==b&&8>c?a+=" ".substr(0,c):1==b?a+=String.fromCharCode(c,c,c,c,c,c,c,c).substr(0,c):!b&&8>c&&(a+="\x00\x00\x00\x00\x00\x00\x00\x00".substr(0,c)),a}function f(a,b){if(2==b)a=a.replace(/ *$/g,"");else if(1==b){var c=a.charCodeAt(a.length-1);a=a.substr(0,a.length-c)}else b||(a=a.replace(/\0*$/g,""));return a}function g(a){this.key=[];for(var b=0;3>b;b++)this.key.push(a.substr(8*b,8));this.encrypt=function(a){return j.str2bin(c(d(this.key[2]),c(d(this.key[1]),c(d(this.key[0]),j.bin2str(a),!0,0,null,null),!1,0,null,null),!0,0,null,null))}}function h(a){this.key=a,this.encrypt=function(a,b){var e=d(this.key);return j.str2bin(c(e,j.bin2str(a),!0,0,null,b))},this.decrypt=function(a,b){var e=d(this.key);return j.str2bin(c(e,j.bin2str(a),!1,0,null,b))}}var j=a("../../util.js");g.keySize=g.prototype.keySize=24,g.blockSize=g.prototype.blockSize=8,b.exports={des:g,originalDes:h}},{"../../util.js":74}],23:[function(a,b){var c=a("./des.js");b.exports={des:c.originalDes,tripledes:c.des,cast5:a("./cast5.js"),twofish:a("./twofish.js"),blowfish:a("./blowfish.js"),idea:function(){throw new Error("IDEA symmetric-key algorithm not implemented")}};var d=a("./aes.js");for(var e in d)b.exports["aes"+e]=d[e]},{"./aes.js":19,"./blowfish.js":20,"./cast5.js":21,"./des.js":22,"./twofish.js":24}],24:[function(a,b){function c(a,b){return(a<>>32-b)&j}function d(a,b){return a[b]|a[b+1]<<8|a[b+2]<<16|a[b+3]<<24}function e(a,b,c){a.splice(b,4,255&c,c>>>8&255,c>>>16&255,c>>>24&255)}function f(a,b){return a>>>8*b&255}function g(){function a(a){function b(a){return a^a>>2^[0,90,180,238][3&a]}function e(a){return a^a>>1^a>>2^[0,238,180,90][3&a]}function g(a,b){var c,d,e;for(c=0;8>c;c++)d=b>>>24,b=b<<8&j|a>>>24,a=a<<8&j,e=d<<1,128&d&&(e^=333),b^=d^e<<16,e^=d>>>1,1&d&&(e^=166),b^=e<<24|e<<8;return b}function h(a,b){var c,d,e,f;return c=b>>4,d=15&b,e=A[a][c^d],f=B[a][E[d]^F[c]],D[a][E[f]^F[e]]<<4|C[a][e^f]}function i(a,b){var c=f(a,0),d=f(a,1),e=f(a,2),g=f(a,3);switch(q){case 4:c=G[1][c]^f(b[3],0),d=G[0][d]^f(b[3],1),e=G[0][e]^f(b[3],2),g=G[1][g]^f(b[3],3);case 3:c=G[1][c]^f(b[2],0),d=G[1][d]^f(b[2],1),e=G[0][e]^f(b[2],2),g=G[0][g]^f(b[2],3);case 2:c=G[0][G[0][c]^f(b[1],0)]^f(b[0],0),d=G[0][G[1][d]^f(b[1],1)]^f(b[0],1),e=G[1][G[0][e]^f(b[1],2)]^f(b[0],2),g=G[1][G[1][g]^f(b[1],3)]^f(b[0],3)}return H[0][c]^H[1][d]^H[2][e]^H[3][g]}o=a;var k,l,m,n,p,q,r,u,v,w=[],x=[],y=[],z=[],A=[[8,1,7,13,6,15,3,2,0,11,5,9,14,12,10,4],[2,8,11,13,15,7,6,14,3,1,9,4,0,10,12,5]],B=[[14,12,11,8,1,2,3,5,15,4,10,6,7,0,9,13],[1,14,2,11,4,12,3,7,6,13,10,5,15,9,0,8]],C=[[11,10,5,14,6,13,9,0,12,8,15,3,2,4,7,1],[4,12,7,5,1,6,9,10,0,14,13,8,2,11,3,15]],D=[[13,7,15,4,1,2,6,14,9,11,3,0,8,5,12,10],[11,9,5,1,12,3,13,14,6,4,7,15,2,0,8,10]],E=[0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15],F=[0,9,2,11,4,13,6,15,8,1,10,3,12,5,14,7],G=[[],[]],H=[[],[],[],[]];for(o=o.slice(0,32),k=o.length;16!=k&&24!=k&&32!=k;)o[k++]=0;for(k=0;k>2]=d(o,k);for(k=0;256>k;k++)G[0][k]=h(0,k),G[1][k]=h(1,k);for(k=0;256>k;k++)r=G[1][k],u=b(r),v=e(r),H[0][k]=r+(u<<8)+(v<<16)+(v<<24),H[2][k]=u+(v<<8)+(r<<16)+(v<<24),r=G[0][k],u=b(r),v=e(r),H[1][k]=v+(v<<8)+(u<<16)+(r<<24),H[3][k]=u+(r<<8)+(v<<16)+(u<<24);for(q=y.length/2,k=0;q>k;k++)l=y[k+k],w[k]=l,m=y[k+k+1],x[k]=m,z[q-k-1]=g(l,m);for(k=0;40>k;k+=2)l=16843009*k,m=l+16843009,l=i(l,w),m=c(i(m,x),8),s[k]=l+m&j,s[k+1]=c(l+2*m,9);for(k=0;256>k;k++)switch(l=m=n=p=k,q){case 4:l=G[1][l]^f(z[3],0),m=G[0][m]^f(z[3],1),n=G[0][n]^f(z[3],2),p=G[1][p]^f(z[3],3);case 3:l=G[1][l]^f(z[2],0),m=G[1][m]^f(z[2],1),n=G[0][n]^f(z[2],2),p=G[0][p]^f(z[2],3);case 2:t[0][k]=H[0][G[0][G[0][l]^f(z[1],0)]^f(z[0],0)],t[1][k]=H[1][G[0][G[1][m]^f(z[1],1)]^f(z[0],1)],t[2][k]=H[2][G[1][G[0][n]^f(z[1],2)]^f(z[0],2)],t[3][k]=H[3][G[1][G[1][p]^f(z[1],3)]^f(z[0],3)]}}function b(a){return t[0][f(a,0)]^t[1][f(a,1)]^t[2][f(a,2)]^t[3][f(a,3)]}function g(a){return t[0][f(a,3)]^t[1][f(a,0)]^t[2][f(a,1)]^t[3][f(a,2)]}function h(a,d){var e=b(d[0]),f=g(d[1]);d[2]=c(d[2]^e+f+s[4*a+8]&j,31),d[3]=c(d[3],1)^e+2*f+s[4*a+9]&j,e=b(d[2]),f=g(d[3]),d[0]=c(d[0]^e+f+s[4*a+10]&j,31),d[1]=c(d[1],1)^e+2*f+s[4*a+11]&j}function i(a,d){var e=b(d[0]),f=g(d[1]);d[2]=c(d[2],1)^e+f+s[4*a+10]&j,d[3]=c(d[3]^e+2*f+s[4*a+11]&j,31),e=b(d[2]),f=g(d[3]),d[0]=c(d[0],1)^e+f+s[4*a+8]&j,d[1]=c(d[1]^e+2*f+s[4*a+9]&j,31)}function k(){s=[],t=[[],[],[],[]]}function l(a,b){p=a,q=b;for(var c=[d(p,q)^s[0],d(p,q+4)^s[1],d(p,q+8)^s[2],d(p,q+12)^s[3]],f=0;8>f;f++)h(f,c);return e(p,q,c[2]^s[4]),e(p,q+4,c[3]^s[5]),e(p,q+8,c[0]^s[6]),e(p,q+12,c[1]^s[7]),q+=16,p}function m(a,b){p=a,q=b;for(var c=[d(p,q)^s[4],d(p,q+4)^s[5],d(p,q+8)^s[6],d(p,q+12)^s[7]],f=7;f>=0;f--)i(f,c);e(p,q,c[2]^s[0]),e(p,q+4,c[3]^s[1]),e(p,q+8,c[0]^s[2]),e(p,q+12,c[1]^s[3]),q+=16}function n(){return p}var o=null,p=null,q=-1,r=null;r="twofish";var s=[],t=[[],[],[],[]];return{name:"twofish",blocksize:16,open:a,close:k,encrypt:l,decrypt:m,finalize:n}}function h(a){this.tf=g(),this.tf.open(k.str2bin(a),0),this.encrypt=function(a){return this.tf.encrypt(i(a),0)}}function i(a){for(var b=[],c=0;c=64;){for(k=0;16>k;++k)b[k]=c.getInt32();for(;64>k;++k)d=b[k-2],d=(d>>>17|d<<15)^(d>>>19|d<<13)^d>>>10,e=b[k-15],e=(e>>>7|e<<25)^(e>>>18|e<<14)^e>>>3,b[k]=d+b[k-7]+e+b[k-16]&4294967295;for(l=a.h0,m=a.h1,n=a.h2,o=a.h3,p=a.h4,q=a.h5,r=a.h6,s=a.h7,k=0;64>k;++k)h=(p>>>6|p<<26)^(p>>>11|p<<21)^(p>>>25|p<<7),i=r^p&(q^r),f=(l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10),j=l&m|n&(l^m),d=s+h+i+g[k]+b[k],e=f+j,s=r,r=q,q=p,p=o+d&4294967295,o=n,n=m,m=l,l=d+e&4294967295;a.h0=a.h0+l&4294967295,a.h1=a.h1+m&4294967295,a.h2=a.h2+n&4294967295,a.h3=a.h3+o&4294967295,a.h4=a.h4+p&4294967295,a.h5=a.h5+q&4294967295,a.h6=a.h6+r&4294967295,a.h7=a.h7+s&4294967295,t-=64}};c.create=function(){f||h();var a=null,b=d.createBuffer(),c=new Array(64),g={algorithm:"sha256",blockLength:64,digestLength:32,messageLength:0};return g.start=function(){return g.messageLength=0,b=d.createBuffer(),a={h0:1779033703,h1:3144134277,h2:1013904242,h3:2773480762,h4:1359893119,h5:2600822924,h6:528734635,h7:1541459225},g},g.start(),g.update=function(e,f){return"utf8"===f&&(e=d.encodeUtf8(e)),g.messageLength+=e.length,b.putBytes(e),i(a,c,b),(b.read>2048||0===b.length())&&b.compact(),g},g.digest=function(){var f=g.messageLength,h=d.createBuffer();h.putBytes(b.bytes()),h.putBytes(e.substr(0,64-(f+8)%64)),h.putInt32(f>>>29&255),h.putInt32(f<<3&4294967295);var j={h0:a.h0,h1:a.h1,h2:a.h2,h3:a.h3,h4:a.h4,h5:a.h5,h6:a.h6,h7:a.h7};i(j,c,h);var k=d.createBuffer();return k.putInt32(j.h0),k.putInt32(j.h1),k.putInt32(j.h2),k.putInt32(j.h3),k.putInt32(j.h4),k.putInt32(j.h5),k.putInt32(j.h6),k.putInt32(j.h7),k},g}},{"./forge_util.js":27}],27:[function(a,b){var c=b.exports={};c.isArray=Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)},c.isArrayBuffer=function(a){return"undefined"!=typeof ArrayBuffer&&a instanceof ArrayBuffer};var d=[];"undefined"!=typeof Int8Array&&d.push(Int8Array),"undefined"!=typeof Uint8Array&&d.push(Uint8Array),"undefined"!=typeof Uint8ClampedArray&&d.push(Uint8ClampedArray),"undefined"!=typeof Int16Array&&d.push(Int16Array),"undefined"!=typeof Uint16Array&&d.push(Uint16Array),"undefined"!=typeof Int32Array&&d.push(Int32Array),"undefined"!=typeof Uint32Array&&d.push(Uint32Array),"undefined"!=typeof Float32Array&&d.push(Float32Array),"undefined"!=typeof Float64Array&&d.push(Float64Array),c.isArrayBufferView=function(a){for(var b=0;b0;)1&b&&(c+=a),b>>>=1,b>0&&(a+=a);return this.data=c,this},c.ByteBuffer.prototype.putBytes=function(a){return this.data+=a,this},c.ByteBuffer.prototype.putString=function(a){return this.data+=c.encodeUtf8(a),this},c.ByteBuffer.prototype.putInt16=function(a){return this.data+=String.fromCharCode(a>>8&255)+String.fromCharCode(255&a),this},c.ByteBuffer.prototype.putInt24=function(a){return this.data+=String.fromCharCode(a>>16&255)+String.fromCharCode(a>>8&255)+String.fromCharCode(255&a),this},c.ByteBuffer.prototype.putInt32=function(a){return this.data+=String.fromCharCode(a>>24&255)+String.fromCharCode(a>>16&255)+String.fromCharCode(a>>8&255)+String.fromCharCode(255&a),this},c.ByteBuffer.prototype.putInt16Le=function(a){return this.data+=String.fromCharCode(255&a)+String.fromCharCode(a>>8&255),this},c.ByteBuffer.prototype.putInt24Le=function(a){return this.data+=String.fromCharCode(255&a)+String.fromCharCode(a>>8&255)+String.fromCharCode(a>>16&255),this},c.ByteBuffer.prototype.putInt32Le=function(a){return this.data+=String.fromCharCode(255&a)+String.fromCharCode(a>>8&255)+String.fromCharCode(a>>16&255)+String.fromCharCode(a>>24&255),this},c.ByteBuffer.prototype.putInt=function(a,b){do b-=8,this.data+=String.fromCharCode(a>>b&255);while(b>0);return this},c.ByteBuffer.prototype.putSignedInt=function(a,b){return 0>a&&(a+=2<0);return b},c.ByteBuffer.prototype.getSignedInt=function(a){var b=this.getInt(a),c=2<=c&&(b-=c<<1),b},c.ByteBuffer.prototype.getBytes=function(a){var b;return a?(a=Math.min(this.length(),a),b=this.data.slice(this.read,this.read+a),this.read+=a):0===a?b="":(b=0===this.read?this.data:this.data.slice(this.read),this.clear()),b},c.ByteBuffer.prototype.bytes=function(a){return"undefined"==typeof a?this.data.slice(this.read):this.data.slice(this.read,this.read+a)},c.ByteBuffer.prototype.at=function(a){return this.data.charCodeAt(this.read+a)},c.ByteBuffer.prototype.setAt=function(a,b){return this.data=this.data.substr(0,this.read+a)+String.fromCharCode(b)+this.data.substr(this.read+a+1),this},c.ByteBuffer.prototype.last=function(){return this.data.charCodeAt(this.data.length-1)},c.ByteBuffer.prototype.copy=function(){var a=c.createBuffer(this.data);return a.read=this.read,a},c.ByteBuffer.prototype.compact=function(){return this.read>0&&(this.data=this.data.slice(this.read),this.read=0),this},c.ByteBuffer.prototype.clear=function(){return this.data="",this.read=0,this},c.ByteBuffer.prototype.truncate=function(a){var b=Math.max(0,this.length()-a);return this.data=this.data.substr(this.read,b),this.read=0,this},c.ByteBuffer.prototype.toHex=function(){for(var a="",b=this.read;bc&&(a+="0"),a+=c.toString(16)}return a},c.ByteBuffer.prototype.toString=function(){return c.decodeUtf8(this.bytes())},c.createBuffer=function(a,b){return b=b||"raw",void 0!==a&&"utf8"===b&&(a=c.encodeUtf8(a)),new c.ByteBuffer(a)},c.fillString=function(a,b){for(var c="";b>0;)1&b&&(c+=a),b>>>=1,b>0&&(a+=a);return c},c.xorBytes=function(a,b,c){for(var d="",e="",f="",g=0,h=0;c>0;--c,++g)e=a.charCodeAt(g)^b.charCodeAt(g),h>=10&&(d+=f,f="",h=0),f+=String.fromCharCode(e),++h;return d+=f},c.hexToBytes=function(a){var b="",c=0;for(a.length&!0&&(c=1,b+=String.fromCharCode(parseInt(a[0],16)));c>24&255)+String.fromCharCode(a>>16&255)+String.fromCharCode(a>>8&255)+String.fromCharCode(255&a)};var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",f=[62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,64,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51];c.encode64=function(a,b){for(var c,d,f,g="",h="",i=0;i>2),g+=e.charAt((3&c)<<4|d>>4),isNaN(d)?g+="==":(g+=e.charAt((15&d)<<2|f>>6),g+=isNaN(f)?"=":e.charAt(63&f)),b&&g.length>b&&(h+=g.substr(0,b)+"\r\n",g=g.substr(b));return h+=g},c.decode64=function(a){a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");for(var b,c,d,e,g="",h=0;h>4),64!==d&&(g+=String.fromCharCode((15&c)<<4|d>>2),64!==e&&(g+=String.fromCharCode((3&d)<<6|e)));return g},c.encodeUtf8=function(a){return unescape(encodeURIComponent(a))},c.decodeUtf8=function(a){return decodeURIComponent(escape(a))}},{}],28:[function(a,b){var c=a("./sha.js"),d=a("./forge_sha256.js");b.exports={md5:a("./md5.js"),sha1:c.sha1,sha224:c.sha224,sha256:c.sha256,sha384:c.sha384,sha512:c.sha512,ripemd:a("./ripe-md.js"),digest:function(a,b){switch(a){case 1:return this.md5(b);case 2:return this.sha1(b);case 3:return this.ripemd(b);case 8:var c=d.create();return c.update(b),c.digest().getBytes();case 9:return this.sha384(b);case 10:return this.sha512(b);case 11:return this.sha224(b);default:throw new Error("Invalid hash function.")}},getHashByteLength:function(a){switch(a){case 1:return 16;case 2:case 3:return 20;case 8:return 32;case 9:return 48;case 10:return 64;case 11:return 28;default:throw new Error("Invalid hash algorithm.")}}}},{"./forge_sha256.js":26,"./md5.js":29,"./ripe-md.js":30,"./sha.js":31}],29:[function(a,b){function c(a,b){var c=a[0],d=a[1],i=a[2],j=a[3];c=e(c,d,i,j,b[0],7,-680876936),j=e(j,c,d,i,b[1],12,-389564586),i=e(i,j,c,d,b[2],17,606105819),d=e(d,i,j,c,b[3],22,-1044525330),c=e(c,d,i,j,b[4],7,-176418897),j=e(j,c,d,i,b[5],12,1200080426),i=e(i,j,c,d,b[6],17,-1473231341),d=e(d,i,j,c,b[7],22,-45705983),c=e(c,d,i,j,b[8],7,1770035416),j=e(j,c,d,i,b[9],12,-1958414417),i=e(i,j,c,d,b[10],17,-42063),d=e(d,i,j,c,b[11],22,-1990404162),c=e(c,d,i,j,b[12],7,1804603682),j=e(j,c,d,i,b[13],12,-40341101),i=e(i,j,c,d,b[14],17,-1502002290),d=e(d,i,j,c,b[15],22,1236535329),c=f(c,d,i,j,b[1],5,-165796510),j=f(j,c,d,i,b[6],9,-1069501632),i=f(i,j,c,d,b[11],14,643717713),d=f(d,i,j,c,b[0],20,-373897302),c=f(c,d,i,j,b[5],5,-701558691),j=f(j,c,d,i,b[10],9,38016083),i=f(i,j,c,d,b[15],14,-660478335),d=f(d,i,j,c,b[4],20,-405537848),c=f(c,d,i,j,b[9],5,568446438),j=f(j,c,d,i,b[14],9,-1019803690),i=f(i,j,c,d,b[3],14,-187363961),d=f(d,i,j,c,b[8],20,1163531501),c=f(c,d,i,j,b[13],5,-1444681467),j=f(j,c,d,i,b[2],9,-51403784),i=f(i,j,c,d,b[7],14,1735328473),d=f(d,i,j,c,b[12],20,-1926607734),c=g(c,d,i,j,b[5],4,-378558),j=g(j,c,d,i,b[8],11,-2022574463),i=g(i,j,c,d,b[11],16,1839030562),d=g(d,i,j,c,b[14],23,-35309556),c=g(c,d,i,j,b[1],4,-1530992060),j=g(j,c,d,i,b[4],11,1272893353),i=g(i,j,c,d,b[7],16,-155497632),d=g(d,i,j,c,b[10],23,-1094730640),c=g(c,d,i,j,b[13],4,681279174),j=g(j,c,d,i,b[0],11,-358537222),i=g(i,j,c,d,b[3],16,-722521979),d=g(d,i,j,c,b[6],23,76029189),c=g(c,d,i,j,b[9],4,-640364487),j=g(j,c,d,i,b[12],11,-421815835),i=g(i,j,c,d,b[15],16,530742520),d=g(d,i,j,c,b[2],23,-995338651),c=h(c,d,i,j,b[0],6,-198630844),j=h(j,c,d,i,b[7],10,1126891415),i=h(i,j,c,d,b[14],15,-1416354905),d=h(d,i,j,c,b[5],21,-57434055),c=h(c,d,i,j,b[12],6,1700485571),j=h(j,c,d,i,b[3],10,-1894986606),i=h(i,j,c,d,b[10],15,-1051523),d=h(d,i,j,c,b[1],21,-2054922799),c=h(c,d,i,j,b[8],6,1873313359),j=h(j,c,d,i,b[15],10,-30611744),i=h(i,j,c,d,b[6],15,-1560198380),d=h(d,i,j,c,b[13],21,1309151649),c=h(c,d,i,j,b[4],6,-145523070),j=h(j,c,d,i,b[11],10,-1120210379),i=h(i,j,c,d,b[2],15,718787259),d=h(d,i,j,c,b[9],21,-343485551),a[0]=n(c,a[0]),a[1]=n(d,a[1]),a[2]=n(i,a[2]),a[3]=n(j,a[3])}function d(a,b,c,d,e,f){return b=n(n(b,a),n(d,f)),n(b<>>32-e,c)}function e(a,b,c,e,f,g,h){return d(b&c|~b&e,a,b,f,g,h)}function f(a,b,c,e,f,g,h){return d(b&e|c&~e,a,b,f,g,h)}function g(a,b,c,e,f,g,h){return d(b^c^e,a,b,f,g,h)}function h(a,b,c,e,f,g,h){return d(c^(b|~e),a,b,f,g,h)}function i(a){txt="";var b,d=a.length,e=[1732584193,-271733879,-1732584194,271733878];for(b=64;b<=a.length;b+=64)c(e,j(a.substring(b-64,b)));a=a.substring(b-64);var f=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(b=0;b>2]|=a.charCodeAt(b)<<(b%4<<3);if(f[b>>2]|=128<<(b%4<<3),b>55)for(c(e,f),b=0;16>b;b++)f[b]=0;return f[14]=8*d,c(e,f),e}function j(a){var b,c=[];for(b=0;64>b;b+=4)c[b>>2]=a.charCodeAt(b)+(a.charCodeAt(b+1)<<8)+(a.charCodeAt(b+2)<<16)+(a.charCodeAt(b+3)<<24);return c}function k(a){for(var b="",c=0;4>c;c++)b+=p[a>>8*c+4&15]+p[a>>8*c&15];return b}function l(a){for(var b=0;b>16)+(b>>16)+(c>>16);return d<<16|65535&c}var o=a("../../util.js");b.exports=function(a){var b=m(a),c=o.hex2bin(b);return c};var p="0123456789abcdef".split("");"5d41402abc4b2a76b9719d911017c592"!=m("hello")},{"../../util.js":74}],30:[function(a,b){function c(a,b){return new Number(a<>>32-b)}function d(a,b,c){return new Number(a^b^c)}function e(a,b,c){return new Number(a&b|~a&c)}function f(a,b,c){return new Number((a|~b)^c)}function g(a,b,c){return new Number(a&c|b&~c)}function h(a,b,c){return new Number(a^(b|~c))}function i(a,b,i,j,k,l,m,n){switch(n){case 0:a+=d(b,i,j)+l+0;break;case 1:a+=e(b,i,j)+l+1518500249;break;case 2:a+=f(b,i,j)+l+1859775393;break;case 3:a+=g(b,i,j)+l+2400959708;break;case 4:a+=h(b,i,j)+l+2840853838;break;case 5:a+=h(b,i,j)+l+1352829926;break;case 6:a+=g(b,i,j)+l+1548603684;break;case 7:a+=f(b,i,j)+l+1836072691;break;case 8:a+=e(b,i,j)+l+2053994217;break;case 9:a+=d(b,i,j)+l+0;break;default:throw new Error("Bogus round number")}a=c(a,m)+k,i=c(i,10),a&=4294967295,b&=4294967295,i&=4294967295,j&=4294967295,k&=4294967295;var o=[];return o[0]=a,o[1]=b,o[2]=i,o[3]=j,o[4]=k,o[5]=l,o[6]=m,o}function j(a){a[0]=1732584193,a[1]=4023233417,a[2]=2562383102,a[3]=271733878,a[4]=3285377520}function k(a,b){blockA=[],blockB=[];var c,d,e;for(d=0;5>d;d++)blockA[d]=new Number(a[d]),blockB[d]=new Number(a[d]);var f=0;for(e=0;5>e;e++)for(d=0;16>d;d++)c=i(blockA[(f+0)%5],blockA[(f+1)%5],blockA[(f+2)%5],blockA[(f+3)%5],blockA[(f+4)%5],b[s[e][d]],r[e][d],e),blockA[(f+0)%5]=c[0],blockA[(f+1)%5]=c[1],blockA[(f+2)%5]=c[2],blockA[(f+3)%5]=c[3],blockA[(f+4)%5]=c[4],f+=4;for(f=0,e=5;10>e;e++)for(d=0;16>d;d++)c=i(blockB[(f+0)%5],blockB[(f+1)%5],blockB[(f+2)%5],blockB[(f+3)%5],blockB[(f+4)%5],b[s[e][d]],r[e][d],e),blockB[(f+0)%5]=c[0],blockB[(f+1)%5]=c[1],blockB[(f+2)%5]=c[2],blockB[(f+3)%5]=c[3],blockB[(f+4)%5]=c[4],f+=4;blockB[3]+=blockA[2]+a[1],a[1]=a[2]+blockA[3]+blockB[4],a[2]=a[3]+blockA[4]+blockB[0],a[3]=a[4]+blockA[0]+blockB[1],a[4]=a[0]+blockA[1]+blockB[2],a[0]=blockB[3]}function l(a){for(var b=0;16>b;b++)a[b]=0}function m(a,b,c,d){var e=new Array(16);l(e);for(var f=0,g=0;(63&c)>g;g++)e[g>>>2]^=(255&b.charCodeAt(f++))<<8*(3&g);e[c>>>2&15]^=1<<8*(3&c)+7,(63&c)>55&&(k(a,e),e=new Array(16),l(e)),e[14]=c<<3,e[15]=c>>>29|d<<3,k(a,e)}function n(a){var b=(255&a.charCodeAt(3))<<24;return b|=(255&a.charCodeAt(2))<<16,b|=(255&a.charCodeAt(1))<<8,b|=255&a.charCodeAt(0)}function o(a){var b,c,d=new Array(q/32),e=new Array(q/8);j(d),b=a.length;var f=new Array(16);l(f);var g,h=0;for(c=b;c>63;c-=64){for(g=0;16>g;g++)f[g]=n(a.substr(h,4)),h+=4;k(d,f)}for(m(d,a.substr(h),b,0),g=0;q/8>g;g+=4)e[g]=255&d[g>>>2],e[g+1]=d[g>>>2]>>>8&255,e[g+2]=d[g>>>2]>>>16&255,e[g+3]=d[g>>>2]>>>24&255;return e}function p(a){for(var b=o(a),c="",d=0;q/8>d;d++)c+=String.fromCharCode(b[d]);return c}var q=160,r=[[11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8],[7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12],[11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5],[11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12],[9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6],[8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6],[9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11],[9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5],[15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8],[8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]],s=[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8],[3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12],[1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2],[4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13],[5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12],[6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2],[15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13],[8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14],[12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]];b.exports=p},{}],31:[function(a,b){var c=function(){var a=8,b="",c=0,d=function(a,b){this.highOrder=a,this.lowOrder=b},e=function(b){var c,d=[],e=(1<c;c+=a)d[c>>5]|=(b.charCodeAt(c/a)&e)<<32-a-c%32;return d},f=function(a){var b,c,d=[],e=a.length;for(b=0;e>b;b+=2){if(c=parseInt(a.substr(b,2),16),isNaN(c))throw new Error("INVALID HEX STRING");d[b>>3]|=c<<24-4*(b%8)}return d},g=function(a){var b,d,e=c?"0123456789ABCDEF":"0123456789abcdef",f="",g=4*a.length;for(b=0;g>b;b+=1)d=a[b>>2]>>8*(3-b%4),f+=e.charAt(d>>4&15)+e.charAt(15&d);return f},h=function(a){var c,d,e,f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",g="",h=4*a.length;for(c=0;h>c;c+=3)for(e=(a[c>>2]>>8*(3-c%4)&255)<<16|(a[c+1>>2]>>8*(3-(c+1)%4)&255)<<8|a[c+2>>2]>>8*(3-(c+2)%4)&255,d=0;4>d;d+=1)g+=8*c+6*d<=32*a.length?f.charAt(e>>6*(3-d)&63):b;return g},i=function(a){for(var b="",c=255,d=0;d<32*a.length;d+=8)b+=String.fromCharCode(a[d>>5]>>>24-d%32&c);return b},j=function(a,b){return a<>>32-b},k=function(a,b){return a>>>b|a<<32-b},l=function(a,b){return 32>=b?new d(a.highOrder>>>b|a.lowOrder<<32-b,a.lowOrder>>>b|a.highOrder<<32-b):new d(a.lowOrder>>>b|a.highOrder<<32-b,a.highOrder>>>b|a.lowOrder<<32-b)},m=function(a,b){return a>>>b},n=function(a,b){return 32>=b?new d(a.highOrder>>>b,a.lowOrder>>>b|a.highOrder<<32-b):new d(0,a.highOrder<<32-b)},o=function(a,b,c){return a^b^c},p=function(a,b,c){return a&b^~a&c},q=function(a,b,c){return new d(a.highOrder&b.highOrder^~a.highOrder&c.highOrder,a.lowOrder&b.lowOrder^~a.lowOrder&c.lowOrder)},r=function(a,b,c){return a&b^a&c^b&c},s=function(a,b,c){return new d(a.highOrder&b.highOrder^a.highOrder&c.highOrder^b.highOrder&c.highOrder,a.lowOrder&b.lowOrder^a.lowOrder&c.lowOrder^b.lowOrder&c.lowOrder)},t=function(a){return k(a,2)^k(a,13)^k(a,22)},u=function(a){var b=l(a,28),c=l(a,34),e=l(a,39);return new d(b.highOrder^c.highOrder^e.highOrder,b.lowOrder^c.lowOrder^e.lowOrder)},v=function(a){return k(a,6)^k(a,11)^k(a,25)},w=function(a){var b=l(a,14),c=l(a,18),e=l(a,41);return new d(b.highOrder^c.highOrder^e.highOrder,b.lowOrder^c.lowOrder^e.lowOrder)},x=function(a){return k(a,7)^k(a,18)^m(a,3)},y=function(a){var b=l(a,1),c=l(a,8),e=n(a,7);return new d(b.highOrder^c.highOrder^e.highOrder,b.lowOrder^c.lowOrder^e.lowOrder)},z=function(a){return k(a,17)^k(a,19)^m(a,10)},A=function(a){var b=l(a,19),c=l(a,61),e=n(a,6);return new d(b.highOrder^c.highOrder^e.highOrder,b.lowOrder^c.lowOrder^e.lowOrder)},B=function(a,b){var c=(65535&a)+(65535&b),d=(a>>>16)+(b>>>16)+(c>>>16); -return(65535&d)<<16|65535&c},C=function(a,b,c,d){var e=(65535&a)+(65535&b)+(65535&c)+(65535&d),f=(a>>>16)+(b>>>16)+(c>>>16)+(d>>>16)+(e>>>16);return(65535&f)<<16|65535&e},D=function(a,b,c,d,e){var f=(65535&a)+(65535&b)+(65535&c)+(65535&d)+(65535&e),g=(a>>>16)+(b>>>16)+(c>>>16)+(d>>>16)+(e>>>16)+(f>>>16);return(65535&g)<<16|65535&f},E=function(a,b){var c,e,f,g;return c=(65535&a.lowOrder)+(65535&b.lowOrder),e=(a.lowOrder>>>16)+(b.lowOrder>>>16)+(c>>>16),f=(65535&e)<<16|65535&c,c=(65535&a.highOrder)+(65535&b.highOrder)+(e>>>16),e=(a.highOrder>>>16)+(b.highOrder>>>16)+(c>>>16),g=(65535&e)<<16|65535&c,new d(g,f)},F=function(a,b,c,e){var f,g,h,i;return f=(65535&a.lowOrder)+(65535&b.lowOrder)+(65535&c.lowOrder)+(65535&e.lowOrder),g=(a.lowOrder>>>16)+(b.lowOrder>>>16)+(c.lowOrder>>>16)+(e.lowOrder>>>16)+(f>>>16),h=(65535&g)<<16|65535&f,f=(65535&a.highOrder)+(65535&b.highOrder)+(65535&c.highOrder)+(65535&e.highOrder)+(g>>>16),g=(a.highOrder>>>16)+(b.highOrder>>>16)+(c.highOrder>>>16)+(e.highOrder>>>16)+(f>>>16),i=(65535&g)<<16|65535&f,new d(i,h)},G=function(a,b,c,e,f){var g,h,i,j;return g=(65535&a.lowOrder)+(65535&b.lowOrder)+(65535&c.lowOrder)+(65535&e.lowOrder)+(65535&f.lowOrder),h=(a.lowOrder>>>16)+(b.lowOrder>>>16)+(c.lowOrder>>>16)+(e.lowOrder>>>16)+(f.lowOrder>>>16)+(g>>>16),i=(65535&h)<<16|65535&g,g=(65535&a.highOrder)+(65535&b.highOrder)+(65535&c.highOrder)+(65535&e.highOrder)+(65535&f.highOrder)+(h>>>16),h=(a.highOrder>>>16)+(b.highOrder>>>16)+(c.highOrder>>>16)+(e.highOrder>>>16)+(f.highOrder>>>16)+(g>>>16),j=(65535&h)<<16|65535&g,new d(j,i)},H=function(a,b){var c,d,e,f,g,h,i,k,l,m=[],n=p,q=o,s=r,t=j,u=B,v=D,w=[1732584193,4023233417,2562383102,271733878,3285377520],x=[1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782];for(a[b>>5]|=128<<24-b%32,a[(b+65>>9<<4)+15]=b,l=a.length,i=0;l>i;i+=16){for(c=w[0],d=w[1],e=w[2],f=w[3],g=w[4],k=0;80>k;k+=1)m[k]=16>k?a[k+i]:t(m[k-3]^m[k-8]^m[k-14]^m[k-16],1),h=20>k?v(t(c,5),n(d,e,f),g,x[k],m[k]):40>k?v(t(c,5),q(d,e,f),g,x[k],m[k]):60>k?v(t(c,5),s(d,e,f),g,x[k],m[k]):v(t(c,5),q(d,e,f),g,x[k],m[k]),g=f,f=e,e=t(d,30),d=c,c=h;w[0]=u(c,w[0]),w[1]=u(d,w[1]),w[2]=u(e,w[2]),w[3]=u(f,w[3]),w[4]=u(g,w[4])}return w},I=function(a,b,c){var e,f,g,h,i,j,k,l,m,n,o,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z=[];for("SHA-224"===c||"SHA-256"===c?(H=64,I=(b+65>>9<<4)+15,L=16,M=1,W=Number,N=B,O=C,P=D,Q=x,R=z,S=t,T=v,V=r,U=p,X=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],o="SHA-224"===c?[3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428]:[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]):("SHA-384"===c||"SHA-512"===c)&&(H=80,I=(b+128>>10<<5)+31,L=32,M=2,W=d,N=E,O=F,P=G,Q=y,R=A,S=u,T=w,V=s,U=q,X=[new W(1116352408,3609767458),new W(1899447441,602891725),new W(3049323471,3964484399),new W(3921009573,2173295548),new W(961987163,4081628472),new W(1508970993,3053834265),new W(2453635748,2937671579),new W(2870763221,3664609560),new W(3624381080,2734883394),new W(310598401,1164996542),new W(607225278,1323610764),new W(1426881987,3590304994),new W(1925078388,4068182383),new W(2162078206,991336113),new W(2614888103,633803317),new W(3248222580,3479774868),new W(3835390401,2666613458),new W(4022224774,944711139),new W(264347078,2341262773),new W(604807628,2007800933),new W(770255983,1495990901),new W(1249150122,1856431235),new W(1555081692,3175218132),new W(1996064986,2198950837),new W(2554220882,3999719339),new W(2821834349,766784016),new W(2952996808,2566594879),new W(3210313671,3203337956),new W(3336571891,1034457026),new W(3584528711,2466948901),new W(113926993,3758326383),new W(338241895,168717936),new W(666307205,1188179964),new W(773529912,1546045734),new W(1294757372,1522805485),new W(1396182291,2643833823),new W(1695183700,2343527390),new W(1986661051,1014477480),new W(2177026350,1206759142),new W(2456956037,344077627),new W(2730485921,1290863460),new W(2820302411,3158454273),new W(3259730800,3505952657),new W(3345764771,106217008),new W(3516065817,3606008344),new W(3600352804,1432725776),new W(4094571909,1467031594),new W(275423344,851169720),new W(430227734,3100823752),new W(506948616,1363258195),new W(659060556,3750685593),new W(883997877,3785050280),new W(958139571,3318307427),new W(1322822218,3812723403),new W(1537002063,2003034995),new W(1747873779,3602036899),new W(1955562222,1575990012),new W(2024104815,1125592928),new W(2227730452,2716904306),new W(2361852424,442776044),new W(2428436474,593698344),new W(2756734187,3733110249),new W(3204031479,2999351573),new W(3329325298,3815920427),new W(3391569614,3928383900),new W(3515267271,566280711),new W(3940187606,3454069534),new W(4118630271,4000239992),new W(116418474,1914138554),new W(174292421,2731055270),new W(289380356,3203993006),new W(460393269,320620315),new W(685471733,587496836),new W(852142971,1086792851),new W(1017036298,365543100),new W(1126000580,2618297676),new W(1288033470,3409855158),new W(1501505948,4234509866),new W(1607167915,987167468),new W(1816402316,1246189591)],o="SHA-384"===c?[new W(3418070365,3238371032),new W(1654270250,914150663),new W(2438529370,812702999),new W(355462360,4144912697),new W(1731405415,4290775857),new W(41048885895,1750603025),new W(3675008525,1694076839),new W(1203062813,3204075428)]:[new W(1779033703,4089235720),new W(3144134277,2227873595),new W(1013904242,4271175723),new W(2773480762,1595750129),new W(1359893119,2917565137),new W(2600822924,725511199),new W(528734635,4215389547),new W(1541459225,327033209)]),a[b>>5]|=128<<24-b%32,a[I]=b,Y=a.length,J=0;Y>J;J+=L){for(e=o[0],f=o[1],g=o[2],h=o[3],i=o[4],j=o[5],k=o[6],l=o[7],K=0;H>K;K+=1)Z[K]=16>K?new W(a[K*M+J],a[K*M+J+1]):O(R(Z[K-2]),Z[K-7],Q(Z[K-15]),Z[K-16]),m=P(l,T(i),U(i,j,k),X[K],Z[K]),n=N(S(e),V(e,f,g)),l=k,k=j,j=i,i=N(h,m),h=g,g=f,f=e,e=N(m,n);o[0]=N(e,o[0]),o[1]=N(f,o[1]),o[2]=N(g,o[2]),o[3]=N(h,o[3]),o[4]=N(i,o[4]),o[5]=N(j,o[5]),o[6]=N(k,o[6]),o[7]=N(l,o[7])}switch(c){case"SHA-224":return[o[0],o[1],o[2],o[3],o[4],o[5],o[6]];case"SHA-256":return o;case"SHA-384":return[o[0].highOrder,o[0].lowOrder,o[1].highOrder,o[1].lowOrder,o[2].highOrder,o[2].lowOrder,o[3].highOrder,o[3].lowOrder,o[4].highOrder,o[4].lowOrder,o[5].highOrder,o[5].lowOrder];case"SHA-512":return[o[0].highOrder,o[0].lowOrder,o[1].highOrder,o[1].lowOrder,o[2].highOrder,o[2].lowOrder,o[3].highOrder,o[3].lowOrder,o[4].highOrder,o[4].lowOrder,o[5].highOrder,o[5].lowOrder,o[6].highOrder,o[6].lowOrder,o[7].highOrder,o[7].lowOrder];default:throw new Error("Unknown SHA variant")}},J=function(b,c){if(this.sha1=null,this.sha224=null,this.sha256=null,this.sha384=null,this.sha512=null,this.strBinLen=null,this.strToHash=null,"HEX"===c){if(0!==b.length%2)throw new Error("TEXT MUST BE IN BYTE INCREMENTS");this.strBinLen=4*b.length,this.strToHash=f(b)}else{if("ASCII"!==c&&"undefined"!=typeof c)throw new Error("UNKNOWN TEXT INPUT TYPE");this.strBinLen=b.length*a,this.strToHash=e(b)}};return J.prototype={getHash:function(a,b){var c=null,d=this.strToHash.slice();switch(b){case"HEX":c=g;break;case"B64":c=h;break;case"ASCII":c=i;break;default:throw new Error("FORMAT NOT RECOGNIZED")}switch(a){case"SHA-1":return null===this.sha1&&(this.sha1=H(d,this.strBinLen)),c(this.sha1);case"SHA-224":return null===this.sha224&&(this.sha224=I(d,this.strBinLen,a)),c(this.sha224);case"SHA-256":return null===this.sha256&&(this.sha256=I(d,this.strBinLen,a)),c(this.sha256);case"SHA-384":return null===this.sha384&&(this.sha384=I(d,this.strBinLen,a)),c(this.sha384);case"SHA-512":return null===this.sha512&&(this.sha512=I(d,this.strBinLen,a)),c(this.sha512);default:throw new Error("HASH NOT RECOGNIZED")}},getHMAC:function(b,c,d,j){var k,l,m,n,o,p,q,r,s,t=[],u=[];switch(j){case"HEX":k=g;break;case"B64":k=h;break;case"ASCII":k=i;break;default:throw new Error("FORMAT NOT RECOGNIZED")}switch(d){case"SHA-1":m=64,s=160;break;case"SHA-224":m=64,s=224;break;case"SHA-256":m=64,s=256;break;case"SHA-384":m=128,s=384;break;case"SHA-512":m=128,s=512;break;default:throw new Error("HASH NOT RECOGNIZED")}if("HEX"===c){if(0!==b.length%2)throw new Error("KEY MUST BE IN BYTE INCREMENTS");l=f(b),r=4*b.length}else{if("ASCII"!==c)throw new Error("UNKNOWN KEY INPUT TYPE");l=e(b),r=b.length*a}for(n=8*m,q=m/4-1,r/8>m?(l="SHA-1"===d?H(l,r):I(l,r,d),l[q]&=4294967040):m>r/8&&(l[q]&=4294967040),o=0;q>=o;o+=1)t[o]=909522486^l[o],u[o]=1549556828^l[o];return"SHA-1"===d?(p=H(t.concat(this.strToHash),n+this.strBinLen),p=H(u.concat(p),n+s)):(p=I(t.concat(this.strToHash),n+this.strBinLen,d),p=I(u.concat(p),n+s,d)),k(p)}},J}();b.exports={sha1:function(a){var b=new c(a,"ASCII");return b.getHash("SHA-1","ASCII")},sha224:function(a){var b=new c(a,"ASCII");return b.getHash("SHA-224","ASCII")},sha256:function(a){var b=new c(a,"ASCII");return b.getHash("SHA-256","ASCII")},sha384:function(a){var b=new c(a,"ASCII");return b.getHash("SHA-384","ASCII")},sha512:function(a){var b=new c(a,"ASCII");return b.getHash("SHA-512","ASCII")}}},{}],32:[function(a,b){b.exports={cipher:a("./cipher"),hash:a("./hash"),cfb:a("./cfb.js"),publicKey:a("./public_key"),signature:a("./signature.js"),random:a("./random.js"),pkcs1:a("./pkcs1.js")};var c=a("./crypto.js");for(var d in c)b.exports[d]=c[d]},{"./cfb.js":18,"./cipher":23,"./crypto.js":25,"./hash":28,"./pkcs1.js":33,"./public_key":36,"./random.js":39,"./signature.js":40}],33:[function(a,b){function c(a){for(var b,c="";c.lengthb-11)throw new Error("Message too long");var e=c(b-d-3),f=String.fromCharCode(0)+String.fromCharCode(2)+e+String.fromCharCode(0)+a;return f},decode:function(a){0!==a.charCodeAt(0)&&(a=String.fromCharCode(0)+a);for(var b=a.charCodeAt(0),c=a.charCodeAt(1),d=2;0!==a.charCodeAt(d)&&d=8&&0===f)return a.substr(d);throw new Error("Decryption error")}},emsa:{encode:function(a,b,c){var e,i=h.digest(a,b);if(i.length!==h.getHashByteLength(a))throw new Error("Invalid hash length");var j="";for(e=0;ec)throw new Error("Intended encoded message length too short");var l="";for(e=0;c-k-3>e;e++)l+=String.fromCharCode(255);var m=String.fromCharCode(0)+String.fromCharCode(1)+l+String.fromCharCode(0)+j;return new g(f.hexstrdump(m),16)}}}},{"../util.js":74,"./crypto.js":25,"./hash":28,"./public_key/jsbn.js":37,"./random.js":39}],34:[function(a,b){function c(){function a(a,b,c,h,i,j){for(var k,l,m,n=g.getLeftNBits(f.digest(a,b),i.bitLength()),o=new d(g.hexstrdump(n),16);;)if(k=e.getRandomBigIntegerInRange(d.ONE,i.subtract(d.ONE)),l=c.modPow(k,h).mod(i),m=k.modInverse(i).multiply(o.add(j.multiply(l))).mod(i),0!=l&&0!=m)break;var p=[];return p[0]=l.toMPI(),p[1]=m.toMPI(),p}function b(a){var b=h.prefer_hash_algorithm;switch(Math.round(a.bitLength()/8)){case 20:return 2!=b&&b>11&&10!=b&&8>b?2:b;case 28:return b>11&&8>b?11:b;case 32:return b>10&&8>b?8:b;default:return g.print_debug("DSA select hash algorithm: returning null for an unknown length of q"),null}}function c(a,b,c,e,h,i,j,k){var l=g.getLeftNBits(f.digest(a,e),i.bitLength()),m=new d(g.hexstrdump(l),16);if(d.ZERO.compareTo(b)>0||b.compareTo(i)>0||d.ZERO.compareTo(c)>0||c.compareTo(i)>0)return g.print_debug("invalid DSA Signature"),null;var n=c.modInverse(i),o=m.multiply(n).mod(i),p=b.multiply(n).mod(i);return j.modPow(o,h).multiply(k.modPow(p,h)).mod(h).mod(i)}this.select_hash_algorithm=b,this.sign=a,this.verify=c}var d=a("./jsbn.js"),e=a("../random.js"),f=a("../hash"),g=a("../../util.js"),h=a("../../config");b.exports=c},{"../../config":17,"../../util.js":74,"../hash":28,"../random.js":39,"./jsbn.js":37}],35:[function(a,b){function c(){function a(a,b,c,f){var g=c.subtract(d.TWO),h=e.getRandomBigIntegerInRange(d.ONE,g);h=h.mod(g).add(d.ONE);var i=[];return i[0]=b.modPow(h,c),i[1]=f.modPow(h,c).multiply(a).mod(c),i}function b(a,b,c,d){return f.print_debug("Elgamal Decrypt:\nc1:"+f.hexstrdump(a.toMPI())+"\nc2:"+f.hexstrdump(b.toMPI())+"\np:"+f.hexstrdump(c.toMPI())+"\nx:"+f.hexstrdump(d.toMPI())),a.modPow(d,c).modInverse(c).multiply(b).mod(c)}this.encrypt=a,this.decrypt=b}var d=a("./jsbn.js"),e=a("../random.js"),f=a("../../util.js");b.exports=c},{"../../util.js":74,"../random.js":39,"./jsbn.js":37}],36:[function(a,b){b.exports={rsa:a("./rsa.js"),elgamal:a("./elgamal.js"),dsa:a("./dsa.js")}},{"./dsa.js":34,"./elgamal.js":35,"./rsa.js":38}],37:[function(a,b){function c(a,b,c){null!=a&&("number"==typeof a?this.fromNumber(a,b,c):null==b&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))}function d(){return new c(null)}function e(a,b,c,d,e,f){for(;--f>=0;){var g=b*this[a++]+c[d]+e;e=Math.floor(g/67108864),c[d++]=67108863&g}return e}function f(a){return ec.charAt(a)}function g(a,b){var c=fc[a.charCodeAt(b)];return null==c?-1:c}function h(a){for(var b=this.t-1;b>=0;--b)a[b]=this[b];a.t=this.t,a.s=this.s}function i(a){this.t=1,this.s=0>a?-1:0,a>0?this[0]=a:-1>a?this[0]=a+this.DV:this.t=0}function j(a){var b=d();return b.fromInt(a),b}function k(a,b){var d;if(16==b)d=4;else if(8==b)d=3;else if(256==b)d=8;else if(2==b)d=1;else if(32==b)d=5;else{if(4!=b)return void this.fromRadix(a,b);d=2}this.t=0,this.s=0;for(var e=a.length,f=!1,h=0;--e>=0;){var i=8==d?255&a[e]:g(a,e);0>i?"-"==a.charAt(e)&&(f=!0):(f=!1,0==h?this[this.t++]=i:h+d>this.DB?(this[this.t-1]|=(i&(1<>this.DB-h):this[this.t-1]|=i<=this.DB&&(h-=this.DB))}8==d&&0!=(128&a[0])&&(this.s=-1,h>0&&(this[this.t-1]|=(1<0&&this[this.t-1]==a;)--this.t}function m(a){if(this.s<0)return"-"+this.negate().toString(a);var b;if(16==a)b=4;else if(8==a)b=3;else if(2==a)b=1;else if(32==a)b=5;else{if(4!=a)return this.toRadix(a);b=2}var c,d=(1<0)for(i>i)>0&&(e=!0,g=f(c));h>=0;)b>i?(c=(this[h]&(1<>(i+=this.DB-b)):(c=this[h]>>(i-=b)&d,0>=i&&(i+=this.DB,--h)),c>0&&(e=!0),e&&(g+=f(c));return e?g:"0"}function n(){var a=d();return c.ZERO.subTo(this,a),a}function o(){return this.s<0?this.negate():this}function p(a){var b=this.s-a.s;if(0!=b)return b;var c=this.t;if(b=c-a.t,0!=b)return this.s<0?-b:b;for(;--c>=0;)if(0!=(b=this[c]-a[c]))return b;return 0}function q(a){var b,c=1;return 0!=(b=a>>>16)&&(a=b,c+=16),0!=(b=a>>8)&&(a=b,c+=8),0!=(b=a>>4)&&(a=b,c+=4),0!=(b=a>>2)&&(a=b,c+=2),0!=(b=a>>1)&&(a=b,c+=1),c}function r(){return this.t<=0?0:this.DB*(this.t-1)+q(this[this.t-1]^this.s&this.DM)}function s(a,b){var c;for(c=this.t-1;c>=0;--c)b[c+a]=this[c];for(c=a-1;c>=0;--c)b[c]=0;b.t=this.t+a,b.s=this.s}function t(a,b){for(var c=a;c=0;--c)b[c+g+1]=this[c]>>e|h,h=(this[c]&f)<=0;--c)b[c]=0;b[g]=h,b.t=this.t+g+1,b.s=this.s,b.clamp()}function v(a,b){b.s=this.s;var c=Math.floor(a/this.DB);if(c>=this.t)return void(b.t=0);var d=a%this.DB,e=this.DB-d,f=(1<>d;for(var g=c+1;g>d;d>0&&(b[this.t-c-1]|=(this.s&f)<c;)d+=this[c]-a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t>=this.DB;d+=this.s}else{for(d+=this.s;c>=this.DB;d-=a.s}b.s=0>d?-1:0,-1>d?b[c++]=this.DV+d:d>0&&(b[c++]=d),b.t=c,b.clamp()}function x(a,b){var d=this.abs(),e=a.abs(),f=d.t;for(b.t=f+e.t;--f>=0;)b[f]=0;for(f=0;f=0;)a[c]=0;for(c=0;c=b.DV&&(a[c+b.t]-=b.DV,a[c+b.t+1]=1)}a.t>0&&(a[a.t-1]+=b.am(c,b[c],a,2*c,0,1)),a.s=0,a.clamp()}function z(a,b,e){var f=a.abs();if(!(f.t<=0)){var g=this.abs();if(g.t0?(f.lShiftTo(k,h),g.lShiftTo(k,e)):(f.copyTo(h),g.copyTo(e));var l=h.t,m=h[l-1];if(0!=m){var n=m*(1<1?h[l-2]>>this.F2:0),o=this.FV/n,p=(1<=0&&(e[e.t++]=1,e.subTo(u,e)),c.ONE.dlShiftTo(l,u),u.subTo(h,h);h.t=0;){var v=e[--s]==m?this.DM:Math.floor(e[s]*o+(e[s-1]+r)*p);if((e[s]+=h.am(0,v,e,t,0,l))0&&e.rShiftTo(k,e),0>i&&c.ZERO.subTo(e,e)}}}function A(a){var b=d();return this.abs().divRemTo(a,null,b),this.s<0&&b.compareTo(c.ZERO)>0&&a.subTo(b,b),b}function B(a){this.m=a}function C(a){return a.s<0||a.compareTo(this.m)>=0?a.mod(this.m):a}function D(a){return a}function E(a){a.divRemTo(this.m,null,a)}function F(a,b,c){a.multiplyTo(b,c),this.reduce(c)}function G(a,b){a.squareTo(b),this.reduce(b)}function H(){if(this.t<1)return 0;var a=this[0];if(0==(1&a))return 0;var b=3&a;return b=b*(2-(15&a)*b)&15,b=b*(2-(255&a)*b)&255,b=b*(2-((65535&a)*b&65535))&65535,b=b*(2-a*b%this.DV)%this.DV,b>0?this.DV-b:-b}function I(a){this.m=a,this.mp=a.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<0&&this.m.subTo(b,b),b}function K(a){var b=d();return a.copyTo(b),this.reduce(b),b}function L(a){for(;a.t<=this.mt2;)a[a.t++]=0;for(var b=0;b>15)*this.mpl&this.um)<<15)&a.DM;for(c=b+this.m.t,a[c]+=this.m.am(0,d,a,b,0,this.m.t);a[c]>=a.DV;)a[c]-=a.DV,a[++c]++}a.clamp(),a.drShiftTo(this.m.t,a),a.compareTo(this.m)>=0&&a.subTo(this.m,a)}function M(a,b){a.squareTo(b),this.reduce(b)}function N(a,b,c){a.multiplyTo(b,c),this.reduce(c)}function O(){return 0==(this.t>0?1&this[0]:this.s)}function P(a,b){if(a>4294967295||1>a)return c.ONE;var e=d(),f=d(),g=b.convert(this),h=q(a)-1;for(g.copyTo(e);--h>=0;)if(b.sqrTo(e,f),(a&1<0)b.mulTo(f,g,e);else{var i=e;e=f,f=i}return b.revert(e)}function Q(a,b){var c;return c=256>a||b.isEven()?new B(b):new I(b),this.exp(a,c)}function R(){var a=d();return this.copyTo(a),a}function S(){if(this.s<0){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<>24}function U(){return 0==this.t?this.s:this[0]<<16>>16}function V(a){return Math.floor(Math.LN2*this.DB/Math.log(a))}function W(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1}function X(a){if(null==a&&(a=10),0==this.signum()||2>a||a>36)return"0";var b=this.chunkSize(a),c=Math.pow(a,b),e=j(c),f=d(),g=d(),h="";for(this.divRemTo(e,f,g);f.signum()>0;)h=(c+g.intValue()).toString(a).substr(1)+h,f.divRemTo(e,f,g);return g.intValue().toString(a)+h}function Y(a,b){this.fromInt(0),null==b&&(b=10);for(var d=this.chunkSize(b),e=Math.pow(b,d),f=!1,h=0,i=0,j=0;jk?"-"==a.charAt(j)&&0==this.signum()&&(f=!0):(i=b*i+k,++h>=d&&(this.dMultiply(e),this.dAddOffset(i,0),h=0,i=0))}h>0&&(this.dMultiply(Math.pow(b,h)),this.dAddOffset(i,0)),f&&c.ZERO.subTo(this,this)}function Z(a,b,d){if("number"==typeof b)if(2>a)this.fromInt(1);else for(this.fromNumber(a,d),this.testBit(a-1)||this.bitwiseTo(c.ONE.shiftLeft(a-1),fb,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(c.ONE.shiftLeft(a-1),this);else{var e=new Array,f=7&a;e.length=(a>>3)+1,b.nextBytes(e),f>0?e[0]&=(1<0)for(d>d)!=(this.s&this.DM)>>d&&(b[e++]=c|this.s<=0;)8>d?(c=(this[a]&(1<>(d+=this.DB-8)):(c=this[a]>>(d-=8)&255,0>=d&&(d+=this.DB,--a)),(e>0||c!=this.s)&&(b[e++]=c);return b}function _(a){return 0==this.compareTo(a)}function ab(a){return this.compareTo(a)<0?this:a}function bb(a){return this.compareTo(a)>0?this:a}function cb(a,b,c){var d,e,f=Math.min(a.t,this.t);for(d=0;f>d;++d)c[d]=b(this[d],a[d]);if(a.ta?this.rShiftTo(-a,b):this.lShiftTo(a,b),b}function nb(a){var b=d();return 0>a?this.lShiftTo(-a,b):this.rShiftTo(a,b),b}function ob(a){if(0==a)return-1;var b=0;return 0==(65535&a)&&(a>>=16,b+=16),0==(255&a)&&(a>>=8,b+=8),0==(15&a)&&(a>>=4,b+=4),0==(3&a)&&(a>>=2,b+=2),0==(1&a)&&++b,b}function pb(){for(var a=0;a=this.t?0!=this.s:0!=(this[b]&1<c;)d+=this[c]+a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t>=this.DB;d+=this.s}else{for(d+=this.s;c>=this.DB;d+=a.s}b.s=0>d?-1:0,d>0?b[c++]=d:-1>d&&(b[c++]=this.DV+d),b.t=c,b.clamp()}function yb(a){var b=d();return this.addTo(a,b),b}function zb(a){var b=d();return this.subTo(a,b),b}function Ab(a){var b=d();return this.multiplyTo(a,b),b}function Bb(){var a=d();return this.squareTo(a),a}function Cb(a){var b=d();return this.divRemTo(a,b,null),b}function Db(a){var b=d();return this.divRemTo(a,null,b),b}function Eb(a){var b=d(),c=d();return this.divRemTo(a,b,c),new Array(b,c)}function Fb(a){this[this.t]=this.am(0,a-1,this,0,0,this.t),++this.t,this.clamp()}function Gb(a,b){if(0!=a){for(;this.t<=b;)this[this.t++]=0;for(this[b]+=a;this[b]>=this.DV;)this[b]-=this.DV,++b>=this.t&&(this[this.t++]=0),++this[b]}}function Hb(){}function Ib(a){return a}function Jb(a,b,c){a.multiplyTo(b,c)}function Kb(a,b){a.squareTo(b)}function Lb(a){return this.exp(a,new Hb)}function Mb(a,b,c){var d=Math.min(this.t+a.t,b);for(c.s=0,c.t=d;d>0;)c[--d]=0;var e;for(e=c.t-this.t;e>d;++d)c[d+this.t]=this.am(0,a[d],c,d,0,this.t);for(e=Math.min(a.t,b);e>d;++d)this.am(0,a[d],c,d,0,b-d);c.clamp()}function Nb(a,b,c){--b;var d=c.t=this.t+a.t-b;for(c.s=0;--d>=0;)c[d]=0;for(d=Math.max(b-this.t,0);d2*this.m.t)return a.mod(this.m);if(a.compareTo(this.m)<0)return a;var b=d();return a.copyTo(b),this.reduce(b),b}function Qb(a){return a}function Rb(a){for(a.drShiftTo(this.m.t-1,this.r2),a.t>this.m.t+1&&(a.t=this.m.t+1,a.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);a.compareTo(this.r2)<0;)a.dAddOffset(1,this.m.t+1);for(a.subTo(this.r2,a);a.compareTo(this.m)>=0;)a.subTo(this.m,a)}function Sb(a,b){a.squareTo(b),this.reduce(b)}function Tb(a,b,c){a.multiplyTo(b,c),this.reduce(c)}function Ub(a,b){var c,e,f=a.bitLength(),g=j(1);if(0>=f)return g;c=18>f?1:48>f?3:144>f?4:768>f?5:6,e=8>f?new B(b):b.isEven()?new Ob(b):new I(b);var h=new Array,i=3,k=c-1,l=(1<1){var m=d();for(e.sqrTo(h[1],m);l>=i;)h[i]=d(),e.mulTo(m,h[i-2],h[i]),i+=2}var n,o,p=a.t-1,r=!0,s=d();for(f=q(a[p])-1;p>=0;){for(f>=k?n=a[p]>>f-k&l:(n=(a[p]&(1<0&&(n|=a[p-1]>>this.DB+f-k)),i=c;0==(1&n);)n>>=1,--i;if((f-=i)<0&&(f+=this.DB,--p),r)h[n].copyTo(g),r=!1;else{for(;i>1;)e.sqrTo(g,s),e.sqrTo(s,g),i-=2;i>0?e.sqrTo(g,s):(o=g,g=s,s=o),e.mulTo(s,h[n],g)}for(;p>=0&&0==(a[p]&1<f)return b;for(f>e&&(f=e),f>0&&(b.rShiftTo(f,b),c.rShiftTo(f,c));b.signum()>0;)(e=b.getLowestSetBit())>0&&b.rShiftTo(e,b),(e=c.getLowestSetBit())>0&&c.rShiftTo(e,c),b.compareTo(c)>=0?(b.subTo(c,b),b.rShiftTo(1,b)):(c.subTo(b,c),c.rShiftTo(1,c));return f>0&&c.lShiftTo(f,c),c}function Wb(a){if(0>=a)return 0;var b=this.DV%a,c=this.s<0?a-1:0;if(this.t>0)if(0==b)c=this[0]%a;else for(var d=this.t-1;d>=0;--d)c=(b*c+this[d])%a;return c}function Xb(a){var b=a.isEven();if(this.isEven()&&b||0==a.signum())return c.ZERO;for(var d=a.clone(),e=this.clone(),f=j(1),g=j(0),h=j(0),i=j(1);0!=d.signum();){for(;d.isEven();)d.rShiftTo(1,d),b?(f.isEven()&&g.isEven()||(f.addTo(this,f),g.subTo(a,g)),f.rShiftTo(1,f)):g.isEven()||g.subTo(a,g),g.rShiftTo(1,g);for(;e.isEven();)e.rShiftTo(1,e),b?(h.isEven()&&i.isEven()||(h.addTo(this,h),i.subTo(a,i)),h.rShiftTo(1,h)):i.isEven()||i.subTo(a,i),i.rShiftTo(1,i);d.compareTo(e)>=0?(d.subTo(e,d),b&&f.subTo(h,f),g.subTo(i,g)):(e.subTo(d,e),b&&h.subTo(f,h),i.subTo(g,i))}return 0!=e.compareTo(c.ONE)?c.ZERO:i.compareTo(a)>=0?i.subtract(a):i.signum()<0?(i.addTo(a,i),i.signum()<0?i.add(a):i):i}function Yb(a){var b,c=this.abs();if(1==c.t&&c[0]<=gc[gc.length-1]){for(b=0;bd;)d*=gc[e++];for(d=c.modInt(d);e>b;)if(d%gc[b++]==0)return!1}return c.millerRabin(a)}function q(a){var b,c=1;return 0!=(b=a>>>16)&&(a=b,c+=16),0!=(b=a>>8)&&(a=b,c+=8),0!=(b=a>>4)&&(a=b,c+=4),0!=(b=a>>2)&&(a=b,c+=2),0!=(b=a>>1)&&(a=b,c+=1),c}function Zb(){var a=this.toByteArray(),b=8*(a.length-1)+q(a[0]),c="";return c+=String.fromCharCode((65280&b)>>8),c+=String.fromCharCode(255&b),c+=ac.bin2str(a)}function $b(a){var b=this.subtract(c.ONE),e=b.getLowestSetBit();if(0>=e)return!1;var f=b.shiftRight(e);a=a+1>>1,a>gc.length&&(a=gc.length);for(var g,h=d(),i=[],j=0;a>j;++j){for(;g=gc[Math.floor(Math.random()*gc.length)],-1!=i.indexOf(g););i.push(g),h.fromInt(g);var k=h.modPow(f,this);if(0!=k.compareTo(c.ONE)&&0!=k.compareTo(b)){for(var g=1;g++=dc;++dc)fc[cc++]=dc;for(cc="a".charCodeAt(0),dc=10;36>dc;++dc)fc[cc++]=dc;for(cc="A".charCodeAt(0),dc=10;36>dc;++dc)fc[cc++]=dc;B.prototype.convert=C,B.prototype.revert=D,B.prototype.reduce=E,B.prototype.mulTo=F,B.prototype.sqrTo=G,I.prototype.convert=J,I.prototype.revert=K,I.prototype.reduce=L,I.prototype.mulTo=N,I.prototype.sqrTo=M,c.prototype.copyTo=h,c.prototype.fromInt=i,c.prototype.fromString=k,c.prototype.clamp=l,c.prototype.dlShiftTo=s,c.prototype.drShiftTo=t,c.prototype.lShiftTo=u,c.prototype.rShiftTo=v,c.prototype.subTo=w,c.prototype.multiplyTo=x,c.prototype.squareTo=y,c.prototype.divRemTo=z,c.prototype.invDigit=H,c.prototype.isEven=O,c.prototype.exp=P,c.prototype.toString=m,c.prototype.negate=n,c.prototype.abs=o,c.prototype.compareTo=p,c.prototype.bitLength=r,c.prototype.mod=A,c.prototype.modPowInt=Q,c.ZERO=j(0),c.ONE=j(1),c.TWO=j(2),b.exports=c,Hb.prototype.convert=Ib,Hb.prototype.revert=Ib,Hb.prototype.mulTo=Jb,Hb.prototype.sqrTo=Kb,Ob.prototype.convert=Pb,Ob.prototype.revert=Qb,Ob.prototype.reduce=Rb,Ob.prototype.mulTo=Tb,Ob.prototype.sqrTo=Sb;var gc=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],hc=(1<<26)/gc[gc.length-1],c=a("./jsbn.js");c.prototype.chunkSize=V,c.prototype.toRadix=X,c.prototype.fromRadix=Y,c.prototype.fromNumber=Z,c.prototype.bitwiseTo=cb,c.prototype.changeBit=tb,c.prototype.addTo=xb,c.prototype.dMultiply=Fb,c.prototype.dAddOffset=Gb,c.prototype.multiplyLowerTo=Mb,c.prototype.multiplyUpperTo=Nb,c.prototype.modInt=Wb,c.prototype.millerRabin=$b,c.prototype.clone=R,c.prototype.intValue=S,c.prototype.byteValue=T,c.prototype.shortValue=U,c.prototype.signum=W,c.prototype.toByteArray=$,c.prototype.equals=_,c.prototype.min=ab,c.prototype.max=bb,c.prototype.and=eb,c.prototype.or=gb,c.prototype.xor=ib,c.prototype.andNot=kb,c.prototype.not=lb,c.prototype.shiftLeft=mb,c.prototype.shiftRight=nb,c.prototype.getLowestSetBit=pb,c.prototype.bitCount=rb,c.prototype.testBit=sb,c.prototype.setBit=ub,c.prototype.clearBit=vb,c.prototype.flipBit=wb,c.prototype.add=yb,c.prototype.subtract=zb,c.prototype.multiply=Ab,c.prototype.divide=Cb,c.prototype.remainder=Db,c.prototype.divideAndRemainder=Eb,c.prototype.modPow=Ub,c.prototype.modInverse=Xb,c.prototype.pow=Lb,c.prototype.gcd=Vb,c.prototype.isProbablePrime=Yb,c.prototype.toMPI=Zb,c.prototype.square=Bb -},{"../../util.js":74,"./jsbn.js":37}],38:[function(a,b){function c(){function a(a){for(var b=0;b>1;for(e.e=parseInt(b,16),e.ee=new g(b,16);;){for(;e.p=new g(a-h,1,f),0!==e.p.subtract(g.ONE).gcd(e.ee).compareTo(g.ONE)||!e.p.isProbablePrime(10););for(;e.q=new g(h,1,f),0!==e.q.subtract(g.ONE).gcd(e.ee).compareTo(g.ONE)||!e.q.isProbablePrime(10););if(e.p.compareTo(e.q)<=0){var i=e.p;e.p=e.q,e.q=i}var j=e.p.subtract(g.ONE),l=e.q.subtract(g.ONE),m=j.multiply(l);if(0===m.gcd(e.ee).compareTo(g.ONE)){e.n=e.p.multiply(e.q),e.d=e.ee.modInverse(m),e.dmp1=e.d.mod(j),e.dmq1=e.d.mod(l),e.u=e.p.modInverse(e.q);break}}d(e)})}this.encrypt=b,this.decrypt=a,this.verify=i,this.sign=f,this.generate=l,this.keyObject=k}var g=a("./jsbn.js"),h=a("../../util.js"),i=a("../random.js"),j=a("../../config"),k=g.ZERO,l=g.ZERO;b.exports=f},{"../../config":17,"../../util.js":74,"../random.js":39,"./jsbn.js":37}],39:[function(a,b){function c(){this.buffer=null,this.size=null}var d=a("../type/mpi.js"),e=null;"undefined"==typeof window&&(e=a("crypto")),b.exports={getRandomBytes:function(a){for(var b="",c=0;a>c;c++)b+=String.fromCharCode(this.getSecureRandomOctet());return b},getSecureRandom:function(a,b){for(var c=this.getSecureRandomUint(),d=(b-a).toString(2).length;(c&Math.pow(2,d)-1)>b-a;)c=this.getSecureRandomUint();return a+Math.abs(c&Math.pow(2,d)-1)},getSecureRandomOctet:function(){var a=new Uint8Array(1);return this.getRandomValues(a),a[0]},getSecureRandomUint:function(){var a=new Uint8Array(4),b=new DataView(a.buffer);return this.getRandomValues(a),b.getUint32(0)},getRandomValues:function(a){if(!(a instanceof Uint8Array))throw new Error("Invalid type: buf not an Uint8Array");if("undefined"!=typeof window&&window.crypto&&window.crypto.getRandomValues)window.crypto.getRandomValues(a);else if("undefined"!=typeof window&&"object"==typeof window.msCrypto&&"function"==typeof window.msCrypto.getRandomValues)window.msCrypto.getRandomValues(a);else if(e){var b=e.randomBytes(a.length);a.set(b)}else{if(!this.randomBuffer.buffer)throw new Error("No secure random number generator available.");this.randomBuffer.get(a)}},getRandomBigInteger:function(a){if(1>a)throw new Error("Illegal parameter value: bits < 1");var b=Math.floor((a+7)/8),c=this.getRandomBytes(b);a%8>0&&(c=String.fromCharCode(Math.pow(2,a%8)-1&c.charCodeAt(0))+c.substring(1));var e=new d;return e.fromBytes(c),e.toBigInteger()},getRandomBigIntegerInRange:function(a,b){if(b.compareTo(a)<=0)throw new Error("Illegal parameter value: max <= min");for(var c=b.subtract(a),d=this.getRandomBigInteger(c.bitLength());d>c;)d=this.getRandomBigInteger(c.bitLength());return a.add(d)},randomBuffer:new c},c.prototype.init=function(a){this.buffer=new Uint8Array(a),this.size=0},c.prototype.set=function(a){if(!this.buffer)throw new Error("RandomBuffer is not initialized");if(!(a instanceof Uint8Array))throw new Error("Invalid type: buf not an Uint8Array");var b=this.buffer.length-this.size;a.length>b&&(a=a.subarray(0,b)),this.buffer.set(a,this.size),this.size+=a.length},c.prototype.get=function(a){if(!this.buffer)throw new Error("RandomBuffer is not initialized");if(!(a instanceof Uint8Array))throw new Error("Invalid type: buf not an Uint8Array");if(this.size>16)+String.fromCharCode(b>>8&255)+String.fromCharCode(255&b);return m.encode(c)}function f(a,b){var c=e(a),d=b;return c[0]==d[0]&&c[1]==d[1]&&c[2]==d[2]&&c[3]==d[3]}function g(a){for(var b=11994318,c=0;a.length-c>16;)b=b<<8^p[255&(b>>16^a.charCodeAt(c))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+1))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+2))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+3))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+4))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+5))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+6))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+7))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+8))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+9))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+10))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+11))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+12))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+13))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+14))],b=b<<8^p[255&(b>>16^a.charCodeAt(c+15))],c+=16;for(var d=c;d>16^a.charCodeAt(c++))];return 16777215&b}function h(a){var b=/^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*\n/m,c="",d=a,e=b.exec(a);if(null===e)throw new Error("Mandatory blank line missing between armor headers and armor data");return c=a.slice(0,e.index),d=a.slice(e.index+e[0].length),c=c.split("\n"),c.pop(),{headers:c,body:d}}function i(a){for(var b=0;bd;d++)c=a.charCodeAt(d),0===h?(f+=e.charAt(c>>2&63),b=(3&c)<<4):1==h?(f+=e.charAt(b|c>>4&15),b=(15&c)<<2):2==h&&(f+=e.charAt(b|c>>6&3),g+=1,g%60===0&&(f+="\n"),f+=e.charAt(63&c)),g+=1,g%60===0&&(f+="\n"),h+=1,3==h&&(h=0);return h>0&&(f+=e.charAt(b),g+=1,g%60===0&&(f+="\n"),f+="=",g+=1),1==h&&(g%60===0&&(f+="\n"),f+="="),f}function d(a){var b,c,d="",f=0,g=0,h=a.length;for(c=0;h>c;c++)b=e.indexOf(a.charAt(c)),b>=0&&(f&&(d+=String.fromCharCode(g|b>>6-f&255)),f=f+2&7,g=b<>c,d.count++})}var e={prio:0,algo:q.encryption_cipher};for(var f in b)try{f!==o.symmetric.plaintext&&f!==o.symmetric.idea&&o.read(o.symmetric,f)&&b[f].count===a.length&&b[f].prio>e.prio&&(e=b[f])}catch(g){}return e.algo}var n=a("./packet"),o=a("./enums.js"),p=a("./encoding/armor.js"),q=a("./config"),r=a("./util");d.prototype.packetlist2structure=function(a){for(var b,c,d,e=0;ethis.primaryKey.created.getTime()+24*this.primaryKey.expirationTimeV3*3600*1e3)return o.keyStatus.expired;for(var a=!1,b=0;bthis.primaryKey.created.getTime()+1e3*c.selfCertificate.keyExpirationTime?o.keyStatus.expired:o.keyStatus.valid:o.keyStatus.invalid},d.prototype.getExpirationTime=function(){if(3==this.primaryKey.version)return g(this.primaryKey);if(4==this.primaryKey.version){var a=this.getPrimaryUser();return a?g(this.primaryKey,a.selfCertificate):null}},d.prototype.getPrimaryUser=function(){for(var a=[],b=0;bb.selfCertificate.isPrimaryUserID?-1:a.selfCertificate.isPrimaryUserIDb.selfCertificate.created?-1:a.selfCertificate.createdb?-1:b>a?1:0}),c=0;cthis.subKey.created.getTime()+24*this.subKey.expirationTimeV3*3600*1e3?o.keyStatus.expired:this.bindingSignature?this.bindingSignature.isExpired()?o.keyStatus.expired:this.bindingSignature.verified||this.bindingSignature.verify(a,{key:a,bind:this.subKey})?4==this.subKey.version&&this.bindingSignature.keyNeverExpires===!1&&Date.now()>this.subKey.created.getTime()+1e3*this.bindingSignature.keyExpirationTime?o.keyStatus.expired:o.keyStatus.valid:o.keyStatus.invalid:o.keyStatus.invalid},j.prototype.getExpirationTime=function(){return g(this.subKey,this.bindingSignature)},j.prototype.update=function(a,b){if(a.verify(b)!==o.keyStatus.invalid){if(this.subKey.getFingerprint()!==a.subKey.getFingerprint())throw new Error("SubKey update method: fingerprints of subkeys not equal"); -this.subKey.tag===o.packet.publicSubkey&&a.subKey.tag===o.packet.secretSubkey&&(this.subKey=a.subKey),!this.bindingSignature&&a.bindingSignature&&(a.bindingSignature.verified||a.bindingSignature.verify(b,{key:b,bind:this.subKey}))&&(this.bindingSignature=a.bindingSignature),this.revocationSignature||!a.revocationSignature||a.revocationSignature.isExpired()||!a.revocationSignature.verified&&!a.revocationSignature.verify(b,{key:b,bind:this.subKey})||(this.revocationSignature=a.revocationSignature)}},c.Key=d,c.readArmored=k,c.generate=l,c.getPreferredSymAlgo=m},{"./config":17,"./encoding/armor.js":41,"./enums.js":43,"./packet":53,"./util":74}],46:[function(a,b){b.exports=a("./keyring.js"),b.exports.localstore=a("./localstore.js")},{"./keyring.js":47,"./localstore.js":48}],47:[function(a,b){function c(b){this.storeHandler=b||new(a("./localstore.js")),this.publicKeys=new d(this.storeHandler.loadPublic()),this.privateKeys=new d(this.storeHandler.loadPrivate())}function d(a){this.keys=a}function e(a,b){a=a.toLowerCase();for(var c=b.getUserIds(),d=0;d")[0].trim().toLowerCase(),keyEmail==a)return!0;return!1}function f(a,b){return 16===a.length?a===b.getKeyId().toHex():a===b.getFingerprint()}{var g=(a("../enums.js"),a("../key.js"));a("../util.js")}b.exports=c,c.prototype.store=function(){this.storeHandler.storePublic(this.publicKeys.keys),this.storeHandler.storePrivate(this.privateKeys.keys)},c.prototype.clear=function(){this.publicKeys.keys=[],this.privateKeys.keys=[]},c.prototype.getKeysForId=function(a,b){var c=[];return c=c.concat(this.publicKeys.getForId(a,b)||[]),c=c.concat(this.privateKeys.getForId(a,b)||[]),c.length?c:null},c.prototype.removeKeysForId=function(a){var b=[];return b=b.concat(this.publicKeys.removeForId(a)||[]),b=b.concat(this.privateKeys.removeForId(a)||[]),b.length?b:null},c.prototype.getAllKeys=function(){return this.publicKeys.keys.concat(this.privateKeys.keys)},d.prototype.getForAddress=function(a){for(var b=[],c=0;c=0;e--){var m=new i.Signature;if(m.signatureType=g,m.hashAlgorithm=l.prefer_hash_algorithm,m.publicKeyAlgorithm=k.algorithm,!k.isDecrypted)throw new Error("Private key is not decrypted.");m.sign(k,c),b.push(m)}return new d(b)},d.prototype.verify=function(a){var b=[],c=this.unwrapCompressed(),d=c.packets.filterByTag(j.packet.literal);if(1!==d.length)throw new Error("Can only verify message with one literal data packet.");for(var e=c.packets.filterByTag(j.packet.signature),f=0;fe?(d=a.charCodeAt(0),b=1):255>e?(d=(a.charCodeAt(0)-192<<8)+a.charCodeAt(1)+192,b=2):255==e&&(d=c.readNumber(a.substr(1,4)),b=5),{len:d,offset:b}},writeSimpleLength:function(a){var b="";return 192>a?b+=String.fromCharCode(a):a>191&&8384>a?(b+=String.fromCharCode((a-192>>8)+192),b+=String.fromCharCode(a-192&255)):(b+=String.fromCharCode(255),b+=c.writeNumber(a,4)),b},writeHeader:function(a,b){var c="";return c+=String.fromCharCode(192|a),c+=this.writeSimpleLength(b)},writeOldHeader:function(a,b){var d="";return 256>b?(d+=String.fromCharCode(128|a<<2),d+=String.fromCharCode(b)):65536>b?(d+=String.fromCharCode(128|a<<2|1),d+=c.writeNumber(b,2)):(d+=String.fromCharCode(128|a<<2|2),d+=c.writeNumber(b,4)),d},read:function(a,b,d){if(null===a||a.length<=b||a.substring(b).length<2||0===(128&a.charCodeAt(b)))throw new Error("Error during parsing. This message / key is probably not containing a valid OpenPGP format.");var e,f=b,g=-1,h=-1;h=0,0!==(64&a.charCodeAt(f))&&(h=1);var i;h?g=63&a.charCodeAt(f):(g=(63&a.charCodeAt(f))>>2,i=3&a.charCodeAt(f)),f++;var j=null,k=-1;if(h)if(a.charCodeAt(f)<192)e=a.charCodeAt(f++),c.print_debug("1 byte length:"+e);else if(a.charCodeAt(f)>=192&&a.charCodeAt(f)<224)e=(a.charCodeAt(f++)-192<<8)+a.charCodeAt(f++)+192,c.print_debug("2 byte length:"+e);else if(a.charCodeAt(f)>223&&a.charCodeAt(f)<255){e=1<<(31&a.charCodeAt(f++)),c.print_debug("4 byte length:"+e);var l=f+e;j=a.substring(f,f+e);for(var m;;){if(a.charCodeAt(l)<192){m=a.charCodeAt(l++),e+=m,j+=a.substring(l,l+m),l+=m;break}if(a.charCodeAt(l)>=192&&a.charCodeAt(l)<224){m=(a.charCodeAt(l++)-192<<8)+a.charCodeAt(l++)+192,e+=m,j+=a.substring(l,l+m),l+=m;break}if(!(a.charCodeAt(l)>223&&a.charCodeAt(l)<255)){l++,m=a.charCodeAt(l++)<<24|a.charCodeAt(l++)<<16|a.charCodeAt(l++)<<8|a.charCodeAt(l++),j+=a.substring(l,l+m),e+=m,l+=m;break}m=1<<(31&a.charCodeAt(l++)),e+=m,j+=a.substring(l,l+m),l+=m}k=l-f}else f++,e=a.charCodeAt(f++)<<24|a.charCodeAt(f++)<<16|a.charCodeAt(f++)<<8|a.charCodeAt(f++);else switch(i){case 0:e=a.charCodeAt(f++);break;case 1:e=a.charCodeAt(f++)<<8|a.charCodeAt(f++);break;case 2:e=a.charCodeAt(f++)<<24|a.charCodeAt(f++)<<16|a.charCodeAt(f++)<<8|a.charCodeAt(f++);break;default:e=d}return-1==k&&(k=e),null===j&&(j=a.substring(f,f+k)),{tag:g,packet:j,offset:f+k}}}},{"../enums.js":43,"../util.js":74}],58:[function(a,b){function c(){this.length=0}b.exports=c;var d=a("./packet.js"),e=a("./all_packets.js"),f=a("../enums.js");c.prototype.read=function(a){for(var b=0;be;e++)d.push(this[e]);return d},c.prototype.concat=function(a){if(a)for(var b=0;bj&&if.length)throw new Error("Error reading MPI @:"+i);return i+6}throw new Error("Version "+this.version+" of the key packet is unsupported.")},c.prototype.readPublicKey=c.prototype.read,c.prototype.write=function(){var a=String.fromCharCode(this.version);a+=d.writeDate(this.created),3==this.version&&(a+=d.writeNumber(this.expirationTimeV3,2)),a+=String.fromCharCode(g.write(g.publicKey,this.algorithm));for(var b=h.getPublicMpiCount(this.algorithm),c=0;b>c;c++)a+=this.mpi[c].write();return a},c.prototype.writePublicKey=c.prototype.write,c.prototype.writeOld=function(){var a=this.writePublicKey();return String.fromCharCode(153)+d.writeNumber(a.length,2)+a},c.prototype.getKeyId=function(){return this.keyid?this.keyid:(this.keyid=new f,4==this.version?this.keyid.read(d.hex2bin(this.getFingerprint()).substr(12,8)):3==this.version&&this.keyid.read(this.mpi[0].write().substr(-8)),this.keyid)},c.prototype.getFingerprint=function(){if(this.fingerprint)return this.fingerprint;var a="";if(4==this.version)a=this.writeOld(),this.fingerprint=h.hash.sha1(a);else if(3==this.version){for(var b=h.getPublicMpiCount(this.algorithm),c=0;b>c;c++)a+=this.mpi[c].toBytes();this.fingerprint=h.hash.md5(a)}return this.fingerprint=d.hexstrdump(this.fingerprint),this.fingerprint},c.prototype.getBitSize=function(){return 8*this.mpi[0].byteLength()},c.prototype.postCloneTypeFix=function(){for(var a=0;ad;d++){var e=new f;b+=e.read(a.substr(b)),this.encrypted.push(e)}},c.prototype.write=function(){var a=String.fromCharCode(this.version);a+=this.publicKeyId.write(),a+=String.fromCharCode(g.write(g.publicKey,this.publicKeyAlgorithm));for(var b=0;bo&&kc;){var d=f.readSimpleLength(a.substr(c));c+=d.offset,this.read_sub_packet(a.substr(c,d.len)),c+=d.len}return c}var c=0;switch(this.version=a.charCodeAt(c++),this.version){case 3:5!=a.charCodeAt(c++)&&e.print_debug("packet/signature.js\ninvalid One-octet length of following hashed material.MUST be 5. @:"+(c-1));var d=c;this.signatureType=a.charCodeAt(c++),this.created=e.readDate(a.substr(c,4)),c+=4,this.signatureData=a.substring(d,c),this.issuerKeyId.read(a.substring(c,c+8)),c+=8,this.publicKeyAlgorithm=a.charCodeAt(c++),this.hashAlgorithm=a.charCodeAt(c++);break;case 4:this.signatureType=a.charCodeAt(c++),this.publicKeyAlgorithm=a.charCodeAt(c++),this.hashAlgorithm=a.charCodeAt(c++),c+=b.call(this,a.substr(c),!0),this.signatureData=a.substr(0,c);var g=c;c+=b.call(this,a.substr(c),!1),this.unhashedSubpackets=a.substr(g,c-g);break;default:throw new Error("Version "+this.version+" of the signature is unsupported.")}this.signedHashValue=a.substr(c,2),c+=2,this.signature=a.substr(c)},c.prototype.write=function(){var a="";switch(this.version){case 3:a+=String.fromCharCode(3),a+=String.fromCharCode(5),a+=this.signatureData,a+=this.issuerKeyId.write(),a+=String.fromCharCode(this.publicKeyAlgorithm),a+=String.fromCharCode(this.hashAlgorithm);break;case 4:a+=this.signatureData,a+=this.unhashedSubpackets?this.unhashedSubpackets:e.writeNumber(0,2)}return a+=this.signedHashValue+this.signature},c.prototype.sign=function(a,b){var c=g.write(g.signature,this.signatureType),d=g.write(g.publicKey,this.publicKeyAlgorithm),e=g.write(g.hash,this.hashAlgorithm),f=String.fromCharCode(4);f+=String.fromCharCode(c),f+=String.fromCharCode(d),f+=String.fromCharCode(e),this.issuerKeyId=a.getKeyId(),f+=this.write_all_sub_packets(),this.signatureData=f;var i=this.calculateTrailer(),j=this.toSign(c,b)+this.signatureData+i,k=h.hash.digest(e,j);this.signedHashValue=k.substr(0,2),this.signature=h.signature.sign(e,d,a.mpi,j)},c.prototype.write_all_sub_packets=function(){var a=g.signatureSubpacket,b="",c="";if(null!==this.created&&(b+=d(a.signature_creation_time,e.writeDate(this.created))),null!==this.signatureExpirationTime&&(b+=d(a.signature_expiration_time,e.writeNumber(this.signatureExpirationTime,4))),null!==this.exportable&&(b+=d(a.exportable_certification,String.fromCharCode(this.exportable?1:0))),null!==this.trustLevel&&(c=String.fromCharCode(this.trustLevel)+String.fromCharCode(this.trustAmount),b+=d(a.trust_signature,c)),null!==this.regularExpression&&(b+=d(a.regular_expression,this.regularExpression)),null!==this.revocable&&(b+=d(a.revocable,String.fromCharCode(this.revocable?1:0))),null!==this.keyExpirationTime&&(b+=d(a.key_expiration_time,e.writeNumber(this.keyExpirationTime,4))),null!==this.preferredSymmetricAlgorithms&&(c=e.bin2str(this.preferredSymmetricAlgorithms),b+=d(a.preferred_symmetric_algorithms,c)),null!==this.revocationKeyClass&&(c=String.fromCharCode(this.revocationKeyClass),c+=String.fromCharCode(this.revocationKeyAlgorithm),c+=this.revocationKeyFingerprint,b+=d(a.revocation_key,c)),this.issuerKeyId.isNull()||(b+=d(a.issuer,this.issuerKeyId.write())),null!==this.notation)for(var f in this.notation)if(this.notation.hasOwnProperty(f)){var h=this.notation[f]; -c=String.fromCharCode(128),c+=String.fromCharCode(0),c+=String.fromCharCode(0),c+=String.fromCharCode(0),c+=e.writeNumber(f.length,2),c+=e.writeNumber(h.length,2),c+=f+h,b+=d(a.notation_data,c)}return null!==this.preferredHashAlgorithms&&(c=e.bin2str(this.preferredHashAlgorithms),b+=d(a.preferred_hash_algorithms,c)),null!==this.preferredCompressionAlgorithms&&(c=e.bin2str(this.preferredCompressionAlgorithms),b+=d(a.preferred_compression_algorithms,c)),null!==this.keyServerPreferences&&(c=e.bin2str(this.keyServerPreferences),b+=d(a.key_server_preferences,c)),null!==this.preferredKeyServer&&(b+=d(a.preferred_key_server,this.preferredKeyServer)),null!==this.isPrimaryUserID&&(b+=d(a.primary_user_id,String.fromCharCode(this.isPrimaryUserID?1:0))),null!==this.policyURI&&(b+=d(a.policy_uri,this.policyURI)),null!==this.keyFlags&&(c=e.bin2str(this.keyFlags),b+=d(a.key_flags,c)),null!==this.signersUserId&&(b+=d(a.signers_user_id,this.signersUserId)),null!==this.reasonForRevocationFlag&&(c=String.fromCharCode(this.reasonForRevocationFlag),c+=this.reasonForRevocationString,b+=d(a.reason_for_revocation,c)),null!==this.features&&(c=e.bin2str(this.features),b+=d(a.features,c)),null!==this.signatureTargetPublicKeyAlgorithm&&(c=String.fromCharCode(this.signatureTargetPublicKeyAlgorithm),c+=String.fromCharCode(this.signatureTargetHashAlgorithm),c+=this.signatureTargetHash,b+=d(a.signature_target,c)),null!==this.embeddedSignature&&(b+=d(a.embedded_signature,this.embeddedSignature.write())),b=e.writeNumber(b.length,2)+b},c.prototype.read_sub_packet=function(a){function b(a,b){this[a]=[];for(var c=0;c0&&4>d?k=1:17==d&&(k=2);for(var l=[],m=0,n=0;k>n;n++)l[n]=new i,m+=l[n].read(this.signature.substr(m));return this.verified=h.signature.verify(d,e,l,a.mpi,f+this.signatureData+j),this.verified},c.prototype.isExpired=function(){return this.signatureNeverExpires?!1:Date.now()>this.created.getTime()+1e3*this.signatureExpirationTime},c.prototype.postCloneTypeFix=function(){this.issuerKeyId=j.fromClone(this.issuerKeyId)}},{"../crypto":32,"../enums.js":43,"../type/keyid.js":71,"../type/mpi.js":72,"../util.js":74,"./packet.js":57}],65:[function(a,b){function c(){this.tag=e.packet.symEncryptedIntegrityProtected,this.encrypted=null,this.modification=!1,this.packets=null}b.exports=c;var d=(a("../util.js"),a("../crypto")),e=a("../enums.js");c.prototype.read=function(a){var b=a.charCodeAt(0);if(1!=b)throw new Error("Invalid packet version.");this.encrypted=a.substr(1)},c.prototype.write=function(){return String.fromCharCode(1)+this.encrypted},c.prototype.encrypt=function(a,b){var c=this.packets.write(),e=d.getPrefixRandom(a),f=e+e.charAt(e.length-2)+e.charAt(e.length-1),g=c;g+=String.fromCharCode(211),g+=String.fromCharCode(20),g+=d.hash.sha1(f+g),this.encrypted=d.cfb.encrypt(e,a,g,b,!1).substring(0,f.length+g.length)},c.prototype.decrypt=function(a,b){var c=d.cfb.decrypt(a,b,this.encrypted,!1);this.hash=d.hash.sha1(d.cfb.mdc(a,b,this.encrypted)+c.substring(0,c.length-20));var e=c.substr(c.length-20,20);if(this.hash!=e)throw new Error("Modification detected.");this.packets.read(c.substr(0,c.length-22))}},{"../crypto":32,"../enums.js":43,"../util.js":74}],66:[function(a,b){function c(){this.tag=e.packet.symEncryptedSessionKey,this.version=4,this.sessionKeyEncryptionAlgorithm=null,this.sessionKeyAlgorithm="aes256",this.encrypted=null,this.s2k=new d}var d=a("../type/s2k.js"),e=a("../enums.js"),f=a("../crypto");b.exports=c,c.prototype.read=function(a){this.version=a.charCodeAt(0);var b=e.read(e.symmetric,a.charCodeAt(1)),c=this.s2k.read(a.substr(2)),d=c+2;d>4)+a},c.prototype.read=function(a){var b=0;switch(this.type=d.read(d.s2k,a.charCodeAt(b++)),this.algorithm=d.read(d.hash,a.charCodeAt(b++)),this.type){case"simple":break;case"salted":this.salt=a.substr(b,8),b+=8;break;case"iterated":this.salt=a.substr(b,8),b+=8,this.c=a.charCodeAt(b++);break;case"gnu":if("GNU"!=a.substr(b,3))throw new Error("Unknown s2k type.");b+=3;var c=1e3+a.charCodeAt(b++);if(1001!=c)throw new Error("Unknown s2k gnu protection mode.");this.type=c;break;default:throw new Error("Unknown s2k type.")}return b},c.prototype.write=function(){var a=String.fromCharCode(d.write(d.s2k,this.type));switch(a+=String.fromCharCode(d.write(d.hash,this.algorithm)),this.type){case"simple":break;case"salted":a+=this.salt;break;case"iterated":a+=this.salt,a+=String.fromCharCode(this.c)}return a},c.prototype.produce_key=function(a,b){function c(b,c){var e=d.write(d.hash,c.algorithm);switch(c.type){case"simple":return f.hash.digest(e,b+a);case"salted":return f.hash.digest(e,b+c.salt+a);case"iterated":var g=[],h=c.get_count();for(data=c.salt+a;g.length*data.lengthh&&(g=g.substr(0,h)),f.hash.digest(e,b+g)}}a=e.encode_utf8(a);for(var g="",h="";g.length<=b;)g+=c(h,this),h+=String.fromCharCode(0);return g.substr(0,b)},b.exports.fromClone=function(a){var b=new c;return this.algorithm=a.algorithm,this.type=a.type,this.c=a.c,this.salt=a.salt,b}},{"../crypto":32,"../enums.js":43,"../util.js":74}],74:[function(a,b){"use strict";var c=a("./config");b.exports={readNumber:function(a){for(var b=0,c=0;cd;d++)c+=String.fromCharCode(a>>8*(b-d-1)&255);return c},readDate:function(a){var b=this.readNumber(a),c=new Date;return c.setTime(1e3*b),c},writeDate:function(a){var b=Math.round(a.getTime()/1e3);return this.writeNumber(b,4)},emailRegEx:/^[+a-zA-Z0-9_.-]+@([a-zA-Z0-9-]+\.)+[a-zA-Z0-9]{2,6}$/,hexdump:function(a){for(var b,c=[],d=a.length,e=0,f=0;d>e;){for(b=a.charCodeAt(e++).toString(16);b.length<2;)b="0"+b;c.push(" "+b),f++,f%32===0&&c.push("\n ")}return c.join("")},hexstrdump:function(a){if(null===a)return"";for(var b,c=[],d=a.length,e=0;d>e;){for(b=a.charCodeAt(e++).toString(16);b.length<2;)b="0"+b;c.push(""+b)}return c.join("")},hex2bin:function(a){for(var b="",c=0;ce;){for(b=a[e++].toString(16);b.length<2;)b="0"+b;c.push(""+b)}return c.join("")},encode_utf8:function(a){return unescape(encodeURIComponent(a))},decode_utf8:function(a){if("string"!=typeof a)throw new Error('Parameter "utf8" is not of type string');try{return decodeURIComponent(escape(a))}catch(b){return a}},bin2str:function(a){for(var b=[],c=0;c=0;d--)c[d]>>=b%8,d>0&&(c[d]|=c[d-1]<<8-b%8&255);return util.bin2str(c)},get_hashAlgorithmString:function(a){switch(a){case 1:return"MD5";case 2:return"SHA1";case 3:return"RIPEMD160";case 8:return"SHA256";case 9:return"SHA384";case 10:return"SHA512";case 11:return"SHA224"}return"unknown"},getWebCrypto:function(){return c.useWebCrypto!==!1&&"undefined"!=typeof window&&window.crypto&&window.crypto.subtle?window.crypto.subtle:void 0}}},{"./config":17}],75:[function(a,b){"use strict";function c(a){this.worker=new Worker(a||"openpgp.worker.js"),this.worker.onmessage=this.onMessage.bind(this),this.worker.onerror=function(a){throw new Error("Unhandled error in openpgp worker: "+a.message+" ("+a.filename+":"+a.lineno+")")},this.seedRandom(h),this.tasks=[]}var d=a("../crypto"),e=a("../packet"),f=a("../key.js"),g=a("../type/keyid.js"),h=5e4,i=2e4;c.prototype.execute=function(a){var b=this,c=new Promise(function(c,d){a(),b.tasks.push({resolve:c,reject:d})});return c},c.prototype.onMessage=function(a){var b=a.data;switch(b.event){case"method-return":b.err?this.tasks.shift().reject(new Error(b.err)):this.tasks.shift().resolve(b.data);break;case"request-seed":this.seedRandom(i);break;default:throw new Error("Unknown Worker Event.")}},c.prototype.seedRandom=function(a){var b=this.getRandomBuffer(a);this.worker.postMessage({event:"seed-random",buf:b})},c.prototype.getRandomBuffer=function(a){if(!a)return null;var b=new Uint8Array(a);return d.random.getRandomValues(b),b},c.prototype.terminate=function(){this.worker.terminate()},c.prototype.encryptMessage=function(a,b){var c=this;return c.execute(function(){a.length||(a=[a]),a=a.map(function(a){return a.toPacketlist()}),c.worker.postMessage({event:"encrypt-message",keys:a,text:b})})},c.prototype.signAndEncryptMessage=function(a,b,c){var d=this;return d.execute(function(){a.length||(a=[a]),a=a.map(function(a){return a.toPacketlist()}),b=b.toPacketlist(),d.worker.postMessage({event:"sign-and-encrypt-message",publicKeys:a,privateKey:b,text:c})})},c.prototype.decryptMessage=function(a,b){var c=this;return c.execute(function(){a=a.toPacketlist(),c.worker.postMessage({event:"decrypt-message",privateKey:a,message:b})})},c.prototype.decryptAndVerifyMessage=function(a,b,c){var d=this,e=new Promise(function(e,f){a=a.toPacketlist(),b.length||(b=[b]),b=b.map(function(a){return a.toPacketlist()}),d.worker.postMessage({event:"decrypt-and-verify-message",privateKey:a,publicKeys:b,message:c}),d.tasks.push({resolve:function(a){a.signatures=a.signatures.map(function(a){return a.keyid=g.fromClone(a.keyid),a}),e(a)},reject:f})});return e},c.prototype.signClearMessage=function(a,b){var c=this;return c.execute(function(){a.length||(a=[a]),a=a.map(function(a){return a.toPacketlist()}),c.worker.postMessage({event:"sign-clear-message",privateKeys:a,text:b})})},c.prototype.verifyClearSignedMessage=function(a,b){var c=this,d=new Promise(function(d,e){a.length||(a=[a]),a=a.map(function(a){return a.toPacketlist()}),c.worker.postMessage({event:"verify-clear-signed-message",publicKeys:a,message:b}),c.tasks.push({resolve:function(a){a.signatures=a.signatures.map(function(a){return a.keyid=g.fromClone(a.keyid),a}),d(a)},reject:e})});return d},c.prototype.generateKeyPair=function(a){var b=this,c=new Promise(function(c,d){b.worker.postMessage({event:"generate-key-pair",options:a}),b.tasks.push({resolve:function(a){var b=e.List.fromStructuredClone(a.key);a.key=new f.Key(b),c(a)},reject:d})});return c},c.prototype.decryptKey=function(a,b){var c=this,d=new Promise(function(d,g){a=a.toPacketlist(),c.worker.postMessage({event:"decrypt-key",privateKey:a,password:b}),c.tasks.push({resolve:function(a){var b=e.List.fromStructuredClone(a);a=new f.Key(b),d(a)},reject:g})});return d},c.prototype.decryptKeyPacket=function(a,b,c){var d=this,g=new Promise(function(g,h){a=a.toPacketlist(),d.worker.postMessage({event:"decrypt-key-packet",privateKey:a,keyIds:b,password:c}),d.tasks.push({resolve:function(a){var b=e.List.fromStructuredClone(a);a=new f.Key(b),g(a)},reject:h})});return g},b.exports=c},{"../crypto":32,"../key.js":45,"../packet":53,"../type/keyid.js":71}]},{},[44])(44)}); \ No newline at end of file diff --git a/vendors/progress.js/LICENSE b/vendors/progress.js/LICENSE new file mode 100644 index 000000000..5d0d36c67 --- /dev/null +++ b/vendors/progress.js/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Afshin Mehrabani (afshin.meh@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendors/progress.js/README.md b/vendors/progress.js/README.md new file mode 100644 index 000000000..d58950751 --- /dev/null +++ b/vendors/progress.js/README.md @@ -0,0 +1,65 @@ +# ProgressJS + +> ProgressJs is a JavaScript and CSS3 library which helps developers create and manage progress bars for every object on the page. + +## How To Use + +1) Include `progress.js` and `progressjs.css` in the page (use the minified version from `minified` folder for production) + +2) Execute the following JavaScript code in the page: + +```javascript +//to set progress-bar for whole page +progressJs().start(); +//or for specific element +progressJs("#targetElement").start(); +``` + + +Use other methods to increase, decrease or set an auto-increase function for your progress-bar. Furthermore, you can change the template using `setOption` method. + +## API + +Check the API and method usage with example here: https://github.com/usablica/progress.js/wiki/API + +## Build + +First, you should install `nodejs` and `npm`, then run this command: `npm install` to install all dependencies. + +Now you can run this command to minify all the static resources: + + make build + +## Roadmap +- Add `example` folder and provide examples +- More browser compatibility + mobile/tablet device support +- Add more templates + +## Release History + * **v0.1.0** - 2014-02-14 + - First version + - Increase, decrease and auto-increase functions + - Ability to design and add templates + +## Author +**Afshin Mehrabani** + +- [Twitter](https://twitter.com/afshinmeh) +- [Github](https://github.com/afshinm) +- [Personal page](http://afshinm.name/) + +## License +> Copyright (C) 2012 Afshin Mehrabani (afshin.meh@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/vendors/progress.js/minified/progress.min.js b/vendors/progress.js/minified/progress.min.js new file mode 100644 index 000000000..f7c5b41be --- /dev/null +++ b/vendors/progress.js/minified/progress.min.js @@ -0,0 +1,11 @@ +(function(l,e){"object"===typeof exports?e(exports):"function"===typeof define&&define.amd?define(["exports"],e):e(l)})(this,function(l){function e(a){this._targetElement="undefined"!=typeof a.length?a:[a];"undefined"===typeof window._progressjsId&&(window._progressjsId=1);"undefined"===typeof window._progressjsIntervals&&(window._progressjsIntervals={});this._options={theme:"blue",overlayMode:!1,considerTransition:!0}}function m(a,c){var d=this;100<=c&&(c=100);a.hasAttribute("data-progressjs")&& +setTimeout(function(){"undefined"!=typeof d._onProgressCallback&&d._onProgressCallback.call(d,a,c);var b=h(a);b.style.width=parseInt(c)+"%";var b=b.querySelector(".progressjs-percent"),g=parseInt(b.innerHTML.replace("%","")),e=parseInt(c),j=function(a,b,c){var d=Math.abs(b-c);3>d?k=30:20>d?k=20:intervanIn=1;0!=b-c&&(a.innerHTML=(f?++b:--b)+"%",setTimeout(function(){j(a,b,c)},k))},f=!0;g>e&&(f=!1);var k=10;j(b,g,e)},50)}function h(a){a=parseInt(a.getAttribute("data-progressjs"));return document.querySelector('.progressjs-container > .progressjs-progress[data-progressjs="'+ +a+'"] > .progressjs-inner')}function p(a){for(var c=0,d=this._targetElement.length;cparseInt(e.style.width.replace("%",""))&&(m.call(this,b,100),l=500);(function(a,b){setTimeout(function(){a.parentNode.className+=" progressjs-end";setTimeout(function(){a.parentNode.parentNode.removeChild(a.parentNode);b.removeAttribute("data-progressjs")},1E3)},l)})(e,b)}if(window._progressjsIntervals[a])try{clearInterval(window._progressjsIntervals[a]),window._progressjsIntervals[a]=null,delete window._progressjsIntervals[a]}catch(j){}}return this}, +onbeforeend:function(a){if("function"===typeof a)this._onBeforeEndCallback=a;else throw Error("Provided callback for onbeforeend was not a function");return this},onbeforestart:function(a){if("function"===typeof a)this._onBeforeStartCallback=a;else throw Error("Provided callback for onbeforestart was not a function");return this},onprogress:function(a){if("function"===typeof a)this._onProgressCallback=a;else throw Error("Provided callback for onprogress was not a function");return this}};return l.progressJs= +n}); diff --git a/vendors/progress.js/minified/progressjs.min.css b/vendors/progress.js/minified/progressjs.min.css new file mode 100644 index 000000000..9ac739e84 --- /dev/null +++ b/vendors/progress.js/minified/progressjs.min.css @@ -0,0 +1 @@ +.progressjs-inner{width:0}.progressjs-progress{z-index:9999999}.progressjs-theme-blue .progressjs-inner{height:2px;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#3498db}.progressjs-theme-blue.progressjs-end{-webkit-transition:opacity .2s ease-out;-moz-transition:opacity .2s ease-out;-o-transition:opacity .2s ease-out;transition:opacity .2s ease-out;opacity:0}.progressjs-theme-blue .progressjs-percent{display:none}.progressjs-theme-blueOverlay{background-color:white;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}.progressjs-theme-blueOverlay .progressjs-inner{height:100%;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#3498db}.progressjs-theme-blueOverlay.progressjs-end{opacity:0!important}.progressjs-theme-blueOverlay .progressjs-percent{display:none}.progressjs-theme-blueOverlay{background-color:white;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}.progressjs-theme-blueOverlay .progressjs-inner{height:100%;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#3498db}.progressjs-theme-blueOverlay.progressjs-end{opacity:0!important}.progressjs-theme-blueOverlay .progressjs-percent{display:none}.progressjs-theme-blueOverlayRadius{background-color:white;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out;border-radius:5px}.progressjs-theme-blueOverlayRadius .progressjs-inner{height:100%;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#3498db;border-radius:5px}.progressjs-theme-blueOverlayRadius.progressjs-end{opacity:0!important}.progressjs-theme-blueOverlayRadius .progressjs-percent{display:none}.progressjs-theme-blueOverlayRadiusHalfOpacity{background-color:white;opacity:.5;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out;border-radius:5px}.progressjs-theme-blueOverlayRadiusHalfOpacity .progressjs-inner{height:100%;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#3498db;border-radius:5px}.progressjs-theme-blueOverlayRadiusHalfOpacity.progressjs-end{opacity:0!important}.progressjs-theme-blueOverlayRadiusHalfOpacity .progressjs-percent{display:none}.progressjs-theme-blueOverlayRadiusWithPercentBar{background-color:white;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out;border-radius:5px}.progressjs-theme-blueOverlayRadiusWithPercentBar .progressjs-inner{height:100%;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#3498db;border-radius:5px}.progressjs-theme-blueOverlayRadiusWithPercentBar.progressjs-end{opacity:0!important}.progressjs-theme-blueOverlayRadiusWithPercentBar .progressjs-percent{width:70px;text-align:center;height:40px;position:absolute;right:50%;margin-right:-35px;top:50%;margin-top:-20px;font-size:30px;opacity:.5}.progressjs-theme-blackRadiusInputs{height:10px;border-radius:10px;overflow:hidden}.progressjs-theme-blackRadiusInputs .progressjs-inner{height:2px;-webkit-transition:all 1s ease-out;-moz-transition:all 1s ease-out;-o-transition:all 1s ease-out;transition:all 1s ease-out;background-color:#34495e}.progressjs-theme-blackRadiusInputs.progressjs-end{-webkit-transition:opacity .2s ease-out;-moz-transition:opacity .2s ease-out;-o-transition:opacity .2s ease-out;transition:opacity .2s ease-out;opacity:0}.progressjs-theme-blackRadiusInputs .progressjs-percent{display:none} \ No newline at end of file diff --git a/vendors/progress.js/minified/progressjs.rainloop.css b/vendors/progress.js/minified/progressjs.rainloop.css new file mode 100644 index 000000000..ddc78a941 --- /dev/null +++ b/vendors/progress.js/minified/progressjs.rainloop.css @@ -0,0 +1,62 @@ +.progressjs-theme-rainloop { + z-index: 2000; +} + +.progressjs-theme-rainloop .progressjs-inner { + + background-color: #939595; + position: relative; + z-index: 2000; + height: 3px; + overflow: hidden; + + -webkit-transition: width .5s; + -moz-transition: width .5s; + -o-transition: width .5s; + transition: width .5s; +} + +.progressjs-theme-rainloop .progressjs-percent { + position: absolute; + top: 0; + left: 0; + right: -32px; + bottom: 0; + + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.3)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.3)), color-stop(0.75, rgba(255, 255, 255, 0.3)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.3) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0.3) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.3) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0.3) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.3) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0.3) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.3) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0.3) 75%, transparent 75%, transparent); + -webkit-background-size: 32px 32px; + -moz-background-size: 32px 32px; + -o-background-size: 32px 32px; + background-size: 32px 32px; + + -webkit-animation: simple-pace-stripe-animation 500ms linear infinite; + -moz-animation: simple-pace-stripe-animation 500ms linear infinite; + -ms-animation: simple-pace-stripe-animation 500ms linear infinite; + -o-animation: simple-pace-stripe-animation 500ms linear infinite; + animation: simple-pace-stripe-animation 500ms linear infinite; +} + +@-webkit-keyframes simple-pace-stripe-animation { + 0% { -webkit-transform: none; transform: none; } + 100% { -webkit-transform: translate(-32px, 0); transform: translate(-32px, 0); } +} +@-moz-keyframes simple-pace-stripe-animation { + 0% { -moz-transform: none; transform: none; } + 100% { -moz-transform: translate(-32px, 0); transform: translate(-32px, 0); } +} +@-o-keyframes simple-pace-stripe-animation { + 0% { -o-transform: none; transform: none; } + 100% { -o-transform: translate(-32px, 0); transform: translate(-32px, 0); } +} +@-ms-keyframes simple-pace-stripe-animation { + 0% { -ms-transform: none; transform: none; } + 100% { -ms-transform: translate(-32px, 0); transform: translate(-32px, 0); } +} +@keyframes simple-pace-stripe-animation { + 0% { transform: none; transform: none; } + 100% { transform: translate(-32px, 0); transform: translate(-32px, 0); } +} \ No newline at end of file diff --git a/vendors/progress.js/package.json b/vendors/progress.js/package.json new file mode 100644 index 000000000..4172afc9c --- /dev/null +++ b/vendors/progress.js/package.json @@ -0,0 +1,17 @@ +{ + "name": "Progress.js", + "description": "Themeable HTML5 progress bar library", + "version": "0.1.0", + "author": "Afshin Mehrabani ", + "repository": { + "type": "git", + "url": "https://github.com/usablica/progress.js" + }, + "devDependencies": { + "node-minify": "*" + }, + "engine": [ + "node >=0.1.90" + ], + "main": "src/progress.js" +} \ No newline at end of file diff --git a/vendors/progress.js/src/progress.js b/vendors/progress.js/src/progress.js new file mode 100644 index 000000000..40f50f37f --- /dev/null +++ b/vendors/progress.js/src/progress.js @@ -0,0 +1,574 @@ +/** + * Progress.js v0.1.0 + * https://github.com/usablica/progress.js + * MIT licensed + * + * Copyright (C) 2013 usabli.ca - Afshin Mehrabani (@afshinmeh) + */ + +(function (root, factory) { + if (typeof exports === 'object') { + // CommonJS + factory(exports); + } else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['exports'], factory); + } else { + // Browser globals + factory(root); + } +} (this, function (exports) { + //Default config/variables + var VERSION = '0.1.0'; + + /** + * ProgressJs main class + * + * @class ProgressJs + */ + function ProgressJs(obj) { + + if (typeof obj.length != 'undefined') { + this._targetElement = obj; + } else { + this._targetElement = [obj]; + } + + if (typeof window._progressjsId === 'undefined') + window._progressjsId = 1; + + if (typeof window._progressjsIntervals === 'undefined') + window._progressjsIntervals = {}; + + this._options = { + //progress bar theme + theme: 'blue', + //overlay mode makes an overlay layer in the target element + overlayMode: false, + //to consider CSS3 transitions in events + considerTransition: true + }; + } + + /** + * Start progress for specific element(s) + * + * @api private + * @method _createContainer + */ + function _startProgress() { + + //call onBeforeStart callback + if (typeof this._onBeforeStartCallback != 'undefined') { + this._onBeforeStartCallback.call(this); + } + + //create the container for progress bar + _createContainer.call(this); + + for (var i = 0, elmsLength = this._targetElement.length; i < elmsLength; i++) { + _setProgress.call(this, this._targetElement[i]); + } + } + + /** + * Set progress bar for specific element + * + * @api private + * @method _setProgress + * @param {Object} targetElement + */ + function _setProgress(targetElement) { + + //if the target element already as `data-progressjs`, ignore the init + if (targetElement.hasAttribute("data-progressjs")) + return; + + //get target element position + var targetElementOffset = _getOffset.call(this, targetElement); + + targetElement.setAttribute("data-progressjs", window._progressjsId); + + var progressElementContainer = document.createElement('div'); + progressElementContainer.className = 'progressjs-progress progressjs-theme-' + this._options.theme; + + + //set the position percent elements, it depends on targetElement tag + if (targetElement.tagName.toLowerCase() === 'body') { + progressElementContainer.style.position = 'fixed'; + } else { + progressElementContainer.style.position = 'absolute'; + } + + progressElementContainer.setAttribute("data-progressjs", window._progressjsId); + var progressElement = document.createElement("div"); + progressElement.className = "progressjs-inner"; + + //create an element for current percent of progress bar + var progressPercentElement = document.createElement('div'); + progressPercentElement.className = "progressjs-percent"; + progressPercentElement.innerHTML = "1%"; + + progressElement.appendChild(progressPercentElement); + + if (this._options.overlayMode && targetElement.tagName.toLowerCase() === 'body') { + //if we have `body` for target element and also overlay mode is enable, we should use a different + //position for progress bar container element + progressElementContainer.style.left = 0; + progressElementContainer.style.right = 0; + progressElementContainer.style.top = 0; + progressElementContainer.style.bottom = 0; + } else { + //set progress bar container size and offset + progressElementContainer.style.left = targetElementOffset.left + 'px'; + progressElementContainer.style.top = targetElementOffset.top + 'px'; + //if targetElement is body set to percent so it scales with browser resize + if (targetElement.nodeName == 'BODY') { + progressElementContainer.style.width = '100%'; + } else { + progressElementContainer.style.width = targetElementOffset.width + 'px'; + } + + if (this._options.overlayMode) { + progressElementContainer.style.height = targetElementOffset.height + 'px'; + } + } + + progressElementContainer.appendChild(progressElement); + + //append the element to container + var container = document.querySelector('.progressjs-container'); + container.appendChild(progressElementContainer); + + _setPercentFor(targetElement, 1); + + //and increase the progressId + ++window._progressjsId; + } + + /** + * Set percent for all elements + * + * @api private + * @method _setPercent + * @param {Number} percent + */ + function _setPercent(percent) { + for (var i = 0, elmsLength = this._targetElement.length; i < elmsLength; i++) { + _setPercentFor.call(this, this._targetElement[i], percent); + } + } + + /** + * Set percent for specific element + * + * @api private + * @method _setPercentFor + * @param {Object} targetElement + * @param {Number} percent + */ + function _setPercentFor(targetElement, percent) { + var self = this; + + //prevent overflow! + if (percent >= 100) + percent = 100; + + if (targetElement.hasAttribute("data-progressjs")) { + //setTimeout for better CSS3 animation applying in some cases + setTimeout(function() { + + //call the onprogress callback + if (typeof self._onProgressCallback != 'undefined') { + self._onProgressCallback.call(self, targetElement, percent); + } + + var percentElement = _getPercentElement(targetElement); + percentElement.style.width = parseInt(percent) + '%'; + + var percentElement = percentElement.querySelector(".progressjs-percent"); + var existingPercent = parseInt(percentElement.innerHTML.replace('%', '')); + + //start increase/decrease the percent element with animation + (function(percentElement, existingPercent, currentPercent) { + + var increasement = true; + if (existingPercent > currentPercent) { + increasement = false; + } + + var intervalIn = 10; + function changePercentTimer(percentElement, existingPercent, currentPercent) { + //calculate the distance between two percents + var distance = Math.abs(existingPercent - currentPercent); + if (distance < 3) { + intervalIn = 30; + } else if (distance < 20) { + intervalIn = 20; + } else { + intervanIn = 1; + } + + if ((existingPercent - currentPercent) != 0) { + //set the percent + percentElement.innerHTML = (increasement ? (++existingPercent) : (--existingPercent)) + '%'; + setTimeout(function() { changePercentTimer(percentElement, existingPercent, currentPercent); }, intervalIn); + } + } + + changePercentTimer(percentElement, existingPercent, currentPercent); + + })(percentElement, existingPercent, parseInt(percent)); + + }, 50); + } + } + + /** + * Get the progress bar element + * + * @api private + * @method _getPercentElement + * @param {Object} targetElement + */ + function _getPercentElement(targetElement) { + var progressjsId = parseInt(targetElement.getAttribute('data-progressjs')); + return document.querySelector('.progressjs-container > .progressjs-progress[data-progressjs="' + progressjsId + '"] > .progressjs-inner'); + } + + /** + * Auto increase the progress bar every X milliseconds + * + * @api private + * @method _autoIncrease + * @param {Number} size + * @param {Number} millisecond + */ + function _autoIncrease(size, millisecond) { + var self = this; + + var target = this._targetElement[0]; + if(!target) return; + var progressjsId = parseInt(target.getAttribute('data-progressjs')); + + if (typeof window._progressjsIntervals[progressjsId] != 'undefined') { + clearInterval(window._progressjsIntervals[progressjsId]); + } + window._progressjsIntervals[progressjsId] = setInterval(function() { + _increasePercent.call(self, size); + }, millisecond); + } + + /** + * Increase the size of progress bar + * + * @api private + * @method _increasePercent + * @param {Number} size + */ + function _increasePercent(size) { + for (var i = 0, elmsLength = this._targetElement.length; i < elmsLength; i++) { + var currentElement = this._targetElement[i]; + if (currentElement.hasAttribute('data-progressjs')) { + var percentElement = _getPercentElement(currentElement); + var existingPercent = parseInt(percentElement.style.width.replace('%', '')); + if (existingPercent) { + _setPercentFor.call(this, currentElement, existingPercent + (size || 1)); + } + } + } + } + + /** + * Close and remove progress bar + * + * @api private + * @method _end + */ + function _end() { + + //call onBeforeEnd callback + if (typeof this._onBeforeEndCallback != 'undefined') { + if (this._options.considerTransition === true) { + //we can safety assume that all layers would be the same, so `this._targetElement[0]` is the same as `this._targetElement[1]` + _getPercentElement(this._targetElement[0]).addEventListener(whichTransitionEvent(), this._onBeforeEndCallback, false); + } else { + this._onBeforeEndCallback.call(this); + } + } + + var target = this._targetElement[0]; + if(!target) return; + var progressjsId = parseInt(target.getAttribute('data-progressjs')); + + for (var i = 0, elmsLength = this._targetElement.length; i < elmsLength; i++) { + var currentElement = this._targetElement[i]; + var percentElement = _getPercentElement(currentElement); + + if (!percentElement) + return; + + var existingPercent = parseInt(percentElement.style.width.replace('%', '')); + + var timeoutSec = 1; + if (existingPercent < 100) { + _setPercentFor.call(this, currentElement, 100); + timeoutSec = 500; + } + + //I believe I should handle this situation with eventListener and `transitionend` event but I'm not sure + //about compatibility with IEs. Should be fixed in further versions. + (function(percentElement, currentElement) { + setTimeout(function() { + percentElement.parentNode.className += " progressjs-end"; + + setTimeout(function() { + //remove the percent element from page + percentElement.parentNode.parentNode.removeChild(percentElement.parentNode); + //and remove the attribute + currentElement.removeAttribute("data-progressjs"); + }, 1000); + }, timeoutSec); + })(percentElement, currentElement); + } + + //clean the setInterval for autoIncrease function + if (window._progressjsIntervals[progressjsId]) { + //`delete` keyword has some problems in IE + try { + clearInterval(window._progressjsIntervals[progressjsId]); + window._progressjsIntervals[progressjsId] = null; + delete window._progressjsIntervals[progressjsId]; + } catch(ex) { } + } + } + + /** + * Remove progress bar without finishing + * + * @api private + * @method _kill + */ + function _kill() { + var target = this._targetElement[0]; + if(!target) return; + var progressjsId = parseInt(target.getAttribute('data-progressjs')); + + for (var i = 0, elmsLength = this._targetElement.length; i < elmsLength; i++) { + var currentElement = this._targetElement[i]; + var percentElement = _getPercentElement(currentElement); + + if (!percentElement) + return; + + //I believe I should handle this situation with eventListener and `transitionend` event but I'm not sure + //about compatibility with IEs. Should be fixed in further versions. + (function(percentElement, currentElement) { + percentElement.parentNode.className += " progressjs-end"; + + setTimeout(function() { + //remove the percent element from page + percentElement.parentNode.parentNode.removeChild(percentElement.parentNode); + //and remove the attribute + currentElement.removeAttribute("data-progressjs"); + }, 1000); + })(percentElement, currentElement); + } + + //clean the setInterval for autoIncrease function + if (window._progressjsIntervals[progressjsId]) { + //`delete` keyword has some problems in IE + try { + clearInterval(window._progressjsIntervals[progressjsId]); + window._progressjsIntervals[progressjsId] = null; + delete window._progressjsIntervals[progressjsId]; + } catch(ex) { } + } + } + + /** + * Create the progress bar container + * + * @api private + * @method _createContainer + */ + function _createContainer() { + //first check if we have an container already, we don't need to create it again + if (!document.querySelector(".progressjs-container")) { + var containerElement = document.createElement("div"); + containerElement.className = "progressjs-container"; + document.body.appendChild(containerElement); + } + } + + /** + * Get an element position on the page + * Thanks to `meouw`: http://stackoverflow.com/a/442474/375966 + * + * @api private + * @method _getOffset + * @param {Object} element + * @returns Element's position info + */ + function _getOffset(element) { + var elementPosition = {}; + + if (element.tagName.toLowerCase() === 'body') { + //set width + elementPosition.width = element.clientWidth; + //set height + elementPosition.height = element.clientHeight; + } else { + //set width + elementPosition.width = element.offsetWidth; + //set height + elementPosition.height = element.offsetHeight; + } + + //calculate element top and left + var _x = 0; + var _y = 0; + while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) { + _x += element.offsetLeft; + _y += element.offsetTop; + element = element.offsetParent; + } + //set top + elementPosition.top = _y; + //set left + elementPosition.left = _x; + + return elementPosition; + } + + /** + * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1 + * via: http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically + * + * @param obj1 + * @param obj2 + * @returns obj3 a new object based on obj1 and obj2 + */ + function _mergeOptions(obj1, obj2) { + var obj3 = {}; + for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; } + for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; } + return obj3; + } + + var progressJs = function (targetElm) { + if (typeof (targetElm) === 'object') { + //Ok, create a new instance + return new ProgressJs(targetElm); + + } else if (typeof (targetElm) === 'string') { + //select the target element with query selector + var targetElement = document.querySelectorAll(targetElm); + + if (targetElement) { + return new ProgressJs(targetElement); + } else { + throw new Error('There is no element with given selector.'); + } + } else { + return new ProgressJs(document.body); + } + }; + + /** + * Get correct transition callback + * Thanks @webinista: http://stackoverflow.com/a/9090128/375966 + * + * @returns transition name + */ + function whichTransitionEvent() { + var t; + var el = document.createElement('fakeelement'); + var transitions = { + 'transition': 'transitionend', + 'OTransition': 'oTransitionEnd', + 'MozTransition': 'transitionend', + 'WebkitTransition': 'webkitTransitionEnd' + } + + for (t in transitions) { + if (el.style[t] !== undefined) { + return transitions[t]; + } + } + } + + /** + * Current ProgressJs version + * + * @property version + * @type String + */ + progressJs.version = VERSION; + + //Prototype + progressJs.fn = ProgressJs.prototype = { + clone: function () { + return new ProgressJs(this); + }, + setOption: function(option, value) { + this._options[option] = value; + return this; + }, + setOptions: function(options) { + this._options = _mergeOptions(this._options, options); + return this; + }, + start: function() { + _startProgress.call(this); + return this; + }, + set: function(percent) { + _setPercent.call(this, percent); + return this; + }, + increase: function(size) { + _increasePercent.call(this, size); + return this; + }, + autoIncrease: function(size, millisecond) { + _autoIncrease.call(this, size, millisecond); + return this; + }, + end: function() { + _end.call(this); + return this; + }, + kill: function() { + _kill.call(this); + return this; + }, + onbeforeend: function(providedCallback) { + if (typeof (providedCallback) === 'function') { + this._onBeforeEndCallback = providedCallback; + } else { + throw new Error('Provided callback for onbeforeend was not a function'); + } + return this; + }, + onbeforestart: function(providedCallback) { + if (typeof (providedCallback) === 'function') { + this._onBeforeStartCallback = providedCallback; + } else { + throw new Error('Provided callback for onbeforestart was not a function'); + } + return this; + }, + onprogress: function(providedCallback) { + if (typeof (providedCallback) === 'function') { + this._onProgressCallback = providedCallback; + } else { + throw new Error('Provided callback for onprogress was not a function'); + } + return this; + } + }; + + exports.progressJs = progressJs; + return progressJs; +})); diff --git a/vendors/progress.js/src/progressjs.css b/vendors/progress.js/src/progressjs.css new file mode 100644 index 000000000..892bd6fbd --- /dev/null +++ b/vendors/progress.js/src/progressjs.css @@ -0,0 +1,181 @@ +.progressjs-inner { + width: 0; +} +.progressjs-progress { + z-index: 9999999; +} + +/* blue theme, like iOS 7 progress bar */ +.progressjs-theme-blue .progressjs-inner { + height: 2px; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; + background-color: #3498db; +} +.progressjs-theme-blue.progressjs-end { + -webkit-transition: opacity 0.2s ease-out; + -moz-transition: opacity 0.2s ease-out; + -o-transition: opacity 0.2s ease-out; + transition: opacity 0.2s ease-out; + opacity: 0; +} +.progressjs-theme-blue .progressjs-percent { + display: none; +} + +/* blue theme with overlay layer, no percent bar */ +.progressjs-theme-blueOverlay { + background-color: white; + -webkit-transition: all 0.2s ease-out; + -moz-transition: all 0.2s ease-out; + -o-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; +} +.progressjs-theme-blueOverlay .progressjs-inner { + height: 100%; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; + background-color: #3498db; +} +.progressjs-theme-blueOverlay.progressjs-end { + opacity: 0 !important; +} +.progressjs-theme-blueOverlay .progressjs-percent { + display: none; +} + +/* blue theme with overlay layer, no percent bar */ +.progressjs-theme-blueOverlay { + background-color: white; + -webkit-transition: all 0.2s ease-out; + -moz-transition: all 0.2s ease-out; + -o-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; +} +.progressjs-theme-blueOverlay .progressjs-inner { + height: 100%; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; + background-color: #3498db; +} +.progressjs-theme-blueOverlay.progressjs-end { + opacity: 0 !important; +} +.progressjs-theme-blueOverlay .progressjs-percent { + display: none; +} + +/* Blue theme with border radius and overlay layer */ +.progressjs-theme-blueOverlayRadius { + background-color: white; + -webkit-transition: all 0.2s ease-out; + -moz-transition: all 0.2s ease-out; + -o-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + border-radius: 5px; +} +.progressjs-theme-blueOverlayRadius .progressjs-inner { + height: 100%; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; + background-color: #3498db; + border-radius: 5px; +} +.progressjs-theme-blueOverlayRadius.progressjs-end { + opacity: 0 !important; +} +.progressjs-theme-blueOverlayRadius .progressjs-percent { + display: none; +} + +/* Blue theme with border radius and overlay layer */ +.progressjs-theme-blueOverlayRadiusHalfOpacity { + background-color: white; + opacity: 0.5; + -webkit-transition: all 0.2s ease-out; + -moz-transition: all 0.2s ease-out; + -o-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + border-radius: 5px; +} +.progressjs-theme-blueOverlayRadiusHalfOpacity .progressjs-inner { + height: 100%; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; + background-color: #3498db; + border-radius: 5px; +} +.progressjs-theme-blueOverlayRadiusHalfOpacity.progressjs-end { + opacity: 0 !important; +} +.progressjs-theme-blueOverlayRadiusHalfOpacity .progressjs-percent { + display: none; +} + +/* Blue theme with border radius, overlay layer and percent bar */ +.progressjs-theme-blueOverlayRadiusWithPercentBar { + background-color: white; + -webkit-transition: all 0.2s ease-out; + -moz-transition: all 0.2s ease-out; + -o-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + border-radius: 5px; +} +.progressjs-theme-blueOverlayRadiusWithPercentBar .progressjs-inner { + height: 100%; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; + background-color: #3498db; + border-radius: 5px; +} +.progressjs-theme-blueOverlayRadiusWithPercentBar.progressjs-end { + opacity: 0 !important; +} +.progressjs-theme-blueOverlayRadiusWithPercentBar .progressjs-percent { + width: 70px; + text-align: center; + height: 40px; + position: absolute; + right: 50%; + margin-right: -35px; + top: 50%; + margin-top: -20px; + font-size: 30px; + opacity: .5; +} + +.progressjs-theme-blackRadiusInputs { + height: 10px; + border-radius: 10px; + overflow: hidden; +} +.progressjs-theme-blackRadiusInputs .progressjs-inner { + height: 2px; + -webkit-transition: all 1s ease-out; + -moz-transition: all 1s ease-out; + -o-transition: all 1s ease-out; + transition: all 1s ease-out; + background-color: #34495e; +} +.progressjs-theme-blackRadiusInputs.progressjs-end { + -webkit-transition: opacity 0.2s ease-out; + -moz-transition: opacity 0.2s ease-out; + -o-transition: opacity 0.2s ease-out; + transition: opacity 0.2s ease-out; + opacity: 0; +} +.progressjs-theme-blackRadiusInputs .progressjs-percent { + display: none; +} \ No newline at end of file diff --git a/vendors/simple-pace/simple-pace.js b/vendors/simple-pace/simple-pace.js index caa462b9c..316109cdb 100644 --- a/vendors/simple-pace/simple-pace.js +++ b/vendors/simple-pace/simple-pace.js @@ -32,7 +32,7 @@ } }, 500); }; - + Bar.prototype.stopAddInterval = function () { window.clearInterval(this.addInterval); this.addInterval = 0; @@ -78,7 +78,7 @@ return this.render(); }; - + Bar.prototype.add = function (iProg) { this.progress += window.parseInt(iProg, 10); this.progress = 100 < this.progress ? 100 : this.progress; @@ -86,7 +86,7 @@ return this.render(); }; - + Bar.prototype.setSpeed = function (iSpeed, iStopProgress) { this.addSpeed = iSpeed; this.stopProgress = iStopProgress || 100; diff --git a/vendors/svg4everybody/LICENSE.md b/vendors/svg4everybody/LICENSE.md new file mode 100644 index 000000000..565f84e33 --- /dev/null +++ b/vendors/svg4everybody/LICENSE.md @@ -0,0 +1,15 @@ +# CC0 1.0 Universal License + +Public Domain Dedication + +The person(s) who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. + +You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. + +In no way are the patent or trademark rights of any person affected by CC0, nor are the rights that other persons may have in the work or in how the work is used, such as publicity or privacy rights. + +Unless expressly stated otherwise, the person(s) who associated a work with this deed makes no warranties about the work, and disclaims liability for all uses of the work, to the fullest extent permitted by applicable law. + +When using or citing the work, you should not imply endorsement by the author or the affirmer. + +This is a [human-readable summary of the Legal Code](https://creativecommons.org/publicdomain/zero/1.0/) ([read the full text](https://creativecommons.org/publicdomain/zero/1.0/legalcode)). diff --git a/vendors/svg4everybody/README.md b/vendors/svg4everybody/README.md new file mode 100644 index 000000000..91ce31d0f --- /dev/null +++ b/vendors/svg4everybody/README.md @@ -0,0 +1,107 @@ +# SVG for Everybody + +[SVG for Everybody] is a script that adds [external spritemaps] support to otherwise [SVG-capable browsers]. + +To use **svg4everybody**, include the script in your document. + +```html + +``` + +To support IE6-8 as well, include the legacy script instead. + +```html + +``` + +The IE6-8 script needs to be included in the `` in order to shiv the **svg** and **use** elements. + +If running the standard script in IE9-11, be sure to set [X-UA-Compatible] higher than IE8. This can be done with a response header or the following meta tag. + +```html + +``` + +## Usage + +**spritemap.svg:** +```html + + CodePen + YouTube + Twitter + +``` + +This spritemap works fine in **Chrome**, **Firefox**, and **Opera**. [SVG for Everybody] polyfills the experience in **IE9-11**. + +```html + + + +``` + +![3 SVG logos](http://i.imgur.com/87Npdzn.png) + +Older browsers falls back to PNG images. + +```html + + + +``` + +Fallback PNGs point to the same location as their corresponding SVGs, only with the `#` hash replaced by a `.` dot, and with an appended `.png` extension. + +## Readability and accessibility + +Within your spritemap, each sprite may use a `` element to identify itself. + +```html +<symbol id="codepen"><title>CodePen +``` + +When this sprite is used, its title will be read aloud in [JAWS](http://www.freedomscientific.com/products/fs/JAWS-product-page.asp) and [NVDA](http://www.nvaccess.org/). Then, within your document, each sprite may use a `title` attribute to identify itself. + +```html + +``` + +This title will be read aloud in [VoiceOver](http://www.apple.com/accessibility/osx/voiceover/) and [NVDA](http://www.nvaccess.org/). At present, the `title` attribute is the only way to properly read aloud an SVG in VoiceOver. + +For maximum compatibility, both the `title` attribute in the document and the `title` element in the SVG should be used. + +ARIA roles may be used to provide even more accessibility. `role="presentation"` should be used when a sprite decorates other content. + +```html + Find me on Twitter +``` + +Alternatively, `role="img"` should be used when a sprite necessitates its own description. + +```html + +``` + +### Futher reading + +- [Tips for creating accessible SVG](https://www.sitepoint.com/tips-accessible-svg/) +- [Using ARIA to enhance SVG accessibility](http://blog.paciellogroup.com/2013/12/using-aria-enhance-svg-accessibility/) +- [SVG symbol a good choice for icons](http://css-tricks.com/svg-symbol-good-choice-icons/) +- [Implementing inline SVG Icons](https://kartikprabhu.com/article/inline-svg-icons) + +## Smaller SVGs + +SVG files, especially exported from various editors, usually contains a lot of redundant and useless information such as editor metadata, comments, hidden elements, default or non-optimal values and other stuff that can be safely removed or converted without affecting SVG rendering result. + +Use a tool like [SVGO](https://github.com/svg/svgo) to optimize SVG spritemaps. + +```sh +$ [sudo] npm install -g svgo +$ svgo spritemap.svg +``` + +[external spritemaps]: http://css-tricks.com/svg-sprites-use-better-icon-fonts/##Browser+Support +[SVG-capable browsers]: http://caniuse.com/svg +[SVG for Everybody]: https://github.com/jonathantneal/svg4everybody +[X-UA-Compatible]: http://www.modern.ie/en-us/performance/how-to-use-x-ua-compatible diff --git a/vendors/svg4everybody/bower.json b/vendors/svg4everybody/bower.json new file mode 100644 index 000000000..28de08c26 --- /dev/null +++ b/vendors/svg4everybody/bower.json @@ -0,0 +1,20 @@ +{ + "name": "svg4everybody", + "homepage": "https://github.com/jonathantneal/svg4everybody", + "authors": [ + "Jonathan Neal " + ], + "description": "Use external SVG spritemaps today.", + "main": ["svg4everybody.js", "svg4everybody.legacy.js"], + "keywords": [ + "svg", + "spritemaps", + "polyfill", + "ie" + ], + "repository": { + "type": "git", + "url": "git@github.com:jonathantneal/svg4everybody.git" + }, + "license": "CC0 1.0" +} diff --git a/vendors/svg4everybody/package.json b/vendors/svg4everybody/package.json new file mode 100644 index 000000000..2ebbeb0ce --- /dev/null +++ b/vendors/svg4everybody/package.json @@ -0,0 +1,18 @@ +{ + "name" : "svg4everybody", + "description" : "Use external SVG spritemaps in any browser", + "keywords" : ["svg", "sprites", "spritemaps", "symbol", "defs", "oldie", "ie8", "ie9", "safari", "external", "icon", "fallback"], + "author" : "Jonathan Neal (http://jonathantneal.com)", + "contributors" : [], + "dependencies" : [], + "main": "svg4everybody.js", + "homepage": "https://github.com/jonathantneal/svg4everybody", + "bugs": { + "url": "https://github.com/jonathantneal/svg4everybody/issues" + }, + "repository" : { + "type": "git", + "url": "git@github.com:jonathantneal/svg4everybody.git" + }, + "version" : "1.0.0" +} diff --git a/vendors/svg4everybody/svg4everybody.js b/vendors/svg4everybody/svg4everybody.js new file mode 100644 index 000000000..41f8ab788 --- /dev/null +++ b/vendors/svg4everybody/svg4everybody.js @@ -0,0 +1,84 @@ +/*! svg4everybody v1.0.0 | github.com/jonathantneal/svg4everybody */ +(function (document, uses, requestAnimationFrame, CACHE, IE9TO11) { + function embed(svg, g) { + if (g) { + var + viewBox = g.getAttribute('viewBox'), + fragment = document.createDocumentFragment(), + clone = g.cloneNode(true); + + if (viewBox) { + svg.setAttribute('viewBox', viewBox); + } + + while (clone.childNodes.length) { + fragment.appendChild(clone.childNodes[0]); + } + + svg.appendChild(fragment); + } + } + + function onload() { + var xhr = this, x = document.createElement('x'), s = xhr.s; + + x.innerHTML = xhr.responseText; + + xhr.onload = function () { + s.splice(0).map(function (array) { + embed(array[0], x.querySelector('#' + array[1].replace(/(\W)/g, '\\$1'))); + }); + }; + + xhr.onload(); + } + + function onframe() { + var use; + + while ((use = uses[0])) { + var + svg = use.parentNode, + url = use.getAttribute('xlink:href').split('#'), + url_root = url[0], + url_hash = url[1]; + + svg.removeChild(use); + + if (url_root.length) { + var xhr = CACHE[url_root] = CACHE[url_root] || new XMLHttpRequest(); + + if (!xhr.s) { + xhr.s = []; + + xhr.open('GET', url_root); + + xhr.onload = onload; + + xhr.send(); + } + + xhr.s.push([svg, url_hash]); + + if (xhr.readyState === 4) { + xhr.onload(); + } + + } else { + embed(svg, document.getElementById(url_hash)); + } + } + + requestAnimationFrame(onframe); + } + + if (IE9TO11) { + onframe(); + } +})( + document, + document.getElementsByTagName('use'), + window.requestAnimationFrame || window.setTimeout, + {}, + /Trident\/[567]\b/.test(navigator.userAgent) || /Edge\/12/.test(navigator.userAgent) || (navigator.userAgent.match(/AppleWebKit\/(\d+)/) || [])[1] < 538 +); diff --git a/vendors/svg4everybody/svg4everybody.legacy.js b/vendors/svg4everybody/svg4everybody.legacy.js new file mode 100644 index 000000000..193a7eea4 --- /dev/null +++ b/vendors/svg4everybody/svg4everybody.legacy.js @@ -0,0 +1,97 @@ +/*! svg4everybody v1.0.0 | github.com/jonathantneal/svg4everybody */ +(function (document, uses, requestAnimationFrame, CACHE, LTEIE8, IE9TO11) { + function embed(svg, g) { + if (g) { + var + viewBox = g.getAttribute('viewBox'), + fragment = document.createDocumentFragment(), + clone = g.cloneNode(true); + + if (viewBox) { + svg.setAttribute('viewBox', viewBox); + } + + while (clone.childNodes.length) { + fragment.appendChild(clone.childNodes[0]); + } + + svg.appendChild(fragment); + } + } + + function onload() { + var xhr = this, x = document.createElement('x'), s = xhr.s; + + x.innerHTML = xhr.responseText; + + xhr.onload = function () { + s.splice(0).map(function (array) { + embed(array[0], x.querySelector('#' + array[1].replace(/(\W)/g, '\\$1'))); + }); + }; + + xhr.onload(); + } + + function onframe() { + var use; + + while ((use = uses[0])) { + if (LTEIE8) { + var img = new Image(), src, q; + + src = use.getAttribute('xlink:href'); + q = (/\?[^#]+/.exec(src) || [''])[0]; + img.src = src.replace(/\?[^#]+/, '').replace('#', '.').replace(/^\./, '') + '.png' + q; + + use.parentNode.replaceChild(img, use); + } else { + var + svg = use.parentNode, + url = use.getAttribute('xlink:href').split('#'), + url_root = url[0], + url_hash = url[1]; + + svg.removeChild(use); + + if (url_root.length) { + var xhr = CACHE[url_root] = CACHE[url_root] || new XMLHttpRequest(); + + if (!xhr.s) { + xhr.s = []; + + xhr.open('GET', url_root); + + xhr.onload = onload; + + xhr.send(); + } + + xhr.s.push([svg, url_hash]); + + if (xhr.readyState === 4) { + xhr.onload(); + } + + } else { + embed(svg, document.getElementById(url_hash)); + } + } + } + + requestAnimationFrame(onframe); + } + + if (LTEIE8 || IE9TO11) { + onframe(); + } +})( + document, + document.getElementsByTagName('use'), + window.requestAnimationFrame || window.setTimeout, + {}, + /MSIE\s[1-8]\b/.test(navigator.userAgent), + /Trident\/[567]\b/.test(navigator.userAgent) || /Edge\/12/.test(navigator.userAgent) || (navigator.userAgent.match(/AppleWebKit\/(\d+)/) || [])[1] < 538, + document.createElement('svg'), + document.createElement('use') +); diff --git a/webpack.config.js b/webpack.config.js index 1f9f928f1..5c9e7da73 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -12,6 +12,7 @@ module.exports = { publicPath: 'rainloop/v/0.0.0/static/js/', chunkFilename: '[chunkhash].subapp.js' }, +// devtool: "#source-map", plugins: [ // new webpack.optimize.CommonsChunkPlugin('common.js'), new webpack.optimize.OccurenceOrderPlugin() @@ -29,7 +30,7 @@ module.exports = { 'JSON': 'window.JSON', 'JSEncrypt': 'window.JSEncrypt', '$LAB': 'window.$LAB', - 'SimplePace': 'window.SimplePace', + 'progressJs': 'window.progressJs', 'PhotoSwipe': 'window.PhotoSwipe', 'PhotoSwipeUI_Default': 'window.PhotoSwipeUI_Default', 'queue': 'window.queue',