diff --git a/AUTHORS.rst b/AUTHORS.rst new file mode 100644 index 0000000..321110c --- /dev/null +++ b/AUTHORS.rst @@ -0,0 +1,10 @@ +Authors +------- +* `David Ghedini`_ +* `Kaloyan Petrov`_ +* `Cited, Inc`_ + +.. _`David Ghedini`: https://github.com/DavidGhedini +.. _`Kaloyan Petrov`: https://github.com/kaloyan13 +.. _`Cited, Inc`: https://www.citedcorp.com + diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 0000000..2c7d427 --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,30 @@ +# Contributing + +## Issues + +If you've found a bug, let us know about it. + +## Pull Requests + +For all cases, you should have your own fork of the repo. + +To submit a pull request for a **new feature**: + +1. Run the tests. Every pull request for a new feature should have an accompanying unit test and docs changes. See the `README.md` in the `tests/` and `docs/` directories for details. +2. Create a new branch off of the `master` branch for your feature. This is particularly helpful when you want to submit multiple pull requests. +3. Add a test (or multiple tests) for your feature. Again, see `tests/README.md`. +4. Add your new feature, making the test pass. +5. Push to your fork and submit the pull request! + +To submit a **bug fix**: + +1. Create a new branch off of the `master` branch. +2. Add a test that demonstrates the bug. +3. Make the test pass. +4. Push to your fork and submit the pull request! + +To submit a **documentation fix**: + +1. Create a new branch off of the `master` branch. +2. Add your documentation fixes (no tests required). +3. Push to your fork and submit the pull request! diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..961f50d --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + 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. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is 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. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + 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. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + 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 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. Use with the GNU Affero General Public License. + + 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 Affero 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 special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 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 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 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. + + Tomcat Module for Webmin + Copyright (C) 2017 Cited, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Tomcat-Webmin-Module Copyright (C) 2017 Cited, Inc. + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + 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 GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md index 4ab3f63..8269dee 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,114 @@ -# Tomcat-Webmin-Module + +# Tomcat Webmin Module + +[![Documentation Status](https://readthedocs.org/projects/tomcat-webmin-module/badge/?version=latest)](https://tomcat-module.citedcorp.com/en/latest/?badge=latest) +# Info + +Apache Tomcat Module for Webmin. + +Install and Manage Apache Tomcat or Manage Existing Installations. + +# Install via Webmin + +Webmin->Webmin Configuration->Webmin Modules->From ftp or http URL + +URL: http://github.com/cited/Tomcat-Webmin-Module/raw/master/scripts/tomcat.wbm.gz + +Go to Servers->Apache Tomcat to complete set up using the setup Wizard (you may need to refresh page). + +# Install via Script + +On Ubuntu, as Root: + +```bash +wget https://raw.githubusercontent.com/cited/Tomcat-Webmin-Module/master/scripts/ubuntu.sh +chmod +x pre-install.sh +./pre-install.sh +``` + +On Rocky Linux or Alma Linux, as Root: + +```bash +wget https://raw.githubusercontent.com/cited/Tomcat-Webmin-Module/master/scripts/alma-rocky.sh +chmod +x pre-install.sh +./pre-install.sh +``` + +Go to Servers->Apache Tomcat to complete set up using the setup Wizard. + +# Install via GIT + +As Root: + +```bash +git clone https://github.com/cited/Tomcat-Webmin-Module +mv Tomcat-Webmin-Module-master tomcat +tar -cvzf tomcat.wbm.gz tomcat/ +``` + +Upload from Webmin->Webmin Configuration->Webmin Modules + +Go to Servers->Apache Tomcat (you may need to refresh page) + +# Notes + +## **Ubuntu** +Tested on Ubuntu 20 and 22 + +## **Readhat/Fedora/CentOS** +Tested on CentOS 6, 7, and 8 + +## **Rocky Linux** +Tested on Rocky Linux 9 + +## **Alma Linux** +Tested on Alma Linux 9 + +## **Arch** +Install tomcat packages manually and then install module, because Webmin doesn't support pacman. Go to Existing Tomcat Installations below. + + pacman --noconfirm -S tomcat8 tomcat-native jre8-openjdk + +## **OpenSuSe** +Install tomcat packages manually and then install module. Go to Existing Tomcat Installations below. + + zypper -n install tomcat tomcat-webapps tomcat-admin-webapps + +## **Slackware** +Install Tomcat using one of our [scripts](https://github.com/AcuGIS)! + +## **Existing Tomcat Installations** + +The module can also be installed on existing Tomcat installations. + +1. Install from Webmin->Webmin Configuration->Webmin Modules +2. Go to Servers > Apache Tomcat +3. Click config icon in top left corner +4. Set the paths to those used on your installation + +Once you have updated the /etc/webmin/tomcat/config file to your installation paths, you should be able to use all functionality. + +## **Issues** +Please report issue here or at hello@acugis.com + +# Screen Shots + +Tomcat Module: + +![tomcat webmin module](https://cdn.acugis.com/apache-tomcat-webmin-plugin/tomcat-module-plugin.gif) + +Tomcat Module WAR Manager: + +![tomcat webmin module deploy wars](https://cdn.acugis.com/apache-tomcat-webmin-plugin/tomcat-module-war-deploy.gif) + +Tomcat Module Configuration Editor: + +![tomcat webmin module edit configs](https://cdn.acugis.com/apache-tomcat-webmin-plugin/tomcat-module-edit-configs.gif) + + +Copyright +--------- + +* Copyright AcuGIS, 2020 +* Copyright Cited, Inc., 2020 diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..944fac4 --- /dev/null +++ b/README.rst @@ -0,0 +1,48 @@ +Apache Tomcat Webmin Module +=========================== + +Apache Tomcat Module for Webmin. + +Install and Manage Apache Tomcat or Manage Existing Installations. + +Features +-------- + +- Install Tomcat +- Install JDK +- Stop, Start, and Restart Tomcat +- Edit Main Config Files +- Deploy WARS + +Installation +------------ + +The preferred method is installing via GIT. + + $ git clone https://github.com/cited/Tomcat-Webmin-Module + + $ mv Tomcat-Webmin-Module tomcat + + $ tar -cvzf tomcat.wbm.gz tomcat/ + + +Upload from Webmin->Webmin Configuration->Webmin Modules + +Go to Servers->Apache Tomcat (you may need to refresh page) + +Contribute +---------- + +- Issue Tracker: github.com/cited/Tomcat-Webmin-Module/issues +- Source Code: github.com/cited/Tomcat-Webmin-Module + +Support +------- + +If you are having issues, please let us know. +We have a mailing list located at: project@google-groups.com + +License +------- + +The project is licensed under the BSD license. diff --git a/config b/config new file mode 100644 index 0000000..363c94a --- /dev/null +++ b/config @@ -0,0 +1 @@ +tomcat_config=/etc/webmin/tomcat/config diff --git a/config.info b/config.info new file mode 100644 index 0000000..da569c7 --- /dev/null +++ b/config.info @@ -0,0 +1 @@ +tomcat_config=Path to the Webmin Tomcat module config file,8 diff --git a/default_java.cgi b/default_java.cgi new file mode 100644 index 0000000..d033107 --- /dev/null +++ b/default_java.cgi @@ -0,0 +1,26 @@ +#!/usr/bin/perl + +require './tomcat-lib.pl'; +require './java-lib.pl'; +require '../webmin/webmin-lib.pl'; #require + +use File::Basename; + +&ReadParse(); +&error_setup($text{'install_err'}); + +&ui_print_header(undef, $text{'java_title'}, ""); + +my $jdk_name = $in{'inst_jdk2'}; +$jdk_name || &error($text{'delete_enone'}); + +my $jdk_dir = get_jdk_dir_by_name($jdk_name); + +if(is_default_jdk($jdk_dir) == 1){ + print "$jdk_dir is already set as default JDK.
"; +}else{ + set_default_java($jdk_dir); +} + +print "
Done
"; +&ui_print_footer("", $text{'index_return'}); diff --git a/delete_war.cgi b/delete_war.cgi new file mode 100644 index 0000000..b9be2d4 --- /dev/null +++ b/delete_war.cgi @@ -0,0 +1,39 @@ +#!/usr/bin/perl + +require './tomcat-lib.pl'; +use File::Path 'rmtree'; + +&ReadParse(); + +&error_setup($text{'delete_err'}); +&ui_print_header(undef, $text{'delete_title'}, ""); + +@mods = split(/\0/, $in{'mod'}); +@mods || &error($text{'delete_enone'}); + +tomcat_service_ctl('stop'); + +#delete each of the specified directories +my $catalina_home = get_catalina_home(); +foreach $d (@mods) { + print "Removing $catalina_home/$d
"; + if(rmtree("$catalina_home/webapps/$d") == 0){ + &error("Failed to remove application"); + &ui_print_footer("", $text{'index_return'}); + exit; + } + + if($in{'rmwar'}){ + $war = "$catalina_home/webapps/$d.war"; + if( -f $war){ + unlink($war); + print "Removed $war
"; + } + } +} +print "Uninstall successful
"; + +tomcat_service_ctl('start'); + +&ui_print_footer("", $text{'index_return'}); + diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..c04268f --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,177 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ReadtheDocsTemplate.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ReadtheDocsTemplate.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/ReadtheDocsTemplate" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ReadtheDocsTemplate" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/authors.rst b/docs/authors.rst new file mode 100644 index 0000000..e122f91 --- /dev/null +++ b/docs/authors.rst @@ -0,0 +1 @@ +.. include:: ../AUTHORS.rst diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..2fbb5bd --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,258 @@ +# -*- coding: utf-8 -*- +# +# Read the Docs Template documentation build configuration file, created by +# sphinx-quickstart on Tue Aug 26 14:19:49 2014. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Tomcat Webmin Module' +copyright = u'2020, Cited, Inc.' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'ReadtheDocsTemplatedoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'ReadtheDocsTemplate.tex', u'Read the Docs Template Documentation', + u'Read the Docs', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'readthedocstemplate', u'Read the Docs Template Documentation', + [u'Read the Docs'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'ReadtheDocsTemplate', u'Read the Docs Template Documentation', + u'Read the Docs', 'ReadtheDocsTemplate', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/docs/contributing.rst b/docs/contributing.rst new file mode 100644 index 0000000..e582053 --- /dev/null +++ b/docs/contributing.rst @@ -0,0 +1 @@ +.. include:: ../CONTRIBUTING.rst diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..9321cb8 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,26 @@ +.. Read the Docs Template documentation master file, created by + sphinx-quickstart on Tue Aug 26 14:19:49 2014. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + + +Tomcat Webmin Module Docs +================================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + :glob: + + * + + + +Cited, Inc. +================== + +`Cited, Inc. `_ + + + diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 0000000..04d5f61 --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,18 @@ +============ +Installation +============ + +The preferred method is installing via GIT. + +Install the package with GIT:: + + $ git clone https://github.com/cited/Tomcat-Webmin-Module + + $ mv Tomcat-Webmin-Module tomcat + + $ tar -cvzf tomcat.wbm.gz tomcat/ + + +Upload from Webmin->Webmin Configuration->Webmin Modules + +Go to Servers->Apache Tomcat (you may need to refresh page) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..2df9a8c --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,242 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\complexity.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\complexity.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/docs/readme.rst b/docs/readme.rst new file mode 100644 index 0000000..72a3355 --- /dev/null +++ b/docs/readme.rst @@ -0,0 +1 @@ +.. include:: ../README.rst diff --git a/docs/usage.rst b/docs/usage.rst new file mode 100644 index 0000000..81afb04 --- /dev/null +++ b/docs/usage.rst @@ -0,0 +1,15 @@ +======== +Usage +======== + +Tomcat Module: + +.. image:: https://cdn.acugis.com/apache-tomcat-webmin-plugin/tomcat-module-plugin.gif + +Tomcat Module WAR Manager: + +.. image:: https://cdn.acugis.com/apache-tomcat-webmin-plugin/tomcat-module-war-deploy.gif + +Tomcat Module Configuration Editor: + +.. image:: https://cdn.acugis.com/apache-tomcat-webmin-plugin/tomcat-module-edit-configs.gif diff --git a/edit_java.cgi b/edit_java.cgi new file mode 100644 index 0000000..f4f7c5c --- /dev/null +++ b/edit_java.cgi @@ -0,0 +1,91 @@ +#!/usr/bin/perl + +require './tomcat-lib.pl'; +require './java-lib.pl'; +require '../webmin/webmin-lib.pl'; #for OS detection + +&ReadParse(); + +&ui_print_header(undef, $text{'java_title'}, ""); + +# Show tabs +@tabs = ( [ "install", $text{'java_tabinstall'}, "edit_java.cgi?mode=install" ], + [ "uninstall", $text{'java_tabuninstall'}, "edit_java.cgi?mode=uninstall" ], + [ "default", $text{'java_tabdefault'}, "edit_java.cgi?mode=default" ] + ); + +print &ui_tabs_start(\@tabs, "mode", $in{'mode'} || "install", 1); + + +print &ui_tabs_start_tab("mode", "install"); +print "$text{'java_desc1'}

