Compare commits

...

173 Commits
1.983 ... 1.990

Author SHA1 Message Date
Jamie Cameron
010936b111 Major version bump 2022-03-01 20:39:53 -08:00
Jamie Cameron
f365761bd3 Use legacy command in init script if installed https://github.com/webmin/webmin/issues/1603 2022-02-27 16:55:38 -08:00
Jamie Cameron
1279626597 Fail nicely if there is no zone file https://forum.virtualmin.com/t/trouble-with-server-creation-and-dnssec-key/114027/10 2022-02-23 16:28:00 -08:00
Jamie Cameron
c480b26605 Small version bump 2022-02-21 17:21:39 -08:00
Jamie Cameron
3050508644 Merge branch 'master' of github.com:webmin/webmin 2022-02-21 16:56:39 -08:00
Jamie Cameron
d300bc1b07 Disallow any top-level directories 2022-02-21 16:53:34 -08:00
Ilia Rostovtsev
e77b0a8dd0 Update translations 2022-02-22 02:45:45 +03:00
Ilia Rostovtsev
fe83967c94 Merge remote-tracking branch 'origin/master' 2022-02-22 02:37:35 +03:00
Ilia Rostovtsev
bd6912deaa Allow escaping log page; add title from caller cc1d97cdd8 2022-02-22 02:37:10 +03:00
Jamie Cameron
778d67f662 Don't allow tempdir to be set to /tmp 2022-02-21 15:14:01 -08:00
Jamie Cameron
627d86f9e8 Don't ever delete /tmp 2022-02-21 15:06:00 -08:00
Jamie Cameron
c8d3e737bd Use consistent function for server name 2022-02-20 20:04:26 -08:00
Jamie Cameron
0176449a81 Check for any of the drive IDs 2022-02-20 19:59:35 -08:00
Jamie Cameron
fe9573eaa2 Fail fast if there's no zone file 2022-02-20 19:58:38 -08:00
Jamie Cameron
7c36902b12 Check harder if syslog-ng is actually being used 2022-02-20 19:57:25 -08:00
Jamie Cameron
232d012a67 Check if syslog-ng is actually running 2022-02-20 19:54:53 -08:00
Jamie Cameron
491a91dbfc Use ui-lib 2022-02-20 19:51:06 -08:00
Jamie Cameron
61892753b7 Use new ui-lib, and add columns for in and out traffic https://github.com/webmin/webmin/issues/1600 2022-02-20 13:01:16 -08:00
Ilia Rostovtsev
6f9f8c5182 Fix missing permission file creation for safe user in some modules 2022-02-20 16:32:57 +03:00
Ilia Rostovtsev
39ea464f0c Foreign module may need a check 2022-02-20 12:48:27 +03:00
Jamie Cameron
b374ad7d28 Use grid table UI 2022-02-19 15:39:39 -08:00
Jamie Cameron
22964473ec Fix wording 2022-02-19 15:32:13 -08:00
Jamie Cameron
e5baa97295 Use new UI lib 2022-02-19 15:29:02 -08:00
Jamie Cameron
548c554a09 Merge branch 'master' of github.com:webmin/webmin 2022-02-19 13:11:03 -08:00
Jamie Cameron
eeeea3c097 Add missing permissions check when saving allowed cron users 2022-02-19 13:10:36 -08:00
Ilia Rostovtsev
3bd9b9dcbe Add status to systemd services 2022-02-19 16:17:23 +03:00
Jamie Cameron
f472208894 Add a security page 2022-02-19 00:02:51 -08:00
Jamie Cameron
c686cfab4e State can be active (exited) when a service is down https://forum.virtualmin.com/t/apparmor/113924/12 2022-02-17 15:43:55 -08:00
Jamie Cameron
dd8685b71a Handle case of disks with multiple IDs that might change 2022-02-15 19:47:41 -08:00
Jamie Cameron
7c8f750364 Disks can have multiple IDs 2022-02-15 19:32:17 -08:00
Jamie Cameron
d44df676bf Merge branch 'master' of github.com:webmin/webmin 2022-02-11 22:24:04 -08:00
Jamie Cameron
aad57cca7c No need for allow from all under Apache 2.4+ 2022-02-11 22:23:23 -08:00
Ilia Rostovtsev
b54a6388ba No need for heading in default table mode 2022-02-10 15:27:06 +03:00
Jamie Cameron
7474f4399f Fix perl warning 2022-02-09 22:40:14 -08:00
Jamie Cameron
feaa6e76c6 Add warning if Virtualmin manages the procmail config 2022-02-09 21:41:52 -08:00
Jamie Cameron
34a6e393ce defang_mime isn't used after version 2.6 2022-02-09 18:54:28 -08:00
Jamie Cameron
30c9cc1b21 detailed_phrase_score isn't used after version 2.6 2022-02-09 18:52:22 -08:00
Jamie Cameron
f794426715 Perl is required for the pre-install script https://sourceforge.net/p/webadmin/bugs/5548/ 2022-02-08 19:47:14 -08:00
Jamie Cameron
23b11d340d Don't try to load firewall6-lib.pl https://github.com/webmin/webmin/issues/1596 2022-02-07 22:07:50 -08:00
Jamie Cameron
6a4ca6f5a2 Merge branch 'master' of github.com:webmin/webmin 2022-02-07 17:41:01 -08:00
Jamie Cameron
8c0fb0ab83 Don't show disk space warnings to domain owners https://github.com/virtualmin/virtualmin-gpl/issues/368 2022-02-07 17:40:37 -08:00
Ilia Rostovtsev
561d53d90e Update to improve globals API 2022-02-08 01:36:01 +03:00
Ilia Rostovtsev
403fe939e0 Fix to store variable before deleted 2022-02-07 17:17:53 +03:00
Ilia Rostovtsev
3225be4ad1 Add support for getting and deleting global vars at once 2022-02-07 17:07:51 +03:00
Jamie Cameron
e00939dc24 Use a better function to map the config file to the pool directory 2022-02-06 13:35:52 -08:00
Jamie Cameron
5b7ccc0342 Merge pull request #1594 from webmin/dev/restart-correct-php-fpm
Fix to restart correct PHP-FPM service
2022-02-06 13:30:37 -08:00
Jamie Cameron
73dd030255 Merge pull request #1595 from webmin/dev/fix-systemd-service-detection
Fix systemd service detection
2022-02-06 13:24:25 -08:00
Ilia Rostovtsev
682a7910ec Fix indent 2022-02-06 21:05:05 +03:00
Ilia Rostovtsev
ef0d07f55b Fix systemd service detection
https://github.com/virtualmin/virtualmin-pro/issues/16#issuecomment-1030869911
2022-02-06 21:03:59 +03:00
Ilia Rostovtsev
f774fe73b6 Fix to quotemeta dir 2022-02-06 20:39:54 +03:00
Ilia Rostovtsev
30a3c3c052 Fix to restart correct PHP-FPM service 2022-02-06 20:35:29 +03:00
Ilia Rostovtsev
8370a5958f Fix help links 2022-02-03 23:06:01 +03:00
Jamie Cameron
0424069d59 Merge branch 'master' of github.com:webmin/webmin 2022-02-01 19:34:50 -08:00
Jamie Cameron
dd5bce5adf Always set ENV{'PASS'} when needed https://sourceforge.net/p/webadmin/bugs/5542/ 2022-02-01 19:34:40 -08:00
Ilia Rostovtsev
323e789c16 Fix to quotemeta when generating certs
https://github.com/virtualmin/virtualmin-gpl/issues/363#issuecomment-1026438307
2022-02-02 01:08:27 +03:00
Ilia Rostovtsev
4f9cba0b33 Fix to drop beloved line separators for Apache config formatter 2022-02-01 22:44:00 +03:00
Jamie Cameron
9146fc9969 Merge branch 'master' of github.com:webmin/webmin 2022-01-31 20:54:20 -08:00
Jamie Cameron
8e378129d0 Replacement field in NAPTR doesn't need quotes 2022-01-31 20:53:55 -08:00
Ilia Rostovtsev
292db2b760 Add more quotemeta escapes for commands 2022-01-31 13:29:13 +03:00
Ilia Rostovtsev
a8084803db Add more quotemeta commands escapes
https://github.com/webmin/webmin/issues/1587
2022-01-31 03:25:43 +03:00
Jamie Cameron
c1b0147a98 Merge branch 'master' of github.com:webmin/webmin 2022-01-30 14:21:16 -08:00
Jamie Cameron
909b1d56f8 Add support for NAPTR records 2022-01-30 14:20:30 -08:00
Ilia Rostovtsev
b647c2c084 Fix to display sub-title in virtual server mode 2022-01-30 16:47:06 +03:00
Jamie Cameron
80ac0fdbc9 Merge pull request #1588 from webmin/dev/usermin-redirect-url
Add support for custom redirect URL for Usermin
2022-01-29 19:39:24 -08:00
Jamie Cameron
536827a96a Quote everything https://github.com/webmin/webmin/issues/1587 2022-01-28 18:11:41 -08:00
Jamie Cameron
d17f01b33a Merge branch 'master' of github.com:webmin/webmin 2022-01-28 15:40:21 -08:00
Jamie Cameron
f35b08dc94 Ensure socket is closed after an error 00~https://github.com/webmin/webmin/issues/158401~ 2022-01-28 15:39:57 -08:00
Jamie Cameron
c6bedaa4f7 Merge pull request #1589 from bctrainers/master
LetsEncrypt Staging URL update
2022-01-27 21:17:14 -08:00
Ilia Rostovtsev
23f853384d Display no return to index when searched from other location 2022-01-27 15:11:02 +03:00
Ilia Rostovtsev
525a835d23 Reset Virtualmin links if logging enabled/disabled 2022-01-27 15:07:25 +03:00
Ilia Rostovtsev
73244f2ba7 Always add a reference for inline tag printing! 2022-01-27 14:54:35 +03:00
Ilia Rostovtsev
08388f58ed Display not return to module index button if searched from outside 2022-01-27 14:49:47 +03:00
Brett
deebc0091a LE Staging URL update
LetsEncrypt staging URL changed per https://letsencrypt.org/docs/staging-environment/
2022-01-27 05:49:30 -06:00
Ilia Rostovtsev
ad24c08fda Optionally hide return to module button for external searches 2022-01-27 14:40:22 +03:00
Ilia Rostovtsev
b7a865d1cf Allow custom title when searching from Virtualmin or other 2022-01-27 14:31:09 +03:00
Ilia Rostovtsev
ef2657364a Add support for custom redirect URL for Usermin 2022-01-27 13:26:35 +03:00
Ilia Rostovtsev
f94c695cdd Fix to swap var names for setting errors 2022-01-26 23:14:53 +03:00
Ilia Rostovtsev
6ff61e8001 Register error-fatal and error-fatal-ignored vars 2022-01-26 14:17:08 +03:00
Ilia Rostovtsev
374f020ce7 Fix to use quotemeta instead 3c687b46be (commitcomment-64599299) 2022-01-25 23:37:15 +03:00
Ilia Rostovtsev
3c687b46be Fix to consider filenames with spaces 2022-01-25 17:31:21 +03:00
Jamie Cameron
758db4c2f5 Improve folder locking functions for use in Usermin 2022-01-23 11:46:08 -08:00
Jamie Cameron
59a5332c21 Merge branch 'master' of github.com:webmin/webmin 2022-01-23 10:04:38 -08:00
Jamie Cameron
22ecccbd1d Fix perl warnings https://sourceforge.net/p/webadmin/bugs/5540/ 2022-01-23 10:04:17 -08:00
Ilia Rostovtsev
e345ba5d4f Fix comment 2022-01-23 20:39:38 +03:00
Ilia Rostovtsev
08fd846c0f Fix indent 2022-01-23 16:57:24 +03:00
Ilia Rostovtsev
d92a35ac3c Add API to control global vars better
966d44ede5
d5082236f6
2022-01-23 16:52:31 +03:00
Jamie Cameron
e8c35eaac7 Merge pull request #1586 from gratuxri/patch-1
Fix Return to Records if using views
2022-01-22 16:16:12 -08:00
gratuxri
47f51a4a83 Fix Return to Records if using views 2022-01-23 00:17:03 +01:00
Jamie Cameron
f5ef354f57 Merge pull request #1585 from danci1973/dmarc_tags
Added missing DMARC tags (fr ri) #1583
2022-01-22 11:37:44 -08:00
danci
72fdc331a6 Added missing DMARC tags (fr ri)
Committer: danci <danci@barbie.agenda.si>

 On branch dmarc_tags
 Changes to be committed:
	modified:   bind8/bind8-lib.pl
	modified:   bind8/lang/en
	modified:   bind8/records-lib.pl
	modified:   bind8/save_record.cgi
2022-01-22 20:10:41 +01:00
Jamie Cameron
89f6c07ce3 Twofactor token can be 16, 26 or 32 characters 2022-01-18 22:26:06 -08:00
Jamie Cameron
9e8747ede4 Add extra check for wrong packet size https://forum.virtualmin.com/t/virtualmin-backup-truncates-part-of-mysql-dump-without-generating-error/113551/9 2022-01-12 21:11:51 -08:00
Jamie Cameron
652d40801b Merge branch 'master' of github.com:webmin/webmin 2022-01-11 20:39:11 -08:00
Jamie Cameron
5ca4ed73b2 Password never contains newlines 2022-01-11 20:36:19 -08:00
Ilia Rostovtsev
df3b5eb94c Add ability to return a list of other Webmin servers as JSON 2022-01-12 00:36:52 +03:00
Jamie Cameron
5a508eb0e9 TTL can be zero https://github.com/webmin/webmin/issues/1577 2022-01-10 21:39:37 -08:00
Jamie Cameron
344bd72f0d Merge branch 'master' of github.com:webmin/webmin 2022-01-10 21:31:33 -08:00
Jamie Cameron
0d6b655314 Check for more algorithms https://github.com/webmin/webmin/issues/1576 2022-01-10 21:10:43 -08:00
Ilia Rostovtsev
60a5ea924e Add better duped uploads name; extract on upload predictably 2022-01-06 14:47:47 +03:00
Jamie Cameron
0e1f7d8d72 Cache list of systemd services https://forum.virtualmin.com/t/new-way-to-copy-system-information-data/113433/12 2022-01-04 22:41:34 -08:00
Jamie Cameron
2602f8dbe1 Don't read init scripts if not looking for one https://forum.virtualmin.com/t/new-way-to-copy-system-information-data/113433/12 2022-01-04 22:35:18 -08:00
Jamie Cameron
14962255a9 Fix dpkg output parsing https://sourceforge.net/p/webadmin/bugs/5538/ 2022-01-04 20:41:56 -08:00
Jamie Cameron
5f25929596 Merge branch 'master' of github.com:webmin/webmin 2022-01-03 11:22:12 -08:00
Jamie Cameron
176d890ebc Fix URL for downloading debian package of usermin https://sourceforge.net/p/webadmin/bugs/5538/ 2022-01-03 11:21:32 -08:00
Ilia Rostovtsev
41eeff8eca Add API to return current monitors status
https://github.com/virtualmin/authentic-theme/issues/1574#issuecomment-1003697841

Output example:

