Compare commits

...

60 Commits

Author SHA1 Message Date
8db1279a3e * Tue Dec 17 2024 Brian Read <brianr@koozali.org> 11.0.0-31.sme
- Edit html to avoid w3c html validation warnings [SME: 6278]
2024-12-17 06:35:33 +00:00
1d3d59b5c1 Fix up action commands for user panel 2024-12-16 19:55:15 +00:00
ff9a84dd29 Fix up action commands for pseudonyms and quota 2024-12-16 16:15:03 +00:00
34e7331845 Fix up action commands for port forwarding and printers 2024-12-16 13:55:52 +00:00
dfda47882d Fix up action commands for Ibays and correct groups link 2024-12-16 13:26:19 +00:00
55269fd685 Fix up action commands for Groups and Host panels 2024-12-15 17:17:32 +00:00
1b1b99955b Fix yp html warnings from w3c - mainly empty paragraphs, but also domain lists recast buttons 2024-12-15 10:15:38 +00:00
c6eb08a727 More Fix up html to conform to W3c standards - avoid duplicate id in nav menu 2024-12-14 14:06:56 +00:00
8e70adc797 A bit more header html fixing 2024-12-13 17:52:32 +00:00
2424684d35 Fix up html warned from w3c validator in header and footed 2024-12-13 16:42:42 +00:00
78bb7743c1 Add in letsencrypt and add requires for certificates and lib 2024-12-13 11:52:45 +00:00
87f6a46502 Add in letsencrypt action routines for SM2 panel 2024-12-01 15:36:46 +00:00
a08767919c Add in getmyip script 2024-11-27 16:01:56 +00:00
2b83be6d70 Fix 1267 in remoteaccess panel 2024-11-26 16:38:31 +00:00
6c1b6ed1f4 Add *.bak to .gitignore 2024-11-12 19:20:21 +00:00
3fa8ab5eda Update README with specific Bugzilla links 2024-10-27 14:23:06 +00:00
55465e3081 Update readme bugzilla link to show all outstanding bugs 2024-10-27 12:12:21 +00:00
e5b9a012d9 * Fri Oct 18 2024 Brian Read <brianr@koozali.org> 11.0.0-28.sme
- Add in emailsettings for port 25,465 and 587  [SME: 12750]
- Comment out change to localhost for roundcube in _user_list email icon setting [SME: 12751]
2024-10-18 11:46:27 +01:00
fbdf3170ec Add in _user_list.html.ep change 2024-10-06 09:48:42 +01:00
87d1d072c0 * Fri Oct 04 2024 Brian Read <brianr@koozali.org> 11.0.0-26.sme
- Add in email link to roundcube from user accounts [SME: 12751]
2024-10-04 12:34:34 +01:00
d49db26f26 Add in email link to roundcube from user accounts 2024-10-04 12:14:56 +01:00
c4f9d67abc First shot at Email icon in action col for user accounts 2024-10-02 16:42:58 +01:00
fe62bd3e39 Add curosr change when save or submit pressed 2024-10-02 14:13:47 +01:00
df6d21dbc9 Up release to accomodate messed up build 2024-10-02 09:56:24 +01:00
9c9592f861 Add release number to footer for SM2 2024-10-02 09:12:38 +01:00
4d2097d2da * Tue Sep 24 2024 Jean-Philippe Pialasse <jpp@koozali.org> 11.0.0-22.sme
- fix typos, and tidy tabs [SME: 12744]
2024-09-24 22:06:09 -04:00
44a9ecc0e1 Remove both option for webmail, add in DB re-open in Emailsetting and Portforwarding panels 2024-09-24 17:37:52 +01:00
785ebcfaaf * Mon Sep 23 2024 Jean-Philippe Pialasse <jpp@koozali.org> 11.0.0-20.sme
- webmail switch panel to use roundcube [SME: 12742]
- prevent browser from caching [SME: 12695]
2024-09-23 10:07:08 -04:00
127ea74a8b Add in WithoutCache plugin 2024-09-05 11:57:23 +01:00
b9f6392c1d Update flag to use emojii and fix singleton locale 2024-08-25 11:34:57 +01:00
659f060eb6 Left align submit in Software Install subservient panels 2024-08-22 15:41:04 +01:00
1087a8a5a2 Software Installer panel - move dnf monitoring to /var/cache/dnf.status 2024-08-22 12:17:32 +01:00
6a5a756438 uc DNF to lc dnf in Yum.pm 2024-08-21 16:06:16 +01:00
91ca26de27 Migrate panel for software installer from yum to dnf 2024-08-21 12:39:46 +01:00
8b93232bbe make small changes to the readme 2024-08-16 15:42:40 +02:00
ed1c3e13b1 * Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-14.sme
- fix [SME: ]
2024-07-28 17:15:10 +01:00
095a0a1499 * Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-13.sme
- Fix sysles.css template - overwrote it by mistake [SME: 12706]
- Also re-organised login and Legacy SM menus and help on top
2024-07-28 17:14:14 +01:00
d16ea6a847 Typo in styles.css template 2024-07-28 16:28:45 +01:00
e70cc67430 * Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-12.sme
- correct positio of flag-icon [SME: 12706]
2024-07-28 15:50:26 +01:00
b097acafab yet more adjustment to header button spacing 2024-07-28 15:46:08 +01:00
5d7655a709 and more adjustment to header 2024-07-28 14:19:54 +01:00
a58df95aa9 More position and format for flag-icon 2024-07-28 14:04:49 +01:00
251b454470 Get Flag icon in correct place 2024-07-28 12:13:03 +01:00
174d511899 * Sat Jul 27 2024 Brian Read <brianr@koozali.org> 11.0.0-11.sme
- Add in flag icon indication of locale [SME: 12706]
2024-07-27 22:33:07 +01:00
4be8a1411f Update js code for flag icon 2024-07-27 22:28:01 +01:00
ba431a8a7d Add in js code for flag icon 2024-07-27 22:07:10 +01:00
77a7849898 Add in locale icon in header 2024-07-27 20:03:14 +01:00
fb5b0942d6 * Fri Jul 26 2024 Brian Read <brianr@koozali.org> 11.0.0-10.sme
- fix navigation2.conf to more correctly translate menus [SME: 12714]
2024-07-27 11:22:39 +01:00
5edc830f9b Few more fixes to navigation2.conf 2024-07-27 10:48:00 +01:00
473cb57a47 More fix up for navigation2.conf 2024-07-26 16:31:20 +01:00
55b85496d4 Fix navigation2.conf to correctly re-create translated menus 2024-07-26 15:45:32 +01:00
2fd6f8b630 Update Readme.md 2024-05-26 17:33:03 +02:00
a428e91c92 * Thu May 09 2024 Brian Read <brianr@koozali.org> 11.0.0-9.sme
- Add mojo logo to footer [SME: 12679]
- Fix default for HeaderWeight to avoid noise in logs if no Nav header in file
- Align buttons consistently [SME: 12680]
2024-05-09 17:02:39 +01:00
03955eecea * Tue Apr 30 2024 Jean-Philippe Pialasse <jpp@koozali.org> 11.0.0-8.sme
- create dedicated log files and logrotate [SME: 12664]
2024-04-30 16:28:32 -04:00
891fc73ce3 * Tue Apr 30 2024 Brian Read <brianr@koozali.org> 11.0.0-7.sme
- Remove use of hel command and replace by call to BlockDevices lib [SME: 12644]
2024-04-30 18:23:52 +01:00
e7d7b6afb8 * Mon Apr 29 2024 Brian Read <brianr@koozali.org> 11.0.0-6.sme
- Update layout for table extras [SME: 12656]
2024-04-29 11:08:21 +01:00
1837bc9a18 * Sun Apr 28 2024 Brian Read <brianr@koozali.org> 11.0.0-5.sme
- Ibay create not getting into panel [SME: 12652]
2024-04-28 11:22:17 +01:00
a580a79ab5 * Tue Apr 23 2024 Brian Read <brianr@koozali.org> 11.0.0-4.sme
- add in Nav numbers for Legacypanels.pm and ignore it when generating nav menu [SME:12643]
2024-04-23 09:28:31 +01:00
c38c471bc0 Set license file to GPL2.0 2024-04-04 11:22:40 +01:00
fbdba9d282 change Requires to reference smeserver-* not e-smith-* in spec 2024-03-23 15:56:49 +00:00
74 changed files with 3827 additions and 911 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@
*.log
*spec-20*
*.tar.xz
*.bak

126
LICENSE
View File