\n"; + +print &ui_form_start("install_java.cgi", "form-data"); +print &ui_table_start($text{'java_install'}, undef, 2); + +my %jdk_version = &get_latest_jdk_version(); +@opt_avail_jdk = (); +foreach $ver (keys %jdk_version) { + push(@opt_avail_jdk, [ "$ver=$jdk_version{$ver}", $ver]); +} + +my %openjdk_version = &get_openjdk_versions(); +@opt_avail_openjdk = (); +foreach $ver (reverse sort { $a <=> $b } keys %openjdk_version) { + push(@opt_avail_openjdk, [ "$ver=$openjdk_version{$ver}", $ver]); +} + +print &ui_table_row($text{'jdk_installsource'}, + &ui_radio_table("source", 200, + [ [ 200, $text{'openjdk_latest'}, &ui_select("openjdk_ver", undef, \@opt_avail_openjdk, 1, 0). + '
'. + &ui_checkbox("openjdk_headless", 1,undef, 1).$text{'openjdk_headless'}. + &ui_hr()], + [ 100, $text{'jdk_latest'}, &ui_select("jdk_ver", undef, \@opt_avail_jdk, 1, 0)], + [ 0, $text{'source_local'}, &ui_textbox("file", undef, 40)." ". &file_chooser_button("file", 0) ], + [ 1, $text{'source_uploaded'},&ui_upload("upload", 40) ], + [ 2, $text{'source_ftp'}, &ui_textbox("url", undef, 40) ] + ]), 2); +print &ui_table_row($text{'java_def_jdk'}, + &ui_checkbox("def_jdk", 1,undef, 1).$text{'java_def_jdk_desc'} + ,2); + + +print &ui_table_end(); +print &ui_form_end([ [ "", $text{'java_installok'} ] ]); +print &ui_tabs_end_tab(); + + +print &ui_tabs_start_tab("mode", "uninstall"); +print "$text{'java_desc2'}

\n"; + +print &ui_form_start("uninstall_java.cgi", "post"); +print &ui_table_start($text{'java_uninstall'}, undef, 2); + +@jdk_vlist = &get_installed_jdk_versions(); +@opts_inst_jdk = ( ); +foreach $jdk_ver (@jdk_vlist) { + push(@opts_inst_jdk, [ $jdk_ver, $jdk_ver ]); +} +print &ui_table_row($text{'java_installed'}, &ui_select("inst_jdk", undef, \@opts_inst_jdk, 1, 0)."
\n", 2); +print &ui_table_row($text{'java_rm_def_jdk'}, &ui_checkbox("rm_def_jdk", 1,undef, 1), 2); + +print &ui_table_end(); +print &ui_form_end([ [ "", $text{'java_deleteok'} ] ]); +print &ui_tabs_end_tab(); + +print &ui_tabs_start_tab("mode", "default"); +print "$text{'java_desc3'}

\n"; + +print &ui_form_start("default_java.cgi", "post"); +print &ui_table_start($text{'java_default'}, undef, 2); + +print &ui_table_row($text{'java_installed'}, &ui_select("inst_jdk2", undef, \@opts_inst_jdk, 1, 0)."
\n", 2); + +print &ui_table_end(); +print &ui_form_end([ [ "", $text{'java_defaultok'} ] ]); +print &ui_tabs_end_tab(); + +print &ui_tabs_end(1); + +&ui_print_footer("", $text{'index_return'}); diff --git a/edit_libs.cgi b/edit_libs.cgi new file mode 100644 index 0000000..27cf0f3 --- /dev/null +++ b/edit_libs.cgi @@ -0,0 +1,56 @@ +#!/usr/bin/perl + +require './tomcat-lib.pl'; +&ReadParse(); + +&ui_print_header(undef, $text{'libs_title'}, ""); + +# Show tabs +@tabs = ( [ "install", $text{'libs_tabinstall'}, "edit_libs.cgi?mode=install" ], + [ "uninstall", $text{'libs_tabuninstall'}, "edit_libs.cgi?mode=uninstall" ] + ); + +print &ui_tabs_start(\@tabs, "mode", $in{'mode'} || "install", 1); + +# Display installation form +print &ui_tabs_start_tab("mode", "install"); +print "$text{'libs_desc1'}

\n"; + +print &ui_form_start("install_libs.cgi", "form-data"); +print &ui_table_start($text{'libs_install'}, undef, 2); + +print &ui_table_row($text{'libs_installsource'}, + &ui_radio_table("source", 0, + [ [ 0, $text{'source_local'}, &ui_textbox("file", undef, 40)." ". &file_chooser_button("file", 0) ], + [ 1, $text{'source_uploaded'},&ui_upload("upload", 40) ], + [ 2, $text{'source_ftp'}, &ui_textbox("url", undef, 40) ] + ])); + +print &ui_table_end(); +print &ui_form_end([ [ "", $text{'libs_installok'} ] ]); +print &ui_tabs_end_tab(); + + +# Display deletion form +print &ui_tabs_start_tab("mode", "uninstall"); +print "$text{'libs_desc2'}

\n"; + +print &ui_form_start("uninstall_libs.cgi", "post"); +print &ui_table_start($text{'libs_delete'}, undef, 2); + +@libs_lists = &get_installed_libs(); +@opts_inst_libs = ( ); +foreach $lib_file (@libs_lists) { + $lib_file =~ /^lib_([a-z0-9\.\-_\s]+)\.list$/i; + push(@opts_inst_libs, [ $1, $1 ]); +} +print &ui_table_row($text{'libs_installed'}, &ui_select("inst_lib", undef, \@opts_inst_libs, 10, 1), 2); + +print &ui_table_end(); +print &ui_form_end([ [ "", $text{'libs_deleteok'} ] ]); +print &ui_tabs_end_tab(); + + +print &ui_tabs_end(1); + +&ui_print_footer("", $text{'index_return'}); diff --git a/edit_manual.cgi b/edit_manual.cgi new file mode 100644 index 0000000..42e952b --- /dev/null +++ b/edit_manual.cgi @@ -0,0 +1,33 @@ +#!/usr/bin/perl +# Show a page for manually editing an Tomcat server.xml config file + +require './tomcat-lib.pl'; +&ReadParse(); +&ui_print_header(undef, $text{'manual_title'}, ""); + +my $catalina_home = get_catalina_home(); + +# Work out and show the files +@files = ( "$catalina_home/bin/setenv.sh", + "$catalina_home/conf/context.xml", + "$catalina_home/conf/server.xml", + "$catalina_home/conf/tomcat-users.xml", + "$catalina_home/conf/web.xml"); +$in{'file'} ||= $files[0]; +&indexof($in{'file'}, @files) >= 0 || &error($text{'manual_efile'}); + +print &ui_form_start("edit_manual.cgi"); +print "$text{'manual_file'}\n"; +print &ui_select("file", $in{'file'}, [ map { [ $_ ] } @files ], 1, 0); +print &ui_submit($text{'manual_ok'}); +print &ui_form_end(); + +# Show the file contents +print &ui_form_start("save_manual.cgi", "form-data"); +print &ui_hidden("file", $in{'file'}),"\n"; +$data = &read_file_contents($in{'file'}); +print &ui_textarea("data", $data, 20, 80),"\n"; +print &ui_form_end([ [ "save", $text{'save'} ] ]); + +&ui_print_footer("", $text{'index_return'}); + diff --git a/edit_proxy.cgi b/edit_proxy.cgi new file mode 100644 index 0000000..1baa3a3 --- /dev/null +++ b/edit_proxy.cgi @@ -0,0 +1,188 @@ +#!/usr/bin/perl + +require './tomcat-lib.pl'; +foreign_require('apache', 'apache-lib.pl'); + +sub get_proxy_file{ + my $domain_user = $_[0]; + my $proxy_file = ''; + + if( -d '/etc/httpd/conf.d' ){ + $proxy_file = '/etc/httpd/conf.d/tomcat.conf'; + }elsif( -d '/etc/apache2/conf-enabled/'){ #ubuntu or debian + $proxy_file = '/etc/apache2/conf-enabled/tomcat.conf'; + } + return $proxy_file; +} + +sub load_proxy_maps{ + my $proxy_file = $_[0]; + + my %maps; + open(my $fh, '<', $proxy_file) or return %maps; + while(my $line = <$fh>){ + if($line =~ /^ProxyPass ([\/a-z0-9_\-\.]+) ([a-z:\/0-9\.\-]+)/i){ + $maps{$2} = $1; + } + } + close $fh; + + return %maps; +} + +sub add_proxy{ + my $proxy_file = $_[0]; + my $app_name = $_[1]; + my $default = $_[2]; + my $ssl_port = $_[3]; + my $wildcard = $_[4]; + + my %idata = ('port_http'=>'8080', 'port_https'=>'8443'); + + my $app_path = '/'; + if($default == 0){ #if app is not default + $app_path .= $app_name; + } + + if($wildcard == 1){ + $app_name = ''; + } + + my $lref = &read_file_lines($proxy_file); + my $lnum = 0; + my $proxy_header_section = 0; + my $user_domain = 'localhost'; + foreach my $line (@$lref) { + if($line =~ /^ProxyPass \/ |^ProxyPassReverse \/ /){ #another default app + if($default == 1){ #if new app is default + delete @{$lref}[$lnum]; #remove old default app + } + }elsif($line =~ /^ProxyPass.*\/$app_name$/){ #if its a line with our app + delete @{$lref}[$lnum]; + }elsif($line =~ /^ProxyRequests Off$/){ + $proxy_header_section = 1; #proxy settings are found + }elsif($line =~ /^ServerName (.*)$/){ + $user_domain = $1; + } + $lnum++; + } + + + my $conf_tail; + if(@$lref[$lnum] eq ''){ + $conf_tail = pop @{$lref}; + } + if($proxy_header_section == 0){ + my $line = "ProxyRequests Off +ProxyPreserveHost On + + Order allow,deny + Allow from all +"; + push(@$lref, $line); + } + + my $proto = ''; + if($ssl_port == 1){ + $proto = 's'; + } + + push(@$lref, "ProxyPass $app_path http".$proto."://$user_domain:".$idata{'port_http'.$proto}."/$app_name"); + push(@$lref, "ProxyPassReverse $app_path http".$proto."://$user_domain:".$idata{'port_http'.$proto}."/$app_name"); + if($conf_tail){ + push(@$lref, $conf_tail); #Restore conf end + } + + flush_file_lines($proxy_file); +} + +sub remove_proxy{ + my ($proxy_file, $app_path) = @_; + + my $lref = &read_file_lines($proxy_file); + my $lnum = 0; + foreach my $line (@$lref) { + if($line =~ /^ProxyPass $app_path |^ProxyPassReverse $app_path /){ #if its a line with our app + delete @{$lref}[$lnum]; + } + $lnum++; + } + flush_file_lines($proxy_file); +} + +&ReadParse(); + +my $form_submit = 0; +if ($in{'submit_flag'}) { + $form_submit = 1; +} + +&ui_print_header(undef, $text{'proxy_title'}, ""); + + +my $proxy_file = get_proxy_file($remote_user); +if($proxy_file eq ''){ + print "Error: Failed to find proxy file for user $remote_user" +} + +if($form_submit == 1){ + if($in{'app_path'}){ + remove_proxy($proxy_file, $in{'app_path'}); + }else{ + add_proxy($proxy_file, $in{'app_name'}, $in{'app_default'}, $in{'proxy_ssl'}, $in{'app_wildcard'}); + } + apache::restart_apache(); +} + +my %maps = load_proxy_maps($proxy_file); +my @tds = (); +print &ui_columns_start(['Path','URL'], undef, 0, \@tds, 'Apps with proxy ('.$proxy_file.')'); +foreach my $url (keys %maps) { + + my @cols; + push(@cols, $maps{$url}); + push(@cols, "$url"); + + print &ui_columns_row(\@cols, \@tds); +} +print &ui_columns_end(); + + +print &ui_form_start("edit_proxy.cgi", "post"); +print &ui_hidden('submit_flag', 1); +print &ui_table_start($text{'proxy_add_options'}, undef, 2); + +my @apps = get_all_war_infos(); +@opt_apps = ( ); +foreach $app (@apps) { + push(@opt_apps, [ $app, $app ]); +} +print &ui_table_row($text{'proxy_wildcard'}, + &ui_checkbox("app_wildcard", 1, $text{'proxy_wildcard_info'}, 0), 2); +print &ui_table_hr(); +print &ui_table_row($text{'wars_installed'}, &ui_select("app_name", undef, \@opt_apps, 10, 1), 2); +print &ui_table_row($text{'proxy_default_app'}, + &ui_checkbox("app_default", 1, $text{'proxy_app_default_warning'}, 0), 2); +print &ui_table_row($text{'proxy_ssl'}, + &ui_checkbox("proxy_ssl", 1, $text{'proxy_ssl_info'}, 0), 2); + +print &ui_table_end(); +print &ui_form_end([ [ "", $text{'proxy_installok'} ] ]); + + +print &ui_form_start("edit_proxy.cgi", "post"); +print &ui_hidden('submit_flag', 1); +print &ui_table_start($text{'proxy_remove_options'}, undef, 2); + + +@opt_paths = ( ); +foreach $path (keys %maps) { + my $val = $maps{$path}; + push(@opt_paths, [ $val, $val ]); +} +print &ui_table_row($text{'proxy_list'}, &ui_select("app_path", undef, \@opt_paths, 10, 1), 2); + +print &ui_table_end(); +print &ui_form_end([ [ "", $text{'proxy_removeok'} ] ]); + +&ui_print_footer("", $text{'index_return'}); diff --git a/edit_war.cgi b/edit_war.cgi new file mode 100644 index 0000000..b354775 --- /dev/null +++ b/edit_war.cgi @@ -0,0 +1,57 @@ +#!/usr/bin/perl + +require './tomcat-lib.pl'; +&ReadParse(); + +&ui_print_header(undef, $text{'wars_title'}, ""); + +# Show tabs +@tabs = ( [ "install", $text{'wars_tabinstall'}, "edit_wars.cgi?mode=install" ], + [ "delete", $text{'wars_tabdelete'}, "edit_wars.cgi?mode=delete" ] + ); + +print &ui_tabs_start(\@tabs, "mode", $in{'mode'} || "install", 1); + +# Display installation form +print &ui_tabs_start_tab("mode", "install"); +print "$text{'wars_desc1'}