```
'bind8' => {
    'icon' => '/status/images/down.gif',
    'icon_title' => 'Local',
    'status' => 0,
    'status_text' => '<font color=#ff0000>Down</font>',
    'title' => 'BIND DNS Server'
  },
```
2022-01-02 16:06:01 +03:00
Jamie Cameron
d996e99c60 Fix ubuntu version detection for development release names 2022-01-01 22:13:28 -08:00
Jamie Cameron
d685e8aec1 Never prompt the user for an OS .. just fail https://sourceforge.net/p/webadmin/bugs/5536/ 2022-01-01 18:40:28 -08:00
Jamie Cameron
68a7ca85ba Make warning about missing crond more obvious 2021-12-31 23:17:11 -08:00
Jamie Cameron
b8d5b7afde Add stop/start buttons 2021-12-31 23:11:53 -08:00
Jamie Cameron
8a51d178df Fix unix permissions 2021-12-31 22:06:33 -08:00
Jamie Cameron
8e2a5fa7ad Clean up message names 2021-12-31 22:05:43 -08:00
Jamie Cameron
c29682afc7 Better handle case where some requested packages don't exist 2021-12-31 12:28:22 -08:00
Jamie Cameron
41800b10f9 Uninstall scripts can exist for themes too 2021-12-28 21:00:10 -08:00
Jamie Cameron
0e3b7e4d94 IPset code cleanup and better rule description 2021-12-27 13:27:31 -08:00
Jamie Cameron
ebe9d58594 Add support for editing IPset match rules 2021-12-27 13:08:26 -08:00
Jamie Cameron
24b3715b95 Fix ipset display 2021-12-27 12:33:40 -08:00
Jamie Cameron
250e579fe4 Merge branch 'master' of github.com:webmin/webmin 2021-12-27 11:14:23 -08:00
Jamie Cameron
ad1b65621b Make warning more scary 2021-12-27 11:13:04 -08:00
Ilia Rostovtsev
68f02e8e2b Add Ubuntu 21 and 22 detection 2021-12-27 14:14:10 +03:00
Jamie Cameron
1a12d6d560 Fix formatting 2021-12-26 22:52:02 -08:00
Jamie Cameron
dbf9c9c96b Recognize --match-set 2021-12-26 22:46:54 -08:00
Jamie Cameron
cc7e470139 Merge branch 'master' of github.com:webmin/webmin 2021-12-26 20:29:28 -08:00
Jamie Cameron
15243eff0d Add option for memcache session path 2021-12-26 20:21:32 -08:00
Ilia Rostovtsev
25a0a79b42 Add support for template substitution; fix bug for datetime replace 2021-12-26 19:45:53 +03:00
Jamie Cameron
158d0e7c34 New version bump 2021-12-25 12:51:53 -08:00
Jamie Cameron
c834423046 Fix duplicate string 2021-12-25 12:51:09 -08:00
Jamie Cameron
37191fb1c8 Remove duplicate %in 2021-12-25 12:46:41 -08:00
Ilia Rostovtsev
1579671702 Add new substitute_pattern API 2021-12-25 22:43:44 +03:00
Jamie Cameron
473776455d Non-empty hashes written to files should never be empty 2021-12-24 13:02:39 -08:00
Jamie Cameron
4c865c5fc8 Add missing quote 2021-12-24 10:21:02 -08:00
Jamie Cameron
134311032e Show leases inside shared networks as well https://sourceforge.net/p/webadmin/bugs/5534/ 2021-12-23 21:47:44 -08:00
Jamie Cameron
a37b82d0d1 Merge branch 'master' of github.com:webmin/webmin 2021-12-20 22:01:21 -08:00
Jamie Cameron
210bf899d1 changelog for fail2ban feature 2021-12-20 22:01:06 -08:00
Ilia Rostovtsev
fb0b5fac8f Add overwrite control when uploading a file in File Manager 2021-12-20 21:47:34 +03:00
Ilia Rostovtsev
216b8ea2e4 Fix to match a token multiple times
https://sourceforge.net/p/webadmin/bugs/5535/
2021-12-16 13:55:29 +03:00
Jamie Cameron
d95e2caca9 If any fail2ban rules already exist before applying, re-merge them 2021-12-15 22:10:29 -08:00
Jamie Cameron
41214d6d96 Merge branch 'master' of github.com:webmin/webmin 2021-12-14 11:03:51 -08:00
Jamie Cameron
3542519fe2 Allow HTTP codes to be selected https://github.com/webmin/webmin/issues/1564 2021-12-14 10:58:24 -08:00
Ilia Rostovtsev
a4a3e867bc Update translations 2021-12-14 20:17:10 +03:00
Jamie Cameron
01fcf9648f Include failed login logger 2021-12-13 15:33:12 -08:00
Ilia Rostovtsev
e2ebee2bb0 Fix to expand passed parameters for webmin_log 2021-12-13 22:11:28 +03:00
Jamie Cameron
d9b8ecbba7 Merge branch 'master' of github.com:webmin/webmin 2021-12-12 19:20:04 -08:00
Jamie Cameron
33232622d3 Use tabs to simplify the page 2021-12-12 18:50:09 -08:00
Ilia Rostovtsev
ee921a67e7 Fix stomped table header for Webmin Action Log module index page 2021-12-12 19:00:00 +03:00
Ilia Rostovtsev
0db149e7c5 Fix to prevent theme making HTML data
This is still `$main::webmin_script_type eq 'web'` so theme thinks it's going to UI
2021-12-12 18:49:17 +03:00
Ilia Rostovtsev
0b840ff8b6 Update translations 2021-12-12 18:39:16 +03:00
Jamie Cameron
92dbe035c6 Add option to control notification subject 2021-12-11 22:34:50 -08:00
Jamie Cameron
a75f7d5a57 Set user environment variable, as remote_user gets re-set from it: 2021-12-11 20:54:11 -08:00
Jamie Cameron
10e9664ecf Updates to the notification email form 2021-12-10 23:54:01 -08:00
Jamie Cameron
b3cb270cca Respect allowed user list for logging to email 2021-12-10 23:52:44 -08:00
Jamie Cameron
d7915e785b Form to save notification settings 2021-12-10 22:14:56 -08:00
Jamie Cameron
795fbc6449 Add ACL for setting up notifications 2021-12-10 21:47:56 -08:00
Jamie Cameron
9b164397b0 Form for setting up notifications 2021-12-10 21:25:53 -08:00
Jamie Cameron
974b18a52c Set DNSn keys if the operating system supports them 2021-12-10 20:57:33 -08:00
Jamie Cameron
aab80b67b9 Don't alloction an IPv6 socket if not supported 2021-12-08 08:56:17 -08:00
Jamie Cameron
098a7a0080 Merge branch 'master' of github.com:webmin/webmin 2021-12-08 08:54:41 -08:00
Jamie Cameron
73c0209111 Fix duplicate import 2021-12-08 08:51:28 -08:00
Ilia Rostovtsev
732941d30a Fix to handle removed options in MySQL 8 #1561 2021-12-08 15:59:33 +03:00
Ilia Rostovtsev
ba25971b89 Revert "Add missing lib call"
This reverts commit d4c61774ee.
2021-12-08 12:29:44 +03:00
Jamie Cameron
951fcc8e51 Merge branch 'master' of github.com:webmin/webmin 2021-12-06 19:41:44 -08:00
Jamie Cameron
56a7828978 Add function to cleanup let's encrypt files for a domain 2021-12-06 19:41:37 -08:00
Ilia Rostovtsev
d4c61774ee Add missing lib call
https://forum.virtualmin.com/t/new-version-of-webmin-causes-problem-with-my-cron/113175/15
2021-12-06 18:47:04 +03:00
Jamie Cameron
92369af3d7 Support systems with more than 10 disks https://sourceforge.net/p/webadmin/bugs/5530/ 2021-12-04 08:44:28 -08:00
Jamie Cameron
1784fc8609 Use forced IP for the transfer if there is one 2021-12-03 22:39:18 -08:00
Jamie Cameron
9df4b2b32d Fix use of IPv6 for file transfers https://forum.virtualmin.com/t/new-version-of-webmin-causes-problem-with-my-cron/113175/9 2021-12-03 22:12:00 -08:00
Jamie Cameron
2adb22b9b8 Merge pull request #1560 from webmin/dev/add-link-mod-lib
Add `link-lib.pl` for module config not to fail
2021-12-03 19:37:26 -08:00
Ilia Rostovtsev
ff2bc98975 Add empty link-lib.pl for module config not to fail
Otherwise the error is getting returned - Require link/link-lib.pl failed : Died at (eval 300) line 1.
2021-12-04 00:46:58 +03:00
Ilia Rostovtsev
52e87db941 Revert not to include webprefix in redirect 2021-12-04 00:33:34 +03:00
Ilia Rostovtsev
439c80d08c Fix bookmarks in File Manager in older themes
https://sourceforge.net/p/webadmin/bugs/5525/
2021-12-03 22:28:16 +03:00
Ilia Rostovtsev
0a3f8985d0 Fix regex for CPU temp https://github.com/webmin/webmin/issues/1552#issuecomment-985504912 2021-12-03 21:58:16 +03:00
Jamie Cameron
5650af58c0 Merge pull request #1559 from niyari/patch-link
Update /link ja translations
2021-12-02 23:35:57 -08:00
niyari
24c08f9079 Fix newline at eof 2021-12-03 16:17:22 +09:00
niyari
f5d4c1bdcf Update /link ja translations 2021-12-03 14:53:06 +09:00
286 changed files with 2805 additions and 794 deletions

View File

