Compare commits

..

251 Commits

Author SHA1 Message Date
Ilia Ross
25321b467b Update changelog 2024-08-11 21:10:43 +03:00
Ilia Ross
dc17b3cbe5 Fix changelog 2024-08-11 21:06:19 +03:00
Ilia Ross
a4621a800b Fix changelog 2024-08-11 21:01:33 +03:00
Jamie Cameron
97308e69aa changelog update 2024-08-11 07:42:09 -07:00
Jamie Cameron
86144e16f7 New version bump 2024-08-11 07:41:05 -07:00
Jamie Cameron
b18b9decd4 Fix schema page description 2024-08-11 03:48:02 -07:00
Jamie Cameron
90cd81893e Fix bugs in LDAP import 2024-08-11 03:42:06 -07:00
Jamie Cameron
9d7c3fdd9a Work on schema import support 2024-08-11 03:27:04 -07:00
Jamie Cameron
c0e36426bd Remove useless fixed spacing 2024-08-11 02:50:23 -07:00
Jamie Cameron
9dd678946d Use proper function to check status 2024-08-08 19:25:14 -07:00
Jamie Cameron
d440ba7f58 Let the user know why no rules are down 2024-08-08 19:24:10 -07:00
Jamie Cameron
090a769145 Use proper function 2024-08-08 19:21:34 -07:00
Jamie Cameron
bcec22b385 Merge branch 'master' of github.com:webmin/webmin 2024-08-08 19:20:43 -07:00
Jamie Cameron
dbfc621482 Add a monitor for firewalld https://github.com/virtualmin/virtualmin-gpl/issues/870 2024-08-08 19:16:00 -07:00
Ilia Ross
6bc70a7738 Add support for disk I/O in FreeBSD 2024-08-07 15:28:58 +03:00
Ilia Ross
f5b3f9cc1d Fix to use os_type for OS check
0ac51a83e9 (r145024453)
2024-08-06 12:21:19 +03:00
Ilia Ross
24055330d3 Fix build system 2024-08-04 17:03:41 +03:00
Ilia Ross
0ac51a83e9 Add an API to count processes 2024-08-03 17:05:56 +03:00
Ilia Ross
e517300fe0 Fix to display wildcard char next to dbs https://github.com/virtualmin/virtualmin-gpl/issues/723#issuecomment-2263713657 2024-08-02 15:22:21 +03:00
Ilia Ross
ae34d0ef86 Fix to unquote database name in view
https://github.com/virtualmin/virtualmin-gpl/issues/723#issuecomment-2262824643
2024-08-01 20:29:40 +03:00
Ilia Ross
8236fb2fd8 Add support to display tag, algo and digests in table #2245 2024-08-01 13:01:30 +03:00
Ilia Ross
f499c62da4 Update CHANGELOG.md 2024-08-01 00:52:57 +03:00
Ilia Ross
a51e3d0a22 Fix BIND service name is now named.service in Debian 12 and Ubuntu 24.04
[build]
2024-08-01 00:34:02 +03:00
Ilia Ross
e1398bf75b Version bump 2.202 2024-07-30 22:13:20 +03:00
Ilia Ross
ba26d2aac0 Merge pull request #2241 from bim-g/update_ui_print_header_documentation
[FIX] Add missing `title` parameter to `ui_print_header` method on the documentation
2024-07-30 05:12:35 +03:00
bim-g
7225ccab73 [FIX] Add missing title parameter to ui_print_header documentation 2024-07-30 01:02:54 +02:00
Ilia Ross
d224d0aafc Fix backup file naming to be consistent with Virtualmin 2024-07-28 23:46:38 +03:00
Ilia Ross
8220fef7e0 Fix to name downloaded backup file nicely #2239
E.g. webmin-backup-config-host.ubuntu24-pro.virtualmin.dev-2024-07-28-20-08.tgz
2024-07-28 20:11:55 +03:00
Jamie Cameron
1a658b1010 If given names are enabled, always add the needed class 2024-07-27 14:53:23 -07:00
Jamie Cameron
4c3b792adc LDAP config file param has moved to the ldap-client module 2024-07-27 14:40:18 -07:00
Jamie Cameron
19940bae86 Base may have a sub-entry for users and groups 2024-07-27 14:26:25 -07:00
Jamie Cameron
256178c6c3 sometimes LDAP connect fails with sigpipe 2024-07-26 21:04:55 -07:00
Jamie Cameron
2a43a870c2 Fix init script name 2024-07-26 19:09:02 -07:00
Jamie Cameron
615765b995 Check status from init script if possible 2024-07-26 19:06:16 -07:00
Jamie Cameron
6f7003965e Merge branch 'master' of github.com:webmin/webmin 2024-07-26 14:56:52 -07:00
Jamie Cameron
d8a7a583a3 Prevent duplication of systemd actions and init scripts https://github.com/webmin/webmin/issues/2227 2024-07-26 14:56:46 -07:00
Jamie Cameron
c51cc8f38a Merge pull request #2234 from webmin/dev/mysql-improve-operations-with-large-dbs
Fix to optimize getting table index structure for large databases
2024-07-26 14:22:58 -07:00
Ilia Ross
5210f623f3 Fix to use prepared statements 2024-07-26 21:11:05 +03:00
Jamie Cameron
ba4b65774e Merge branch 'master' of github.com:webmin/webmin 2024-07-26 10:20:51 -07:00
Jamie Cameron
b1d273c555 BIND 4 is ancient and shouldn't be shown by default https://github.com/webmin/webmin/issues/2232 2024-07-26 10:20:42 -07:00
Ilia Ross
b03f1b766f Fix to optimize getting table index stats for large tables 2024-07-26 19:56:45 +03:00
Ilia Ross
a9ed10401d Update changelog (progress) 2024-07-26 00:55:11 +03:00
Ilia Ross
253d85b6ee Fix setting webprefix for WebSocket URL
https://forum.virtualmin.com/t/after-update-webmin-2-200-cant-view-stat-history/128119/6?u=ilia
2024-07-26 00:41:40 +03:00
Jamie Cameron
0247b71fb7 Show full BIND version https://github.com/webmin/webmin/issues/2226 2024-07-24 14:02:00 -07:00
Jamie Cameron
fd819d83e8 New version bump 2024-07-23 21:58:01 -07:00
Jamie Cameron
8c5fcef916 Fix string for update logging 2024-07-23 21:57:32 -07:00
Jamie Cameron
c15bbca109 Separate comment column https://github.com/webmin/webmin/issues/2221 2024-07-23 21:52:24 -07:00
Jamie Cameron
c47c4b7ffd Merge branch 'master' of github.com:webmin/webmin 2024-07-23 20:12:17 -07:00
Jamie Cameron
8efa25eabf Add missing function 2024-07-23 20:12:06 -07:00
Ilia Ross
190bd58b1b Fix to clarify option name 2024-07-24 03:50:01 +03:00
Ilia Ross
d645dc9345 Update changelog for Webmin 2.201 2024-07-24 03:25:43 +03:00
Ilia Ross
963bb60c02 Fix to go directly to viewing logs on module load 2024-07-24 03:18:31 +03:00
Jamie Cameron
fa4e39ec9a Merge branch 'master' of github.com:webmin/webmin 2024-07-23 17:00:41 -07:00
Jamie Cameron
c1b45ff210 Add option to include compressed rotated logs in searches, and enable it by default, to maintain parity with the old sylog module 2024-07-23 17:00:34 -07:00
Ilia Ross
5cb103bde3 Revert "Fix to call exit after redirect"
This reverts commit e3a1fd849b.
2024-07-24 02:02:14 +03:00
Ilia Ross
7282348b7d Fix to use consistent download page 2024-07-24 00:20:58 +03:00
Ilia Ross
e3a1fd849b Fix to call exit after redirect 2024-07-24 00:20:47 +03:00
Jamie Cameron
1fb01aa46e Fix permissions 2024-07-23 13:50:19 -07:00
Jamie Cameron
779ebb4a63 Fix redirection to first log 2024-07-23 13:50:02 -07:00
Jamie Cameron
c391830670 Fix more cases where switch_to_unix_user isn't being passed the username 2024-07-22 16:48:28 -07:00
Jamie Cameron
c8c6c3e40f Merge branch 'master' of github.com:webmin/webmin 2024-07-22 16:11:41 -07:00
Jamie Cameron
c1f45d6d61 When running a command as a different user, the username needs to be passed to switch_to_unix_user so that all the secondary groups can be populated https://github.com/webmin/webmin/issues/2223 2024-07-22 16:11:37 -07:00
Ilia Ross
8804ba6529 Update CHANGELOG.md 2024-07-22 16:00:56 +03:00
Ilia Ross
11ae39081c Fix to try more simple patch command at first 2024-07-22 14:18:51 +03:00
Jamie Cameron
2751224d4d Really update version 2024-07-21 10:21:20 -07:00
Jamie Cameron
6fce9fa491 New version bump 2024-07-21 10:20:43 -07:00
Jamie Cameron
41fdb5dac2 Fix renumbering when adding a domain 2024-07-20 21:53:49 -07:00
Jamie Cameron
4ffca4597c Clean up group_to_dn function 2024-07-20 21:30:46 -07:00
Jamie Cameron
ecfc06d9c6 Preserve firstname and surname 2024-07-20 21:28:45 -07:00
Jamie Cameron
db55dde7ce Merge branch 'master' of github.com:webmin/webmin 2024-07-20 21:23:16 -07:00
Jamie Cameron
c6edd4b97d Code cleanups 2024-07-20 21:19:01 -07:00
Ilia Ross
8cd2dbae96 Fix to redirect to tabs only inside same module
https://forum.virtualmin.com/t/small-upgrade-error-maybe-wrong-url-on-button/127999?u=ilia
2024-07-21 02:37:32 +03:00
Jamie Cameron
8676a3fb21 Merge branch 'master' of github.com:webmin/webmin 2024-07-20 16:18:25 -07:00
Jamie Cameron
27339eb1bf Use my instead of local 2024-07-20 16:18:16 -07:00
Ilia Ross
e014926854 Update CHANGELOG.md for 2.200 2024-07-21 02:00:01 +03:00
Ilia Ross
a721f60f9c Fix to allow service-worker.js in unauth [build] 2024-07-20 15:57:40 +03:00
Jamie Cameron
46c76e13f9 Merge branch 'master' of github.com:webmin/webmin 2024-07-19 16:52:29 -07:00
Jamie Cameron
f72058306b COnfig option to show hostname and comment https://github.com/webmin/webmin.com/issues/18 2024-07-19 16:52:23 -07:00
Ilia Ross
a15446d3b1 Fix to simplify the code and use no globals [build] 2024-07-19 13:40:14 +03:00
Ilia Ross
fc9ce7f3dd Fix comment 2024-07-19 13:30:01 +03:00
Ilia Ross
72cd50a054 Fix to consider "F" as new theme name "Framed" not "Gray" 2024-07-19 13:13:53 +03:00
Ilia Ross
e307fb4dcd Fix to drop unnecessary option 2024-07-19 12:36:52 +03:00
Jamie Cameron
d631929194 Merge branch 'master' of github.com:webmin/webmin 2024-07-16 16:08:06 -07:00
Jamie Cameron
db9628e7eb Update MIME types for javascript and gzipped files 2024-07-16 16:08:01 -07:00
Jamie Cameron
2c04c04ce7 Merge pull request #2217 from webmin/dev/package-updates-always-show-sec
Fix to always show security updates button
2024-07-16 11:51:16 -07:00
Ilia Ross
a5301245d3 Fix to always show security updates button 2024-07-16 17:38:14 +03:00
Jamie Cameron
165af690c7 Log automatic package updates 2024-07-13 17:07:07 -07:00
Jamie Cameron
29da8ea3d0 Clarify what kind of update it is https://forum.virtualmin.com/t/security-updates-being-auto-installed-regardles-of-software-scheduled-upgrades-set-to-just-notify/127852 2024-07-12 17:22:19 -07:00
Jamie Cameron
73b7e62f13 Merge branch 'master' of github.com:webmin/webmin 2024-07-09 08:30:51 -07:00
Ilia Ross
76141ce22f Fix to use larger QR code [build] 2024-07-09 15:53:18 +03:00
Jamie Cameron
4b575b8168 Clarify comment 2024-07-08 22:55:44 -07:00
Ilia Ross
2b28521297 Fix to display correct return button 2024-07-08 21:03:40 +03:00
Ilia Ross
be767951ca Fix to have no block elements in header 2024-07-08 19:33:52 +03:00
Jamie Cameron
9960d6011f Update comment to match reality 2024-07-07 11:12:47 -07:00
Jamie Cameron
461bd30e2a Save last size and subset mode 2024-07-06 15:26:57 -07:00
Jamie Cameron
2f88a4eefb Follow default reuse option 2024-07-06 15:23:17 -07:00
Jamie Cameron
c9f368d264 Properly check all ServerAlias directives and ports 2024-07-06 15:12:08 -07:00
Jamie Cameron
0e24e8ac61 Merge branch 'master' of github.com:webmin/webmin 2024-07-05 10:32:21 -07:00
Jamie Cameron
1d0d25efac Don't add tab param twice https://sourceforge.net/p/webadmin/bugs/5648/ 2024-07-05 10:01:55 -07:00
Jamie Cameron
1c5d2d2bd7 Merge pull request #2211 from webmin/dev/preserve-file-acls
Add ability to preserve original file ACLs
2024-07-03 15:43:43 -07:00
Ilia Ross
77e809166c Fix to use backquote_command instead 2024-07-03 10:40:20 +03:00
Jamie Cameron
927a2c32d8 Show queue state in list 2024-07-02 21:36:05 -07:00
Jamie Cameron
4a3c6c4854 Merge branch 'master' of github.com:webmin/webmin 2024-07-02 21:21:27 -07:00
Jamie Cameron
37beab77ba Show mail queue directory 2024-07-02 21:21:21 -07:00
Ilia Ross
82f5284ffc Fix to use pipe handling data directly in memory
https://github.com/webmin/webmin/pull/2211#discussion_r1663042881
2024-07-02 22:48:40 +03:00
Ilia Ross
5f579e8ded Fix to invalidate OS EOL data on upgrade 2024-07-02 22:24:09 +03:00
Ilia Ross
4b66ac0be5 Add ability to preserve original file ACLs
https://github.com/webmin/authentic-theme/discussions/1511#discussioncomment-9913902
2024-07-02 20:50:19 +03:00
Jamie Cameron
e69fb75c8e Show the mail queue path 2024-07-01 21:33:22 -07:00
Jamie Cameron
ff8781c112 Merge branch 'master' of github.com:webmin/webmin 2024-07-01 21:15:04 -07:00
Jamie Cameron
0dd75db8d8 Don't wrap header lines 2024-07-01 21:09:17 -07:00
Jamie Cameron
05d01aeef3 Merge pull request #2207 from webmin/dev/patch-api
Add apply patch CLI API
2024-06-30 11:05:00 -07:00
Jamie Cameron
11f2bc20eb Merge branch 'master' of github.com:webmin/webmin 2024-06-30 10:07:08 -07:00
Jamie Cameron
52c3178b92 Add API to delete sections 2024-06-30 10:07:01 -07:00
Jamie Cameron
e3dec2222d Merge pull request #2209 from webmin/dev/separate-temps-collection-2208
Fix to separate drive and CPU temperatures collection #2208
2024-06-30 08:24:26 -07:00
Ilia Ross
05752faec0 Fix to separate drive and CPU temperatures collection #2208 2024-06-30 15:54:47 +03:00
Ilia Ross
7507433bf1 Fix to drop dependency from Term::ANSIColor 2024-06-30 11:41:41 +03:00
Ilia Ross
248cb719c0 Fix restart command depend on config dir 2024-06-29 23:32:15 +03:00
Ilia Ross
94b7fdf0ec Fix to escape params 2024-06-29 23:29:55 +03:00
Ilia Ross
d89f6411b6 Fix to use has_command API 2024-06-29 20:34:29 +03:00
Ilia Ross
01d08a3605 Fix to make patch API work directly from URL 2024-06-28 19:48:51 +03:00
Jamie Cameron
1cf3813fb6 Merge branch 'master' of github.com:webmin/webmin 2024-06-27 19:45:29 -07:00
Jamie Cameron
1216ae709b Stop showing and editing dnssec-lookaside https://github.com/webmin/webmin/issues/617 2024-06-27 19:45:21 -07:00
Ilia Ross
3d9497ff45 Fix command example 2024-06-28 01:51:02 +03:00
Ilia Ross
a6832450d1 Fix to restart Webmin when done 2024-06-28 01:38:28 +03:00
Ilia Ross
e41037388c Apply a patch to Webmin core or its modules from GitHub or a local file 2024-06-28 01:35:10 +03:00
Ilia Ross
a7b3af534b Fix to drop Threads module from recommended packages 2024-06-26 18:12:47 +03:00
Ilia Ross
87e006ceeb Add new API to verify session id 2024-06-26 14:39:23 +03:00
Ilia Ross
fbee8f0588 Add logging for active FTP conns 2024-06-20 20:04:19 +03:00
Jamie Cameron
e077b4da94 Start of work on support for requesting only a subset of hostnames 2024-06-19 22:05:22 -07:00
Jamie Cameron
38efad8265 Escape some inputs 2024-06-19 20:37:25 -07:00
Jamie Cameron
4d2a1fa084 Add spam folder name 2024-06-19 17:19:51 -07:00
Jamie Cameron
13b2eca3b1 Follow webmin code standards 2024-06-19 16:48:41 -07:00
Ilia Ross
aa4c3b1de6 Fix embedded styles margin 2024-06-19 16:55:25 +03:00
Ilia Ross
edaab4fd6f Fix embedded styles 2024-06-19 16:52:04 +03:00
Jamie Cameron
6fded0862c Merge pull request #2201 from webmin/dev/fix-last-command-match-freebsd
Fix listing last logins in FreeBSD
2024-06-18 16:16:37 -07:00
Ilia Ross
4006b0454e Fix to escape and not to truncate username 2024-06-18 23:51:19 +03:00
Ilia Ross
5d4ab58baa Fix the regex for last command on FreeBSD 2024-06-18 23:50:12 +03:00
Jamie Cameron
e6c7a60fe6 Merge pull request #2200 from webmin/dev/fix-last-command-regexes
Fix the regex to correctly match the output of the `last` command on contemporary systems
2024-06-18 13:38:21 -07:00
Ilia Ross
a75781d61a Fix the regex to correctly match the output of the last command on contemporary systems 2024-06-18 23:36:31 +03:00
Jamie Cameron
45348f5b02 Merge pull request #2199 from webmin/dev/last-dont-truncate-username
Fix not to truncate usernames
2024-06-18 11:33:01 -07:00
Ilia Ross
548c078813 Fix not to truncate usernames 2024-06-18 20:23:22 +03:00
Ilia Ross
76ccb2b7ed Fix support for Chrony in Debian systems 2024-06-17 15:09:42 +03:00
Ilia Ross
61d2081371 Add to support more passible options to systemd service file 2024-06-16 01:55:03 +03:00
Ilia Ross
458916b4d8 Fix to simplify make_date calls 2024-06-16 01:48:14 +03:00
Jamie Cameron
37451ad905 Merge pull request #2197 from vsc55/fix-2196
Fix metod detect Linux Gentoo.
2024-06-15 09:50:06 -07:00
Javier Pastor
9eec58a1f1 Fix metod detect Linux Gentoo. 2024-06-15 18:41:54 +02:00
Ilia Ross
178f527afa Fix to return an actual value 2024-06-15 16:50:04 +03:00
Jamie Cameron
cd1555b3e1 Merge branch 'master' of github.com:webmin/webmin 2024-06-12 16:53:02 -07:00
Jamie Cameron
2d7cfca67f Prevent duplicate also-notify and allow-transfer IPs 2024-06-12 16:52:50 -07:00
Jamie Cameron
e92a35b3ed Merge pull request #2195 from webmin/dev/xterm-acls-allow-not-enforce-sudo
Fix to allow disabling the enforcement of sudo-capable logins
2024-06-12 15:47:08 -07:00
Ilia Ross
e35efd0f00 Fix to always show the field 2024-06-13 01:36:41 +03:00
Ilia Ross
a12f385a5b Fix to consider user with the same name 2024-06-13 01:07:21 +03:00
Ilia Ross
5dc7cfafd7 Fix to allow disabling the enforcement of sudo-capable logins 2024-06-12 20:14:06 +03:00
Jamie Cameron
35aee74311 Merge pull request #2194 from webmin/dev/xterm-start-with-sudocapable
Fix to start with a sudo-capable user if possible
2024-06-11 18:19:05 -07:00
Ilia Ross
d04dfdf157 Fix to simplify the test 2024-06-12 01:20:29 +03:00
Ilia Ross
41f1adf0df Fix to start with a sudo-capable user if possible 2024-06-11 15:31:00 +03:00
Ilia Ross
1ae01bed8d Fix to support theme styling for embedded calendar 2024-06-10 16:34:29 +03:00
Ilia Ross
4a6f5d9a6a Fix not to load images by default and ask 2024-06-10 14:23:18 +03:00
Ilia Ross
bb3a4bc1e8 Fix font size consistency 2024-06-10 13:48:14 +03:00
Jamie Cameron
084c117547 Merge pull request #2193 from webmin/dev/embed-calendar
Add support for embedding calendar events inline in email messages
2024-06-09 18:48:18 -07:00
Ilia Ross
0221a092b9 Drop duplicate code
https://github.com/webmin/webmin/pull/2193#discussion_r1632362334
2024-06-09 21:16:52 +03:00
Ilia Ross
535d4173b3 Fix to factor out code to separate functions to be available in Usermin 2024-06-09 19:59:50 +03:00
Ilia Ross
20d481e96b Add further margin fixes 2024-06-09 19:13:52 +03:00
Ilia Ross
0256ee47f2 Fix block margin for perfect alignment 2024-06-09 16:16:52 +03:00
Ilia Ross
6af5ed6e2f Fix margin for inner content 2024-06-09 16:09:44 +03:00
Ilia Ross
abeff44b1a Add further improvements to TZs 2024-06-09 04:39:53 +03:00
Ilia Ross
35298efd8a Fix timezones 2024-06-09 04:14:32 +03:00
Ilia Ross
3fa687e716 Fix bugs 2024-06-09 03:49:43 +03:00
Ilia Ross
43fc057484 Add further indent improvements 2024-06-09 03:24:23 +03:00
Ilia Ross
70e9a1c00b Fix indentation 2024-06-09 03:14:50 +03:00
Ilia Ross
d21188c2ad Add improvements to mail frame interactions 2024-06-09 03:06:53 +03:00
Ilia Ross
a780103e2f Fix to improve calendar styles 2024-06-09 02:45:51 +03:00
Ilia Ross
4014293760 Fix to resize embedding iframe for content to fit on view details 2024-06-09 01:55:56 +03:00
Ilia Ross
ba3be31335 Fix to resize iframe if called by some elements from inside 2024-06-09 01:53:36 +03:00
Ilia Ross
adb3d0bb67 Revert "Fix to expose mail iframe resize function"
This reverts commit cd9bc8b7c4.
2024-06-09 01:42:12 +03:00
Ilia Ross
cd9bc8b7c4 Fix to expose mail iframe resize function 2024-06-09 01:16:21 +03:00
Ilia Ross
e1ebcf0506 Fix code to fit within an 80-character width 2024-06-09 01:06:27 +03:00
Ilia Ross
17a27dbe00 Fix to drop showing organizer time unless TZ is explicitly given 2024-06-09 00:48:36 +03:00
Ilia Ross
e36e943251 Fix to keep calendar cell always in right size 2024-06-09 00:31:39 +03:00
Ilia Ross
95ee1e2f2d Add support to embed iCalendar to email message 2024-06-08 23:52:59 +03:00
Ilia Ross
37cde80bbe Fix standard description to replace new lines to HTML break 2024-06-08 23:36:59 +03:00
Ilia Ross
45852664fe Add further fixes and improvements to the processor 2024-06-08 23:19:46 +03:00
Ilia Ross
00885b1f76 Fix location detection 2024-06-08 18:40:35 +03:00
Ilia Ross
cce8911f0f Add additional details to the object 2024-06-08 16:53:25 +03:00
Ilia Ross
3a151469c7 Add proper date parsing and storing extensive details about event 2024-06-08 16:47:08 +03:00
Ilia Ross
e3b94dc458 Fix summary match for strings like SUMMARY;LANGUAGE=fr-CA 2024-06-08 02:18:20 +03:00
Jamie Cameron
cde548ada3 Merge pull request #2192 from webmin/dev/websocket-url-proxy-rely
Set websocket URL depending on the proxy unless defined in config
2024-06-06 20:39:03 -07:00
Ilia Ross
00d0a89630 Set socket URL depending on the proxy unless defined in config 2024-06-07 01:15:27 +03:00
Ilia Ross
9c971202b3 Remove debug 2024-06-07 00:47:47 +03:00
Ilia Ross
2aa3bce4da Fix explicitly set module name from the caller 2024-06-07 00:35:41 +03:00
Ilia Ross
4103177d1e Fix dependencies [build] 2024-06-06 22:55:39 +03:00
Jamie Cameron
31b6cdc82b Merge branch 'master' of github.com:webmin/webmin 2024-06-06 08:34:03 -07:00
Jamie Cameron
fd8c634277 Zone key record might not exist https://forum.virtualmin.com/t/security-updates/127159 2024-06-06 08:33:34 -07:00
Ilia Ross
596ba13b1e Add logic to store iCalendars 2024-06-06 01:59:58 +03:00
Ilia Ross
5e684bf41b Add improvements to iCalendar parser 2024-06-05 03:34:33 +03:00
Jamie Cameron
356c8f7f53 Merge pull request #2191 from webmin/dev/websockets-funcs-are-global
Improve WebSockets API
2024-06-04 16:27:40 -07:00
Ilia Ross
185465351a Fix to use named loop variable 2024-06-05 00:07:44 +03:00
Ilia Ross
8d84e7313a Fix to call function properly 2024-06-04 23:54:13 +03:00
Ilia Ross
71e37adfed Add ability to clean all modules with websockets=1 on the .info 2024-06-04 19:55:25 +03:00
Ilia Ross
af912d9539 Add API to get WebSocket URL 2024-06-04 19:07:34 +03:00
Ilia Ross
5b31c7df84 Factor out WebSockets port and host options to global config 2024-06-04 18:43:34 +03:00
Ilia Ross
55b5939194 Move websocket functions to be always available 2024-06-04 15:48:06 +03:00
Jamie Cameron
00ddfd4d05 Also cleanup websockets 2024-06-03 18:42:31 -07:00
Jamie Cameron
2d23a3503e Fix spacing 2024-06-03 18:34:59 -07:00
Jamie Cameron
a838d11a26 No need for a loop to process a 1-element array 2024-06-03 18:29:56 -07:00
Jamie Cameron
5f28a28d8d Merge pull request #2189 from webmin/dev/icalendar-event-parser
Add support to parse calendar events files #2160
2024-06-03 16:05:49 -07:00
Ilia Ross
e13df24539 Fix to assign argument array before anything else 2024-06-04 00:54:55 +03:00
Ilia Ross
4f7924338d Add missing websockets-lib-funcs.pl file to the build #2190
[build]
2024-06-04 00:48:35 +03:00
Ilia Ross
3a1d609579 Add support to parse calendar events files 2024-06-03 20:58:38 +03:00
Jamie Cameron
e441427031 Merge pull request #2170 from webmin/dev/logviewer-custom-units
Add support for additional units in systemd log viewer
2024-06-01 09:57:19 -07:00
Ilia Ross
469857a41e Fix to use links as is
https://github.com/webmin/webmin/pull/2170#discussion_r1623004037
2024-06-01 18:37:28 +03:00
Ilia Ross
e47c82e7e8 Fix cron id format [build] 2024-06-01 15:32:43 +03:00
Ilia Ross
a0f6dd935c Fix to favour lexically scoped variable over global 2024-06-01 15:31:50 +03:00
Jamie Cameron
e302b706ec Add a default option for mynetworks_style https://github.com/webmin/webmin/issues/2174 2024-05-31 16:26:56 -07:00
Jamie Cameron
8c7fc88d51 Use more accurate wording https://github.com/webmin/webmin/issues/2174 2024-05-31 16:25:11 -07:00
Jamie Cameron
7b4d905eb6 Merge branch 'master' of github.com:webmin/webmin 2024-05-31 16:02:57 -07:00
Jamie Cameron
a1a6f669b2 Use a unique ID for webmin crons created in the same process at the same time https://forum.virtualmin.com/t/webmin-server-stauts/126983 2024-05-31 16:02:41 -07:00
Jamie Cameron
0298d884ef Merge pull request #2182 from webmin/dev/take-out-ws-lib-and-make-it-work-with-themes
Dev/take-out-ws-lib-and-make-it-work-with-themes
2024-05-31 13:40:31 -07:00
Ilia Ross
5a8b3467a1 Fix to consider themes using websockets too 2024-05-31 23:04:19 +03:00
Ilia Ross
17fb8304c3 Fix to take out WebSockets library 2024-05-31 22:58:27 +03:00
Jamie Cameron
5cd88dad43 Merge pull request #2181 from webmin/dev/fix-proftpd-mods-load
Fix how modules are loaded in ProFTPd
2024-05-31 12:41:50 -07:00
Ilia Ross
c15e7a5e5e Fix how modules are loaded in ProFTPd 2024-05-31 19:55:37 +03:00
Jamie Cameron
fad464be47 Merge pull request #2180 from webmin/dev/better-xterm-logging
Dev/better-xterm-logging
2024-05-31 08:57:39 -07:00
Ilia Ross
489db4c769 Fix to store logs in var directory 2024-05-31 16:54:36 +03:00
Ilia Ross
cc663af3df Fix to log username 2024-05-31 16:51:08 +03:00
Ilia Ross
0b58cd5197 Fix to print log nicely 2024-05-31 16:31:56 +03:00
Ilia Ross
dbd16c21cc Fix to drop extra new line [build] 2024-05-31 15:52:50 +03:00
Ilia Ross
8ddabb35b6 Fix test for ports below zero and put port number to error message 2024-05-31 15:50:34 +03:00
Ilia Ross
8476206da8 Merge pull request #2179 from webmin/dev/impove-status-module
Dev/impove-status-module
2024-05-31 13:37:18 +03:00
Ilia Ross
ca3362ee84 Fix to properly test fetched filtered content 2024-05-29 19:20:15 +03:00
Ilia Ross
e88ba87eae Add a message for progressive logs with no data 2024-05-29 17:38:28 +03:00
Ilia Ross
a420c7142f Fix to use hash for mapping since select names 2024-05-29 15:35:41 +03:00
Ilia Ross
6f37dc94bf Revert the change to hide logs from other modules yet
https://github.com/webmin/webmin/pull/2170#discussion_r1618145017
2024-05-29 11:30:53 +03:00
Ilia Ross
c59a200725 Fix functions name 2024-05-29 03:11:28 +03:00
Ilia Ross
e56aa7711c Add status handler function 2024-05-29 03:11:18 +03:00
Ilia Ross
b480b4caa3 Fix SPA themes have own control over onbeforeunload event 2024-05-29 01:37:43 +03:00
Ilia Ross
db456ad458 Add crucial calls abortion control 2024-05-29 01:11:53 +03:00
Ilia Ross
9513d85157 Fix to just always call it Filter 2024-05-28 22:59:45 +03:00
Ilia Ross
dccc3fb10e Fix to call check right away
https://github.com/webmin/webmin/pull/2170#discussion_r1616387257
2024-05-28 00:08:23 +03:00
Ilia Ross
bb7938a0f5 Add support for tailing logs in real time 2024-05-27 21:52:24 +03:00
Ilia Ross
8164480b48 Fix lines bug in journalctl 2024-05-27 18:08:57 +03:00
Ilia Ross
4155fdb4c5 Fix not to use bare words 2024-05-27 15:05:15 +03:00
Ilia Ross
19efd89c28 Fix bug when hiding controls 2024-05-27 14:53:01 +03:00
Ilia Ross
f911137624 Add module config and other buttons in case index page is bypassed 2024-05-27 14:40:06 +03:00
Ilia Ross
d4ac34e4b5 Fix to show right title when viewing journal 2024-05-27 14:39:23 +03:00
Ilia Ross
5323bda372 Fix to limit select width not to break the page on long systemd entries 2024-05-27 14:37:40 +03:00
Ilia Ross
1b1ac686e3 Fix to redirect straight to log view or show error 2024-05-27 13:57:27 +03:00
Ilia Ross
75e9323429 Rename the old logging system to "System Logs RS" to free up the name for actual systemd-journald 2024-05-27 13:47:10 +03:00
Ilia Ross
554b439bf8 Fix to drop redundant support for extra units 2024-05-27 00:56:42 +03:00
Ilia Ross
2f9a0b3f21 Add support for showing messages all units and filter by since
Fix numerous of other bugs:

  1. No `tac` for `journalctl` as there is a special `-r` flag
  2. No using tail for `journalctl`