\n"; + +print &ui_form_start("install_war.cgi", "form-data"); +print &ui_table_start($text{'war_install'}, undef, 2); + +print &ui_table_row($text{'war_installsource'}, + &ui_radio_table("source", 0, + [ [ 0, $text{'source_local'}, &ui_textbox("file", undef, 40)." ". &file_chooser_button("file", 0) ], + [ 1, $text{'source_uploaded'}, &ui_upload("upload", 40) ], + [ 2, $text{'source_ftp'},&ui_textbox("url", undef, 40) ] + ])); + +print &ui_table_end(); +print &ui_form_end([ [ "", $text{'war_installok'} ] ]); +print &ui_tabs_end_tab(); + + +# Display deletion form +print &ui_tabs_start_tab("mode", "delete"); +print "$text{'wars_desc2'}

\n"; + +print &ui_form_start("delete_war.cgi", "post"); +print &ui_table_start($text{'wars_delete'}, undef, 2); + +@wlist = &get_all_war_infos(); +@opts = ( ); +foreach $d (@wlist) { + push(@opts, [ $d, $d ]); +} +print &ui_table_row($text{'wars_installed'}, + &ui_select("mod", undef, \@opts, 10, 1)."
\n". + &ui_checkbox("rmwar", 1, $text{'wars_rmwar'}, 0), 2); + +print &ui_table_end(); +print &ui_form_end([ [ "", $text{'wars_deleteok'} ] ]); +print &ui_tabs_end_tab(); + + +print &ui_tabs_end(1); + +&ui_print_footer("", $text{'index_return'}); diff --git a/help/intro.html b/help/intro.html new file mode 100644 index 0000000..7274854 --- /dev/null +++ b/help/intro.html @@ -0,0 +1,29 @@ +

Apache_Tomcat">Apache Tomcat
+ +

Module produced by Cited, Inc. © 2019 AcuGIS, Cited, Inc.

+ +

The Apache Tomcat® software is an open source implementation +of the Java Servlet, JavaServer Pages, Java Expression Language and Java +WebSocket technologies. The Java Servlet, JavaServer Pages, Java Expression +Language and Java WebSocket specifications are developed under the +Java Community +Process. +

+ +

The Apache Tomcat software is developed in an open and participatory +environment and released under the +Apache License version 2. The +Apache Tomcat project is intended to be a collaboration of the best-of-breed +developers from around the world. We invite you to participate in this open +development project. To learn more about getting involved, +click here.

+ +

Apache Tomcat software powers numerous large-scale, mission-critical web +applications across a diverse range of industries and organizations. Some of +these users and their stories are listed on the +PoweredBy wiki page.

+ +

Apache Tomcat, Tomcat, Apache, the Apache feather, and the Apache Tomcat +project logo are trademarks of the Apache Software Foundation.

+ +
diff --git a/images/edit-file.png b/images/edit-file.png new file mode 100644 index 0000000..9ee10d7 Binary files /dev/null and b/images/edit-file.png differ diff --git a/images/icon.gif b/images/icon.gif new file mode 100644 index 0000000..a2d1fdc Binary files /dev/null and b/images/icon.gif differ diff --git a/images/jar.png b/images/jar.png new file mode 100644 index 0000000..130a797 Binary files /dev/null and b/images/jar.png differ diff --git a/images/java.png b/images/java.png new file mode 100644 index 0000000..1ac8e42 Binary files /dev/null and b/images/java.png differ diff --git a/images/manual.gif b/images/manual.gif new file mode 100644 index 0000000..e65c7f0 Binary files /dev/null and b/images/manual.gif differ diff --git a/images/mapping.png b/images/mapping.png new file mode 100644 index 0000000..6268659 Binary files /dev/null and b/images/mapping.png differ diff --git a/images/war.png b/images/war.png new file mode 100644 index 0000000..fbc0ad6 Binary files /dev/null and b/images/war.png differ diff --git a/index.cgi b/index.cgi new file mode 100644 index 0000000..ae4d04d --- /dev/null +++ b/index.cgi @@ -0,0 +1,71 @@ +#!/usr/bin/perl +# index.cgi + +require './tomcat-lib.pl'; +require '../webmin/webmin-lib.pl'; #for OS detection + +# Check if config file exists +if (! -r $config{'tomcat_config'}) { + &ui_print_header(undef, $text{'index_title'}, "", "intro", 1, 1); + print &text('index_econfig', "$config{'tomcat_config'}", + "$gconfig{'webprefix'}/config.cgi?$module_name"),"

\n"; + &ui_print_footer("/", $text{"index"}); + exit; +} + +if(-f "$module_root_directory/setup.cgi"){ + &redirect("setup.cgi?mode=checks"); + exit; +} + +my %version = get_catalina_version(); + +&ui_print_header(undef, $text{'index_title'}, "", "intro", 1, 1, 0, + &help_search_link("tomcat", "man", "doc", "google"), undef, undef, + "Tomcat $version{'number'} / Java $version{'jvm'}"); + +push(@links, "edit_manual.cgi"); +push(@titles, $text{'manual_title'}); +push(@icons, "images/edit-file.png"); + +push(@links, "edit_war.cgi"); +push(@titles, $text{'wars_title'}); +push(@icons, "images/war.png"); + +push(@links, "edit_libs.cgi"); +push(@titles, $text{'libs_title'}); +push(@icons, "images/jar.png"); + +push(@links, "edit_java.cgi"); +push(@titles, $text{'java_title'}); +push(@icons, "images/java.png"); + +push(@links, "edit_proxy.cgi"); +push(@titles, $text{'proxy_title'}); +push(@icons, "images/mapping.png"); + +&icons_table(\@links, \@titles, \@icons, 2); + +# Check if tomcat is running +print &ui_hr().&ui_buttons_start(); +my ($running, $status) = &tomcat_service_ctl('status'); +print "$status
"; +if ($running == 1) { + # Running .. offer to apply changes and stop + print &ui_buttons_row("stop.cgi", $text{'index_stop'}, "$text{'index_stopmsg'}"); + print &ui_buttons_row("restart.cgi", $text{'index_restart'}, "$text{'index_restartmsg'}"); +}else { + # Not running .. offer to start + print &ui_buttons_row("start.cgi", $text{'index_start'}, $text{'index_startmsg'}); +} + + +#Check for an update of tomcat, once a day +my $latest_ver = upgrade_available(); +if($latest_ver){ + print &ui_buttons_row("tomcat_upgrade.cgi", $text{'index_upgrade'}, "Tomcat will be updated to $latest_ver. All WARs will be moved and config will be copied to new install!"); +} +print &ui_buttons_end(); + + +&ui_print_footer("/", $text{"index"}); diff --git a/install_check.sh b/install_check.sh new file mode 100644 index 0000000..6f8c85a --- /dev/null +++ b/install_check.sh @@ -0,0 +1,14 @@ +# install_check.pl + +do 'tomcat-lib.pl'; + +# is_installed(mode) +# For mode 1, returns 2 if the server is installed and configured for use by +# Webmin, 1 if installed but not configured, or 0 otherwise. +# For mode 0, returns 1 if installed, 0 if not +sub is_installed +{ +return 0 if (!-r $config{'tomcat_config'} || !&has_command($config{'tomcat_path'})); +return $_[0] ? 2 : 1; +} + diff --git a/install_java.cgi b/install_java.cgi new file mode 100644 index 0000000..1d338dc --- /dev/null +++ b/install_java.cgi @@ -0,0 +1,85 @@ +#!/usr/bin/perl + +require './tomcat-lib.pl'; +require './java-lib.pl'; +require '../webmin/webmin-lib.pl'; #require +foreign_require('software', 'software-lib.pl'); + +use File::Basename; + +sub extract_java_archive{ + my $jdk_archive = $_[0]; + + my $java_dir = '/usr/java'; + if( ! -d $java_dir){ + &make_dir($java_dir, 0755, 1); + } + + $cmd_out=''; + $cmd_err=''; + print "


Extracting $jdk_archive to $java_dir...
"; + local $out = &execute_command("tar -x -v --overwrite -f \"$jdk_archive\" -C/usr/java", undef, \$cmd_out, \$cmd_err, 0, 0); + + my $jdk_tar_first_line = ( split /\n/, $cmd_out )[0]; + my $jdk_dir = $java_dir."/".(split /\//, $jdk_tar_first_line)[0]; + + if($cmd_err){ + $cmd_err = s/\n/
/g; + &error("Error: tar: $cmd_err"); + }else{ + $cmd_out = s/\n/
/g; + print &html_escape($cmd_out); + } + + &set_ownership_permissions('root','root', 0755, $jdk_dir); + &execute_command("chown -R root:root $jdk_dir", undef, \$cmd_out, \$cmd_err, 0, 0); + if($cmd_err){ + $cmd_err = s/\n/
/g; + &error("Error: chown: $cmd_err"); + } + + return $jdk_dir; +} + +#$| = 1; + +if ($ENV{REQUEST_METHOD} eq "POST") { + &ReadParse(\%getin, "GET"); + &ReadParseMime(undef, \&read_parse_mime_callback, [ $getin{'id'} ]); + } +else { + &ReadParse(); + $no_upload = 1; + } +&error_setup($text{'install_err'}); +&ui_print_header(undef, $text{'java_title'}, ""); + +my $jdk_path = ''; +if($in{'source'} == 200){ + + my $jdk_name = (split /=/, $in{'openjdk_ver'})[1]; + my $openjdk_pkg = $jdk_name; + if($in{'openjdk_headless'} == 1){ + $openjdk_pkg .= '-headless'; + } + + software::update_system_install($openjdk_pkg, undef); + $jdk_path = get_jdk_dir_by_name($jdk_name); + +} else { + if ($in{'source'} == 100) { + + my ($jdk_name, $url) = split /=/, $in{'jdk_ver'}; + $in{'url'} = $url; + $in{'source'} = 2; + } + my $jdk_archive = process_file_source(); + $jdk_path = extract_java_archive($jdk_archive); +} + +if($in{'def_jdk'} == 1){ + set_default_java($jdk_path); +} + +print "
Done
"; +&ui_print_footer("", $text{'index_return'}); diff --git a/install_libs.cgi b/install_libs.cgi new file mode 100644 index 0000000..e04d9d9 --- /dev/null +++ b/install_libs.cgi @@ -0,0 +1,72 @@ +#!/usr/bin/perl + +require './tomcat-lib.pl'; + +use File::Basename; +use File::Path 'rmtree'; + +sub inst_error{ + print "$main::whatfailed : $_[0]

\n"; + &ui_print_footer("", $text{'index_return'}); + exit; +} + +if($ENV{'CONTENT_TYPE'} =~ /boundary=(.*)$/) { + &ReadParseMime(); +}else { + &ReadParse(); + $no_upload = 1; +} + +$| = 1; +&ui_print_header(undef, $text{'libs_install_title'}, ""); + +my $lib_file = process_file_source(); +my @suffixlist = ('\.zip', '\.jar'); +($lib_name,$path,$lib_suffix) = fileparse($lib_file,@suffixlist); + +my $unzip_dir = ''; +my @lib_jars; + +#Check if its a .zip or .jar +print "Source: $lib_file
"; +if($lib_suffix eq ".zip"){ + $unzip_dir = unzip_file($lib_file); + + #make a list of extension jars + opendir(DIR, $unzip_dir) or die $!; + @lib_jars = grep { $_ = $unzip_dir.'/'.$_ ; -f && /\.jar$/ } readdir(DIR); + closedir(DIR); + +}elsif($lib_suffix eq ".jar"){ + push(@lib_jars, $lib_file); +}else{ + &error("Error: Unsupported file type $lib_suffix"); + &ui_print_footer("", $text{'index_return'}); +} + +print "