@@ -29,7 +29,7 @@ Webmin can be installed in two different ways:
1. By downloading a pre-built package, available for different distributions (CentOS, Fedora, SuSE, Mandriva, Debian, Ubuntu, Solaris and [other](http://www.webmin.com/support.html)) from our [download page](http://webmin.com/download.html);
<kbd>Note: It is highly recommended to [add repository](https://doxfer.webmin.com/Webmin/Installation) to your system for having automatic updates.</kbd>
2. By downloading, extracting [source file](https://prdownloads.sourceforge.net/webadmin/webmin-1.983.tar.gz), and running [_setup.sh_](http://www.webmin.com/tgz.html) script, with no arguments, which will setup to run it directly from this directory, or with a command-line argument, such as targeted directory.
2. By downloading, extracting [source file](https://prdownloads.sourceforge.net/webadmin/webmin-1.990.tar.gz), and running [_setup.sh_](http://www.webmin.com/tgz.html) script, with no arguments, which will setup to run it directly from this directory, or with a command-line argument, such as targeted directory.
<kbd>Note: If you are installing Webmin [on Windows](http://www.webmin.com/windows.html) system, you must run the command `perl setup.pl` instead. The Windows version depends on several programs, and modules that may not be part of the standard distribution. You will need _process.exe_ commmand, _sc.exe_ command, and _Win32::Daemon_ Perl module.</kbd>
## Documentation

23
SECURITY.md Normal file
View File

@@ -0,0 +1,23 @@
## Reporting Security Issues
Please send all reports of security issues found in Webmin to security@webmin.com
via email, ideally PGP encrypted with the key from https://www.webmin.com/jcameron-key.asc .
Potential security issues, in descending order of impact, include :
* Remotely exploitable attacks that allow `root` access to Webmin without
any credentials.
* Privilege escalation vulnerabilities that allow non-`root` users of Webmin
to run commands or access files as `root`.
* XSS attacks that target users already logged into Webmin when they visit
another website.
Things that are not actually security issues include :
* XSS attacks that are blocked by Webmin's referrer checks, which are enabled
by default.
* Attacks that require modifications to Webmin's code or configuration, which
can only be done by someone who already has `root` permissions.

File diff suppressed because one or more lines are too long

View File

@@ -651,7 +651,7 @@ else {
my $deny = $user->{'deny'};
$deny =~ s/:/;/g if ($deny);
foreach my $l (@pwfile) {
if ($l =~ /^([^:]+):([^:]*)/ && $1 eq $username) {
if ($l =~ /^([^:]+):([^:\r\n]*)/ && $1 eq $username) {
&add_old_password($user, "$2", \%miniserv);
&print_tempfile($fh,
$user->{'name'},":",

View File

@@ -2168,23 +2168,6 @@ foreach my $l (@{$conf_lref}) {
if ($conf_block_opening == $conf_block_closing) {
my $conf_lvl = 0;
my $conf_prev_line;
my $conf_curr_line;
my $conf_virthost;
my @confs_separate =
(
'Protocols',
'SuexecUserGroup',
'ServerName',
'ScriptAlias',
'DocumentRoot',
'ErrorLog',
'DirectoryIndex',
'Alias',
'RewriteEngine',
'Fcgid',
'SSL',
);
foreach my $l (@{$conf_lref}) {
my $indent_current = $indent x $conf_lvl;
@@ -2194,59 +2177,20 @@ if ($conf_block_opening == $conf_block_closing) {
# Indent up next line if a new block
if ($l =~ /(<[a-zA-Z]+).*>/) {
$conf_lvl++;
if ($l =~ /(<VirtualHost).*>/) {
$conf_virthost++;
}
}
# Indent down next line if a closing block
if ($l =~ /(<\/[a-zA-Z]+).*>/) {
$conf_lvl--;
if ($l =~ /(<\/VirtualHost).*>/) {
$conf_virthost--;
}
# Change current indent right now as it is a closing block
$indent_current = $indent x $conf_lvl;
}
}
# Store previous and current lines
$conf_prev_line = &trim($conf_curr_line);
$conf_curr_line = &trim($l);
# Replace beginning spaces with needed indent
$l =~ s/^\s*/$indent_current/
if($l);
# Check if current line needs to be prepended
# with a new line for better readability
if (!$config{'format_config_lines'}) {
# Allow new line insertion only inside of VirtualHost block
if ($conf_virthost) {
# If current line is not part of a commented block
if ($conf_curr_line !~ /^\s*#/) {
# If previous line is not already an empty line
if (length($conf_prev_line)) {
# If the previous line was something
# we want to take a break before and after match
if (grep {$conf_curr_line =~ /^$_/} @confs_separate &&
grep {$conf_prev_line !~ /^$_/} @confs_separate) {
# If not the first directive in VirtualHost
if($conf_prev_line !~ /(^<VirtualHost).*>/) {
$l = "\n$l"
}
}
# If current is opening block
elsif ($conf_curr_line =~ /(^<[a-zA-Z]+).*>/) {
$l = "\n$l";
}
}
}
}
}
}
}
}

View File

@@ -217,15 +217,17 @@ push(@mems, @cmems);
if ($in{'adddir'} && $in{'root'}) {
# Add a <Directory> section for the root
my @dmems;
if ($httpd_modules{'core'} < 2.4) {
push(@dmems, { 'name' => 'allow',
'value' => 'from all' });
}
push(@dmems, { 'name' => 'Options',
'value' => 'None' });
$dirsect = { 'name' => 'Directory',
'value' => "\"$in{'root'}\"",
'type' => 1,
'members' => [
{ 'name' => 'allow',
'value' => 'from all' },
{ 'name' => 'Options',
'value' => 'None' },
],
'members' => \@dmems,
};
if ($httpd_modules{'core'} >= 2.4) {
# Apache 2.4+ needs a 'Require all granted' line

View File

@@ -5,17 +5,16 @@ do 'bandwidth-lib.pl';
# Output HTML for editing security options for the acl module
sub acl_security_form
{
print "<tr> <td><b>$text{'acl_setup'}</b></td> <td>\n";
printf "<input type=radio name=setup value=1 %s> $text{'yes'}\n",
$o->{'setup'} ? 'checked' : '';
printf "<input type=radio name=setup value=0 %s> $text{'no'}</td> </tr>\n",
$o->{'setup'} ? '' : 'checked';
my ($o) = @_;
print &ui_table_row($text{'acl_setup'},
&ui_yesno_radio("setup", $o->{'setup'}));
}
# acl_security_save(&options)
# Parse the form for security options for the acl module
sub acl_security_save
{
$_[0]->{'setup'} = $in{'setup'};
my ($o) = @_;
$o->{'setup'} = $in{'setup'};
}

View File

@@ -8,12 +8,12 @@
BEGIN { push(@INC, ".."); };
use WebminCore;
&init_config();
if (&foreign_installed("syslog-ng")) {
&foreign_require("syslog-ng", "syslog-ng-lib.pl");
if (&foreign_installed("syslog-ng", 1) == 2) {
&foreign_require("syslog-ng");
$syslog_module = "syslog-ng";
}
elsif (&foreign_installed("syslog")) {
&foreign_require("syslog", "syslog-lib.pl");
&foreign_require("syslog");
$syslog_module = "syslog";
}
else {

View File

@@ -124,54 +124,47 @@ elsif ($missingrule || !$sysconf) {
if (@hours) {
# Show reporting form
print &ui_form_start("index.cgi");
print "<table>\n";
print &ui_table_start(undef, undef, 2);
print "<tr> <td><b>$text{'index_by'}</b></td>\n";
print "<td>",&ui_select("by", $in{'by'},
[ [ 'hour', $text{'index_hour'} ],
[ 'day', $text{'index_day'} ],
[ 'host', $text{'index_host'} ],
[ 'proto', $text{'index_proto'} ],
[ 'iport', $text{'index_iport'} ],
[ 'oport', $text{'index_oport'} ],
[ 'port', $text{'index_port'} ] ]),"</td>\n";
print &ui_table_row($text{'index_by'},
&ui_select("by", $in{'by'},
[ [ 'hour', $text{'index_hour'} ],
[ 'day', $text{'index_day'} ],
[ 'host', $text{'index_host'} ],
[ 'proto', $text{'index_proto'} ],
[ 'iport', $text{'index_iport'} ],
[ 'oport', $text{'index_oport'} ],
[ 'port', $text{'index_port'} ] ]));
print "<td><b>$text{'index_for'}</b></td>\n";
print "<td>",&ui_select("for", $in{'for'},
[ [ '', $text{'index_all'} ],
[ 'host', $text{'index_forhost'} ],
[ 'proto', $text{'index_forproto'} ],
[ 'iport', $text{'index_foriport'} ],
[ 'oport', $text{'index_foroport'} ] ]),"\n";
print &ui_textbox("what", $in{'for'} ? $in{'what'} : "", 20),
"</td> </tr>\n";
print &ui_table_row($text{'index_for'},
&ui_select("for", $in{'for'},
[ [ '', $text{'index_all'} ],
[ 'host', $text{'index_forhost'} ],
[ 'proto', $text{'index_forproto'} ],
[ 'iport', $text{'index_foriport'} ],
[ 'oport', $text{'index_foroport'} ] ])." ".
&ui_textbox("what", $in{'for'} ? $in{'what'} : "", 20));
print "<tr> <td><b>$text{'index_from'}</b></td>\n";
print "<td colspan=4>",
print &ui_table_row($text{'index_from'},
&date_input($in{'from_day'}, $in{'from_month'},
$in{'from_year'}, "from"),
&hourmin_input($in{'from_hour'}, "00", "from"),"</td> </tr>\n";
$in{'from_year'}, "from").
&hourmin_input($in{'from_hour'}, "00", "from"));
print "<tr> <td><b>$text{'index_to'}</b></td>\n";
print "<td colspan=4>",
print &ui_table_row($text{'index_to'},
&date_input($in{'to_day'}, $in{'to_month'},
$in{'to_year'}, "to"),
&hourmin_input($in{'to_hour'}, "00", "to"),"</td> </tr>\n";
$in{'to_year'}, "to").
&hourmin_input($in{'to_hour'}, "00", "to"));
if (!%in) {
# Enable by default
$in{'low'} = 1;
}
print "<tr> <td></td> <td colspan=4>\n";
print &ui_checkbox("low", 1, $text{'index_low'}, $in{'low'});
print &ui_checkbox("resolv", 1, $text{'index_resolv'}, $in{'resolv'});
print "</td> </tr>\n";
print &ui_table_row("",
&ui_checkbox("low", 1, $text{'index_low'}, $in{'low'}).
&ui_checkbox("resolv", 1, $text{'index_resolv'}, $in{'resolv'}));
print "<tr> <td colspan=4>",
&ui_submit($text{'index_search'}),"</td> </td>\n";
print "</table>\n";
print &ui_form_end();
print &ui_table_end();
print &ui_form_end([ [ undef, $text{'index_search'} ] ]);
}
elsif (!$missingrule && $sysconf) {
print "<b>$text{'index_none'}</b><p>\n";
@@ -344,37 +337,45 @@ if ($in{'by'}) {
@order = grep { $count{$_} } @order;
}
if (@order) {
print "<table width=100% cellpadding=0 cellspacing=0>\n";
print "<tr>\n";
print "<td><b>",$text{'index_h'.$in{'by'}},"</b></td>\n";
print "<td colspan=2><b>$text{'index_usage'}</b></td>\n";
print "</tr>\n";
$total = 0;
print &ui_columns_start([ $text{'index_h'.$in{'by'}},
$text{'index_usage'},
$text{'index_in'},
$text{'index_out'},
$text{'index_total'} ], 100, 0);
$itotal = $ototal = $total = 0;
foreach $k (@order) {
print "<tr>\n";
my @cols;
if ($in{'by'} eq 'hour') {
print "<td>",&make_date($k*60*60),"</td>\n";
push(@cols, &make_date($k*60*60));
}
elsif ($in{'by'} eq 'day') {
$date = &make_date_day($k*60*60);
print "<td>$date</td>\n";
push(@cols, $date);
}
else {
print "<td>$k</td>\n";
push(@cols, $k);
}
print "<td>";
printf "<img src=images/red.gif width=%d height=10>",
my $bar = sprintf
"<img src=images/red.gif width=%d height=10>",
$max ? int($width * $icount{$k}/$max)+1 : 1;
printf "<img src=images/blue.gif width=%d height=10>",
$bar .= sprintf
"<img src=images/blue.gif width=%d height=10>",
$max ? int($width * $ocount{$k}/$max)+1 : 1;
print "</td>";
print "<td>",&nice_size($count{$k}),"</td>\n";
push(@cols, $bar);
push(@cols, &nice_size($icount{$k}),
&nice_size($ocount{$k}),
&nice_size($count{$k}));
$total += $count{$k};
$itotal += $icount{$k};
$ototal += $ocount{$k};
print "</tr>\n";
print &ui_columns_row(\@cols);
}
print "<tr> <td colspan=2></td> <td><b>",
&nice_size($total),"</td> </tr>\n";
print "</table>\n";
print &ui_columns_row([ undef, undef,
&nice_size($itotal),
&nice_size($ototal),
&nice_size($total) ]);
print &ui_columns_end();
}
else {
print "<b>$text{'index_nomatch'}</b><p>\n";

View File

@@ -41,6 +41,9 @@ index_efrom=Invalid starting date and time
index_eto=Invalid ending date and time
index_err=Failed to generate report
index_usage=Network traffic <font color=#ff0000>downloaded</font> and <font color=#0000ff>uploaded</font>
index_in=Download
index_out=Upload
index_total=Total
index_hhour=Hour
index_hhost=Host
index_hday=Day

View File

@@ -1281,6 +1281,14 @@ elsif ($type eq "DMARC") {
print &ui_table_row($text{'value_dmarcruf'},
&ui_opt_textbox("dmarcruf", $ruf, 50, $text{'value_dmarcnor'}), 3);
print &ui_table_row($text{'value_dmarcrf'},
&ui_select("dmarcrf", $dmarc->{'rf'},
[ [ undef, $text{'default'} ],
[ 'afrf', $text{'value_dmarcafrf'} ] ]));
print &ui_table_row($text{'value_dmarcri'},
&ui_textbox("dmarcri", $dmarc->{'ri'}, 5)."s");
print &ui_table_row($text{'value_dmarcfo'},
&ui_select("dmarcfo", $dmarc->{'fo'},
[ [ undef, $text{'default'} ],
@@ -1322,6 +1330,30 @@ elsif ($type eq "CAA") {
print &ui_table_row($text{'value_CAA3'},
&ui_textbox("value2", $v[2], 40));
}
elsif ($type eq "NAPTR") {
# NAPTR records have order, preference, flags, services and regexp
print &ui_table_row($text{'value_NAPTR1'},
&ui_textbox("value0", $v[0], 5));
print &ui_table_row($text{'value_NAPTR2'},
&ui_textbox("value1", $v[1], 5));
my %flags = map { $_, 1 } split(//, $v[2]);
my @fopts = ("S", "A", "U", "P");
print &ui_table_row($text{'value_NAPTR3'},
join(" ", map { &ui_checkbox("value2", $_, $text{'value_NAPTR3_'.$_}, $flags{$_})."<br>" } @fopts));
print &ui_table_row($text{'value_NAPTR4'},
&ui_textbox("value3", $v[3], 40), 3);
print &ui_table_row($text{'value_NAPTR5'},
&ui_opt_textbox("value4", $v[4], 50,
$text{'value_NAPTR5_def'}), 3);
print &ui_table_row($text{'value_NAPTR6'},
&ui_opt_textbox("value5", $v[5] eq "." ? "" : $v[5], 50,
$text{'value_NAPTR6_def'}), 3);
}
else {
# All other types just have a text box
print &ui_table_row($text{'value_other'},
@@ -2983,7 +3015,7 @@ $slave_error = $_[0];
sub get_forward_record_types
{
return ("A", "NS", "CNAME", "MX", "HINFO", "TXT", "SPF", "DMARC", "WKS", "RP", "PTR", "LOC", "SRV", "KEY", "TLSA", "SSHFP", "CAA", "NSEC3PARAM", $config{'support_aaaa'} ? ( "AAAA" ) : ( ), @extra_forward);
return ("A", "NS", "CNAME", "MX", "HINFO", "TXT", "SPF", "DMARC", "WKS", "RP", "PTR", "LOC", "SRV", "KEY", "TLSA", "SSHFP", "CAA", "NAPTR", "NSEC3PARAM", $config{'support_aaaa'} ? ( "AAAA" ) : ( ), @extra_forward);
}
sub get_reverse_record_types
@@ -3333,6 +3365,7 @@ if (!$single) {
# Add the new DNSKEY record(s) to the zone
my $chrootfn = &get_zone_file($z);
$chrootfn || return "Could not work out records file!";
my @recs = &read_zone_file($chrootfn, $dom);
for(my $i=$#recs; $i>=0; $i--) {
if ($recs[$i]->{'type'} eq 'DNSKEY') {
@@ -3487,7 +3520,7 @@ while($tries++ < 10) {
$out = &backquote_logged(
"cd ".quotemeta($dir)." && ".
"$config{'signzone'} -o ".quotemeta($dom).
($alg =~ /^NSEC3/ ? " -3 -" : "").
($alg =~ /^(NSEC3|RSASHA256|RSASHA512|ECCGOST|ECDSAP256SHA256|ECDSAP384SHA384)/ ? " -3 -" : "").
" -f ".quotemeta($signed)." ".
quotemeta($chrootfn)." 2>&1");
last if (!$?);

View File

@@ -28,6 +28,6 @@ my $desc = &text('edit_header', &zone_subhead($zone));
&ui_print_footer("", $text{'index_return'},
"edit_$type.cgi?zone=$in{'zone'}&view=$in{'view'}",
$text{'recs_return'},
"edit_recs.cgi?zone=$in{'zone'}&type=$in{'type'}",
"edit_recs.cgi?zone=$in{'zone'}&view=$in{'view'}&type=$in{'type'}",
$text{'edit_return'});

View File

@@ -313,6 +313,10 @@ edit_edmarcpct=Percentage of messages must be an integer between 0 and 100
edit_edmarcrua=Missing aggregate feedback address
edit_edmarcruf=Missing forensic information address
edit_ecaavalue2=Missing or invalid-looking domain name
edit_enaptrvalue0=Record order must be a number
edit_enaptrvalue1=Record preference must be a number
edit_enaptrvalue3=Missing services field
edit_enaptrvalue4=Only one of the regexp and replacement fields can be set
text_title=Edit Records File
text_title2=View Records File
@@ -403,6 +407,7 @@ type_SRV=Service Address
type_ALL=All Record Types
type_KEY=Public Key
type_CAA=Certificate Authority
type_NAPTR=Name Authority Pointer
edit_A=Address
edit_AAAA=IPv6 Address
@@ -423,6 +428,7 @@ edit_NSEC3PARAM=DNSSEC Parameters
edit_TLSA=SSL Certificate
edit_SSHFP=SSH Public Key
edit_CAA=Certificate Authority
edit_NAPTR=Name Authority Pointer
recs_defttl=Default TTL
recs_A=Address
@@ -445,6 +451,7 @@ recs_NSEC3PARAM=DNSSEC Parameters
recs_TLSA=SSL Certificate
recs_SSHFP=SSH Public Key
recs_CAA=Certificate Authority
recs_NAPTR=Name Authority
recs_delete=Delete Selected
value_A1=Address
@@ -528,6 +535,21 @@ value_CAA3=CA domain name
value_caa_issue=Single domain cert
value_caa_issuewild=Wildcard cert
value_caa_iodef=Policy violation URL
+value_dmarcri=Reporting interval
+value_dmarcrf=Report format
+value_dmarcafrf=Authentication Failure Reporting Format
value_NAPTR1=Order
value_NAPTR2=Preference
value_NAPTR3=Flags
value_NAPTR4=Services
value_NAPTR5=Regexp
value_NAPTR5_def=None (use replacement)
value_NAPTR6=Replacement
value_NAPTR6_def=None (use regexp)
value_NAPTR3_S=Lookup SRV record next
value_NAPTR3_A=Lookup A or AAAA record next
value_NAPTR3_U=Use regexp output next
value_NAPTR3_P=Protocol-specific action
tlsa_usage0=Certificate authority
tlsa_usage1=End entity

View File

@@ -478,8 +478,12 @@ sub make_record
my ($name, $ttl, $cls, $type, $values, $cmt) = @_;
$type = $type eq "SPF" && !$config{'spf_record'} ? "TXT" :
$type eq "DMARC" ? "TXT" : $type;
return $name . ($ttl ? "\t".$ttl : "") . "\t" . $cls . "\t" . $type ."\t" .
$values . ($cmt ? "\t;$cmt" : "");
return $name.
(defined($ttl) && $ttl ne "" ? "\t".$ttl : "").
"\t".$cls.
"\t".$type.
"\t".$values.
(defined($cmt) && $cmt ne "" ? "\t;$cmt" : "");
}
# bump_soa_record(file, &records)
@@ -863,7 +867,7 @@ if ($txt =~ /^v=dmarc1/i) {
my $dmarc = { };
foreach my $w (@w) {
$w = lc($w);
if ($w =~ /^(v|pct|ruf|rua|p|sp|adkim|aspf|fo)=(\S+)$/i) {
if ($w =~ /^(v|pct|ruf|rua|p|sp|adkim|aspf|fo|rf|ri)=(\S+)$/i) {
$dmarc->{$1} = $2;
}
else {
@@ -883,7 +887,7 @@ sub join_dmarc
{
my ($dmarc) = @_;
my @rv = ( "v=DMARC1" );
foreach my $s ("p", "pct", "ruf", "rua", "sp", "adkim", "aspf", "fo") {
foreach my $s ("p", "pct", "ruf", "rua", "sp", "adkim", "aspf", "fo", "rf", "ri") {
if ($dmarc->{$s} && $dmarc->{$s} ne '') {
push(@rv, $s."=".$dmarc->{$s});
}
@@ -997,6 +1001,7 @@ if ($z->{'members'}) {
else {
$fn = $z->{'file'};
}
return undef if (!$fn);
if ($abs) {
$fn = &absolute_path($fn);
}

View File

@@ -422,6 +422,20 @@ else {
$dmarc->{'fo'} = $in{'dmarcfo'};
}
if ($in{'dmarcrf'} eq '') {
delete($dmarc->{'rf'});
}
else {
$dmarc->{'rf'} = $in{'dmarcrf'};
}
if ($in{'dmarcri'} eq '') {
delete($dmarc->{'ri'});
}
else {
$dmarc->{'ri'} = $in{'dmarcri'};
}
$vals = "\"".&join_dmarc($dmarc)."\"";
}
elsif ($in{'type'} eq 'NSEC3PARAM') {
@@ -440,6 +454,23 @@ else {
$vals = join(" ", $in{'value0'}, $in{'value1'},
"\"$in{'value2'}\"");
}
elsif ($in{'type'} eq 'NAPTR') {
my $flags = join("", split(/\0/, $in{'value2'}));
$in{'value0'} =~ /^\d+$/ ||
&error($text{'edit_enaptrvalue0'});
$in{'value1'} =~ /^\d+$/ ||
&error($text{'edit_enaptrvalue1'});
$in{'value3'} =~ /^\S+$/ ||
&error($text{'edit_enaptrvalue3'});
if (!$in{'value4_def'} && !$in{'value5_def'}) {
&error($text{'edit_enaptrvalue4'});
}
$vals = join(" ", $in{'value0'}, $in{'value1'},
"\"$flags\"",
"\"$in{'value3'}\"",
$in{'value4_def'} ? "\"\"" : "\"$in{'value4'}\"",
$in{'value5_def'} ? "." : $in{'value5'});
}
else {
# For other record types, just save the lines
$in{'values'} =~ s/\r//g;

View File

@@ -26,9 +26,9 @@ sub list_disks_partitions
my @rv;
# Iterate over disk devices
foreach my $dev (glob("/dev/ada[0-9]"),
glob("/dev/ad[0-9]"),
glob("/dev/da[0-9]")) {
foreach my $dev (glob("/dev/ada[0-9]"), glob("/dev/ada[0-9][0-9]"),
glob("/dev/ad[0-9]"), glob("/dev/ad[0-9][0-9]"),
glob("/dev/da[0-9]"), glob("/dev/da[0-9][0-9]")) {
next if (!-r $dev || -l $dev);
my $disk = { 'device' => $dev,
'prefix' => $dev,

View File

@@ -39,16 +39,13 @@ if ($config{'max_users'} && @ulist > $config{'max_users'}) {
}
else {
# Show as table of users
print &ui_table_start($passwd::text{'index_header'}, "width=100%");
my @grid;
for($i=0; $i<@ulist; $i++) {
if ($i%4 == 0) { print "<tr>\n"; }
print "<td width=25%><a href=\"edit_passwd.cgi?",
"user=$ulist[$i]->{'user'}\">",
&html_escape($ulist[$i]->{'user'})."</a></td>\n";
if ($i%4 == 3) { print "</tr>\n"; }
push(@grid, &ui_link("edit_passwd.cgiuser=$ulist[$i]->{'user'}",
&html_escape($ulist[$i]->{'user'})));
}
while($i++ % 4) { print "<td width=25%></td>\n"; }
print &ui_table_end();
print &ui_grid_table(\@grid, 4, 100, undef, undef,
$passwd::text{'index_header'});
}
&ui_print_footer("/", $text{'index'});

View File

@@ -109,7 +109,10 @@ elsif ($uconfig{'home_style'} == 3) {
sub server_name
{
my ($server) = @_;
return $server->{'desc'} || $server->{'host'};
my @w;
push(@w, $server->{'host'} || &get_system_hostname());
push(@w, "(".$server->{'desc'}.")") if ($server->{'desc'});
return join(" ", @w);
}
# supports_gothers(&server)

View File

@@ -52,23 +52,19 @@ print &ui_buttons_end();
# Show users and groups
print &ui_hr();
print &ui_table_start($text{'host_users'}, undef, 2);
my @ugrid;
foreach my $u (@{$host->{'users'}}) {
push(@ugrid, &ui_link("edit_user.cgi?user=".&urlize($u->{'user'}).
"&host=".&urlize($server->{'id'}), $u->{'user'}));
}
print &ui_table_row(undef, &ui_grid_table(\@ugrid, 4), 2);
print &ui_table_end();
print &ui_grid_table(\@ugrid, 4, 100, undef, undef, $text{'host_users'});
print &ui_table_start($text{'host_groups'}, undef, 2);
my @ggrid;
foreach $g (@{$host->{'groups'}}) {
push(@ggrid, &ui_link("edit_group.cgi?group=".&urlize($g->{'group'}).
"&host=".&urlize($server->{'id'}), $g->{'group'}));
}
print &ui_table_row(undef, &ui_grid_table(\@ggrid, 4), 2);
print &ui_table_end();
print &ui_grid_table(\@ggrid, 4, 100, undef, undef, $text{'host_groups'});
&ui_print_footer("", $text{'index_return'});

View File

@@ -24,8 +24,7 @@ foreach $h (@hosts) {
local ($s) = grep { $_->{'id'} == $h->{'id'} } @servers;
next if (!$s);
local ($link) = $config{'conf_host_links'} ? "edit_host.cgi?id=$h->{'id'}" : "#";
push(@titles, $s->{'desc'} ? $s->{'desc'}
: "$s->{'host'}:$s->{'port'}");
push(@titles, &server_name($s));
push(@links, $link);
push(@icons, &get_webprefix()."/servers/images/".
$s->{'type'}.".gif");
@@ -151,6 +150,8 @@ if (@hosts) {
&ui_textbox("what", undef, 15));
}
print &ui_buttons_hr();
if ($config{'conf_add_user'}) {
print &ui_buttons_row("user_form.cgi",
$text{'index_newuser'},
@@ -165,6 +166,8 @@ if (@hosts) {
[ [ "new", 1 ] ]);
}
print &ui_buttons_hr();
if ($config{'conf_allow_refresh'}) {
print &ui_buttons_row("refresh.cgi",
$text{'index_refresh'}, undef, undef,

View File

@@ -5,7 +5,7 @@ index_add=Add server
index_gadd=Add servers in group
index_users=Users and Groups
index_return=servers list
index_refresh=Refresh user and group lists
index_refresh=Refresh user and group lists on
index_finduser=Find users whose
index_findgroup=Find groups whose
index_newuser=Add User

View File

@@ -47,21 +47,21 @@ elsif ($in{'source'} == 2) {
close(FILE);
unlink($file);
if ($in{'mode'} eq 'rpm') {
$progress_callback_url = "http://$usermin::update_host/download/rpm/usermin-$site_version-1.noarch.rpm";
$progress_callback_url = "http://$usermin::update_host/download/rpm/usermin-${site_version}-1.noarch.rpm";
&http_download($usermin::update_host, $usermin::update_port,
"/download/rpm/usermin-$site_version-1.noarch.rpm", $file,
"/download/rpm/usermin-${site_version}-1.noarch.rpm", $file,
\$error, \&progress_callback);
}
elsif ($in{'mode'} eq 'deb') {
$progress_callback_url = "http://$usermin::update_host/download/deb/usermin_$site_version.deb";
$progress_callback_url = "http://$usermin::update_host/download/deb/usermin_${site_version}_all.deb";
&http_download($usermin::update_host, $usermin::update_port,
"/download/deb/usermin_$site_version.deb", $file,
"/download/deb/usermin_${site_version}_all.deb", $file,
\$error, \&progress_callback);
}
else {
$progress_callback_url = "http://$usermin::update_host/download/usermin-$site_version.tar.gz";
$progress_callback_url = "http://$usermin::update_host/download/usermin-${site_version}.tar.gz";
&http_download($usermin::update_host, $usermin::update_port,
"/download/usermin-$site_version.tar.gz", $file,
"/download/usermin-${site_version}.tar.gz", $file,
\$error, \&progress_callback);
}
$error && &inst_error($error);
@@ -95,7 +95,7 @@ if (`rpm -qp $file 2>&1` =~ /(^|\n)usermin-(\d+\.\d+)/) {
$mode = "rpm";
$version = $2;
}
elsif (`dpkg --info $file 2>&1` =~ /Package:\s+usermin-(\d+\.\d+)/) {
elsif (`dpkg --info $file 2>&1` =~ /Package:\s+usermin\n\s*Version:\s+(\d+\.\d+)/) {
# Looks like a Usermin Debian package
$mode = "deb";
$version = $2;

View File

@@ -45,3 +45,5 @@ Added buttons to move cron jobs to the top and bottom of the list.
Added a page for manually editing cron jobs.
---- Changes since 1.900 ----
The next run time of each cron job can be displayed by enable a new config option.
---- Changes since 1.980 ----
Added buttons to stop and start crond on the main page.

View File

@@ -56,6 +56,10 @@ print &ui_table_row($text{'acl_hourly'},
&ui_radio("hourly", $_[0]->{'hourly'},
[ [ 1, $text{'yes'} ], [ 0, $text{'no'} ],
[ 2, $text{'acl_hourlydef'} ] ]), 3);
print &ui_table_row($text{'acl_stop'},
&ui_radio("stop", $_[0]->{'stop'},
[ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ]));
}
# acl_security_save(&options)
@@ -77,5 +81,6 @@ $_[0]->{'delete'} = $in{'delete'};
$_[0]->{'move'} = $in{'move'};
$_[0]->{'kill'} = $in{'kill'};
$_[0]->{'hourly'} = $in{'hourly'};
$_[0]->{'stop'} = $in{'stop'};
}

17
cron/bootup.cgi Executable file
View File

@@ -0,0 +1,17 @@
#!/usr/local/bin/perl
# Enable or disable crond at boot time
require './cron-lib.pl';
&ReadParse();
&foreign_require("init");
$access{'stop'} || &error($text{'bootup_ecannot'});
$init = $config{'init_name'};
if ($in{'boot'}) {
&init::enable_at_boot($init);
}
else {
&init::disable_at_boot($init);
}
&webmin_log($in{'boot'} ? "bootup" : "bootdown");
&redirect("");

View File

@@ -21,3 +21,4 @@ show_comment=0
hourly_only=0
max_jobs=100
show_next=0
init_name=cron

View File

@@ -23,3 +23,4 @@ show_comment=0
hourly_only=0
max_jobs=100
show_next=0
init_name=cron

View File

@@ -23,3 +23,4 @@ show_comment=0
hourly_only=0
max_jobs=100
show_next=0
init_name=crond

View File

@@ -25,3 +25,4 @@ system_crontab=Path to Vixie-Cron system crontab file,0
single_file=Path to single user crontab file,0
cronfiles_dir=Path to extra cron files directory,3,None
run_parts=run-parts command,0
init_name=Cron daemon bootup action name,3,None exists

View File

@@ -310,7 +310,7 @@ elsif ($fcron) {
}
else {
system("cp ".&translate_filename("$config{'cron_dir'}/$_[0]->{'user'}").
" $cron_temp_file 2>/dev/null");
" ".quotemeta($cron_temp_file)." 2>/dev/null");
}
}
@@ -378,7 +378,7 @@ else {
$_[0]->{'line'} = 0;
splice(@$lref, 0, 0, &cron_job_line($_[0]));
&flush_file_lines();
system("chown $_[0]->{'user'} $cron_temp_file");
&set_ownership_permissions($_[0]->{'user'}, undef, undef, $cron_temp_file);
&copy_crontab($_[0]->{'user'});
$_[0]->{'file'} = "$config{'cron_dir'}/$_[0]->{'user'}";
$_[0]->{'index'} = scalar(@cron_jobs_cache);
@@ -497,8 +497,8 @@ if (&read_file_contents($cron_temp_file) =~ /\S/) {
local $rv;
if (!&has_crontab_cmd()) {
# We have no crontab command .. emulate by copying to user file
$rv = system("cat $cron_temp_file".
" >$config{'cron_dir'}/$_[0] 2>/dev/null");
$rv = system("cat ".quotemeta($cron_temp_file).
" >".quotemeta("$config{'cron_dir'}/$_[0]")." 2>/dev/null");
&set_ownership_permissions($_[0], undef, 0600,
"$config{'cron_dir'}/$_[0]");
}
@@ -518,12 +518,12 @@ if (&read_file_contents($cron_temp_file) =~ /\S/) {
chdir("/");
if ($single_user) {
$rv = system($config{'cron_user_edit_command'}.
" >$temp 2>&1 <$notemp");
" >".quotemeta($temp)." 2>&1 <".quotemeta($notemp));
}
else {
$rv = system(
&user_sub($config{'cron_edit_command'},$_[0]).
" >$temp 2>&1 <$notemp");
" >".quotemeta($temp)." 2>&1 <".quotemeta($notemp));
}
unlink($notemp);
chdir($oldpwd);
@@ -533,12 +533,12 @@ if (&read_file_contents($cron_temp_file) =~ /\S/) {
if ($single_user) {
$rv = &execute_command(
$config{'cron_user_copy_command'},
$cron_temp_file, $temp, $temp);
quotemeta($cron_temp_file), quotemeta($temp), quotemeta($temp));
}
else {
$rv = &execute_command(
&user_sub($config{'cron_copy_command'}, $_[0]),
$cron_temp_file, $temp, $temp);
quotemeta($cron_temp_file), quotemeta($temp), quotemeta($temp));
}
}
local $out = &read_file_contents($temp);

View File

@@ -8,3 +8,4 @@ delete=1
move=1
kill=1
hourly=2
stop=1

View File

@@ -286,5 +286,34 @@ else {
print &ui_links_row(\@crlinks);
}
# If there is an init script that runs crond, show status
&foreign_require("init");
my $init = $config{'init_name'};
my $atboot;
if ($access{'stop'} && $init && ($atboot = &init::action_status($init))) {
print &ui_hr();
print &ui_buttons_start();
# Running now?
my $r = &init::status_action($init);
if ($r == 1) {
print &ui_buttons_row("stop.cgi", $text{'index_stop'},
$text{'index_stopdesc'});
}
elsif ($r == 0) {
print &ui_buttons_row("start.cgi", $text{'index_start'},
$text{'index_startdesc'});
}
# Start at boot?
print &ui_buttons_row("bootup.cgi", $text{'index_boot'},
$text{'index_bootdesc'}, undef,
&ui_radio("boot", $atboot == 2 ? 1 : 0,
[ [ 1, $text{'yes'} ],
[ 0, $text{'no'} ] ]));
print &ui_buttons_end();
}
&ui_print_footer("/", $text{'index'});

View File

@@ -31,6 +31,12 @@ index_ok=Search
index_searchres=Cron jobs matching $1 ..
index_reset=Reset search.
index_econfigcheck=Cron jobs cannot be managed on your system, as the module configuration is not valid : $1
index_stop=Stop Cron Daemon
index_stopdesc=Shut down the <tt>crond</tt> background server process that runs scheduled cron jobs. This will prevent commands from executing at their specified times.
index_start=Start Cron Daemon
index_startdesc=Start up the <tt>crond</tt> background server process that runs scheduled cron jobs. <font color=red><b>This is required for commands to execute at their specified times.</b></font>
index_boot=Start Cron Daemon Boot?
index_bootdesc=Change this setting to enable or disable starting the scheduled cron jobs daemon at system boot time.
edit_title=Edit Cron Job
create_title=Create Cron Job
@@ -128,6 +134,7 @@ acl_move=Can move Cron jobs?
acl_kill=Can terminate Cron jobs?
acl_hourly=Limit jobs to at most hourly?
acl_hourlydef=As set in Module Config
acl_stop=Can stop and start the Cron daemon?
log_modify=Modified Cron job for $1
log_modify_l=Modified Cron job "$2" for $1
@@ -146,6 +153,10 @@ log_move=Moved Cron job for $1
log_crons_delete=Deleted $1 Cron jobs
log_crons_disable=Disabled $1 Cron jobs
log_crons_enable=Enabled $1 Cron jobs
log_stop=Stopped cron daemon
log_start=Started cron daemon
log_bootup=Enabled cron daemon at boot
log_bootdown=Disabled cron daemon at boot
ecopy=An error was detected in the new Cron configuration : $1 $2
@@ -195,4 +206,10 @@ manual_editing=Use the text box below to edit Cron jobs in $1. Be careful, as no
manual_efile=Selected file is not valid!
manual_ecannot=You are not allowed to manually edit cron jobs
stop_err=Failed to stop daemon
start_err=Failed to start daemon
stop_ecannot=You are not allowed to stop the daemon
start_ecannot=You are not allowed to start the daemon
bootup_ecannot=You are not allowed to enable the daemon at boot
__norefs=1

View File

@@ -37,11 +37,8 @@ elsif ($action eq 'exec' || $action eq 'kill') {
"<tt>$object</tt>",
"<tt>".&html_escape($p->{'command'})."</tt>");
}
elsif ($action eq 'allow') {
return $text{'log_allow'};
}
else {
return undef;
return $text{'log_'.$action};
}
}

1
cron/negativeacl Normal file
View File

@@ -0,0 +1 @@
stop=0

View File

@@ -4,6 +4,7 @@
require './cron-lib.pl';
&ReadParse();
$access{'allow'} || &error($text{'allow_ecannot'});
&lock_file($config{cron_allow_file});
&lock_file($config{cron_deny_file});

14
cron/start.cgi Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/local/bin/perl
# Start crond
require './cron-lib.pl';
&error_setup($text{'start_err'});
$access{'stop'} || &error($text{'start_ecannot'});
&foreign_require("init");
my $init = $config{'init_name'};
my ($ok, $err) = &init::start_action($init);
&error($err) if (!$ok);
&webmin_log("start");
&redirect("");

14
cron/stop.cgi Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/local/bin/perl
# Stop crond
require './cron-lib.pl';
&error_setup($text{'stop_err'});
$access{'stop'} || &error($text{'stop_ecannot'});
&foreign_require("init");
my $init = $config{'init_name'};
my ($ok, $err) = &init::stop_action($init);
&error($err) if (!$ok);
&webmin_log("stop");
&redirect("");

View File

@@ -23,8 +23,21 @@ print "Refresh: $config{'lease_refresh'}\r\n"
%ranges = ( );
$conf = &get_config();
@subnets = &find("subnet", $conf);
foreach $shared (&find("shared-network", $conf)) {
@shareds = &find("shared-network", $conf);
foreach $shared (@shareds) {
push(@subnets, &find("subnet", $shared->{'members'}));
@ranges = &find("range", $shared->{'members'});
foreach $pool (&find("pool", $shared->{'members'})) {
push(@ranges, &find("range", $pool->{'members'}));
}
foreach $range (@ranges) {
local @rv = @{$range->{'values'}};
shift(@rv) if ($rv[0] eq "dynamic-bootp");
foreach $ip (&expand_ip_range($rv[0], $rv[1])) {
$ranges{$ip} = $shared;
$shared->{'ips'}++;
}
}
}
foreach $subnet (@subnets) {
if ($in{'network'}) {
@@ -111,7 +124,7 @@ else {
}
if ($in{'bysubnet'}) {
# Show table of subnets, with lease usage
# Show table of subnets and shared nets, with lease usage
print &ui_columns_start([
$text{'index_net'}, $text{'index_desc'},
$text{'listl_size'}, $text{'listl_used'},
@@ -135,6 +148,25 @@ else {
"",
]);
}
foreach $shared (grep { $_->{'ips'} } @shareds) {
%used = ( );
foreach $lease (@leases) {
$r = $ranges{$lease->{'values'}->[0]};
if ($r eq $shared && !$lease->{'expired'}) {
$used{$lease->{'values'}->[0]}++;
}
}
$used = scalar(keys %used);
print &ui_columns_row([
$shared->{'values'}->[0],
&html_escape($shared->{'comment'}),
$shared->{'ips'},
$used,
$shared->{'ips'} ?
int(100*$used / $shared->{'ips'})."%" :
"",
]);
}
print &ui_columns_end();
}
elsif (@leases) {

View File

@@ -153,16 +153,25 @@ while(1) {
&tempname();
print STDERR "fastrpc: tcpwrite $file\n" if ($gconfig{'rpcdebug'});
local $tsock = time().$$;
local $tsock6 = $use_ipv6 ? time().$$."v6" : undef;
local $tport = $port + 1;
&allocate_socket($tsock, \$tport);
&allocate_socket($tsock, $tsock6, \$tport);
if (!fork()) {
# Accept connection in separate process
print STDERR "fastrpc: tcpwrite $file port $tport\n" if ($gconfig{'rpcdebug'});
local $rmask;
vec($rmask, fileno($tsock), 1) = 1;
if ($use_ipv6) {
vec($rmask, fileno($tsock6), 1) = 1;
}
local $sel = select($rmask, undef, undef, 30);
exit if ($sel <= 0);
accept(TRANS, $tsock) || exit;
if (vec($rmask, fileno($tsock), 1)) {
accept(TRANS, $tsock) || exit;
}
elsif ($use_ipv6 && vec($rmask, fileno($tsock6), 1)) {
accept(TRANS, $tsock6) || exit;
}
print STDERR "fastrpc: tcpwrite $file accepted\n" if ($gconfig{'rpcdebug'});
local $buf;
local $err;
@@ -189,6 +198,7 @@ while(1) {
exit;
}
close($tsock);
close($tsock6);
print STDERR "fastrpc: tcpwrite $file done\n" if ($gconfig{'rpcdebug'});
$rawrv = &serialise_variable(
{ 'status' => 1, 'rv' => [ $file, $tport ] } );
@@ -221,15 +231,24 @@ while(1) {
else {
binmode(FILE);
local $tsock = time().$$;
local $tsock6 = $use_ipv6 ? time().$$."v6" : undef;
local $tport = $port + 1;
&allocate_socket($tsock, \$tport);
&allocate_socket($tsock, $tsock6, \$tport);
if (!fork()) {
# Accept connection in separate process
local $rmask;
vec($rmask, fileno($tsock), 1) = 1;
if ($use_ipv6) {
vec($rmask, fileno($tsock6), 1) = 1;
}
local $sel = select($rmask, undef, undef, 30);
exit if ($sel <= 0);
accept(TRANS, $tsock) || exit;
if (vec($rmask, fileno($tsock), 1)) {
accept(TRANS, $tsock) || exit;
}
elsif (vec($rmask, fileno($tsock6), 1)) {
accept(TRANS, $tsock6) || exit;
}
local $buf;
while(read(FILE, $buf, 1024) > 0) {
print TRANS $buf;
@@ -240,6 +259,7 @@ while(1) {
}
close(FILE);
close($tsock);
close($tsock6);
print STDERR "fastrpc: tcpread $arg->{'file'} done\n" if ($gconfig{'rpcdebug'});
$rawrv = &serialise_variable(
{ 'status' => 1, 'rv' => [ $arg->{'file'}, $tport ] } );

View File

@@ -226,6 +226,7 @@ if (!-d "/proc/ide") {
# Get Linux disk ID mapping
local %id_map;
local %all_id_map;
local $id_dir = "/dev/disk/by-id";
opendir(IDS, $id_dir);
foreach my $id (readdir(IDS)) {
@@ -233,6 +234,8 @@ foreach my $id (readdir(IDS)) {
if ($id_link) {
local $id_real = &simplify_path(&resolve_links("$id_dir/$id"));
$id_map{$id_real} = $id;
$all_id_map{$id_real} ||= [];
push(@{$all_id_map{$id_real}}, $id);
}
}
closedir(IDS);
@@ -440,6 +443,8 @@ while(<FDISK>) {
$disk->{'id'} = $id_map{$disk->{'device'}} ||
$id_map{"/dev/$short"};
$disk->{'ids'} = $all_id_map{$disk->{'device'}} ||
$all_id_map{"/dev/$short"};
push(@disks, $disk);
}

View File

@@ -486,11 +486,23 @@ foreach my $fref (@{$files_to_extract}) {
my $cwd = $fref->{'path'};
my $name = $fref->{'file'};
my $extract_to = "$cwd/" . fileparse("$cwd/$name", qr/\.[^.]*/);
if (-e $extract_to) {
$extract_to .= "_" . int(rand(1000)) . $$;
my $extract_to = $cwd;
if (!$in{'overwrite_existing'}) {
my ($file_name) = $name =~ /(?|(.*)\.((?|tar|wbm|wbt)\..*)|(.*)\.([a-zA-Z]+\.(?|gpg|pgp))|(.*)\.(?=(.*))|(.*)())/;
if (!-e "$cwd/$file_name") {
$extract_to = "$cwd/$file_name";
} else {
my $__ = 1;
for (;;) {
my $new_dir_name = "$file_name(" . $__++ . ")";
if (!-e "$cwd/$new_dir_name") {
$extract_to = "$cwd/$new_dir_name";
last;
}
}
}
}
mkdir($extract_to);
mkdir("$extract_to");
my $archive_type = mimetype($cwd . '/' . $name);

View File

@@ -166,3 +166,4 @@ index_return=file listing
upload_dirs=Directory Upload
extract_uploaded=Extract Compressed
extract_cmd_not_avail=Could not extract $1 file as $2 command is missing
overwrite_existing=Overwrite Existing

View File

@@ -121,13 +121,13 @@ function Menu(caller, options){
case 37: // left arrow
if (menuType == 'flyout') {
$(event.target).trigger('mouseout');
if ($('.'+options.flyOutOnState).size() > 0) { $('.'+options.flyOutOnState).trigger('mouseover'); };
if ($('.'+options.flyOutOnState).length > 0) { $('.'+options.flyOutOnState).trigger('mouseover'); };
};
if (menuType == 'ipod') {
$(event.target).trigger('mouseout');
if ($('.fg-menu-footer').find('a').size() > 0) { $('.fg-menu-footer').find('a').trigger('click'); };
if ($('.fg-menu-header').find('a').size() > 0) { $('.fg-menu-current-crumb').prev().find('a').trigger('click'); };
if ($('.fg-menu-footer').find('a').length > 0) { $('.fg-menu-footer').find('a').trigger('click'); };
if ($('.fg-menu-header').find('a').length > 0) { $('.fg-menu-current-crumb').prev().find('a').trigger('click'); };
if ($('.fg-menu-current').prev().is('.fg-menu-indicator')) {
$('.fg-menu-current').prev().trigger('mouseover');
};
@@ -138,7 +138,7 @@ function Menu(caller, options){
case 38: // up arrow
if ($(event.target).is('.' + options.linkHover)) {
var prevLink = $(event.target).parent().prev().find('a:eq(0)');
if (prevLink.size() > 0) {
if (prevLink.length > 0) {
$(event.target).trigger('mouseout');
prevLink.trigger('mouseover');
};
@@ -165,7 +165,7 @@ function Menu(caller, options){
case 40: // down arrow
if ($(event.target).is('.' + options.linkHover)) {
var nextLink = $(event.target).parent().next().find('a:eq(0)');
if (nextLink.size() > 0) {
if (nextLink.length > 0) {
$(event.target).trigger('mouseout');
nextLink.trigger('mouseover');
};
@@ -190,7 +190,7 @@ function Menu(caller, options){
});
};
this.create = function(){
this.create = function() {
container.css({ width: options.width }).appendTo('body').find('ul:first').not('.fg-menu-breadcrumb').addClass('fg-menu');
container.find('ul, li a').addClass('ui-corner-all');
@@ -201,7 +201,7 @@ function Menu(caller, options){
container.find('a').attr('tabindex', '-1');
// when there are multiple levels of hierarchy, create flyout or drilldown menu
if (container.find('ul').size() > 1) {
if (container.find('ul').length > 1) {
if (options.flyOut) { menu.flyout(container, options); }
else { menu.drilldown(container, options); }
}
@@ -239,6 +239,9 @@ function Menu(caller, options){
menu.setPosition(container, caller, options);
menu.menuExists = true;
// Hide empty
container.find('a:empty').parent('li').hide()
};
this.chooseItem = function(item){
@@ -386,7 +389,7 @@ Menu.prototype.drilldown = function(container, options) {
// initialize "back" link
if (options.backLink) {
if (footer.find('a').size() == 0) {
if (footer.find('a').length == 0) {
footer.show();
$('<a href="#"><span class="ui-icon ui-icon-triangle-1-w"></span> <span>Back</span></a>')
.appendTo(footer)
@@ -402,7 +405,7 @@ Menu.prototype.drilldown = function(container, options) {
}
// or initialize top breadcrumb
else {
if (breadcrumb.find('li').size() == 1){
if (breadcrumb.find('li').length == 1){
breadcrumb.empty().append(firstCrumb);
firstCrumb.find('a').click(function(){
menu.resetDrilldownMenu();
@@ -419,7 +422,7 @@ Menu.prototype.drilldown = function(container, options) {
menu.chooseItem(this);
}
else {
var newLeftVal = - ($('.fg-menu-current').parents('ul').size() - 1) * 180;
var newLeftVal = - ($('.fg-menu-current').parents('ul').length - 1) * 180;
topList.animate({ left: newLeftVal }, options.crossSpeed, function(){
setPrevMenu();
});

View File

@@ -337,6 +337,7 @@
</div>
<input type="checkbox" data-id="webkitdirectory" onchange="document.querySelector('#upload-form > #upfiles').toggleAttribute('webkitdirectory')"> $text{'upload_dirs'}
<input type="checkbox" data-id="extract_uploaded" onchange="t=document.querySelector('#upload-form'),v=t.getAttribute('action'),x='&extract_uploaded=1',this.checked?t.setAttribute('action', t.getAttribute('action') + x):t.setAttribute('action',t.getAttribute('action').replace(x,''))"> $text{'extract_uploaded'}
<input type="checkbox" data-id="overwrite_existing" onchange="t=document.querySelector('#upload-form'),v=t.getAttribute('action'),x='&overwrite_existing=1',this.checked?t.setAttribute('action', t.getAttribute('action') + x):t.setAttribute('action',t.getAttribute('action').replace(x,''))"> $text{'overwrite_existing'}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" onclick="uploadFiles()">$text{'upload_files'}</button>

View File

@@ -111,6 +111,8 @@
<input type="checkbox" id="filetype" onchange="this.parentElement.querySelector('#upfiles').toggleAttribute('webkitdirectory')"><label for="filetype"> $text{'upload_dirs'}</label>
<br>
<input type="checkbox" id="extract_upload" onchange="t=document.querySelector('#upload-form'),v=t.getAttribute('action'),x='&extract_uploaded=1',this.checked?t.setAttribute('action', t.getAttribute('action') + x):t.setAttribute('action',t.getAttribute('action').replace(x,''))"><label for="extract_upload"> $text{'extract_uploaded'}</label>
<br>
<input type="checkbox" id="overwrite_existing" onchange="t=document.querySelector('#upload-form'),v=t.getAttribute('action'),x='&overwrite_existing=1',this.checked?t.setAttribute('action', t.getAttribute('action') + x):t.setAttribute('action',t.getAttribute('action').replace(x,''))"><label for="overwrite_existing"> $text{'overwrite_existing'}</label>
</form>
<div id="readyForUploadList" class="well" style="max-height: 180px;">
</div>

View File

@@ -9,6 +9,7 @@ get_paths();
my @errors;
my @uploaded_files;
my $uploaded_dir;
$line = "";
# Use Webmin's callback function to track progress
@@ -57,6 +58,29 @@ MAINLOOP: while(index($line,"$boundary--") == -1) {
if ($dir) {
my @dirs = split('/', $dir);
$dir = '/';
# If overwriting is not allowed check for dupes
if (!$in{'overwrite_existing'}) {
if ($dirs[0] && -e "$cwd/$dirs[0]") {
# As only one directory upload at a time allowed
# check if parent exists and if it does add
# predictable suffix, like `dir(1)` or `dir(2)`
if (!$uploaded_dir) {
my $__ = 1;
for (;;) {
my $new_dir_name = "$dirs[0](" . $__++ . ")";
if (!-e "$cwd/$new_dir_name") {
$uploaded_dir = $new_dir_name;
last;
}
}
}
}
else {
$uploaded_dir = $dirs[0];
}
$file =~ s/^(\Q$dirs[0]\E)/$uploaded_dir/;
$dirs[0] = $uploaded_dir;
}
foreach my $updir (@dirs) {
$dir .= "$updir/";
if (!-e "$cwd$dir") {
@@ -66,6 +90,23 @@ MAINLOOP: while(index($line,"$boundary--") == -1) {
}
}
}
# In case of a regular file check for dupes
if (!$in{'overwrite_existing'}) {
if ($file && -e "$cwd/$file") {
# If file exists add predictable suffix, like `file(1)` or `file(2)`
my ($file_name, $file_extension) = $file =~ /(?|(.*)\.((?|tar|wbm|wbt)\..*)|(.*)\.([a-zA-Z]+\.(?|gpg|pgp))|(.*)\.(?=(.*))|(.*)())/;
$file_extension = ".$file_extension" if ($file_extension);
my $__ = 1;
for (;;) {
my $new_file_name = "$file_name(" . $__++ . ")";
if (!-e "$cwd/$new_file_name$file_extension") {
$file = "$new_file_name$file_extension";
last;
}
}
}
}
# OK, we have a file, let`s save it
my $full = "$cwd/$file";
my $newfile = !-e $full;

View File

@@ -40,3 +40,5 @@ Added support for physdev module options, for matching based on the bridged inte
Added the open-ports.pl command which can be run from the shell to open ports on the firewall.
---- Changes since 1.630 ----
Updated all screens to use Webmin's new user interface library, for a more consistent look.
---- Changes since 1.980 ----
Fail2ban rules are preserved when applying the IPtables configuration file.

View File

@@ -345,10 +345,20 @@ print &ui_table_row($text{'edit_physdevisbridged'},
&print_mode("physdevisbridged", $rule->{'physdev-is-bridged'},
$text{'yes'}, $text{'no'}));
# IPset to match
print &ui_table_row($text{'edit_matchset'},
&print_mode("matchset", $rule->{'match-set'})." ".
&ui_select("matchset", $rule->{'match-set'}->[1],
[ map { $_->{'Name'} } &get_ipsets_active() ])." ".
&ui_select("matchset2", $rule->{'match-set'}->[2],
[ [ "src", $text{'edit_matchsetsrc'} ],
[ "dst", $text{'edit_matchsetdst'} ] ], 1, 0,
$rule->{'match-set'}->[2] ? 1 : 0));
print &ui_table_hr();
# Show unknown modules
@mods = grep { !/^(tcp|udp|icmp${ipvx_icmp}|multiport|mac|limit|owner|state|conntrack|tos|comment|physdev)$/ } map { $_->[1] } @{$rule->{'m'}};
@mods = grep { !/^(tcp|udp|icmp${ipvx_icmp}|multiport|mac|limit|owner|state|conntrack|tos|comment|physdev|set)$/ } map { $_->[1] } @{$rule->{'m'}};
print &ui_table_row($text{'edit_mods'},
&ui_textbox("mods", join(" ", @mods), 60));

View File

@@ -175,25 +175,9 @@ foreach $d (keys %{$_[0]->{'defaults'}}) {
push(@lines, ":$d $_[0]->{'defaults'}->{$d} [0:0]");
}
foreach $r (@{$_[0]->{'rules'}}) {
local $line;
local $line = "";
$line = "# $r->{'cmt'}\n" if ($r->{'cmt'});
$line .= "-A $r->{'chain'}";
foreach $a (@known_args) {
local ($aa = $a); $aa =~ s/^-+//;
if ($r->{$aa}) {
local @al = ref($r->{$aa}->[0]) ?
@{$r->{$aa}} : ( $r->{$aa} );
foreach $ag (@al) {
local $n = shift(@$ag);
local @w = ( $n ? ( $n ) : (), $a, @$ag );
@w = map { $_ =~ /'/ ? "\"$_\"" :
$_ =~ /"/ ? "'".$_."'" :
$_ =~ /\s/ ? "\"$_\"" : $_ } @w;
$line .= " ".join(" ", @w);
}
}
}
$line .= " $r->{'args'}" if ($r->{'args'} =~ /\S/);
$line .= &make_rule_command($r);
push(@lines, $line);
}
push(@lines, "COMMIT");
@@ -218,26 +202,48 @@ else {
}
}
# make_rule_command(&rule)
# Returns the flags needed to create a rule
sub make_rule_command
{
my ($r) = @_;
my $line = "-A $r->{'chain'}";
foreach my $a (@known_args) {
my $aa = $a;
$aa =~ s/^-+//;
if ($r->{$aa}) {
my @al = ref($r->{$aa}->[0]) ? @{$r->{$aa}} : ( $r->{$aa} );
foreach my $ag (@al) {
my $n = shift(@$ag);
my @w = ( $n ? ( $n ) : (), $a, @$ag );
@w = map { $_ =~ /'/ ? "\"$_\"" :
$_ =~ /"/ ? "'".$_."'" :
$_ =~ /\s/ ? "\"$_\"" : $_ } @w;
$line .= " ".join(" ", @w);
}
}
}
$line .= " $r->{'args'}" if ($r->{'args'} =~ /\S/);
return $line;
}
# get_ipsets_active()
# return a list of active ipsets
sub get_ipsets_active
{
local (@rv, $name, $set={});
my (@rv, $name, $set);
open(FILE, "ipset list -t 2>/dev/null |");
LINE:
while(<FILE>) {
# remove newlines, get arg and value
# remove newlines, get arg and value
s/\r|\n//g;
local ($n, $v) = split(/: /, $_);
($n) = $n =~ /(\S+)/;
# get values from name to number
$name=$v if ($n eq "Name");
$set->{$n}=$v;
if ($n eq "Number") {
push(@rv, $set);
$set={};
}
}
my ($n, $v) = split(/: /, $_);
$n =~ s/^(\S+).*/$1/;
if ($n eq "Name") {
$set = { };
push(@rv, $set);
}
$set->{$n} = $v;
}
return @rv;
}
@@ -246,35 +252,43 @@ return @rv;
# Returns a human-readable description of some rule conditions
sub describe_rule
{
local (@c, $d);
my ($rule) = @_;
my (@c, $d);
foreach $d ('p', 's', 'd', 'i', 'o', 'f', 'dport',
'sport', 'tcp-flags', 'tcp-option',
'icmp-type', 'icmpv6-type', 'mac-source', 'limit', 'limit-burst',
'ports', 'uid-owner', 'gid-owner',
'pid-owner', 'sid-owner', 'ctstate', 'state', 'tos',
'dports', 'sports', 'physdev-in', 'physdev-out', 'args') {
if ($_[0]->{$d}) {
'dports', 'sports', 'physdev-in', 'physdev-out', 'match-set',
'args') {
if ($rule->{$d}) {
# get name and values
local ($n, @v) = @{$_[0]->{$d}};
my ($n, @v) = @{$rule->{$d}};
# with additional args
if ($d eq 'args') {
# get args
@v = grep {/\S/} split(/ / , $_[0]->{$d});
@v = grep {/\S/} split(/ / , $rule->{$d});
# first arg is name, next are values
$n=shift(@v);
# translate src and dest parameter for ipset
push(@v, &text("desc_". pop(@v))) if ($n eq "--match-set");
push(@v, &text("desc_".pop(@v)))
if ($n eq "--match-set");
}
# uppercase for p
@v = map { uc($_) } @v if ($d eq 'p');
# merge all in one for s and d
@v = map { join(", ", split(/,/, $_)) } @v if ($d eq 's' || $d eq 'd' );
# compose desc_$n$d to get localized message, provide values as $1, ..., $n
local $txt = &text("desc_$d$n", map { "<strong>$_</strong>" } @v);
@v = map { join(", ", split(/,/, $_)) } @v
if ($d eq 's' || $d eq 'd' );
# compose desc_$n$d to get myized message, provide values
# as $1, ..., $n
if ($d eq 'match-set') {
$v[1] = $text{'desc_'.$d.'_'.$v[1]} || $v[1];
}
my $txt = &text("desc_$d$n", map { "<b>$_</b>" } @v);
push(@c, $txt) if ($txt);
}
}
local $rv;
my $rv;
if (@c) {
$rv = &text('desc_conds', join(" $text{'desc_and'} ", @c));
}
@@ -302,7 +316,7 @@ else {
# Create (if necessary) the Webmin iptables init script
sub create_webmin_init
{
local $res = &has_command("ip${ipvx}tables-restore");
local $res = &iptable_restore_command();
local $ipt = &has_command("ip${ipvx}tables");
local $out = &backquote_command("$res -h 2>&1 </dev/null");
if ($out =~ /\s+-w\s+/) {
@@ -378,12 +392,17 @@ foreach $c ("ip${ipvx}tables", "ip${ipvx}tables-restore", "ip${ipvx}tables-save"
return undef;
}
sub iptables_restore_command
{
return &has_command("ip${ipvx}tables-legacy-restore") ||
&has_command("ip${ipvx}tables-restore");
}
# iptables_restore()
# Activates the current firewall rules, and returns any error
sub iptables_restore
{
local $rcmd = &has_command("ip${ipvx}tables-legacy-restore") ||
"ip${ipvx}tables-restore";
local $rcmd = &iptables_restore_command();
local $out = &backquote_logged("cd / && $rcmd <$ipvx_save 2>&1");
return $? ? "<pre>$out</pre>" : undef;
}
@@ -486,13 +505,41 @@ return undef;
sub merge_fail2ban_rules
{
local ($oldlive, $newlive) = @_;
local ($oldchain) = grep { $_->{'name'} eq 'f2b-default' } @$oldlive;
local ($newchain) = grep { $_->{'name'} eq 'f2b-default' } @$newlive;
return if (!$oldchain); # fail2ban was never used
local ($oldinput) = grep { $_->{'name'} eq 'INPUT' } @$oldlive;
return if (!$oldinput);
local $oldrule;
# XXX not complete yet
# Get old and new filter table
local ($oldfilter) = grep { $_->{'name'} eq 'filter' } @$oldlive;
local ($newfilter) = grep { $_->{'name'} eq 'filter' } @$newlive;
return if (!$oldfilter || !$newfilter);
local $oldrules = $oldfilter->{'rules'};
local $newrules = $newfilter->{'rules'};
# Get all old fail2ban chain rules and inputs that jump to them
local @oldrules = grep { $_->{'chain'} =~ /^f2b-/ } @$oldrules;
return if (!@oldrules);
local @oldjumps = grep { $_->{'chain'} eq 'INPUT' &&
$_->{'j'}->[1] =~ /^f2b-/ } @$oldrules;
# Get all new fail2ban chain rules and inputs that jump to them
local @newrules = grep { $_->{'chain'} =~ /^f2b-/ } @$newrules;
local @newjumps = grep { $_->{'chain'} eq 'INPUT' &&
$_->{'j'}->[1] =~ /^f2b-/ } @newrules;
# Re-create the chains
my @oldchains = &unique(map { $_->{'chain'} } @oldrules);
foreach my $c (@oldchains) {
&system_logged("ip${ipvx}tables -t filter -N $c 2>&1");
}
# Re-create any missing old rules
foreach my $r (@oldrules) {
&create_active_rule($newfilter, $r, 0);
}
foreach my $j (@oldjumps) {
my ($nj) = grep { $_->{'j'}->[1] eq $j->{'j'}->[1] } @newjumps;
if (!$nj) {
&create_active_rule($newfilter, $j, 1);
}
}
}
# list_cluster_servers()
@@ -600,5 +647,17 @@ if (!defined($supports_conntrack_cache)) {
return $supports_conntrack_cache;
}
# create_active_rule(&table, &rule, insert?)
# Execute the commands to create one rule
sub create_active_rule
{
my ($table, $rule, $insert) = @_;
my $flags = &make_rule_command($rule);
$flags =~ s/^-A /-I / if ($insert);
my $cmd = "ip${ipvx}tables -t ".$table->{'name'}." ".$flags;
my $out = &backquote_logged("$cmd 2>&1 </dev/null");
return $? ? $out : undef;
}
1;

View File

@@ -27,7 +27,7 @@ else {
'--ports', '--uid-owner', '--gid-owner',
'--pid-owner', '--sid-owner', '--state', '--ctstate', '--tos',
'-j', '--to-ports', '--to-destination', '--to-source',
'--reject-with', '--dports', '--sports',
'--reject-with', '--dports', '--sports', '--match-set',
'--comment',
'--physdev-is-bridged',
'--physdev-is-in',

View File

@@ -145,8 +145,8 @@ else {
if (!$config{"direct${ipvx}"}) {
my $err = &validate_iptables_config();
if ($err) {
print "<b>",&text('index_evalid',
&html_escape($err)),"</b><p>\n";
print "<b><font color=red>",&text('index_evalid',
&html_escape($err)),"</font></b><p>\n";
}
}
@@ -433,29 +433,36 @@ else {
# Show ipset overview if ipsets are availibe
# may need to check if they are used by firewall rules
@ipsets = &get_ipsets_active();
@ipsets = &get_ipsets_active();
if (@ipsets) {
print &ui_hr();
print "<b>$text{'index_ipset_title'}</b>";
# Generate the header
local (@hcols, @tds);
push(@hcols, $text{'index_ipset'}, "<b>$text{'index_ipset_name'}</b>&nbsp;&nbsp;", $text{'index_ipset_type'},
$text{'index_ipset_elem'}, $text{'index_ipset_maxe'}, $text{'index_ipset_size'});
push(@tds, "", "", "", "", "");
print &ui_columns_start(\@hcols, 100, 0, \@tds);
# Generate a row for each rule
foreach $s (@ipsets) {
local @cols;
local @h= split(/ /, $s->{'Header'});
# print matching pínet version
if ($h[1] =~ /inet${ipvx}$/) {
push(@cols, "&nbsp;&nbsp;$h[0] $h[1]", "&nbsp;&nbsp;<b>$s->{'Name'}</b>",
$s->{'Type'}, $s->{'Number'}, $h[5], $s->{'Size'});
print &ui_columns_row(\@cols, \@tds);
print &ui_hr();
print "<b>$text{'index_ipset_title'}</b>";
# Generate the header
@hcols = ( $text{'index_ipset'},
$text{'index_ipset_name'},
$text{'index_ipset_type'},
$text{'index_ipset_elem'},
$text{'index_ipset_maxe'},
$text{'index_ipset_size'} );
print &ui_columns_start(\@hcols, 100, 0);
# Generate a row for each rule
foreach $s (@ipsets) {
my @h = split(/ /, $s->{'Header'});
# print matching pínet version
if ($h[1] =~ /inet${ipvx}$/) {
my @cols = ( "$h[0] $h[1]",
$s->{'Name'},
$s->{'Type'},
$s->{'Number'} || 0,
$h[5],
$s->{'Size'} );
print &ui_columns_row(\@cols);
}
}
}
print &ui_columns_end();
}
print &ui_columns_end();
}
# Display buttons for applying and un-applying the configuration,
# and for creating an init script if possible
@@ -524,29 +531,29 @@ else {
&ui_print_footer("/", $text{'index'});
sub external_firewall_message
{
local $fwname="";
local $fwconfig="@{[&get_webprefix()]}/config.cgi?firewall";
{
my $fwname = "";
my $fwconfig="@{[&get_webprefix()]}/config.cgi?firewall";
# detect external firewalls
local ($filter) = grep { $_->{'name'} eq 'filter' } @{$_[0]};
if ($filter->{'defaults'}->{'shorewall'}) {
$fwname.='shorewall ';
}
if ($filter->{'defaults'}->{'INPUT_ZONES'}) {
$fwname.='firewalld ';
}
if ($filter->{'defaults'} =~ /^f2b-|^fail2ban-/ && !$config{'filter_chain'} ) {
$fwname.='fail2ban ';
}
# warning about not using direct
if($fwname && !$config{"direct${ipvx}"}) {
print "<b><center>",
&text('index_filter_nodirect', $fwconfig),
"</b></center><p>\n";
}
# alert about the detected firewall modules
foreach my $word (split ' ', $fwname) {
print ui_alert_box(&text("index_$word", "@{[&get_webprefix()]}/$word/", $fwconfig), 'warn');
}
}
# detect external firewalls
local ($filter) = grep { $_->{'name'} eq 'filter' } @{$_[0]};
if ($filter->{'defaults'}->{'shorewall'}) {
$fwname.='shorewall ';
}
if ($filter->{'defaults'}->{'INPUT_ZONES'}) {
$fwname.='firewalld ';
}
if ($filter->{'defaults'} =~ /^f2b-|^fail2ban-/ && !$config{'filter_chain'} ) {
$fwname.='fail2ban ';
}
# warning about not using direct
if($fwname && !$config{"direct${ipvx}"}) {
print "<b><center>",
&text('index_filter_nodirect', $fwconfig),
"</b></center><p>\n";
}
# alert about the detected firewall modules
foreach my $word (split ' ', $fwname) {
print ui_alert_box(&text("index_$word", "@{[&get_webprefix()]}/$word/", $fwconfig), 'warn');
}
}

View File

@@ -79,9 +79,9 @@ index_reset=Reset Firewall
index_resetdesc=Click this button to clear all existing firewall rules and set up new rules for a basic initial configuration.
index_cluster=Cluster Servers
index_clusterdesc=Click this button to set up additional Webmin servers to which the firewall configuration will be automatically copied.
index_ipset=IP-set
index_ipset_title=Active IP-sets which can be used by firewall rules
index_ipset_name=Name of IP set
index_ipset=IPset Protocol
index_ipset_title=Active IPsets which can be used by firewall rules
index_ipset_name=Name of IPset
index_ipset_type=Type
index_ipset_elem=# Elements
index_ipset_maxe=# Max
@@ -140,6 +140,10 @@ desc_ctstate=state of connection is $1
desc_ctstate!=state of connection is not $1
desc_tos=type of service field is $1
desc_tos!=type of service field is not $1
desc_match-set=$2 matches IPset $1
desc_match-set!=$2 does not match IPset $1
desc_match-set_src=incoming traffic
desc_match-set_dst=outgoing traffic
desc_physdev-in=input physical interface is $1
desc_physdev-in!=input physical interface is not $1
desc_physdev-out=output physical interface is $1
@@ -227,6 +231,9 @@ edit_physdevout=Outgoing physical interface
edit_physdevisin=Packet incoming on bridge interface
edit_physdevisout=Packet outgoing on bridge interface
edit_physdevisbridged=Packet is being bridged
edit_matchset=Matching IPset
edit_matchsetsrc=on incoming traffic
edit_matchsetdst=on outgoing traffic
save_err=Failed to save rule
save_echain=Missing or invalid chain to run

View File

@@ -362,6 +362,13 @@ else {
push(@mods, "physdev");
}
# Parse IPset
if (&parse_mode("matchset", $rule, "match-set")) {
$rule->{'match-set'}->[1] = $in{'matchset'};
$rule->{'match-set'}->[2] = $in{'matchset2'};
push(@mods, "set");
}
# Add custom parameters and modules
$rule->{'args'} = $in{'args'};
push(@mods, split(/\s+/, $in{'mods'}));

View File

@@ -3,3 +3,4 @@ category=net
longdesc=Configure a Linux firewall using ip6tables. Allows the editing of all tables, chains, rules and options.
name=Firewall6
os_support=*-linux
library=firewall-lib.pl

View File

@@ -273,7 +273,7 @@ if ($_[0] eq 'tar') {
3, $tds);
# Password option for SSH
print &ui_table_row(&hlink($text{'dump_pass2'},"passs"),
print &ui_table_row(&hlink($text{'dump_pass2'},"pass2"),
&ui_password("pass", $_[1]->{'pass'}, 20),
3, $tds);

View File

@@ -553,7 +553,7 @@ if ($_[0] eq 'tar') {
3, $tds);
# Password option for SSH
print &ui_table_row(&hlink($text{'dump_pass2'},"passs"),
print &ui_table_row(&hlink($text{'dump_pass2'},"pass2"),
&ui_password("pass", $_[1]->{'pass'}, 20),
3, $tds);
@@ -622,7 +622,7 @@ else {
3, $tds);
# Password option for SSH
print &ui_table_row(&hlink($text{'dump_pass2'},"passs"),
print &ui_table_row(&hlink($text{'dump_pass2'},"pass2"),
&ui_password("pass", $_[1]->{'pass'}, 20),
3, $tds);

View File

@@ -128,8 +128,7 @@ elsif ($init_mode eq "init" && $access{'bootup'}) {
foreach $s (@{$actsb[$i]}) {
if ($s->[2]) {
$boot = 1;
push(@levels,
"<font color=#ff0000>$s->[0]</font>");
push(@levels, &ui_text_color($s->[0], 'danger'));
}
else {
push(@levels, $s->[0]);
@@ -145,8 +144,8 @@ elsif ($init_mode eq "init" && $access{'bootup'}) {
push(@cols, join(" ", @levels));
}
else {
push(@cols,$boot ? $text{'yes'} :
"<font color=#ff0000>$text{'no'}</font>");
push(@cols,$boot ? &ui_text_color("$text{'yes'}", 'success') :
&ui_text_color("$text{'no'}", 'danger'));
}
if ($config{'order'}) {
push(@cols, $order);
@@ -155,12 +154,10 @@ elsif ($init_mode eq "init" && $access{'bootup'}) {
if ($actsl[$i] =~ /^0/ && $has{'status'}) {
local $r = &action_running($actsf[$i]);
if ($r == 0) {
push(@cols,
"<font color=#ff0000>".
"$text{'no'}</font>");
push(@cols, &ui_text_color("$text{'no'}", 'danger'));
}
elsif ($r == 1) {
push(@cols, $text{'yes'});
push(@cols, &ui_text_color("$text{'yes'}", 'success'));
}
else {
push(@cols, undef);
@@ -273,9 +270,9 @@ elsif ($init_mode eq "rc" && $access{'bootup'}) {
&ui_checkbox("d", $rc->{'name'}, undef),
&ui_link("edit_rc.cgi?name=".&urlize($rc->{'name'}), $rc->{'name'}),
$rc->{'desc'},
$rc->{'enabled'} == 1 ? $text{'yes'} :
$rc->{'enabled'} == 1 ? &ui_text_color("$text{'yes'}", 'success') :
$rc->{'enabled'} == 2 ? "<i>$text{'index_unknown'}</i>":
"<font color=#ff0000>$text{'no'}</font>",
&ui_text_color("$text{'no'}", 'danger'),
]);
}
print &ui_columns_end();
@@ -312,13 +309,13 @@ elsif ($init_mode eq "upstart" && $access{'bootup'}) {
&ui_checkbox("d", $u->{'name'}, undef, 0),
&ui_link($l, $u->{'name'}),
$u->{'desc'},
$u->{'boot'} eq 'start' ? $text{'yes'} :
$u->{'boot'} eq 'start' ? &ui_text_color("$text{'yes'}", 'success') :
$u->{'boot'} eq 'stop' ?
"<font color=#ff0000>$text{'no'}</font>" :
&ui_text_color("$text{'no'}", 'danger') :
"<i>$text{'index_unknown'}</i>",
$u->{'status'} eq 'running' ? $text{'yes'} :
$u->{'status'} eq 'running' ? &ui_text_color("$text{'yes'}", 'success') :
$u->{'status'} eq 'waiting' ?
"<font color=#ff0000>$text{'no'}</font>" :
&ui_text_color("$text{'no'}", 'danger') :
"<i>$text{'index_unknown'}</i>",
]);
}
@@ -345,6 +342,7 @@ elsif ($init_mode eq "systemd" && $access{'bootup'}) {
print &ui_links_row(\@links);
print &ui_columns_start([ "", $text{'index_uname'},
$text{'index_udesc'},
$text{'index_ucstatus'},
$text{'index_uboot'},
$text{'index_ustatus'}, ]);
foreach $u (&list_systemd_services()) {
@@ -358,12 +356,13 @@ elsif ($init_mode eq "systemd" && $access{'bootup'}) {
&ui_checkbox("d", $u->{'name'}, undef),
&ui_link($l, $u->{'name'}),
$u->{'desc'},
$u->{'boot'} == 1 ? $text{'yes'} :
$u->{'fullstatus'} || "<i>$text{'index_unknown'}</i>",
$u->{'boot'} == 1 ? &ui_text_color("$text{'yes'}", 'success') :
$u->{'boot'} == 2 ? $text{'index_always'} :
"<font color=#ff0000>$text{'no'}</font>",
$u->{'status'} == 1 ? $text{'yes'} :
&ui_text_color("$text{'no'}", 'danger'),
$u->{'status'} == 1 ? &ui_text_color("$text{'yes'}", 'success') :
$u->{'status'} == 0 ?
"<font color=#ff0000>$text{'no'}</font>" :
&ui_text_color("$text{'no'}", 'danger') :
"<i>$text{'index_unknown'}</i>",
]);
}
@@ -396,10 +395,10 @@ elsif ($init_mode eq "launchd" && $access{'bootup'}) {
print &ui_columns_row([
&ui_checkbox("d", $u->{'name'}, undef),
&ui_link($l, $u->{'name'}),
$u->{'boot'} ? $text{'yes'} :
"<font color=#ff0000>$text{'no'}</font>",
$u->{'status'} ? $text{'yes'} :
"<font color=#ff0000>$text{'no'}</font>",
$u->{'boot'} ? &ui_text_color("$text{'yes'}", 'success') :
&ui_text_color("$text{'no'}", 'danger'),
$u->{'status'} ? &ui_text_color("$text{'yes'}", 'success') :
&ui_text_color("$text{'no'}", 'danger'),
]);
}
print &ui_columns_end();

View File

@@ -1434,8 +1434,10 @@ elsif ($action_mode eq "systemd") {
my $out = &backquote_command(
"systemctl is-failed ".quotemeta($name)." 2>/dev/null");
$out =~ s/\r?\n//g;
$out = lc($out);
return $out eq "active" ? 1 :
$out eq "inactive" || $out eq "failed" ? 0 : -1;
$out eq "inactive" || $out eq "failed" ||
$out eq "active (exited)" ? 0 : -1;
}
elsif ($action_mode eq "launchd") {
my @agents = &list_launchd_agents();
@@ -2098,7 +2100,7 @@ my $ifile = "/etc/init.d/$name";
&unlink_logged($cfile, $ifile);
}
=head2 list_systemd_services
=head2 list_systemd_services(skip-init)
Returns a list of all known systemd services, each of which is a hash ref
with 'name', 'desc', 'boot', 'status' and 'pid' keys. Also includes init.d
@@ -2108,6 +2110,11 @@ systemd automatically includes init scripts).
=cut
sub list_systemd_services
{
my ($noinit) = @_;
if (@list_systemd_services_cache && !$noinit) {
return @list_systemd_services_cache;
}
# Get all systemd unit names
my $out = &backquote_command("systemctl list-units --full --all -t service --no-legend");
my $ex = $?;
@@ -2192,6 +2199,10 @@ foreach my $name (keys %info) {
'boot' => $i->{'UnitFileState'} eq 'enabled' ? 1 :
$i->{'UnitFileState'} eq 'static' ? 2 : 0,
'status' => $i->{'ActiveState'} eq 'active' ? 1 : 0,
'substatus' => $i->{'SubState'},
'fullstatus' => $i->{'SubState'} ?
"@{[ucfirst($i->{'ActiveState'})]} ($i->{'SubState'})" :
ucfirst($i->{'ActiveState'}),
'start' => $i->{'ExecStart'},
'stop' => $i->{'ExecStop'},
'reload' => $i->{'ExecReload'},
@@ -2201,27 +2212,32 @@ foreach my $name (keys %info) {
}
# Also add legacy init scripts
my @rls = &get_inittab_runlevel();
foreach my $a (&list_actions()) {
$a =~ s/\s+\d+$//;
my $f = &action_filename($a);
my $s = { 'name' => $a,
'legacy' => 1 };
$s->{'boot'} = 0;
foreach my $rl (@rls) {
my $l = glob("/etc/rc$rl.d/S*$a");
$s->{'boot'} = 1 if ($l);
if (!$noinit) {
my @rls = &get_inittab_runlevel();
foreach my $a (&list_actions()) {
$a =~ s/\s+\d+$//;
my $f = &action_filename($a);
my $s = { 'name' => $a,
'legacy' => 1 };
$s->{'boot'} = 0;
foreach my $rl (@rls) {
my $l = glob("/etc/rc$rl.d/S*$a");
$s->{'boot'} = 1 if ($l);
}
$s->{'desc'} = &init_description($f);
my $hasarg = &get_action_args($f);
if ($hasarg->{'status'}) {
my $r = &action_running($f);
$s->{'status'} = $r;
}
push(@rv, $s);
}
$s->{'desc'} = &init_description($f);
my $hasarg = &get_action_args($f);
if ($hasarg->{'status'}) {
my $r = &action_running($f);
$s->{'status'} = $r;
}
push(@rv, $s);
}
return sort { $a->{'name'} cmp $b->{'name'} } @rv;
# Return actions sorted by name
@rv = sort { $a->{'name'} cmp $b->{'name'} } @rv;
@list_systemd_services_cache = @rv if (!$noinit);
return @rv;
}
=head2 start_systemd_service(name)
@@ -2366,8 +2382,9 @@ Returns 1 if some service is managed by systemd
sub is_systemd_service
{
my ($name) = @_;
foreach my $s (&list_systemd_services()) {
if ($s->{'name'} eq $name && !$s->{'legacy'}) {
foreach my $s (&list_systemd_services(1)) {
if (($s->{'name'} eq $name ||
$s->{'name'} eq "$name.service") && !$s->{'legacy'}) {
return 1;
}
}

View File

@@ -45,6 +45,7 @@ index_radd=Skep 'n nuwe aksie.
index_unknown=onbekend
index_uname=Diensnaam
index_udesc=Diensbeskrywing
index_ucstatus=Diensstatus
index_uboot=Begin met die boot?
index_ustatus=Nou hardloop?
index_uadd=Skep 'n nuwe suksesvolle diens.

View File

@@ -43,6 +43,7 @@ index_radd=قم بإنشاء إجراء جديد.
index_unknown=مجهول
index_uname=اسم الخدمة
index_udesc=وصف الخدمة
index_ucstatus=حالة الخدمة
index_uboot=هل تريد البدء في التمهيد؟
index_ustatus=تعمل الآن؟
index_uadd=إنشاء خدمة مبتدئة جديدة.

View File

@@ -45,6 +45,7 @@ index_radd=Стварыце новае дзеянне.
index_unknown=Невядома
index_uname=Назва службы
index_udesc=Апісанне паслугі
index_ucstatus=Стан абслугоўвання
index_uboot=Пачаць з загрузкі?
index_ustatus=Цяпер працуе?
index_uadd=Стварыце новую паслугу для запуску.

View File

@@ -45,6 +45,7 @@ index_radd=Създайте ново действие.
index_unknown=неизвестен
index_uname=Име на услугата
index_udesc=Описание на услугата
index_ucstatus=Състояние на услугата
index_uboot=Започнете от зареждане?
index_ustatus=Сега тече?
index_uadd=Създайте нова услуга за стартиране.

View File

@@ -1,3 +1,5 @@
index_ucstatus=Estat del servei
systemd_file=Fitxer de configuració
syslog_journalctl=Registres SystemD

View File

@@ -1,6 +1,7 @@
index_mode=Zaváděcí systém : $1
index_uname=Název služby
index_udesc=Popis služby
index_ucstatus=Stav služby
index_uboot=Začít při spuštění?
index_ustatus=Běží nyní?
index_uadd=Vytvořte novou službu upstart.

View File

@@ -45,6 +45,7 @@ index_radd=Opret en ny handling.
index_unknown=Ukendt
index_uname=Servicenavn
index_udesc=Servicebeskrivelse
index_ucstatus=Servicestatus
index_uboot=Start ved opstart?
index_ustatus=Kører nu?
index_uadd=Opret en ny upstart-tjeneste.

View File

@@ -1,3 +1,5 @@
index_ucstatus=Service Status
systemd_file=Konfigurationsdatei
syslog_journalctl=SystemD-Protokolle

View File

@@ -45,6 +45,7 @@ index_radd=Δημιουργήστε μια νέα ενέργεια.
index_unknown=Αγνωστος
index_uname=Ονομα Υπηρεσίας
index_udesc=Περιγραφή υπηρεσίας
index_ucstatus=Κατάσταση υπηρεσίας
index_uboot=Ξεκινήστε από την εκκίνηση;
index_ustatus=Τρέχοντας τώρα;
index_uadd=Δημιουργήστε μια νέα υπηρεσία εκκίνησης.

View File

@@ -45,6 +45,7 @@ index_radd=Create a new action.
index_unknown=Unknown
index_uname=Service name
index_udesc=Service description
index_ucstatus=Service status
index_uboot=Start at boot?
index_ustatus=Running now?
index_uadd=Create a new upstart service.

View File

@@ -17,6 +17,7 @@ index_radd=Crea una nueva acción.
index_unknown=Desconocido
index_uname=Nombre del Servicio
index_udesc=Descripción del servicio
index_ucstatus=Estado del servicio
index_uboot=Comience en el arranque?
index_ustatus=Corriendo ahora?
index_uadd=Crea un nuevo servicio advenedizo.

View File

@@ -2,6 +2,7 @@ index_title=Abiarazi eta itzali
index_mode=Abiapuntu sistema : $1
index_uname=Zerbitzuaren izena
index_udesc=Zerbitzuaren deskribapena
index_ucstatus=Zerbitzuaren egoera
index_uboot=Hasi abiarazi?
index_ustatus=Orain exekutatzen ari zara?
index_uadd=Sortu martxan dagoen zerbitzu berria.

View File

@@ -17,6 +17,7 @@ index_radd=یک اقدام جدید ایجاد کنید.
index_unknown=ناشناخته
index_uname=نام سرویس
index_udesc=شرح خدمات
index_ucstatus=وضعیت سرویس
index_uboot=شروع کنید؟
index_ustatus=الان دویدن؟
index_uadd=یک سرویس upstart جدید ایجاد کنید.

View File

@@ -45,6 +45,7 @@ index_radd=Luo uusi toiminto.
index_unknown=Tuntematon
index_uname=Palvelun nimi
index_udesc=Palvelun kuvaus
index_ucstatus=Palvelun tila
index_uboot=Aloita käynnistyessä?
index_ustatus=Juoksutko nyt?
index_uadd=Luo uusi käynnistyspalvelu.

View File

@@ -10,6 +10,7 @@ index_radd=Créez une nouvelle action.
index_unknown=Inconnue
index_uname=Nom du service
index_udesc=Description du service
index_ucstatus=État du service
index_uboot=Commencez au démarrage?
index_ustatus=Vous courez maintenant?
index_uadd=Créez un nouveau service parvenu.

View File

@@ -45,6 +45,7 @@ index_radd=צור פעולה חדשה.
index_unknown=לא ידוע
index_uname=שם השירות
index_udesc=תיאור השירות
index_ucstatus=סטטוס שרות
index_uboot=מתחילים באתחול?
index_ustatus=רץ עכשיו?
index_uadd=צור שירות עליון חדש.

View File

@@ -45,6 +45,7 @@ index_radd=Stvorite novu radnju.
index_unknown=Nepoznata
index_uname=Naziv usluge
index_udesc=Opis usluge
index_ucstatus=Status usluge
index_uboot=Započeti pri pokretanju?
index_ustatus=Sada trčite?
index_uadd=Stvorite novu uslugu upstart.

View File

@@ -1,3 +1,4 @@
index_ucstatus=Szolgáltatás állapota
index_sadd=Hozzon létre egy új rendszeres szolgáltatást.
index_always=Mindig
index_ladd=Hozzon létre egy új indított ügynököt.

View File

@@ -37,6 +37,7 @@ index_radd=Crea una nuova azione.
index_unknown=Sconosciuto
index_uname=Nome di Servizio
index_udesc=Descrizione del servizio
index_ucstatus=Stato del servizio
index_uboot=Inizia all'avvio?
index_ustatus=In esecuzione adesso?
index_uadd=Crea un nuovo servizio di avvio.

View File

@@ -1,4 +1,5 @@
index_mode=ブートシステム: $1
index_ucstatus=サービスステータス
index_uadd=新しいupstartサービスを作成します。
index_sadd=新しいsystemdサービスを作成します。
index_ladd=新しいlaunchdエージェントを作成します。

View File

@@ -1,6 +1,7 @@
index_mode=부팅 시스템 : $1
index_uname=서비스 이름
index_udesc=서비스 설명
index_ucstatus=서비스 상태
index_uboot=부팅 할 때 시작 하시겠습니까?
index_ustatus=지금 달려?
index_uadd=새로운 시작 서비스를 작성하십시오.

View File

@@ -45,6 +45,7 @@ index_radd=Sukurkite naują veiksmą.
index_unknown=Nežinoma
index_uname=Paslaugos pavadinimas
index_udesc=Aptarnavimo Aprašymas
index_ucstatus=Paslaugos būsena
index_uboot=Pradėti nuo įkrovos?
index_ustatus=Veikia dabar?
index_uadd=Sukurkite naują įdiegtą paslaugą.

View File

@@ -45,6 +45,7 @@ index_radd=Izveidojiet jaunu darbību.
index_unknown=Nezināms
index_uname=Pakalpojuma nosaukums
index_udesc=Pakalpojuma apraksts
index_ucstatus=Pakalpojuma statuss
index_uboot=Sākt no sāknēšanas?
index_ustatus=Darbojas tagad?
index_uadd=Izveidojiet jaunu sākotnējo pakalpojumu.

View File

@@ -45,6 +45,7 @@ index_radd=Buat tindakan baru.
index_unknown=Tidak diketahui
index_uname=Nama perkhidmatan
index_udesc=Penerangan perkhidmatan
index_ucstatus=Status perkhidmatan
index_uboot=Mula boot?
index_ustatus=Berlari sekarang?
index_uadd=Buat perkhidmatan upstart baru.

View File

@@ -45,6 +45,7 @@ index_radd=Oħloq azzjoni ġdida.
index_unknown=Mhux magħruf
index_uname=Isem tas-servizz
index_udesc=Deskrizzjoni tas-Servizz
index_ucstatus=L-istatus tas-servizz
index_uboot=Ibda mill-ibbutjar?
index_ustatus=Tiġri issa?
index_uadd=Oħloq servizz upstart ġdid.

View File

@@ -1,3 +1,4 @@
index_ucstatus=Service status
index_ladd=Maak een nieuwe launchd-agent.
index_lname=Naam agent

View File

@@ -1 +1,3 @@
index_ucstatus=Tjenestestatus
systemd_file=Konfigurasjonsfil

View File

@@ -1,6 +1,7 @@
index_mode=System rozruchowy : $1
index_downscript=Podobnie skrypt $1 wymieniony poniżej zostanie uruchomiony w momencie zamknięcia. Możesz dodać własne polecenia, aby demony lub serwery zostały zatrzymane w sposób czysty po zamknięciu systemu.
index_rlchangedesc=Kliknij ten przycisk, aby przełączyć system z bieżącego poziomu uruchamiania na wybrany. Spowoduje to zatrzymanie wszystkich działań na bieżącym poziomie, a następnie uruchomienie wszystkich akcji na nowym poziomie uruchamiania.
index_ucstatus=Status usługi
log_condrestart=Warunkowo wznowione działanie $1

View File

@@ -37,6 +37,7 @@ index_radd=Crie uma nova ação.
index_unknown=Desconhecido
index_uname=Nome do Serviço
index_udesc=Descrição do Serviço
index_ucstatus=Status do serviço
index_uboot=Iniciar na inicialização?
index_ustatus=Correndo agora?
index_uadd=Crie um novo serviço inicial.

View File

@@ -45,6 +45,7 @@ index_radd=Crie uma nova ação.
index_unknown=Desconhecido
index_uname=Nome do Serviço
index_udesc=Descrição do Serviço
index_ucstatus=Status do serviço
index_uboot=Iniciar na inicialização?
index_ustatus=Correndo agora?
index_uadd=Crie um novo serviço inicial.

View File

@@ -45,6 +45,7 @@ index_radd=Creați o acțiune nouă.
index_unknown=Necunoscut
index_uname=Numele serviciului
index_udesc=Descrierea serviciului
index_ucstatus=Starea serviciului
index_uboot=Începeți la pornire?
index_ustatus=Alerga acum?
index_uadd=Creați un nou serviciu de actualizare.

View File

@@ -1,6 +1,7 @@
index_mode=Загрузочная система : $1
index_uname=Наименование услуги
index_udesc=Описание услуг
index_ucstatus=Статус услуги
index_uboot=Начать при загрузке?
index_ustatus=Бегом сейчас?
index_uadd=Создать новый сервис выскочки.

View File

@@ -45,6 +45,7 @@ index_radd=Vytvorte novú akciu.
index_unknown=nevedno
index_uname=Názov služby
index_udesc=Popis služby
index_ucstatus=Stav služby
index_uboot=Začať pri štarte?
index_ustatus=Bežíte teraz?
index_uadd=Vytvorte novú službu upstart.

View File

@@ -45,6 +45,7 @@ index_radd=Ustvari novo dejanje.
index_unknown=Neznano
index_uname=Ime storitve
index_udesc=Opis storitve
index_ucstatus=Stanje storitve
index_uboot=Začeti ob zagonu?
index_ustatus=Teče zdaj?
index_uadd=Ustvari novo storitev za zagon.

View File

@@ -33,6 +33,7 @@ index_radd=Skapa en ny åtgärd.
index_unknown=Okänd
index_uname=Service namn
index_udesc=Service beskrivning
index_ucstatus=Servicestatus
index_uboot=Börja vid start?
index_ustatus=Kör nu?
index_uadd=Skapa en ny upstart-tjänst.

View File

@@ -45,6 +45,7 @@ index_radd=สร้างการกระทำใหม่
index_unknown=ไม่ทราบ
index_uname=ชื่อบริการ
index_udesc=รายละเอียดการบริการ
index_ucstatus=สถานะการให้บริการ
index_uboot=เริ่มตอนบูทเหรอ?
index_ustatus=วิ่งตอนนี้เหรอ?
index_uadd=สร้างบริการพุ่งพรวดใหม่

View File

@@ -34,6 +34,7 @@ index_radd=Yeni bir eylem oluşturun.
index_unknown=Bilinmeyen
index_uname=Hizmet adı
index_udesc=Servis açıklaması
index_ucstatus=Servis durumu
index_uboot=Önyüklemeden başla?
index_ustatus=Şimdi mi koşuyorsunuz?
index_uadd=Yeni bir başlangıç hizmeti oluşturun.

View File

@@ -22,6 +22,7 @@ index_radd=Створіть нову дію.
index_unknown=Невідомо
index_uname=Назва послуги
index_udesc=Опис послуги
index_ucstatus=Статус сервісу
index_uboot=Почати з завантаження?
index_ustatus=Працює зараз?
index_uadd=Створіть нову послугу для запуску.

View File

@@ -45,6 +45,7 @@ index_radd=ایک نئی کارروائی بنائیں۔
index_unknown=نامعلوم
index_uname=سروس کا نام
index_udesc=خدمت کی تفصیل
index_ucstatus=سروس کی حیثیت
index_uboot=بوٹ پر شروع کریں؟
index_ustatus=ابھی چل رہا ہے؟
index_uadd=ایک نئی اسٹارسٹ سروس بنائیں۔

View File

@@ -45,6 +45,7 @@ index_radd=Tạo một hành động mới.
index_unknown=không xác định
index_uname=Tên dịch vụ
index_udesc=Dịch vụ Mô tả
index_ucstatus=Tình trạng dịch vụ
index_uboot=Bắt đầu lúc khởi động?
index_ustatus=Chạy ngay bây giờ?
index_uadd=Tạo một dịch vụ mới bắt đầu.

View File

@@ -23,6 +23,7 @@ index_radd=创建一个新动作。
index_unknown=未知
index_uname=服务名称
index_udesc=服务说明
index_ucstatus=服务状态
index_uboot=从启动开始?
index_ustatus=现在跑步?
index_uadd=创建一个新的新贵服务。

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