@@ -1,73 +1,119 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
1. Definitions.
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
Preamble
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
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 this service 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.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. 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.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
The precise terms and conditions for copying, distribution and modification follow.
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the 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 a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE 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.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
How to Apply These Terms to Your New Programs
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
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.
Copyright [yyyy] [name of copyright owner]
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 convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker.
signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -13,10 +13,70 @@ SMEServer Koozali developed git repo for smeserver-manager smeserver
<br />https://wiki.koozali.org/Server_Manager_2_Howto_incorporate_a_legacy_contrib
## Bugzilla
Show list of outstanding bugs: [here](https://bugs.koozali.org/buglist.cgi?component=smeserver-manager&product=SME%20Server%2010.X&query_format=advanced&limit=0&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=CONFIRMED)
Show list of outstanding bugs:
[All](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=NEEDINFO&bug_status=IN_PROGRESS&bug_status=RESOLVED&bug_status=VERIFIED&cf_package=smeserver-manager&classification=SME+Server&list_id=105756&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)
[Confirmed](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=CONFIRMED&cf_package=smeserver-manager&classification=SME+Server&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)
[Unconfirmed](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=UNCONFIRMED&cf_package=smeserver-manager&classification=SME+Server&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)
[Need info](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=NEEDINFO&cf_package=smeserver-manager&classification=SME+Server&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)
[In progress](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=IN_PROGRESS&cf_package=smeserver-manager&classification=SME+Server&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)
[Resolved](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=RESOLVED&cf_package=smeserver-manager&classification=SME+Server&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)
[Verified](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=VERIFIED&cf_package=smeserver-manager&classification=SME+Server&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)
## Description
<br />*This description has been generated by an LLM AI system and cannot be relied on to be fully correct.*
*Once it has been checked, then this comment will be deleted*
<br />
The *smeserver-manager* is a web-based management interface for the SME Server (formerly known as e-smith server and gateway). SME Server is a Linux-based distribution designed for small to medium-sized enterprises, providing a wide range of network services and simplified server management.
It is based on the perl Mojolicious package. Mojolicious is a real-time web framework for Perl, which provides a range of functionalities that make it a powerful and flexible tool for web development.
### Features
#### Web-Based Management Interface:
smeserver-manager provides an intuitive and user-friendly web interface that allows administrators to manage various aspects of the server without needing deep technical knowledge or command-line skills.
#### User and Group Management:
It allows you to easily add, remove, and manage user accounts and groups. The interface simplifies creating email accounts, setting passwords, and configuring user permissions.
#### Network Configuration:
You can configures network settings such as IP addresses, DNS, DHCP, and gateway settings. The interface also provides options for setting up VPNs, remote access, and firewall rules.
#### File Sharing and Storage:
Enables and manages file sharing services like Samba (for Windows file sharing) and NFS (for Unix/Linux file sharing). Administrators can easily create shared folders and manage permissions.
#### Email Services:
Configure and manage email services, including setting up mail domains, user mailboxes, and SMTP/IMAP/POP3 settings. It also provides options for spam and virus filtering.
#### Web Services:
Host and manage websites using the integrated web server (usually Apache). It supports virtual hosting, where multiple websites can be hosted on the same server.
#### Backup and Restore:
Perform backups of essential data and server configurations. The interface provides options for scheduled backups and restoring from backup files.
#### Software Updates and Installation:
Keep the server up-to-date with the latest security patches and software updates. The interface helps in installing and updating software packages and extensions.
#### Monitoring and Reporting:
Monitor server performance and health. The interface provides logs, status reports, and alerts for various server components, including disk usage, network traffic, and system load.
### Installation and Access
Typically, smeserver-manager is installed by default on SME Server. To access the interface:
Open a web browser on a device connected to the same network as the SME Server. Enter the server's IP address or hostname followed by /server-manager in the address bar (e.g., https://192.168.1.1/server-manager).
You will be prompted to log in. Use the administrator credentials set during the SME Server installation.
### Benefits
Simplicity: Makes it easy for non-technical users to manage a server.
Centralized Management: Provides a single point of control for various server functionalities.
Efficiency: Saves time and reduces complexity in server management tasks.
Security: Regular updates and built-in security features ensure the server remains secure.
### Considerations
Learning Curve: While designed to be user-friendly, some features may still require a basic understanding of server and network management concepts.
Dependencies: Relies on specific packages and configurations of SME Server, and may not be directly applicable to other Linux distributions.
### Summary
SMEserver-manager is a powerful tool that brings simplicity and efficiency to server management for small to medium-sized enterprises. By providing a centralized, web-based interface, it allows administrators to manage users, network settings, file sharing, email services, web hosting, and more, all from a single location.

View File

@@ -47,6 +47,9 @@ for my $event ( qw( smeserver-manager-update smanager-refresh bootstrap-console-
event_link('systemd-default', "smeserver-manager-update", '88');
event_link('systemd-reload', "smeserver-manager-update", '89');
templates2events("/etc/rsyslog.conf", "smeserver-manager-update");
safe_symlink("restart",
"root/etc/e-smith/events/smeserver-manager-update/services2adjust/rsyslog");
use esmith::Build::Backup qw(:all);
backup_includes("smeserver-manager", qw(

View File

@@ -33,6 +33,8 @@ use esmith::I18N;
use Data::Dumper; # activate if DEBUG
binmode(STDOUT, ":encoding(UTF-8)");
my $navigation_ignore =
"(\.\.?|Swttheme\.pm|Login\.pm|Request\.pm|Modules\.pm(-.*)?)";
@@ -46,131 +48,193 @@ my @files = grep (!/^${navigation_ignore}$/, readdir (FUNCTIONS));
closedir FUNCTIONS;
my @langs = $i18n->availableLanguages();
#my @langs = ('en', 'fr');
#print Dumper(\@langs);
#my @langs = ('tr'); #Temp override
foreach my $lang (@langs)
{
my $long_lex = SMNGR_LIB.'/'.I18NMODULES."/General/general_$lang.lex";
next unless ( -e $long_lex );
my $long_lex = SMNGR_LIB.'/'.I18NMODULES."/General/general_$lang.lex";
next unless ( -e $long_lex );
open(LEX, '<:encoding(UTF-8)', $long_lex)
or die "Couldn't open ", $long_lex, " for reading.\n";
my @gen_lex = <LEX>;
close LEX;
open(LEX, '<:encoding(UTF-8)', $long_lex)
or die "Couldn't open ", $long_lex, " for reading.\n";
my @gen_lex = <LEX>;
close LEX;
foreach my $file (@files)
{
next if (-d SMNGR_LIB.'/'.WEBFUNCTIONS . "/$file");
# next unless ( $file =~ m/D.*\.pm$/ );
next unless ( $file =~ m/[A-Z].*\.pm$/ );
my $file2 = lc($file);
$file2 =~ s/\.pm$//;
#--------------------------------------------------
# extract heading, description and weight information
# from Mojo controller
#--------------------------------------------------
open(SCRIPT, SMNGR_LIB.'/'.WEBFUNCTIONS . "/$file");
my $heading = undef;
my $description = undef;
my $heading_weight = undef;
my $description_weight = undef;
my $menucat = undef;
my $routes = undef;
while ( <SCRIPT> )
#my @files = ('Portforwarding.pm'); #Temp override
foreach my $file (@files)
{
$heading = $1 if (/^\s*#\s*heading\s*:\s*(.+?)\s*$/);
$description = $1
if (/^\s*#\s*description\s*:\s*(.+?)\s*$/);
($heading_weight, $description_weight) = ($1, $2)
if (/^\s*#\s*navigation\s*:\s*(\d+?)\s+(\d+?)\s*$/);
$menucat = $1
if (/^\s*#\s*menu\s*:\s*(.+?)\s*$/);
next if (-d SMNGR_LIB.'/'.WEBFUNCTIONS . "/$file");
# next unless ( $file =~ m/D.*\.pm$/ );
next unless ( $file =~ m/[A-Z].*\.pm$/ );
last if (defined $heading and
defined $description and
defined $heading_weight and
defined $description_weight and
defined $menucat);
my $file2 = lc($file);
$file2 =~ s/\.pm$//;
#--------------------------------------------------
# extract heading, description and weight information
# from Mojo controller
#--------------------------------------------------
open(SCRIPT, SMNGR_LIB.'/'.WEBFUNCTIONS . "/$file");
my $heading = undef;
my $description = undef;
my $heading_weight = undef;
my $description_weight = undef;
my $menucat = undef;
my $routes = undef;
# routes : end (stop before eof if 'menu' is not here before 'routes'!!!
$routes = $1 if (/^\s*#\s*routes\s*:\s*(.+?)\s*$/);
last if (defined $routes and $routes eq 'end');
while ( <SCRIPT> )
{
$heading = $1 if (/^\s*#\s*heading\s*:\s*(.+?)\s*$/);
$description = $1
if (/^\s*#\s*description\s*:\s*(.+?)\s*$/);
($heading_weight, $description_weight) = ($1, $2)
if (/^\s*#\s*navigation\s*:\s*(\d+?)\s+(\d+?)\s*$/);
$menucat = $1
if (/^\s*#\s*menu\s*:\s*(.+?)\s*$/);
last if (defined $heading and
defined $description and
defined $heading_weight and
defined $description_weight and
defined $menucat);
# routes : end (stop before eof if 'menu' is not here before 'routes'!!!
$routes = $1 if (/^\s*#\s*routes\s*:\s*(.+?)\s*$/);
last if (defined $routes and $routes eq 'end');
}
close SCRIPT;
print "updating script $file for lang $lang\n"if DEBUG;
my $navdb = $navdbs{$lang};
my $navinfo = NAVDIR.'/'.NAVIGATIONDIR . "/navigation.$lang";
$navdb ||= esmith::NavigationDB->open($navinfo);
$navdb ||= esmith::NavigationDB->create($navinfo) or
die "Couldn't create $navinfo\n";
$navdbs{$lang} ||= $navdb;
my $rec = $navdb->get($file2) ||
$navdb->new_record($file2, { type => 'panel' } );
my @panel_lex = ();
$long_lex = SMNGR_LIB.'/'.I18NMODULES.'/'.ucfirst($file2)."/${file2}_$lang.lex";
if ( -e $long_lex ) {
open(LEX, '<:encoding(UTF-8)', $long_lex)
or die "Couldn't open ", $long_lex, " for reading.\n";
@panel_lex = <LEX>;
close LEX;
}
#Extract the prefix for this module
my @keys = values @panel_lex; # Get all values from the array
my $i = 0; # Initialize the index
my $found = 0; # Flag to check if the prefix was found
my $prefix = "xx_"; # Probably never match!!
while ($i < @keys) { # Loop until we run out of entries
my $extracted_value = $keys[$i] || ""; # The current entry
#print("Extracted val: ".$extracted_value."\n");
# Extract prefix from the second value (up to and including the first underscore)
#my ($prefix) = $second_value =~ /^'(.*?_)/; # Match everything up to and including the first underscore
($prefix) = $extracted_value =~ /^'(.*?_)/; # Match everything up to and including the first underscore
if (defined $prefix) {
$found = 1; # Set found flag to true
last; # Exit the loop if prefix is found
} else {
#print("Extracted Val: " . $extracted_value . "\n");
}
$i++; # Increment the index to check the next entry
}
if (!$found) {
print(STDERR "No valid prefix found in any entries: ".$file2." (".$lang.")\n"); # if DEBUG;
$prefix = "xx_"; # Probably never match!!
}
#print("Prefix: ".$prefix." ".$file2." (".$lang.")\n");
my %Lexicon = ();
push(@panel_lex, @gen_lex);
my $top_error = 0;
chomp @panel_lex;
for (@panel_lex) {
next unless $_; # first one empty
my ($k, $v) = split / => /, $_;
# errors on split to $v (use DEBUG to see)
if ( $k and $v ) {
$k =~ s/\'//g;
$v =~ s/\'//g;
$v =~ s/,$//g;
$Lexicon{ lc($k) } = $v;
} else {
$k = "?" unless ($k);
print STDERR "Error for $lang $file2 on $k \n" if DEBUG;
$top_error++;
}
}
if ( $top_error > 0) {
if ( DEBUG ) {
print STDERR "$top_error errors for $lang $file2\n";
# print Dumper(\@panel_lex);
# print Dumper(\%Lexicon);
# exit 1;
}
}
$heading = "" unless defined $heading;
$description = "" unless defined $description;
# Get the base language code from $lang
my $base_lang = (split('-', $lang))[0];
my $loc_heading = process_localization( \%Lexicon, $heading, $lang, $prefix );
my $loc_description = process_localization( \%Lexicon, $description, $lang, $prefix );
$loc_heading =~ s/^\s*(\w.*?)\s*$/$1/;
$loc_description =~ s/^\s*(\w.*?)\s*$/$1/;
$rec->merge_props(
Heading => $loc_heading,
Description => $loc_description,
HeadingWeight => localise( \%Lexicon, $heading_weight ),
DescriptionWeight => localise( \%Lexicon, $description_weight ),
MenuCat => (defined $menucat ? $menucat : 'A'));
}
close SCRIPT;
print "updating script $file for lang $lang\n" if DEBUG;
#warn "trying to close for lang $lang\n";
my $navdb = $navdbs{$lang};
my $navinfo = NAVDIR.'/'.NAVIGATIONDIR . "/navigation.$lang";
$navdb ||= esmith::NavigationDB->open($navinfo);
$navdb ||= esmith::NavigationDB->create($navinfo) or
die "Couldn't create $navinfo\n";
$navdbs{$lang} ||= $navdb;
my $rec = $navdb->get($file2) ||
$navdb->new_record($file2, { type => 'panel' } );
my @panel_lex = ();
$long_lex = SMNGR_LIB.'/'.I18NMODULES.'/'.ucfirst($file2)."/${file2}_$lang.lex";
if ( -e $long_lex ) {
open(LEX, '<:encoding(UTF-8)', $long_lex)
or die "Couldn't open ", $long_lex, " for reading.\n";
@panel_lex = <LEX>;
close LEX;
}
my %Lexicon = ();
push(@panel_lex, @gen_lex);
my $top_error = 0;
chomp @panel_lex;
for (@panel_lex) {
next unless $_; # first one empty
my ($k, $v) = split / => /, $_;
# errors on split to $v (use DEBUG to see)
if ( $k and $v ) {
$k =~ s/\'//g;
$v =~ s/\'//g;
$v =~ s/,$//g;
$Lexicon{ $k } = $v;
} else {
$k = "?" unless ($k);
print STDERR "Error for $lang $file2 on $k \n" if DEBUG;
$top_error++;
}
}
if ( $top_error > 0) {
if ( DEBUG ) {
print STDERR "$top_error errors for $lang $file2\n";
# print Dumper(\@panel_lex);
# print Dumper(\%Lexicon);
# exit 1;
}
}
my $loc_heading = localise( \%Lexicon, $heading );
my $loc_description = localise( \%Lexicon, $description );
$loc_heading =~ s/^\s*(\w.*?)\s*$/$1/;
$loc_description =~ s/^\s*(\w.*?)\s*$/$1/;
$rec->merge_props(
Heading => $loc_heading,
Description => $loc_description,
HeadingWeight => localise( \%Lexicon, $heading_weight ),
DescriptionWeight => localise( \%Lexicon, $description_weight ),
MenuCat => (defined $menucat ? $menucat : 'A'));
}
#warn "trying to close for lang $lang\n";
my $navdb = $navdbs{$lang};
$navdb->close();
$navdb->close();
}
sub localise {
my ($lexicon, $string) = @_;
#print("Looking up:".$string."\n");
$string = "" unless defined $string;
return $lexicon->{$string} || $string;
my $lc_string = lc($string);
my $res = $lexicon->{$lc_string} || $string;
#print("Returning:".$res."\n");
return $res;
}
# Subroutine to process localization
sub process_localization {
my ($lexicon_ref, $heading, $lang, $prefix) = @_;
# Localized heading based on original heading
my $loc_heading = localise($lexicon_ref, $heading);
# Get the base language code from $lang
my $base_lang = (split('-', $lang))[0];
# Check the condition
if ($loc_heading eq $heading && $base_lang ne 'en') {
# Construct the new key by combining the prefix and the original heading
my $key = $prefix . $heading;
# Localize using the constructed key
$loc_heading = localise($lexicon_ref, $key);
# See if it got a hit
if ($loc_heading eq $key){
$loc_heading = $heading;
}
}
return $loc_heading; # Optionally return the localized heading
}

View File

@@ -40,5 +40,10 @@
$OUT .= " Require ip $localAccess $externalSSLAccess\n";
}
$OUT .= " </Location>\n";
# prevent caching of manager files in browser
$OUT .= " <LocationMatch \"/$place/.+\.(html|cgi)\$\">\n";
$OUT .= " Header set Cache-Control no-store\n";
$OUT .= " </LocationMatch>\n";
}
}

View File

@@ -0,0 +1,4 @@
#smanager
:programname, isequal, "smanager" /var/log/smanager/smanager.log
& stop

View File

@@ -67,5 +67,21 @@ hr.sme-copyrightbar {
color: #8ebe43;
background-color: #8ebe43;
}
/* flag container no flag */
#flag-container span {
font-size: 24px;
}
.fallback-box {
display: inline-block; /* Make it inline-block to fit around the content */
border: 2px solid gray; /* Change the border color as desired */
padding: 10px; /* Add some padding */
border-radius: 10px; /* Round the corners of the box */
font-size: 60px; /* Adjust size if needed */
margin-top: 10px; /* Add some margin */
text-align: center; /* Center text inside the box */
}
HERE
}

View File

@@ -234,7 +234,7 @@ a.menu-title {
width: 100%;
}
#h2e11 {
width: 70%;
width: 50%;
float: left;
}
#h2e12 {
@@ -257,9 +257,9 @@ a.menu-title {
width: 70%;
}
#h2e22,#h2e23 {
#h2e22,#h2e23,#h2e12 {
float: left;
width: 10%;
width: 14em;
text-align: center;
}
@@ -273,6 +273,7 @@ a.menu-title {
left: 2px;
}
/*end*/
EOF
}

View File

@@ -0,0 +1,27 @@
document.addEventListener('DOMContentLoaded', () => {
const flagContainer = document.getElementById('flag-container');
// Function to get the browser's locale
function getBrowserLocale() {
return navigator.language || navigator.userLanguage;
}
// Function to map locale to country code
function getCountryCodeFromLocale(locale) {
const localeParts = locale.split('-');
return localeParts.length > 1 ? localeParts[1] : localeParts[0];
}
// Function to create and display the flag icon
function displayFlagIcon(countryCode) {
const flagIcon = document.createElement('span');
flagIcon.className = `flag-icon flag-icon-${countryCode.toLowerCase()}`;
flagIcon.id = 'flag-icon';
flagContainer.appendChild(flagIcon);
}
// Main logic
const locale = getBrowserLocale();
const countryCode = getCountryCodeFromLocale(locale);
displayFlagIcon(countryCode);
});

View File

@@ -1,4 +1,6 @@
/usr/share/smanager/log/production.log {
/var/log/smanager/smanager.log {
su root root
create 600 root root
weekly
copytruncate
rotate 12

View File

@@ -7,7 +7,7 @@ After=network.target
Type=simple
SyslogIdentifier=smanager
WorkingDirectory=/usr/share/smanager/script
PIDFile=/var/run/smanager.pid
PIDFile=/run/smanager.pid
ExecStartPre=/sbin/e-smith/service-status smanager
ExecStart=/usr/bin/hypnotoad srvmngr -f
ExecStop=/usr/bin/hypnotoad -s srvmngr

View File

@@ -25,8 +25,16 @@ use SrvMngr::Plugin::I18N;
use SrvMngr::I18N;
use SrvMngr::Model::Main;
use SrvMngr::Plugin::WithoutCache;
our $VERSION = '1.420';
#this is overwrittrn with the "release" by the spec file - release can be "99.el8.sme"
our $VERSION = '';
#Extract the release value
if ($VERSION =~ /^(\d+)/) {
$VERSION = $1; # $1 contains the matched numeric digits
} else {
$VERSION = '999' #No leading numeric digits found
}
$VERSION = eval $VERSION;
use Exporter 'import';
@@ -210,6 +218,8 @@ sub setup_plugins {
$self->plugin('TagHelpers');
$self->plugin('RenderFile');
$self->plugin('SrvMngr::Plugin::WithoutCache');
# CSRF protection if production mode
# $self->plugin('Mojolicious::Plugin::CSRFDefender' => {
@@ -535,7 +545,7 @@ sub getNavigation {
# Determine the directory where the functions are kept
#-----------------------------------------------------
my $navigation_ctlr_ignore =
"(\.\.?|Swttheme\.pm|Login\.pm|Request\.pm|Modules\.pm(-.*)?)";
"(\.\.?|Swttheme\.pm|Login\.pm|Request\.pm|Modules\.pm|Legacypanel\.pm(-.*)?)";
# "(\.\.?|Initial\.pm|Manual\.pm|Swttheme\.pm|Request\.pm|Modules\.pm(-.*)?)";
my $navigation_cgi_ignore =
"(\.\.?|navigation|noframes|online-manual|(internal|pleasewait)(-.*)?)";
@@ -624,7 +634,7 @@ sub getNavigation {
{
$heading = $rec->prop('Heading');
$description = $rec->prop('Description');
$headingWeight = $rec->prop('HeadingWeight');
$headingWeight = $rec->prop('HeadingWeight') || 99999; #Stop noise in logs if file in dir does not have nav header.
$descriptionWeight = $rec->prop('DescriptionWeight');
$urlpath = $rec->prop('UrlPath') || '';
$menucat = $rec->prop('MenuCat') || 'A'; # admin menu (default)

View File

@@ -37,6 +37,8 @@ use esmith::BackupHistoryDB;
use esmith::util;
use esmith::lockfile;
use esmith::BlockDevices;
use constant DEBUG => $ENV{MOJO_SMANAGER_DEBUG} || 0;
our $cdb = esmith::ConfigDB->open || die "Couldn't open config db";
@@ -1576,19 +1578,33 @@ sub get_BackupwkDest_options {
my @usbdisks = ();
if ( $VFSType eq 'usb' ) {
foreach my $udi (qx(hal-find-by-property --key volume.fsusage --string filesystem)) {
$udi =~ m/^(\S+)/;
my $devices = esmith::BlockDevices->new ('allowmount' => 'disabled');
my ($valid, $invalid) = $devices->checkBackupDrives(0);
my $is_mounted = qx(hal-get-property --udi $1 --key volume.is_mounted);
if ($is_mounted eq "false\n") {
my $vollbl = qx(hal-get-property --udi $1 --key volume.label);
$vollbl =~ m/^(\S+)/;
if ($vollbl =~ /^\s/) {$vollbl = 'nolabel';}
chomp $vollbl;
push @usbdisks, $vollbl;
if ( ${$valid}[0] ) {
foreach ( @{$valid} ) {
push @usbdisks, $devices->label($_);
}
}
if (!$usbdisks[0]){
push (@usbdisks,$c->l('bac_No suitable local devices found'));
}
$devices->destroy;
#foreach my $udi (qx(hal-find-by-property --key volume.fsusage --string filesystem)) {
#$udi =~ m/^(\S+)/;
#my $is_mounted = qx(hal-get-property --udi $1 --key volume.is_mounted);
#if ($is_mounted eq "false\n") {
#my $vollbl = qx(hal-get-property --udi $1 --key volume.label);
#$vollbl =~ m/^(\S+)/;
#if ($vollbl =~ /^\s/) {$vollbl = 'nolabel';}
#chomp $vollbl;
#push @usbdisks, $vollbl;
#}
#}
# return undef unless ($usbdisks[0]);
}
@@ -1985,31 +2001,50 @@ sub dmount {
return ( qx(/bin/mount -t nfs -o nolock "$host:/$share" $mountdir 2>&1) );
}
elsif ($VFSType eq 'usb') {
my $device = "";
my $blkdev = "";
my $device = "";
my $vollbl = "";
foreach my $udi (qx(hal-find-by-property --key volume.fsusage --string filesystem)) {
$udi =~ m/^(\S+)/;
my $is_mounted = qx(hal-get-property --udi $1 --key volume.is_mounted);
if ($is_mounted eq "false\n") {
$blkdev = qx(hal-get-property --udi $1 --key block.device);
if ($blkdev =~ m/^(\S+)/) {$blkdev = $1;}
}
if ($is_mounted eq "false\n") {
$vollbl = qx(hal-get-property --udi $1 --key volume.label);
$vollbl =~ m/^(\S+)/;
if ($vollbl =~ /^\s/) {$vollbl = 'nolabel';}
}
my $devices = esmith::BlockDevices->new ('allowmount' => 'disabled');
my ($valid, $invalid) = $devices->checkBackupDrives(0);
chomp $vollbl;
chomp $blkdev;
$vollbl = "media/$vollbl";
if ($vollbl eq $share) {
$device = $blkdev;
}
if ( ${$valid}[0] ) {
foreach ( @{$valid} ) {
$vollbl = $devices->label($_);
if ( $share eq "media/$vollbl" ) {
$device = "/dev/$_";
}
}
}
return ( qx(/bin/mount $device "/$share" 2>&1) );
$devices->destroy;
return ( qx (mount $device /$share 2>&1) );
#-------------------------------------------------------------------------------------------------------
#my $device = "";
#my $blkdev = "";
#my $vollbl = "";
#foreach my $udi (qx(hal-find-by-property --key volume.fsusage --string filesystem)) {
#$udi =~ m/^(\S+)/;
#my $is_mounted = qx(hal-get-property --udi $1 --key volume.is_mounted);
#if ($is_mounted eq "false\n") {
#$blkdev = qx(hal-get-property --udi $1 --key block.device);
#if ($blkdev =~ m/^(\S+)/) {$blkdev = $1;}
#}
#if ($is_mounted eq "false\n") {
#$vollbl = qx(hal-get-property --udi $1 --key volume.label);
#$vollbl =~ m/^(\S+)/;
#if ($vollbl =~ /^\s/) {$vollbl = 'nolabel';}
#}
#chomp $vollbl;
#chomp $blkdev;
#$vollbl = "media/$vollbl";
#if ($vollbl eq $share) {
#$device = $blkdev;
#}
#}
#return ( qx(/bin/mount $device "/$share" 2>&1) );
#-------------------------------------------------------------------------------------------------------
} else {
return ("Error while mounting $host/$share : $VFSType not supported.\n");
}

View File

@@ -12,6 +12,9 @@ use strict;
use warnings;
use Mojo::Base 'Mojolicious::Controller';
use constant FALSE => 0;
use constant TRUE => 1;
use Locale::gettext;
use SrvMngr::I18N;
@@ -36,7 +39,7 @@ sub main {
my $title = $c->l('mai_FORM_TITLE');
$mai_datas{'trt'} = 'LIST';
$mai_datas{fetchmailmethod} = $cdb->get_prop('fetchmail', 'Method');
$mai_datas{fetchmailmethod} = $c->l($cdb->get_prop('fetchmail', 'Method'));
$c->stash( title => $title, notif => '', mai_datas => \%mai_datas );
$c->render(template => 'emailsettings');
@@ -56,13 +59,16 @@ sub do_display {
my ($notif, $dest) = '';
$mai_datas{'trt'} = $trt;
$cdb = esmith::ConfigDB->open || die "Couldn't open config db";
if ( $trt eq 'ACC' ) {
$dest = 'emailaccess';
$mai_datas{fetchmailmethod} = $cdb->get_prop('fetchmail', 'Method');
}
if ( $trt eq 'ACC' )
{
$dest = 'emailaccess';
$mai_datas{fetchmailmethod} = $cdb->get_prop('fetchmail', 'Method');
}
if ( $trt eq 'FIL' ) {
if ( $trt eq 'FIL' )
{
$dest = 'emailfilter';
$mai_datas{'virusstatus'} = $c->get_virus_status();
$mai_datas{'spamstatus'} = $cdb->get_prop('spamassassin', 'status');
@@ -72,9 +78,10 @@ sub do_display {
$mai_datas{spamsortspam} = $cdb->get_prop('spamassassin', 'SortSpam');
$mai_datas{spamsubjecttag} = $cdb->get_prop('spamassassin', 'SubjectTag');
$mai_datas{spamsubject} = $cdb->get_prop('spamassassin', 'Subject');
}
}
if ( $trt eq 'REC' ) {
if ( $trt eq 'REC' )
{
$dest = 'emailreceive';
$mai_datas{fetchmailmethod} = $cdb->get_prop('fetchmail', 'Method');
$mai_datas{freqoffice} = $cdb->get_prop('fetchmail', 'FreqOffice');
@@ -86,9 +93,10 @@ sub do_display {
$mai_datas{specifyheader} = get_secondary_mail_use_envelope();
$mai_datas{secondarymailenvelope} = $cdb->get_prop('fetchmail', 'SecondaryMailEnvelope');
}
}
if ( $trt eq 'DEL' ) {
if ( $trt eq 'DEL' )
{
$dest = 'emaildeliver';
$mai_datas{emailunknownuser} = $cdb->get_value('EmailUnknownUser') || '"returntosender';
$mai_datas{delegatemailserver} = $cdb->get_value('DelegateMailServer');
@@ -96,7 +104,7 @@ sub do_display {
$mai_datas{smtpauthproxystatus} = $cdb->get_prop('smtp-auth-proxy', 'status') || 'disabled';
$mai_datas{smtpauthproxyuserid} = $cdb->get_prop('smtp-auth-proxy', 'Userid') || '';
$mai_datas{smtpauthproxypassword} = $cdb->get_prop('smtp-auth-proxy', 'Passwd') || '';
}
}
$c->stash( title => $title, notif => $notif, mai_datas => \%mai_datas );
@@ -115,103 +123,113 @@ sub do_update {
my %mai_datas = ();
$mai_datas{trt} = $trt;
$cdb = esmith::ConfigDB->open || die "Couldn't open config db";
my $title = $c->l('mai_FORM_TITLE');
my ($dest, $res, $result) = '';
if ( $trt eq 'ACC' ) {
if ( $trt eq 'ACC' )
{
$dest = 'emailaccess';
# $mai_datas{xxx} = $c->param('XXX');
# controls
# $res = xxxxxxx( $c );
# $result .= $res unless $res eq 'OK';
$dest = 'emailaccess';
# $mai_datas{xxx} = $c->param('XXX');
if ( ! $result )
{
$res = $c->change_settings_access();
$result .= $res unless $res eq 'OK';
if ( ! $result )
{
$result = $c->l('mai_SUCCESS');
}
}
}
# controls
# $res = xxxxxxx( $c );
# $result .= $res unless $res eq 'OK';
if ( $trt eq 'FIL' )
{
$dest = 'emailfilter';
# $mai_datas{xxx} = $c->param('XXX');
# controls
# $res = zzzzzz( $c );
# $result .= $res unless $res eq 'OK';
if ( ! $result ) {
$res = $c->change_settings_access();
$result .= $res unless $res eq 'OK';
if ( ! $result ) {
$result = $c->l('mai_SUCCESS');
}
}
}
if ( ! $result )
{
$res = $c->change_settings_filtering();
$result .= $res unless $res eq 'OK';
if ( ! $result )
{
$result = $c->l('mai_SUCCESS');
}
}
}
if ( $trt eq 'FIL' ) {
if ( $trt eq 'REC' )
{
$dest = 'emailreceive';
# $mai_datas{xxx} = $c->param('XXX');
# controls
# $res = yyyyyyyyy( $c );
# $result .= $res unless $res eq 'OK';
$dest = 'emailfilter';
# $mai_datas{xxx} = $c->param('XXX');
if ( ! $result )
{
$res = $c->change_settings_reception();
$result .= $res unless $res eq 'OK';
if ( ! $result )
{
$result = $c->l('mai_SUCCESS');
}
}
}
# controls
# $res = zzzzzz( $c );
# $result .= $res unless $res eq 'OK';
if ( $trt eq 'DEL' )
{
$dest = 'emaildeliver';
# $mai_datas{xxx} = $c->param('XXX');
# controls
$res = $c->ip_number_or_blank( $c->param('DelegateMailServer') );
$result .= $res . ' DMS <br>' unless $res eq 'OK';
if ( ! $result ) {
$res = $c->change_settings_filtering();
$result .= $res unless $res eq 'OK';
if ( ! $result ) {
$result = $c->l('mai_SUCCESS');
}
}
}
$res = $c->validate_smarthost( $c->param('SMTPSmartHost') );
$result .= $res . ' SH <br>' unless $res eq 'OK';
if ( $trt eq 'REC' ) {
$res = $c->nonblank_if_smtpauth( $c->param('SMTPSmartHost') );
$result .= $res . ' SH <br>' unless $res eq 'OK';
$dest = 'emailreceive';
# $mai_datas{xxx} = $c->param('XXX');
$res = $c->nonblank_if_smtpauth( $c->param('SMTPAUTHPROXY_Userid') );
$result .= $res . ' USR <br>' unless $res eq 'OK';
# controls
# $res = yyyyyyyyy( $c );
# $result .= $res unless $res eq 'OK';
$res = $c->nonblank_if_smtpauth( $c->param('SMTPAUTHPROXY_Passwd') );
$result .= $res . ' PWD <br>' unless $res eq 'OK';
if ( ! $result ) {
$res = $c->change_settings_reception();
$result .= $res unless $res eq 'OK';
if ( ! $result ) {
$result = $c->l('mai_SUCCESS');
}
}
}
if ( $trt eq 'DEL' ) {
$dest = 'emaildeliver';
# $mai_datas{xxx} = $c->param('XXX');
# controls
$res = $c->ip_number_or_blank( $c->param('DelegateMailServer') );
$result .= $res . ' DMS <br>' unless $res eq 'OK';
$res = $c->validate_smarthost( $c->param('SMTPSmartHost') );
$result .= $res . ' SH <br>' unless $res eq 'OK';
$res = $c->nonblank_if_smtpauth( $c->param('SMTPSmartHost') );
$result .= $res . ' SH <br>' unless $res eq 'OK';
$res = $c->nonblank_if_smtpauth( $c->param('SMTPAUTHPROXY_Userid') );
$result .= $res . ' USR <br>' unless $res eq 'OK';
$res = $c->nonblank_if_smtpauth( $c->param('SMTPAUTHPROXY_Passwd') );
$result .= $res . ' PWD <br>' unless $res eq 'OK';
if ( ! $result ) {
$res = $c->change_settings_delivery();
$result .= $res unless $res eq 'OK';
if ( ! $result ) {
$result = $c->l('mai_SUCCESS');
}
}
}
if ( ! $result )
{
$res = $c->change_settings_delivery();
$result .= $res unless $res eq 'OK';
if ( ! $result )
{
$result = $c->l('mai_SUCCESS');
}
}
}
# common part
if ($res ne 'OK') {
$c->stash( error => $result );
$c->stash( title => $title, mai_datas => \%mai_datas );
return $c->render( $dest );
}
if ($res ne 'OK')
{
$c->stash( error => $result );
$c->stash( title => $title, mai_datas => \%mai_datas );
return $c->render( $dest );
}
my $message = "emailsettings updates $trt DONE";
$c->app->log->info($message);
@@ -221,7 +239,6 @@ sub do_update {
};
sub get_virus_status {
my ($c, $localise) = @_;
@@ -249,10 +266,10 @@ sub localise_status {
}
sub get_prop {
sub get_db_prop {
my ($c, $item, $prop, $default) = @_;
return $cdb->get_prop($item, $prop) || $default;
}
@@ -364,6 +381,48 @@ sub get_current_imap_access {
}
sub get_current_smtp_ssl_auth {
my ($c, $localise, $soru, $debug) = @_;
die "Error: \$soru must be either 's' or 'u':$soru.\n" unless $soru eq 's' || $soru eq 'u';
$cdb = esmith::ConfigDB->open || die "Couldn't open config db";
# Initialize variables with default values
my $smtpStatus = 'none';
my $smtpAccess = 'none';
my $smtpAuth = 'disabled'; # assuming 'disabled' as a default
# Fetch SMTP settings based on the value of `$soru`
if ($soru eq "u") {
$smtpStatus = $cdb->get_prop('uqpsmtpd', 'status') || 'enabled'; # Fetch from uqpsmtpd
$smtpAccess = $cdb->get_prop('uqpsmtpd', 'access') || 'public';
$smtpAuth = 'enabled'; # Assuming authentication is enabled in this context
} else {
$smtpStatus = $cdb->get_prop('sqpsmtpd', 'status') || 'enabled'; # Fetch from sqpsmtpd
$smtpAccess = $cdb->get_prop('sqpsmtpd', 'access') || 'public';
$smtpAuth = 'enabled'; # Assuming authentication is enabled in this context
}
# Retrieve SMTP SSL authentication options
my $options = $c->get_smtp_ssl_auth_options();
if ($soru eq "u" && $debug ) {
$c->stash('smtp'=>[$smtpStatus,$smtpAccess,$smtpAuth,$soru,$options->{$smtpAccess},$c->l($options->{$smtpAccess})]);
# die "Stop $soru in get_current_smtp_ssl_auth";
}
# Return appropriate message based on SMTP settings
if ($smtpStatus eq 'enabled' && $smtpAuth eq 'enabled') {
return $localise ? $c->l($options->{$smtpAccess}) : $smtpAccess;
}
return $localise ? $c->l($options->{disabled}) : 'disabled';
}
sub get_current_smtp_auth {
my ($c, $localise) = @_;
@@ -371,16 +430,13 @@ sub get_current_smtp_auth {
my $smtpStatus = $cdb->get_prop('qpsmtpd', 'status') || 'enabled';
my $smtpAuth = $cdb->get_prop('qpsmtpd', 'Authentication') || 'enabled';
my $smtpsStatus = $cdb->get_prop('sqpsmtpd', 'status') || 'enabled';
my $smtpsAuth = $cdb->get_prop('sqpsmtpd', 'Authentication') || 'enabled';
my $options = get_smtp_auth_options();
if ($smtpStatus eq 'enabled' && $smtpAuth eq 'enabled')
if ($smtpStatus eq 'enabled' && $smtpAuth eq 'disabled')
{
return $localise ? $c->l($options->{public}) : 'public';
}
elsif ($smtpsStatus eq 'enabled' && $smtpsAuth eq 'enabled')
elsif ($smtpStatus eq 'enabled' && $smtpAuth eq 'enabled')
{
return $localise ? $c->l($options->{publicSSL}) : 'publicSSL';
}
@@ -388,6 +444,8 @@ sub get_current_smtp_auth {
}
sub get_current_webmail_status {
my ($c, $localise) = @_;
@@ -395,19 +453,16 @@ sub get_current_webmail_status {
# determine status of webmail
my $WebmailStatus = "disabled";
my $IMPStatus = $cdb->get_prop('imp', 'status') || 'disabled';
my $HordeStatus = $cdb->get_prop('horde', 'status') || 'disabled';
my $RoundcubeStatus = $cdb->get_prop('roundcube', 'status') || 'disabled';
my $MysqlStatus = $cdb->get_prop('mariadb', 'status') || 'disabled';
my $PHPStatus = $cdb->get_prop('php', 'status') || 'disabled';
my $PHPStatus = $cdb->get_prop('php81-php-fpm', 'status') || 'disabled';
my $Networkaccess = $cdb->get_prop('horde','access') || 'disabled';
my $Networkaccess = $cdb->get_prop('roundcube','access') || 'disabled';
# all four components must be on for webmail to be working
if ( ( $IMPStatus eq "enabled" )
&& ( $HordeStatus eq "enabled" )
# all 3 components must be on for webmail to be working
if ( ( $RoundcubeStatus eq "enabled" )
&& ( $MysqlStatus eq "enabled" )
&& ( $PHPStatus eq "enabled" )
&& ( $Networkaccess eq "public"))
@@ -415,8 +470,7 @@ sub get_current_webmail_status {
$WebmailStatus = "enabledSSL";
}
elsif ( ( $IMPStatus eq "enabled" )
&& ( $HordeStatus eq "enabled" )
elsif ( ( $RoundcubeStatus eq "enabled" )
&& ( $MysqlStatus eq "enabled" )
&& ( $PHPStatus eq "enabled" )
&& ( $Networkaccess eq "private" ))
@@ -491,13 +545,58 @@ sub get_imap_options {
}
sub get_smtp_auth_opt {
my $c = shift;
return [[ $c->l('mai_SECURE_SMTP') => 'publicSSL'],
[ $c->l('Only allow insecure access') => 'public'],
[ $c->l('DISABLED') => 'disabled']
];
}
sub get_smtp_auth_options {
my $c = shift;
my %options = ( disabled => 'DISABLED', publicSSL => 'mai_SECURE_SMTP', public => 'mai_INSECURE_SMTP');
my %options = ( publicSSL => 'mai_SECURE_SMTP', public => 'Only allow insecure access',disabled => 'DISABLED');
\%options;
return \%options;
}
sub get_smtp_ssl_auth_options {
my $c = shift;
my %options = ( public => 'Allow public access', local => 'Allow local access only',disabled => 'DISABLED');
return \%options;
}
sub get_smtp_ssl_auth_opt {
my $c = shift;
return [[ $c->l('Allow public access') => 'public'],
[ $c->l('Allow local access only') => 'local'],
[ $c->l('DISABLED') => 'disabled']
];
}
sub get_key_by_value {
my ($hash_ref, $target_value) = @_;
# Iterate over the hash
while (my ($key, $value) = each %$hash_ref) {
return $key if $value eq $target_value;
}
return undef; # Return undef if no match is found
}
sub get_value_by_key {
my ($hash_ref, $key) = @_;
return $hash_ref->{$key}; # Return the value associated with the key
}
@@ -507,8 +606,7 @@ sub get_webmail_opt {
return [[ $c->l('DISABLED') => 'disabled' ],
[ $c->l('mai_ENABLED_SECURE_ONLY') => 'enabledSSL' ],
[ $c->l('mai_ONLY_LOCAL_NETWORK_SSL') => 'localnetworkSSL' ],
[ $c->l('mai_ENABLED_BOTH') => 'public' ]];
[ $c->l('mai_ONLY_LOCAL_NETWORK_SSL') => 'localnetworkSSL' ]];
}
@@ -519,10 +617,10 @@ sub get_webmail_options {
my %options = (
disabled => 'DISABLED',
enabledSSL => 'mai_ENABLED_SECURE_ONLY',
localnetworkSSL => 'mai_ONLY_LOCAL_NETWORK_SSL' );
enabledSSL => 'mai_ENABLED_SECURE_ONLY',
localnetworkSSL => 'mai_ONLY_LOCAL_NETWORK_SSL');
\%options;
return \%options;
}
@@ -538,15 +636,6 @@ sub get_retrieval_opt {
}
sub get_smtp_auth_opt {
my $c = shift;
return [[ $c->l('DISABLED') => 'disabled'],
[ $c->l('mai_SECURE_SMTP') => 'publicSSL'],
[ $c->l('mai_INSECURE_SMTP') => 'public']];
}
sub get_emailunknownuser_options {
@@ -658,6 +747,7 @@ sub display_multidrop {
sub change_settings_reception {
my $c = shift;
$cdb = esmith::ConfigDB->open || die "Couldn't open config db";
my $FetchmailMethod = ( $c->param('FetchmailMethod') || 'standard' );
@@ -701,18 +791,47 @@ sub change_settings_reception {
}
}
my $smtpAuth = ($c->param('SMTPAuth') || 'public');
if ($smtpAuth eq 'public') {
$cdb->set_prop("qpsmtpd", "Authentication", "enabled" );
$cdb->set_prop("sqpsmtpd", "Authentication", "enabled" );
} elsif ($smtpAuth eq 'publicSSL') {
$cdb->set_prop("qpsmtpd", "Authentication", "disabled" );
$cdb->set_prop("sqpsmtpd", "Authentication", "enabled" );
} else {
$cdb->set_prop("qpsmtpd", "Authentication", "disabled" );
$cdb->set_prop("sqpsmtpd", "Authentication", "disabled" );
}
# Need code here for all 3 options - 25, 465 ad 587
# Options for 25 are enabled and disabled
# for 465 and 587 are (access) public, local and (status) disabled
#my $smtpAuth = ($c->param('SMTPAuth') || 'public');
#if ($smtpAuth eq 'public') {
#$cdb->set_prop("qpsmtpd", "Authentication", "enabled" );
#$cdb->set_prop("sqpsmtpd", "Authentication", "enabled" );
#} elsif ($smtpAuth eq 'publicSSL') {
#$cdb->set_prop("qpsmtpd", "Authentication", "disabled" );
#$cdb->set_prop("sqpsmtpd", "Authentication", "enabled" );
#} else {
#$cdb->set_prop("qpsmtpd", "Authentication", "disabled" );
#$cdb->set_prop("sqpsmtpd", "Authentication", "disabled" );
#}
my @keys = qw(qpsmtpd uqpsmtpd sqpsmtpd);
foreach my $key (@keys) {
my $param_name = $key eq 'qpsmtpd' ? 'SMTPAuth'
: $key eq 'uqpsmtpd' ? 'uSMTPAuth'
: 'sSMTPAuth'; # Defaults to 'sSMTPAuth' for 'sqpsmtpd'
my $SMTPAuth = $c->param($param_name);
if ($SMTPAuth eq 'disabled') {
$cdb->set_prop($key, 'status', 'disabled');
$cdb->set_prop($key, 'access', 'disabled');
} else {
$cdb->set_prop($key, 'status', 'enabled');
if ($key eq 'qpsmtpd') {
my $auth_status = $SMTPAuth eq 'publicSSL' ? 'enabled' : 'disabled';
$cdb->set_prop($key, 'Authentication', $auth_status);
$cdb->set_prop($key, 'access', 'public');
} else {
$cdb->set_prop($key, 'Authentication', 'enabled');
my $auth_key = ($key eq 'uqpsmtpd') ? 'uSMTPAuth' : 'sSMTPAuth';
my $access_value = $c->param($auth_key) eq 'public' ? 'public' : 'local';
$cdb->set_prop($key, 'access', $access_value);
}
}
}
unless ( system( "/sbin/e-smith/signal-event", "email-update" ) == 0 )
{
return $c->l('mai_ERROR_UPDATING_CONFIGURATION');
@@ -724,6 +843,7 @@ sub change_settings_reception {
sub change_settings_delivery {
my ($c) = shift;
$cdb = esmith::ConfigDB->open || die "Couldn't open config db";
my $EmailUnknownUser = ($c->param('EmailUnknownUser') || 'returntosender');
@@ -752,7 +872,8 @@ sub change_settings_delivery {
sub change_settings_access {
my $c = shift;
$cdb = esmith::ConfigDB->open || die "Couldn't open config db";
my $pop3Access = ($c->param('POPAccess') || 'private');
if ($pop3Access eq 'disabled') {
$cdb->set_prop('pop3', "status", "disabled" );
@@ -802,38 +923,22 @@ sub change_settings_access {
#------------------------------------------------------------
my $webmail = ($c->param('WebMail') || 'disabled');
if ( $webmail eq "enabled" ) {
$cdb->set_prop('php', "status", $webmail );
$cdb->set_prop('mariadb',"status", $webmail );
$cdb->set_prop('imp',"status", $webmail );
$cdb->set_prop('horde', "status", $webmail );
$cdb->set_prop('imp',"access", "full" );
$cdb->set_prop('horde',"access", "public" );
$cdb->set_prop('horde',"HttpsOnly", "no" );
}
elsif ( $webmail eq "enabledSSL" ) {
$cdb->set_prop('php',"status", "enabled" );
if ( $webmail eq "enabledSSL" ) {
$cdb->set_prop('php81-php-fpm',"status", "enabled" );
$cdb->set_prop('mariadb',"status", "enabled" );
$cdb->set_prop('imp',"status", 'enabled' );
$cdb->set_prop('horde',"status", 'enabled' );
$cdb->set_prop('imp',"access", "SSL" );
$cdb->set_prop('horde',"access", "public" );
$cdb->set_prop('horde',"HttpsOnly", "yes" );
$cdb->set_prop('roundcube',"status", 'enabled' );
$cdb->set_prop('roundcube',"access", "public" );
}
elsif ( $webmail eq "localnetworkSSL" ) {
$cdb->set_prop('php',"status", "enabled" );
$cdb->set_prop('php81-php-fpm',"status", "enabled" );
$cdb->set_prop('mariadb',"status", "enabled" );
$cdb->set_prop('imp',"status", 'enabled' );
$cdb->set_prop('horde',"status", 'enabled' );
$cdb->set_prop('imp',"access", "SSL" );
$cdb->set_prop('horde',"access", "private" );
$cdb->set_prop('horde',"HttpsOnly", "yes" );
$cdb->set_prop('roundcube',"status", 'enabled' );
$cdb->set_prop('roundcube',"access", "private" );
}
else {
$cdb->set_prop('imp',"status", 'disabled' );
$cdb->set_prop('horde',"status", 'disabled' );
$cdb->set_prop('roundcube',"status", 'disabled' );
}
unless ( system( "/sbin/e-smith/signal-event", "email-update" ) == 0 ) {
@@ -847,6 +952,8 @@ sub change_settings_access {
sub change_settings_filtering {
my $c = shift;
$cdb = esmith::ConfigDB->open || die "Couldn't open config db";
my $virus_status = ( $c->param('VirusStatus') || 'disabled' );
$cdb->set_prop("qpsmtpd", 'VirusScan', $virus_status);
@@ -860,7 +967,7 @@ sub change_settings_filtering {
Subject
SubjectTag) )
{
$cdb->set_prop('spamassassin', $param, $c->param("Spam$param"));
$cdb->set_prop('spamassassin', $param, $c->param("Spam$param"));
}
my $patterns_status = $c->adjust_patterns() ? 'enabled' : 'disabled';
@@ -868,7 +975,7 @@ sub change_settings_filtering {
unless ( system( "/sbin/e-smith/signal-event", "email-update" ) == 0 )
{
return $c->l('mai_ERROR_UPDATING_CONFIGURATION');
return $c->l('mai_ERROR_UPDATING_CONFIGURATION');
}
return 'OK';
@@ -922,4 +1029,4 @@ sub validate_smarthost {
}
1;
1;

View File

@@ -1,5 +1,10 @@
package SrvMngr::Controller::Legacypanel;
#----------------------------------------------------------------------
# heading : Legacy
# description : Legacy panel
# navigation : 99999 9999
#----------------------------------------------------------------------
#----------------------------------------------------------------------
# name : legacypanel, method : get, url : /legacypanel, ctlact : Legacypanel#main
#

View File

@@ -0,0 +1,472 @@
#
# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-11-16 10:30:16
#
#
# Routines to be edited by the developer to provide content and validation for parameters
# and provison of the control data for table(s)
#
use esmith::util;
use esmith::util::network;
use esmith::ConfigDB;
use esmith::HostsDB;
use esmith::AccountsDB;
use esmith::NetworksDB;
use esmith::DomainsDB;
use constant FALSE => 0;
use constant TRUE => 1;
#The most common ones
our $cdb = esmith::ConfigDB->open() || die("Couldn't open config db");
our $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db");
our $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db");
our $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db");
our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db");
# Validation routines - parameters for each panel
sub validate_LIST {
my $c = shift;
my $prefix_data = shift; #Data hash as parameter
# Validation for each field
my $ret = "";
if (! TRUE) #validate $c->param('InternalIP')
{$ret .= 'Validation for InternalIP failed';}
if (! TRUE) #validate $c->param('ExternalIP')
{$ret .= 'Validation for ExternalIP failed';}
if (! TRUE) #validate $c->param('InternetIP')
{$ret .= 'Validation for InternetIP failed';}
if (! TRUE) #validate $c->param('Issuer')
{$ret .= 'Validation for Issuer failed';}
if (! TRUE) #validate $c->param('Expiry')
{$ret .= 'Validation for Expiry failed';}
if (! TRUE) #validate $c->param('NotBefore')
{$ret .= 'Validation for NotBefore failed';}
if ($ret eq "") {$ret = 'ok';}
return $ret;
}
sub validate_PARAMS {
my $c = shift;
my $prefix_data = shift; #Data hash as parameter
# Validation for each field
my $ret = "";
if (! TRUE) #validate $c->param('status')
{$ret .= 'Validation for status failed';}
if (! TRUE) #validate $c->param('hookScript')
{$ret .= 'Validation for hookScript failed';}
if (! TRUE) #validate $c->param('hostOverride')
{$ret .= 'Validation for hostOverride failed';}
if (! TRUE) #validate $c->param('ACCEPT_TERMS')
{$ret .= 'Validation for ACCEPT_TERMS failed';}
if (! TRUE) #validate $c->param('API')
{$ret .= 'Validation for API failed';}
if (! TRUE) #validate $c->param('keysize')
{$ret .= 'Validation for keysize failed';}
if (! TRUE) #validate $c->param('configure')
{$ret .= 'Validation for configure failed';}
if (! TRUE) #validate $c->param('Email')
{$ret .= 'Validation for Email failed';}
if ($ret eq "") {$ret = 'ok';}
return $ret;
}
sub validate_CHECKALLDOMAINS {
my $c = shift;
my $prefix_data = shift; #Data hash as parameter
# Validation for each field
my $ret = "";
if (! TRUE) #validate $c->param('AllDomainsCheck')
{$ret .= 'Validation for AllDomainsCheck failed';}
if ($ret eq "") {$ret = 'ok';}
return $ret;
}
sub validate_CHECKALLENABLEDDOMAINS {
my $c = shift;
my $prefix_data = shift; #Data hash as parameter
# Validation for each field
my $ret = "";
if (! TRUE) #validate $c->param('EnabledDomainsCheck')
{$ret .= 'Validation for EnabledDomainsCheck failed';}
if ($ret eq "") {$ret = 'ok';}
return $ret;
}
sub validate_CHECKONEDOMAIN {
my $c = shift;
my $prefix_data = shift; #Data hash as parameter
# Validation for each field
my $ret = "";
if (! TRUE) #validate $c->param('OneDomainToCheck')
{$ret .= 'Validation for OneDomainToCheck failed';}
if (! TRUE) #validate $c->param('OneDomainsCheck')
{$ret .= 'Validation for OneDomainsCheck failed';}
if ($ret eq "") {$ret = 'ok';}
return $ret;
}
# Get singleton data for each panel
sub get_data_for_panel_LIST {
# Return a hash with the fields required which will be loaded into the shared data
my $c = shift;
# my ($reply, $err, $server_cert) = Net::SSLeay::sslcat('localhost', 443, '/');
# my $issuer = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($server_cert));
# my $before = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notBefore($server_cert));
# my $expiry = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($server_cert));
my %ret = (
'Data1'=>'Data for LIST', #Example
# fields from Inputs in LIST $fields['LIST']
'InternalIP'=>$cdb->get_prop('InternalInterface','IPAddress'),
'ExternalIP'=>$cdb->get_prop('ExternalInterface','IPAddress'),
'InternetIP'=>$c->get_my_ip(),
'Issuer'=>'$issuer',
'Expiry'=>'$expiry',
'NotBefore'=>'$before',
);
return %ret;
}
sub get_data_for_panel_PARAMS {
# Return a hash with the fields required which will be loaded into the shared data
my $c = shift;
my %ret = (
'Data1'=>'Data for PARAMS', #Example
# fields from Inputs in PARAMS $fields['PARAMS']
'status'=>$cdb->get_prop('letsencrypt', 'status', 'disabled'),
'hookScript'=>$cdb->get_prop('letsencrypt', 'hookScript', 'disabled'),
'hostOverride'=>$cdb->get_prop('letsencrypt', 'hostOverride', 'disabled'),
'ACCEPT_TERMS'=>$cdb->get_prop('letsencrypt', 'ACCEPT_TERMS', ''),
'API'=>$cdb->get_prop('letsencrypt', 'API', '2'),
'keysize'=>$cdb->get_prop('letsencrypt', 'keysize', '4096'),
'configure'=>$cdb->get_prop('letsencrypt', 'configure', 'none' ),
'email'=>$cdb->get_prop('letsencrypt', 'email')
);
return %ret;
}
sub get_data_for_panel_CHECKALLDOMAINS {
# Return a hash with the fields required which will be loaded into the shared data
my $c = shift;
my %ret = (
'Data1'=>'Data for CHECKALLDOMAINS', #Example
# fields from Inputs in CHECKALLDOMAINS $fields['CHECKALLDOMAINS']
'AllDomainsCheck'=>$c->update_all_domains(),
);
return %ret;
}
sub get_data_for_panel_CHECKALLENABLEDDOMAINS {
# Return a hash with the fields required which will be loaded into the shared data
my $c = shift;
my %ret = (
'Data1'=>'Data for CHECKALLENABLEDDOMAINS', #Example
# fields from Inputs in CHECKALLENABLEDDOMAINS $fields['CHECKALLENABLEDDOMAINS']
'EnabledDomainsCheck'=>$c->update_enabled_domains(),
);
return %ret;
}
sub get_data_for_panel_CHECKONEDOMAIN {
# Return a hash with the fields required which will be loaded into the shared data
my $c = shift;
my %ret = (
'Data1'=>'Data for CHECKONEDOMAIN', #Example
# fields from Inputs in CHECKONEDOMAIN $fields['CHECKONEDOMAIN']
'OneDomainToCheck'=>$c->param("CHECKONEDOMAIN"),
'OneDomainsCheck'=>$c->update_one_domain($c->param("CHECKONEDOMAIN"))
);
return %ret;
}
# Get control data for table(s)
# Define a constant hash for field name mapping
use constant DomainList_FIELD_MAPPING => (
'Table1-Domain name / HOSTNAME' => 'Domain',
'Table1-Brief description' => 'Description',
'Table1-Content' => 'Content',
'Table1-LABEL_NAMESERVERS' => 'Nameservers',
'Table1-LABEL_POINT' => 'Source-for-Table1-LABEL_POINT',
'Table1-LABEL_LECERT' => 'letsencryptSSLcert',
'Table1-IS_IN_CERT' => 'isincert',
'Table1-CHECK' => 'Check'
#'target_field2' => 'source_field2',
# Add more mappings as needed
);
use constant TEST_DOMAIN_LIST => (
{ "domain" => "Domain1","fred" => "fred1" , "description"=>"Description1"},
{ "domain" => "Domain2", "fred" => "fred2", "description"=>"Description2" },
{ "domain" => "Domain3", "fred" => "fred3", "description"=>"Description3" },
# Add more test entries as needed
);
sub actual_DomainList {
my $c = shift;
# Actual code for extracting DomainList
my @list = ();
# my @rv = Net::SSLeay::X509_get_subjectAltNames($server_cert);
# foreach my $element (@rv) {
# next if $element =~ /^\d+$/; ;
# #print $element . "\n";
# push @list, $element;
# }
my @data = ();
my $check = $c->l('Check Domain');
for ($ddb->domains)
{
my $ns = $_->prop('Nameservers') || 'internet';
my $le = $_->prop('letsencryptSSLcert') || 'disabled';#letsencrypt configure all
my $dname= $_->key;
my $isincert = "N";
my $link = $c->create_link("letsencryptd","CHECKONEDOMAIN","");
my $checklink = "<a href='".$link."&CHECKONEDOMAIN=".$_->key."'>".$check."</a>";
#my $checklink = "<a href=''>check</a>";
$isincert = "Y" if ( $dname ~~ @list);
# domain
push @data,
{ Domain => $_->key,
$_->props,
letsencryptSSLcert => $le,
isincert => $isincert,
Check => $checklink,
Nameservers => $ns,
};
#and hosts
for my $h ($hdb->get_hosts_by_domain($dname))
{
next if $ddb->get($h->key);
next unless ($h->prop('HostType') eq "Self" || $h->prop('HostType') eq "Local");
$le = $h->prop('letsencryptSSLcert') || 'disabled';#letsencrypt configure all
$isincert = "N";
$isincert = "Y" if ( $h->key ~~ @list);
push @data,
{ Domain => "--> ". $h->key,
$h->props,
Description=>$h->prop('ExternalIP')|| $h->prop('InternalIP')||"",
Content => $h->prop('HostType'),
isincert => $isincert,
Check => "", #$checklink
Nameservers => $c->l($ns),
}
}
}
return @data;
}
sub get_DomainList {
# Return an array of hashes of the contents for each row and column for DomainList
my $c = shift;
my @source_records = $c->actual_DomainList(); #TEST_DOMAIN_LIST #Replace by code or call to produce contents of table;
my @transformed_records;
my %Field_Mapping = DomainList_FIELD_MAPPING;
# Iterate over each record in the source array
for my $source_record (@source_records) {
my %transformed_record;
# Iterate over each key-value pair in the $Field_Mapping constant
while (my ($target, $source) = each %Field_Mapping) {
# Check if the source field exists in the source record
if (exists $source_record->{$source}) {
# Assign the source field value to the target field in the transformed record
$transformed_record{$target} = $source_record->{$source};
}
}
# Add transformed record to the array if it's not empty
push @transformed_records, \%transformed_record if %transformed_record;
}
return \@transformed_records;
}
# Return hash with values from row in which link clicked on table
sub get_selected_LIST {
my $c = shift;
my $selected = shift; #Parameter is name of selected row.
my $is_new_record = shift; #Indicates new record required (defaults)
my %ret = {};
return $ret;
}
sub get_selected_PARAMS {
my $c = shift;
my $selected = shift; #Parameter is name of selected row.
my $is_new_record = shift; #Indicates new record required (defaults)
my %ret = {};
return $ret;
}
sub get_selected_CHECKALLDOMAINS {
my $c = shift;
my $selected = shift; #Parameter is name of selected row.
my $is_new_record = shift; #Indicates new record required (defaults)
my %ret = {};
return $ret;
}
sub get_selected_CHECKALLENABLEDDOMAINS {
my $c = shift;
my $selected = shift; #Parameter is name of selected row.
my $is_new_record = shift; #Indicates new record required (defaults)
my %ret = {};
return $ret;
}
sub get_selected_CHECKONEDOMAIN {
my $c = shift;
my $selected = shift; #Parameter is name of selected row.
my $is_new_record = shift; #Indicates new record required (defaults)
my %ret = {};
return $ret;
}
#after sucessful modify or create or whatever and submit then perfom (if the params validate)
sub perform_LIST {
my $c = shift;
my $prefix_data = shift; #Data hash as parameter
my $ret = "";
my $db = $cdb; #maybe one of the others
my $dbkey = 'ChangeThis';
if (! TRUE) #copy or perform with value: InternalIP e.g. $db->set_prop($dbkey,'InternalIP',$c->param('InternalIP'),type=>'service'))
{$ret .= 'Perform/save failed for InternalIP';}
if (! TRUE) #copy or perform with value: ExternalIP e.g. $db->set_prop($dbkey,'ExternalIP',$c->param('ExternalIP'),type=>'service'))
{$ret .= 'Perform/save failed for ExternalIP';}
if (! TRUE) #copy or perform with value: InternetIP e.g. $db->set_prop($dbkey,'InternetIP',$c->param('InternetIP'),type=>'service'))
{$ret .= 'Perform/save failed for InternetIP';}
if (! TRUE) #copy or perform with value: Issuer e.g. $db->set_prop($dbkey,'Issuer',$c->param('Issuer'),type=>'service'))
{$ret .= 'Perform/save failed for Issuer';}
if (! TRUE) #copy or perform with value: Expiry e.g. $db->set_prop($dbkey,'Expiry',$c->param('Expiry'),type=>'service'))
{$ret .= 'Perform/save failed for Expiry';}
if (! TRUE) #copy or perform with value: NotBefore e.g. $db->set_prop($dbkey,'NotBefore',$c->param('NotBefore'),type=>'service'))
{$ret .= 'Perform/save failed for NotBefore';}
if ($ret eq "") {$ret = 'ok';}
return $ret;
}
sub perform_PARAMS {
my $c = shift;
my $prefix_data = shift; #Data hash as parameter
my $ret = "";
my $db = $cdb; #maybe one of the others
my $dbkey = 'letsencrypt';
# To make it write to DB as comment, delete this (regex) string in each if statement "TRUE\) \#copy or perform with value: .* e.g."
if (! $db->set_prop($dbkey,'status',$c->param('status'),type=>'service'))
{$ret .= 'Perform/save failed for status';}
if (! $db->set_prop($dbkey,'hookScript',$c->param('hookScript'),type=>'service'))
{$ret .= 'Perform/save failed for hookScript';}
if (! $db->set_prop($dbkey,'hostOverride',$c->param('hostOverride'),type=>'service'))
{$ret .= 'Perform/save failed for hostOverride';}
if (! $db->set_prop($dbkey,'ACCEPT_TERMS',$c->param('ACCEPT_TERMS'),type=>'service'))
{$ret .= 'Perform/save failed for ACCEPT_TERMS';}
if (! $db->set_prop($dbkey,'API',$c->param('API'),type=>'service'))
{$ret .= 'Perform/save failed for API';}
if (! $db->set_prop($dbkey,'keysize',$c->param('keysize'),type=>'service'))
{$ret .= 'Perform/save failed for keysize';}
if (! $db->set_prop($dbkey,'configure',$c->param('configure'),type=>'service'))
{$ret .= 'Perform/save failed for configure';}
if (! $db->set_prop($dbkey,'email',$c->param('email'),type=>'service'))
{$ret .= 'Perform/save failed for email';}
if ($ret eq "") {$ret = 'ok';}
return $ret;
}
sub perform_CHECKALLDOMAINS {
my $c = shift;
my $prefix_data = shift; #Data hash as parameter
my $ret = "";
my $db = $cdb; #maybe one of the others
my $dbkey = 'ChangeThis';
if (! TRUE) #copy or perform with value: AllDomainsCheck e.g. $db->set_prop($dbkey,'AllDomainsCheck',$c->param('AllDomainsCheck'),type=>'service'))
{$ret .= 'Perform/save failed for AllDomainsCheck';}
if ($ret eq "") {$ret = 'ok';}
return $ret;
}
sub perform_CHECKALLENABLEDDOMAINS {
my $c = shift;
my $prefix_data = shift; #Data hash as parameter
my $ret = "";
my $db = $cdb; #maybe one of the others
my $dbkey = 'ChangeThis';
if (! TRUE) #copy or perform with value: EnabledDomainsCheck e.g. $db->set_prop($dbkey,'EnabledDomainsCheck',$c->param('EnabledDomainsCheck'),type=>'service'))
{$ret .= 'Perform/save failed for EnabledDomainsCheck';}
if ($ret eq "") {$ret = 'ok';}
return $ret;
}
sub perform_CHECKONEDOMAIN {
my $c = shift;
my $prefix_data = shift; #Data hash as parameter
my $ret = "";
my $db = $cdb; #maybe one of the others
my $dbkey = 'ChangeThis';
if (! TRUE) #copy or perform with value: OneDomainToCheck e.g. $db->set_prop($dbkey,'OneDomainToCheck',$c->param('OneDomainToCheck'),type=>'service'))
{$ret .= 'Perform/save failed for OneDomainToCheck';}
if (! TRUE) #copy or perform with value: OneDomainsCheck e.g. $db->set_prop($dbkey,'OneDomainsCheck',$c->param('OneDomainsCheck'),type=>'service'))
{$ret .= 'Perform/save failed for OneDomainsCheck';}
if ($ret eq "") {$ret = 'ok';}
return $ret;
}
sub create_link{
# WIP
my ($c,$route, $panel, $index) = @_;
my $link = "$route?trt=$panel&Selected=$index";
return $link;
}
sub get_my_ip
{
my ($self, $item, $prop, $default) = @_;
my $output = `/usr/sbin/e-smith/getmyip`;
return $output || "IP";
}
sub update_one_domain
{
my ($self,$domain) = @_;
return "$domain not domain" unless ($ddb->get($domain) || $hdb->get($domain));
($domain) = ($domain =~ /([\w\p{L}.]+)/);
my $output = `/etc/e-smith/events/actions/letsencrypt-setdomains " " $domain `;
return $output || "-empty-";
}
sub update_all_domains
{
my $self = shift;
my $output = `/etc/e-smith/events/actions/letsencrypt-setdomains "" "" all `;
return $output || "-empty-";
}
sub update_enabled_domains
{
my $self = shift;
my $output = `/etc/e-smith/events/actions/letsencrypt-setdomains "" "" enabled `;
return $output || "-empty-";
}
1;

View File

@@ -0,0 +1,429 @@
package SrvMngr::Controller::Letsencrypt;
#
# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43
#
#----------------------------------------------------------------------
# heading : Network
# description : Letsencrypt certificate
# navigation : 6000 6600
#
# name : letsencrypt, method : get, url : /letsencrypt, ctlact : Letsencrypt#main
# name : letsencryptu, method : post, url : /letsencryptu, ctlact : Letsencrypt#do_update
# name : letsencryptd, method : get, url : /letsencryptd, ctlact : Letsencrypt#do_display
#
# routes : end
#
# Documentation: https://wiki.contribs.org/Letsencrypt
#----------------------------------------------------------------------
#
# Scheme of things:
#
# TBA!!
use strict;
use warnings;
use Mojo::Base 'Mojolicious::Controller';
use constant FALSE => 0;
use constant TRUE => 1;
use Locale::gettext;
use SrvMngr::I18N;
use SrvMngr qw(theme_list init_session);
use Data::Dumper;
use esmith::util;
use esmith::util::network;
use esmith::ConfigDB;
use esmith::AccountsDB;
use esmith::NetworksDB;
use esmith::HostsDB;
use esmith::DomainsDB;
require '/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt-Custom.pm'; #The code that is to be added by the developer
sub main {
#
# Initial entry - route is "/<whatever>"
#
#set initial panel
#for initial panel:
#Specifiy panel to enter
#load up _data hash with DB fields
#load up stash with pointer(s) to control fields hash(= get-))
#and a pointer to the prefix_data hash
#render initial panel
my $c = shift;
$c->app->log->info( $c->log_req );
#The most common ones
my $cdb = esmith::ConfigDB->open() || die("Couldn't open config db");
my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db");
my $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db");
my $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db");
my $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db");
my %lets_data = ();
my $title = $c->l('lets_Letsencrypt_certificate');
my $modul = '';
$lets_data{'trt'} = 'LIST';
#Load any DB entries into the <prefix>_data area so as they are preset in the form
# which DB - this only really works if the initial panel is a PARAMS type panel and not a TABLE
my $db = $cdb; #pickup local or global db or Default to config
$c->do_display($lets_data{'trt'});
}
# Post request with params - submit from the form
sub do_update {
#
# Return after submit pushed on panel (this is a post) - route is "/<whatever>u"
# parameters in the params hash.
#
#load up all params into prefix_data hash:
#By panel (series of if statements - only one executed):
#call validate-PANEL() - return ret = ok or error message
#if validation not ok:
#render back to current panel with error message in stash
#otherwise:
#By panel (series of if statements - only one executed):
#do whatever is required: call perform-PANEL() - return "ok" or Error Message
#call signal-event for any global actions specified (check it exists - error and continue?)
#if action smeserver-<whatever>-update exists
#signal_event smeserver-<whatever>-update
#call signal-event for any specific actions for thids panel (check it exists first - error and continue)
#set success in stash
#if no "nextpanel" entry:
#set firstpanel
#else
#set nextpanel
#call render
my $c = shift;
$c->app->log->info($c->log_req);
my $modul = '';
#The most common ones - you might want to comment out any not used.
my $cdb = esmith::ConfigDB->open() || die("Couldn't open config db");
my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db");
my $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db");
my $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db");
my $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db");
my %lets_data = ();
my $title = $c->l('lets_Letsencrypt_certificate');
# Accessing all POST parameters
my %params = $c->req->params->to_hash;
# Get number of POST parameters
my $num_params = keys %params;
#Params are available in the hash "params" - copy to the prefix_data hash
#while (my ($key, $value) = each %{$c->req->params->to_hash}) {
# $lets_data{$key} = $value;
#}
# the value of trt will tell you which panel has returned
my $trt = $c->param('trt') || 'LIST'; #hidden control on every form.
my $ret = 'ok';
#Validate the parameters in a custom sub one for each panel (although only one of these will be executed)
my $thispanel;
if ($trt eq 'LIST'){
#Validate form parameters for panel LIST
$ret = $c->validate_LIST(\%lets_data);
$thispanel = 'LIST';
}
if ($trt eq 'PARAMS'){
#Validate form parameters for panel PARAMS
$ret = $c->validate_PARAMS(\%lets_data);
$thispanel = 'PARAMS';
}
if ($trt eq 'CHECKALLDOMAINS'){
#Validate form parameters for panel CHECKALLDOMAINS
$ret = $c->validate_CHECKALLDOMAINS(\%lets_data);
$thispanel = 'CHECKALLDOMAINS';
}
if ($trt eq 'CHECKALLENABLEDDOMAINS'){
#Validate form parameters for panel CHECKALLENABLEDDOMAINS
$ret = $c->validate_CHECKALLENABLEDDOMAINS(\%lets_data);
$thispanel = 'CHECKALLENABLEDDOMAINS';
}
if ($trt eq 'CHECKONEDOMAIN'){
#Validate form parameters for panel CHECKONEDOMAIN
$ret = $c->validate_CHECKONEDOMAIN(\%lets_data);
$thispanel = 'CHECKONEDOMAIN';
}
if ($ret ne "ok"){
$c->do_display($thispanel);
} else {
#Do whatever is needed, including writing values to the DB
if ($trt eq 'LIST'){
#do whatever is required ...
$ret = $c->perform_LIST(\%lets_data);
if ($ret ne "ok") {
# return to the panel with error message
$c->stash(error => $c->l($ret));
$c->stash(
title => $title,
modul => $modul,
lets_data => \%lets_data
);
$c->render(template => "letsencrypt");
} else {
$c->stash( success => $c->l('lets_LIST_panel_action_was_successful')); #A bit bland - edit it in the lex file
}
}
if ($trt eq 'PARAMS'){
#do whatever is required ...
$ret = $c->perform_PARAMS(\%lets_data);
if ($ret ne "ok") {
# return to the panel with error message
$c->stash(error => $c->l($ret));
$c->stash(
title => $title,
modul => $modul,
lets_data => \%lets_data
);
$c->render(template => "letsencrypt");
} else {
$c->stash( success => $c->l('lets_PARAMS_panel_action_was_successful')); #A bit bland - edit it in the lex file
}
}
if ($trt eq 'CHECKALLDOMAINS'){
#do whatever is required ...
$ret = $c->perform_CHECKALLDOMAINS(\%lets_data);
if ($ret ne "ok") {
# return to the panel with error message
$c->stash(error => $c->l($ret));
$c->stash(
title => $title,
modul => $modul,
lets_data => \%lets_data
);
$c->render(template => "letsencrypt");
} else {
$c->stash( success => $c->l('lets_CHECKALLDOMAINS_panel_action_was_successful')); #A bit bland - edit it in the lex file
}
}
if ($trt eq 'CHECKALLENABLEDDOMAINS'){
#do whatever is required ...
$ret = $c->perform_CHECKALLENABLEDDOMAINS(\%lets_data);
if ($ret ne "ok") {
# return to the panel with error message
$c->stash(error => $c->l($ret));
$c->stash(
title => $title,
modul => $modul,
lets_data => \%lets_data
);
$c->render(template => "letsencrypt");
} else {
$c->stash( success => $c->l('lets_CHECKALLENABLEDDOMAINS_panel_action_was_successful')); #A bit bland - edit it in the lex file
}
}
if ($trt eq 'CHECKONEDOMAIN'){
#do whatever is required ...
$ret = $c->perform_CHECKONEDOMAIN(\%lets_data);
if ($ret ne "ok") {
# return to the panel with error message
$c->stash(error => $c->l($ret));
$c->stash(
title => $title,
modul => $modul,
lets_data => \%lets_data
);
$c->render(template => "letsencrypt");
} else {
$c->stash( success => $c->l('lets_CHECKONEDOMAIN_panel_action_was_successful')); #A bit bland - edit it in the lex file
}
}
# and call any signal-events needed
#TBD
# Setup shared data and call panel
if ('none' eq 'none') {
$lets_data{'trt'} = 'LIST';
} else {
$lets_data{'trt'} = 'none';
}
$c->do_display($lets_data{'trt'});
}
}
sub do_display {
#
# Return after link clicked in table (this is a get) - route is "/<whatever>d"
# Expects ?trt=PANEL&selected="TableRowName" plus any other required
#
# OR it maybe a post from the main panel to add a new record
#
#load up all supplied params into prefix_data hash
#call get-selected-PANEL() - returns hash of all relevent parameters
#load up returned hash into prefix_data
#render - to called panel
my ($c,$trt) = @_;
$c->app->log->info($c->log_req);
#The most common ones - you might want to comment out any not used.
my $cdb = esmith::ConfigDB->open() || die("Couldn't open config db");
my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db");
my $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db");
my $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db");
my $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db");
my %lets_data = ();
my $title = $c->l('lets_Letsencrypt_certificate');
my $modul = "";
# Accessing all parameters
my %params = $c->req->params->to_hash;
# Get number of parameters
my $num_params = keys %params;
#Tag as Post or Get (ie. create new entry or edit existing one
my $is_new_record = ($c->req->method() eq 'POST');
#Params are available in the hash "params" - copy to the prefix_data hash
#while (my ($key, $value) = each %{$c->req->params->to_hash}) {
# $lets_data{$key} = $value;
#}
# the value of trt will tell you which panel has returned
if (! $trt){
$trt = $c->param('trt') || 'LIST'; #Indicates where to go now
}
# Now add in the params from the selected row from the table
my %selectedrow;
if ($trt eq 'LIST'){
#Validate Get selected row (if applicable) LIST
%selectedrow = $c->get_selected_LIST($lets_data{'Selected'},$is_new_record);
}
if ($trt eq 'PARAMS'){
#Validate Get selected row (if applicable) PARAMS
%selectedrow = $c->get_selected_PARAMS($lets_data{'Selected'},$is_new_record);
}
if ($trt eq 'CHECKALLDOMAINS'){
#Validate Get selected row (if applicable) CHECKALLDOMAINS
%selectedrow = $c->get_selected_CHECKALLDOMAINS($lets_data{'Selected'},$is_new_record);
}
if ($trt eq 'CHECKALLENABLEDDOMAINS'){
#Validate Get selected row (if applicable) CHECKALLENABLEDDOMAINS
%selectedrow = $c->get_selected_CHECKALLENABLEDDOMAINS($lets_data{'Selected'},$is_new_record);
}
if ($trt eq 'CHECKONEDOMAIN'){
#Validate Get selected row (if applicable) CHECKONEDOMAIN
%selectedrow = $c->get_selected_CHECKONEDOMAIN($lets_data{'Selected'},$is_new_record);
}
#Copy in the selected row params to the prefix_data hash to pass to the panel
while (my ($key, $value) = each %selectedrow){
$lets_data{$key} = $value;
}
# Where to go now
$lets_data{'trt'} = $trt;
# Set up other shared data according to the panel to go to
if ($trt eq 'LIST'){
# pickup any other contents needed and load them into hash shared with panel
my %returned_hash;
# subroutine returns a hash directly
%returned_hash = $c->get_data_for_panel_LIST();
# Copy each key-value pair from the returned hash to the prefix data hash
while (my ($key, $value) = each %returned_hash) {
$lets_data{$key} = $value;
}
}
if ($trt eq 'PARAMS'){
# pickup any other contents needed and load them into hash shared with panel
my %returned_hash;
# subroutine returns a hash directly
%returned_hash = $c->get_data_for_panel_PARAMS();
# Copy each key-value pair from the returned hash to the prefix data hash
while (my ($key, $value) = each %returned_hash) {
$lets_data{$key} = $value;
}
}
if ($trt eq 'CHECKALLDOMAINS'){
# pickup any other contents needed and load them into hash shared with panel
my %returned_hash;
# subroutine returns a hash directly
%returned_hash = $c->get_data_for_panel_CHECKALLDOMAINS();
# Copy each key-value pair from the returned hash to the prefix data hash
while (my ($key, $value) = each %returned_hash) {
$lets_data{$key} = $value;
}
}
if ($trt eq 'CHECKALLENABLEDDOMAINS'){
# pickup any other contents needed and load them into hash shared with panel
my %returned_hash;
# subroutine returns a hash directly
%returned_hash = $c->get_data_for_panel_CHECKALLENABLEDDOMAINS();
# Copy each key-value pair from the returned hash to the prefix data hash
while (my ($key, $value) = each %returned_hash) {
$lets_data{$key} = $value;
}
}
if ($trt eq 'CHECKONEDOMAIN'){
# pickup any other contents needed and load them into hash shared with panel
my %returned_hash;
# subroutine returns a hash directly
%returned_hash = $c->get_data_for_panel_CHECKONEDOMAIN();
# Copy each key-value pair from the returned hash to the prefix data hash
while (my ($key, $value) = each %returned_hash) {
$lets_data{$key} = $value;
}
}
# and table control fields
$c->stash(DomainList=>$c->get_DomainList());
# Data for panel
$c->stash(
title => $title,
modul => $modul,
lets_data => \%lets_data
);
$c->render(template => "letsencrypt");
}
1;

View File

@@ -171,9 +171,11 @@ sub add_portforward {
#work out which protocol
my $fdb;
if ($proto eq 'TCP') {
$tcp_db = esmith::ConfigDB->open('portforward_tcp') || die "Can't open portforward_tcp database: $!\n";
$fdb = $tcp_db;
}
else {
$udp_db = esmith::ConfigDB->open('portforward_udp') || die "Can't open portforward_udp database: $!\n";
$fdb = $udp_db;
}
#Get the other values

View File

@@ -26,165 +26,182 @@ use Socket qw( inet_aton );
#our @ISA = qw(esmith::FormMagick Exporter);
our @EXPORT = qw( networkAccess_list passwordLogin_list get_ssh_permit_root_login get_ssh_access get_telnet_mode
get_ftp_access get_ftp_password_login_access
get_value get_prop get_ssh_password_auth
validate_network_and_mask ip_number_or_blank subnet_mask_or_blank
get_ipsecrw_sessions pptp_and_dhcp_range
);
our @EXPORT =
qw( networkAccess_list passwordLogin_list get_ssh_permit_root_login get_ssh_access get_telnet_mode
get_ftp_access get_ftp_password_login_access
get_value get_prop get_ssh_password_auth
validate_network_and_mask ip_number_or_blank subnet_mask_or_blank
get_ipsecrw_sessions pptp_and_dhcp_range
);
# get_pptp_sessions
our $db = esmith::ConfigDB->open || warn "Couldn't open configuration database";
sub main {
my $c = shift;
$c->app->log->info($c->log_req);
$c->app->log->info( $c->log_req );
my $title = $c->l('rma_FORM_TITLE');
my $notif = '';
my $title = $c->l('rma_FORM_TITLE');
my $notif = '';
my %rma_datas = ();
$db = esmith::ConfigDB->open || warn "Couldn't open configuration database";
#$rma_datas{ipsecrwSess} = $c->get_ipsecrw_sessions();
#$rma_datas{pptpSessions} = $c->get_pptp_sessions();
$rma_datas{sshAccess} = $c->get_ssh_access();
$rma_datas{sshPermitRootLogin} = $c->get_ssh_permit_root_login();
$rma_datas{sshAccess} = $c->get_ssh_access();
$rma_datas{sshPermitRootLogin} = $c->get_ssh_permit_root_login();
$rma_datas{sshPasswordAuthentication} = $c->get_ssh_password_auth();
$rma_datas{sshTCPPort} = $c->get_ssh_port();
$rma_datas{ftpAccess} = $c->get_ftp_access();
$rma_datas{ftpPasswordAccess} = $c->get_ftp_password_login_access();
$rma_datas{sshTCPPort} = $c->get_ssh_port();
$rma_datas{ftpAccess} = $c->get_ftp_access();
$rma_datas{ftpPasswordAccess} = $c->get_ftp_password_login_access();
#$rma_datas{telnetAccess} = $c->get_telnet_access;
$c->stash( title => $title, notif => $notif, rma_datas => \%rma_datas );
$c->render(template => 'remoteaccess');
};
$c->render( template => 'remoteaccess' );
}
sub do_action {
my $c = shift;
$c->app->log->info($c->log_req);
$c->app->log->info( $c->log_req );
my $title = $c->l('rma_FORM_TITLE');
my ($result, $res, $trt) = '';
my ( $result, $res, $trt ) = '';
my %rma_datas = ();
$rma_datas{ipsecrwSess} = ($c->param ('IpsecrwSess') || '');
$rma_datas{ipsecrwReset} = ($c->param ('IpsecrwReset') || '');
$db = esmith::ConfigDB->open || warn "Couldn't open configuration database";
$rma_datas{ipsecrwSess} = ( $c->param('IpsecrwSess') || '' );
$rma_datas{ipsecrwReset} = ( $c->param('IpsecrwReset') || '' );
#$rma_datas{pptpSessions} = ($c->param ('PptpSessions') || '0');
$rma_datas{validFromNetwork} = ($c->param ('ValidFromNetwork') || '');
$rma_datas{validFromMask} = ($c->param ('ValidFromMask') || '');
$rma_datas{validFromNetwork} = ( $c->param('ValidFromNetwork') || '' );
$rma_datas{validFromMask} = ( $c->param('ValidFromMask') || '' );
## my @remove = $q->param('validFromRemove'); ???????? the first one only !!
my @vals = $c->param ('Remove_nets');
my @vals = $c->param('Remove_nets');
$rma_datas{remove_nets} = join ',', @vals;
$rma_datas{sshaccess} = ($c->param ('SshAccess') || 'off');
$rma_datas{sshPermitRootLogin} = ($c->param ('SshPermitRootLogin') || 'no');
$rma_datas{sshPasswordAuthentication} = ($c->param ('SshPasswordAuthentication') || 'no');
$rma_datas{sshTCPPort} = ($c->param ('SshTCPPort') || '22');
$rma_datas{sshaccess} = ( $c->param('SshAccess') || 'off' );
$rma_datas{sshPermitRootLogin} =
( $c->param('SshPermitRootLogin') || 'no' );
$rma_datas{sshPasswordAuthentication} =
( $c->param('SshPasswordAuthentication') || 'no' );
$rma_datas{sshTCPPort} = ( $c->param('SshTCPPort') || '22' );
$rma_datas{ftpAccess} = ($c->param ('FtpAccess') || 'off');
$rma_datas{ftpPasswordAccess} = ($c->param ('FtpPasswordAccess') || 'private');
$rma_datas{ftpAccess} = ( $c->param('FtpAccess') || 'off' );
$rma_datas{ftpPasswordAccess} =
( $c->param('FtpPasswordAccess') || 'private' );
$rma_datas{telnetAccess} = ($c->param ('TelnetAccess') || 'off');
$rma_datas{telnetAccess} = ( $c->param('TelnetAccess') || 'off' );
# validate
my $v = $c->validation;
return $c->render('remoteaccess') unless $v->has_data;
#$v->optional('PptpSessions')->num(0, 999)->is_valid;
$v->optional('ValidFromNetwork')->size(7, 15)->is_valid;
$v->optional('ValidFromMask')->size(7, 15)->is_valid;
$v->required('SshTCPPort')->num(1, 65535)->is_valid;
if ( $c->param('ValidFromNetwork') ne "" ) {
$v->optional('ValidFromNetwork')->size( 7, 15 )->is_valid;
}
if ( $c->param('ValidFromMask') ne "" ) {
$v->optional('ValidFromMask')->size( 7, 15 )->is_valid;
}
$v->required('SshTCPPort')->num( 1, 65535 )->is_valid;
$result .= 'field validation error' if $v->has_error;
if ( ! $result ) {
if ( !$result ) {
# controls
#$res = pptp_and_dhcp_range( $c, $rma_datas{pptpSessions} );
#$result .= $res . ' ' unless $res eq 'OK';
# controls
#$res = pptp_and_dhcp_range( $c, $rma_datas{pptpSessions} );
#$result .= $res . ' ' unless $res eq 'OK';
$res = ip_number_or_blank( $c, $rma_datas{validFromNetwork} );
$result .= $res . ' ' unless $res eq 'OK';
$res = ip_number_or_blank( $c, $rma_datas{validFromNetwork} );
$result .= $res . ' ' unless $res eq 'OK';
$res = subnet_mask_or_blank( $c, $rma_datas{validFromMask} );
$result .= $res . ' ' unless $res eq 'OK';
$res = subnet_mask_or_blank( $c, $rma_datas{validFromMask} );
$result .= $res . ' ' unless $res eq 'OK';
$res = validate_network_and_mask( $c, $rma_datas{validFromNetwork}, $rma_datas{validFromMask} );
$result .= $res . ' ' unless $res eq 'OK';
$res = validate_network_and_mask(
$c,
$rma_datas{validFromNetwork},
$rma_datas{validFromMask}
);
$result .= $res . ' ' unless $res eq 'OK';
#$result .= ' blocked for testing !' . $rma_datas{remove_nets};
#$result .= ' blocked for testing !' . $rma_datas{remove_nets};
}
if ( ! $result ) {
if ( !$result ) {
$res = change_settings( $c, %rma_datas );
$result .= $res unless $res eq 'OK';
}
if ( ! $result ) {
$result = $c->l('rma_ACTION_SUCCEEDED');
$trt = 'SUC';
if ( $result eq "" ) {
$result = $c->l('rma_SUCCESS');
$trt = 'SUC';
}
$c->stash( title => $title, notif => $result, rma_datas => \%rma_datas );
if ( $trt ne 'SUC' ) {
return $c->render(template => 'remoteaccess');
#return $c->render( template => 'remoteaccess' );
if ( $trt eq 'SUC' ) {
$c->stash( title => $title,modul => $result);
return $c->render( template => 'module' );
}
$c->redirect_to('/remoteaccess');
};
return $c->render( template => 'remoteaccess' );
#$c->redirect_to('/remoteaccess');
}
sub networkAccess_list {
my $c = shift;
return [[ $c->l('rma_NO_ACCESS') => 'off'],
[ $c->l('NETWORKS_ALLOW_LOCAL') => 'private'],
[ $c->l('NETWORKS_ALLOW_PUBLIC') => 'public']];
return [
[ $c->l('rma_NO_ACCESS') => 'off' ],
[ $c->l('NETWORKS_ALLOW_LOCAL') => 'private' ],
[ $c->l('NETWORKS_ALLOW_PUBLIC') => 'public' ]
];
}
sub passwordLogin_list {
my $c = shift;
return [[$c->l('rma_PASSWORD_LOGIN_PRIVATE') => 'private'],
[$c->l('rma_PASSWORD_LOGIN_PUBLIC') => 'public']];
return [
[ $c->l('rma_PASSWORD_LOGIN_PRIVATE') => 'private' ],
[ $c->l('rma_PASSWORD_LOGIN_PUBLIC') => 'public' ]
];
}
sub get_prop {
my ($c, $item, $prop) = @_;
warn "You must specify a record key" unless $item;
warn "You must specify a property name" unless $prop;
my $record = $db->get($item) or warn "Couldn't get record for $item";
return $record ? $record->prop($prop) : undef;
my ( $c, $item, $prop ) = @_;
warn "You must specify a record key" unless $item;
warn "You must specify a property name" unless $prop;
my $record = $db->get($item) or warn "Couldn't get record for $item";
return $record ? $record->prop($prop) : undef;
}
sub get_value {
my $c = shift;
my $item = shift;
return ($db->get($item)->value());
my $c = shift;
my $item = shift;
return ( $db->get($item)->value() );
}
sub get_ftp_access {
my $status = get_prop('','ftp','status') || 'disabled';
my $status = get_prop( '', 'ftp', 'status' ) || 'disabled';
return 'off' unless $status eq 'enabled';
my $access = get_prop('','ftp','access') || 'private';
return ($access eq 'public') ? 'normal' : 'private';
my $access = get_prop( '', 'ftp', 'access' ) || 'private';
return ( $access eq 'public' ) ? 'normal' : 'private';
}
#sub get_pptp_sessions {
# my $status = get_prop('','pptpd','status');
# if (defined($status) && ($status eq 'enabled')) {
@@ -192,314 +209,317 @@ sub get_ftp_access {
# return '0';
#}
sub get_ssh_permit_root_login {
return(get_prop('','sshd','PermitRootLogin') || 'no');
return ( get_prop( '', 'sshd', 'PermitRootLogin' ) || 'no' );
}
sub get_ssh_password_auth {
return(get_prop('','sshd','PasswordAuthentication') || 'yes');
return ( get_prop( '', 'sshd', 'PasswordAuthentication' ) || 'yes' );
}
sub get_ssh_access {
my $status = get_prop('','sshd','status');
if (defined($status) && ($status eq 'enabled')) {
my $access = get_prop('','sshd','access');
$access = ($access eq 'public') ? 'public' : 'private';
return($access);
}
else {
return('off');
}
my $status = get_prop( '', 'sshd', 'status' );
if ( defined($status) && ( $status eq 'enabled' ) ) {
my $access = get_prop( '', 'sshd', 'access' );
$access = ( $access eq 'public' ) ? 'public' : 'private';
return ($access);
}
else {
return ('off');
}
}
sub get_ssh_port {
return(get_prop('$c','sshd','TCPPort') || '22');
return ( get_prop( '$c', 'sshd', 'TCPPort' ) || '22' );
}
sub get_ftp_password_login_access {
my $status = get_prop('','ftp','status') || 'disabled';
my $status = get_prop( '', 'ftp', 'status' ) || 'disabled';
return 'private' unless $status eq 'enabled';
my $access = get_prop('','ftp','LoginAccess') || 'private';
my $access = get_prop( '', 'ftp', 'LoginAccess' ) || 'private';
return ($access eq 'public') ? 'public' : 'private';
return ( $access eq 'public' ) ? 'public' : 'private';
}
sub get_telnet_mode {
my $telnet = $db->get('telnet');
return('off') unless $telnet;
my $status = $telnet->prop('status') || 'disabled';
return('off') unless $status eq 'enabled';
my $access = $telnet->prop('access') || 'private';
return ($access eq "public") ? "public" : "private";
my $telnet = $db->get('telnet');
return ('off') unless $telnet;
my $status = $telnet->prop('status') || 'disabled';
return ('off') unless $status eq 'enabled';
my $access = $telnet->prop('access') || 'private';
return ( $access eq "public" ) ? "public" : "private";
}
sub get_ipsecrw_sessions {
sub get_ipsecrw_sessions {
my $status = $db->get('ipsec')->prop('RoadWarriorStatus');
if (defined($status) && ($status eq 'enabled')) {
return($db->get('ipsec')->prop('RoadWarriorSessions') || '0');
}
else {
return('0');
}
my $status = $db->get('ipsec')->prop('RoadWarriorStatus');
if ( defined($status) && ( $status eq 'enabled' ) ) {
return ( $db->get('ipsec')->prop('RoadWarriorSessions') || '0' );
}
else {
return ('0');
}
}
sub get_ipsecrw_status {
return undef unless ( $db->get('ipsec'));
return $db->get('ipsec')->prop('RoadWarriorStatus');
return undef unless ( $db->get('ipsec') );
return $db->get('ipsec')->prop('RoadWarriorStatus');
}
sub pptp_and_dhcp_range {
my $c = shift;
my $val = shift || 0;
my $dhcp_status = $db->get_prop('dhcpd','status') || 'disabled';
my $dhcp_end = $db->get_prop('dhcpd','end') || '';
my $dhcp_start = $db->get_prop('dhcpd','start') || '';
my $c = shift;
my $val = shift || 0;
my $dhcp_status = $db->get_prop( 'dhcpd', 'status' ) || 'disabled';
my $dhcp_end = $db->get_prop( 'dhcpd', 'end' ) || '';
my $dhcp_start = $db->get_prop( 'dhcpd', 'start' ) || '';
if ( $dhcp_status eq 'enabled' ) {
my $ip_start = unpack 'N', inet_aton($dhcp_start);
my $ip_end = unpack 'N', inet_aton($dhcp_end);
my $ip_count = $ip_end - $ip_start;
return 'OK' if( $val < $ip_count );
return $c->l('rma_NUMBER_OF_PPTP_CLIENTS_MUST_BE_LESSER_THAN_NUMBER_OF_IP_IN_DHCP_RANGE');
} else {
my $ip_start = unpack 'N', inet_aton($dhcp_start);
my $ip_end = unpack 'N', inet_aton($dhcp_end);
my $ip_count = $ip_end - $ip_start;
return 'OK' if ( $val < $ip_count );
return $c->l(
'rma_NUMBER_OF_PPTP_CLIENTS_MUST_BE_LESSER_THAN_NUMBER_OF_IP_IN_DHCP_RANGE'
);
}
else {
return 'OK';
}
}
sub _get_valid_from {
my $c = shift;
my $c = shift;
my $rec = $db->get('httpd-admin');
return undef unless($rec);
my @vals = (split ',', ($rec->prop('ValidFrom') || ''));
return @vals;
my $rec = $db->get('httpd-admin');
return undef unless ($rec);
my @vals = ( split ',', ( $rec->prop('ValidFrom') || '' ) );
return @vals;
}
sub ip_number_or_blank {
my $c = shift;
my $c = shift;
my $ip = shift;
if (!defined($ip) || $ip eq "") {
return 'OK';
if ( !defined($ip) || $ip eq "" ) {
return 'OK';
}
return ip_number($c, $ip);
return ip_number( $c, $ip );
}
sub subnet_mask_or_blank {
my $c = shift;
my $c = shift;
my $mask = shift;
if (!defined($mask) || $mask eq "") {
if ( !defined($mask) || $mask eq "" ) {
return "OK";
}
chomp $mask ;
chomp $mask;
return ( subnet_mask( $mask ) ne 'OK' ) ? $c->l('rma_INVALID_SUBNET_MASK') . " (" . $mask . ")" : 'OK';
return ( subnet_mask($mask) ne 'OK' )
? $c->l('rma_INVALID_SUBNET_MASK') . " (" . $mask . ")"
: 'OK';
}
sub validate_network_and_mask {
my $c = shift;
my $net = shift || "";
my $mask = shift || "";
my $c = shift;
my $net = shift || "";
my $mask = shift || "";
if ($net xor $mask) {
return $c->l('rma_ERR_INVALID_PARAMS' . " (" . $net."/".$mask . ")");
}
return 'OK';
if ( $net xor $mask ) {
return $c->l(
'rma_ERR_INVALID_PARAMS' . " (" . $net . "/" . $mask . ")" );
}
return 'OK';
}
sub change_settings {
my ($c, %rma_datas) = @_;
my ( $c, %rma_datas ) = @_;
#------------------------------------------------------------
# good; go ahead and change the access.
#------------------------------------------------------------
my $rec = $db->get('telnet');
if($rec) {
if ($rma_datas{telnetAccess} eq "off") {
$rec->set_prop('status','disabled');
} else {
$rec->set_prop('status','enabled');
$rec->set_prop('access', $rma_datas{telnetAccess});
}
if ($rec) {
if ( $rma_datas{telnetAccess} eq "off" ) {
$rec->set_prop( 'status', 'disabled' );
}
else {
$rec->set_prop( 'status', 'enabled' );
$rec->set_prop( 'access', $rma_datas{telnetAccess} );
}
}
$rec = $db->get('sshd') || $db->new_record('sshd', {type => 'service'});
$rec->set_prop('TCPPort', $rma_datas{sshTCPPort});
$rec->set_prop('status', ( $rma_datas{sshaccess} eq "off" ? 'disabled' : 'enabled'));
$rec->set_prop('access', $rma_datas{sshaccess});
$rec->set_prop('PermitRootLogin', $rma_datas{sshPermitRootLogin});
$rec->set_prop('PasswordAuthentication', $rma_datas{sshPasswordAuthentication});
$rec = $db->get('sshd') || $db->new_record( 'sshd', { type => 'service' } );
$rec->set_prop( 'TCPPort', $rma_datas{sshTCPPort} );
$rec->set_prop( 'status',
( $rma_datas{sshaccess} eq "off" ? 'disabled' : 'enabled' ) );
$rec->set_prop( 'access', $rma_datas{sshaccess} );
$rec->set_prop( 'PermitRootLogin', $rma_datas{sshPermitRootLogin} );
$rec->set_prop( 'PasswordAuthentication',
$rma_datas{sshPasswordAuthentication} );
$rec = $db->get('ftp');
if($rec) {
if ($rma_datas{ftpAccess} eq "off") {
$rec->set_prop('status', 'disabled');
$rec->set_prop('access', 'private');
$rec->set_prop('LoginAccess', 'private');
} elsif ($rma_datas{ftpAccess} eq "normal") {
$rec->set_prop('status', 'enabled');
$rec->set_prop('access', 'public');
$rec->set_prop('LoginAccess', $rma_datas{ftpPasswordAccess});
} else {
$rec->set_prop('status', 'enabled');
$rec->set_prop('access', 'private');
$rec->set_prop('LoginAccess', $rma_datas{ftpPasswordAccess});
}
if ($rec) {
if ( $rma_datas{ftpAccess} eq "off" ) {
$rec->set_prop( 'status', 'disabled' );
$rec->set_prop( 'access', 'private' );
$rec->set_prop( 'LoginAccess', 'private' );
}
elsif ( $rma_datas{ftpAccess} eq "normal" ) {
$rec->set_prop( 'status', 'enabled' );
$rec->set_prop( 'access', 'public' );
$rec->set_prop( 'LoginAccess', $rma_datas{ftpPasswordAccess} );
}
else {
$rec->set_prop( 'status', 'enabled' );
$rec->set_prop( 'access', 'private' );
$rec->set_prop( 'LoginAccess', $rma_datas{ftpPasswordAccess} );
}
}
# if ($rma_datas{pptpSessions} == 0) {
# $db->get('pptpd')->set_prop('status', 'disabled');
# } else {
# $db->get('pptpd')->set_prop('status', 'enabled');
# $db->get('pptpd')->set_prop('sessions', $rma_datas{pptpSessions});
# }
# if ($rma_datas{pptpSessions} == 0) {
# $db->get('pptpd')->set_prop('status', 'disabled');
# } else {
# $db->get('pptpd')->set_prop('status', 'enabled');
# $db->get('pptpd')->set_prop('sessions', $rma_datas{pptpSessions});
# }
if ( $rma_datas{validFromNetwork} && $rma_datas{validFromMask} ) {
unless (add_new_valid_from( $c, $rma_datas{validFromNetwork}, $rma_datas{validFromMask} )) {
return $c->l('rma_ERROR_UPDATING_CONFIGURATION') . 'new net';
}
unless (
add_new_valid_from(
$c,
$rma_datas{validFromNetwork},
$rma_datas{validFromMask}
)
)
{
return $c->l('rma_ERROR_UPDATING_CONFIGURATION') . 'new net';
}
}
if ( $rma_datas{remove_nets} ) {
unless (remove_valid_from( $c, $rma_datas{remove_nets} )) {
return $c->l('rma_ERROR_UPDATING_CONFIGURATION') . 'del net';
}
unless ( remove_valid_from( $c, $rma_datas{remove_nets} ) ) {
return $c->l('rma_ERROR_UPDATING_CONFIGURATION') . 'del net';
}
}
# reset ipsec roadwarrior CA,server,client certificates
if ($rma_datas{ipsecrwReset}) {
system('/sbin/e-smith/roadwarrior', 'reset_certs') == 0 or
return $c->l('rma_ERROR_UPDATING_CONFIGURATION') . 'rst ipsec';
if ( $rma_datas{ipsecrwReset} ) {
system( '/sbin/e-smith/roadwarrior', 'reset_certs' ) == 0
or return $c->l('rma_ERROR_UPDATING_CONFIGURATION') . 'rst ipsec';
}
if ( $rma_datas{ipsecrwSess} ) {
set_ipsecrw_sessions( $c, $rma_datas{ipsecrwSess} );
set_ipsecrw_sessions( $c, $rma_datas{ipsecrwSess} );
}
unless ( system( "/sbin/e-smith/signal-event", "remoteaccess-update" ) == 0 ) {
unless (
system( "/sbin/e-smith/signal-event", "remoteaccess-update" ) == 0 )
{
return $c->l('rma_ERROR_UPDATING_CONFIGURATION');
}
return 'OK';
}
sub set_ipsecrw_sessions {
my $c = shift;
my $c = shift;
my $sessions = shift;
if (defined $sessions) {
$db->get('ipsec')->set_prop('RoadWarriorSessions', $sessions);
if (int($sessions) > 0) {
$db->get('ipsec')->set_prop('RoadWarriorStatus', 'enabled');
}
if ( defined $sessions ) {
$db->get('ipsec')->set_prop( 'RoadWarriorSessions', $sessions );
if ( int($sessions) > 0 ) {
$db->get('ipsec')->set_prop( 'RoadWarriorStatus', 'enabled' );
}
}
return '';
}
sub add_new_valid_from {
my $c = shift;
my $net = shift;
my $mask = shift;
my $c = shift;
my $net = shift;
my $mask = shift;
# we transform bit mask to regular mask
$mask = get_reg_mask( $net, $mask );
my $rec = $db->get('httpd-admin');
return $c->error('ERR_NO_RECORD') unless $rec;
# we transform bit mask to regular mask
$mask = get_reg_mask( $net, $mask );
my $prop = $rec->prop('ValidFrom') || '';
my $rec = $db->get('httpd-admin');
return $c->error('ERR_NO_RECORD') unless $rec;
my @vals = split /,/, $prop;
return '' if (grep /^$net\/$mask$/, @vals); # already have this entry
my $prop = $rec->prop('ValidFrom') || '';
if ($prop ne '') {
$prop .= ",$net/$mask";
} else {
$prop = "$net/$mask";
}
my @vals = split /,/, $prop;
return '' if ( grep /^$net\/$mask$/, @vals ); # already have this entry
$rec->set_prop('ValidFrom', $prop);
if ( $prop ne '' ) {
$prop .= ",$net/$mask";
}
else {
$prop = "$net/$mask";
}
return 1;
$rec->set_prop( 'ValidFrom', $prop );
return 1;
}
sub remove_valid_from {
my $c = shift;
my $remove_nets = shift;
my $c = shift;
my $remove_nets = shift;
my @remove = split /,/, $remove_nets;
my @remove = split /,/, $remove_nets;
# my @remove = $c->param('Remove_nets');
my @vals = $c->_get_valid_from();
# my @remove = $c->param('Remove_nets');
my @vals = $c->_get_valid_from();
foreach my $entry (@remove) {
return undef unless $entry;
foreach my $entry (@remove) {
my ($net, $mask) = split (/\//, $entry);
return undef unless $entry;
unless (@vals) {
print STDERR "ERROR: unable to load ValidFrom property from conf db\n";
return undef;
}
my ( $net, $mask ) = split( /\//, $entry );
# what if we don't have a mask because someone added an entry from
# the command line? by the time we get here, the panel will have
# added a 32 bit mask, so we don't know for sure if the value in db
# is $net alone or $net/255.255.255.255. we have to check for both
# in this special case...
@vals = (grep { $entry ne $_ && $net ne $_ } @vals);
}
unless (@vals) {
print STDERR
"ERROR: unable to load ValidFrom property from conf db\n";
return undef;
}
my $prop;
if (@vals) {
$prop = join ',',@vals;
} else {
$prop = '';
}
# what if we don't have a mask because someone added an entry from
# the command line? by the time we get here, the panel will have
# added a 32 bit mask, so we don't know for sure if the value in db
# is $net alone or $net/255.255.255.255. we have to check for both
# in this special case...
@vals = ( grep { $entry ne $_ && $net ne $_ } @vals );
}
$db->get('httpd-admin')->set_prop('ValidFrom', $prop);
my $prop;
if (@vals) {
$prop = join ',', @vals;
}
else {
$prop = '';
}
return 1;
$db->get('httpd-admin')->set_prop( 'ValidFrom', $prop );
return 1;
}
1;
1;

View File

@@ -0,0 +1,46 @@
package SrvMngr::Controller::Roundcubepanel;
#----------------------------------------------------------------------
# heading : System
# description : Roundcube webmail
# navigation : 99999 9999
#----------------------------------------------------------------------
#----------------------------------------------------------------------
# name : roundcubepanel, method : get, url : /roundcubepanel, ctlact : Roundcubepanel#main
#
# routes : end
#----------------------------------------------------------------------
use strict;
use warnings;
use Mojo::Base 'Mojolicious::Controller';
use Locale::gettext;
use SrvMngr::I18N;
use SrvMngr qw(theme_list init_session);
#use SrvMngr::Model::Main;
sub main {
my $c = shift;
$c->app->log->info($c->log_req);
my $title = $c->l('Roundcube Webmail');
my $roundcube_url = $c->param('url');
my $roundcube_height = $c->param('height') | 600;
$c->stash( title => $title, modul => $roundcube_url, height => $roundcube_height );
$c->render(template => 'roundcube');
}
sub getroundcubeurl {
my $c = shift;
my $url = shift;
return "/smanager/roundcube?url=$url";
}
1;

View File

@@ -23,14 +23,16 @@ use File::Basename;
our $cdb = esmith::ConfigDB->open || die "Couldn't open config db";
my $dnf_status_file = '/var/cache/dnf/dnf.status';
#use File::stat;
our %dbs;
for ( qw(available installed updates) )
{
$dbs{$_} = esmith::ConfigDB->open_ro("yum_$_") or
die "Couldn't open yum_$_ DB\n";
$dbs{$_} = esmith::ConfigDB->open_ro("dnf_$_") or
die "Couldn't open dnf_$_ DB\n";
}
for ( qw(repositories) )
@@ -52,10 +54,11 @@ sub main {
$yum_datas{'trt'} = 'STAT';
if ( -e "/var/run/yum.pid" ) {
if ( $c->is_dnf_running()) {
$yum_datas{'trt'} = 'LOGF';
$dest = 'yumlogfile';
} elsif ($cdb->get_prop('yum', 'LogFile')) {
} elsif ($cdb->get_prop('dnf', 'LogFile')) {
$yum_datas{'trt'} = 'PSTU';
$yum_datas{'reconf'} = $cdb->get_value('UnsavedChanges', 'yes');
$dest = 'yumpostupg';
@@ -83,9 +86,9 @@ sub do_display {
$yum_datas{'trt'} = $trt;
# force $trt if current logfile
if ( -e "/var/run/yum.pid" ) {
if ( $c->is_dnf_running() ) {
$trt = 'LOGF';
} elsif ($cdb->get_prop('yum', 'LogFile')) {
} elsif ($cdb->get_prop('dnf', 'LogFile')) {
$trt = 'PSTU';
}
@@ -106,13 +109,13 @@ sub do_display {
}
if ( $trt eq 'LOGF' ) {
if (-e "/var/run/yum.pid") {
if ($c->is_dnf_running()) {
$dest = 'yumlogfile';
}
}
if ( $trt eq 'PSTU') {
if ($cdb->get_prop('yum', 'LogFile')) {
if ($cdb->get_prop('dnf', 'LogFile')) {
$dest = 'yumpostupg';
$yum_datas{'reconf'} = $cdb->get_value('UnsavedChanges', 'yes');
}
@@ -221,7 +224,7 @@ sub do_update {
if ( $trt eq 'LOGF' ) {
$dest = 'yumlogfile';
if ( ! -e "/var/run/yum.pid") {
if ( ! $c->is_dnf_running()) {
$yum_datas{trt} = 'SUC';
$result = $c->l('yum_SUCCESS');
}
@@ -247,6 +250,24 @@ sub do_update {
};
sub get_dnf_status {
#interrogate status file created and maintained by smeserver.py plugin for dnf.
my ($c) = @_;
my $file_name = $dnf_status_file;
my $content = "resolved";
if ( -e "$file_name") {
open my $fh, '<', $file_name or die "Can't open file: $!";
$content = <$fh>;
close $fh;
}
return $content;
}
sub is_dnf_running {
my ($c) = @_;
my $dnf_status = $c->get_dnf_status();
return $dnf_status ne "resolved" && $dnf_status ne "config" && $dnf_status ne "sack";
}
sub is_empty {
@@ -289,7 +310,7 @@ sub package_functions_enabled {
my ($c) = @_;
return ($cdb->get_prop("yum", "PackageFunctions") eq "enabled");
return ($cdb->get_prop("dnf", "PackageFunctions") eq "enabled");
}
@@ -298,7 +319,7 @@ sub get_status {
my ($c, $prop, $localise) = @_;
my $status = $cdb->get_prop("yum", $prop) || 'disabled';
my $status = $cdb->get_prop("dnf", $prop) || 'disabled';
return $status unless $localise;
@@ -433,7 +454,7 @@ sub change_settings {
PackageFunctions
) )
{
$cdb->set_prop('yum', $param, $c->param("yum_$param"));
$cdb->set_prop("dnf", $param, $c->param("yum_$param"));
}
my $check4updates = $c->param("yum_check4updates");
@@ -441,21 +462,21 @@ sub change_settings {
if ($check4updates ne 'disabled') { $status = 'enabled'; }
$cdb->set_prop('yum', 'check4updates', $check4updates);
$cdb->set_prop("dnf", 'check4updates', $check4updates);
my $deltarpm = $c->param("yum_DeltaRpmProcess");
$cdb->set_prop('yum', 'DeltaRpmProcess', $deltarpm);
$cdb->set_prop("dnf", 'DeltaRpmProcess', $deltarpm);
my $downloadonly = $c->param("yum_DownloadOnly");
if ($downloadonly ne 'disabled') { $status = 'enabled'; }
$cdb->set_prop('yum', 'DownloadOnly', $downloadonly);
$cdb->set_prop("dnf", 'DownloadOnly', $downloadonly);
my $AutoInstallUpdates = $c->param("yum_AutoInstallUpdates");
if ($AutoInstallUpdates ne 'disabled') { $status = 'enabled'; }
$cdb->set_prop('yum', 'AutoInstallUpdates', $AutoInstallUpdates);
$cdb->set_prop('yum', 'status', $status);
$cdb->set_prop("dnf", 'AutoInstallUpdates', $AutoInstallUpdates);
$cdb->set_prop("dnf", 'status', $status);
my %selected = map {$_ => 1} @{$c->every_param('SelectedRepositories')};
@@ -469,7 +490,7 @@ sub change_settings {
$dbs{repositories}->reload;
unless ( system( "/sbin/e-smith/signal-event", "yum-modify" ) == 0 )
unless ( system( "/sbin/e-smith/signal-event", "dnf-modify" ) == 0 )
{
return $c->l('yum_ERROR_UPDATING_CONFIGURATION');
}
@@ -484,11 +505,11 @@ sub do_yum {
for ( qw(SelectedGroups SelectedPackages) )
{
$cdb->set_prop("yum", $_, join(',', (@{$c->every_param($_)} )));
$cdb->set_prop("dnf", $_, join(',', (@{$c->every_param($_)} )));
}
esmith::util::backgroundCommand(0,
"/sbin/e-smith/signal-event", "yum-$function");
"/sbin/e-smith/signal-event", "dnf-$function");
for ( qw(available installed updates) ) {
$dbs{$_}->reload;
@@ -517,7 +538,7 @@ sub format_yum_log {
$cdb->reload;
my $filepage = $cdb->get_prop('yum', 'LogFile');
my $filepage = $cdb->get_prop('dnf', 'LogFile');
return '' unless $filepage and ( -e "$filepage" );
my $out = sprintf "<PRE>";
@@ -537,7 +558,7 @@ sub post_upgrade_reboot {
my $c = shift;
$cdb->get_prop_and_delete('yum', 'LogFile');
$cdb->get_prop_and_delete('dnf', 'LogFile');
$cdb->reload;
if (fork == 0) {
@@ -552,7 +573,7 @@ sub post_upgrade_reboot {
sub show_yum_log {
my $c = shift;
my $out = $c->format_yum_log();
my $yum_log = $cdb->get_prop_and_delete('yum', 'LogFile');
my $yum_log = $cdb->get_prop_and_delete('dnf', 'LogFile');
return $out;
}

View File

@@ -1,3 +1,4 @@
'bac_No suitable local devices found' => 'No suitable local devices found',
'bac_BACKUP_TITLE' => 'Backup or restore server data',
'bac_BACKUP_DESC' => '<P>The server provides two ways to back up and restore
your server: using your local desktop or a tape drive.</P>

View File

@@ -0,0 +1,72 @@
package SrvMngr::I18N::Modules::Letsencrypt::en;
use strict;
use warnings;
use utf8;
use Mojo::Base 'SrvMngr::I18N';
use SrvMngr::I18N::Modules::General::en;
my %lexicon = (
#
# Generated by SM2Gen version: SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43
#
'lets_Manage_letsencrypt-config_settings:' => 'Manage letsencrypt-config settings',
'lets_HOOKSCRIPT_STATUS' => 'Hookscript Status',
'lets_SERVICE_STATUS' => 'Service Status',
'lets_EMAIL' => 'Email',
'lets_Back' => 'Back',
'lets_Internal_IP' => 'Internal IP',
'lets_Save' => 'Save',
'lets_Issuer' => 'Issuer',
'lets_IS_IN_CERT' => 'Is In cart',
'lets_For_this_Server' => 'For this Server',
'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain',
'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain which is enabled',
'lets_Check_just_one_domain' => 'Check just one domain',
'lets_PARAMS_panel_action_was_successful' => 'PARAMS panel action was successful',
'lets_Check_all_domains' => 'Check all domains',
'lets_LIST_panel_action_was_successful' => 'LIST panel action was successful',
'lets_Status_Report' => 'Status Report',
'lets_LABEL_NAMESERVERS' => 'Label timeservers',
'lets_Loop_through_and_check_the' => 'Loop through and check the letsencrypt status for a specific domain',
'lets_Letsencrypt_certificate' => 'Letsencrypt certificate',
'lets_Error_Status_Report' => 'Error Status Report',
'lets_Not_Before' => 'Not Before',
'lets_Content' => 'Content',
'lets_CONFIG_LETSENCRYPT' => 'confirm Letsencrypt',
'lets_API_STATUS' => 'ape Status',
'lets_ACCEPT_TERMS_STATUS' => 'Accept Terms Status',
'lets_Check_all_enabled_domains' => 'Check all enabled domains',
'lets_All_domains_check_result' => 'All domains check result',
'lets_CHECKALLDOMAINS_panel_action_was_successful' => 'CHECKALLDOMAINS panel action was successful',
'lets_Domains_name' => 'Domains name',
'lets_HOSTOVERRIDE_STATUS' => 'Hostoverride Status',
'lets_List_of_Domains_and_Hosts' => 'List of Domains and Hosts',
'lets_Brief_description' => 'Brief description',
'lets_KEYSIZE_STATUS' => 'Keysize Status',
'lets_Domain_name_/_HOSTNAME' => 'Domain name / HOSTNAME',
'lets_Enabled_domains_check_result' => 'Enabled domains check result',
'lets_CHECKALLENABLEDDOMAINS_panel_action_was_successful' => 'CHECKALLENABLEDDOMAINS panel action was successful',
'lets_Internet_IP' => 'Internet IP',
'lets_Expiry' => 'Expiry',
'lets_CHECK_ALL_DOMAINS' => 'Check All Domains',
'lets_LABEL_POINT' => 'Label Point',
'lets_CHECK' => 'Check',
'lets_CONFIG' => 'Config',
'lets_Current_certificate_details' => 'Current certificate details',
'lets_LABEL_LECERT' => 'Label secret',
'lets_One_domain_check_result' => 'One domain check result',
'lets_CHECKONEDOMAIN_panel_action_was_successful' => 'CHECKONEDOMAIN panel action was successful',
'lets_CONFIGUREMODE_STATUS' => 'Configuremode Status',
'lets_CHECK_ALL_ENABLED_DOMAINS' => 'Check All Enabled Domains',
'lets_External_Interface_IP' => 'External Interface IP',
'lets_APPLY' => 'Apply',
);
our %Lexicon = (
%{ SrvMngr::I18N::Modules::General::en::Lexicon },
%lexicon
);
1;

View File

@@ -0,0 +1,54 @@
#
# Generated by SM2Gen version: SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43
#
'lets_Manage_letsencrypt-config_settings:' => 'Manage letsencrypt-config settings',
'lets_HOOKSCRIPT_STATUS' => 'Hookscript Status',
'lets_SERVICE_STATUS' => 'Service Status',
'lets_EMAIL' => 'Email',
'lets_Back' => 'Back',
'lets_Internal_IP' => 'Internal IP',
'lets_Save' => 'Save',
'lets_Issuer' => 'Issuer',
'lets_IS_IN_CERT' => 'Is In cart',
'lets_For_this_Server' => 'For this Server',
'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain',
'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain which is enabled',
'lets_Check_just_one_domain' => 'Check just one domain',
'lets_PARAMS_panel_action_was_successful' => 'PARAMS panel action was successful',
'lets_Check_all_domains' => 'Check all domains',
'lets_LIST_panel_action_was_successful' => 'LIST panel action was successful',
'lets_Status_Report' => 'Status Report',
'lets_LABEL_NAMESERVERS' => 'Label timeservers',
'lets_Loop_through_and_check_the' => 'Loop through and check the letsencrypt status for a specific domain',
'lets_Letsencrypt_certificate' => 'Letsencrypt certificate',
'lets_Error_Status_Report' => 'Error Status Report',
'lets_Not_Before' => 'Not Before',
'lets_Content' => 'Content',
'lets_CONFIG_LETSENCRYPT' => 'confirm Letsencrypt',
'lets_API_STATUS' => 'ape Status',
'lets_ACCEPT_TERMS_STATUS' => 'Accept Terms Status',
'lets_Check_all_enabled_domains' => 'Check all enabled domains',
'lets_All_domains_check_result' => 'All domains check result',
'lets_CHECKALLDOMAINS_panel_action_was_successful' => 'CHECKALLDOMAINS panel action was successful',
'lets_Domains_name' => 'Domains name',
'lets_HOSTOVERRIDE_STATUS' => 'Hostoverride Status',
'lets_List_of_Domains_and_Hosts' => 'List of Domains and Hosts',
'lets_Brief_description' => 'Brief description',
'lets_KEYSIZE_STATUS' => 'Keysize Status',
'lets_Domain_name_/_HOSTNAME' => 'Domain name / HOSTNAME',
'lets_Enabled_domains_check_result' => 'Enabled domains check result',
'lets_CHECKALLENABLEDDOMAINS_panel_action_was_successful' => 'CHECKALLENABLEDDOMAINS panel action was successful',
'lets_Internet_IP' => 'Internet IP',
'lets_Expiry' => 'Expiry',
'lets_CHECK_ALL_DOMAINS' => 'Check All Domains',
'lets_LABEL_POINT' => 'Label Point',
'lets_CHECK' => 'Check',
'lets_CONFIG' => 'Config',
'lets_Current_certificate_details' => 'Current certificate details',
'lets_LABEL_LECERT' => 'Label secret',
'lets_One_domain_check_result' => 'One domain check result',
'lets_CHECKONEDOMAIN_panel_action_was_successful' => 'CHECKONEDOMAIN panel action was successful',
'lets_CONFIGUREMODE_STATUS' => 'Configuremode Status',
'lets_CHECK_ALL_ENABLED_DOMAINS' => 'Check All Enabled Domains',
'lets_External_Interface_IP' => 'External Interface IP',
'lets_APPLY' => 'Apply',

View File

@@ -0,0 +1,73 @@
package SrvMngr::Plugin::Cache;
use Mojo::Base -base;
=head1 NAME
Mojolicious::Plugin::Renderer::WithoutCache::Cache - Mojo::Cache that doesn't cache
=head1 VERSION
Version 0.04
=cut
our $VERSION = '0.04';
$VERSION = eval $VERSION;
=head1 SYNOPSIS
You probably don't want to use this directly.
my $cache = Mojolicious::Plugin::Renderer::WithoutCache::Cache->new;
# this cache does nothing
=head1 DESCRIPTION
A cache object that's compatible to Mojo::Cache but does nothing. It does
not save or return any values. It's always empty.
=head1 METHODS
=head2 get
Does nothing. Returns C<undef>.
=cut
sub get {}
=head2 set
Does nothing. Returns C<$self> so chaining is possible.
=cut
sub set { shift; }
=head2 max_keys
Always returns zero. Can't be set. We don't want any keys.
=cut
sub max_keys { 0 }
=head1 AUTHOR
simbabque, C<< <simbabque at cpan.org> >>
=head1 BUGS
Please report any bugs or feature requests through an issue
on github at L<https://github.com/simbabque/Mojolicious-Plugin-Renderer-WithoutCache/issues>.
=head1 LICENSE
Copyright (C) simbabque.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
1;

View File

@@ -0,0 +1,94 @@
package SrvMngr::Plugin::WithoutCache;
use Mojo::Base 'Mojolicious::Plugin';
use SrvMngr::Plugin::Cache;
=head1 NAME
Mojolicious::Plugin::Renderer::WithoutCache - Disable the template cache in your Mojo app
=begin html
<p>
<a href="https://travis-ci.org/simbabque/Mojolicious-Plugin-Renderer-WithoutCache"><img src="https://travis-ci.org/simbabque/Mojolicious-Plugin-Renderer-WithoutCache.svg?branch=master"></a>
<a href='https://coveralls.io/github/simbabque/Mojolicious-Plugin-Renderer-WithoutCache?branch=master'><img src='https://coveralls.io/repos/github/simbabque/Mojolicious-Plugin-Renderer-WithoutCache/badge.svg?branch=master' alt='Coverage Status' /></a>
</p>
=end html
=head1 VERSION
Version 0.04
=cut
our $VERSION = '0.04';
$VERSION = eval $VERSION;
=head1 SYNOPSIS
This plugin turns off the renderer's cache in L<Mojolicious> and L<Mojo::Lite> applications.
use Mojolicious::Lite;
plugin 'Renderer::WithoutCache';
=head1 DESCRIPTION
This does what it says on the box. It turns off caching for the L<Mojolicious::Renderer>
or any other renderer that's inside C<$app-E<gt>renderer> by injecting a cache object that
does not do anything. This is superior to setting the C<max_keys> of L<Mojo::Cache>
to C<0> if you plan to do a lot of uncached requests, because L<Mojolicious::Renderer>
will still try to cache, and every time L<Mojo::Cache> sets a value in the cache it
looks at the C<max_keys>, and then stops.
Doing nothing at all is cheaper. But not a lot really.
=head1 METHODS
=head2 register
Register the plugin in a L<Mojolicious> application.
$plugin->register(Mojolicious->new);
=cut
sub register {
my ( $self, $app ) = @_;
$app->renderer->cache( SrvMngr::Plugin::Cache->new );
}
=head1 AUTHOR
simbabque, C<< <simbabque at cpan.org> >>
=head1 BUGS
Please report any bugs or feature requests through an issue
on github at L<https://github.com/simbabque/Mojolicious-Plugin-Renderer-WithoutCache/issues>.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Mojolicious::Plugin::Renderer::WithoutCache
=head2 Why would I want to turn off the cache?
I don't know.
=head1 ACKNOWLEDGEMENTS
This plugin was inspired by Tom Hunt asking about turning the cache off
on L<Stack Overflow|http://stackoverflow.com/q/41750243/1331451>.
=head1 LICENSE
Copyright (C) simbabque.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
1;

View File

@@ -0,0 +1,90 @@
/*
Generated by SM2Gen version: SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43
*/
.Letsencrypt-panel {}
.name {}
.rout {}
.grou {}
.link2 {}
.link3 {}
.link4 {}
.endg {}
.subh2 {}
.read4 {}
.read5 {}
.read6 {}
.subh3 {}
.read1 {}
.read2 {}
.read3 {}
.subh4 {}
.tabl1 {}
thead .tabl1 {}
tbody .tabl1 {}
.name {}
.rout {}
.subh {}
.para1 {}
.sele1 {}
.sele2 {}
.sele3 {}
.sele4 {}
.sele5 {}
.sele6 {}
.sele7 {}
.emai8 {}
.subm9 {}
.name {}
.rout {}
.head {}
.subh {}
.text1 {}
.back2 {}
.name {}
.rout {}
.head {}
.subh {}
.text1 {}
.back2 {}
.name {}
.rout {}
.head {}
.subh {}
.read1 {}
.text2 {}
.back3 {}
.inline-buttons {
display: flex; /* Use flexbox to arrange items horizontally */
gap: 10px; /* Optional: Add space between buttons */
}
.inline-buttons .link {
/* Additional styling can be added here if needed */
}
.inline-buttons .link {
display: inline-block; /* Keep links as inline-block for button shape */
padding: 7px 14px; /* Adjusted padding to approximate 70% of the original */
margin: 0; /* Remove margin */
background-color: #efefef; /* Light gray background color */
color: black; /* Text color */
text-decoration: none; /* Remove underline */
border: 2px solid #bbb; /* Thin, light gray border */
border-radius: 3px; /* Slightly rounded corners */
font-size: 11.2px; /* Adjusted font size to approximate 70% of the original */
text-align: center; /* Center the text */
cursor: pointer; /* Pointer cursor on hover */ }
/* Hover and active effects for better interaction */
.inline-buttons .link:hover {
background-color: #d9d9d9; /* Darker shade on hover */
}
.inline-buttons .link:active {
background-color: #c0c0c0; /* Even darker shade on click */
}
span .label {
padding-top:13em;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,278 @@
document.addEventListener('DOMContentLoaded', () => {
const flagContainer = document.getElementById('flag-container');
async function getCountryName(countryCode) {
try {
const response = await fetch(`https://restcountries.com/v3.1/alpha/${countryCode}`);
if (!response.ok) throw new Error('Country not found');
const data = await response.json();
// Return the name in the native language
return data[0].name.common;
} catch (error) {
console.error(error);
return 'Unknown Country';
}
}
function getFlagEmoji(locale) {
// Split the locale to get the language and country code
const parts = locale.split('-');
let countryCode;
// Handle single subtag (language only) or double subtag (language-country)
if (parts.length === 1) {
countryCode = getCountryCodeFromLanguage(parts[0]);
} else if (parts.length === 2) {
countryCode = parts[1].toLowerCase(); // Use the country code
}
// If country code is not found, set a fallback output
if (!countryCode) {
const fallback = `? ${locale.toUpperCase()}`; // Just a question mark and the full locale
return { flag: fallback, isUnknown: true, countryName: 'Unknown Country' };
}
// Convert the country code to a flag emoji
return {
flag: String.fromCodePoint(...[...countryCode.toUpperCase()].map(char => 0x1F1E6 + char.charCodeAt(0) - 'A'.charCodeAt(0))),
isUnknown: false,
countryCode: countryCode
};
}
function getCountryCodeFromLanguage(language) {
// Map languages to countries (this is an example, extend as needed)
const languageToCountryMap = {
// Add more mappings as needed
"af": "NA",
"agq": "CM",
"ak": "GH",
"am": "ET",
"ar": "01",
"as": "IN",
"asa": "TZ",
"ast": "ES",
"az": "rl",
"bas": "CM",
"be": "BY",
"bem": "ZM",
"bez": "TZ",
"bg": "BG",
"bm": "ML",
"bn": "BD",
"bo": "CN",
"br": "FR",
"brx": "IN",
"bs": "rl",
"ca": "AD",
"ccp": "BD",
"ce": "RU",
"cgg": "UG",
"chr": "US",
"ckb": "IQ",
"cs": "CZ",
"cy": "GB",
"da": "DK",
"dav": "KE",
"de": "DE",
"dje": "NE",
"dsb": "DE",
"dua": "CM",
"dyo": "SN",
"dz": "BT",
"ebu": "KE",
"ee": "GH",
"el": "CY",
"en": "01",
"es": "ES",
"et": "EE",
"eu": "ES",
"ewo": "CM",
"fa": "AF",
"ff": "CM",
"fi": "FI",
"fil": "PH",
"fo": "FO",
"fr": "FR",
"fur": "IT",
"fy": "NL",
"ga": "IE",
"gd": "GB",
"gl": "ES",
"gsw": "CH",
"gu": "IN",
"guz": "KE",
"gv": "IM",
"ha": "GH",
"haw": "US",
"he": "IL",
"hi": "IN",
"hr": "HR",
"hsb": "DE",
"hu": "HU",
"hy": "AM",
"id": "ID",
"ig": "NG",
"ii": "CN",
"is": "IS",
"it": "IT",
"ja": "JP",
"jgo": "CM",
"jmc": "TZ",
"ka": "GE",
"kab": "DZ",
"kam": "KE",
"kde": "TZ",
"kea": "CV",
"khq": "ML",
"ki": "KE",
"kk": "KZ",
"kkj": "CM",
"kl": "GL",
"kln": "KE",
"km": "KH",
"kn": "IN",
"ko": "KP",
"kok": "IN",
"ks": "IN",
"ksb": "TZ",
"ksf": "CM",
"ksh": "DE",
"kw": "GB",
"ky": "KG",
"lag": "TZ",
"lb": "LU",
"lg": "UG",
"lkt": "US",
"ln": "AO",
"lo": "LA",
"lrc": "IQ",
"lt": "LT",
"lu": "CD",
"luo": "KE",
"Luo": "KE",
"luy": "KE",
"lv": "LV",
"mas": "KE",
"mer": "KE",
"mfe": "MU",
"mg": "MG",
"mgh": "MZ",
"mgo": "CM",
"mk": "MK",
"ml": "IN",
"mn": "MN",
"mr": "IN",
"ms": "BN",
"mt": "MT",
"mua": "CM",
"my": "MM",
"mzn": "IR",
"naq": "NA",
"nb": "NO",
"nd": "ZW",
"nds": "DE",
"ne": "IN",
"nl": "NL",
"nmg": "CM",
"nn": "NO",
"nnh": "CM",
"nus": "SS",
"nyn": "UG",
"om": "ET",
"or": "IN",
"os": "GE",
"pa": "ab",
"pl": "PL",
"ps": "AF",
"pt": "PT",
"qu": "BO",
"rm": "CH",
"rn": "BI",
"ro": "RO",
"rof": "TZ",
"ru": "RU",
"rw": "RW",
"rwk": "TZ",
"sah": "RU",
"saq": "KE",
"sbp": "TZ",
"se": "SE",
"seh": "MZ",
"ses": "ML",
"sg": "CF",
"shi": "tn",
"si": "LK",
"sk": "SK",
"sl": "SI",
"smn": "FI",
"sn": "ZW",
"so": "SO",
"sq": "AL",
"sr": "rl",
"sv": "AX",
"sw": "CD",
"ta": "IN",
"te": "IN",
"teo": "KE",
"tg": "TJ",
"th": "TH",
"ti": "ER",
"to": "TO",
"tr": "TR",
"tt": "RU",
"twq": "NE",
"tzm": "MA",
"ug": "CN",
"uk": "UA",
"ur": "IN",
"uz": "ab",
"vai": "tn",
"Vai": "tn",
"vi": "VN",
"vun": "TZ",
"wae": "CH",
"wo": "SN",
"xog": "UG",
"yav": "CM",
"yi": "01",
"yo": "BJ",
"yue": "ns",
"zgh": "MA",
"zh": "ns",
"zu": "ZA"
};
return languageToCountryMap[language] || null;
}
async function displayLocaleAndFlag() {
// Get the browser locale
const userLocale = navigator.language || navigator.userLanguage;
const { flag, isUnknown, countryCode } = getFlagEmoji(userLocale);
// Display the locale and the corresponding flag (or fallback)
//document.getElementById('locale').textContent = `Your Locale: ${userLocale}`;
if (isUnknown) {
const fallbackDiv = document.createElement('div');
fallbackDiv.className = 'fallback-box';
fallbackDiv.textContent = `? ${userLocale.toUpperCase()}`; // Only show ? and locale code inside the box
//document.getElementById('flag-container').textContent = "Flag: ";
document.getElementById('flag-container').appendChild(fallbackDiv);
// Tooltip for fallback
fallbackDiv.title = "Unknown Country"; // Tooltip for fallback
} else {
const countryName = await getCountryName(countryCode);
const flagSpan = document.createElement('span');
flagSpan.textContent = flag; // Use flag emoji
flagSpan.title = countryName; // Tooltip for the flag in country language
//document.getElementById('flag-container').textContent = "Flag: ";
document.getElementById('flag-container').appendChild(flagSpan);
}
}
displayLocaleAndFlag();
});

View File

@@ -13,11 +13,10 @@
<h1><%= $title %></h1>
<!--br><%= $modul %><br-->
<p>
<p><b>
<b>
%=l ('bugr_DO_NOT_PANIC')
</b></p>
</b>
<p>
%=l ('bugr_SME_EXPERIENCE')
</p><p>
@@ -49,7 +48,7 @@
%=l ('bugr_YUM_REPOS')
</li><br></ul>
%=l ('bugr_PRIVACY')
</p><p>
</p>
<% my $btn = l('bugr_CREATE_REPORT'); %>
@@ -57,7 +56,7 @@
%= submit_button "$btn", class => 'action'
% end
</p><p><b>
<p><b>
%=l ('bugr_DONATING')
</b><br><br>
%=l ('bugr_AWARE_SME')
@@ -66,6 +65,7 @@
</b><br><br>
%=l ('bugr_CONSIDER_DONATING')
<br><br>
</p>
%= link_to 'https://wiki.koozali.org/Donate' => begin
%= image '/images/btn_donateCC_LG.gif'
@@ -76,8 +76,7 @@
<br>
%=l ('bugr_THANK_YOU')
</p>
</div>
%end
%end

View File

@@ -15,7 +15,6 @@
<br><%= $modul %><br>
<p>
<% my $btn = l('bugr_Download this report'); %>
%= form_for 'bugreportD' => (method => 'POST') => begin
@@ -25,4 +24,4 @@
</div>
%end
%end

View File

@@ -45,6 +45,7 @@
%= $dat_datas->{now_string}
</b>
</p>
<p>
<br>
<span class=label>
%=l 'dat_NTP_SERVER'
@@ -121,4 +122,4 @@
% end
</div>
%end
%end

View File

@@ -44,25 +44,25 @@
</span><span class=data>
%= text_field 'department' => $dir_datas->{department}, class => 'input'
</span>
</p>
</p><p>
<span class=label>
%=l 'dir_COMPANY', class => 'label'
</span><span class=data>
%= text_field 'company', $dir_datas->{company}, class => 'input'
</span>
</p>
</p><p>
<span class=label>
%=l 'dir_STREET', class => 'label'
</span><span class=data>
%= text_field 'street' => $dir_datas->{street}, class => 'input'
</span>
</p>
</p><p>
<span class=label>
%=l 'dir_CITY', class => 'label'
</span><span class=data>
%= text_field 'city', $dir_datas->{city}, class => 'input'
</span>
</p>
</p><p>
<span class=label>
%=l 'dir_PHONENUMBER', class => 'label'
</span><span class=data>
@@ -85,4 +85,4 @@
% end
</div>
%end
%end

View File

@@ -1,12 +1,17 @@
% layout 'default', title => "Sme server 2 - emailreceive";
% content_for 'module' => begin
% use constant FALSE => 0;
% use constant TRUE => 1;
<div id='module' class='module emailreceive-panel'>
% if ($config->{debug} == 1) {
<p>
%= dumper $c->current_route
%= dumper $mai_datas
%= dumper $c->param('SMTPAuth')
</p>
% }
@@ -26,16 +31,65 @@
%=l 'mai_LABEL_MODE'
</span><span class=input>
% param 'FetchmailMethod' => $mai_datas->{fetchmailmethod} unless param 'FetchmailMethod';
<!--
<pre>
%= dumper $mai_datas->{fetchmailmethod}
%= dumper $c->get_retrieval_opt()
%= param 'FetchmailMethod'
</pre>
-->
%= select_field 'FetchmailMethod' => $c->get_retrieval_opt(), class => 'input'
</span></p>
%=l 'mai_DESC_SMTP_AUTH_CONTROL'
%#=l 'mai_DESC_SMTP_AUTH_CONTROL'
<br />
%= l "SMTP port (25) main purpose is to receive emails from another server, STARTTLS is always offered, but auth if offered is only if STARTTLS is also used by client."
<br />
%= l "SMTPS port (465) will require implicit SSL/TLS then authenticate to send."
<br />
%= l "SMTP Submission port (587) will require STARTTLS, then authenticate to send."
<br />
% my $smtp_mesg=l('SMTP port %u allow client to authenticate:');
<p><span class=label>
%=l 'mai_LABEL_SMTP_AUTH_CONTROL'
%= sprintf($smtp_mesg,$c->get_db_prop('qpsmtpd','TCPPort',25));
</span><span class=input>
% param 'SMTPAuth' => $c->get_current_smtp_auth() unless param 'SMTPAuth';
%= select_field 'SMTPAuth' => $c->get_smtp_auth_opt(), class => 'input'
% param 'SMTPAuth' => $c->get_current_smtp_auth( FALSE ) unless param 'SMTPAuth';
<!--
<pre>
%= dumper $c->get_smtp_auth_opt()
%= dumper $c->get_current_smtp_auth(FALSE)
%= dumper $c->get_db_prop("qpsmtpd","Authentication")
%= param 'SMTPAuth'
</pre>
-->
%= select_field 'SMTPAuth' => $c->get_smtp_auth_opt(), class => 'input'
</span></p>
% my $smtp_mesg=l('SMTPS SSL/TLS auth: port %u status:');
<p><span class=label>
%= sprintf($smtp_mesg,$c->get_db_prop('sqpsmtpd','TCPPort',465));
</span><span class=input>
% param 'sSMTPAuth' => $c->get_current_smtp_ssl_auth(FALSE,'s', TRUE) unless param 'sSMTPAuth';
%= select_field 'sSMTPAuth' => $c->get_smtp_ssl_auth_opt(), class => 'input'
</span></p>
%my $smtp_mesg=l('Submission port %u status:');
<p><span class=label>
%= sprintf($smtp_mesg,$c->get_db_prop('uqpsmtpd','TCPPort',587));
</span><span class=input>
% param 'uSMTPAuth' => $c->get_current_smtp_ssl_auth(FALSE,'u', TRUE) unless param 'uSMTPAuth';
<!--
<pre>
%= dumper $c->get_smtp_ssl_auth_opt()
%= dumper $c->get_current_smtp_ssl_auth(FALSE,'s', TRUE)
%= dumper $c->get_current_smtp_ssl_auth(FALSE,'u', TRUE)
%= dumper $c->get_db_prop("uqpsmtpd","access")
%= param 'uSMTPAuth'
</pre>
-->
%= select_field 'uSMTPAuth' => $c->get_smtp_ssl_auth_opt(), class => 'input'
</span></p>
<hr class="sectionbar" />
@@ -110,4 +164,4 @@
% end
</div>
%end
%end

View File

@@ -1,9 +1,13 @@
% layout 'default', title => "Sme server 2 - emailsettings";
% content_for 'module' => begin
% use constant FALSE => 0;
% use constant TRUE => 1;
<div id='module' class='module emailsettings-panel'>
% if ($config->{debug} == 1) {
% if ($config->{debug} == TRUE) {
<p>
%= dumper $c->current_route
%= dumper $mai_datas
@@ -22,19 +26,19 @@
<p><span class=label>
%=l 'mai_LABEL_POP_ACCESS_CONTROL'
</span><span class=data2>
%= $c->get_current_pop3_access( 1 )
%= $c->get_current_pop3_access( TRUE )
</span></p>
<p><span class=label>
%=l 'mai_LABEL_IMAP_ACCESS_CONTROL'
</span><span class=data2>
%= $c->get_current_imap_access( 1 )
%= $c->get_current_imap_access( TRUE )
</span></p>
<p><span class=label>
%=l 'mai_LABEL_WEBMAIL'
</span><span class=data2>
%= $c->get_current_webmail_status( 1 )
%= $c->get_current_webmail_status( TRUE )
</span></p>
% my $btn = l('mai_DESC_STATE_ACCESS_BUTTON');
@@ -51,19 +55,19 @@
<p><span class=label>
%=l 'mai_LABEL_VIRUS_SCAN'
</span><span class=data2>
%= $c->get_virus_status(1)
%= $c->get_virus_status(TRUE)
</span></p>
<p><span class=label>
%=l 'mai_LABEL_SPAM_SCAN'
</span><span class=data2>
%= $c->get_spam_status(1)
%= $c->get_spam_status(TRUE)
</span></p>
<p><span class=label>
%=l 'mai_LABEL_BLOCK_EXECUTABLE_CONTENT'
</span><span class=data2>
%= $c->get_patterns_status(1)
%= $c->get_patterns_status(TRUE)
</span></p>
% my $btn = l('mai_DESC_STATE_FILTERING_BUTTON');
@@ -83,12 +87,28 @@
%= $mai_datas->{fetchmailmethod}
</span></p>
% my $smtp_mesg=l('SMTP port %u allow client to authenticate:');
<p><span class=label>
%=l 'mai_LABEL_SMTP_AUTH_CONTROL'
%= sprintf($smtp_mesg,$c->get_db_prop('qpsmtpd','TCPPort',25));
</span><span class=data2>
%= $c->get_current_smtp_auth( 1 )
%= $c->get_current_smtp_auth( TRUE )
</span></p>
% my $smtp_mesg=l('SMTPS SSL/TLS auth: port %u status:');
<p><span class=label>
%= sprintf($smtp_mesg,$c->get_db_prop('sqpsmtpd','TCPPort',465));
</span><span class=data2>
%= $c->get_current_smtp_ssl_auth( TRUE, 's', FALSE )
</span></p>
%my $smtp_mesg=l 'Submission port %u status:';
<p><span class=label>
%= sprintf($smtp_mesg,$c->get_db_prop('uqpsmtpd','TCPPort',587));
</span><span class=data2>
%= $c->get_current_smtp_ssl_auth( TRUE,'u', FALSE )
</span></p>
<br />
% my $btn = l('mai_DESC_STATE_RECEPTION_BUTTON');
<div class='center'>
%= submit_button "$btn", class => 'action'
@@ -103,7 +123,7 @@
<p><span class=label>
%=l 'mai_LABEL_UNKNOWN'
</span><span class=data2>
%= $c->get_emailunknownuser_status( 1 )
%= $c->get_emailunknownuser_status( TRUE )
</span></p>
<p><span class=label>
@@ -127,4 +147,4 @@
% end
</div>
%end
%end

View File

@@ -5,7 +5,7 @@
<!-- default +jquery -->
<head>
<title><%= $title %></title>
<link rev="made" href="mailto:bugs%40koozali.org">
<link rel="made" href="mailto:bugs%40koozali.org">
<meta name="copyright" content="(head.tmpl)Copyright 2003-2004 Mitel Corporation">
%= stylesheet '/css/sme_core.css'
%= stylesheet '/css/sme_main.css'
@@ -19,18 +19,35 @@
%= content_for 'refresh'
%= stylesheet '/js/datatables.min.css'
%= javascript '/js/datatables.min.js'
%= stylesheet '/js/jquery-ui.min.css'
%= javascript '/js/jquery-ui.min.js'
%= stylesheet '/js/dataTables.buttons.min.js'
%= stylesheet '/js/jszip.min.js'
%= stylesheet '/js/pdfmake.min.js'
%= stylesheet '/js/vfs_fonts.js'
%= stylesheet '/js/buttons.html5.min.js'
%= stylesheet '/js/buttons.print.min.js'
%= javascript '/js/datatables.min.js'
%= stylesheet '/js/jquery-ui.min.css'
%= javascript '/js/jquery-ui.min.js'
%= javascript '/js/dataTables.buttons.min.js'
%= javascript '/js/jszip.min.js'
%= javascript '/js/pdfmake.min.js'
%= javascript '/js/vfs_fonts.js'
%= javascript '/js/buttons.html5.min.js'
%= javascript '/js/buttons.print.min.js'
%= javascript '/js/flag-by-locale.js'
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.5.0/css/flag-icon.min.css">
%= stylesheet '/css/sme-jquery-overrides.css'
<style>
#busy-indicator {
display: none;
margin-top: 10px;
font-weight: bold;
color: red;
}
.busy {
cursor: wait; /* Change the cursor to a 'wait' cursor */
}
</style>
</head>
@@ -91,46 +108,21 @@
%= javascript '/js/sme-dataTable-setup.js'
%= javascript begin
//Set menu to initial condition based on localStorage
$(document).ready(function() {
let menunavflag = window.localStorage.getItem('menunav');
if (menunavflag != "false"){
$('#menunav').toggle(true);
} else {
$('#menunav').toggle(false);
}
let menuadmflag = window.localStorage.getItem('menuadm');
if (menuadmflag != "false"){
$('#menuadm').toggle(true);
} else {
$('#menuadm').toggle(false);
}
<script>
$(document).ready(function() {
// Handle form submission for any form
$('form').on('submit', function(event) {
// Disable the submit button
$(this).find('button[type="submit"], input[type="submit"]').prop('disabled', true);
// Show the busy indicator
// $('#busy-indicator').show();
// Change the cursor to "wait"
$('body').addClass('busy');
});
});
</script>
let menuuserflag = window.localStorage.getItem('menuuser');
if (menuuserflag != "false"){
$('#menuuser').toggle(true);
} else {
$('#menuuser').toggle(false);
}
var sections = document.getElementsByClassName("section-title");
for (var i = 0, len = sections.length; i < len; i++) {
var jqObj = $(sections[i]);
var $section = jqObj.parent().next('div');
if(!$section.length){
return false;
}
let localStorageTag = "admSection-"+sections[i].innerHTML;
if (window.localStorage.getItem(localStorageTag) != "false"){
$section.toggle(true);
} else {
$section.toggle(false);
}
}
})
%end
</body>
</html>
</html>

View File

@@ -0,0 +1,69 @@
%#
%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43
%#
% layout 'default', title => "Sme server 2 - Letsencrypt certificate", share_dir => './';
%# css specific to this panel:
% content_for 'module' => begin
%= stylesheet '/css/letsencrypt.css'
<div id="module" class="module Letsencrypt-panel">
% if ($config->{debug} == 1) {
<pre>
%= dumper $c->current_route
%= dumper $lets_data->{trt}
</pre>
% }
<h1><%=$title%></h1>
% if ( stash('modul')) {
%= $c->render_to_string(inline => stash('modul') );
% }
%if ($c->stash('first')) {
<br><p>
%=$c->render_to_string(inline =>$c->l($c->stash('first')))
</p>
%} elsif ($c->stash('success')) {
<div class='success '>
<h2><%=$c->l('lets_Status_Report') %></h2><p>
%= $c->l($c->stash('success'));
</p>
</div>
%} elsif ($c->stash('error')) {
<div class='sme-error'>
<h2><%=$c->l('lets_Error_Status_Report') %></h2><p>
%= $c->l($c->stash('error'));
</p>
</div>
%}
%#Routing to partials according to trt parameter.
%#This ought to be cascading if/then/elsif, but is easier to just stack the if/then's rather like a case statement'
% if ($lets_data->{trt} eq "LIST") {
%= include 'partials/_lets_LIST'
%}
% if ($lets_data->{trt} eq "PARAMS") {
%= include 'partials/_lets_PARAMS'
%}
% if ($lets_data->{trt} eq "CHECKALLDOMAINS") {
%= include 'partials/_lets_CHECKALLDOMAINS'
%}
% if ($lets_data->{trt} eq "CHECKALLENABLEDDOMAINS") {
%= include 'partials/_lets_CHECKALLENABLEDDOMAINS'
%}
% if ($lets_data->{trt} eq "CHECKONEDOMAIN") {
%= include 'partials/_lets_CHECKONEDOMAIN'
%}
</div>
%end

View File

@@ -46,19 +46,34 @@
%= t td => (class => 'sme-border') => $domain->{'Content'}
%= t td => (class => 'sme-border') => l('dom_' . $domain->{'Nameservers'})
% my $actionModify = "<a href='domains2?CsrfDef=TOKEN&trt=UPD&Domain=" . $domain->{Domain} . "'>" . "<button class='sme-modify-button' title=".l('MODIFY').">".l('MODIFY')."</button>" . "</a>";
% my $removable = ($domain->{Removable} || 'yes');
% my $actionRemove = '&nbsp;';
% if ($removable eq 'yes') {
% $actionRemove = "<a href='domains2?CsrfDef=TOKEN&trt=DEL&Domain=" . $domain->{Domain} . "'>" . "<button class='sme-remove-button' title=".l('REMOVE').">".l('REMOVE')."</button>" . "</a>";
% }
<td class='sme-border' style="min-width:15em">
<%= $c->render_to_string(inline => $actionModify) %> <%= $c->render_to_string(inline => $actionRemove) %>
</td>
</tr>
%# my $actionModify = "<a href='domains2?CsrfDef=TOKEN&trt=UPD&Domain=" . $domain->{Domain} . "'>" . "<button class='sme-modify-button' title=".l('MODIFY').">".l('MODIFY')."</button>" . "</a>";
%my $modify_text = l('MODIFY'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $domain_name = $domain->{Domain}; # Domain name extracted from the data structure
%my $actionModify = qq{
% <button type='button' class='sme-modify-button' title='$modify_text'
% onclick="window.location.href='domains2?CsrfDef=$csrf_token&trt=UPD&Domain=$domain_name'">
% $modify_text
% </button>
%};
%my $removable = ($domain->{Removable} || 'yes');
%my $actionRemove = '&nbsp;';
%if ($removable eq 'yes') {
%my $remove_text = l('REMOVE'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $domain_name = $domain->{Domain}; # Domain name extracted from the data structure
%$actionRemove = qq{
% <button type='button' class='sme-remove-button' title='$remove_text'
% onclick="window.location.href='domains2?CsrfDef=$csrf_token&trt=DEL&Domain=$domain_name'">
% $remove_text
% </button>
%};
%# $actionRemove = "<a href='domains2?CsrfDef=TOKEN&trt=DEL&Domain=" . $domain->{Domain} . "'>" . "<button class='sme-remove-button' title=".l('REMOVE').">".l('REMOVE')."</button>" . "</a>";
%};
<td class='sme-border' style="min-width:15em">
<%= $c->render_to_string(inline => $actionModify) %> <%= $c->render_to_string(inline => $actionRemove) %>
</td>
</tr>
% }
</tbody>
@@ -102,4 +117,4 @@
</div>
</div>

View File

@@ -1,11 +1,11 @@
<div id="footer">
<HR class="sme-copyrightbar">
<a href="https://mojolicious.org" target="_blank"><img src="images/sme-mojo-logo-white.png" style="position:relative;"></a>
<font class="sme-copyright">
% if ( $c->is_logged_in ) {
SME Server <%= session 'releaseVersion' %> - Manager <%= $c->app->VERSION %>
SME Server <%= session 'releaseVersion' %>-<%= $c->app->VERSION %> Manager II
% }
<br>Copyright 1999-2006 Mitel Corporation<br>
%= session 'copyRight'
<br>Copyright (c) 2013-2024 Koozali Foundation Inc.<br>
</font>
</font>

View File

@@ -39,8 +39,25 @@
%= t td => (class => 'sme-border') => $group->key
%= t td => (class => 'sme-border') => $group->prop('Description')
<td class='sme-border' style="min-width:15em">
<a href='groups2?CsrfDef=TOKEN&trt=UPD&group=<%= $group->key%>'><button class='sme-modify-button' title=<%=l('MODIFY')%>><%=l('MODIFY') %></button></a>
<a href='groups2?CsrfDef=TOKEN&trt=DEL&group=<%= $group->key%>'><button class='sme-remove-button' title=<%=l('REMOVE')%>><%=l('REMOVE') %></button></a>
%my $modify_text = l('MODIFY'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $group_name = $group->key; # group name extracted from the data structure
%my $actionModify = qq{
% <button type='button' class='sme-modify-button' title='$modify_text'
% onclick="window.location.href='groups2?CsrfDef=$csrf_token&trt=UPD&group=$group_name'">
% $modify_text
% </button>
%};
%my $remove_text = l('REMOVE'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $group_name = $group->key; # group name extracted from the data structure
%my $actionRemove = qq{
% <button type='button' class='sme-remove-button' title='$remove_text'
% onclick="window.location.href='groups2?CsrfDef=$csrf_token&trt=DEL&group=$group_name'">
% $remove_text
% </button>
%};
<%= $c->render_to_string(inline => $actionModify) %> <%= $c->render_to_string(inline => $actionRemove) %>
</td>
</tr>
% }
@@ -50,4 +67,4 @@
</p>
</div>
</div>

View File

@@ -1,27 +1,128 @@
<style>
#h2l1 {
display: flex; /* Use flexbox layout */
justify-content: space-between; /* Space between child elements */
align-items: center; /* Center items vertically */
}
#h2e11 {
flex: 1; /* Allow the first div to take available space on the left */
}
#h2e12 {
display: flex; /* Make this div a flex container */
align-items: center; /* Vertically center content in this div */
margin-left: 20px; /* Add margin to the left of this div */
}
#flag-container {
display: flex; /* Make this div a flex container */
align-items: center; /* Vertically center content in this div */
margin-left: 20px; /* Add margin to the left of the flag container */
padding-right: 20px; /* Add padding to the right side of the flag container */
}
.flag-icon {
width: 43px;
font-size: 20px;
}
#legacy-button button {
background-color: #98d36e; /* Button background color */
font-weight: lighter; /* Lighter text for the button */
color: #063; /* Button text color */
padding: 5px 10px; /* Padding for the button */
border: none; /* Remove default button border */
border-radius: 4px; /* Rounded corners for button */
cursor: pointer; /* Change cursor on hover */
}
#legacy-button button:hover {
background-color: #82c961; /* Change color on hover */
}
.infobar {
display: flex; /* Use flexbox for alignment */
justify-content: space-between; /* Space between child elements */
align-items: center; /* Center items vertically */
padding: 10px; /* Adjust padding as desired */
}
#h2e21 {
flex: 1; /* Allow the first div to take available space on the left */
}
#h2e22 {
display: flex; /* Make this div a flex container */
justify-content: center; /* Center the help button */
align-items: center; /* Center vertically */
flex: none; /* Prevent this div from growing */
position: relative; /* Relative position for centering */
width: 100px; /* Set a width for the help button container */
}
#h2e23 {
margin-left: auto; /* Push the third div to the right */
}
.login-button {
background-color: #98d36e; /* Button background color */
font-weight: bold; /* Bold text */
xxcolor: #ffffff; /* Button text color */
padding: 8px 12px; /* Adjust padding for button height */
border: none; /* Remove default border */
border-radius: 4px; /* Rounded corners */
cursor: pointer; /* Change cursor on hover */
}
.login-button:hover {
background-color: #82c961; /* Change color on hover */
}
#help-button {
text-decoration: none; /* Remove underline from link */
font-size: 20px; /* Adjust font size as needed */
padding: 8px 12px; /* Add padding to the help link */
background-color: #98d36e; /* Background for visibility */
border-radius: 4px; /* Rounded corners */
color: #000; /* Button text color */
}
#help-button:hover {
background-color: #82c961; /* Change background on hover */
}
</style>
<div id="header2" class="hd2">
<div id="h2l1">
<div id="h2e11">
<a target='_blank' href="http://www.koozali.org"><img src="images/smeserver_logo.jpg" height="40" alt="SME Server"></a>
</div>
<!-- <div id="h2e12"><h5><a href="initial">Server Manager</a>
<a href="/server-manager" target='_blank'>&nbsp &nbsp (Prev SM)</a></h5> -->
<div id="h2e12" style="float:right;"><br><a href="/server-manager" target='_blank'><button style="background-color:#98d36e;font-weight:bold;color:#063;">Legacy SM</button></a></div>
</div>
<div id="h2e11">
<a target='_blank' href="http://www.koozali.org"><img src="images/smeserver_logo.jpg" height="40" alt="SME Server"></a>
</div>
<div id="h2l2" class="infobar">
<div id="h2e21">
<b>
<%= session 'SystemName' %>@<%= session 'DomainName' %></b>
</div>
<div id="h2e22">
<a target="_parent" href="manual">&nbsp;&nbsp;<b> ? </b>&nbsp;&nbsp;</a>&nbsp;
</div>
<div id="h2e23">
% if ( not defined $c->session->{username} ) {
<a target="_parent" href="login"><b>Login</b></a>&nbsp;
% } else {
<a target="_parent" href="logout"><b><%= $c->session->{username} %> Logout</b></a>&nbsp;
% }
</div>
<div id="h2e22">
<button type='button'><a id="help-button" target="_parent" href="manual">?</a></button>
</div>
<div id="h2e12">
<button type='button'><a id="legacy-button" href="/server-manager" target='_blank'>Legacy SM</a></button>
</div>
<div id="h2e23">
% if ( not defined $c->session->{username} ) {
<button type='button' class="login-button"><a target="_parent" href="login">Login</a></button>
% } else {
<button type='button' class="login-button"><a target="_parent" href="logout"><%= $c->session->{username} %> Logout</a></button>
% }
</div>
<div id="flag-container">
<!-- The flag icon will be inserted here -->
</div>
</div>
</div>
<div id="h2l2" class="infobar">
<div id="h2e21">
<b>
<%= session 'SystemName' %>@<%= session 'DomainName' %></b>
</div>
</div>
</div>

View File

@@ -49,25 +49,34 @@
%= t td => (class => 'sme-border') => $_->{'IP'};
%= t td => (class => 'sme-border') => $_->{'MACAddress'};
%= t td => (class => 'sme-border') => $_->{'Comment'};
% my ($actionModify, $actionRemove) = '&nbsp;';
% if ($_->{'static'} ne 'yes') {
% $actionModify = "<a href='hostentriesd?CsrfDef=TOKEN&trt=UPD&Hostname=" . $_->{'HostName'} . "'>" . "<button class='sme-modify-button' title=".l('MODIFY').">".l('MODIFY')."</button>" . "</a>";
% $actionRemove = "<a href='hostentriesd?CsrfDef=TOKEN&trt=DEL&Hostname=" . $_->{'HostName'} . "'>" . "<button class='sme-remove-button' title=".l('REMOVE').">".l('REMOVE')."</button>" . "</a>";
% }
<td class='sme-border' style="min-width:15em">
<%= $c->render_to_string(inline => $actionModify) %>
<%= $c->render_to_string(inline => $actionRemove) %>
%my ($actionModify, $actionRemove) = '&nbsp;';
%my $static = $_->{'static'} || "no";
%if ($static ne 'yes') {
%my $modify_text = l('MODIFY'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $hostentries_name = $_->{'HostName'}; # hostentries name extracted from the data structure
%$actionModify = qq{
% <button type='button' class='sme-modify-button' title='$modify_text'
% onclick="window.location.href='hostentriesd?CsrfDef=$csrf_token&trt=UPD&Hostname=$hostentries_name'">
% $modify_text
% </button>
%};
%my $remove_text = l('REMOVE'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%#my $hostentries_name = $_->{'HostName'}; # hostentries name extracted from the data structure
%$actionRemove = qq{
% <button type='button' class='sme-remove-button' title='$remove_text'
% onclick="window.location.href='hostentriesd?CsrfDef=$csrf_token&trt=DEL&Hostname=$hostentries_name'">
% $remove_text
% </button>
%};
%}
<%= $c->render_to_string(inline => $actionModify) %> <%= $c->render_to_string(inline => $actionRemove) %>
</td>
</tr>
% }
</tbody>
</table>
</p>
% }
</div>
</tbody>
</table>
% }
</div>

View File

@@ -9,6 +9,7 @@
<br>
%= submit_button "$btn", class => 'action'
</p>
%= hidden_field 'trt' => 'ADD';
% end
@@ -45,35 +46,62 @@
<tr>
%= t td => (class => 'sme-border') => $ibay->key
%= t td => (class => 'sme-border') => $ibay->prop('Name')
% my ($actionModify, $actionResetPw, $actionRemove) = '&nbsp;';
% if ($modifiable eq 'yes') {
% $actionModify = "<a href='ibaysd?CsrfDef=TOKEN&trt=UPD&ibay=" . $ibay->key . "'>" . "<button class='sme-modify-button' title=".l('MODIFY').">".l('MODIFY')."</button>" . "</a>";
% }
% if ($passwordable eq 'yes') {
% if ($ibay->prop('PasswordSet') ne 'yes' && $needPassword) {
%# $actionResetPw .= "<a href='ibaysd?CsrfDef=TOKEN&trt=PWD&ibay=" . $ibay->key . "' class='error'>" . l('PASSWORD_RESET') . "</a>";
% $actionResetPw .= "<a href='ibaysd?CsrfDef=TOKEN&trt=PWD&ibay=" . $ibay->key. "'>" . "<button class='sme-password-button' style ='border-color:red;' title=".l("Reset-Password").">".l("Reset-Password")."</button></a>";
% } else {
% $actionResetPw .= "<a href='ibaysd?CsrfDef=TOKEN&trt=PWD&ibay=" . $ibay->key . "'>" . "<button class='sme-password-button' title=".l("Reset-Password").">".l("Reset-Password")."</button></a>";
%# $actionResetPw .= "<a href='ibaysd?CsrfDef=TOKEN&trt=PWD&ibay=" . $ibay->key . "'>" . l('PASSWORD_RESET') . "</a>";
% }
% $actionResetPw .= '&nbsp';
% }
% if ($removable eq 'yes') {
% $actionRemove = "<a href='ibaysd?CsrfDef=TOKEN&trt=DEL&ibay=" . $ibay->key . "'>" . "<button class='sme-remove-button' title=".l('REMOVE').">".l('REMOVE')."</button>" . "</a>";
% }
<td class='sme-border' style="min-width:20em">
<td class='sme-border' style="min-width:15em">
%my ($actionModify, $actionResetPw, $actionRemove) = '&nbsp;';
%if ($modifiable eq 'yes') {
%my $modify_text = l('MODIFY'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $ibays_entry_name = $ibay->key; # ibays_entry name extracted from the data structure
%$actionModify = qq{
% <button type='button' class='sme-modify-button' title='$modify_text'
% onclick="window.location.href='ibaysd?CsrfDef=$csrf_token&trt=UPD&ibay=$ibays_entry_name'">
% $modify_text
% </button>
%};
%}
%if ($passwordable eq 'yes') {
%my $password_text = l('PASSWORD_RESET'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $ibays_entry_name = $ibay->key; # ibays_entry name extracted from the data structure
%if ($ibay->prop('PasswordSet') ne 'yes' && $needPassword) {
%$actionResetPw = qq{
% <button type='button' class='sme-password-button unset' title="$password_text - currently unset" style = background:pink;
% onclick="window.location.href='ibaysd?CsrfDef=$csrf_token&trt=PWD&ibay=$ibays_entry_name'">
% $password_text
% </button>
%};
%} else {
%$actionResetPw = qq{
% <button type='button' class='sme-password-button' title='$password_text'
% onclick="window.location.href='ibaysd?CsrfDef=$csrf_token&trt=PWD&ibay=$ibays_entry_name'">
% $password_text
% </button>
%};
%}
%}
%if ($removable eq 'yes') {
%my $remove_text = l('REMOVE'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $ibays_entry_name = $ibay->key; # ibays_entry name extracted from the data structure
%$actionRemove = qq{
% <button type='button' class='sme-remove-button' title='$remove_text'
% onclick="window.location.href='ibaysd?CsrfDef=$csrf_token&trt=DEL&ibays=$ibays_entry_name'">
% $remove_text
% </button>
%};
%}
<%= $c->render_to_string(inline => $actionModify) %>
<%= $c->render_to_string(inline => $actionResetPw)%>
<%= $c->render_to_string(inline => $actionRemove) %>
</td>
</tr>
</td>
</tr>
% }
</tbody>
</table>
<%} %>
%= hidden_field 'trt' => $iba_datas->{trt}
</div>
</div>

View File

@@ -0,0 +1,39 @@
%#
%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43
%#
<div id="Letsencrypt-CHECKALLDOMAINS" class="partial Letsencrypt-CHECKALLDOMAINS">
<script>
window.onload = function() {
SelectInput();
};
</script>
% if ($config->{debug} == 1) {
<pre>
%= dumper $lets_data
</pre>
% }
% my $btn = l('lets_APPLY');
%= form_for "letsencryptu" => (method => 'POST') => begin
% param 'trt' => $lets_data->{trt} unless param 'trt';
%= hidden_field 'trt' => $lets_data->{trt}
%# Inputs etc in here.
<h1 class='head'><%=l('lets_Check_all_domains')%></h1>
<h2 class='subh'><%=l('lets_Loop_through_checking_the_letsencrypt')%></h2>
<span class=label>
%=l('lets_All_domains_check_result')
</span><span class=data>
% param 'AllDomainsCheck' => $lets_data->{AllDomainsCheck} unless param 'AllDomainsCheck';
%= text_area 'AllDomainsCheck', cols=>40, rows=>10, Readonly=>'true'
</span><br>
<span class='data'>
%= submit_button l('lets_Back'), class => 'action back', onclick =>'history.back()'
</span>
%# Probably finally by a submit.
%end
</div>

View File

@@ -0,0 +1,39 @@
%#
%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43
%#
<div id="Letsencrypt-CHECKALLENABLEDDOMAINS" class="partial Letsencrypt-CHECKALLENABLEDDOMAINS">
<script>
window.onload = function() {
SelectInput();
};
</script>
% if ($config->{debug} == 1) {
<pre>
%= dumper $lets_data
</pre>
% }
% my $btn = l('lets_APPLY');
%= form_for "letsencryptu" => (method => 'POST') => begin
% param 'trt' => $lets_data->{trt} unless param 'trt';
%= hidden_field 'trt' => $lets_data->{trt}
%# Inputs etc in here.
<h1 class='head'><%=l('lets_Check_all_enabled_domains')%></h1>
<h2 class='subh'><%=l('lets_Loop_through_checking_the_letsencrypt')%></h2>
<span class=label>
%=l('lets_Enabled_domains_check_result')
</span><span class=data>
% param 'EnabledDomainsCheck' => $lets_data->{EnabledDomainsCheck} unless param 'EnabledDomainsCheck';
%= text_area 'EnabledDomainsCheck', cols=>40, rows=>10, Readonly=>'true'
</span><br>
<span class='data'>
%= submit_button l('lets_Back'), class => 'action back', onclick =>'history.back()'
</span>
%# Probably finally by a submit.
%end
</div>

View File

@@ -0,0 +1,46 @@
%#
%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43
%#
<div id="Letsencrypt-CHECKONEDOMAIN" class="partial Letsencrypt-CHECKONEDOMAIN">
<script>
window.onload = function() {
SelectInput();
};
</script>
% if ($config->{debug} == 1) {
<pre>
%= dumper $lets_data
</pre>
% }
% my $btn = l('lets_APPLY');
%= form_for "letsencryptu" => (method => 'POST') => begin
% param 'trt' => $lets_data->{trt} unless param 'trt';
%= hidden_field 'trt' => $lets_data->{trt}
%# Inputs etc in here.
<h1 class='head'><%=l('lets_Check_just_one_domain')%></h1>
<h2 class='subh'><%=l('lets_Loop_through_and_check_the')%></h2>
<p><span class=label>
%=l('lets_Domains_name')
</span><span class=data>
% param 'OneDomainToCheck' => $lets_data->{OneDomainToCheck} unless param 'OneDomainToCheck';
%= text_field 'OneDomainToCheck', size => '50', class => 'textinput OneDomainToCheck' , pattern=>'.*' , placeholder=>'OneDomainToCheck', Readonly=>'true'
<br></span></p>
<span class=label>
%=l('lets_One_domain_check_result')
</span><span class=data>
% param 'OneDomainsCheck' => $lets_data->{OneDomainsCheck} unless param 'OneDomainsCheck';
%= text_area 'OneDomainsCheck', cols=>40, rows=>10, Readonly=>'true'
</span><br>
<span class='data'>
%= submit_button l('lets_Back'), class => 'action back', onclick =>'history.back()'
</span>
%# Probably finally by a submit.
%end
</div>

View File

@@ -0,0 +1,126 @@
%#
%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43
%#
<div id="Letsencrypt-LIST" class="partial Letsencrypt-LIST">
<script>
window.onload = function() {
SelectInput();
};
</script>
% if ($config->{debug} == 1) {
<pre>
%= dumper $lets_data
</pre>
% }
% my $btn = l('lets_APPLY');
%= form_for "letsencryptu" => (method => 'POST') => begin
% param 'trt' => $lets_data->{trt} unless param 'trt';
%= hidden_field 'trt' => $lets_data->{trt}
%# Inputs etc in here.
<div class=inline-buttons>
<a href='letsencryptd?trt=PARAMS' class='link link2'>
%= l('lets_CONFIG')
</a>
%#= link_to l('lets_CONFIG'), 'letsencryptd?trt=PARAMS' , class=>'link link2'
<a href='letsencryptd?trt=CHECKALLDOMAINS' class='link link3'>
%= l('lets_CHECK_ALL_DOMAINS')
</a>
%#= link_to l('lets_CHECK_ALL_DOMAINS'), 'letsencryptd?trt=CHECKALLDOMAINS' , class=>'link link3'
<a href='letsencryptd?trt=CHECKALLENABLEDDOMAINS' class='link link4'>
%= l('lets_CHECK_ALL_ENABLED_DOMAINS')
</a>
%#= link_to l('lets_CHECK_ALL_ENABLED_DOMAINS'), 'letsencryptd?trt=CHECKALLENABLEDDOMAINS' , class=>'link link4'
</div>
<h2 class='subh2'><%=l('lets_For_this_Server')%></h2>
<p><span class=label>
%=l('lets_Internal_IP')
</span><span class=data>
% param 'InternalIP' => $lets_data->{InternalIP} unless param 'InternalIP';
%= text_field 'InternalIP', size => '50', class => 'textinput InternalIP' , pattern=>'.*' , placeholder=>'InternalIP', Readonly=>'true'
<br></span></p>
<p><span class=label>
%=l('lets_External_Interface_IP')
</span><span class=data>
% param 'ExternalIP' => $lets_data->{ExternalIP} unless param 'ExternalIP';
%= text_field 'ExternalIP', size => '50', class => 'textinput ExternalIP' , pattern=>'.*' , placeholder=>'ExternalIP', Readonly=>'true'
<br></span></p>
<p><span class=label>
%=l('lets_Internet_IP')
</span><span class=data>
% param 'InternetIP' => $lets_data->{InternetIP} unless param 'InternetIP';
%= text_field 'InternetIP', size => '50', class => 'textinput InternetIP' , pattern=>'.*' , placeholder=>'InternetIP', Readonly=>'true'
<br></span></p>
<h2 class='subh3'><%=l('lets_Current_certificate_details')%></h2>
<p><span class=label>
%=l('lets_Issuer')
</span><span class=data>
% param 'Issuer' => $lets_data->{Issuer} unless param 'Issuer';
%= text_field 'Issuer', size => '50', class => 'textinput Issuer' , pattern=>'.*' , placeholder=>'Issuer', Readonly=>'true'
<br></span></p>
<p><span class=label>
%=l('lets_Expiry')
</span><span class=data>
% param 'Expiry' => $lets_data->{Expiry} unless param 'Expiry';
%= text_field 'Expiry', size => '50', class => 'textinput Expiry' , pattern=>'.*' , placeholder=>'Expiry', Readonly=>'true'
<br></span></p>
<p><span class=label>
%=l('lets_Not_Before')
</span><span class=data>
% param 'NotBefore' => $lets_data->{NotBefore} unless param 'NotBefore';
%= text_field 'NotBefore', size => '50', class => 'textinput NotBefore' , pattern=>'.*' , placeholder=>'NotBefore', Readonly=>'true'
<br></span></p>
<h2 class='subh4'><%=l('lets_List_of_Domains_and_Hosts')%></h2>
<br /><table class="sme-border TableSort sme-table tabl1 ">
<thead class='tabl1'>
<tr table-head-row>
<th class='sme-border table-head-col table-head-col-Domain name / HOSTNAME '><%=l('lets_Domain_name_/_HOSTNAME')%></th>
<th class='sme-border table-head-col table-head-col-Brief description '><%=l('lets_Brief_description')%></th>
<th class='sme-border table-head-col table-head-col-Content '><%=l('lets_Content')%></th>
<th class='sme-border table-head-col table-head-col-LABEL_NAMESERVERS '><%=l('lets_LABEL_NAMESERVERS')%></th>
<th class='sme-border table-head-col table-head-col-LABEL_POINT '><%=l('lets_LABEL_POINT')%></th>
<th class='sme-border table-head-col table-head-col-LABEL_LECERT '><%=l('lets_LABEL_LECERT')%></th>
<th class='sme-border table-head-col table-head-col-IS_IN_CERT '><%=l('lets_IS_IN_CERT')%></th>
<th class='sme-border table-head-col table-head-col-CHECK '><%=l('lets_CHECK')%></th>
</tr>
</thead>
<tbody class='tabl1'>
% my $control_data = $c->stash('DomainList');
% foreach my $row (@$control_data) {
<tr class='table-row'>
<td class='sme-border table-col table-col-Table1-Domain name / HOSTNAME'><%=$c->render_to_string(inline=>$row->{'Table1-Domain name / HOSTNAME'})%></td>
<td class='sme-border table-col table-col-Table1-Brief description'><%=$c->render_to_string(inline=>$row->{'Table1-Brief description'})%></td>
<td class='sme-border table-col table-col-Table1-Content'><%=$c->render_to_string(inline=>$row->{'Table1-Content'})%></td>
<td class='sme-border table-col table-col-Table1-LABEL_NAMESERVERS'><%=$c->render_to_string(inline=>$row->{'Table1-LABEL_NAMESERVERS'})%></td>
<td class='sme-border table-col table-col-Table1-LABEL_POINT'><%=$c->render_to_string(inline=>$row->{'Table1-LABEL_POINT'})%></td>
<td class='sme-border table-col table-col-Table1-LABEL_LECERT'><%=$c->render_to_string(inline=>$row->{'Table1-LABEL_LECERT'})%></td>
<td class='sme-border table-col table-col-Table1-IS_IN_CERT'><%=$c->render_to_string(inline=>$row->{'Table1-IS_IN_CERT'})%></td>
<td class='sme-border table-col table-col-Table1-CHECK'><%=$c->render_to_string(inline=>$row->{'Table1-CHECK'})%></td>
</tr>
%}
</tbody>
</table>
%# Probably finally by a submit.
%end
</div>

View File

@@ -0,0 +1,97 @@
%#
%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43
%#
<div id="Letsencrypt-PARAMS" class="partial Letsencrypt-PARAMS">
<script>
window.onload = function() {
SelectInput();
};
</script>
% if ($config->{debug} == 1) {
<pre>
%= dumper $lets_data
</pre>
% }
% my $btn = l('lets_APPLY');
%= form_for "letsencryptu" => (method => 'POST') => begin
% param 'trt' => $lets_data->{trt} unless param 'trt';
%= hidden_field 'trt' => $lets_data->{trt}
%# Inputs etc in here.
<h2 class='subh'><%=l('lets_Manage_letsencrypt-config_settings:')%></h2>
<p class='paragraph para1'>
%=l('lets_CONFIG_LETSENCRYPT')
</p>
<p><span class=label>
%=l('lets_SERVICE_STATUS')
</span><span class=data>
% my @status_options = [['Disabled' => 'disabled'], ['Enabled' => 'enabled'], ['TEST' => 'test']];
% param 'status' => $lets_data->{status} unless param 'status';
%= select_field 'status' => @status_options, class => 'input'
<br></span> </p>
<p><span class=label>
%=l('lets_HOOKSCRIPT_STATUS')
</span><span class=data>
% my @hookScript_options = [['Disabled' => 'disabled'], ['Enabled' => 'enabled']];
% param 'hookScript' => $lets_data->{hookScript} unless param 'hookScript';
%= select_field 'hookScript' => @hookScript_options, class => 'input'
<br></span> </p>
<p><span class=label>
%=l('lets_HOSTOVERRIDE_STATUS')
</span><span class=data>
% my @hostOverride_options = [['Disabled' => 'disabled'], ['Yes' => 'yes']];
% param 'hostOverride' => $lets_data->{hostOverride} unless param 'hostOverride';
%= select_field 'hostOverride' => @hostOverride_options, class => 'input'
<br></span> </p>
<p><span class=label>
%=l('lets_ACCEPT_TERMS_STATUS')
</span><span class=data>
% my @ACCEPT_TERMS_options = [['Disabled' => 'disabled'], ['Yes' => 'yes']];
% param 'ACCEPT_TERMS' => $lets_data->{ACCEPT_TERMS} unless param 'ACCEPT_TERMS';
%= select_field 'ACCEPT_TERMS' => @ACCEPT_TERMS_options, class => 'input'
<br></span> </p>
<p><span class=label>
%=l('lets_API_STATUS')
</span><span class=data>
% my @API_options = [['2' => '2']];
% param 'API' => $lets_data->{API} unless param 'API';
%= select_field 'API' => @API_options, class => 'input'
<br></span> </p>
<p><span class=label>
%=l('lets_KEYSIZE_STATUS')
</span><span class=data>
% my @keysize_options = [['2048' => '2048'], ['3072' => '3072'], ['4096' => '4096']];
% param 'keysize' => $lets_data->{keysize} unless param 'keysize';
%= select_field 'keysize' => @keysize_options, class => 'input'
<br></span> </p>
<p><span class=label>
%=l('lets_CONFIGUREMODE_STATUS')
</span><span class=data>
% my @configure_options = [['ALL' => 'all'], ['Domains' => 'domains'], ['HOSTS' => 'hosts'], ['NONE' => 'none']];
% param 'configure' => $lets_data->{configure} unless param 'configure';
%= select_field 'configure' => @configure_options, class => 'input'
<br></span> </p>
<p><span class=label>
%=l('lets_EMAIL')
</span><span class=data>
% param 'email' => $lets_data->{email} unless param 'email';
%=email_field 'email', class => 'emai8'
</span></p>
<span class='data'>
%= submit_button l('lets_Save'), class => 'action subm9'
</span>
%# Probably finally by a submit.
%end
</div>

View File

@@ -60,9 +60,10 @@
<span class=data>
%=text_field 'networkRouter'
</span><br><br>
<div class='center'>
%= submit_button "$btn", class => 'action'
</div>
<p>
<br>
%= submit_button "$btn", class => 'action'
</p>
%end
</div>

View File

@@ -49,9 +49,11 @@
</span><br><br>
%}
%= hidden_field localnetwork=>$localnetwork
<div class='center'>
%= submit_button "$btn", class => 'action'
</div>
<p>
<br>
%= submit_button "$btn", class => 'action'
</p>
%end
</div>

View File

@@ -37,10 +37,12 @@
%= $c->render_to_string(inline => l($ret{ret},$var1,$var2,$var3,$var4,$var5,$var6,$var7));
</div>
%}
<br><br>
<div class='center'>
<p>
<br>
%= submit_button "$btn", class => 'action'
</div>
</p>
% end
<br>

View File

@@ -5,7 +5,7 @@
<!-- <a href='#' id='tognav' class='menu-title'>NAVIGATION</a> -->
<div id='menunav'>
% my $cc = 1;
% my $cc = 200;
% foreach my $h (sort { ($nav{$a}{'WEIGHT'}/$nav{$a}{'COUNT'})
% <=> ($nav{$b}{'WEIGHT'}/$nav{$b}{'COUNT'}) } keys %nav) {
%
@@ -33,4 +33,4 @@
% }
</div>
</div>
</div>

View File

@@ -5,7 +5,7 @@
<!-- ><div><a href='#' id='togadm' class='menu-title'>ADMINISTRATION</a></div> -->
<div id='menuadm'>
% my $cc = 1;
% my $cc = 100;
% foreach my $h (sort { ($nav{$a}{'WEIGHT'}/$nav{$a}{'COUNT'})
% <=> ($nav{$b}{'WEIGHT'}/$nav{$b}{'COUNT'}) } keys %nav) {
<div><a href='#' class='section section-title'><%= $h %></a></div>
@@ -35,4 +35,4 @@
% }
</div>
</div>
</div>

View File

@@ -77,9 +77,11 @@
<span class=data>
%=text_field 'cmmnt'
</span><br><br>
<div class='center'>
%= submit_button "$btn", class => 'action'
</div>
<p>
<br>
%= submit_button "$btn", class => 'action'
</p>
%end
</div>

View File

@@ -57,9 +57,10 @@
%#}
%= hidden_field sport=>$sport
%= hidden_field proto=>$proto
<div class='center'>
%= submit_button "$btn", class => 'action'
</div>
<br>
%= submit_button "$btn", class => 'action'
</p>
%end
</div>

View File

@@ -18,8 +18,6 @@
% my $var5 = @vars[4];
% my $var6 = @vars[5];
%if ($ret{ret} eq "") {
%= $c->render_to_string(inline => l('pf_FIRST_PAGE_DESCRIPTION'));
%} elsif (index($ret{ret},"SUCCESS") != -1) {
@@ -33,21 +31,22 @@
%= $c->l($ret{ret},$var1,$var2,$var3,$var4,$var5,$var6);
</div>
%}
<br><br>
<div class='center'>
<p>
<br>
%= submit_button "$btn", class => 'action'
</div>
</p>
% end
<br>
% if ($empty){
<br>
%=l 'pf_NO_FORWARDS'
% } else {
<br>
%=l 'pf_SHOW_FORWARDS'
<br>
<br><br />
<table class="sme-border TableSort"><thead>
<tr>
<th class='sme-border'>
@@ -94,7 +93,15 @@
%= t td => (class => 'sme-border') => $allow
%= t td => (class => 'sme-border') => $cmmnt
<td class='sme-border'>
<a href="portforwardingd?CsrfDef=TOKEN&trt=DEL&sport=<%= $sport%>&proto=<%= $proto%>"><button class='sme-remove-button' title="<%=l('REMOVE')%>"><%=l('REMOVE') %></button></a>
%my $remove_text = l('REMOVE'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $actionRemove = qq{
% <button type='button' class='sme-remove-button' title='$remove_text'
% onclick="window.location.href='portforwardingd?CsrfDef=$csrf_token&trt=DEL&sport=$sport&proto=$proto'">
% $remove_text
% </button>
%};
<%= $c->render_to_string(inline => $actionRemove) %>
</td>
</tr>
% }
@@ -105,5 +112,4 @@
</table>
%= hidden_field 'trt' => $pf_datas->{trt}
</div>
</div>

View File

@@ -57,7 +57,18 @@
%= t td => (class => 'sme-border') => $printer->prop('Location')
%= t td => (class => 'sme-border') => $address
%= t td => (class => 'sme-border') => $remoteName
<td class='sme-border'><a href="printers2?CsrfDef=TOKEN&trt=DEL&printer=<%= $printer->key%>"><button class='sme-remove-button' title="<%=l('REMOVE')%>"><%=l('REMOVE') %></button></a></td>
<td class='sme-border'>
%my $remove_text = l('REMOVE'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $printer_name = $printer->key;
%my $actionRemove = qq{
% <button type='button' class='sme-remove-button' title='$remove_text'
% onclick="window.location.href='printers2?CsrfDef=$csrf_token&trt=DEL&&printer=$printer_name'">
% $remove_text
% </button>
%};
<%= $c->render_to_string(inline => $actionRemove) %>
</td>
</tr>
% }
</tbody>
@@ -66,4 +77,4 @@
</p>
</div>
</div>

View File

@@ -54,19 +54,35 @@
%= t td => (class => 'sme-border') => $pseudonym->key
%= t td => (class => 'sme-border') => $account
% my ($actionModify, $actionRemove) = '&nbsp;';
% if ($modifiable eq 'yes') {
% $actionModify = "<a href='pseudonyms2?CsrfDef=TOKEN&trt=UPD&pseudonym=" . $pseudonym->key . "'>" . "<button class='sme-modify-button' title=".l('MODIFY').">".l('MODIFY')."</button>" . "</a>";
% }
% if ($removable eq 'yes') {
% $actionRemove = "<a href='pseudonyms2?CsrfDef=TOKEN&trt=DEL&pseudonym=" . $pseudonym->key . "'>" . "<button class='sme-remove-button' title=".l('REMOVE').">".l('REMOVE')."</button>" . "</a>";
% }
<td class='sme-border'>
%my ($actionModify, $actionRemove) = '&nbsp;';
%if ($modifiable eq 'yes') {
%my $modify_text = l('MODIFY'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $pseudonyms_entry_name = $pseudonym->key; # pseudonyms_entry name extracted from the data structure
%$actionModify = qq{
% <button type='button' class='sme-modify-button' title='$modify_text'
% onclick="window.location.href='pseudonyms2?CsrfDef=$csrf_token&trt=UPD&pseudonym=$pseudonyms_entry_name'">
% $modify_text
% </button>
%};
%}
<td class='sme-border' style="min-width:15em">
<%= $c->render_to_string(inline => $actionModify) %>&nbsp;<%= $c->render_to_string(inline => $actionRemove) %>
</td>
</tr>
%if ($removable eq 'yes') {
%my $remove_text = l('REMOVE'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $pseudonyms_entry_name = $pseudonym->key; # pseudonyms_entry name extracted from the data structure
%$actionRemove = qq{
% <button type='button' class='sme-remove-button' title='$remove_text'
% onclick="window.location.href='pseudonyms2?CsrfDef=$csrf_token&trt=DEL&pseudonym=$pseudonyms_entry_name'">
% $remove_text
% </button>
%};
%}
<%= $c->render_to_string(inline => $actionModify) %> <%= $c->render_to_string(inline => $actionRemove) %>
</td>
</tr>
% }
</tbody>
</table>
@@ -75,5 +91,4 @@
</div>
</div>

View File

@@ -57,7 +57,18 @@
%= t td => (class => 'sme-border') => sprintf("%.2f", $bs / 1024 )
%= t td => (class => 'sme-border') => sprintf("%.2f", $bh / 1024 )
%= t td => (class => 'sme-border') => sprintf("%.2f", $bc / 1024 )
<td class='sme-border'><a href="quotad?CsrfDef=TOKEN&trt=UPD&user=<%= $user->key%>"><button class='sme-modify-button' title="<%=l('MODIFY')%>"><%=l('MODIFY') %></button></a></td>
<td class='sme-border'>
%my $modify_text = l('MODIFY'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $quota_user_name = $user->key; # quotas_entry name extracted from the data structure
%my $actionModify = qq{
% <button type='button' class='sme-modify-button' title='$modify_text'
% onclick="window.location.href='quotad?CsrfDef=$csrf_token&trt=UPD&user=$quota_user_name'">
% $modify_text
% </button>
%};
<%= $c->render_to_string(inline => $actionModify) %>
</td>
</tr>
% }
</tbody>
@@ -67,4 +78,4 @@
%= hidden_field 'trt' => $quo_datas->{trt}
</div>
</div>

View File

@@ -37,7 +37,7 @@
%= $ic
%=l 'quo_FILES'
%=l 'quo_OCCUPYING'
%= $bc
%= $c->toMB($bc)
%=l 'quo_MEGABYTES'
</p>
@@ -81,4 +81,4 @@
% end
</div>
</div>

View File

@@ -4,7 +4,7 @@
<div id='usermenu'>
<a href='#' id='toguser' class='section section-title'>Current User (<%= session 'username' %>)</a>
<div id='menuuser'>
% my $cc = 1;
% my $cc = 300;
% foreach my $h (sort { ($nav{$a}{'WEIGHT'}/$nav{$a}{'COUNT'})
% <=> ($nav{$b}{'WEIGHT'}/$nav{$b}{'COUNT'}) } keys %nav) {
<!-- div class='section'><%= $h %></div -->
@@ -29,4 +29,4 @@
% }
</div>
</div>
</div>

View File

@@ -59,28 +59,72 @@
%= t td => (class => 'sme-border') => "$first $last"
%= t td => (class => 'sme-border') => $vpnaccess
%= t td => (class => 'sme-border') => $fwd
% my ($actionModify, $actionLock, $actionResetPw, $actionRemove) = '&nbsp;';
% if ($username eq 'admin') {
% $actionModify = "<a href='useraccountsd?CsrfDef=TOKEN&trt=UPS&user=" . $username . "'>" . "<button class='sme-modify-button' title=".l("MODIFY").">".l("MODIFY")."</button></a>";
% $actionResetPw = "<a href='useraccountsd?CsrfDef=TOKEN&trt=PWS&user=" . $username . "'>" . "<button class='sme-password-button' title=".l("Reset-Password").">".l("Reset-Password")."</button></a>";
% } else {
% $actionModify = "<a href='useraccountsd?CsrfDef=TOKEN&trt=UPD&user=" . $username . "'>" . "<button class='sme-modify-button' title=".l("MODIFY").">".l("MODIFY")."</button></a>";
% if ($password_set ne 'yes') {
% $actionLock = l('ACCOUNT_LOCKED');
% $actionResetPw = "<a href='useraccountsd?CsrfDef=TOKEN&trt=PWD&user=" . $username . "'>" . "<button class='sme-password-button' style ='border-color:red;' title=".l("Reset-Password").">".l("Reset-Password")."</button></a>";
% } else {
% $actionLock = "<a href='useraccountsd?CsrfDef=TOKEN&trt=LCK&user=" . $username . "'>" . "<button class='sme-lock-button' title=".l('usr_LOCK_ACCOUNT').">".l("usr_LOCK_ACCOUNT")."</button></a>";
% $actionResetPw = "<a href='useraccountsd?CsrfDef=TOKEN&trt=PWD&user=" . $username . "'>" . "<button class='sme-password-button' title=".l("Reset-Password").">".l("Reset-Password")."</button></a>";
% }
% if ( $removable eq 'yes' ) {
% $actionRemove = "<a href='useraccountsd?CsrfDef=TOKEN&trt=DEL&user=" . $username . "'>" . "<button class='sme-remove-button' title=".l("REMOVE").">".l("REMOVE")."</button></a>";
% }
% }
<td class='sme-border' style="min-width:35em">
%my ($actionModify, $actionLock, $actionResetPw, $actionRemove) = '&nbsp;';
%my $modify_text = l('MODIFY'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $useraccounts_user_name = $user->key; # useraccountss_entry name extracted from the data structure
%my $password_text = l("PASSWORD_RESET");
%if ($username eq 'admin') {
%$actionModify = qq{
% <button type='button' class='sme-modify-button' title='$modify_text'
% onclick="window.location.href='useraccountsd?CsrfDef=$csrf_token&trt=UPS&user=$useraccounts_user_name'">
% $modify_text
% </button>
%};
%} else {
%$actionModify = qq{
% <button type='button' class='sme-modify-button' title='$modify_text'
% onclick="window.location.href='useraccountsd?CsrfDef=$csrf_token&trt=UPD&user=$useraccounts_user_name'">
% $modify_text
% </button>
%};
%}
%if ($password_set ne 'yes') {
%$actionLock = l('ACCOUNT_LOCKED');
%$actionResetPw = qq{
% <button type='button' class='sme-password-button unset' title="$password_text - currently unset" style = background:pink;
% onclick="window.location.href='useraccountsd?CsrfDef=$csrf_token&trt=PWD&ibay=$useraccounts_user_name'">
% $password_text
% </button>
%};
%} else {
%my $lock_text = l('ACCOUNT LOCKED'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%my $useraccounts_user_name = $user->key; # useraccountss_entry name extracted from the data structure
%$actionLock = qq{
% <button type='button' class='sme-lock-button' title='$lock_text'
% onclick="window.location.href='useraccountsd?CsrfDef=$csrf_token&trt=LCK&user=$useraccounts_user_name'">
% $lock_text
% </button>
%};
%$actionResetPw = qq{
% <button type='button' class='sme-password-button' title='$password_text'
% onclick="window.location.href='useraccountsd?CsrfDef=$csrf_token&trt=PWD&user=$useraccounts_user_name'">
% $password_text
% </button>
%};
%}
%if ( $removable eq 'yes' ) {
%my $remove_text = l('REMOVE'); # Localized text
%my $csrf_token = "TOKEN"; # CSRF token for security
%$actionRemove = qq{
% <button type='button' class='sme-remove-button' title='$remove_text'
% onclick="window.location.href='useraccountsd?CsrfDef=$csrf_token&trt=DEL&user=$useraccounts_user_name'">
% $remove_text
% </button>
%};
%}
% my $thisdomain = session 'SystemName';
% $thisdomain .= ".".session 'DomainName';
%# my $thisdomain = "localhost";
<td class='sme-border' style="min-width:35em">
<%= $c->render_to_string(inline => $actionModify) %>
<%= $c->render_to_string(inline => $actionResetPw) %>
<%= $c->render_to_string(inline => $actionLock) %>
<%= $c->render_to_string(inline => $actionRemove) %>
<a href="<%= "roundcubepanel/?url=https://".$thisdomain."/" %>roundcube?_user=<%= $username %>"><button class="sme-email-button" title="<%= l('EMAIL') %>"><%= l('EMAIL') %></button></a>
</td>
</tr>
% }
@@ -91,4 +135,4 @@
%= hidden_field 'trt' => $usr_datas->{trt}
</div>
</div>

View File

@@ -12,8 +12,8 @@
% if ( stash 'error' ) {
<br><div class=sme-error>
%= $c->render_to_string(inline => stash 'error')
</div>
%= $c->render_to_string(inline => stash 'error')
</div>
%}
<h1><%= $title%></h1>
@@ -29,5 +29,4 @@
%}
</div>
%end
%end

View File

@@ -52,12 +52,11 @@
<hr class='sectionbar' />
</p>
%}
<!-- percequ include 'partials/_rma_pptp' -->
<p><h2>
<h2>
%= $c->l('rma_VALIDFROM_TITLE', $c->l('rma_REMOTE_MANAGEMENT'));
</h2><br>
%=l 'rma_VALIDFROM_DESC'
@@ -86,7 +85,7 @@
%= t td => (class => 'sme-border') => $net
%= t td => (class => 'sme-border') => $mask
%= t td => (class => 'sme-border') => $numhosts
<td class='sme-border'><input type='checkbox' name='Remove_nets' value='<%= $net.'/'.$mask %>'> </td>
<td class='sme-border'><input type='checkbox' name='Remote_nets' value='<%= $net.'/'.$mask %>'> </td>
</tr>
% }
@@ -102,9 +101,6 @@
%= l('rma_NO_ENTRIES_YET');
</b>
%}
</p>
<p>
%=l 'rma_DESC_VALID_FROM_ENTRIES'
<br><br>
<span class=label>
@@ -118,11 +114,10 @@
</span><span class=data>
%= text_field 'ValidFromMask', class => 'input'
</span>
</p>
<hr class='sectionbar' />
<p><h2>
<h2>
%=l 'rma_TITLE_SSH'
</h2><br>
%=l 'rma_DESC_SSH'
@@ -158,11 +153,10 @@
%= text_field 'SshTCPPort', class => 'input'
</span>
<br>
</p>
<hr class='sectionbar' />
<p><h2>
<h2>
%=l 'rma_TITLE_FTP_ACCESS'
</h2><br>
%= $c->render_to_string(inline => $c->l('rma_DESC_FTP_ACCESS'));
@@ -186,11 +180,9 @@
%= select_field 'FtpPasswordAccess' => $c->passwordLogin_list(), class => 'input'
</span>
<br>
</p>
% my $mode = $c->get_telnet_mode();
% if ( $mode ne 'off') {
<p>
<hr class='sectionbar' />
<h2>
@@ -210,16 +202,13 @@
</span>
<br>
</p>
%}
<div class='center'>
<br>
%= submit_button "$btn", class => 'action'
</div>
% end
</div>
% end
% end

View File

@@ -0,0 +1,39 @@
% layout 'default', title => "Sme server 2 - roundcube";
% content_for 'module' => begin
<div id='roundcube' class='roundcube roundcube-panel'>
% if ($config->{debug} == 1) {
<p>
%= dumper $c->current_route
</p>
% }
% if ( stash 'error' ) {
<br><div class=sme-error>
%= $c->render_to_string(inline => stash 'error')
</div>
%}
<h1> roundcube - <%=$title %></h1><br>
<p>If the roundcube panel does not appear after logging in, then please check your password.</p><br />
% my $thisdomain = session 'SystemName';
% $thisdomain .= ".".session 'DomainName';
% my $url = $c->stash('modul');
% my $username = 'admin';
% if ($url =~ /[?&]_user=([^&]+)/) {
% $username = $1;
%}
<a href="<%= "https://".$thisdomain."/" %>roundcube?_user=<%= $username %>"><button class="sme-fullwindow1-button" width=20em title="<%= l('Full Window') %>"><%= l('Full Window') %></button></a>
% my $height = $c->stash('height') | '600px';
% if ($height !~ /px$/) { $height = $height.'px';}
% if ($url eq "") {
% $url = "https://".$thisdomain."/roundcube";
%}
<object id="roundcube" class="roundcube" data="<%=$url %>" style="width:99%;height:<%= $height %>;" title="<%= $c->stash('title') %>" type="text/html" ><%= $c->stash('title') %> not found</object>
</div>
%end

View File

@@ -66,9 +66,10 @@
</span>
<br><br></p>
<div class='center'>
%= submit_button "$btn", class => 'action'
</div>
<p>
<br>
%= submit_button "$btn", class => 'action'
</p>
% end

View File

@@ -79,9 +79,9 @@
%= hidden_field 'trt' => 'CONF'
<br>
<div class='center'>
<!--<div class='center'>-->
%= submit_button $c->l('SAVE'), class => 'action'
</div>
<!--</div>-->
% end

View File

@@ -47,9 +47,9 @@
%= hidden_field 'trt' => 'INST'
<br><br>
<div class='center'>
<!-- <div class='center'>-->
%= submit_button $c->l('yum_INSTALL_SOFTWARE'), class => 'action'
</div>
<!--</div>-->
% end

View File

@@ -34,9 +34,9 @@
%= hidden_field 'trt' => 'PSTU'
%= hidden_field 'reconf' => $yum_datas->{reconf}
<br>
<div class='center'>
<!-- <div class='center'>-->
%= submit_button "$btn", class => 'action'
</div>
<!--</div>-->
% end

View File

@@ -46,9 +46,9 @@
%= hidden_field 'trt' => 'REMO'
<br>
<div class='center'>
<!--<div class='center'>-->
%= submit_button $c->l('REMOVE'), class => 'action'
</div>
<!--</div>-->
% end

View File

@@ -33,9 +33,9 @@
%= hidden_field 'trt' => 'UPDT'
<br>
<div class='center'>
<!--<div class='center'>-->
%= submit_button $c->l('yum_INSTALL_UPDATES'), class => 'action'
</div>
<!--</div>-->
% end

0
root/var/log/smanager/.gitignore vendored Normal file
View File

View File

@@ -2,7 +2,7 @@ Summary: Sme server navigation module : manager 2
%define name smeserver-manager
Name: %{name}
%define version 11.0.0
%define release 1
%define release 31
Version: %{version}
Release: %{release}%{?dist}
License: GPL
@@ -12,7 +12,7 @@ Source1: visible.png
BuildRoot: /var/tmp/%{name}-%{version}-%{release}-buildroot
BuildArchitectures: noarch
BuildRequires: e-smith-devtools
BuildRequires: smeserver-devtools
#<Build tests>
#BuildRequires: perl >= 0:5.016
#BuildRequires: perl(Test::More)
@@ -22,9 +22,9 @@ BuildRequires: e-smith-devtools
#BuildRequires: perl(Net::Netmask) >= 1.9
#</Build tests>
Requires: e-smith-lib >= 1.18.0-26
Requires: e-smith-manager >= 2.4.0-22
Requires: e-smith-apache >= 2.6.0-19
Requires: smeserver-lib >= 1.18.0-26
Requires: smeserver-manager >= 2.4.0-22
Requires: smeserver-apache >= 2.6.0-19
Requires: smeserver-php >= 3.0.0-43
Requires: perl(Mojolicious) >= 7.56
Requires: perl(Mojolicious::Plugin::I18N) >= 1.6
@@ -35,6 +35,8 @@ Requires: perl(DBM::Deep) >= 2.0011-1
Requires: perl(Mojo::JWT) >= 0.08-1
Requires: mutt >= 1.5.21
Requires: smeserver-manager-jsquery >= 1.0
Requires: smeserver-lib >= 11.0
Requires: smeserver-certificates >= 11.0
#Requires: js-jquery > 2.2.4-3 (optional)
Provides: server-manager
@@ -49,6 +51,11 @@ This RPM contributes the navigation bars for the smeserver-manager. New Mojolici
%setup
%build
#extract the release number and drop it in to the version for SM2 footer.
sed -i "s/our \$VERSION = '[^']*'/our \$VERSION = '%{release}'/g" root/usr/share/smanager/lib/SrvMngr.pm
perl createlinks
# Force creation of potentially empty directories
@@ -108,6 +115,103 @@ true
%defattr(-,root,root)
%changelog
* Tue Dec 17 2024 Brian Read <brianr@koozali.org> 11.0.0-31.sme
- Edit html to avoid w3c html validation warnings [SME: 6278]
* Fri Dec 13 2024 Brian Read <brianr@koozali.org> 11.0.0-30.sme
- Add in letsencrypt panel, add requires for smeserver-lib and smeserver-certificates [SME: 12810]
* Tue Nov 26 2024 Brian Read <brianr@koozali.org> 11.0.0-29.sme
- Fix remoteaccess panel, reformat pm file and bring success panel into line with other similar panels [SME: 12747]
* Fri Oct 18 2024 Brian Read <brianr@koozali.org> 11.0.0-28.sme
- Add in emailsettings for port 25,465 and 587 [SME: 12750]
- Comment out change to localhost for roundcube in _user_list email icon setting [SME: 12751]
* Sun Oct 06 2024 Brian Read <brianr@koozali.org> 11.0.0-27.sme
- Add in change to _user_list.html.ep for access to roundcube email from useraccounts [SME: 12751]
* Fri Oct 04 2024 Brian Read <brianr@koozali.org> 11.0.0-26.sme
- Add in email link to roundcube from user accounts [SME: 12751]
* Wed Oct 02 2024 Brian Read <brianr@koozali.org> 11.0.0-25.sme
- Add in cursor change when save/submit pressed to indicate processing [SME: 12748]
* Wed Oct 02 2024 Brian Read <brianr@koozali.org> 11.0.0-24.sme
- Messed up build - finger trouble [SME: 12753]
* Wed Oct 02 2024 Brian Read <brianr@koozali.org> 11.0.0-23.sme
- Add release number to footer [SME: 12753]
* Tue Sep 24 2024 Jean-Philippe Pialasse <jpp@koozali.org> 11.0.0-22.sme
- fix typos, and tidy tabs [SME: 12744]
* Mon Sep 23 2024 Brian Read <brianr@koozali.org> 11.0.0-21.sme
- Remove both option for webmail [SME: 12744]
- Add in re-open DB for portforwarding and email settings.
* Mon Sep 23 2024 Jean-Philippe Pialasse <jpp@koozali.org> 11.0.0-20.sme
- webmail switch panel to use roundcube [SME: 12742]
- prevent browser from caching [SME: 12695]
* Thu Sep 05 2024 Brian Read <brianr@koozali.org> 11.0.0-19.sme
- Add in mojo plugin WithoutCache [SME: 12695]
* Sun Aug 25 2024 Brian Read <brianr@koozali.org> 11.0.0-18.sme
- Move flag to emojii from downloaded jpg. Fix singleton locale issue[SME: 12706]
* Thu Aug 22 2024 Brian Read <brianr@koozali.org> 11.0.0-17.sme
- Left Align Software Install panels Submit button [SME: 12727]
* Wed Aug 21 2024 Brian Read <brianr@koozali.org> 11.0.0-16.sme
- Typo uc DNF changed to lc dnf in Yum.pm [SME: 127245]
- Monitor dnf running using dnf status file
* Wed Aug 21 2024 Brian Read <brianr@koozali.org> 11.0.0-15.sme
- Migrate SM2 Software installer panel from use of yum to dnf [SME: 12718]
* Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-14.sme
- Version skipped due to operator error! [SME: <none> ]
* Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-13.sme
- Fix sysles.css template - overwrote it by mistake [SME: 12706]
- Also re-organised login and Legacy SM menus and help on top
* Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-12.sme
- correct positio of flag-icon [SME: 12706]
* Sat Jul 27 2024 Brian Read <brianr@koozali.org> 11.0.0-11.sme
- Add in flag icon indication of locale [SME: 12706]
* Fri Jul 26 2024 Brian Read <brianr@koozali.org> 11.0.0-10.sme
- fix navigation2.conf to more correctly translate menus [SME: 12714]
* Thu May 09 2024 Brian Read <brianr@koozali.org> 11.0.0-9.sme
- Add mojo logo to footer [SME: 12679]
- Fix default for HeaderWeight to avoid noise in logs if no Nav header in file
- Align buttons consistently [SME: 12680]
* Tue Apr 30 2024 Jean-Philippe Pialasse <jpp@koozali.org> 11.0.0-8.sme
- create dedicated log files and logrotate [SME: 12664]
* Tue Apr 30 2024 Brian Read <brianr@koozali.org> 11.0.0-7.sme
- Remove use of hel command and replace by call to BlockDevices lib [SME: 12644]
* Mon Apr 29 2024 Brian Read <brianr@koozali.org> 11.0.0-6.sme
- Update layout for table extras [SME: 12656]
* Sun Apr 28 2024 Brian Read <brianr@koozali.org> 11.0.0-5.sme
- Ibay create not getting into panel [SME: 12652]
* Tue Apr 23 2024 Brian Read <brianr@koozali.org> 11.0.0-4.sme
- add in Nav numbers for Legacypanels.pm and ignore it when generating nav menu [SME:12643]
* Thu Apr 04 2024 Brian Read <brianr@koozali.org> 11.0.0-3.sme
- Set license file to GPL2.0 [SME: 12577]
* Sat Mar 23 2024 Brian Read <brianr@koozali.org>11.0.0-2.sme
- Change Requires: e-smith- to Requires:smeserver-
* Sat Mar 23 2024 Brian Read <brianr@koozali.org>11.0.0-1.sme
- Update Release and Version to base version and 1st release for SME11 [SME: 12518]