Installing $lib_name files...
"; +my $catalina_home = get_catalina_home(); + +#move jars to Tomcat lib and save list of installed jars to lib file +open(my $fh, '>', "$module_config_directory/lib_$lib_name.list") or die "open:$!"; +foreach $j (@lib_jars) { + #move jars to Tomcat lib + if(!move("$j", "$catalina_home/lib/")){ + &error("Error: Can't move file: $!"); + } + my $j_name = basename($j); + &set_ownership_permissions('tomcat','tomcat', 0444, "$catalina_home/lib/$j_name"); + + print "$catalina_home/lib/$j_name
"; + print $fh "$j_name=$catalina_home/lib/$j_name\n"; +} +close $fh; + +print "
Done.
"; + +if($unzip_dir ne ''){ + &rmtree($unzip_dir); #remove temp dir +} + +&ui_print_footer("", $text{'index_return'}); diff --git a/install_war.cgi b/install_war.cgi new file mode 100644 index 0000000..651c812 --- /dev/null +++ b/install_war.cgi @@ -0,0 +1,63 @@ +#!/usr/bin/perl + +require './tomcat-lib.pl'; +use File::Basename; +use File::Path 'rmtree'; + +sub inst_error{ + print "$main::whatfailed : $_[0]

\n"; + &ui_print_footer("", $text{'index_return'}); + exit; +} + +if($ENV{'CONTENT_TYPE'} =~ /boundary=(.*)$/) { &ReadParseMime(); } +else { &ReadParse(); $no_upload = 1; } + +$| = 1; +$theme_no_table = 1 if ($in{'source'} == 2 || $in{'source'} == 4); +&ui_print_header(undef, $text{'install_title'}, ""); + +my $file = process_file_source(); + +my @suffixlist = ('\.zip', '\.war'); +($file_name,$path,$file_suffix) = fileparse($file,@suffixlist); + +my $unzip_dir = ''; +my @wars; + +#Check if its a .zip or .jar +print "Source: $file
"; +if($file_suffix eq ".zip"){ + $unzip_dir = unzip_file($file); + + #make a list of extension jars + opendir(DIR, $unzip_dir) or die $!; + @wars = grep { $_ = $unzip_dir.'/'.$_ ; -f && /\.war$/ } readdir(DIR); + closedir(DIR); + +}elsif($file_suffix eq ".war"){ + push(@wars, $file); +}else{ + &error("Error: Unsupported file type $file_suffix"); + &ui_print_footer("", $text{'index_return'}); +} + +$catalina_home = get_catalina_home(); + +foreach $war (@wars) { + my $war_name = basename($war); + if(!move($war, "$catalina_home/webapps/")){ + &error("Error: Can't move file: $!"); + }else{ + print "Install of $war_name is successful
"; + } + &set_ownership_permissions('tomcat','tomcat', 0444, "$catalina_home/webapps/$war_name"); +} + +if($unzip_dir ne ''){ + &rmtree($unzip_dir); #remove temp dir +} + +#tomcat_service_ctl('restart'); + +&ui_print_footer("", $text{'index_return'}); diff --git a/java-lib.pl b/java-lib.pl new file mode 100644 index 0000000..62f4f63 --- /dev/null +++ b/java-lib.pl @@ -0,0 +1,363 @@ +=head1 java-lib.pl + +Functions for managing Oracle JDK installations. + + foreign_require("tomcat", "tomcat-lib.pl"); + @sites = tomcat::list_tomcat_websites() + +=cut + +BEGIN { push(@INC, ".."); }; +use warnings; +use WebminCore; + +foreign_require('software', 'software-lib.pl'); + +sub search_pkg{ + my $pattern = $_[0]; + + my @avail = (); + if (defined(&software::update_system_search)) { + # Call the search function + @avail = &software::update_system_search($pattern); + } else { + # Scan through list manually + @avail = &software::update_system_available(); + @avail = grep { $_->{'name'} =~ /\Q$pattern\E/i } @avail; + } + return sort @avail; +} + +sub get_openjdk_patterns(){ + my %osinfo = &detect_operating_system(); + + my %rv; + if( ($osinfo{'real_os_type'} =~ /centos/i) or #CentOS + ($osinfo{'real_os_type'} =~ /fedora/i) or #Fedora + ($osinfo{'real_os_type'} =~ /rocky/i) or # Rocky + ($osinfo{'real_os_type'} =~ /alma/i) or # Alma + ($osinfo{'real_os_type'} =~ /scientific/i) ){ + + $rv{'search'} = 'openjdk'; + $rv{'version'} = '^java-([0-9\.]+)-openjdk$'; + + }elsif( $osinfo{'os_type'} =~ /debian/i){ #ubuntu + $rv{'search'} = 'openjdk-[0-9]+-jdk$'; + $rv{'version'} = 'openjdk-([0-9]+)-jdk'; + } + return %rv; +} + +sub get_openjdk_versions(){ + my $cache_file = "$module_config_directory/openjdk_version_cache"; + my %openjdk_versions; + + if(-f $cache_file){ + read_file_cached($cache_file, \%openjdk_versions); + + if($openjdk_versions{'updated'} >= (time() - 86400)){ #if last update was less than a day ago + delete $openjdk_versions{'updated'}; #remove the cache mtime key + return %openjdk_versions; + } + } + + my %patterns = get_openjdk_patterns(); + my @avail = search_pkg($patterns{'search'}); + foreach $a (@avail) { + if($a->{'name'} =~ /$patterns{'version'}/){ + $openjdk_versions{$1} = $a->{'name'}; + } + } + + #cache the results + $openjdk_versions{'updated'} = time(); + &write_file($cache_file, \%openjdk_versions); + delete $openjdk_versions{'updated'}; #remove the cache mtime key + + return %openjdk_versions; +} + +sub get_latest_jdk_version(){ + + my %java_tar_gz; + my $cache_file = "$module_config_directory/oracle_version_cache"; + if(-f $cache_file){ + read_file_cached($cache_file, \%java_tar_gz); + if($java_tar_gz{'updated'} >= (time() - 86400)){ #if last update was less than a day ago + delete $java_tar_gz{'updated'}; #remove the cache mtime key + return %java_tar_gz; + } + } + + my $error; + my $url = 'https://www.oracle.com/java/technologies/downloads/'; + $tmpfile = &transname("javase.html"); + &error_setup(&text('install_err3', $url)); + &http_download("www.oracle.com", 443, "/java/technologies/downloads/", $tmpfile, \$error, + undef, 1, undef, 0, 0, 1); + + open($fh, '<', $tmpfile) or die "open:$!"; + while(my $line = <$fh>){ + #https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz + if($line =~ /(https:\/\/download.oracle.com\/java\/([0-9]+)\/latest\/jdk-[0-9]+_linux-x64_bin.tar.gz)/){ + #if($line =~ /"filepath":"(https:\/\/download.oracle.com\/otn-pub\/java\/jdk\/([a-z0-9-\.+]+)\/[a-z0-9]+\/jdk-[a-z0-9-\.]+_linux-x64_bin.tar.gz)/){ + $java_tar_gz{$2} = $1; + #last; + } + } + close $fh; + + #cache the results + $java_tar_gz{'updated'} = time(); + &write_file($cache_file, \%java_tar_gz); + delete $java_tar_gz{'updated'}; #remove the cache mtime key + + return %java_tar_gz; +} + +sub get_installed_jdk_versions(){ + my @jdks = get_installed_oracle_jdk_versions(); + + push(@jdks, get_installed_openjdk_versions()); + return @jdks; +} + +sub get_installed_openjdk_versions{ + + my @pkgs = (); + my %patterns = get_openjdk_patterns(); + + my $cmd_out=''; + my $cmd_err=''; + if(has_command('rpm')){ + local $out = &execute_command("rpm -qa --queryformat \"%{NAME}\n\" \"*$patterns['search']*\"", undef, \$cmd_out, \$cmd_err, 0, 0); + + my @lines = split /\n/, $cmd_out; + foreach my $line (@lines){ + if($line =~ /^(java-[0-9\.]+-openjdk).*/i){ #package pgdg96-centos is not installed + push(@pkgs, $1); + } + } + }elsif(has_command('dpkg')){ + local $out = &execute_command("dpkg -l \"*openjdk*\"", undef, \$cmd_out, \$cmd_err, 0, 0); + + my %all_pkgs; + my @lines = split /\n/, $cmd_out; + foreach my $line (@lines){ + if($line =~ /^(..)\s+(openjdk-[0-9\.]*)-.*:.*/i){ + my $pkg = $2; + if($1 =~ /[uirph]i/){ + $all_pkgs{$pkg} = 1; + } + } + } + @pkgs = keys %all_pkgs; + }else{ + my @dirs; + opendir(DIR, '/usr/java/') or return @dirs; + @dirs + = grep { + /^jdk-[0-9\.]+/ + && -d "/usr/java/$_" + } readdir(DIR); + closedir(DIR); + } + + return sort @pkgs; +} + +sub get_installed_oracle_jdk_versions{ + my @dirs; + opendir(DIR, '/usr/java/') or return @dirs; + @dirs + = grep { + /^jdk[0-9\.\-_]+/ + && -d "/usr/java/$_" + } readdir(DIR); + closedir(DIR); + + return sort @dirs; +} + +sub is_default_jdk{ + my $jdk_dir = $_[0]; + + my %os_env; + if(-f '/etc/profile.d/jdk.sh'){ + read_env_file('/etc/profile.d/jdk.sh', \%os_env); + }elsif(-f '/etc/environment'){ + read_env_file('/etc/environment', \%os_env); + } + + if($os_env{'JAVA_HOME'} eq $jdk_dir){ + return 1; + }else{ + return 0; + } +} + +sub get_java_version(){ + local %version; + local $out = &backquote_command('java \-version 2>&1'); + + #Oracle Java <= 8 + if ($out =~ /Java\(TM\)\sSE\sRuntime\sEnvironment\s\(build\s([0-9]\.([0-9]+)\.[0-9]_([0-9]+)\-([a-z0-9]+))\)/) { + $version{'full'} = $1; + $version{'major'} = $2; + $version{'release'} = $3; + $version{'build'} = $4; + $version{'vendor'} = 'oracle'; + + #Oracle Java >=12 - Java(TM) SE Runtime Environment (build 12.0.1+12) + }elsif ($out =~ /Java\(TM\)\sSE\sRuntime\sEnvironment\s\(build\s((\d+)\.\d+\.\d+\+(\d+))\)/) { + $version{'full'} = $1; + $version{'major'} = $2; + $version{'release'} = 0; + $version{'build'} = $3; + $version{'vendor'} = 'oracle'; + + # OpenJDK Runtime Environment (build 11.0.7+10-post-Ubuntu-2ubuntu218.04) + # OpenJDK Runtime Environment (build 11.0.9+11-Ubuntu-0ubuntu1.20.04) + # OpenJDK Runtime Environment (build 1.8.0_252-8u252-b09-1~18.04-b09) + }elsif ($out =~ /Runtime\sEnvironment\s\(build\s((\d+)\.(\d+)\.\d+[\+_](\d+))/) { + if($2 eq '1'){ #1.8.x + $version{'major'} = $3; + $version{'release'} = $4; + $version{'build'} = $5; + }else{ #11.0.x + $version{'major'} = $2; + $version{'release'} = $3; + $version{'build'} = $4; + } + $version{'full'} = $1; + + $version{'vendor'} = 'openjdk'; + }else { + $version{'major'} = 0; + $version{'full'} = $out; + $version{'release'} = 0; + $version{'build'} = 0; + } + return %version; +} + +sub get_java_home(){ + my $java_path = &resolve_links('/usr/bin/java'); + $java_path =~ s/\/bin\/java//; + return $java_path; +} + +sub set_default_java{ + my $jdk_dir = $_[0]; + + my $alt_cmd = ""; + if(has_command('alternatives')){ #CentOS + $alt_cmd = 'alternatives'; + }elsif(has_command('update-alternatives')){ #ubuntu + $alt_cmd = 'update-alternatives'; + }else{ + print "Warning: No alternatives command found
"; + } + + if($alt_cmd ne ""){ + print "Updating Java using $alt_cmd
"; + my @jdk_progs = ('java', 'jar', 'javac'); + foreach my $prog (@jdk_progs){ + + $cmd_out=''; + $cmd_err=''; + local $out = &execute_command("$alt_cmd --install /usr/bin/$prog $prog $jdk_dir/bin/$prog 1", undef, \$cmd_out, \$cmd_err, 0, 0); + $out.= &execute_command("$alt_cmd --set $prog $jdk_dir/bin/$prog", undef, \$cmd_out, \$cmd_err, 0, 0); + + if($cmd_err){ + $cmd_err = s/\n/
/g; + &error("Error: $alt_cmd: $cmd_err"); + }elsif($cmd_out){ + $cmd_out = s/\n/
/g; + print &html_escape($cmd_out); + } + } + } + + print "