2024-05-27 00:52:45 +03:00
Ilia Ross
cc2502737f Add support for additional units in systemd log viewer 2024-05-26 01:12:39 +03:00
170 changed files with 2706 additions and 735 deletions

View File

@@ -7,13 +7,13 @@ on:
jobs:
build:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
if: contains(github.event.head_commit.message, '[build]')
steps:
- uses: actions/checkout@v3
- uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: git tar gzip openssl curl openssh-client rpm perl libjson-pp-perl libdigest-sha-perl liblist-moreutils-perl libencode-detect-perl
packages: git tar gzip openssl curl openssh-client rpm perl libjson-pp-perl libdigest-sha-perl liblist-moreutils-perl libencode-detect-perl zstd
version: 1.0
- uses: szenius/set-timezone@v1.2
with:

View File

@@ -1,5 +1,43 @@
## Changelog
#### 2.202 (August 12, 2024)
* Add support for importing schemas to the LDAP Server module
* Add support for displaying disk and network I/Os in FreeBSD on the dashboard
* Fix to automatically set the WebSocket URL webprefix correctly
* Fix to name downloaded backup file nicely in Backup Configuration Files module [#2239](https://github.com/webmin/webmin/issues/2239)
* Fix to optimize getting table index stats for large tables in MySQL/MariaDB module [pull#2234](https://github.com/webmin/webmin/pull/2234)
* Fix duplication of _systemd_ actions and init scripts [#2227](https://github.com/webmin/webmin/issues/2227)
* Fix BIND service name for Debian 12 and Ubuntu 24.04
* Update the Authentic theme to the latest version with various fixes and improvements
#### 2.201 (July 24, 2024)
* Fix real-time monitoring not updating graphs in the Dashboard [#2222](https://github.com/webmin/webmin/issues/2222)
* Fix Terminal module to work correctly with _sudo_-capable users [#2223](https://github.com/webmin/webmin/issues/2223)
#### 2.200 (July 21, 2024)
* Add support for blocking a given IP temporarily or permanently in the FirewallD module
* Add support for parsing iCalendar event files in the Mailbox module
* Add support for tailing logs in real time in System Logs module
* Add ability to preserve original file ACLs when writing files [webmin/authentic-theme#1511](https://github.com/webmin/authentic-theme/discussions/1511#discussioncomment-9913902)
* Add a `patch` sub-command to the `webmin` command for easy application of patches
* Add a config option to display hostname and comment in the DHCP Server module [#2221](https://github.com/webmin/webmin/issues/2221)
* Add support for ED25519 and ED448 algorithms in BIND DNS module for DNSSEC
* Add support for larger ranger of authentication methods in Dovecot module
* Add improved support for displaying last logins in the Users and Groups module
* Fix to prevent duplicate `also-notify` and `allow-transfer` IPs in the BIND DNS module
* Fix issues with Terminal module to correct text display problems in editor mode
* Fix to store Terminal module logs in the `/var/webmin` directory
* Fix to display the Spam folder nicely in the Mailbox module
* Fix how modules are loaded in ProFTPd module
* Fix support for the Chrony service on Debian systems in the System Time module
* Fix to use static routes to set the default gateway in Network Configuration module
* Fix to correctly invalidate EOL cache on re-checks [#2139](https://github.com/webmin/webmin/issues/2139)
* Fix to change default monitor name based on database used MariaDB vs MySQL [#2139](https://github.com/virtualmin/virtualmin-gpl/issues/798)
* Fix to disable manual upgrades for systems installed from the repository
* Fix to preserve Webmin service state during package upgrades [#2133](https://github.com/webmin/webmin/issues/2133)
* Change to enforce _sudo_-capable logins as themselves in the Terminal module [docs/modules/terminal](https://webmin.com/docs/modules/terminal/#about)
* Rename "System Logs" module to "System Logs RS" and "System Logs Viewer" to "System Logs" for clarity
#### 2.111 (April 16, 2024)
* Fix EOL detection for unreleased Linux distributions

File diff suppressed because one or more lines are too long

View File

@@ -3,6 +3,7 @@
use strict;
use warnings;
use POSIX qw(strftime);
no warnings 'redefine';
no warnings 'uninitialized';
require './backup-config-lib.pl';
@@ -59,7 +60,12 @@ print &ui_tabs_end_tab();
# Show immediate form
print &ui_tabs_start_tab("tab", "backup");
print &ui_form_start("backup.cgi/backup.tgz", "post");
my $filename = 'webmin-backup-config-on-';
my $hostname = &get_system_hostname();
$hostname =~ s/\./-/g;
$filename .= $hostname;
$filename .= "-".strftime("%Y-%m-%d-%H-%M", localtime);
print &ui_form_start("backup.cgi/$filename.tgz", "post");
print &ui_table_start($text{'index_header'}, undef, 2);
my @dmods = split(/\s+/, $config{'mods'} || "");

164
bin/patch Executable file
View File

@@ -0,0 +1,164 @@
#!/usr/bin/env perl
# patch - Apply a patch to Webmin core or its modules from GitHub or a local file
use strict;
use warnings;
use 5.010;
use Getopt::Long qw(:config permute pass_through);
use Pod::Usage;
use File::Basename;
use Cwd qw(cwd);
my %opt;
GetOptions(
'help|h' => \$opt{'help'},
'config|c=s' => \$opt{'config'},
);
pod2usage(0) if ($opt{'help'});
# Get Webmin path
my $path = cwd;
my $lib = "web-lib-funcs.pl";
if (!-r "$path/$lib") {
$path = dirname(dirname($0));
if (!-r "$path/$lib") {
$path = $path = Cwd::realpath('..');
}
}
# Init core
my $config_dir = $opt{'config'} || '/etc/webmin';
$ENV{'WEBMIN_CONFIG'} = $config_dir;
push(@INC, $path);
eval 'use WebminCore';
init_config();
# Check if curl is installed
if (!has_command('curl')) {
print "\"curl\" command is not installed\n";
exit 1;
}
# Check if git is installed
if (!has_command('patch')) {
if (!has_command('git')) {
print "Neither \"patch\" nor \"git\" commands are installed\n";
exit 1;
}
}
# Get patch URL or file
my $patch = $ARGV[0];
# Params check
if (!$patch) {
pod2usage(0);
exit 1;
}
# Patch check
if ($patch !~ /^https?:\/\//) {
if (!-r $patch) {
print "Patch file $patch doesn't exist\n";
exit 1;
}
}
elsif ($patch =~ /^https?:\/\/(github|gitlab)\.com/ &&
$patch !~ /\.patch$/ && $patch !~ /\.diff$/) {
$patch .= '.patch';
}
# Parse module name from URL
my $module = "";
if ($patch =~ m{https://(github|gitlab)\.com/[^/]+/([^/]+)/commit/[^/]+}) {
$module = $2;
$module = "" if ($2 eq 'webmin');
# Special handling for some modules
$module = $module =~ /^virtualmin-pro$/ ?
'virtual-server/pro' :
'virtual-server'
if $module =~ /^virtualmin-(gpl|pro)$/;
}
# Check if module exists
if (!-d "$path/$module") {
print "Module $module doesn't exist\n";
exit 1;
}
# Download command or cat patch file
my $cmd;
if ($patch =~ /^https?:\/\//) {
$cmd = "curl -s @{[quotemeta($patch)]}";
chdir "$path/$module";
}
else {
$cmd = "cat @{[quotemeta($patch)]}";
}
# Apply patch using Patch or Git command
my $output;
if (has_command('patch')) {
$output = `$cmd 2>&1 | patch -p1 --verbose 2>&1`;
if ($output !~ /succeeded/i) {
print "Patch failed: $output\n";
exit 1;
}
} else {
$output = `$cmd 2>&1 | git apply --reject --verbose --whitespace=fix 2>&1`;
if ($output !~ /applied patch.*?cleanly/i) {
print "Patch failed: $output\n";
exit 1;
}
}
print "Patch applied successfully to:\n";
print " $1\n" while $output =~ /^(?|Applied patch\s+(\S+)|patching file\s+(\S+))/mg;
system("$config_dir/restart");
=pod
=head1 NAME
patch
=head1 DESCRIPTION
Apply a patch to Webmin core or its modules from GitHub or a local file.
=head1 SYNOPSIS
webmin patch patch-url/file
=head1 OPTIONS
=over
=item --help, -h
Give this help list.
=item --config, -c
Specify the full path to the Webmin configuration directory. Defaults to
C</etc/webmin>
Examples of usage:
Apply a patch from a URL.
- webmin patch https://github.com/webmin/webmin/commit/e6a2bb15b0.patch
- webmin patch https://github.com/virtualmin/virtualmin-gpl/commit/f4433153d
Apply a patch from local file.
- cd /usr/libexec/webmin/virtual-server/pro &&
webmin patch /root/virtualmin-pro/patches/patch-1.patch
=back
=head1 LICENSE AND COPYRIGHT
Copyright 2024 Ilia Ross <ilia@virtualmin.com>

View File

@@ -1988,6 +1988,8 @@ if (@transfer) {
}
}
if (@notify) {
my %done;
@notify = grep { !$done{$_->{'name'}}++ } @notify;
my $also = { 'name' => 'also-notify',
'type' => 1,
'members' => \@notify};
@@ -1996,6 +1998,8 @@ if (@notify) {
'values' => [ 'yes' ] });
}
if (@transfer) {
my %done;
@transfer = grep { !$done{$_->{'name'}}++ } @transfer;
my $allow = { 'name' => 'allow-transfer',
'type' => 1,
'members' => \@transfer };

View File

@@ -17,7 +17,6 @@ $access{'defaults'} || &error($text{'trusted_ecannot'});
my $conf = &get_config();
my $options = &find("options", $conf);
my $mems = $options->{'members'};
my @dlv = &find("dnssec-lookaside", $mems);
my $tkeys = &find("trusted-keys", $conf);
$tkeys ||= { 'members' => [ ] };
@@ -38,33 +37,6 @@ if (&supports_dnssec_client() == 2) {
$text{'default'}, undef);
}
# Trusted DLVs (obsolete)
if (@dlv) {
my @dtable = ( );
my $i = 0;
foreach my $d (@dlv, { 'values' => [ '.' ] }) {
my $dlv = $d->{'values'}->[0];
$dlv = "" if ($dlv eq ".");
push(@dtable, [
&ui_opt_textbox("anchor_$i", $d->{'values'}->[2],
30, $text{'trusted_none'}),
&ui_opt_textbox("dlv_$i", $dlv, 20,
$text{'trusted_root'}) ]);
$i++;
}
print &ui_table_row($text{'trusted_dlvs'},
&ui_radio("dlv_auto",
@dlv == 0 ? 2 :
@dlv == 1 && $dlv[0]->{'values'}->[0] eq 'auto' ? 1 : 0,
[ [ 1, $text{'trusted_dlvs1'} ],
[ 2, $text{'trusted_dlvs2'} ],
[ 0, $text{'trusted_dlvs0'} ] ])."<br>\n".
&ui_columns_table([ $text{'trusted_anchor'},
$text{'trusted_dlv'} ],
undef,
\@dtable), 3);
}
# Trusted keys
if (@{$tkeys->{'members'}}) {
my @ktable = ( );

View File

@@ -0,0 +1,50 @@
soa_style=1
named_path=/usr/sbin/named
named_conf=/etc/bind/named.conf
show_list=1
records_order=0
max_zones=50
rev_def=0
support_aaaa=1
allow_comments=0
allow_wild=1
allow_long=0
master_ttl=1
whois_cmd=whois
short_names=0
updserial_def=0
updserial_on=1
updserial_man=1
ndc_cmd=ndc
forwardzonefilename_format=ZONE.hosts
reversezonefilename_format=ZONE.rev
rev_must=0
ipv6_mode=1
allow_underscore=1
by_view=0
confirm_zone=1
confirm_rec=0
no_chroot=0
relative_paths=0
rndc_cmd=rndc
pid_file=/var/run/named/named.pid
zones_file=/etc/bind/named.conf.local
master_dir=/var/lib/bind
slave_dir=/var/lib/bind
no_pid_chroot=0
soa_start=0
rndc_conf=/etc/bind/rndc.conf
rndcconf_cmd=rndc-confgen
largezones=0
checkzone=named-checkzone
keygen=dnssec-keygen
signzone=dnssec-signzone
checkconf=named-checkconf
other_slaves=1
force_random=0
spf_record=0
dnssec_info=1
start_cmd=systemctl start named.service
stop_cmd=systemctl stop named.service
restart_cmd=systemctl reload named.service
dnssec_period=21

View File

@@ -0,0 +1,50 @@
soa_style=1
named_path=/usr/sbin/named
named_conf=/etc/bind/named.conf
show_list=1
records_order=0
max_zones=50
rev_def=0
support_aaaa=1
allow_comments=0
allow_wild=1
allow_long=0
master_ttl=1
whois_cmd=whois
short_names=0
updserial_def=0
updserial_on=1
updserial_man=1
ndc_cmd=ndc
forwardzonefilename_format=ZONE.hosts
reversezonefilename_format=ZONE.rev
rev_must=0
ipv6_mode=1
allow_underscore=1
by_view=0
confirm_zone=1
confirm_rec=0
no_chroot=0
relative_paths=0
rndc_cmd=rndc
pid_file=/var/run/named/named.pid
zones_file=/etc/bind/named.conf.local
master_dir=/var/lib/bind
slave_dir=/var/lib/bind
no_pid_chroot=0
soa_start=0
rndc_conf=/etc/bind/rndc.conf
rndcconf_cmd=rndc-confgen
largezones=0
checkzone=named-checkzone
keygen=dnssec-keygen
signzone=dnssec-signzone
checkconf=named-checkconf
other_slaves=1
force_random=0
spf_record=0
dnssec_info=1
start_cmd=systemctl start bind9.service
stop_cmd=systemctl stop bind9.service
restart_cmd=systemctl reload bind9.service
dnssec_period=21

View File

@@ -0,0 +1,50 @@
soa_style=1
named_path=/usr/sbin/named
named_conf=/etc/bind/named.conf
show_list=1
records_order=0
max_zones=50
rev_def=0
support_aaaa=1
allow_comments=0
allow_wild=1
allow_long=0
master_ttl=1
whois_cmd=whois
short_names=0
updserial_def=0
updserial_on=1
updserial_man=1
ndc_cmd=ndc
forwardzonefilename_format=ZONE.hosts
reversezonefilename_format=ZONE.rev
rev_must=0
ipv6_mode=1
allow_underscore=1
by_view=0
confirm_zone=1
confirm_rec=0
no_chroot=0
relative_paths=0
rndc_cmd=rndc
pid_file=/var/run/named/named.pid
zones_file=/etc/bind/named.conf.local
master_dir=/var/lib/bind
slave_dir=/var/lib/bind
no_pid_chroot=0
soa_start=0
rndc_conf=/etc/bind/rndc.conf
rndcconf_cmd=rndc-confgen
largezones=0
checkzone=named-checkzone
keygen=dnssec-keygen
signzone=dnssec-signzone
checkconf=named-checkconf
other_slaves=1
force_random=0
spf_record=0
dnssec_info=1
start_cmd=systemctl start named.service
stop_cmd=systemctl stop named.service
restart_cmd=systemctl reload named.service
dnssec_period=21

View File

@@ -40,6 +40,7 @@ if (@keyrecs) {
my $kt = $key->{'ksk'} ? 'ksk' : 'zone';
my ($keyrec) = grep { $_->{'values'}->[0] ==
($key->{'ksk'} ? 257 : 256) } @keyrecs;
next if (!$keyrec);
my $keyline = format_dnssec_public_key(
join(" ", $keyrec->{'name'}, $keyrec->{'class'},
$keyrec->{'type'}, @{$keyrec->{'values'}}));
@@ -67,8 +68,28 @@ if (@keyrecs) {
my $ds = &get_ds_record($zone);
if ($ds) {
print $text{'zonekey_ds'},"<br>\n";
print &ui_textarea("ds", join("\n".$desc, split(/$desc/, $ds)), 2, 80, "off", 0,
# Split DS records in string into a list
my @ds = split(/\s(?=\S+\.\s+\d+\s+IN\s+DS\s+\d+\s+
\d+\s+\d+\s+[0-9A-Fa-f]{16,})/x, $ds);
print &ui_textarea("ds", join("\n", @ds), 2, 80, "off", 0,
"readonly style='width:90%'"),"<br>\n";
print &ui_columns_start([
$text{'zonekey_ds_keytag'},
$text{'zonekey_ds_alg'},
$text{'zonekey_ds_type'},
$text{'zonekey_ds_digest'},
]);
foreach my $r (@ds) {
if ($r =~ /
\bDS\s+(?<key_tag>\d+)\s+(?<algorithm>\d+)\s+
(?<digest_type>\d+)\s+
(?<digest>[0-9A-Fa-f]+)\b/x) {
print &ui_columns_row([
$+{key_tag}, $+{algorithm},
$+{digest_type}, $+{digest}]);
}
}
print &ui_columns_end();
}
# Offer to disable

View File

@@ -68,7 +68,7 @@ my $chroot = &get_chroot() || "";
&restart_links().'<br>'.
&help_search_link("bind", "doc", "google"), undef, undef,
&text($chroot eq "/" || !$chroot ? 'index_version' : 'index_chroot',
$bind_version, "<tt>$chroot</tt>"));
&get_bind_version(), "<tt>$chroot</tt>"));
# If the named.conf file does not exist, offer to create it
if ($need_create) {

View File

@@ -1282,6 +1282,10 @@ zonekey_private=Private key details :
zonekey_privatefile=Private key file : $1
zonekey_algorithm=DNSSEC algorithm : $1
zonekey_ds=DS record for parent zone :
zonekey_ds_keytag=Key tag
zonekey_ds_alg=Algorithm
zonekey_ds_type=Digest type
zonekey_ds_digest=Digest string
zonekey_expandksk=Show public and private key-signing-key details ..
zonekey_expandzone=Show public and private zone-key details ..
zonekey_noprivate=However, Webmin could not find the private key associated with the zone, and so will not be able to re-sign it.

View File

@@ -24,46 +24,6 @@ if (&supports_dnssec_client() == 2) {
&save_choice("dnssec-validation", $options, 1);
}
# Save DLV zones
if (defined($in{'dlv_auto'})) {
my @dlvs = ( );
if ($in{'dlv_auto'} == 1) {
# Automatic mode
push(@dlvs, { 'name' => 'dnssec-lookaside',
'values' => [ 'auto' ] });
}
elsif ($in{'dlv_auto'} == 0) {
# Listed zones
my $dlv;
for(my $i=0; defined($in{"anchor_$i"}); $i++) {
if (!$in{"anchor_${i}_def"}) {
$in{"anchor_$i"} =~ /^[a-z0-9\.\-\_]+$/ ||
&error(&text('trusted_eanchor', $i+1));
$in{"anchor_$i"} .= "."
if ($in{"anchor_$i"} !~ /\.$/);
if ($in{"dlv_${i}_def"}) {
$dlv = ".";
}
else {
$in{"dlv_$i"} =~ /^[a-z0-9\.\-\_]+$/ ||
&error(&text('trusted_edlv', $i+1));
$dlv = $in{"dlv_$i"};
$dlv .= "." if ($dlv !~ /\.$/);
}
push(@dlvs, { 'name' => 'dnssec-lookaside',
'values' => [
$dlv, "trust-anchor",
$in{"anchor_$i"} ] });
}
}
}
elsif ($in{'dlv_auto'} == 2) {
# None
@dlvs = ( );
}
&save_directive($options, "dnssec-lookaside", \@dlvs, 1);
}
# Save trusted keys
if (defined($in{'zone_0'})) {
my @keys = ( );

View File

@@ -21,7 +21,7 @@ if ($in{'source'} == 0) {
if (!$in{'local'})
{ &install_error($text{'download_elocal'}); }
if (!-r $in{'local'})
{ &install_error(&text('download_elocal2', $in{'local'})); }
{ &install_error(&text('download_elocal2', &html_escape($in{'local'}))); }
$source = $in{'local'};
@pfile = ( $in{'local'} );
$need_unlink = 0;
@@ -91,8 +91,9 @@ elsif ($in{'source'} == 3) {
$i = 0;
@fallback = ( );
foreach $yum (@cpanyum) {
print &text('download_yum', "<tt>$cpan[$i]</tt>",
"<tt>$yum->{'package'}</tt>"),"<br>\n";
print &text('download_yum',
"<tt>".&html_escape($cpan[$i])."</tt>",
"<tt>".&html_escape($yum->{'package'})."</tt>"),"<br>\n";
print "<ul>\n";
@got = &software::update_system_install(
$yum->{'package'});
@@ -154,7 +155,8 @@ elsif ($in{'source'} == 3) {
# Fail if any modules are missing from CPAN
for($i=0; $i<@cpan; $i++) {
push(@missing, "<tt>$cpan[$i]</tt>") if (!$source[$i]);
push(@missing, "<tt>".&html_escape($cpan[$i])."</tt>")
if (!$source[$i]);
}
if ($in{'missingok'}) {
@@ -167,11 +169,12 @@ elsif ($in{'source'} == 3) {
}
}
@cpan || &install_error(&text('download_ecpan',
join(" ", @missing)));
&html_escape(join(" ", @missing))));
}
elsif (@missing) {
# Fail due to missing modules
&install_error(&text('download_ecpan', join(" ", @missing)));
&install_error(&text('download_ecpan',
&html_escape(join(" ", @missing))));
}
$source = join("<br>", @source);
@@ -192,14 +195,16 @@ elsif ($in{'source'} == 3) {
&ftp_download($host, $file, $pfile, \$error,
\&progress_callback);
}
else { &install_error(&text('download_eurl', $m)); }
else {
&install_error(&text('download_eurl',&html_escape($m)));
}
&install_error($error) if ($error);
push(@pfile, $pfile);
}
$need_unlink = 1;
}
else {
&error("Unknown source mode $in{'source'}");
&error("Unknown source mode ".&html_escape($in{'source'}));
}
# Check if the file looks like a perl module
@@ -287,7 +292,7 @@ foreach $d (@dirs) {
close(MAKEFILE);
push(@allreqs, @prereqs);
}
system("rm -rf $mtemp");
&unlink_file($mtemp);
# Work out which pre-requesites are missing
@allreqs = &unique(@allreqs);

View File

@@ -1567,28 +1567,31 @@ if (!$gconfig{'tempdelete_days'}) {
print STDERR "Temp file clearing is disabled\n";
return;
}
# Cleanup files in /tmp/.webmin
if ($gconfig{'tempdir'} && !$gconfig{'tempdirdelete'}) {
print STDERR "Temp file clearing is not done for the custom directory $gconfig{'tempdir'}\n";
return;
}
local $tempdir = &transname();
$tempdir =~ s/\/([^\/]+)$//;
if (!$tempdir || $tempdir eq "/") {
$tempdir = "/tmp/.webmin";
}
local $cutoff = time() - $gconfig{'tempdelete_days'}*24*60*60;
opendir(DIR, $tempdir);
foreach my $f (readdir(DIR)) {
next if ($f eq "." || $f eq "..");
local @st = lstat("$tempdir/$f");
if ($st[9] < $cutoff) {
&unlink_file("$tempdir/$f");
else {
local $tempdir = &transname();
$tempdir =~ s/\/([^\/]+)$//;
if (!$tempdir || $tempdir eq "/") {
$tempdir = "/tmp/.webmin";
}
}
closedir(DIR);
local $cutoff = time() - $gconfig{'tempdelete_days'}*24*60*60;
opendir(DIR, $tempdir);
foreach my $f (readdir(DIR)) {
next if ($f eq "." || $f eq "..");
local @st = lstat("$tempdir/$f");
if ($st[9] < $cutoff) {
&unlink_file("$tempdir/$f");
}
}
closedir(DIR);
}
# Delete stale lock files
my $lockdir = $var_directory."/locks";
opendir(DIR, $lockdir);
foreach my $f (readdir(DIR)) {
@@ -1600,6 +1603,11 @@ foreach my $f (readdir(DIR)) {
}
}
closedir(DIR);
# Cleanup old websockets
foreach (&get_miniserv_websockets_modules()) {
&cleanup_miniserv_websockets(undef, $_);
}
}
=head2 list_cron_files()

View File

@@ -8,7 +8,7 @@ lease_refresh=Seconds between refreshing lease list,3,Never
show_ip=Show IP addresses for hosts?,1,1-Yes,0-No
show_mac=Show MAC addresses for hosts?,1,1-Yes,0-No
group_name=Show group names as,1,1-<tt>domain&#45;name</tt> option,0-Name or member count,2-Description
desc_name=Show other object descriptions instead of names?,1,1-Yes,0-No
desc_name=Show descriptions instead of names?,1,1-Description only,0-Name only,2-Both name and description
display_max=Maximum number of subnets and hosts to display,3,Unlimited
add_file=Add new subnets&#44; hosts and groups to file,3,Main configuration file
line2=System configuration,11

View File

@@ -7,7 +7,6 @@ lease_refresh=Segons entre refrescs de la llista de préstecs,3,Mai
show_ip=Mostra les adreces IP dels hosts,1,1-Sí,0-No
show_mac=Mostra les adreces MAC dels hosts,1,1-Sí,0-No
group_name=Mostra els noms de grup com,1,1-Opció <tt>domini&#45;nom</tt>,0-Nom o recompte de membres,2-Descripció
desc_name=Mostra les descripcions dels altres objectes en lloc dels noms,1,1-Sí,0-No
display_max=Nombre màxim de subxarxes i hosts a mostrar,3,Il·limitat
add_file=Afegeix subxarxes noves&#44; hosts i grups al fitxer,3,Fitxer de configuració principal
line2=Configuració del sistema,11

View File

@@ -6,7 +6,6 @@ lease_tz=Zobrazit dobu pronájmu v,1,0-GMT,1-Lokálním čase
show_ip=Zobrazit IP adresy pro hosty?,1,1-ano,0-ne
show_mac=Zobrazit MAC adresy hostů?,1,1-Ano,0-Ne
group_name=Zobrazení jmen skupin jako,1,1-<tt>doménová jména</tt>,0-Jména nebo počtu členů,2-Popisu
desc_name=Ukázat popisy objektů místo jejich názvů?,1,1-Ano,0-Ne
display_max=Počet maximálně zobrazených podsítí a hostů,3,Bezomezení
line2=Konfigurace systému,11
dhcpd_conf=Konfigurační soubor DHCP serveru,0

View File

@@ -6,7 +6,6 @@ lease_tz=Vis lease tider i,1,0-GMT,1-Lokal tid
show_ip=Vis IP adresser for hosts?,1,1-Ja,0-Nej
show_mac=Vis MAC adresser for hosts?,1,1-Ja,0-Nej
group_name=Vis gruppenavne som,1,1-<tt>domæne&#45;navne</tt> indstilling,0-Navn eller medlemsantal,2-Beskrivelse
desc_name=Vis andre objektbeskrivelse istedet for navne?,1,1-Ja,0-Nej
display_max=Maksimalt antal hosts og subnet der skal vises,3,Ubegrænset
line2=Systemkonfiguration
dhcpd_conf=DHCP server config fil,0

View File

@@ -7,7 +7,6 @@ lease_refresh=Sekunden zwischen dem Aktualisieren der Leasing-Liste,3,Niemals
show_ip=Zeige IP-Adressen für Hosts?,1,1-Ja,0-Nein
show_mac=Zeige MAC-Adressen für Hosts?,1,1-Ja,0-Nein
group_name=Zeige Gruppennamen als,1,1-<tt>domain&#45;name</tt> Option,0-Name oder Mitglied,2-Beschreibung
desc_name=Zeige andere Objektbeschreibungen statt Namen?,1,1-Ja,0-Nein
display_max=Maximale Anzahl an Subnetzen und Hosts zum Anzeigen,3,Unbegrenzt
add_file=Füge neue Subnetze&#44; Hosts und Gruppen in einer Datei hinzu,3,Haupt-Konfigurationsdatei
line2=Systemkonfiguration,11

View File

@@ -6,7 +6,6 @@ lease_tz=نمايش زمان انتساب داده شده‌ها براساس,1,
show_ip=آيا نشانيهاي IP براي ميزبانها نشان داده شود؟,1,1-بله,0-خير
show_mac=آيا نشانيهاي MACبراي ميزبانها نشان داده شود؟,1,1-بله,0-خير
group_name=نشان‌دادن نامهاي گروه به‌صورت,1,1- گزينه<tt> دامنه/نام </tt>,0-نام يا تعداد اعضا,2-شرح
desc_name=آيا ساير شرحها به جاي نام نشان داده شود؟,1,1-بله,0-خير
display_max=حداکثر تعداد زيرشبکه‌ها و ميزبانها جهت نمايش,3,نامحدود
line2=پيکربندي سيستم,11
dhcpd_conf=پرونده پيکربندي کارساز DHCP,0

View File

@@ -6,7 +6,6 @@ lease_tz=Afficher les temps de bail en,1,0-GMT,1-Temps local
show_ip=Montrer les adresses IP des postes ?,1,1-Oui,0-Non
show_mac=Montrer les adresses MAC des postes ?,1,1-Oui,0-Non
group_name=Montrer les noms de groupe comme,1,1-Nom de domaine,0-Nom ou numero de membre
desc_name=Montrer les descriptions au lieu des noms ?,1,1-Oui,0-Non
display_max=Nombre maximum de sous-reseaux et de postes a afficher,3,Illimite
line2=Configuration du systeme,11
dhcpd_conf=Fichier de configuration du serveur DHCP,0

View File

@@ -6,7 +6,6 @@ lease_tz=リース時間の表示形式,1,0-GMT,1-ローカル時間
show_ip=ホストのIPアドレスを表示しますか?,1,1-はい,0-いいえ
show_mac=ホストのMACアドレスを表示しますか?,1,1-はい,0-いいえ
group_name=グループ名の表示方法,1,1-<tt>ドメイン&#45;名</tt> オプション,0-名前またはメンバー数
desc_name=名称の替わりにオブジェクトの説明を表示しますか?,1,1-はい,0-いいえ
display_max=サブネットとホストの表示する最大数,3,無制限
line2=システム設定,11
dhcpd_conf=DHCPサーバ 設定ファイル,0

View File

@@ -7,7 +7,6 @@ lease_refresh=Seconden tussen verversen van lease lijst,3,Nooit
show_ip=Laat IP adressen zien voor hosts?,1,1-Ja,0-Nee
show_mac=Laat MAC adressen zien voor hosts?,1,1-Ja,0-Nee
group_name=Laat groep namen zien als,1,1-<tt>domein&#45;naam</tt> optie,0-Naam of Lid van,2-Omschrijving
desc_name=Laat andere object omschrijvingen zien in plaats van namen?,1,1-Ja,0-Nee
display_max=Maximum aantal subnets en hosts om te laten zien,3,Ongelimiteerd
add_file=Toevoegen nieuwe subnetten&#44; host en groepen aan file,3,Hoofd configuratie file
line2=Systeem configuratie,11

View File

@@ -7,7 +7,6 @@ lease_refresh=Sekunder mellom oppfrisking av liste med leieavtaler,3,Aldri
show_ip=Vis IP adresser for verter?,1,1-Ja,0-Nei
show_mac=Vis MAC adresser for verter?,1,1-Ja,0-Nei
group_name=Vis gruppenavn som,1,1-<tt>domene&#45;navn</tt> alternativ,0-Navn eller antall medlemmer,2-Beskrivelse
desc_name=Vis andre objektbeskrivelser i stedet for navn,1,1-Ja,0-Nei
display_max=Maks antall subnett og verter som skal vises,3,Ubegrenset
add_file=Legg til nye subnett&#44; verter og grupper i filen,3,Hoved konfigurasjonsfil
line2=System konfigurasjon,11

View File

@@ -7,7 +7,6 @@ lease_refresh=Sekund pomiędzy odświeżaniem listy dzierżawy,3,Nigdy
show_ip=Wyświetlać adres IP hostów?,1,1-Tak,0-Nie
show_mac=Wyświetlać adres MAC hostów?,1,1-Tak,0-Nie
group_name=Wyświetl nazwy grupy jako,1,1-<tt>domain&#45;name</tt>,0-Ilość lub nazwa użytkowników,2-Opis
desc_name=Wyświetlać inne opisy obiektów zamiast nazw,1,1-Tak,0-Nie
display_max=Maksymalna liczba wyświetlanych podsieci i hostów,3,Nieograniczona
add_file=Dodaj nowe podsieci&#44; hosty i grupy do pliku,3,Główny plik konfiguracyjny
line2=Opcje systemowe,11

View File

@@ -6,7 +6,6 @@ lease_tz=Display leases times in,1,0-GMT,1-Local time
show_ip=Mostrar endereço IP para computadores?,1,1-Sim,0-Não
show_mac=Mostrar endereço MAC para computadores?,1,1-Sim,0-Não
group_name=Mostrar nomes de grupo como,1,1-<tt>nome de&#45;domínio</tt>,0-Nome ou membro
desc_name=Mostrar descrição de objetos ao invés de nomes?,1,1-Sim,0-Não
display_max=Número máximo de subredes e computadores a serem
add_file=Acrescentar novas subredes&#44; hosts e grupos para arquivo,3,Arquivo principal de configuração
line2=Configuração do sistema,11

View File

@@ -6,7 +6,6 @@ lease_tz=Zobraziť časy pridelených adries v,1,0-GMT,1-Lokálnom čase
show_ip=Zobraziť IP adresy pre počítače?,1,1-Áno,0-Nie
show_mac=Zobraziť MAC adresy pre počítače?,1,1-Áno,0-Nie
group_name=Zobraziť skupinové mená ako ,1,1-<tt>doménové mená</tt> ,0-Meno alebo počet členov,2-Popis
desc_name=Ukázať popisy objektov namiesto ich názvov?,1,1-Áno,0-Nie
display_max=Maximálny počet subnetov a hostiteľov pre zobrazenie,3,Bez limitu
line2=Systémové nastavenia,11
dhcpd_conf=Konfiguračný súbor DHCP servera,0

View File

@@ -211,14 +211,18 @@ foreach $u (@subn) {
push(@sicons, $i = "images/shared.gif");
push(@checkboxids, $u->{'index'});
}
if ($config{'desc_name'} && $u->{'comment'}) {
push(@utitles, $t = &html_escape($u->{'comment'}));
if ($config{'desc_name'} == 0) {
$t = $u->{'values'}->[0];
}
elsif ($config{'desc_name'} == 1) {
$t = $u->{'comment'} || $u->{'values'}->[0];
}
else {
push(@utitles, $t = &html_escape($u->{'values'}->[0]));
$t = $u->{'values'}->[0].($u->{'comment'} ? " ($u->{'comment'})" : "");
}
push(@utitles, &html_escape($t));
push(@uslinks, $l); # so that ordering is preserved
push(@ustitles, $t);
push(@ustitles, &html_escape($t));
push(@usicons, $i);
}
@checkboxes = map { &ui_checkbox("d", $_) } @checkboxids;
@@ -336,12 +340,16 @@ foreach $h (@host) {
(defined($subnet{$h}) ? "&uidx=$subnet{$h}" : "").
(defined($shared{$h}) ? "&sidx=$shared{$h}" : "") :
undef);
if ($config{'desc_name'} && $h->{'comment'}) {
push(@htitles, &html_escape($h->{'comment'}));
if ($config{'desc_name'} == 0) {
$t = $h->{'values'}->[0];
}
elsif ($config{'desc_name'} == 1) {
$t = $h->{'comment'} || $h->{'values'}->[0];
}
else {
push(@htitles, &html_escape($h->{'values'}->[0]));
$t = $h->{'values'}->[0].($h->{'comment'} ? " ($h->{'comment'})" : "");
}
push(@htitles, &html_escape($t));
if ($config{'show_ip'}) {
$fv = &fixedaddr($h);
$htitles[$#htitles] .= "<br>".$fv if ($fv);
@@ -589,7 +597,13 @@ sub host_table
{
local ($i, $h, $parent);
local @tds = ( "width=5" );
print &ui_columns_start([ "", $text{'index_hostgroup'},
my $hascmt;
for ($i = $_[1]; $i < $_[2]; $i++) {
$hascmt++ if ($_[4]->[$i] =~ /\(.*\)/);
}
print &ui_columns_start([ "",
$text{'index_hostgroup'},
$hascmt ? ( $text{'index_comment'} ) : ( ),
$text{'index_parent'}, $text{'index_hardware'},
$text{'index_nameip'} ], 100, 0, \@tds);
for ($i = $_[1]; $i < $_[2]; $i++) {
@@ -605,6 +619,10 @@ for ($i = $_[1]; $i < $_[2]; $i++) {
$firstcol .= $text{'index_group'}." ";
$sp = "\&nbsp;\&nbsp;";
}
my $cmt;
if ($_[4]->[$i] =~ s/\s+\((.*)\)//) {
$cmt = $1;
}
if ($_[3]->[$i]) {
$firstcol .= &ui_link($_[3]->[$i], $_[4]->[$i]);
}
@@ -612,6 +630,7 @@ for ($i = $_[1]; $i < $_[2]; $i++) {
$firstcol .= $_[4]->[$i];
}
push(@cols, $firstcol);
push(@cols, $cmt) if ($hascmt);
if ($par{$h}->{'name'} eq "group") {
$par_type = $text{'index_togroup'};
@@ -640,7 +659,14 @@ sub net_table
{
local ($i, $n);
local @tds = ( "width=5" );
print &ui_columns_start([ "", $text{'index_net'}, $text{'index_netmask'},
my $hascmt;
for ($i = $_[1]; $i < $_[2]; $i++) {
$hascmt++ if ($_[4]->[$i] =~ /\(.*\)/);
}
print &ui_columns_start([ "",
$text{'index_net'},
$hascmt ? ( $text{'index_comment'} ) : ( ),
$text{'index_netmask'},
$text{'index_desc'}, $text{'index_parent'} ], 100,
0, \@tds);
for ($i = $_[1]; $i < $_[2]; $i++) {
@@ -653,6 +679,10 @@ for ($i = $_[1]; $i < $_[2]; $i++) {
else {
$sp = "\&nbsp;\&nbsp;";
}
my $cmt;
if ($_[4]->[$i] =~ s/\s+\((.*)\)//) {
$cmt = $1;
}
if ($_[3]->[$i]) {
$first .= &ui_link($_[3]->[$i],$_[4]->[$i]);
}
@@ -660,6 +690,7 @@ for ($i = $_[1]; $i < $_[2]; $i++) {
$first .= $_[4]->[$i];
}
push(@cols, $first);
push(@cols, $cmt) if ($hascmt);
push(@cols, $_[3]->[$i] ? &netmask($n) : "");
push(@cols, $n->{'comment'});
push(@cols, $par{$n} ?

View File

@@ -14,6 +14,7 @@ index_memb=$1 members
index_hst=Hosts and Host Groups
index_nohst=No hosts or groups have been defined.
index_hostgroup=Host/Group
index_comment=Description
index_parent=Parent
index_hardware=Hardware Address
index_group=Group:

View File

@@ -95,7 +95,7 @@ foreach (@lines) {
}
}
elsif (/^(\s*)(#?)([a-z0-9\_]+)\s+=\s*(.*)/) {
# A directive inside a section
# A directive which may or may not be inside a section
local $dir = { 'name' => $3,
'value' => $4,
'enabled' => !$2,
@@ -376,9 +376,9 @@ else {
}
}
splice(@$lref, $section->{'line'}, 0, @newlines);
$section->{'eline'} = $section->{'line'} + scalar(@newlines) - 1;
&renumber($conf, $section->{'eline'}, $section->{'file'},
scalar(@newlines)-$oldlen);
$section->{'eline'} = $section->{'line'} + scalar(@newlines) - 1;
$section->{'file'} = $file;
my $i = 1;
foreach my $m (@{$section->{'members'}}) {
@@ -391,6 +391,17 @@ foreach my $m (@{$section->{'members'}}) {
}
}
# delete_section(&conf, &section)
# Remove a section and all it's members from the config file
sub delete_section
{
my ($conf, $section) = @_;
my $lref = &read_file_lines($section->{'file'});
my $len = $section->{'eline'} - $section->{'line'} + 1;
splice(@$lref, $section->{'line'}, $len);
&renumber($conf, $section->{'line'}, $section->{'file'}, -$len);
}
# renumber(&conf, line, file, offset)
sub renumber
{

View File

@@ -55,7 +55,7 @@ if (@jails) {
$col =~ s/\s/_/g;
if ($col !~ /journal_matches/ &&
$col !~ /file_list/) {
push(@head, "<div $tdc>".$text{"status_head_$col"}."</div>");
push(@head, "<span $tdc>".$text{"status_head_$col"}."</span>");
if ($col =~ /banned_ip_list/) {
$jips = $val;
my @ips = split(/\s+/, $val);

View File

@@ -349,8 +349,8 @@ if ($fh6) {
}
while(1) {
$$port++;
if ($$port >= 65536) {
return "Failed to allocate a free port!";
if ($$port < 0 || $$port > 65535) {
return "Failed to allocate a free port number: $$port";
}
$pack = pack_sockaddr_in($$port, INADDR_ANY);
next if (!bind($fh, $pack));
@@ -366,4 +366,3 @@ if ($fh6) {
}
return undef;
}

0
firewalld/block_ip.cgi Normal file → Executable file
View File

View File

@@ -173,7 +173,10 @@ if ($ok) {
print &ui_buttons_row("stop.cgi", $text{'index_stop'},
$text{'index_stopdesc'},
[ [ "zone", $zone->{'name'} ] ]);
}
}
else {
print &ui_alert_box($text{'index_downrules'}, 'warn');
}
# Show Start and disable/enabled at boot button
if (!$ok) {

View File

@@ -45,6 +45,7 @@ index_restart_firewallddesc=Reload the FirewallD server and apply the rules that
index_listrules_restartdesc=List details about existing rich and direct FirewallD rules in $1 zone.
index_dependent=Failed to restart $1 dependent service
index_manual=Edit Config Files.
index_downrules=FirewallD rules cannot be created or edited and are not enforced unless the server is running.
manual_title=Edit Config Files
manual_editsel=Edit FirewallD configuration file

View File

@@ -1,7 +1 @@
body blockquote:not([style*="border-left"]) {
border-left: 1px solid #ccc;
margin-left: 6px;
margin-top: 0;
margin-bottom: 0;
padding-left: 12px;
}
body blockquote:not([style*="border-left"]){border-left:1px solid #ccc;margin-left:6px;margin-top:0;margin-bottom:0;padding-left:12px;}pre{white-space:break-spaces;margin:0 0 4px 0}

View File

@@ -29,9 +29,6 @@ table.ui_table thead td {
table.sortable tbody td {
padding: 2px;
}
table.ui_table td * {
line-height:1.5em;
}
table.ui_table td textarea {line-height:normal; font-family:monospace;}
table.ui_table td div.barchart * {
margin: 0;
@@ -55,9 +52,16 @@ div.ui_form_end_buttons {
padding: 6px 3px;
}
.ui_form_end_buttons input {
padding: 2px;
padding: 1px;
}
table.ui_grid_table td { padding: 2px 4px; }
.ui_form_value td > b > input+label+tt,
.ui_form_value td > b > input+label {
font-weight: normal !important;
}
table.ui_grid_table td {
padding: 2px 4px;
}
select,
input {
padding: 1px;
}

View File

@@ -2212,6 +2212,7 @@ if ($ecount && keys(%info) < 2) {
# Extract info we want
my @rv;
my %done;
foreach my $name (keys %info) {
my $root = &get_systemd_root($name);
my $i = $info{$name};
@@ -2233,6 +2234,7 @@ foreach my $name (keys %info) {
'pid' => $i->{'ExecMainPID'},
'file' => $i->{'FragmentPath'} || $root."/".$name,
});
$done{$name}++;
}
# Also add legacy init scripts
@@ -2240,6 +2242,7 @@ if (!$noinit) {
my @rls = &get_inittab_runlevel();
foreach my $a (&list_actions()) {
$a =~ s/\s+\d+$//;
next if ($done{$a} || $done{$a.".service"});
my $f = &action_filename($a);
my $s = { 'name' => $a,
'legacy' => 1 };
@@ -2371,6 +2374,8 @@ if (ref($opts)) {
&print_tempfile(CFILE, "ExecReload=$kill -HUP \$MAINPID\n") if ($opts->{'reload'} eq '0');
&print_tempfile(CFILE, "ExecStop=$opts->{'stop'}\n") if ($opts->{'stop'});
&print_tempfile(CFILE, "ExecReload=$opts->{'reload'}\n") if ($opts->{'reload'});
&print_tempfile(CFILE, "ExecStartPre=$opts->{'startpre'}\n") if ($opts->{'startpre'});
&print_tempfile(CFILE, "ExecStartPost=$opts->{'startpost'}\n") if ($opts->{'startpost'});
&print_tempfile(CFILE, "Type=$opts->{'type'}\n") if ($opts->{'type'});
&print_tempfile(CFILE, "Environment=\"$opts->{'env'}\"\n") if ($opts->{'env'});
&print_tempfile(CFILE, "User=$opts->{'user'}\n") if ($opts->{'user'});
@@ -2381,8 +2386,8 @@ if (ref($opts)) {
&print_tempfile(CFILE, "RestartSec=$opts->{'restartsec'}\n") if ($opts->{'restartsec'});
&print_tempfile(CFILE, "TimeoutSec=$opts->{'timeout'}\n") if ($opts->{'timeout'});
&print_tempfile(CFILE, "TimeoutStopSec=$opts->{'timeoutstopsec'}\n") if ($opts->{'timeoutstopsec'});
&print_tempfile(CFILE, "StandardOutput=file:$opts->{'logstd'}\n") if ($opts->{'logstd'});
&print_tempfile(CFILE, "StandardError=file:$opts->{'logerr'}\n") if ($opts->{'logerr'});
&print_tempfile(CFILE, "StandardOutput=".($opts->{'logstd'} =~ /^\// ? 'file:' : '')."$opts->{'logstd'}\n") if ($opts->{'logstd'});
&print_tempfile(CFILE, "StandardError=".($opts->{'logerr'} =~ /^\// ? 'file:' : '')."$opts->{'logerr'}\n") if ($opts->{'logerr'});
}
&print_tempfile(CFILE, "\n");

View File

@@ -235,6 +235,7 @@ if ($ldap_hosts) {
&find_svalue("port", $conf) ||
($use_ssl == 1 ? 636 : 389);
foreach my $h (@hosts) {
local $SIG{'PIPE'} = 'ignore';
eval {
$ldap = Net::LDAP->new($h, port => $port,
scheme => $use_ssl == 1 ? 'ldaps' : 'ldap',
@@ -267,10 +268,18 @@ elsif ($uri) {
elsif (!$port && $proto eq "ldaps") {
$port = 636;
}
$ldap = Net::LDAP->new($host, port => $port,
scheme => $proto,
inet6 => &should_use_inet6($host));
if (!$ldap) {
local $SIG{'PIPE'} = 'ignore';
eval {
$ldap = Net::LDAP->new($host, port => $port,
scheme => $proto,
inet6 => &should_use_inet6($host));
};
if ($@) {
$err = &text('ldap_econn2',
"<tt>$host</tt>", "<tt>$port</tt>",
&html_escape($@));
}
elsif (!$ldap) {
$err = &text('ldap_econn',
"<tt>$host</tt>","<tt>$port</tt>");
}

View File

@@ -4,3 +4,4 @@ slapd=slapd
ldap_user=ldap
browse_max=100
attr_count=6
ldapadd=ldapadd

View File

@@ -8,3 +8,4 @@ stop_cmd=/etc/init.d/ldap stop
apply_cmd=/etc/init.d/ldap restart
init_name=ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -6,6 +6,7 @@ browse_max=100
start_cmd=systemctl start slapd
stop_cmd=systemctl stop slapd
apply_cmd=systemctl restart slapd
init_name=ldap
init_name=slapd
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -6,6 +6,7 @@ browse_max=100
start_cmd=systemctl start slapd
stop_cmd=systemctl stop slapd
apply_cmd=systemctl restart slapd
init_name=ldap
init_name=slapd
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -6,6 +6,7 @@ browse_max=100
start_cmd=systemctl start slapd
stop_cmd=systemctl stop slapd
apply_cmd=systemctl restart slapd
init_name=ldap
init_name=slapd
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -6,6 +6,7 @@ browse_max=100
start_cmd=systemctl start slapd
stop_cmd=systemctl stop slapd
apply_cmd=systemctl restart slapd
init_name=ldap
init_name=slapd
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -6,6 +6,7 @@ browse_max=100
start_cmd=systemctl start slapd
stop_cmd=systemctl stop slapd
apply_cmd=systemctl restart slapd
init_name=ldap
init_name=slapd
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -6,6 +6,7 @@ browse_max=100
start_cmd=systemctl start slapd
stop_cmd=systemctl stop slapd
apply_cmd=systemctl restart slapd
init_name=ldap
init_name=slapd
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -6,6 +6,7 @@ browse_max=100
start_cmd=/etc/init.d/slapd start
stop_cmd=/etc/init.d/slapd stop
apply_cmd=/etc/init.d/slapd restart
init_name=ldap
init_name=slapd
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -6,6 +6,7 @@ browse_max=100
start_cmd=systemctl start slapd
stop_cmd=systemctl stop slapd
apply_cmd=systemctl restart slapd
init_name=ldap
init_name=slapd
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -6,6 +6,7 @@ browse_max=100
start_cmd=systemctl start slapd
stop_cmd=systemctl stop slapd
apply_cmd=systemctl restart slapd
init_name=ldap
init_name=slapd
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -9,3 +9,4 @@ apply_cmd=/etc/init.d/ldap restart
init_name=ldap
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -6,6 +6,7 @@ browse_max=100
start_cmd=systemctl start slapd
stop_cmd=systemctl stop slapd
apply_cmd=systemctl restart slapd
init_name=ldap
init_name=slapd
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -8,3 +8,4 @@ stop_cmd=/etc/init.d/slapd stop
apply_cmd=/etc/init.d/slapd restart
init_name=slapd
attr_count=6
ldapadd=ldapadd

View File

@@ -8,3 +8,4 @@ stop_cmd=/etc/init.d/slapd stop
apply_cmd=/etc/init.d/slapd restart
init_name=slapd
attr_count=6
ldapadd=ldapadd

View File

@@ -8,3 +8,4 @@ stop_cmd=/etc/init.d/slapd stop
apply_cmd=/etc/init.d/slapd restart
init_name=slapd
attr_count=6
ldapadd=ldapadd

View File

@@ -7,3 +7,4 @@ attr_count=6
start_cmd=/usr/local/etc/rc.d/slapd start
stop_cmd=/usr/local/etc/rc.d/slapd stop
apply_cmd=/usr/local/etc/rc.d/slapd restart
ldapadd=ldapadd

View File

@@ -8,3 +8,4 @@ start_cmd=/usr/local/etc/rc.d/slapd forcestart
stop_cmd=/usr/local/etc/rc.d/slapd forcestop
apply_cmd=/usr/local/etc/rc.d/slapd onerestart
init_name=slapd
ldapadd=ldapadd

View File

@@ -8,3 +8,4 @@ stop_cmd=/etc/rc./init.d/ldap stop
apply_cmd=/etc/rc./init.d/ldap restart
init_name=ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -8,3 +8,4 @@ stop_cmd=systemctl stop ldap
apply_cmd=systemctl restart ldap
init_name=ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -6,3 +6,4 @@ browse_max=100
data_dir=/var/lib/openladp-data
attr_count=6
ldapadd=ldapadd

View File

@@ -9,3 +9,4 @@ apply_cmd=/etc/init.d/ldap restart
init_name=ldap
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -9,3 +9,4 @@ apply_cmd=systemctl restart slapd.service
init_name=slapd
data_dir=/var/lib/ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -5,3 +5,4 @@ slapd=/opt/csw/libexec/slapd
ldap_user=ldap
browse_max=100
attr_count=6
ldapadd=ldapadd

View File

@@ -8,3 +8,4 @@ stop_cmd=/etc/init.d/ldap stop
apply_cmd=/etc/init.d/ldap restart
init_name=ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -8,3 +8,4 @@ config_file=/etc/ldap/slapd.conf
stop_cmd=/etc/init.d/ldap stop
attr_count=6
browse_max=100
ldapadd=ldapadd

View File

@@ -8,3 +8,4 @@ stop_cmd=/etc/rc./init.d/ldap stop
apply_cmd=/etc/rc./init.d/ldap restart
init_name=ldap
attr_count=6
ldapadd=ldapadd

View File

@@ -7,6 +7,7 @@ ssl=Use encryption with LDAP server?,1,-Detect automatically,1-Yes,2-Yes TLS,0-N
line4=LDAP server options,11
slapd=Full path to OpenLDAP server program,8
ldapadd=Full path to <tt>ldapadd</tt> command,8
config_file=OpenLDAP server configuration file or directory,8
schema_dir=OpenLDAP schema directory,7
ldap_user=User OpenLDAP server runs as,5

View File

@@ -6,11 +6,10 @@ require './ldap-server-lib.pl';
$access{'slapd'} || &error($text{'slapd_ecannot'});
&ui_print_header(undef, $text{'slapd_title'}, "", "slapd");
$conf = &get_ldif_config();
@tds = ( "width=30%" );
print &ui_form_start("save_ldif.cgi", "post");
print &ui_hidden_table_start($text{'slapd_header'}, "width=100%", 2,
"basic", 1,\@tds);
"basic", 1);
# Top-level DN
$defdb = &get_default_db();
@@ -74,7 +73,7 @@ print &ui_hidden_table_end("basic");
# SSL section
print &ui_hidden_table_start($text{'slapd_header2'}, "width=100%", 2,
"ssl", 0, \@tds);
"ssl", 0);
# Protocols to serve
if (&can_get_ldap_protocols()) {

View File

@@ -18,7 +18,12 @@ if (&get_config_type() == 1) {
}
# Show a table of all known schema files, with checkboxes
print $text{'schema_pagedesc'},"<p>\n";
if (&get_config_type() == 1) {
print $text{'schema_pagedesc'},"<p>\n";
}
else {
print $text{'schema_pagedesc2'},"<p>\n";
}
@tds = ( $editable ? ( "width=5" ) : ( ),
"width=20%", "width=65%", "width=10%", "width=5% nowrap" );
print &ui_form_start("save_schema.cgi", "post");
@@ -31,8 +36,8 @@ print &ui_columns_start([ $editable ? ( "" ) : ( ),
@files = sort { &schema_sorter } &list_schema_files();
for($i=0; $i<@files; $i++) {
$s = $files[$i];
@acts = ( &ui_link("view_sfile.cgi?file=".&urlize($s->{'file'})."",$text{'schema_view'}),
&ui_link("edit_sfile.cgi?file=".&urlize($s->{'file'})."",$text{'schema_edit'}) );
@acts = ( &ui_link("view_sfile.cgi?file=".&urlize($s->{'file'}), $text{'schema_view'}),
&ui_link("edit_sfile.cgi?file=".&urlize($s->{'file'}), $text{'schema_edit'}) );
if ($incs{$s->{'file'}}) {
$mover = &ui_up_down_arrows(
"up_schema.cgi?file=".&urlize($s->{'file'}),
@@ -56,6 +61,8 @@ for($i=0; $i<@files; $i++) {
}
else {
# View files only
push(@acts, &ui_link("import_sfile.cgi?file=".&urlize($s->{'file'}),
$text{'schema_import'}));
print &ui_columns_row(
[ $s->{'name'},
$s->{'desc'} || $s->{'file'},

61
ldap-server/import_sfile.cgi Executable file
View File

@@ -0,0 +1,61 @@
#!/usr/local/bin/perl
# Import a schema file into the server
require './ldap-server-lib.pl';
&error_setup($text{'import_err'});
&local_ldap_server() == 1 || &error($text{'slapd_elocal'});
$access{'schema'} || &error($text{'schema_ecannot'});
&ReadParse();
&is_under_directory($config{'schema_dir'}, $in{'file'}) ||
&error($text{'schema_edir'});
&has_command($config{'ldapadd'}) ||
&error(&text('import_eldapadd', "<tt>$config{'ldapadd'}</tt>"));
# Get login credentials
$user = $config{'user'};
$pass = $config{'pass'};
if (&get_config_type() == 1) {
my $conf = &get_config();
$user ||= &find_value("rootdn", $conf);
$pass ||= &find_value("rootpw", $conf);
}
else {
$defdb = &get_default_db();
$conf = &get_ldif_config();
$user ||= &find_ldif_value("olcRootDN", $conf, $defdb);
$pass ||= &find_ldif_value("olcRootPW", $conf, $defdb);
}
$user || &error($text{'import_euser'});
# Check that there's a corresponding LDIF file
$ldiffile = $in{'file'};
$ldiffile =~ s/\.schema$/.ldif/;
-r $ldiffile ||
&error(&text('import_eldif', "<tt>".&html_escape($ldiffile)."</tt>"));
# Run the import command
$cmd = $config{'ldapadd'}.
" -D ".quotemeta($user).
" -w ".quotemeta($pass).
" -H ldapi:///".
" -Y external".
" -f ".quotemeta($ldiffile);
&ui_print_unbuffered_header(undef, $text{'import_title'}, "");
print &text('import_doing', "<tt>".&html_escape($ldiffile)."</tt>"),"<p>\n";
print "<pre>\n";
&open_execute_command(CMD, $cmd, 2);
while(<CMD>) {
print &html_escape($_);
}
close(CMD);
print "</pre>\n";
if ($?) {
print $text{'import_failed'},"<p>\n";
}
else {
print $text{'import_ok'},"<p>\n";
}
&ui_print_footer("edit_schema.cgi", $text{'schema_return'});

View File

@@ -84,11 +84,13 @@ schema_title=Manage Schema
schema_file=Name
schema_desc=Description
schema_pagedesc=The LDAP schema determines which object classes and attributes can be stored in your LDAP database. This page allows you to select which schema types are supported by your server - but be careful de-selecting any entries that are used by existing objects.
schema_pagedesc2=The LDAP schema determines which object classes and attributes can be stored in your LDAP database. Schemas files must be imported before their types can be used to create objects.
schema_err=Failed to save schema
schema_move=Move
schema_act=Actions..
schema_view=View
schema_edit=Edit
schema_import=Import
schema_edir=File is not in the schema directory!
schema_etitle=Edit Schema File
schema_eheader=Schema file contents
@@ -214,6 +216,7 @@ apply_ecannot=You are not allowed to apply the configuration
stop_err=Failed to stop LDAP server
stop_ecmd=$1 failed : $2
stop_egone=No longer running!
stop_egone2=Running but PID is unknown!
stop_ekill=Kill process failed : $1
stop_ecannot=You are not allowed to stop the LDAP server
@@ -328,4 +331,13 @@ eacl_eaccess=Missing or invalid access level in row $1
eacl_order=Rule order
eacl_noorder=None set
import_err=Failed to import schema
import_eldapadd=Could not find the $1 command
import_euser=Could not work out LDAP server login
import_eldif=LDIF file $1 does not exist
import_title=Import Schema
import_doing=Importing LDIF schema file $1 ..
import_failed=.. import failed!
import_ok=.. import completed successfully
__norefs=1

View File

@@ -526,6 +526,7 @@ if ($config{'stop_cmd'}) {
else {
local $pid = &is_ldap_server_running();
$pid || return $text{'stop_egone'};
$pid > 1 || return $text{'stop_egone2'};
return kill('TERM', $pid) ? undef : &text('stop_ekill', $!);
}
}
@@ -564,6 +565,9 @@ else {
# Returns the process ID of the running LDAP server, or undef
sub is_ldap_server_running
{
&foreign_require("init");
my $iname = $config{'init_name'} || $module_name;
return 1 if (&init::status_action($iname) == 1);
local $pidfile = &get_ldap_server_pidfile();
if ($pidfile) {
return &check_pid_file($pidfile);

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/pam_ldap/auth_ldap.conf
imap_login=cyrus
samba_class=sambaAccount
imap_class=SuSEeMailObject

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/ldap.conf
imap_login=cyrus
samba_class=sambaAccount
imap_class=SuSEeMailObject

View File

@@ -1,4 +1,3 @@
auth_ldap=/usr/share/libnss-ldap/ldap.conf
imap_login=cyrus
samba_class=sambaSamAccount
imap_class=SuSEeMailObject

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/libnss-ldap.conf
imap_login=cyrus
samba_class=sambaSamAccount
imap_class=SuSEeMailObject

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/ldap.conf
imap_login=cyrus
samba_class=sambaSamAccount
imap_class=SuSEeMailObject

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/ldap/ldap.conf
imap_login=cyrus
samba_class=sambaSamAccount
imap_class=SquirrelMailUser inetLocalMailRecipient

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/ldap.conf
imap_login=cyrus
samba_class=sambaAccount
imap_class=SuSEeMailObject

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/openldap/ldap.conf
imap_login=cyrus
samba_class=sambaAccount
imap_class=SuSEeMailObject

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/openldap/ldap.conf
imap_login=cyrus
samba_class=sambaSamAccount
imap_class=SuSEeMailObject

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/ldap.conf
imap_login=cyrus
samba_class=sambaAccount
imap_class=SuSEeMailObject

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/ldap.conf
imap_login=cyrus
samba_class=sambaAccount
imap_class=SuSEeMailObject

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/openldap/ldap.conf
imap_login=cyrus
samba_class=sambaAccount
imap_class=SuSEeMailObject

View File

@@ -1,5 +1,4 @@
samba_class=sambaAccount
auth_ldap=/etc/pam_ldap/auth_ldap.conf
ldap_tls=0
imap_login=cyrus
imap_class=SuSEeMailObject

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/openldap/ldap.conf
imap_login=cyrus
samba_class=sambaAccount
imap_class=SuSEeMailObject

View File

@@ -1,4 +1,3 @@
auth_ldap=/etc/openldap/ldap.conf
imap_login=cyrus
samba_class=sambaAccount
imap_class=SuSEeMailObject

View File

@@ -8,8 +8,9 @@ do 'ldap-useradmin-lib.pl';
# For mode 0, returns 1 if installed, 0 if not
sub is_installed
{
if ($config{'auth_ldap'}) {
return 0 if (!-r $config{'auth_ldap'});
my $cfile = &ldap_client::get_ldap_config_file();
if ($cfile) {
return 0 if (!-r $cfile);
}
else {
if ($_[0]) {

View File

@@ -92,8 +92,15 @@ else { &error($ldap); }
sub get_user_base
{
local $conf = &ldap_client::get_config();
local $passwd_base;
foreach my $b (&ldap_client::find_value("base", $conf)) {
if ($b =~ /^passwd\s+(\S+)/) {
$passwd_base = $1;
}
}
local $base = $config{'user_base'} ||
&ldap_client::find_svalue("nss_base_passwd", $conf) ||
$passwd_base ||
&ldap_client::find_svalue("base", $conf);
$base =~ s/\?.*$//;
return $base;
@@ -103,8 +110,15 @@ return $base;
sub get_group_base
{
local $conf = &ldap_client::get_config();
local $group_base;
foreach my $b (&ldap_client::find_value("base", $conf)) {
if ($b =~ /^group\s+(\S+)/) {
$group_base = $1;
}
}
local $base = $config{'group_base'} ||
&ldap_client::find_svalue("nss_base_group", $conf) ||
$group_base ||
&ldap_client::find_svalue("base", $conf);
$base =~ s/\?.*$//;
return $base;
@@ -230,31 +244,35 @@ return @list_users_cache;
# it to the LDAP database
sub create_user
{
local $ldap = &ldap_connect();
local $base = &get_user_base();
$_[0]->{'dn'} = "uid=$_[0]->{'user'},$base";
local @classes = ( &def_user_obj_class(), "shadowAccount",
my ($user) = @_;
my $ldap = &ldap_connect();
my $base = &get_user_base();
$user->{'dn'} = "uid=$user->{'user'},$base";
my @classes = ( &def_user_obj_class(), "shadowAccount",
split(/\s+/, $config{'other_class'}),
@{$_[0]->{'ldap_class'}} );
local $schema = $ldap->schema();
@{$user->{'ldap_class'}} );
my $schema = $ldap->schema();
if ($schema->objectclass("person") && $config{'person'}) {
push(@classes, "person");
}
if ($config{'given'}) {
push(@classes, $config{'given_class'});
}
@classes = &uniquelc(@classes);
@classes = grep { /\S/ } @classes; # Remove empty
local @attrs = &user_to_dn($_[0]);
push(@attrs, &split_props($config{'props'}, $_[0]));
push(@attrs, @{$_[0]->{'ldap_attrs'}});
my @attrs = &user_to_dn($user);
push(@attrs, &split_props($config{'props'}, $user));
push(@attrs, @{$user->{'ldap_attrs'}});
push(@attrs, "objectClass" => \@classes);
if (&indexoflc("person", @classes) >= 0 && !&in_props(\@attrs, "sn")) {
# Person needs 'sn'
push(@attrs, "sn", &in_props(\@attrs, "cn"));
}
local $rv = $ldap->add($_[0]->{'dn'}, attr => \@attrs);
my $rv = $ldap->add($user->{'dn'}, attr => \@attrs);
if ($rv->code) {
&error(&text('usave_eadd', $rv->error));
}
push(@list_users_cache, $_[0]) if (scalar(@list_users_cache));
push(@list_users_cache, $user) if (scalar(@list_users_cache));
$ldap->unbind();
&useradmin::refresh_nscd() if (!$batch_mode);
}
@@ -264,8 +282,9 @@ $ldap->unbind();
# it from the LDAP database
sub delete_user
{
local $ldap = &ldap_connect();
local $rv = $ldap->delete($_[0]->{'dn'});
my ($user) = @_;
my $ldap = &ldap_connect();
my $rv = $ldap->delete($user->{'dn'});
if ($rv->code) {
my $err = $rv->error;
if ($err !~ /No such object/i) {
@@ -273,7 +292,7 @@ if ($rv->code) {
}
}
$ldap->unbind();
@list_users_cache = grep { $_ ne $_[0] } @list_users_cache
@list_users_cache = grep { $_ ne $user } @list_users_cache
if (scalar(@list_users_cache));
&useradmin::refresh_nscd() if (!$batch_mode);
}
@@ -281,52 +300,53 @@ $ldap->unbind();
# modify_user(&olduser, &newuser)
sub modify_user
{
local $ldap = &ldap_connect();
local $base = &get_user_base();
local @attrs = &user_to_dn($_[1]);
push(@attrs, &split_props($config{'mod_props'}, $_[1]));
push(@attrs, @{$_[1]->{'ldap_attrs'}});
if ($_[1]->{'ldap_class'} &&
(!ref($_[1]->{'ldap_class'}) || @{$_[1]->{'ldap_class'}})) {
push(@attrs, "objectClass" => $_[1]->{'ldap_class'});
my ($olduser, $user) = @_;
my $ldap = &ldap_connect();
my $base = &get_user_base();
my @attrs = &user_to_dn($user);
push(@attrs, &split_props($config{'mod_props'}, $user));
push(@attrs, @{$user->{'ldap_attrs'}});
if ($user->{'ldap_class'} &&
(!ref($user->{'ldap_class'}) || @{$user->{'ldap_class'}})) {
push(@attrs, "objectClass" => $user->{'ldap_class'});
}
if (&indexoflc("person", @{$_[1]->{'ldap_class'}}) >= 0 &&
if (&indexoflc("person", @{$user->{'ldap_class'}}) >= 0 &&
!&in_props(\@attrs, "sn")) {
# Person needs 'sn'
push(@attrs, "sn", &in_props(\@attrs, "cn"));
}
local %replace;
my %replace;
for(my $i=0; $i<@attrs; $i+=2) {
$replace{$attrs[$i]} ||= [ ];
local $v = $attrs[$i+1];
my $v = $attrs[$i+1];
push(@{$replace{$attrs[$i]}}, ref($v) ? @$v : $v);
}
if ($_[0]->{'pass'} eq $_[1]->{'pass'}) {
if ($olduser->{'pass'} eq $user->{'pass'}) {
# Don't change password attribute if not change
delete($replace{'userPassword'});
}
# Do rename to new DN first
if ($_[0]->{'user'} ne $_[1]->{'user'}) {
local $newdn = $_[0]->{'dn'};
if ($newdn !~ s/^uid=$_[0]->{'user'},/uid=$_[1]->{'user'},/) {
$newdn = "uid=$_[1]->{'user'},$base";
if ($olduser->{'user'} ne $user->{'user'}) {
my $newdn = $olduser->{'dn'};
if ($newdn !~ s/^uid=$olduser->{'user'},/uid=$user->{'user'},/) {
$newdn = "uid=$user->{'user'},$base";
}
if (!&same_dn($newdn, $_[0]->{'dn'})) {
$rv = $ldap->moddn($_[0]->{'dn'},
newrdn => "uid=$_[1]->{'user'}");
if (!&same_dn($newdn, $olduser->{'dn'})) {
$rv = $ldap->moddn($olduser->{'dn'},
newrdn => "uid=$user->{'user'}");
if ($rv->code) {
&error(&text('usave_emoddn', $rv->error));
}
$_[1]->{'dn'} = $newdn;
$user->{'dn'} = $newdn;
}
}
local $rv = $ldap->modify($_[1]->{'dn'}, replace => \%replace);
my $rv = $ldap->modify($user->{'dn'}, replace => \%replace);
if ($rv->code) {
&error(&text('usave_emod', $rv->error));
}
if ($_[0] ne $_[1] && &indexof($_[0], @list_users_cache) != -1) {
if ($olduser ne $user && &indexof($olduser, @list_users_cache) != -1) {
# Update old object in cache
%{$_[0]} = %{$_[1]};
%{$olduser} = %{$user};
}
$ldap->unbind();
&useradmin::refresh_nscd() if (!$batch_mode);
@@ -431,37 +451,42 @@ $ldap->unbind();
# in the same format uses by the useradmin module
sub dn_to_hash
{
if ($_[0]->get_value("uid")) {
local %user = ( 'dn' => $_[0]->dn(),
'user' => $_[0]->get_value("uid"),
'uid' => $_[0]->get_value("uidNumber"),
'gid' => $_[0]->get_value("gidNumber"),
'real' => $_[0]->get_value("cn"),
'home' => $_[0]->get_value("homeDirectory"),
'shell' => $_[0]->get_value("loginShell"),
'pass' => $_[0]->get_value("userPassword"),
'change' => $_[0]->get_value("shadowLastChange") || "",
'expire' => $_[0]->get_value("shadowExpire") || "",
'min' => $_[0]->get_value("shadowMin") || "",
'max' => $_[0]->get_value("shadowMax") || "",
'warn' => $_[0]->get_value("shadowWarning") || "",
'inactive' => $_[0]->get_value("shadowInactive") || "",
);
my ($obj) = @_;
if ($obj->get_value("uid")) {
my %user = ( 'dn' => $obj->dn(),
'user' => $obj->get_value("uid"),
'uid' => $obj->get_value("uidNumber"),
'gid' => $obj->get_value("gidNumber"),
'real' => $obj->get_value("cn"),
'home' => $obj->get_value("homeDirectory"),
'shell' => $obj->get_value("loginShell"),
'pass' => $obj->get_value("userPassword"),
'change' => $obj->get_value("shadowLastChange") || "",
'expire' => $obj->get_value("shadowExpire") || "",
'min' => $obj->get_value("shadowMin") || "",
'max' => $obj->get_value("shadowMax") || "",
'warn' => $obj->get_value("shadowWarning") || "",
'inactive' => $obj->get_value("shadowInactive") || "",
);
if ($config{'given'}) {
$user{'firstname'} = $obj->get_value("givenName");
$user{'surname'} = $obj->get_value("sn");
}
$user{'pass'} =~ s/^(\!?)\{[a-z0-9]+\}/$1/i;
$user{'all_ldap_attrs'} = { map { lc($_), scalar($_[0]->get_value($_)) }
$_[0]->attributes() };
$user{'ldap_class'} = [ $_[0]->get_value('objectClass') ];
$user{'all_ldap_attrs'} = { map { lc($_), scalar($obj->get_value($_)) }
$obj->attributes() };
$user{'ldap_class'} = [ $obj->get_value('objectClass') ];
return %user;
}
else {
local @members = $_[0]->get_value('memberUid');
local %group = ( 'dn' => $_[0]->dn(),
'group' => $_[0]->get_value("cn"),
'gid' => $_[0]->get_value("gidNumber"),
'pass' => $_[0]->get_value("userPassword") || "",
'members' => join(",", @members) || "",
'desc' => $_[0]->get_value("description"),
);
my @members = $obj->get_value('memberUid');
my %group = ( 'dn' => $obj->dn(),
'group' => $obj->get_value("cn"),
'gid' => $obj->get_value("gidNumber"),
'pass' => $obj->get_value("userPassword") || "",
'members' => join(",", @members) || "",
'desc' => $obj->get_value("description"),
);
return %group;
}
}
@@ -470,48 +495,56 @@ else {
# Given a useradmin-style user hash, returns a list of properties
sub user_to_dn
{
local $pfx = $_[0]->{'pass'} =~ /^\{[a-z0-9]+\}/i ? undef :
$_[0]->{'pass'} =~ /^\$1\$/ ? "{md5}" :
$_[0]->{'pass'} =~ /^[a-zA-Z0-9\.\/]{13}$/ ? "{crypt}" :
$config{'md5'} == 1 || $config{'md5'} == 3 ? "{md5}" :
$config{'md5'} == 4 ? "{ssha}" :
$config{'md5'} == 0 ? "{crypt}" : "";
local $pass = $_[0]->{'pass'};
local $disabled;
my ($user) = @_;
my $pfx = $user->{'pass'} =~ /^\{[a-z0-9]+\}/i ? undef :
$user->{'pass'} =~ /^\$1\$/ ? "{md5}" :
$user->{'pass'} =~ /^[a-zA-Z0-9\.\/]{13}$/ ? "{crypt}" :
$config{'md5'} == 1 || $config{'md5'} == 3 ? "{md5}" :
$config{'md5'} == 4 ? "{ssha}" :
$config{'md5'} == 0 ? "{crypt}" : "";
my $pass = $user->{'pass'};
my $disabled;
if ($pass =~ s/^\!//) {
$disabled = "!";
}
$cn = $_[0]->{'real'} eq '' ? $_[0]->{'user'} : $_[0]->{'real'};
my $cn = $user->{'real'} eq '' ? $user->{'user'} : $user->{'real'};
return ( "cn" => $cn,
"uid" => $_[0]->{'user'},
"uidNumber" => $_[0]->{'uid'},
"loginShell" => $_[0]->{'shell'},
"homeDirectory" => $_[0]->{'home'},
"gidNumber" => $_[0]->{'gid'},
"uid" => $user->{'user'},
"uidNumber" => $user->{'uid'},
"loginShell" => $user->{'shell'},
"homeDirectory" => $user->{'home'},
"gidNumber" => $user->{'gid'},
"userPassword" => $disabled.$pfx.$pass,
$_[0]->{'change'} eq '' ? ( ) :
( "shadowLastChange" => $_[0]->{'change'} ),
$_[0]->{'expire'} eq '' ? ( ) :
( "shadowExpire" => $_[0]->{'expire'} ),
$_[0]->{'min'} eq '' ? ( ) :
( "shadowMin" => $_[0]->{'min'} ),
$_[0]->{'max'} eq '' ? ( ) :
( "shadowMax" => $_[0]->{'max'} ),
$_[0]->{'warn'} eq '' ? ( ) :
( "shadowWarning" => $_[0]->{'warn'} ),
$_[0]->{'inactive'} eq '' ? ( ) :
( "shadowInactive" => $_[0]->{'inactive'} )
$user->{'change'} eq '' ? ( ) :
( "shadowLastChange" => $user->{'change'} ),
$user->{'expire'} eq '' ? ( ) :
( "shadowExpire" => $user->{'expire'} ),
$user->{'min'} eq '' ? ( ) :
( "shadowMin" => $user->{'min'} ),
$user->{'max'} eq '' ? ( ) :
( "shadowMax" => $user->{'max'} ),
$user->{'warn'} eq '' ? ( ) :
( "shadowWarning" => $user->{'warn'} ),
$user->{'inactive'} eq '' ? ( ) :
( "shadowInactive" => $user->{'inactive'} ),
$user->{'firstname'} eq '' ? ( ) :
( "givenName" => $user->{'firstname'} ),
$user->{'surname'} eq '' ? ( ) :
( "sn" => $user->{'surname'} ),
);
}
# group_to_dn(&group)
# Given a useradmin-style group hash, returns a list of properties
sub group_to_dn
{
local @members = split(/,/, $_[0]->{'members'});
return ( "cn" => $_[0]->{'group'},
"gidNumber" => $_[0]->{'gid'},
"userPassword" => $_[0]->{'pass'},
my ($group) = @_;
my @members = split(/,/, $group->{'members'});
return ( "cn" => $group->{'group'},
"gidNumber" => $group->{'gid'},
"userPassword" => $group->{'pass'},
@members ? ( "memberUid" => \@members ) : ( ),
defined($_[0]->{'desc'}) ? ( "description" => $_[0]->{'desc'} ) : ( ),
defined($group->{'desc'}) ? ( "description" => $group->{'desc'} ) : ( ),
);
}

View File

@@ -1,3 +1,6 @@
skip_index=1
lines=100
others=1
reverse=1
log_any=0
compressed=1

View File

@@ -1,5 +1,8 @@
skip_index=Open log view on module load?,1,1-Yes,0-No
lines=Default number of lines to display,0,6
compressed=Include compressed logs in searches?,1,1-Yes,0-No
refresh=Seconds between log view refreshes,3,Never
others=Show logs from other modules?,1,1-Yes,0-No
extras=Extra log files to show,9,50,4,\t
reverse=Log display order,1,1-Newest lines at top,0-Newest lines at bottom
log_any=Can view any file as a log?,1,1-Yes,0-No

View File

@@ -4,26 +4,24 @@
require './logviewer-lib.pl';
&ui_print_header($text{'index_subtitle'}, $text{'index_title'}, "", undef, 1, 1, 0,
&help_search_link("systemd-journal journalctl", "man", "doc"));
if (!&has_command('journalctl')) {
# Not installed
&ui_print_endpage(&text('index_econf', "<tt>$config{'syslog_conf'}</tt>", "../config.cgi?$module_name"));
}
# Display syslog rules
my @col0;
my @col1;
my @col2;
my @col3;
my @lnks;
if ($access{'syslog'}) {
my @systemctl_cmds = &get_systemctl_cmds();
foreach $o (@systemctl_cmds) {
local @cols;
push(@cols, &text('index_cmd', "<tt>".$o->{'cmd'}."</tt>"));
push(@cols, $o->{'desc'});
push(@cols, &ui_link("view_log.cgi?idx=$o->{'id'}&view=1", $text{'index_view'}) );
push(@col1, \@cols);
push(@cols, &text('index_cmd', "<tt>".
&cleanup_destination($o->{'cmd'})."</tt>"));
my $icon = $o->{'id'} =~ /journal-(a|x)/ ? "&#x25E6;&nbsp; " : "";
push(@cols, $icon.&cleanup_description($o->{'desc'}));
push(@cols, &ui_link("view_log.cgi?idx=$o->{'id'}&view=1",
$text{'index_view'}) );
push(@lnks, "view_log.cgi?idx=$o->{'id'}&view=1");
push(@col0, \@cols);
}
# System logs from other modules
@@ -47,6 +45,8 @@ if ($access{'syslog'}) {
map { &html_escape($_) } @{$c->{'sel'}}));
push(@cols, &ui_link("view_log.cgi?idx=syslog-".
$c->{'index'}."&"."view=1", $text{'index_view'}) );
push(@lnks, "view_log.cgi?idx=syslog-".
$c->{'index'}."&"."view=1");
push(@col1, \@cols);
push(@foreign_syslogs, $c->{'file'});
}
@@ -73,6 +73,9 @@ if ($access{'syslog'}) {
"view_log.cgi?idx=syslog-ng-".
$dest->{'index'}."&"."view=1",
$text{'index_view'}) );
push(@lnks, "view_log.cgi?idx=syslog-ng-".
$dest->{'index'}."&"."view=1");
@cols = sort { $a->[2] cmp $b->[2] } @cols;
push(@col1, \@cols);
}
}
@@ -95,9 +98,12 @@ if ($config{'others'} && $access{'others'}) {
push(@cols, &text('index_cmd',
"<tt>".&html_escape($o->{'cmd'})."</tt>"));
}
push(@cols, &html_escape($o->{'desc'}));
push(@cols, $o->{'desc'} ? &html_escape($o->{'desc'}) : "");
push(@cols, &ui_link("view_log.cgi?oidx=$o->{'mindex'}".
"&omod=$o->{'mod'}&view=1", $text{'index_view'}) );
push(@lnks, "view_log.cgi?oidx=$o->{'mindex'}".
"&omod=$o->{'mod'}&view=1");
@cols = sort { $a->[2] cmp $b->[2] } @cols;
push(@col2, \@cols);
}
}
@@ -114,29 +120,47 @@ foreach $e (&extra_log_files()) {
push(@cols, &text('index_cmd',
"<tt>".&html_escape($e->{'cmd'})."</tt>"));
}
push(@cols, &html_escape($e->{'desc'}));
push(@cols, $e->{'desc'} ? &html_escape($e->{'desc'}) : "");
push(@cols, &ui_link("view_log.cgi?extra=".&urlize($e->{'file'} || $e->{'cmd'})."&view=1", $text{'index_view'}) );
push(@lnks, "view_log.cgi?extra=".&urlize($e->{'file'} || $e->{'cmd'})."&view=1");
@cols = sort { $a->[2] cmp $b->[2] } @cols;
push(@col3, \@cols);
}
# Print sorted table with logs files and commands
my @acols = (@col1, @col2, @col3);
my @acols = (@col0, @col1, @col2, @col3);
my $print_header = sub {
# Print the header
&ui_print_header($text{'index_subtitle'}, $text{'index_title'}, "", undef, 1, 1, 0,
&help_search_link("systemd-journal journalctl", "man", "doc"));
};
# If no logs are available just show the message
if (!@acols) {
$print_header->();
&ui_print_endpage($text{'index_elogs'});
}
# If we jump directly to logs just redirect
if ($config{'skip_index'} == 1 && $lnks[0]) {
&redirect($lnks[0]);
return;
}
# Print the header
$print_header->();
print &ui_columns_start( @acols ? [
$text{'index_to'},
$text{'index_rule'}, "" ] : [ ], 100);
if (@acols) {
@acols = sort { $a->[2] cmp $b->[2] } @acols;
foreach my $col (@acols) {
print &ui_columns_row($col);
}
}
else {
print &ui_columns_row([$text{'index_elogs'}], [" colspan='3' style='text-align: center'"], 3);
foreach my $col (@acols) {
print &ui_columns_row($col);
}
print &ui_columns_end();
print "<p>\n";
if ($access{'any'}) {
if ($access{'any'} && $config{'log_any'} == 1) {
# Can view any log (under allowed dirs)
print &ui_form_start("view_log.cgi");
print &ui_hidden("view", 1),"\n";

View File

@@ -1,10 +1,10 @@
index_title=System Logs Viewer
index_elogs=No logs were found to display
index_to=Log destination
index_rule=Messages selected
index_title=System Logs
index_elogs=The <tt>journalctl</tt> command is not available on your system, and other logs are configured not to be displayed in the module configuration.
index_to=Log
index_rule=Description
index_file=File $1
index_cmd=Output from $1
index_return=system logs viewer
index_return=system logs
index_view=View..
index_viewfile=View log file:
index_viewok=View
@@ -16,16 +16,35 @@ journal_journalctl_debug_info=Debug and info messages
journal_journalctl_notice_warning=Notice and warning messages
journal_journalctl_err_crit=Error and critical messages
journal_journalctl_alert_emerg=Alert and emergency messages
journal_journalctl_unit=Messages for specific unit
journal_since0=Latest available
journal_since1=Real-time follow
journal_since2=Current boot
journal_since3=7 days ago
journal_since4=24 hours ago
journal_since5=8 hours ago
journal_since6=1 hour ago
journal_since7=30 minutes ago
journal_since8=10 minutes ago
journal_since9=3 minutes ago
journal_since10=1 minute ago
journal_sincefollow=in
journal_since=since
view_title=View Logfile
view_titlejournal=View Journal
view_header=Last $1 lines of $2
view_header2=Last $1 lines
view_header3=Lines of $1
view_empty=Log file is empty
view_refresh=Refresh
view_loading=Log file is being watched .. No new lines yet.
view_filter=Filter lines with text $1
view_filter_btn=Filter
save_efile='$1' is not a valid filename : $2
save_ecannot2=You are not allowed to view this log
save_ecannot3=Error: You are not allowed to view this log
save_ecannot4=Error: Could not open '$1'
save_ecannot6=You are not allowed to view arbitrary logs
save_ecannot7=You are not allowed to view this extra log
save_emissing=Missing log file to view

View File

@@ -27,33 +27,139 @@ foreach $f (@files) {
return 0;
}
#
# Returns standard
# get_journal_since
# Returns a list of journalctl since commands
sub get_journal_since
{
return [
{ "" => $text{'journal_since0'} },
{ "-f" => $text{'journal_since1'} },
{ "-b" => $text{'journal_since2'} },
{ "-S '7 days ago'" => $text{'journal_since3'} },
{ "-S '24 hours ago'" => $text{'journal_since4'} },
{ "-S '8 hours ago'" => $text{'journal_since5'} },
{ "-S '1 hour ago'" => $text{'journal_since6'} },
{ "-S '30 minutes ago'" => $text{'journal_since7'} },
{ "-S '10 minutes ago'" => $text{'journal_since8'} },
{ "-S '3 minutes ago'" => $text{'journal_since9'} },
{ "-S '1 minute ago'" => $text{'journal_since10'} },
];
}
# get_systemctl_cmds([force-select])
# Returns logs for journalctl
sub get_systemctl_cmds
{
my $lines = $config{'lines'} || 1000;
return !&has_command('journalctl') ? () : (
{ 'cmd' => "journalctl --lines $lines -p alert..emerg",
'desc' => $text{'journal_journalctl_alert_emerg'},
'id' => "journal-1", },
{ 'cmd' => "journalctl --lines $lines -p err..crit",
'desc' => $text{'journal_journalctl_err_crit'},
'id' => "journal-2", },
{ 'cmd' => "journalctl --lines $lines -p notice..warning",
'desc' => $text{'journal_journalctl_notice_warning'},
'id' => "journal-3", },
{ 'cmd' => "journalctl --lines $lines -p debug..info",
'desc' => $text{'journal_journalctl_debug_info'},
'id' => "journal-4", },
{ 'cmd' => "journalctl --lines $lines -k ",
'desc' => $text{'journal_journalctl_dmesg'},
'id' => "journal-5", },
{ 'cmd' => "journalctl --lines $lines -x ",
'desc' => $text{'journal_expla_journalctl'},
'id' => "journal-6", },
{ 'cmd' => "journalctl --lines $lines",
my $fselect = shift;
my $lines = $in{'lines'} ? int($in{'lines'}) : int($config{'lines'}) || 1000;
my $journalctl_cmd = &has_command('journalctl');
return () if (!$journalctl_cmd);
my @rs = (
{ 'cmd' => "journalctl -n $lines",
'desc' => $text{'journal_journalctl'},
'id' => "journal-1", },
{ 'cmd' => "journalctl -n $lines -x ",
'desc' => $text{'journal_expla_journalctl'},
'id' => "journal-2", },
{ 'cmd' => "journalctl -n $lines -p alert..emerg",
'desc' => $text{'journal_journalctl_alert_emerg'},
'id' => "journal-3", },
{ 'cmd' => "journalctl -n $lines -p err..crit",
'desc' => $text{'journal_journalctl_err_crit'},
'id' => "journal-4", },
{ 'cmd' => "journalctl -n $lines -p notice..warning",
'desc' => $text{'journal_journalctl_notice_warning'},
'id' => "journal-5", },
{ 'cmd' => "journalctl -n $lines -p debug..info",
'desc' => $text{'journal_journalctl_debug_info'},
'id' => "journal-6", },
{ 'cmd' => "journalctl -n $lines -k ",
'desc' => $text{'journal_journalctl_dmesg'},
'id' => "journal-7", } );
# Add more units from config if exists on the system
my (%ucache, %uread);
my $units_cache = "$module_config_directory/units.cache";
&read_file($units_cache, \%ucache);
if (!%ucache) {
my $out = &backquote_command("systemctl list-units --all --no-legend ".
"--no-pager");
foreach my $line (split(/\r?\n/, $out)) {
$line =~ s/^[^a-z0-9\-\_\.]+//i;
my ($unit, $desc) = (split(/\s+/, $line, 5))[0, 4];
$uread{$unit} = $desc;
}
}
# All units
%ucache = %uread if (%uread);
# If forced to select, return full list
if ($fselect) {
my %units = %uread ? %uread : %ucache;
foreach my $u (sort keys %units) {
my $uname = $u;
$uname =~ s/\\x([0-9A-Fa-f]{2})/pack('H2', $1)/eg;
push(@rs, { 'cmd' => "journalctl -n ".
"$lines -u $u",
'desc' => $uname,
'id' => "journal-a-$u", });
}
}
# Otherwise, return only the pointer
# element for the index page
else {
push(@rs,
{ 'cmd' => "journalctl -n $lines -u",
'desc' => $text{'journal_journalctl_unit'},
'id' => "journal-u" });
}
# Save cache
if (%uread) {
&lock_file($units_cache);
&write_file($units_cache, \%ucache);
&unlock_file($units_cache);
}
return @rs;
}
# clear_systemctl_cache()
# Clear the cache of systemctl units
sub clear_systemctl_cache
{
unlink("$module_config_directory/units.cache");
}
# cleanup_destination(cmd)
# Returns a destination of some command cleaned up for display
sub cleanup_destination
{
my $cmd = shift;
$cmd =~ s/-n\s+\d+\s*//;
$cmd =~ s/\.service$//;
return $cmd;
}
# cleanup_description(desc)
# Returns a description cleaned up for display
sub cleanup_description
{
my $desc = shift;
$desc =~ s/\s+\(Virtualmin\)//;
return $desc;
}
# fix_clashing_description(description, service)
# Returns known clashing descriptions fixed
sub fix_clashing_description
{
my ($desc, $serv) = @_;
# EL systems name for PHP FastCGI Process Manager is repeated
if ($serv =~ /php(\d+)-php-fpm/) {
my $php_version = $1;
$php_version = join(".", split(//, $php_version));
$desc =~ s/PHP/PHP $php_version/;
}
return $desc;
}
# all_log_files(file)
@@ -138,5 +244,36 @@ foreach my $f (@rv) {
return @rv;
}
# config_post_save
# Called after the module's configuration has been saved
sub config_post_save
{
&clear_systemctl_cache();
}
# catter_command(file)
# Given a file that may be compressed, returns the command to output it in
# plain text, or undef if impossible
sub catter_command
{
local ($l) = @_;
local $q = quotemeta($l);
if ($l =~ /\.gz$/i) {
return &has_command("gunzip") ? "gunzip -c $q" : undef;
}
elsif ($l =~ /\.Z$/i) {
return &has_command("uncompress") ? "uncompress -c $q" : undef;
}
elsif ($l =~ /\.bz2$/i) {
return &has_command("bunzip2") ? "bunzip2 -c $q" : undef;
}
elsif ($l =~ /\.xz$/i) {
return &has_command("xz") ? "xz -d -c $q" : undef;
}
else {
return "cat $q";
}
}
1;

View File

@@ -1,7 +1,7 @@
name=logviewer
category=system
os_support=*-linux
desc=System Logs Viewer
desc=System Logs
depends=proc
longdesc=View and search all logs available on system
readonly=1

View File

@@ -7,7 +7,7 @@ require './logviewer-lib.pl';
&foreign_require("proc", "proc-lib.pl");
# Viewing a log file
@extras = &extra_log_files();
my @extras = &extra_log_files();
if ($in{'idx'} =~ /^\//) {
# The drop-down selector on this page has chosen a file
if (&indexof($in{'idx'}, (map { $_->{'file'} } @extras)) >= 0) {
@@ -21,11 +21,31 @@ if ($in{'idx'} =~ /^\//) {
delete($in{'idx'});
delete($in{'oidx'});
}
my $journal_since = &get_journal_since();
if ($in{'idx'} ne '') {
# From systemctl commands
if ($in{'idx'} =~ /^journal-/) {
my @systemctl_cmds = &get_systemctl_cmds();
my ($log) = grep { $_->{'id'} eq $in{'idx'} } @systemctl_cmds;
my @systemctl_cmds = &get_systemctl_cmds(1);
my ($log);
if ($in{'idx'} eq 'journal-u') {
($log) = grep { $_->{'cmd'} =~ /-u\s+\w+/ }
@systemctl_cmds;
$in{'idx'} = $log->{'id'};
}
else {
($log) = grep { $_->{'id'} eq $in{'idx'} }
@systemctl_cmds;
}
# If reverse is set, add it to the command
if ($reverse) {
$log->{'cmd'} .= " -r";
}
# If since is set and allowed, add it to the command
if ($in{'since'} &&
grep { $_ eq $in{'since'} }
map { keys %$_ } @$journal_since) {
$log->{'cmd'} .= " $in{'since'}";
}
&can_edit_log($log) && $access{'syslog'} ||
&error($text{'save_ecannot2'});
$cmd = $log->{'cmd'};
@@ -94,99 +114,204 @@ else {
}
print "Refresh: $config{'refresh'}\r\n"
if ($config{'refresh'});
&ui_print_header("<tt>".&html_escape($file || $cmd)."</tt>",
$in{'linktitle'} || $text{'view_title'}, "", undef, undef, $in{'nonavlinks'});
$lines = $in{'lines'} ? int($in{'lines'}) : int($config{'lines'});
$filter = $in{'filter'} ? quotemeta($in{'filter'}) : "";
my $lines = $in{'lines'} ? int($in{'lines'}) : int($config{'lines'});
my $jfilter = $in{'filter'} ? $in{'filter'} : "";
my $filter = $jfilter ? quotemeta($jfilter) : "";
my $reverse = $config{'reverse'} ? 1 : 0;
my $follow = $in{'since'} eq '-f' ? 1 : 0;
my $no_navlinks = $in{'nonavlinks'} == 1 ? 1 : undef;
my $skip_index = $config{'skip_index'} == 1 ? 1 : undef;
my $help_link = (!$no_navlinks && $skip_index) ?
&help_search_link("systemd-journal journalctl", "man", "doc") : undef;
my $no_links = $no_navlinks || $skip_index;
my $cmd_unpacked = $cmd;
$cmd_unpacked =~ s/\\x([0-9A-Fa-f]{2})/pack('H2', $1)/eg;
$cmd_unpacked =~ s/\s+\-r// if ($follow);
$cmd_unpacked =~ s/\s+\-n\s+\d+// if ($follow);
$cmd_unpacked .= " -g \"@{[&html_escape($jfilter)]}\"" if ($filter);
my $view_title = $in{'idx'} =~ /^journal/ ?
$text{'view_titlejournal'} : $text{'view_title'};
&ui_print_header("<tt>".&html_escape($file || $cmd_unpacked)."</tt>",
$in{'linktitle'} || $view_title, "", undef,
!$no_navlinks && $skip_index,
($no_navlinks || $skip_index) ? 1 : undef,
0, $help_link);
&filter_form();
$| = 1;
print "<pre>";
local $tailcmd = $config{'tail_cmd'} || "tail -n LINES";
$tailcmd =~ s/LINES/$lines/g;
if ($filter ne "") {
# Are we supposed to filter anything? Then use grep.
local @cats;
if ($cmd) {
# Getting output from a command
push(@cats, $cmd);
}
elsif ($config{'compressed'}) {
# All compressed versions
foreach $l (&all_log_files($file)) {
$c = &catter_command($l);
push(@cats, $c) if ($c);
}
}
else {
# Just the one log
@cats = ( "cat ".quotemeta($file) );
}
$cat = "(".join(" ; ", @cats).")";
if ($config{'reverse'}) {
$tailcmd .= " | tac";
}
$eflag = $gconfig{'os_type'} =~ /-linux/ ? "-E" : "";
$dashflag = $gconfig{'os_type'} =~ /-linux/ ? "--" : "";
if (@cats) {
$got = &proc::safe_process_exec(
"$cat | grep -i -a $eflag $dashflag $filter ".
"| $tailcmd",
0, 0, STDOUT, undef, 1, 0, undef, 1);
}
else {
$got = undef;
}
} else {
# Not filtering .. so cat the most recent non-empty file
if ($cmd) {
# Getting output from a command
$fullcmd = $cmd." | ".$tailcmd;
}
elsif ($config{'compressed'}) {
# Cat all compressed files
# Standard output
if (!$follow) {
$| = 1;
print "<pre>";
local $tailcmd = $config{'tail_cmd'} || "tail -n LINES";
$tailcmd =~ s/LINES/$lines/g;
my ($safe_proc_out, $safe_proc_out_got);
if ($filter ne "") {
# Are we supposed to filter anything? Then use grep.
local @cats;
$total = 0;
foreach $l (reverse(&all_log_files($file))) {
next if (!-s $l);
$c = &catter_command($l);
if ($c) {
$len = int(&backquote_command(
"$c | wc -l"));
$total += $len;
push(@cats, $c);
last if ($total > $in{'lines'});
if ($cmd) {
# Getting output from a command
push(@cats, $cmd);
}
elsif ($config{'compressed'}) {
# All compressed versions
foreach $l (&all_log_files($file)) {
$c = &catter_command($l);
push(@cats, $c) if ($c);
}
}
else {
# Just the one log
@cats = ( "cat ".quotemeta($file) );
}
$cat = "(".join(" ; ", @cats).")";
if ($reverse) {
$tailcmd .= " | tac" if ($cmd !~ /journalctl/);
}
$eflag = $gconfig{'os_type'} =~ /-linux/ ? "-E" : "";
$dashflag = $gconfig{'os_type'} =~ /-linux/ ? "--" : "";
if (@cats) {
$cat = "(".join(" ; ", reverse(@cats)).")";
$fullcmd = $cat." | ".$tailcmd;
my $fcmd;
if ($cmd =~ /journalctl/) {
$fcmd = "$cmd -g $filter";
}
else {
$fcmd = "$cat | grep -i -a $eflag $dashflag $filter ".
"| $tailcmd";
}
open(my $output_fh, '>', \$safe_proc_out);
$safe_proc_out_got = &proc::safe_process_exec(
$fcmd, 0, 0, $output_fh, undef, 1, 0, undef, 1);
close($output_fh);
print $safe_proc_out if ($safe_proc_out !~ /-- No entries --/m);
}
else {
$fullcmd = undef;
$safe_proc_out_got = undef;
}
} else {
# Not filtering .. so cat the most recent non-empty file
if ($cmd) {
# Getting output from a command
$fullcmd = $cmd.($cmd =~ /journalctl/ ? "" : (" | ".$tailcmd));
}
elsif ($config{'compressed'}) {
# Cat all compressed files
local @cats;
$total = 0;
foreach $l (reverse(&all_log_files($file))) {
next if (!-s $l);
$c = &catter_command($l);
if ($c) {
$len = int(&backquote_command(
"$c | wc -l"));
$total += $len;
push(@cats, $c);
last if ($total > $in{'lines'});
}
}
if (@cats) {
$cat = "(".join(" ; ", reverse(@cats)).")";
$fullcmd = $cat." | ".$tailcmd;
}
else {
$fullcmd = undef;
}
}
else {
# Just run tail on the file
$fullcmd = $tailcmd." ".quotemeta($file);
}
if ($reverse && $fullcmd) {
$fullcmd .= " | tac" if ($fullcmd !~ /journalctl/);
}
if ($fullcmd) {
open(my $output_fh, '>', \$safe_proc_out);
$safe_proc_out_got = &proc::safe_process_exec(
$fullcmd, 0, 0, $output_fh, undef, 1, 0, undef, 1);
close($output_fh);
print $safe_proc_out if ($safe_proc_out !~ /-- No entries --/m);
}
else {
$safe_proc_out_got = undef;
}
}
else {
# Just run tail on the file
$fullcmd = $tailcmd." ".quotemeta($file);
}
if ($config{'reverse'} && $fullcmd) {
$fullcmd .= " | tac";
}
if ($fullcmd) {
$got = &proc::safe_process_exec(
$fullcmd, 0, 0, STDOUT, undef, 1, 0, undef, 1);
}
else {
$got = undef;
}
print "<i data-empty>$text{'view_empty'}</i>\n"
if (!$safe_proc_out_got || $safe_proc_out =~ /-- No entries --/m);
print "</pre>\n";
}
# Progressive output
else {
print "<pre id='logdata' data-reversed='$reverse'>";
print "<i data-loading>$text{'view_loading'}</i>\n";
print "</pre>\n";
my %tinfo = &get_theme_info($current_theme);
my $spa_theme = $tinfo{'spa'} ? 1 : 0;
print <<EOF;
<script>
// Abort previous log viewer progress fetch
if (typeof fn_logviewer_progress_abort === 'function') {
fn_logviewer_progress_abort();
}
// Update log viewer with new data from the server
(async function () {
const logviewer_progress_abort = new AbortController();
const logDataElement = document.getElementById("logdata"),
response = await fetch("view_log_progress.cgi?idx=$in{'idx'}&filter=$jfilter",
{ signal: logviewer_progress_abort.signal }),
reader = response.body.getReader(),
decoder = new TextDecoder("utf-8"),
processText = async function () {
let { done, value } = await reader.read();
while (!done) {
const chunk = decoder.decode(value, { stream: true }).trim(),
dataReversed = logDataElement.getAttribute("data-reversed");
if (!processText.started) {
processText.started = true;
const loadingElement = logDataElement.querySelector("i[data-loading]");
if (loadingElement) {
loadingElement.remove();
}
}
let lines = chunk.split("\\n");
if (dataReversed === "1") {
lines = lines.reverse();
logDataElement.textContent =
lines.join("\\n") + "\\n" + logDataElement.textContent;
}
else {
logDataElement.textContent += lines.join("\\n") + "\\n";
}
if (typeof fn_logviewer_progress_update === 'function') {
fn_logviewer_progress_update(chunk, dataReversed);
}
({ done, value } = await reader.read());
}
};
if (typeof fn_logviewer_progress_status === 'function') {
fn_logviewer_progress_status(response);
}
fn_logviewer_progress_abort = function () {
logviewer_progress_abort.abort();
fn_logviewer_progress_abort = null;
}
if ($spa_theme !== 1) {
window.onbeforeunload = function() {
if (typeof fn_logviewer_progress_abort === 'function') {
fn_logviewer_progress_abort();
}
};
}
processText().catch((error) => {
if (typeof fn_logviewer_progress_ended === 'function') {
fn_logviewer_progress_ended(error);
}
});
})();
</script>
EOF
}
print "<i>$text{'view_empty'}</i>\n" if (!$got);
print "</pre>\n";
&filter_form();
if ($in{'nonavlinks'}) {
if ($no_links) {
&ui_print_footer();
}
else {
@@ -196,7 +321,9 @@ else {
sub filter_form
{
print &ui_form_start("view_log.cgi");
print &ui_hidden("nonavlinks", $in{'nonavlinks'} ? 1 : 0),"\n";
if ($no_navlinks) {
print &ui_hidden("nonavlinks", $no_navlinks),"\n";
}
print &ui_hidden("linktitle", $in{'linktitle'}),"\n";
print &ui_hidden("oidx", $in{'oidx'}),"\n";
print &ui_hidden("omod", $in{'omod'}),"\n";
@@ -210,10 +337,11 @@ my $found = 0;
my $text_view_header = 'view_header';
if ($access{'syslog'}) {
# Logs from syslog
my @systemctl_cmds = &get_systemctl_cmds();
my @systemctl_cmds = &get_systemctl_cmds(1);
foreach $c (@systemctl_cmds) {
next if (!&can_edit_log($c));
push(@logfiles, [ $c->{'id'}, "$c->{'desc'}" ]);
my $icon = $c->{'id'} =~ /journal-(a|x)/ ? "&#x25E6;&nbsp; " : "";
push(@logfiles, [ $c->{'id'}, $icon.$c->{'desc'} ]);
$found++ if ($c->{'id'} eq $in{'idx'});
}
@@ -267,18 +395,35 @@ foreach $e (&extra_log_files()) {
}
if (@logfiles && $found) {
$sel = &ui_select("idx", $in{'idx'} eq '' ? $file : $in{'idx'},
[ @logfiles ], undef, undef, undef, undef, "onChange='form.submit()'");
[ @logfiles ], undef, undef, undef, undef,
"onChange='form.submit()' style='max-width: 240px'");
if ($in{'idx'} =~ /^journal-/) {
my $since_label = $follow ? $text{'journal_sincefollow'} :
$text{'journal_since'};
$sel .= "$since_label&nbsp; " .
&ui_select("since", $in{'since'},
[ map { my ($key) = keys %$_;
[ $key, $_->{$key} ] }
@$journal_since ],
undef, undef, undef, undef,
"onChange='form.submit()'");
}
}
else {
$text_view_header = 'view_header2';
print &ui_hidden("idx", $in{'idx'}),"\n";
}
print &text($text_view_header, "&nbsp;" . &ui_textbox("lines", $lines, 3), "&nbsp;$sel"),"\n";
if ($follow) {
print &text('view_header3', "&nbsp;$sel"),"\n";
}
else {
print &text($text_view_header, "&nbsp;" . &ui_textbox("lines", $lines, 3), "&nbsp;$sel"),"\n";
}
print "&nbsp;&nbsp;&nbsp;&nbsp;\n";
print &text('view_filter', "&nbsp;" . &ui_textbox("filter", $in{'filter'}, 25)),"\n";
print &text('view_filter', "&nbsp;" . &ui_textbox("filter", $in{'filter'}, 12)),"\n";
print "&nbsp;&nbsp;\n";
print &ui_submit($text{'view_refresh'});
print &ui_submit($text{'view_filter_btn'});
print &ui_form_end(),"<br>\n";
}

47
logviewer/view_log_progress.cgi Executable file
View File

@@ -0,0 +1,47 @@
#!/usr/local/bin/perl
# view_log_progress.cgi
# Returns progressive output for some system log
require './logviewer-lib.pl';
&ReadParse();
&foreign_require("proc", "proc-lib.pl");
# Send headers
print "Content-Type: text/plain\n\n";
# System log to follow
my @systemctl_cmds = &get_systemctl_cmds(1);
my ($log) = grep { $_->{'id'} eq $in{'idx'} } @systemctl_cmds;
if (!&can_edit_log($log) ||
!$log->{'cmd'} ||
$log->{'cmd'} !~ /^journalctl/) {
print $text{'save_ecannot3'};
exit;
}
# Disable output buffering
$| = 1;
# No lines for real time logs
$log->{'cmd'} =~ s/\s+\-n\s+\d+//;
# Show real time logs
$log->{'cmd'} .= " -f";
# Add filter to the command if present
my $filter = $in{'filter'} ? quotemeta($in{'filter'}) : "";
if ($filter) {
$log->{'cmd'} .= " -g $filter";
}
# Open a pipe to the journalctl command
my $pid = open(my $fh, '-|', $log->{'cmd'}) ||
print &text('save_ecannot4', $log->{'cmd'}).": $!";
# Read and output the log
while (my $line = <$fh>) {
print $line;
}
# Clean up when done
close($fh);

Some files were not shown because too many files have changed in this diff Show More