Setting Java environment variables...
"; + my %os_env; + $os_env{'J2SDKDIR'} = $jdk_dir; + $os_env{'JAVA_HOME'} = $jdk_dir; + $os_env{'DERBY_HOME'}= "$jdk_dir/db"; + $os_env{'J2REDIR'} = "$jdk_dir/jre"; + + if(-e '/etc/profile.d/'){ + $os_env{'PATH'} = "\$PATH:$jdk_dir/bin:$jdk_dir/db/bin:$jdk_dir/jre/bin"; + write_env_file('/etc/profile.d/jdk.sh', \%os_env, 1); + }elsif(-e '/etc/environment'){ + read_env_file('/etc/environment', \%os_env); + $os_env{'PATH'} = "$os_env{'PATH'}:$jdk_dir/bin:$jdk_dir/db/bin:$jdk_dir/jre/bin"; + write_env_file('/etc/environment', \%os_env, 0); + } +} + +sub unset_default_java{ + my $jdk_dir = $_[0]; + print "Removing Java environment variables ...
"; + if(-f '/etc/profile.d/jdk.sh'){ + unlink_file('/etc/profile.d/jdk.sh'); + }elsif(-f '/etc/environment'){ + my %os_env; + read_env_file('/etc/environment', \%os_env); + delete $os_env{'J2SDKDIR'}; + delete $os_env{'JAVA_HOME'}; + delete $os_env{'DERBY_HOME'}; + delete $os_env{'J2REDIR'}; + write_env_file('/etc/environment', \%os_env, 0); + } + + my $alt_cmd = ""; + if(has_command('alternatives')){ #CentOS + $alt_cmd = 'alternatives'; + }elsif(has_command('update-alternatives')){ #ubuntu + $alt_cmd = 'update-alternatives'; + }else{ + print "Warning: No alternatives command found
"; + } + + if($alt_cmd ne ""){ + print "Removing Java using $alt_cmd
"; + my @jdk_progs = ('java', 'jar', 'javac'); + foreach my $prog (@jdk_progs){ + + $cmd_out=''; + $cmd_err=''; + local $out = &execute_command("$alt_cmd --remove $prog $jdk_dir/bin/$prog", undef, \$cmd_out, \$cmd_err, 0, 0); + if($cmd_err){ + &error("Error: $alt_cmd: $cmd_err"); + }else{ + $cmd_out = s/\r\n/
/g; + print &html_escape($cmd_out); + } + } + } +} + +sub get_jdk_dir_by_name{ + my $jdk_name = $_[0]; + my $jdk_dir = ''; + + if($jdk_name =~ /.*openjdk.*/){ + + my $jdk_ver = (split /-/, $jdk_name)[1]; #get version from name + my @known_dirs = ('java-'.$jdk_ver.'-openjdk', 'java-'.$jdk_ver.'-openjdk-amd64', 'jre-'.$jdk_ver.'-openjdk'); + + foreach $jvm_name (@known_dirs){ + if(-d '/usr/lib/jvm/'.$jvm_name){ + $jdk_dir = '/usr/lib/jvm/'.$jvm_name; + last; + } + } + + }else{ + $jdk_dir = '/usr/java/'.$jdk_name; + } + return $jdk_dir; +} + +1; diff --git a/lang/en b/lang/en new file mode 100644 index 0000000..fda3959 --- /dev/null +++ b/lang/en @@ -0,0 +1,121 @@ +index_title=Tomcat Server +index_root=The root directory is $1. + +index_start=Start Server +index_startmsg=Click this button to start the Tomcat server +index_stop=Stop Server +index_stopmsg=Click this button to stop the running Tomcat server +index_restart=Restart Server +index_restartmsg=Click this button to restart the running Tomcat server +index_return=Tomcat +index_install=Install Tomcat +index_upgrade=Upgrade Tomcat + +users_title=Users + +wars_title=WARs +manual_title=Edit config +manual_ecannot=You are not allowed to edit the Tomcat server.xml config file +manual_ok=Edit +manual_efile=Selected file is not part of the Tomcat server configuration +manual_file=Edit config file: +manual_edata=Nothing entered! +manual_err=Failed to save config file + +war_install=Install Application +war_installsource=Install source (.war or .zip) +war_installok=Deploy +wars_tabinstall=Deploy +wars_tabdelete=Undeploy +wars_tablist=List +wars_desc1=Tomcat applications can be installed using .war files from local or remote locations. +wars_desc2=After deleting an application, Tomcat server will be restarted. If you keep, the war file, application will be redeployed! +wars_delete=Delete Application +wars_deleteok=Undeploy +wars_rmwar=Remove war file too +wars_installed=Installed Apps + +install_title=Install WAR +install_err1=Invalid URL +install_err2=Failed to install uploaded module +install_err3=Failed to install module from $1 +install_efile=File does not exist +install_ebrowser=Your browser does not support file uploads + +delete_title=Uninstall WAR +delete_err=Failed to delete modules +delete_enone=No modules selected + +start_err=Failed to start Tomcat +stop_err=Failed to stop Tomcat +restart_err=Failed to restart Tomcat + +java_title=Java +java_tabinstall=Install +java_tabuninstall=Uninstall +java_tabdefault=Default +java_desc1=Install Java Development Kit(JDK) from distribution repository or from Oracle .tar.gz archive +java_desc2=Uninstall Oracle Java 8 files from /usr/share +java_desc3=Set default Java, using update-alternatives and /etc/profile.d/jdk.sh +java_install=Install Options +java_uninstall=Uninstall Options +java_default=update-alternatives Options +jdk_installsource=JDK source +jdk_latest=Oracle JDK +java_installok=Install +java_deleteok=Uninstall +java_defaultok=Update +java_def_jdk=Set as system default Java +java_def_jdk_desc= ( using alternatives ) +java_rm_def_jdk=Remove, if default Java +java_installed=JDK versions +openjdk_latest=OpenJDK +openjdk_headless=Headless package +openjdk_headless_desc=only for OpenJDK + +libs_title=Libraries +libs_desc1=Install libraries into Tomcat's lib/ directory +libs_desc2=Uninstall librarues from Tomcat's lib/ directory +libs_install=Libraries to be installed +libs_delete=Libraries to be uninstalled +libs_installsource=Library source(.zip or .jar) +libs_tabinstall=Install +libs_tabuninstall=Uninstall +libs_installok=Install +libs_deleteok=Uninstall +libs_installed=Libraries found +libs_install_title=Installing Tomcat library +libs_uninstall_title=Uninstalling Tomcat libraries + +source_local=Local file +source_uploaded=Uploaded file +source_ftp=FTP or HTTP URL +source_archive=Apache Archive + +source_err0=File Error +source_err1=Upload Error +source_err1.2=No upload file +source_err2=Download error +source_err3=Invalid URL + +setup_title=Setup + +base_options=Options +base_major=Tomcat Major Version +base_archive=Release +base_installok=Download +base_installsource=Install source +base_desc1=Download an archive of Apache Tomcat Server from Apache website and install it + +proxy_title=Proxy +proxy_add_options=Add proxy +proxy_remove_options=Remove proxy +proxy_default_app=Make this the default (/) +proxy_app_default_warning=Will remove previous default path! +proxy_ssl=Use SSL port +proxy_ssl_info=Use Tomcat HTTPs port +proxy_list=Available proxies +proxy_installok=Add +proxy_removeok=Remove +proxy_wildcard=Add Wildcard map +proxy_wildcard_info=Proxy Apache:80 to Tomcat:8080 diff --git a/module.info b/module.info new file mode 100644 index 0000000..b419d77 --- /dev/null +++ b/module.info @@ -0,0 +1,3 @@ +desc=Apache Tomcat +os_support=*-linux freebsd archlinux +category=servers diff --git a/restart.cgi b/restart.cgi new file mode 100644 index 0000000..8599e08 --- /dev/null +++ b/restart.cgi @@ -0,0 +1,15 @@ +#!/usr/bin/perl +# restart.cgi +# Restart the tomcat daemon + +require './tomcat-lib.pl'; +&ReadParse(); +&error_setup($text{'restart_err'}); +my ($rc, $err) = tomcat_service_ctl('restart'); +if ($rc != 0){ + &ui_print_header(undef, $text{'index_title'}, ""); + &error($err); + &ui_print_footer("", $text{'index_return'}); + exit; +} +&redirect(""); diff --git a/save_manual.cgi b/save_manual.cgi new file mode 100644 index 0000000..977a3cf --- /dev/null +++ b/save_manual.cgi @@ -0,0 +1,27 @@ +#!/usr/bin/perl +# Update a manually edited config file + +require './tomcat-lib.pl'; +&error_setup($text{'manual_err'}); +&ReadParseMime(); + +my $catalina_home = get_catalina_home(); + +# Work out the file +@files = ( "$catalina_home/bin/setenv.sh", + "$catalina_home/conf/context.xml", + "$catalina_home/conf/server.xml", + "$catalina_home/conf/tomcat-users.xml", + "$catalina_home/conf/web.xml"); +&indexof($in{'file'}, @files) >= 0 || &error($text{'manual_efile'}); +$in{'data'} =~ s/\r//g; +$in{'data'} =~ /\S/ || &error($text{'manual_edata'}); + +# Write to it +&open_lock_tempfile(DATA, ">$in{'file'}"); +&print_tempfile(DATA, $in{'data'}); +&close_tempfile(DATA); + +&webmin_log("manual", undef, $in{'file'}); +&redirect(""); + diff --git a/scripts/alma-rocky.sh b/scripts/alma-rocky.sh new file mode 100644 index 0000000..1e38817 --- /dev/null +++ b/scripts/alma-rocky.sh @@ -0,0 +1,95 @@ +# !/bin/bash -e +# Tomcat Module Script for Rocky Linux +# Usage: +# wget https://raw.githubusercontent.com/cited/Tomcat-Webmin-Module/master/scripts/rocky-linux.sh +# chmod +x pre-installer +# ./pre-installer.sh + +function get_deps(){ + + yum -y install wget unzip bzip2 + +} + +function setup_selinux(){ + + #allow apache port for django app + semanage port -a -t http_port_t -p tcp 7800 + semanage port -m -t http_port_t -p tcp 9000 + + setsebool -P httpd_can_network_connect 1 +} + + +function install_apache(){ + + yum -y install httpd + +} + +function install_webmin(){ + wget -P/tmp 'https://download.webmin.com/developers-key.asc' + rpm --import /tmp/developers-key.asc || true + cp -f /tmp/developers-key.asc /etc/pki/rpm-gpg/RPM-GPG-KEY-webmin-developers + + cat >/etc/yum.repos.d/webmin.repo < Tomcat to complete installation" + +} + +get_deps; +#install_apache; +#install_webmin; +#download_certbot_module; +setup_selinux; +#install_certbot_module; +download_tomcat_module; +install_tomcat_module; diff --git a/scripts/index.rst b/scripts/index.rst new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/scripts/index.rst @@ -0,0 +1 @@ +1 diff --git a/scripts/pre-install.sh b/scripts/pre-install.sh new file mode 100644 index 0000000..9de6a81 --- /dev/null +++ b/scripts/pre-install.sh @@ -0,0 +1,124 @@ +# !/bin/bash -e +# Tomcat Module Script for CentOS and Ubuntu +# For use on clean CentOS or Ubuntu box only +# Usage: +# wget https://raw.githubusercontent.com/cited/Tomcat-Webmin-Module/master/scripts/pre-install.sh +# chmod +x pre-installer +# ./pre-installer.sh + +function get_repo(){ + if [ -f /etc/centos-release ]; then + REPO='rpm' + + elif [ -f /etc/debian_version ]; then + REPO='apt' +fi +} + +function install_webmin(){ + + if [ "${REPO}" == 'apt' ]; then + + echo "deb http://download.webmin.com/download/repository sarge contrib" > /etc/apt/sources.list.d/webmin.list + wget -qO - http://www.webmin.com/jcameron-key.asc | apt-key add - + apt-get -y update + apt-get -y install webmin + + elif [ "${REPO}" == 'rpm' ]; then + + + + + + wget -P/tmp 'https://download.webmin.com/developers-key.asc' + rpm --import /tmp/developers-key.asc || true + cp -f /tmp/developers-key.asc /etc/pki/rpm-gpg/RPM-GPG-KEY-webmin-developers + + cat >/etc/yum.repos.d/webmin.repo < Tomcat to complete installation" + +} + + + +function download_certbot_module(){ +pushd /tmp/ + wget https://github.com/cited/Certbot-Webmin-Module/archive/master.zip + unzip master.zip + mv Certbot-Webmin-Module-master certbot + tar -czf /opt/certbot.wbm.gz certbot + rm -rf certbot master.zip +popd +} + +function install_apache(){ + if [ "${REPO}" == 'apt' ]; then + apt-get -y install apache2 + elif [ "${REPO}" == 'rpm' ]; then + yum -y install httpd + fi +} + +function install_certbot_module(){ +pushd /opt/ + if [ "${REPO}" == 'apt' ]; then + /usr/share/webmin/install-module.pl certbot.wbm.gz + elif [ "${REPO}" == 'rpm' ]; then + /usr/libexec/webmin/install-module.pl certbot.wbm.gz + fi +popd + echo -e "Certbot is now installed. Go to Servers > Certbot to complete installation" + +} + +function get_deps(){ +if [ "${REPO}" == 'apt' ]; then + apt-get -y install wget unzip + elif [ "${REPO}" == 'rpm' ]; then + yum -y install wget unzip bzip2 + fi +} + +get_repo; +get_deps; +# Uncomment line(s) below if you wish to install Webmin, Apache HTTP Server, and Certbot as well. +#install_webmin; +#install_apache; +#download_certbot_module; +#install_certbot_module; +download_tomcat_module; +install_tomcat_module; diff --git a/scripts/rocky-linux.sh b/scripts/rocky-linux.sh new file mode 100644 index 0000000..1e38817 --- /dev/null +++ b/scripts/rocky-linux.sh @@ -0,0 +1,95 @@ +# !/bin/bash -e +# Tomcat Module Script for Rocky Linux +# Usage: +# wget https://raw.githubusercontent.com/cited/Tomcat-Webmin-Module/master/scripts/rocky-linux.sh +# chmod +x pre-installer +# ./pre-installer.sh + +function get_deps(){ + + yum -y install wget unzip bzip2 + +} + +function setup_selinux(){ + + #allow apache port for django app + semanage port -a -t http_port_t -p tcp 7800 + semanage port -m -t http_port_t -p tcp 9000 + + setsebool -P httpd_can_network_connect 1 +} + + +function install_apache(){ + + yum -y install httpd + +} + +function install_webmin(){ + wget -P/tmp 'https://download.webmin.com/developers-key.asc' + rpm --import /tmp/developers-key.asc || true + cp -f /tmp/developers-key.asc /etc/pki/rpm-gpg/RPM-GPG-KEY-webmin-developers + + cat >/etc/yum.repos.d/webmin.repo < Tomcat to complete installation" + +} + +get_deps; +#install_apache; +#install_webmin; +#download_certbot_module; +setup_selinux; +#install_certbot_module; +download_tomcat_module; +install_tomcat_module; diff --git a/scripts/tomcat.wbm.gz b/scripts/tomcat.wbm.gz new file mode 100644 index 0000000..f96281b Binary files /dev/null and b/scripts/tomcat.wbm.gz differ diff --git a/scripts/ubuntu.sh b/scripts/ubuntu.sh new file mode 100644 index 0000000..9de6a81 --- /dev/null +++ b/scripts/ubuntu.sh @@ -0,0 +1,124 @@ +# !/bin/bash -e +# Tomcat Module Script for CentOS and Ubuntu +# For use on clean CentOS or Ubuntu box only +# Usage: +# wget https://raw.githubusercontent.com/cited/Tomcat-Webmin-Module/master/scripts/pre-install.sh +# chmod +x pre-installer +# ./pre-installer.sh + +function get_repo(){ + if [ -f /etc/centos-release ]; then + REPO='rpm' + + elif [ -f /etc/debian_version ]; then + REPO='apt' +fi +} + +function install_webmin(){ + + if [ "${REPO}" == 'apt' ]; then + + echo "deb http://download.webmin.com/download/repository sarge contrib" > /etc/apt/sources.list.d/webmin.list + wget -qO - http://www.webmin.com/jcameron-key.asc | apt-key add - + apt-get -y update + apt-get -y install webmin + + elif [ "${REPO}" == 'rpm' ]; then + + + + + + wget -P/tmp 'https://download.webmin.com/developers-key.asc' + rpm --import /tmp/developers-key.asc || true + cp -f /tmp/developers-key.asc /etc/pki/rpm-gpg/RPM-GPG-KEY-webmin-developers + + cat >/etc/yum.repos.d/webmin.repo < Tomcat to complete installation" + +} + + + +function download_certbot_module(){ +pushd /tmp/ + wget https://github.com/cited/Certbot-Webmin-Module/archive/master.zip + unzip master.zip + mv Certbot-Webmin-Module-master certbot + tar -czf /opt/certbot.wbm.gz certbot + rm -rf certbot master.zip +popd +} + +function install_apache(){ + if [ "${REPO}" == 'apt' ]; then + apt-get -y install apache2 + elif [ "${REPO}" == 'rpm' ]; then + yum -y install httpd + fi +} + +function install_certbot_module(){ +pushd /opt/ + if [ "${REPO}" == 'apt' ]; then + /usr/share/webmin/install-module.pl certbot.wbm.gz + elif [ "${REPO}" == 'rpm' ]; then + /usr/libexec/webmin/install-module.pl certbot.wbm.gz + fi +popd + echo -e "Certbot is now installed. Go to Servers > Certbot to complete installation" + +} + +function get_deps(){ +if [ "${REPO}" == 'apt' ]; then + apt-get -y install wget unzip + elif [ "${REPO}" == 'rpm' ]; then + yum -y install wget unzip bzip2 + fi +} + +get_repo; +get_deps; +# Uncomment line(s) below if you wish to install Webmin, Apache HTTP Server, and Certbot as well. +#install_webmin; +#install_apache; +#download_certbot_module; +#install_certbot_module; +download_tomcat_module; +install_tomcat_module; diff --git a/setup.cgi b/setup.cgi new file mode 100644 index 0000000..3079809 --- /dev/null +++ b/setup.cgi @@ -0,0 +1,307 @@ +#!/usr/bin/perl + +require './tomcat-lib.pl'; +require '../webmin/webmin-lib.pl'; #for OS detection +foreign_require('software', 'software-lib.pl'); + +sub add_tomcat_user{ + #check if tomcat user exists + if(read_file_contents('/etc/passwd') !~ /\ntomcat:/){ + #add tomcat user + local $out = &backquote_command('useradd -m tomcat', 0); + }elsif(! -d '/home/tomcat'){ + &make_dir("/home/tomcat", 0755, 1); + &set_ownership_permissions('tomcat','tomcat', undef, '/home/tomcat'); + } +} + +sub setup_catalina_env{ + my $tomcat_ver = $_[0]; + + my %os_env; + + print "
Setting CATALINA environment..."; + + read_env_file('/etc/environment', \%os_env); + $os_env{'CATALINA_HOME'} = "/home/tomcat/apache-tomcat-$tomcat_ver/"; + $os_env{'CATALINA_BASE'} = "/home/tomcat/apache-tomcat-$tomcat_ver/"; + write_env_file('/etc/environment', \%os_env, 0); + + open(my $fh, '>>', "/home/tomcat/apache-tomcat-$tomcat_ver/bin/setenv.sh") or die "open:$!"; + print $fh "CATALINA_PID=\"/home/tomcat/apache-tomcat-$tomcat_ver/temp/tomcat.pid\"\n"; + close $fh; +} + +sub setup_tomcat_users{ + my $tomcat_ver = $_[0]; + my @pw_chars = ("A".."Z", "a".."z", "0".."9", "_", "-"); + my $manager_pass; + my $admin_pass; + + $manager_pass .= $pw_chars[rand @pw_chars] for 1..32; + $admin_pass .= $pw_chars[rand @pw_chars] for 1..32; + + #Save tomcat-users.xml + open(my $fh, '>', "/home/tomcat/apache-tomcat-$tomcat_ver/conf/tomcat-users.xml") or die "open:$!"; + print $fh < + + + + + + + +EOF + close $fh; + print "
Setting Tomcat users..."; +} + +sub install_tomcat_from_archive{ + + add_tomcat_user(); + my $tomcat_ver = download_and_install($in{'source_archive'}); + + setup_catalina_env($tomcat_ver); + setup_tomcat_users($tomcat_ver); + setup_tomcat_service($tomcat_ver); +} + +sub get_apache_proxy_file(){ + my $proxy_file; + my %osinfo = &detect_operating_system(); + if( ( $osinfo{'real_os_type'} =~ /centos/i) or #CentOS + ( $osinfo{'real_os_type'} =~ /rocky/i) or #rocky + ( $osinfo{'real_os_type'} =~ /alma/i) or #alma + ($osinfo{'real_os_type'} =~ /fedora/i) ){ #Fedora + if( ! -d '/etc/httpd/'){ + return 0; + } + $proxy_file = '/etc/httpd/conf.d/tomcat.conf'; + + }elsif( ($osinfo{'real_os_type'} =~ /ubuntu/i) or + ($osinfo{'real_os_type'} =~ /debian/i) ){ #ubuntu or debian + if( ! -d '/etc/apache2/'){ + return 0; + } + $proxy_file = '/etc/apache2/conf-enabled/tomcat.conf'; + } + return $proxy_file; +} + +sub setup_default_apache_proxy(){ + my $proxy_file = get_apache_proxy_file(); + my %osinfo = &detect_operating_system(); + + if(-f $proxy_file){ + return 0; + } + + open(my $fh, '>', $proxy_file) or die "open:$!"; + + if( ($osinfo{'real_os_type'} =~ /centos/i) or #CentOS + ($osinfo{'real_os_type'} =~ /fedora/i) ){ #Fedora + + &execute_command('setsebool httpd_can_network_connect 1'); + + print $fh "LoadModule proxy_module modules/mod_proxy.so\n"; + print $fh "LoadModule proxy_http_module modules/mod_proxy_http.so\n"; + print $fh "LoadModule rewrite_module modules/mod_rewrite.so\n"; + + }elsif( $osinfo{'os_type'} =~ /debian/i){ #ubuntu or debian + + print $fh "LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so\n"; + print $fh "LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so\n"; + print $fh "LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so\n"; + } + + print $fh "ProxyRequests Off\n"; + print $fh "ProxyPreserveHost On\n"; + print $fh " \n"; + print $fh " Order allow,deny\n"; + print $fh " Allow from all\n"; + print $fh " \n"; + print $fh "ProxyPass / http://localhost:8080/\n"; + print $fh "ProxyPassReverse / http://localhost:8080/\n"; + + close $fh; + + print "Added proxy configuration / -> 8080 in $proxy_file\n"; +} + +sub select_tomcat_archive{ + print "$text{'base_desc1'}

\n"; + print &ui_form_start("setup.cgi", "form-data"); + print ui_hidden('mode', 'tomcat_install'); + print &ui_table_start($text{'base_options'}, undef, 2); + + my @tmver = &get_tomcat_major_versions(); + my $sel_tmver = $in{'tmver'} || $tmver[0]; + my @tm_opts = ( ); + foreach my $v (@tmver) { + push(@tm_opts, [ $v, $v ]); + } + + print < + function update_select(){ + var majorSel = document.getElementById('base_major'); + var major = majorSel.options[majorSel.selectedIndex].value; + + get_pjax_content('/tomcat/setup.cgi?mode=tomcat_install_form&tmver='+major); + } + +EOF + + print &ui_table_row($text{'base_major'}, + &ui_select("base_major", $sel_tmver, \@tm_opts, 1, 0, undef, undef, 'id="base_major" onchange="update_select()"')); + + my @tver = &major_tomcat_versions($sel_tmver); + my @tver_opts = ( ); + foreach my $v (reverse @tver) { + push(@tver_opts, [ $v, $v ]); + } + + print &ui_table_row($text{'base_installsource'}, + &ui_radio_table("source", 100, + [ [ 100, $text{'source_archive'}, &ui_select("source_archive", undef, \@tver_opts,1, 0)], + [ 0, $text{'source_local'}, &ui_textbox("file", undef, 40)." ". &file_chooser_button("file", 0) ], + [ 1, $text{'source_uploaded'}, &ui_upload("upload", 40) ], + [ 2, $text{'source_ftp'},&ui_textbox("url", undef, 40) ] + ])); + + print &ui_table_end(); + print &ui_form_end([ [ "", $text{'base_installok'} ] ]); +} + +sub setup_selinux{ + my $tomcat_home = get_catalina_home(); + + local $out = &execute_command("semanage fcontext -a -t bin_t \"$tomcat_home/bin(/.*)?\"", undef, \$cmd_out, \$cmd_err, 0, 0); + print &html_escape($cmd_out.$cmd_err); + + local $out = &execute_command("restorecon -r -v \"$tomcat_home/bin\"", undef, \$cmd_out, \$cmd_err, 0, 0); + print &html_escape($cmd_out.$cmd_err); +} + +sub setup_checks{ + + my %osinfo = &detect_operating_system(); + + #Check for commands + if (!&has_command('java')) { + print '

Warning: Java is not found. Install it manually or from the '. + "Java tab

"; + } + + my @pinfo = software::package_info('haveged', undef, ); + if(!@pinfo){ + if( ($osinfo{'real_os_type'} =~ /centos/i) or #CentOS + ($osinfo{'real_os_type'} =~ /alma/i) or #Alma + ($osinfo{'real_os_type'} =~ /rocky/i) ){ #Rocky + @pinfo = software::package_info('epel-release', undef, ); + if(!@pinfo){ + print "

Warning: haveged needs epel-release. Install it manually or ". + "click here to have it downloaded and installed.

"; + } + } + print "

Warning: haveged package is not installed. Install it manually or ". + "click here to have it downloaded and installed.

"; + } + + my $tomcat_ver = installed_tomcat_version(); + if(!$tomcat_ver){ + print "

Click here to install Tomcat from Apache site.

"; + } + + if (!&has_command('unzip')) { + print '

Warning: unzip command is not found. Install it manually or '. + "click here to have it downloaded and installed.

"; + } + + my $proxy_file = get_apache_proxy_file(); + my $www_name = ''; + + if( ( $osinfo{'real_os_type'} =~ /centos/i) or #CentOS + ( $osinfo{'real_os_type'} =~ /rocky/i) or #Rocky + ( $osinfo{'real_os_type'} =~ /alma/i) or #Alma + ($osinfo{'real_os_type'} =~ /fedora/i) ){ #Fedora + $www_name = 'httpd'; + + }elsif( ($osinfo{'real_os_type'} =~ /ubuntu/i) or + ($osinfo{'real_os_type'} =~ /debian/i) ){ #ubuntu or debian + $www_name = 'apache2'; + } + + @pinfo = software::package_info($www_name, undef, ); + if(!@pinfo){ + print "

Warning: $www_name is not installed. Install it manually or ". + "click here to have it downloaded and installed.

"; + } + + if(! -f $proxy_file){ + print "

Apache default proxy is not configured. ". + "click here

"; + } + + if(@pinfo){ + if( ($osinfo{'real_os_type'} =~ /alma/i) or #Alma + ($osinfo{'real_os_type'} =~ /rocky/i) ){ #Rocky + + local $out = &execute_command("sestatus", undef, \$cmd_out, \$cmd_err, 0, 0); + if($cmd_out =~ /SELinux status:\s+enabled/i){ + my $se_utils_pkg = 'policycoreutils-python-utils'; + @pinfo = software::package_info($se_utils_pkg, undef, ); + if(!@pinfo){ + print "

Warning: $se_utils_pkg is not installed. Install it manually or ". + "click here to have it downloaded and installed.

"; + }else{ + my $tomcat_home = get_catalina_home(); + local $out = &execute_command("ls -lZ $tomcat_home/bin/startup.sh", undef, \$cmd_out, \$cmd_err, 0, 0); + if($cmd_out !~ /:bin_t:/i){ + printf "

SELinux is enabled. Configured it from ". + "here.

"; + } + } + } + } + } + print '

If you don\'t see any warning above, you can complete setup from '. + "here

"; +} + +#Remove all setup files +sub setup_cleanup{ + my $file = $module_root_directory.'/setup.cgi'; + print "Completing Installation
"; + &unlink_file($file); + print &js_redirect("index.cgi"); +} + + +&ui_print_header(undef, $text{'setup_title'}, ""); + +if($ENV{'CONTENT_TYPE'} =~ /boundary=(.*)$/) { + &ReadParseMime(); +}else { + &ReadParse(); $no_upload = 1; +} + +my $mode = $in{'mode'} || "checks"; + +if($mode eq "checks"){ setup_checks(); + &ui_print_footer('', $text{'index_return'}); + exit 0; +}elsif($mode eq "cleanup"){ setup_cleanup(); + &ui_print_footer('', $text{'index_return'}); + exit 0; +}elsif($mode eq "tomcat_install_form"){ select_tomcat_archive(); +}elsif($mode eq "tomcat_install"){ install_tomcat_from_archive(); +}elsif($mode eq "tomcat_upgrade"){ upgrade_tomcat_from_archive(); +}elsif($mode eq "setup_apache_proxy"){ setup_default_apache_proxy(); +}elsif($mode eq "setup_selinux"){ setup_selinux(); +}else{ + print "Error: Invalid setup mode\n"; +} + +&ui_print_footer('setup.cgi', $text{'setup_title'}); diff --git a/start.cgi b/start.cgi new file mode 100644 index 0000000..4a94b3c --- /dev/null +++ b/start.cgi @@ -0,0 +1,15 @@ +#!/usr/bin/perl +# start.cgi +# Start the tomcat daemon + +require './tomcat-lib.pl'; +&ReadParse(); +&error_setup($text{'start_err'}); +my ($rc, $err) = tomcat_service_ctl('start'); +if ($rc != 0){ + &ui_print_header(undef, $text{'index_title'}, ""); + &error($err); + &ui_print_footer("", $text{'index_return'}); + exit; +} +&redirect(""); diff --git a/stop.cgi b/stop.cgi new file mode 100644 index 0000000..a5d1ad1 --- /dev/null +++ b/stop.cgi @@ -0,0 +1,14 @@ +#!/usr/bin/perl + +require './tomcat-lib.pl'; +&ReadParse(); +&error_setup($text{'stop_err'}); +my ($rc, $err) = tomcat_service_ctl('stop'); +if ($rc != 0){ + &ui_print_header(undef, $text{'index_title'}, ""); + &error($err); + &ui_print_footer("", $text{'index_return'}); + exit; +} +&redirect(""); + diff --git a/tomcat-lib.pl b/tomcat-lib.pl new file mode 100644 index 0000000..770703b --- /dev/null +++ b/tomcat-lib.pl @@ -0,0 +1,408 @@ +=head1 tomcat-lib.pl + +Functions for managing Tomcat server configuration files. + + foreign_require("tomcat", "tomcat-lib.pl"); + @sites = tomcat::list_tomcat_websites() + +=cut + +BEGIN { push(@INC, ".."); }; +use WebminCore; +use File::Copy; +init_config(); + +sub get_tomcat_config +{ +my $lref = &read_file_lines($config{'foobar_conf'}); +my @rv; +my $lnum = 0; +foreach my $line (@$lref) { + my ($n, $v) = split(/\s+/, $line, 2); + if ($n) { + push(@rv, { 'name' => $n, 'value' => $v, 'line' => $lnum }); + } + $lnum++; + } +return @rv; +} + +# Returns a hash containing the version type, number and full version +sub get_catalina_version +{ + local %version; + local $catalina_home = get_catalina_home(); + local $out = &backquote_command($catalina_home."/bin/catalina.sh version 2>&1 : '.$1."
"; + } + } + } + + $running = $out >> 8; + if($ctl eq 'status'){ + # swap running values, to match init.d logic + if($running == 0){ + $running = 1; + }elsif($running > 0){ + $running = 0; + } + } + + }else{ + local $out = &execute_command("/etc/init.d/tomcat $ctl", undef, \$cmd_out, \$cmd_err, 0, 0); + + $running = $out >> 8; + if($cmd_err ne ""){ + $status = $cmd_err; + }else{ + $status = $cmd_out; + } + } + + return ($running, $status); +} + +sub get_all_war_infos(){ + my $catalina_home = get_catalina_home(); + opendir(DIR, $catalina_home.'/webapps') or die $!; + my @dirs + = grep { + ! /^\./ # Doesn't begins with a period + && -d "$catalina_home/webapps/$_" # and is a directory + } readdir(DIR); + closedir(DIR); + + return sort @dirs; +} + +sub file_basename +{ + my $rv = $_[0]; + $rv =~ s/^.*[\/\\]//; + return $rv; +} + +sub sort_version { + my @A = split(/\./, $a); + my @B = split(/\./, $b); + # a sort subroutine, expect $a and $b + for(my $i=0; $i < 3; $i++){ + if ($A[$i] < $B[$i]) { return -1 } elsif ($A[$i] > $B[$i]) { return 1 } + } + return 0; +} + +sub latest_tomcat_version{ + my $tomcat_ver = $_[0]; + my %version; + if(-f "$module_config_directory/version"){ + read_file_cached("$module_config_directory/version", \%version); + + if( $version{'updated'} >= (time() - 86400)){ #if last update was less than a day ago + return $version{'latest'} if ($version{'latest'} ne '0.0.0'); + } + } + + my $major = (split /\./, $tomcat_ver)[0]; + my @all_ver = &major_tomcat_versions($major); + my $latest_ver = $all_ver[-1]; + + #renew the updated timestamp and latest version + $version{'updated'} = time(); + $version{'latest'} = $latest_ver; + &write_file("$module_config_directory/version", \%version); + + return $latest_ver; +} + +sub installed_tomcat_version(){ + my %os_env; + read_env_file('/etc/environment', \%os_env); + + if($os_env{'CATALINA_HOME'}){ + $os_env{'CATALINA_HOME'} =~ /\/home\/tomcat\/apache-tomcat-([0-9\.]+)/; + return $1; + }else{ + return undef; + } +} + +sub get_catalina_home(){ + my $tomcat_ver = installed_tomcat_version(); + return "/home/tomcat/apache-tomcat-$tomcat_ver"; +} + +sub download_and_install{ + my $tomcat_ver = $_[0]; + my $major = (split /\./, $tomcat_ver)[0]; + + #download tomcat archive + $in{'url'} = "https://archive.apache.org/dist/tomcat/tomcat-$major/v$tomcat_ver/bin/apache-tomcat-$tomcat_ver.tar.gz"; + $in{'source'} = 2; + + my $tmpfile = process_file_source(); + + #extract tomcat archive + my $cmd_out=''; + my $cmd_err=''; + print "
Extracting to /home/tomcat/apache-tomcat-$tomcat_ver/ ...
"; + local $out = &execute_command("tar -x -v --overwrite -f \"$tmpfile\" -C/home/tomcat/", undef, \$cmd_out, \$cmd_err, 0, 0); + + if($cmd_err ne ""){ + &error("Error: tar: $cmd_err"); + }else{ + $cmd_out = s/\n/
/g; + print &html_escape($cmd_out); + print "Done
"; + } + + #folder is created after tomcat is started, but we need it now + &make_dir("/home/tomcat/apache-tomcat-$tomcat_ver/conf/Catalina/localhost/", 0755, 1); + + open(my $fh, '>', "/home/tomcat/apache-tomcat-$tomcat_ver/conf/Catalina/localhost/manager.xml") or die "open:$!"; + print $fh < + + +EOF + close $fh; + + #&set_ownership_permissions('tomcat','tomcat', undef, "/home/tomcat/apache-tomcat-$tomcat_ver/"); + &execute_command("chown -R tomcat:tomcat /home/tomcat/apache-tomcat-$tomcat_ver"); + + return $tomcat_ver; +} + +sub setup_catalina_env{ + my $tomcat_ver = $_[0]; + + my %os_env; + + print "
Setting CATALINA environment..."; + + read_env_file('/etc/environment', \%os_env); + $os_env{'CATALINA_HOME'} = "/home/tomcat/apache-tomcat-$tomcat_ver/"; + $os_env{'CATALINA_BASE'} = "/home/tomcat/apache-tomcat-$tomcat_ver/"; + write_env_file('/etc/environment', \%os_env, 0); + + open(my $fh, '>>', "/home/tomcat/apache-tomcat-$tomcat_ver/bin/setenv.sh") or die "open:$!"; + print $fh "CATALINA_PID=\"/home/tomcat/apache-tomcat-$tomcat_ver/temp/tomcat.pid\"\n"; + close $fh; +} + +sub get_installed_libs{ + opendir(DIR, $module_config_directory) or die $!; + my @lib_lists + = grep { + /^lib_[a-z0-9\.\-_\s]+\.list$/i # + && -f "$module_config_directory/$_" # and is a file + } readdir(DIR); + closedir(DIR); + + return sort @lib_lists; +} + +sub process_file_source{ + my $file = ''; + + if (($in{'source'} == 0) && ($in{'file'} ne "")) { # from local file + &error_setup(&text('source_err0', $in{'file'})); + $file = $in{'file'}; + if (!(-r $file)){ + &error($text{'source_err0'}); + } + + }elsif (($in{'source'} == 1) && ($in{'upload_filename'} ne "")) { # from uploaded file + &error_setup($text{'source_err1'}); + $need_unlink = 1; + if ($no_upload) { + &error($text{'source_err1.2'}); + } + $file = transname(file_basename($in{'upload_filename'})); + open(MOD, ">$file"); + binmode(MOD); + print MOD $in{'upload'}; + close(MOD); + + }elsif ($in{'source'} == 2 and $in{'url'} ne '') { # from ftp or http url (possible third-party) + $url = $in{'url'}; + &error_setup(&text('source_err2', $url)); + $file = &transname(file_basename($url)); + $need_unlink = 1; + my $error; + $progress_callback_url = $url; + if ($url =~ /^(http|https):\/\/([^\/]+)(\/.*)$/) { + $ssl = $1 eq 'https'; + $host = $2; $page = $3; $port = $ssl ? 443 : 80; + if ($host =~ /^(.*):(\d+)$/) { $host = $1; $port = $2; } + my %cookie_headers = ('Cookie'=>'oraclelicense=accept-securebackup-cookie'); + &http_download($host, $port, $page, $file, \$error, + \&progress_callback, $ssl, undef, undef, 0, 0, 1, \%cookie_headers); + } elsif ( + $url =~ /^ftp:\/\/([^\/]+)(:21)?\/(.*)$/) { + $host = $1; $ffile = $3; + &ftp_download($host, $ffile, $file, \$error, \&progress_callback); + }else { + &error($text{'source_err3'}); + } + &error($error) if ($error); + } + return $file; +} + +sub unzip_file{ + my $file = $_[0]; + my @suffixlist = ('.zip'); + ($lib_name,$path,$lib_suffix) = fileparse($file,@suffixlist); + + my $unzip_dir = "/tmp/.webmin/$lib_name"; + + #if old temp extension dir exist, remove it + #if( -d $unzip_dir and rmtree($unzip_dir) == 0){ + # &error("Failed to remove temp extension dir"); + # &ui_print_footer("", $text{'index_return'}); + # exit; + #} + &make_dir($unzip_dir, 0754, 1); + + my $unzip_out; + my $unzip_err; + print "
Unzipping to $unzip_dir ...
"; + local $out = &execute_command("unzip -u \"$file\" -d \"$unzip_dir\"", undef, \$unzip_out, \$unzip_err, 0, 0); + + if($unzip_err){ + &error("Error: unzip: $unzip_err"); + }else{ + $unzip_out = s/\r\n/
/g; + print &html_escape($unzip_out); + } + return $unzip_dir; +} + +sub get_tomcat_major_versions(){ + my @majors = (); + my $url = "https://archive.apache.org/dist/tomcat/"; + &error_setup(&text('install_err3', $url)); + my $error = ''; + my $tmpfile = &transname('tomcat.html'); + + + &http_download('archive.apache.org', 80, "/dist/tomcat/", $tmpfile, \$error); + if($error){ + error($error); + } + + my @latest_versions; + open(my $fh, '<', $tmpfile) or die "open:$!"; + while(my $line = <$fh>){ + if($line =~ /tomcat\-[0-9\.]+\/<\/a>/){ + push(@majors, $1); + } + } + close $fh; + + return reverse sort sort_version @majors; +} + +sub major_tomcat_versions{ + my $major = $_[0]; #Tomcat major version 6,7,8,9 + + my $url = "https://archive.apache.org/dist/tomcat/tomcat-$major/"; + &error_setup(&text('install_err3', $url)); + my $error = ''; + my $tmpfile = &transname('tomcat.html'); + + + &http_download('archive.apache.org', 80, "/dist/tomcat/tomcat-$major/", $tmpfile, \$error); + if($error){ + error($error); + } + + my @latest_versions; + open(my $fh, '<', $tmpfile) or die "open:$!"; + while(my $line = <$fh>){ + if($line =~ /v[0-9\.]+\/<\/a>/){ + push(@latest_versions, $1); + } + } + close $fh; + + return sort sort_version @latest_versions; +} + +sub setup_tomcat_service{ + my $tomcat_ver = $_[0]; + if (&has_command('systemctl')) { + + copy_source_dest("$module_root_directory/tomcat.service", '/etc/systemd/system/tomcat.service'); + + my $ln = 0; + $lref = read_file_lines('/etc/systemd/system/tomcat.service'); + foreach $line (@$lref){ + chomp $line; + if($line =~ /\$TOMCAT_VER/){ #if its a section start + $line =~ s/\$TOMCAT_VER/$tomcat_ver/; + @{$lref}[$ln] = $line; + }elsif($line =~ /\$CATALINA_HOME/){ + $line =~ s/\$CATALINA_HOME/\/home\/tomcat\/apache-tomcat-$tomcat_ver/; + @{$lref}[$ln] = $line; + } + $ln=$ln+1; + } + &flush_file_lines('/etc/systemd/system/tomcat.service'); + + &set_ownership_permissions('root','root', 0555, "/etc/systemd/system/tomcat.service"); + + &backquote_command("systemctl daemon-reload", undef, \$cmd_out, \$cmd_err, 0, 0); + }else{ + copy_source_dest("$module_root_directory/tomcat.init", '/etc/init.d/tomcat'); + &set_ownership_permissions('root','root', 0555, "/etc/init.d/tomcat"); + } + print "
Setting Tomcat service ..."; +} + +sub upgrade_available(){ + my $tomcat_ver = installed_tomcat_version(); + my $latest_ver = latest_tomcat_version($tomcat_ver); + + my @versions = ($tomcat_ver, $latest_ver); + @versions = sort sort_version @versions; + + if($versions[0] eq $tomcat_ver){ + return ''; + }else { + return $latest_ver; + } +} \ No newline at end of file diff --git a/tomcat.init b/tomcat.init new file mode 100644 index 0000000..4276ed1 --- /dev/null +++ b/tomcat.init @@ -0,0 +1,57 @@ +#!/bin/bash +### BEGIN INIT INFO +# Provides: tomcat +# Required-Start: $network +# Required-Stop: $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start/Stop Tomcat server +### END INIT INFO + +# Source function library. +. /etc/environment; #Catalina variables +. $CATALINA_HOME/bin/setenv.sh + +RETVAL=$? + +function start(){ + echo "Starting Tomcat" + /bin/su - tomcat $CATALINA_HOME/bin/startup.sh + RETVAL=$? +} + +function stop(){ + echo "Stopping Tomcat" + /bin/su - tomcat -c "$CATALINA_HOME/bin/shutdown.sh 60 -force" + RETVAL=$? +} + +case "$1" in + start) + start; + ;; + stop) + stop; + ;; + restart) + echo "Restarting Tomcat" + stop; + start; + ;; + status) + + if [ -f "${CATALINA_PID}" ]; then + TOMCAT_PID=$(cat "${CATALINA_PID}") + echo "Tomcat is running with PID ${TOMCAT_PID}"; + RETVAL=1 + else + echo "Tomcat is not running"; + RETVAL=0 + fi + ;; + *) + echo $"Usage: $0 {start|stop|restart|status}" + exit 1 + ;; +esac +exit $RETVAL diff --git a/tomcat.service b/tomcat.service new file mode 100644 index 0000000..70a4765 --- /dev/null +++ b/tomcat.service @@ -0,0 +1,19 @@ +[Unit] +Description=Tomcat $TOMCAT_VER +After=multi-user.target + +[Service] +User=tomcat +Group=tomcat + +WorkingDirectory=$CATALINA_HOME +Type=forking +Restart=always + +EnvironmentFile=/etc/environment + +ExecStart=$CATALINA_HOME/bin/startup.sh +ExecStop=$CATALINA_HOME/bin/shutdown.sh 60 -force + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/tomcat_upgrade.cgi b/tomcat_upgrade.cgi new file mode 100644 index 0000000..debf6a0 --- /dev/null +++ b/tomcat_upgrade.cgi @@ -0,0 +1,75 @@ +#!/usr/bin/perl + +require './tomcat-lib.pl'; + +sub migrate_settings_and_apps{ + my $old_ver = $_[0]; + my $new_ver = $_[1]; + my $apps_ref = $_[2]; + + #Copy Settings + my @files = ('bin/setenv.sh', 'conf/tomcat-users.xml'); + foreach my $file (@files){ + if( -f "/home/tomcat/apache-tomcat-$old_ver/$file"){ + copy_source_dest("/home/tomcat/apache-tomcat-$old_ver/$file", + "/home/tomcat/apache-tomcat-$new_ver/$file"); + print "Copying $file to /home/tomcat/apache-tomcat-$new_ver/$file
"; + } + } + + #make a list of installed apps + my @exclude_apps = ('docs', 'examples', 'host-manager', 'manager', 'ROOT'); + + #move apps + print "Copying apps ...
"; + foreach my $app (@$apps_ref){ + + next if grep( /^$app$/, @exclude_apps); + + if(!copy_source_dest( "/home/tomcat/apache-tomcat-$old_ver/webapps/$app", + "/home/tomcat/apache-tomcat-$new_ver/webapps/$app")){ + &error("Error: Can't copy $app: $!"); + }else{ + print "$app
"; + } + + if(-f "/home/tomcat/apache-tomcat-$old_ver/webapps/$app.war"){ + if(!copy_source_dest( "/home/tomcat/apache-tomcat-$old_ver/webapps/$app.war", + "/home/tomcat/apache-tomcat-$new_ver/webapps/$app.war")){ + &error("Error: Can't copy $app.war: $!"); + }else{ + print "$app.war
"; + } + } + } +} + +sub upgrade_tomcat_from_archive{ + + my $install_ver = installed_tomcat_version(); + my $latest_ver = latest_tomcat_version($install_ver); + + my @installed_apps = get_all_war_infos(); + + #add_tomcat_user(); + download_and_install($latest_ver); + + tomcat_service_ctl('stop'); + + setup_catalina_env($latest_ver); + #setup_tomcat_users($latest_ver); + setup_tomcat_service($latest_ver); + + migrate_settings_and_apps($install_ver, $latest_ver, \@installed_apps); + + print("Update done, starting new Tomcat ".$latest_ver); + tomcat_service_ctl('start'); +} + + +&ui_print_header(undef, $text{'index_title'}, "", "intro", 1, 1); +&ReadParse(); +&error_setup($text{'start_err'}); +$err = upgrade_tomcat_from_archive(); + +&ui_print_footer("", $text{'index_return'}); diff --git a/uninstall_java.cgi b/uninstall_java.cgi new file mode 100644 index 0000000..4bbc2fb --- /dev/null +++ b/uninstall_java.cgi @@ -0,0 +1,45 @@ +#!/usr/bin/perl + +use File::Path 'rmtree'; + +require './tomcat-lib.pl'; +require './java-lib.pl'; +require '../webmin/webmin-lib.pl'; #For OS Fetection +&ReadParse(); + +&error_setup($text{'delete_err'}); + +my $jdk_name = $in{'inst_jdk'}; +$jdk_name || &error($text{'delete_enone'}); + +my $jdk_dir = get_jdk_dir_by_name($jdk_name); +my $def_jdk = is_default_jdk($jdk_dir); + +if(($def_jdk == 1) and ($in{'rm_def_jdk'} == 0)){ + + &ui_print_header(undef, $text{'java_tabuninstall'}, ""); + print "Uninstall stopped, since $jdk_dir is default JDK.
"; + +}else{ + + if($jdk_name =~ /.*openjdk.*/){ + &redirect("/software/search.cgi?search=$jdk_name"); + return; + } + + &ui_print_header(undef, $text{'delete_title'}, ""); + + print "Removing $jdk_dir...
"; + + if($def_jdk == 1){ + unset_default_java($jdk_dir); + } + + if( -d $jdk_dir){ + rmtree($jdk_dir); + } + + print "
Uninstall of $jdk_name is successful
"; +} + +&ui_print_footer("", $text{'index_return'}); diff --git a/uninstall_libs.cgi b/uninstall_libs.cgi new file mode 100644 index 0000000..111d081 --- /dev/null +++ b/uninstall_libs.cgi @@ -0,0 +1,48 @@ +#!/usr/bin/perl + +use File::Path 'rmtree'; + +require './tomcat-lib.pl'; +&ReadParse(); + +sub uninstall_lib{ + my $lib_name = $_[0]; + + #get extension files + my $lib_list = "$module_config_directory/lib_$lib_name.list"; + my %lib_files; + &read_file($lib_list, \%lib_files); + + foreach $j (keys %lib_files){ + if( -e $lib_files{$j} or -l $lib_files{$j}){ + &unlink_file($lib_files{$j}); + print "$lib_files{$j}
"; + }elsif( -d $lib_files{$j}){ + rmtree($lib_files{$j}); + }else{ + print "Listed jar $j doesn't exist!
"; + } + } + &unlink_file($lib_list); + + print "
Uninstall of $lib_name is successful
"; +} + +&error_setup($text{'delete_err'}); +&ui_print_header(undef, $text{'libs_uninstall_title'}, ""); + +@libs = split(/\0/, $in{'inst_lib'}); +@libs || &error($text{'delete_enone'}); + +tomcat_service_ctl('stop'); + +#delete each of the specified directories +my $catalina_home = get_catalina_home(); +foreach $lib (@libs) { + print "Removing $lib
"; + uninstall_lib($lib); +} + +tomcat_service_ctl('start'); + +&ui_print_footer("", $text{'index_return'});