Compare commits

..

113 Commits

Author SHA1 Message Date
Michael Kaufmann (d00p)
f5dc8aa1c9 set version to 0.9.37 for upcoming release
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-08-02 08:51:34 +02:00
Michael Kaufmann (d00p)
ceaa0fcf5c Update phpMailer to version 5.2.16
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-08-02 08:50:22 +02:00
Michael Kaufmann (d00p)
cc372ba89b show DNS editor only if nameserver is activated at all
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-08-02 07:58:23 +02:00
Michael Kaufmann (d00p)
526eb84b71 Remove superfluous exit-statement
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-08-01 15:05:58 +02:00
Michael Kaufmann
14e54ff41a Merge pull request #368 from micw/feature-zugang-zu-ausgeblendeten-seiten-sperren
If a customer's page is hidden from menu via settings, redirect the user if he tries to access the page
2016-08-01 15:03:48 +02:00
Michael Kaufmann (d00p)
aa76ae4ddc check for uid/gid or username/groupname correctly in config-xml files, fixes #1642
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-08-01 08:47:45 +02:00
Michael Kaufmann (d00p)
f1b7d731bd Fix #2 Parameter 3 to getFormFieldDataXXX() expected to be a reference, value given since php-7.0.9
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-07-29 09:13:34 +02:00
Michael Wyraz
e3587fb346 If a customer's page is hidden from menu via settings, redirect the user if he tries to access the page 2016-07-27 13:45:54 +02:00
Michael Kaufmann (d00p)
e5c649aba3 Add dns-editor icon/link to domain-overview list
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-07-27 07:48:25 +02:00
Michael Kaufmann
4a3b64b497 Merge pull request #367 from micw/feature-optionen-fuer-kunden-ausblenden
Feature: Panel setting to hide certain menu items and traffic charts from customers
2016-07-25 08:00:37 +02:00
Michael Wyraz
54e2f83b17 function Settings::IsInList that tests if an option of a multi-select setting is set 2016-07-22 10:30:13 +02:00
Michael Wyraz
a95233041e Better translations for new feature to hide menu items and traffic charts from customer panel 2016-07-22 09:56:40 +02:00
Michael Wyraz
5165cac4e2 Hide http/ftp/mail traffic charts based on new settings 2016-07-22 09:44:20 +02:00
Michael Wyraz
d31c4fa37c Hide customer menu items based on new settings 2016-07-22 09:31:20 +02:00
Michael Wyraz
084e72968a Moved new texts to end of language file 2016-07-22 09:30:55 +02:00
Michael Wyraz
6ab8cb1d7c Adding option to hide some elements in customer panel 2016-07-21 15:53:14 +02:00
Michael Kaufmann (d00p)
6589653667 set version to 0.9.37-rc1 for upcoming release candidate
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-07-18 16:47:19 +02:00
Michael Kaufmann (d00p)
c3753478f2 add newline after custom options to avoid possible syntax error in apache-config, thx to J-BBB for testing
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-07-14 09:14:37 +02:00
Michael Kaufmann (d00p)
b63fc5b508 fix glued strings in german language file
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-07-14 08:45:10 +02:00
Michael Kaufmann (d00p)
3d2cb879b0 actually use the new setting for custom directory options file content, refs #1638
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-07-14 08:36:14 +02:00
Michael Kaufmann (d00p)
8366e57512 Adding new setting for mod_php users to specify content of the global directory options file, fixes #1638
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-07-14 08:25:28 +02:00
Michael Kaufmann (d00p)
1c369e5503 add possibility to disable web or traffic cron by setting the max-percentage value to 0, fixes #1639
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-07-14 07:58:56 +02:00
Michael Kaufmann (d00p)
83f40401be fix change_date for PDNS records
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-07-11 09:15:21 +02:00
Michael Kaufmann
19456e9b30 Merge pull request #365 from nachtgeist/master
generic html form handling: don't remove leading tabs
2016-06-24 09:09:23 +02:00
Daniel Reichelt
7d2c64ce63 generic html form handling: don't remove leading tabs
(+remove commented out code in the vicinity, probably debugging remnants)
2016-06-24 08:43:02 +02:00
Michael Kaufmann (d00p)
3f790bc334 keep the same structure for every distro + minor permission fixes
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-06-24 08:03:42 +02:00
Michael Kaufmann (d00p)
164e1108e5 fix for sql changes, refs #1635
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-06-24 07:49:52 +02:00
Michael Kaufmann (d00p)
8fe20251f3 try to be more strict-mode compatible, fixes #1635
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-06-24 07:42:23 +02:00
Michael Kaufmann (d00p)
a121363dd2 update pdns-config templates / commands
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-06-24 07:38:19 +02:00
Michael Kaufmann (d00p)
7ec777c9dd put index back in location-context; try_files not really necessary if not using PHP, also eases use of proxy_pass users; thx to karstenk
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-06-20 09:55:27 +02:00
Michael Kaufmann
77aa58a0a3 Merge pull request #362 from nachtgeist/master
don't split .gitignore
2016-06-20 06:26:45 +02:00
Daniel Reichelt
1e8bc553b8 fix/add SAPI checks to prevent execution via webserver 2016-06-19 23:43:42 +02:00
Daniel Reichelt
6df08f6b9a don't split .gitignore
they would end up in .deb packages
2016-06-19 23:09:04 +02:00
Michael Kaufmann (d00p)
5e9e2996d7 avoid php-5.6 operator
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-06-19 22:08:17 +02:00
Michael Kaufmann (d00p)
6f8aa1cbc0 update another idnaconvert related class
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-06-19 20:22:00 +02:00
Michael Kaufmann (d00p)
b22e70804b update new IdnaConvert class with needed fixes in them
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-06-19 20:15:33 +02:00
Michael Kaufmann (d00p)
5789e9a8a4 re-add old IDNA class so we do not have to force the php-5.6 requirement for froxlor
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-06-19 18:59:44 +02:00
Michael Kaufmann
6c55a40606 Merge pull request #361 from Froxlor/dns-subzone
Dns subzone fixes by nachtgeist
2016-06-18 08:06:51 +02:00
Daniel Reichelt
b4f90730cc unify "reloading" the dns daemon 2016-06-18 02:33:03 +02:00
Daniel Reichelt
50317da185 dns: no separate zonefiles for ismainbutsubto domains 3/3
replace iteration over $domains array by recursive walkDomainList()
2016-06-18 02:33:02 +02:00
Daniel Reichelt
631e36f4d5 dns: no separate zonefiles for ismainbutsubto domains 2/3
rewrite getDomainList() to contain parent-relations
2016-06-18 01:47:16 +02:00
Daniel Reichelt
a400fc9c65 dns: no separate zonefiles for ismainbutsubto domains 1/3
move log message
2016-06-18 01:47:12 +02:00
Daniel Reichelt
5f9962b6ba dns: fix generation of zone serials 2016-06-17 22:25:35 +02:00
Daniel Reichelt
d6dc71436a dns: fix generation of imap/pop3/mail/smtp A/AAAA-records
The dns-editor introduced a regression where imap/pop3/mail/smtp A-records
would not get created, even tough the setting system.dns_createmailentry was
enabled.

fix A fix
2016-06-17 22:25:21 +02:00
Daniel Reichelt
b6f99958fd dns: fix generation of alias records for subdomains
The checks whether or not to create wildcard/www records for subdomains
wrongly depended on the setting of the parent domain instead of the
subdomain in question.
2016-06-17 19:43:36 +02:00
Michael Kaufmann (d00p)
9a89f06bf0 Merge branch 'master' of github.com:Froxlor/Froxlor 2016-06-16 11:03:10 +02:00
Michael Kaufmann (d00p)
843845a825 Update Idna-Converter to version 1.0.2 (default IDNA standard is now 2008)
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-06-16 11:03:02 +02:00
Michael Kaufmann
0b93ba3dde Merge pull request #360 from nachtgeist/master
cron_traffic: replace echo by log message
2016-06-15 16:33:19 +02:00
Daniel Reichelt
bd36145ad6 cron_traffic: replace echo by log message 2016-06-15 16:15:34 +02:00
Michael Kaufmann (d00p)
88ccf5b869 don't generate unnecessary php-related vhost-entries when php is disabled, thx to karstenk
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-06-14 07:29:38 +02:00
Michael Kaufmann (d00p)
5866293a25 add script to change ip-addresses in froxlor from CLI and updated corresponding settings. Helpful for VM-template installations or similar. Use at own risk; feedback is appreciated
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-06-13 13:45:23 +02:00
Michael Kaufmann
d2711889de Merge pull request #359 from flokli/lng-typos
Fix language typos
2016-06-08 06:23:37 +02:00
Florian Klink
82af43f598 lng/english: unify upper/lowercase string in $lng['panel']
Some where lowercase, some uppercase. Especially in the Cancel/save case
this looked weird.

This patch changes all button labels to their uppercase form.
2016-06-07 22:36:45 +02:00
Florian Klink
7a36f5edac lng: fix typo decending -> descending 2016-06-07 22:33:24 +02:00
Michael Kaufmann
480d21f555 Merge pull request #358 from ohader/SecDatabaseInformationDisclosure
[SECURITY] Information disclosure on database failures
2016-06-04 21:47:12 +02:00
Oliver Hader
2e7133d619 [SECURITY] Information disclosure on database failures
In case the database is not responding, e.g. due to "too many connections"
cut-off database credentials might be shown and system path be revealed.
In terms of security this is considered as information disclosure.
2016-06-04 20:41:03 +02:00
Michael Kaufmann
85f707af8a Merge pull request #357 from yaplik/master
fix non-persistent XSS due inproper content escaping
2016-06-03 16:29:28 +02:00
Jiří Zapletal
970a119f23 fix non-persistent XSS due inproper content escaping 2016-06-03 16:20:34 +02:00
Stefan Heid
7faebbb197 BUGFIX: Cleaninstall fails due syntax error in froxlor.sql (missing comma) (#356) 2016-06-02 21:21:40 +02:00
Michael Kaufmann
08d505b308 Merge pull request #355 from Froxlor/dns-editor
Add full dns editor + powerdns to froxlor; fixes #53, fixes #731, fixes #1196,
2016-05-30 09:09:15 +02:00
Michael Kaufmann (d00p)
1b0649d0cf replace CUSTOMER_TMP with the correct tmp-folder, depending what php-interface is being used
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-29 09:56:33 +02:00
Michael Kaufmann (d00p)
e5c16439e1 replace config-template-variables also in commands to be executed, e.g. used in proftpd ssl-cert generation command
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-29 09:41:38 +02:00
Michael Kaufmann (d00p)
151d8f8c5c Merge remote-tracking branch 'origin/master' into dns-editor 2016-05-23 15:55:24 +02:00
Michael Kaufmann (d00p)
08563e9298 add more opcache-php.ini directives for php-fpm, fixes #1624
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-23 13:01:05 +02:00
Michael Kaufmann (d00p)
b51f0821cb show scheduled backup and give customer the possiblity to abort the job
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-22 11:08:44 +02:00
Michael Kaufmann (d00p)
339d84736e no quotation of dns data for powerdns
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-21 09:03:21 +02:00
Michael Kaufmann (d00p)
7ea1de2a92 allow defined non-existing entry for SRV target-value for real now, i guess
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-20 16:21:55 +02:00
Michael Kaufmann (d00p)
be373e278f allow defined non-existing entry for SRV target-value
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-20 16:17:33 +02:00
Michael Kaufmann (d00p)
61eab6fd93 do not validate fqdn of SRV and TXT entries, as they might use underscores
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-20 15:56:06 +02:00
Michael Kaufmann (d00p)
c2b0714b4a powerdns needs the 'whole' record (., e.g. sub.example.com)
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-19 13:49:22 +02:00
Michael Kaufmann (d00p)
5c1079e04b Add change_date value to the pdns-record entries
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-19 12:09:04 +02:00
Michael Kaufmann (d00p)
257f65bd1b add powerdns config-templates for distros
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-19 10:29:17 +02:00
Michael Kaufmann (d00p)
96ff346e54 fix powerdns-config template
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-19 09:28:46 +02:00
Michael Kaufmann (d00p)
076b6143ce limit record length
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-18 15:55:20 +02:00
Michael Kaufmann (d00p)
1e3262d691 do not show dns-editor to customers if not allowed and they enter the URL manually
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-18 13:54:21 +02:00
Michael Kaufmann (d00p)
94af32fb82 Merge remote-tracking branch 'origin/master' into dns-editor 2016-05-18 13:40:41 +02:00
Michael Kaufmann (d00p)
1f63ea10a0 adjust install sql file for dnsenabled flag and db-version
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-18 13:39:46 +02:00
Michael Kaufmann (d00p)
fa60c17dbc fix sql-query when editing a customer; check for dnsenabled flag in customer-domain-view template
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-18 13:32:44 +02:00
Michael Kaufmann (d00p)
b4c7fb574c increase DB version for db-updates
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-18 13:27:56 +02:00
Michael Kaufmann (d00p)
83fa0059de add flag to allow access to dns-editor per customer; clean up dns-entries when domain gets deleted
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-18 13:25:31 +02:00
Michael Kaufmann (d00p)
d97957e558 array short-syntax is only PHP >= 5.4
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-18 12:12:34 +02:00
Michael Kaufmann (d00p)
b14ab6b1c1 validate record/label in dns-editor; better escaping for soa-admin mail
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-18 10:35:47 +02:00
Michael Kaufmann (d00p)
b029fe113e Merge remote-tracking branch 'origin/master' into dns-editor 2016-05-18 10:34:14 +02:00
Michael Kaufmann (d00p)
477c99b4de Merge remote-tracking branch 'origin/master' into dns-editor 2016-05-18 10:31:05 +02:00
Michael Kaufmann (d00p)
1ce5cf6c00 various fixes for dns with froxlor-hostname
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-17 09:12:39 +02:00
Michael Kaufmann (d00p)
f7441df895 add missing file inclusion
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-17 08:43:02 +02:00
Michael Kaufmann (d00p)
69443d95d5 add support for power-dns (untested); most config-templates missing for pdns; create SPF/DKIM entries only if domain is emaildomain
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-17 08:30:02 +02:00
Michael Kaufmann (d00p)
11e923453e Merge remote-tracking branch 'origin/master' into dns-editor 2016-05-16 19:59:27 +02:00
Michael Kaufmann (d00p)
28115e6b1d add missing german language string
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-15 10:08:42 +02:00
Michael Kaufmann (d00p)
68fa0e6576 let createDomainZone() return the DnsZone object for better use later
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-15 09:56:48 +02:00
Michael Kaufmann (d00p)
8d8da0986a fix typo in DnsEntry class
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-15 08:53:47 +02:00
Michael Kaufmann (d00p)
e0e748a0bc outsource record-generation and zone-generation to classes for better handling
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-15 08:46:23 +02:00
Michael Kaufmann (d00p)
02654a256d fix sql query in getAllowedDomainEntry()
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-14 08:59:46 +02:00
Michael Kaufmann (d00p)
552c6e6cf9 add 'enable dns editor'-setting; fix missing isbinddomain index in customer_domain
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-14 08:32:38 +02:00
Michael Kaufmann (d00p)
86dc57c2cc outsource some dns functions to own files; allow opening of dns-editor only for domains that belong to the user (or the user has permission to edit as admin/reseller)
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-13 19:40:37 +02:00
Michael Kaufmann (d00p)
11eb08e031 add enabled-flag; enable dns-editor for customers; add german translations; few more fixes
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-13 13:27:33 +02:00
Michael Kaufmann (d00p)
4a4acc5c01 fix constructor of DnsBase 2016-05-12 14:32:41 +02:00
Michael Kaufmann (d00p)
899663350d fix handling of DKIM multi-line entries; outsource some code to new DnsBase class
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-12 13:36:17 +02:00
Michael Kaufmann (d00p)
689a1fdbd2 inform cronjob to regenerate bind-configs on changes
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-12 10:18:45 +02:00
Michael Kaufmann (d00p)
cec5f33870 fix checking for existing SPF entry in DNS
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-12 10:14:04 +02:00
Michael Kaufmann (d00p)
bd9ef50e94 correct SPF dns entry for new layout
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-12 09:47:36 +02:00
Michael Kaufmann (d00p)
68d579b629 add SPF and DKIM stuff to DNS
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-12 09:36:33 +02:00
Michael Kaufmann (d00p)
0404618c24 add experimental bind-cron for testing purposes
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-11 18:10:17 +02:00
Michael Kaufmann (d00p)
9b5ce83e8b add testing-bind-cron for new dns-stuff (not activated); added main-but-subdomain-stuff
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-11 16:11:23 +02:00
Michael Kaufmann (d00p)
7379398d22 set correct primary nameserver for SOA record
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-11 13:47:36 +02:00
Michael Kaufmann (d00p)
d1106dd984 fix wrong unset of array-element
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-11 07:44:32 +02:00
Michael Kaufmann (d00p)
b775c2f60e minor fixes
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-10 19:20:01 +02:00
Michael Kaufmann (d00p)
407a7c01aa add createDomainZone function for new dns-editor; dump zone below the editor for testing purposes; all required entries that are not custom entered will be auto-generated like the bind-cron does this for now
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-10 14:11:01 +02:00
Michael Kaufmann (d00p)
64d068659f more validation for NS and SRV records; fix display of long records
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-10 10:54:59 +02:00
Michael Kaufmann (d00p)
e33d7b756f add missing error-language-string; check whether domain is bind-domain
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-10 07:37:42 +02:00
Michael Kaufmann (d00p)
283e272b99 enhance MX validation; fix SRV validation
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-10 07:37:42 +02:00
Michael Kaufmann (d00p)
31d08d532c fix missing auto-increment for new table
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-10 07:37:42 +02:00
Michael Kaufmann (d00p)
5acd51fdd3 add first part of new dns-editor
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-10 07:37:42 +02:00
97 changed files with 9279 additions and 1691 deletions

12
.gitignore vendored
View File

@@ -1,6 +1,7 @@
templates/*
logs/*
install/update.log
templates/*
lib/userdata.inc.php
logs/*
.buildpath
.project
.settings/
@@ -8,4 +9,9 @@ install/update.log
*~
.well-known
.idea
*.iml
*.iml
!templates/Froxlor/
!templates/Sparkle/
!templates/misc/
templates/Froxlor/assets/img/logo_custom.png

View File

@@ -227,6 +227,30 @@ return array(
'default' => false,
'save_method' => 'storeSettingField',
),
'panel_customer_hide_options' => array(
'label' => $lng['serversettings']['panel_customer_hide_options'],
'settinggroup' => 'panel',
'varname' => 'customer_hide_options',
'type' => 'option',
'default' => '',
'option_mode' => 'multiple',
'option_options' => array(
'email' => $lng['menue']['email']['email'],
'mysql' => $lng['menue']['mysql']['mysql'],
'domains' => $lng['menue']['domains']['domains'],
'ftp' => $lng['menue']['ftp']['ftp'],
'extras' => $lng['menue']['extras']['extras'],
'extras.directoryprotection' => $lng['menue']['extras']['extras']." / ".$lng['menue']['extras']['directoryprotection'],
'extras.pathoptions' => $lng['menue']['extras']['extras']." / ".$lng['menue']['extras']['pathoptions'],
'extras.logger' => $lng['menue']['extras']['extras']." / ".$lng['menue']['logger']['logger'],
'extras.backup' => $lng['menue']['extras']['extras']." / ".$lng['menue']['extras']['backup'],
'traffic' => $lng['menue']['traffic']['traffic'],
'traffic.http' => $lng['menue']['traffic']['traffic']." / HTTP",
'traffic.ftp' => $lng['menue']['traffic']['traffic']." / FTP",
'traffic.mail' => $lng['menue']['traffic']['traffic']." / Mail",
),
'save_method' => 'storeSettingField',
),
),
),
),

View File

@@ -145,7 +145,7 @@ return array(
'settinggroup' => 'system',
'varname' => 'report_webmax',
'type' => 'int',
'int_min' => 1,
'int_min' => 0,
'int_max' => 150,
'default' => 90,
'save_method' => 'storeSettingField',
@@ -155,7 +155,7 @@ return array(
'settinggroup' => 'system',
'varname' => 'report_trafficmax',
'type' => 'int',
'int_min' => 1,
'int_min' => 0,
'int_max' => 150,
'default' => 90,
'save_method' => 'storeSettingField',

View File

@@ -16,7 +16,6 @@
* @package Settings
*
*/
return array(
'groups' => array(
'webserver' => array(
@@ -29,11 +28,15 @@ return array(
'type' => 'option',
'default' => 'apache2',
'option_mode' => 'one',
'option_options' => array('apache2' => 'Apache 2', 'lighttpd' => 'ligHTTPd', 'nginx' => 'Nginx'),
'option_options' => array(
'apache2' => 'Apache 2',
'lighttpd' => 'ligHTTPd',
'nginx' => 'Nginx'
),
'save_method' => 'storeSettingField',
'plausibility_check_method' => 'checkPhpInterfaceSetting',
'overview_option' => true
),
),
'system_apache_24' => array(
'label' => $lng['serversettings']['apache_24'],
'settinggroup' => 'system',
@@ -41,34 +44,38 @@ return array(
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField',
'websrv_avail' => array('apache2')
),
'system_apache_itksupport' => array(
'label' => $lng['serversettings']['apache_itksupport'],
'settinggroup' => 'system',
'varname' => 'apacheitksupport',
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField',
'visible' => (Settings::Get('system.mod_fcgid') == 0 && Settings::Get('phpfpm.enabled') == 0),
'websrv_avail' => array('apache2')
),
'websrv_avail' => array(
'apache2'
)
),
'system_apache_itksupport' => array(
'label' => $lng['serversettings']['apache_itksupport'],
'settinggroup' => 'system',
'varname' => 'apacheitksupport',
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField',
'visible' => (Settings::Get('system.mod_fcgid') == 0 && Settings::Get('phpfpm.enabled') == 0),
'websrv_avail' => array(
'apache2'
)
),
'system_httpuser' => array(
'label' => $lng['admin']['webserver_user'],
'settinggroup' => 'system',
'varname' => 'httpuser',
'type' => 'string',
'default' => 'www-data',
'save_method' => 'storeSettingWebserverFcgidFpmUser',
),
'save_method' => 'storeSettingWebserverFcgidFpmUser'
),
'system_httpgroup' => array(
'label' => $lng['admin']['webserver_group'],
'settinggroup' => 'system',
'varname' => 'httpgroup',
'type' => 'string',
'default' => 'www-data',
'save_method' => 'storeSettingField',
),
'save_method' => 'storeSettingField'
),
'system_apacheconf_vhost' => array(
'label' => $lng['serversettings']['apacheconf_vhost'],
'settinggroup' => 'system',
@@ -76,8 +83,8 @@ return array(
'type' => 'string',
'string_type' => 'filedir',
'default' => '/etc/apache2/sites-enabled/',
'save_method' => 'storeSettingField',
),
'save_method' => 'storeSettingField'
),
'system_apacheconf_diroptions' => array(
'label' => $lng['serversettings']['apacheconf_diroptions'],
'settinggroup' => 'system',
@@ -85,8 +92,8 @@ return array(
'type' => 'string',
'string_type' => 'filedir',
'default' => '/etc/apache2/sites-enabled/',
'save_method' => 'storeSettingField',
),
'save_method' => 'storeSettingField'
),
'system_apacheconf_htpasswddir' => array(
'label' => $lng['serversettings']['apacheconf_htpasswddir'],
'settinggroup' => 'system',
@@ -94,8 +101,8 @@ return array(
'type' => 'string',
'string_type' => 'confdir',
'default' => '/etc/apache2/htpasswd/',
'save_method' => 'storeSettingField',
),
'save_method' => 'storeSettingField'
),
'system_logfiles_directory' => array(
'label' => $lng['serversettings']['logfiles_directory'],
'settinggroup' => 'system',
@@ -103,8 +110,8 @@ return array(
'type' => 'string',
'string_type' => 'dir',
'default' => '/var/customers/logs/',
'save_method' => 'storeSettingField',
),
'save_method' => 'storeSettingField'
),
'system_customersslpath' => array(
'label' => $lng['serversettings']['customerssl_directory'],
'settinggroup' => 'system',
@@ -112,8 +119,8 @@ return array(
'type' => 'string',
'string_type' => 'confdir',
'default' => '/etc/ssl/froxlor-custom/',
'save_method' => 'storeSettingField',
),
'save_method' => 'storeSettingField'
),
'system_phpappendopenbasedir' => array(
'label' => $lng['serversettings']['phpappendopenbasedir'],
'settinggroup' => 'system',
@@ -121,8 +128,8 @@ return array(
'type' => 'string',
'string_emptyallowed' => true,
'default' => '',
'save_method' => 'storeSettingField',
),
'save_method' => 'storeSettingField'
),
'system_deactivateddocroot' => array(
'label' => $lng['serversettings']['deactivateddocroot'],
'settinggroup' => 'system',
@@ -131,24 +138,36 @@ return array(
'string_type' => 'dir',
'string_emptyallowed' => true,
'default' => '',
'save_method' => 'storeSettingField',
),
'save_method' => 'storeSettingField'
),
'system_default_vhostconf' => array(
'label' => $lng['serversettings']['default_vhostconf'],
'settinggroup' => 'system',
'varname' => 'default_vhostconf',
'type' => 'text',
'default' => '',
'save_method' => 'storeSettingField'
),
'system_apache_globaldiropt' => array(
'label' => $lng['serversettings']['apache_globaldiropt'],
'settinggroup' => 'system',
'varname' => 'apacheglobaldiropt',
'type' => 'text',
'default' => '',
'save_method' => 'storeSettingField',
),
'visible' => (Settings::Get('system.mod_fcgid') == 0 && Settings::Get('phpfpm.enabled') == 0),
'websrv_avail' => array(
'apache2'
)
),
'system_apachereload_command' => array(
'label' => $lng['serversettings']['apachereload_command'],
'settinggroup' => 'system',
'varname' => 'apachereload_command',
'type' => 'string',
'default' => '/etc/init.d/apache2 reload',
'save_method' => 'storeSettingField',
),
'save_method' => 'storeSettingField'
),
'system_phpreload_command' => array(
'label' => $lng['serversettings']['phpreload_command'],
'settinggroup' => 'system',
@@ -156,8 +175,10 @@ return array(
'type' => 'string',
'default' => '',
'save_method' => 'storeSettingField',
'websrv_avail' => array('nginx')
),
'websrv_avail' => array(
'nginx'
)
),
'system_nginx_php_backend' => array(
'label' => $lng['serversettings']['nginx_php_backend'],
'settinggroup' => 'system',
@@ -165,8 +186,10 @@ return array(
'type' => 'string',
'default' => '127.0.0.1:8888',
'save_method' => 'storeSettingField',
'websrv_avail' => array('nginx')
),
'websrv_avail' => array(
'nginx'
)
),
'nginx_fastcgiparams' => array(
'label' => $lng['serversettings']['nginx_fastcgiparams'],
'settinggroup' => 'nginx',
@@ -175,16 +198,18 @@ return array(
'string_type' => 'file',
'default' => '/etc/nginx/fastcgi_params',
'save_method' => 'storeSettingField',
'websrv_avail' => array('nginx')
),
'websrv_avail' => array(
'nginx'
)
),
'defaultwebsrverrhandler_enabled' => array(
'label' => $lng['serversettings']['defaultwebsrverrhandler_enabled'],
'settinggroup' => 'defaultwebsrverrhandler',
'varname' => 'enabled',
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField',
),
'save_method' => 'storeSettingField'
),
'defaultwebsrverrhandler_err401' => array(
'label' => $lng['serversettings']['defaultwebsrverrhandler_err401'],
'settinggroup' => 'defaultwebsrverrhandler',
@@ -192,8 +217,11 @@ return array(
'type' => 'string',
'default' => '',
'save_method' => 'storeSettingField',
'websrv_avail' => array('apache2', 'nginx')
),
'websrv_avail' => array(
'apache2',
'nginx'
)
),
'defaultwebsrverrhandler_err403' => array(
'label' => $lng['serversettings']['defaultwebsrverrhandler_err403'],
'settinggroup' => 'defaultwebsrverrhandler',
@@ -201,16 +229,19 @@ return array(
'type' => 'string',
'default' => '',
'save_method' => 'storeSettingField',
'websrv_avail' => array('apache2', 'nginx')
),
'websrv_avail' => array(
'apache2',
'nginx'
)
),
'defaultwebsrverrhandler_err404' => array(
'label' => $lng['serversettings']['defaultwebsrverrhandler_err404'],
'settinggroup' => 'defaultwebsrverrhandler',
'varname' => 'err404',
'type' => 'string',
'default' => '',
'save_method' => 'storeSettingField',
),
'save_method' => 'storeSettingField'
),
'defaultwebsrverrhandler_err500' => array(
'label' => $lng['serversettings']['defaultwebsrverrhandler_err500'],
'settinggroup' => 'defaultwebsrverrhandler',
@@ -218,8 +249,11 @@ return array(
'type' => 'string',
'default' => '',
'save_method' => 'storeSettingField',
'websrv_avail' => array('apache2', 'nginx')
),
'websrv_avail' => array(
'apache2',
'nginx'
)
),
'customredirect_enabled' => array(
'label' => $lng['serversettings']['customredirect_enabled'],
'settinggroup' => 'customredirect',
@@ -227,8 +261,11 @@ return array(
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField',
'websrv_avail' => array('apache2', 'lighttpd')
),
'websrv_avail' => array(
'apache2',
'lighttpd'
)
),
'customredirect_default' => array(
'label' => $lng['serversettings']['customredirect_default'],
'settinggroup' => 'customredirect',
@@ -238,9 +275,12 @@ return array(
'option_mode' => 'one',
'option_options_method' => 'getRedirectCodes',
'save_method' => 'storeSettingField',
'websrv_avail' => array('apache2', 'lighttpd')
'websrv_avail' => array(
'apache2',
'lighttpd'
)
)
)
)
);
)
);

View File

@@ -114,7 +114,7 @@ return array(
'varname' => 'letsencryptstate',
'type' => 'string',
'string_emptyallowed' => false,
'default' => 'Germany',
'default' => 'Hessen',
'save_method' => 'storeSettingField',
),
'system_letsencryptchallengepath' => array(

View File

@@ -31,6 +31,24 @@ return array(
'save_method' => 'storeSettingField',
'overview_option' => true
),
'system_dnsenabled' => array(
'label' => $lng['serversettings']['dnseditorenable'],
'settinggroup' => 'system',
'varname' => 'dnsenabled',
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField'
),
'system_dns_server' => array(
'label' => $lng['serversettings']['dns_server'],
'settinggroup' => 'system',
'varname' => 'dns_server',
'type' => 'option',
'default' => 'bind',
'option_mode' => 'one',
'option_options' => array('bind' => 'Bind9', 'pdns' => 'PowerDNS'),
'save_method' => 'storeSettingField'
),
'system_bindconf_directory' => array(
'label' => $lng['serversettings']['bindconf_directory'],
'settinggroup' => 'system',

View File

@@ -34,7 +34,7 @@ return array(
'settinggroup' => 'spf',
'varname' => 'spf_entry',
'type' => 'string',
'default' => '@ IN TXT "v=spf1 a mx -all"',
'default' => '"v=spf1 a mx -all"',
'save_method' => 'storeSettingField'
)
)

View File

@@ -19,199 +19,209 @@ define('AREA', 'admin');
require './lib/init.php';
if ($userinfo['change_serversettings'] == '1') {
$replace_arr = Array(
'<SQL_UNPRIVILEGED_USER>' => $sql['user'],
'<SQL_UNPRIVILEGED_PASSWORD>' => 'MYSQL_PASSWORD',
'<SQL_DB>' => $sql['db'],
'<SQL_HOST>' => $sql['host'],
'<SQL_SOCKET>' => isset($sql['socket']) ? $sql['socket'] : null,
'<SERVERNAME>' => Settings::Get('system.hostname'),
'<SERVERIP>' => Settings::Get('system.ipaddress'),
'<NAMESERVERS>' => Settings::Get('system.nameservers'),
'<VIRTUAL_MAILBOX_BASE>' => Settings::Get('system.vmail_homedir'),
'<VIRTUAL_UID_MAPS>' => Settings::Get('system.vmail_uid'),
'<VIRTUAL_GID_MAPS>' => Settings::Get('system.vmail_gid'),
'<SSLPROTOCOLS>' => (Settings::Get('system.use_ssl') == '1') ? 'imaps pop3s' : '',
'<CUSTOMER_TMP>' => (Settings::Get('system.mod_fcgid_tmpdir') != '') ? makeCorrectDir(Settings::Get('system.mod_fcgid_tmpdir')) : '/tmp/',
'<BASE_PATH>' => makeCorrectDir(FROXLOR_INSTALL_DIR),
'<BIND_CONFIG_PATH>' => makeCorrectDir(Settings::Get('system.bindconf_directory')),
'<WEBSERVER_RELOAD_CMD>' => Settings::Get('system.apachereload_command'),
'<CUSTOMER_LOGS>' => makeCorrectDir(Settings::Get('system.logfiles_directory')),
'<FPM_IPCDIR>' => makeCorrectDir(Settings::Get('phpfpm.fastcgi_ipcdir')),
'<WEBSERVER_GROUP>' => Settings::Get('system.httpgroup')
);
// get distro from URL param
$distribution = (isset($_GET['distribution']) && $_GET['distribution'] != 'choose') ? $_GET['distribution'] : "";
$service = (isset($_GET['service']) && $_GET['service'] != 'choose') ? $_GET['service'] : "";
$daemon = (isset($_GET['daemon']) && $_GET['daemon'] != 'choose') ? $_GET['daemon'] : "";
$distributions_select = "";
$services_select = "";
$daemons_select = "";
$configfiles = "";
$services = "";
$daemons = "";
$config_dir = makeCorrectDir(FROXLOR_INSTALL_DIR . '/lib/configfiles/');
if ($distribution != "") {
// create configparser object
$configfiles = new ConfigParser($config_dir . '/' . $distribution . ".xml");
// get distro-info
$dist_display = getCompleteDistroName($configfiles);
// get all the services from the distro
$services = $configfiles->getServices();
if ($service != "") {
$daemons = $services[$service]->getDaemons();
if ($daemon == "") {
foreach ($daemons as $di => $dd) {
$title = $dd->title;
if ($dd->default) {
$title = $title." (".strtolower($lng['panel']['default']).")";
}
$daemons_select .= makeoption($title, $di);
}
}
} else {
foreach ($services as $si => $sd) {
$services_select .= makeoption($sd->title, $si);
}
}
} else {
// show list of available distro's
$distros = glob($config_dir . '*.xml');
// tmp array
$distributions_select_data = array();
// read in all the distros
foreach ($distros as $_distribution) {
// get configparser object
$dist = new ConfigParser($_distribution);
// get distro-info
$dist_display = getCompleteDistroName($dist);
// store in tmp array
$distributions_select_data[$dist_display] = str_replace(".xml", "", strtolower(basename($_distribution)));
}
// sort by distribution name
ksort($distributions_select_data);
foreach ($distributions_select_data as $dist_display => $dist_index) {
// create select-box-option
$distributions_select .= makeoption($dist_display, $dist_index);
}
}
if ($distribution != "" && $service != "" && $daemon != "") {
$confarr = $daemons[$daemon]->getConfig();
$configpage = '';
$distro_editor = $configfiles->distributionEditor;
$commands_pre = "";
$commands_file = "";
$commands_post = "";
$lasttype = '';
$commands = '';
foreach ($confarr as $idx => $action) {
if ($lasttype != '' && $lasttype != $action['type']) {
$commands = trim($commands);
$numbrows = count(explode("\n", $commands));
eval("\$configpage.=\"" . getTemplate("configfiles/configfiles_commands") . "\";");
$lasttype = '';
$commands = '';
}
switch ($action['type']) {
case "install":
$commands .= $action['content'] . "\n";
$lasttype = "install";
break;
case "command":
$commands .= $action['content'] . "\n";
$lasttype = "command";
break;
case "file":
if (array_key_exists('content', $action)) {
$commands_file = getFileContentContainer($action['content'], $replace_arr, $action['name'], $distro_editor);
} elseif (array_key_exists('subcommands', $action)) {
foreach ($action['subcommands'] as $fileaction) {
if (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "pre") {
$commands_pre .= $fileaction['content'] . "\n";
} elseif (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "post") {
$commands_post .= $fileaction['content'] . "\n";
} elseif ($fileaction['type'] == 'file') {
$commands_file = getFileContentContainer($fileaction['content'], $replace_arr, $action['name'], $distro_editor);
}
}
}
$realname = $action['name'];
$commands = trim($commands_pre);
if ($commands != "") {
$numbrows = count(explode("\n", $commands));
eval("\$commands_pre=\"" . getTemplate("configfiles/configfiles_commands") . "\";");
}
$commands = trim($commands_post);
if ($commands != "") {
$numbrows = count(explode("\n", $commands));
eval("\$commands_post=\"" . getTemplate("configfiles/configfiles_commands") . "\";");
}
eval("\$configpage.=\"" . getTemplate("configfiles/configfiles_subfileblock") . "\";");
$commands = '';
$commands_pre = '';
$commands_post = '';
break;
}
}
$commands = trim($commands);
if ($commands != '') {
$numbrows = count(explode("\n", $commands));
eval("\$configpage.=\"" . getTemplate("configfiles/configfiles_commands") . "\";");
}
eval("echo \"" . getTemplate("configfiles/configfiles") . "\";");
} else {
eval("echo \"" . getTemplate("configfiles/wizard") . "\";");
}
$customer_tmpdir = '/tmp/';
if (Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_tmpdir') != '')
{
$customer_tmpdir = Settings::Get('system.mod_fcgid_tmpdir');
}
elseif (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.tmpdir') != '')
{
$customer_tmpdir = Settings::Get('phpfpm.tmpdir');
}
$replace_arr = Array(
'<SQL_UNPRIVILEGED_USER>' => $sql['user'],
'<SQL_UNPRIVILEGED_PASSWORD>' => 'MYSQL_PASSWORD',
'<SQL_DB>' => $sql['db'],
'<SQL_HOST>' => $sql['host'],
'<SQL_SOCKET>' => isset($sql['socket']) ? $sql['socket'] : null,
'<SERVERNAME>' => Settings::Get('system.hostname'),
'<SERVERIP>' => Settings::Get('system.ipaddress'),
'<NAMESERVERS>' => Settings::Get('system.nameservers'),
'<VIRTUAL_MAILBOX_BASE>' => Settings::Get('system.vmail_homedir'),
'<VIRTUAL_UID_MAPS>' => Settings::Get('system.vmail_uid'),
'<VIRTUAL_GID_MAPS>' => Settings::Get('system.vmail_gid'),
'<SSLPROTOCOLS>' => (Settings::Get('system.use_ssl') == '1') ? 'imaps pop3s' : '',
'<CUSTOMER_TMP>' => makeCorrectDir($customer_tmpdir),
'<BASE_PATH>' => makeCorrectDir(FROXLOR_INSTALL_DIR),
'<BIND_CONFIG_PATH>' => makeCorrectDir(Settings::Get('system.bindconf_directory')),
'<WEBSERVER_RELOAD_CMD>' => Settings::Get('system.apachereload_command'),
'<CUSTOMER_LOGS>' => makeCorrectDir(Settings::Get('system.logfiles_directory')),
'<FPM_IPCDIR>' => makeCorrectDir(Settings::Get('phpfpm.fastcgi_ipcdir')),
'<WEBSERVER_GROUP>' => Settings::Get('system.httpgroup')
);
// get distro from URL param
$distribution = (isset($_GET['distribution']) && $_GET['distribution'] != 'choose') ? $_GET['distribution'] : "";
$service = (isset($_GET['service']) && $_GET['service'] != 'choose') ? $_GET['service'] : "";
$daemon = (isset($_GET['daemon']) && $_GET['daemon'] != 'choose') ? $_GET['daemon'] : "";
$distributions_select = "";
$services_select = "";
$daemons_select = "";
$configfiles = "";
$services = "";
$daemons = "";
$config_dir = makeCorrectDir(FROXLOR_INSTALL_DIR . '/lib/configfiles/');
if ($distribution != "") {
// create configparser object
$configfiles = new ConfigParser($config_dir . '/' . $distribution . ".xml");
// get distro-info
$dist_display = getCompleteDistroName($configfiles);
// get all the services from the distro
$services = $configfiles->getServices();
if ($service != "") {
$daemons = $services[$service]->getDaemons();
if ($daemon == "") {
foreach ($daemons as $di => $dd) {
$title = $dd->title;
if ($dd->default) {
$title = $title . " (" . strtolower($lng['panel']['default']) . ")";
}
$daemons_select .= makeoption($title, $di);
}
}
} else {
foreach ($services as $si => $sd) {
$services_select .= makeoption($sd->title, $si);
}
}
} else {
// show list of available distro's
$distros = glob($config_dir . '*.xml');
// tmp array
$distributions_select_data = array();
// read in all the distros
foreach ($distros as $_distribution) {
// get configparser object
$dist = new ConfigParser($_distribution);
// get distro-info
$dist_display = getCompleteDistroName($dist);
// store in tmp array
$distributions_select_data[$dist_display] = str_replace(".xml", "", strtolower(basename($_distribution)));
}
// sort by distribution name
ksort($distributions_select_data);
foreach ($distributions_select_data as $dist_display => $dist_index) {
// create select-box-option
$distributions_select .= makeoption($dist_display, $dist_index);
}
}
if ($distribution != "" && $service != "" && $daemon != "") {
$confarr = $daemons[$daemon]->getConfig();
$configpage = '';
$distro_editor = $configfiles->distributionEditor;
$commands_pre = "";
$commands_file = "";
$commands_post = "";
$lasttype = '';
$commands = '';
foreach ($confarr as $idx => $action) {
if ($lasttype != '' && $lasttype != $action['type']) {
$commands = trim($commands);
$numbrows = count(explode("\n", $commands));
eval("\$configpage.=\"" . getTemplate("configfiles/configfiles_commands") . "\";");
$lasttype = '';
$commands = '';
}
switch ($action['type']) {
case "install":
$commands .= strtr($action['content'], $replace_arr) . "\n";
$lasttype = "install";
break;
case "command":
$commands .= strtr($action['content'], $replace_arr) . "\n";
$lasttype = "command";
break;
case "file":
if (array_key_exists('content', $action)) {
$commands_file = getFileContentContainer($action['content'], $replace_arr, $action['name'], $distro_editor);
} elseif (array_key_exists('subcommands', $action)) {
foreach ($action['subcommands'] as $fileaction) {
if (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "pre") {
$commands_pre .= $fileaction['content'] . "\n";
} elseif (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "post") {
$commands_post .= $fileaction['content'] . "\n";
} elseif ($fileaction['type'] == 'file') {
$commands_file = getFileContentContainer($fileaction['content'], $replace_arr, $action['name'], $distro_editor);
}
}
}
$realname = $action['name'];
$commands = trim($commands_pre);
if ($commands != "") {
$numbrows = count(explode("\n", $commands));
eval("\$commands_pre=\"" . getTemplate("configfiles/configfiles_commands") . "\";");
}
$commands = trim($commands_post);
if ($commands != "") {
$numbrows = count(explode("\n", $commands));
eval("\$commands_post=\"" . getTemplate("configfiles/configfiles_commands") . "\";");
}
eval("\$configpage.=\"" . getTemplate("configfiles/configfiles_subfileblock") . "\";");
$commands = '';
$commands_pre = '';
$commands_post = '';
break;
}
}
$commands = trim($commands);
if ($commands != '') {
$numbrows = count(explode("\n", $commands));
eval("\$configpage.=\"" . getTemplate("configfiles/configfiles_commands") . "\";");
}
eval("echo \"" . getTemplate("configfiles/configfiles") . "\";");
} else {
eval("echo \"" . getTemplate("configfiles/wizard") . "\";");
}
} else {
die('not allowed to see this page');
// redirect or similar here
die('not allowed to see this page');
// redirect or similar here
}
// helper functions
function getFileContentContainer($file_content, &$replace_arr, $realname, $distro_editor)
{
$files = "";
$file_content = trim($file_content);
if ($file_content != '') {
$file_content = strtr($file_content, $replace_arr);
$file_content = htmlspecialchars($file_content);
$numbrows = count(explode("\n", $file_content));
eval("\$files=\"" . getTemplate("configfiles/configfiles_file") . "\";");
}
return $files;
$files = "";
$file_content = trim($file_content);
if ($file_content != '') {
$file_content = strtr($file_content, $replace_arr);
$file_content = htmlspecialchars($file_content);
$numbrows = count(explode("\n", $file_content));
eval("\$files=\"" . getTemplate("configfiles/configfiles_file") . "\";");
}
return $files;
}
function getCompleteDistroName($cparser)
{
// get distro-info
$dist_display = $cparser->distributionName;
if ($cparser->distributionCodename != '') {
$dist_display .= " ".$cparser->distributionCodename;
}
if ($cparser->distributionVersion != '') {
$dist_display .= " (" . $cparser->distributionVersion . ")";
}
if ($cparser->deprecated) {
$dist_display .= " [deprecated]";
}
return $dist_display;
// get distro-info
$dist_display = $cparser->distributionName;
if ($cparser->distributionCodename != '') {
$dist_display .= " " . $cparser->distributionCodename;
}
if ($cparser->distributionVersion != '') {
$dist_display .= " (" . $cparser->distributionVersion . ")";
}
if ($cparser->deprecated) {
$dist_display .= " [deprecated]";
}
return $dist_display;
}

View File

@@ -278,12 +278,14 @@ if ($page == 'customers'
Database::pexecute($stmt, array('id' => $id));
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DATABASES . "` WHERE `customerid` = :id");
Database::pexecute($stmt, array('id' => $id));
// first gather all domain-id's to clean up panel_domaintoip accordingly
// first gather all domain-id's to clean up panel_domaintoip and dns-entries accordingly
$did_stmt = Database::prepare("SELECT `id` FROM `".TABLE_PANEL_DOMAINS."` WHERE `customerid` = :id");
Database::pexecute($did_stmt, array('id' => $id));
while ($row = $did_stmt->fetch(PDO::FETCH_ASSOC)) {
$stmt = Database::prepare("DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :did");
Database::pexecute($stmt, array('did' => $row['id']));
$stmt = Database::prepare("DELETE FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did");
Database::pexecute($stmt, array('did' => $row['id']));
}
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id");
Database::pexecute($stmt, array('id' => $id));
@@ -526,6 +528,11 @@ if ($page == 'customers'
$perlenabled = intval($_POST['perlenabled']);
}
$dnsenabled = 0;
if (isset($_POST['dnsenabled'])) {
$dnsenabled = intval($_POST['dnsenabled']);
}
$store_defaultindex = 0;
if (isset($_POST['store_defaultindex'])) {
$store_defaultindex = intval($_POST['store_defaultindex']);
@@ -638,6 +645,10 @@ if ($page == 'customers'
$perlenabled = '1';
}
if ($dnsenabled != '0') {
$dnsenabled = '1';
}
if ($password == '') {
$password = generatePassword();
}
@@ -676,6 +687,7 @@ if ($page == 'customers'
'imap' => $email_imap,
'pop3' => $email_pop3,
'perlenabled' => $perlenabled,
'dnsenabled' => $dnsenabled,
'theme' => $_theme,
'custom_notes' => $custom_notes,
'custom_notes_show' => $custom_notes_show
@@ -715,6 +727,7 @@ if ($page == 'customers'
`imap` = :imap,
`pop3` = :pop3,
`perlenabled` = :perlenabled,
`dnsenabled` = :dnsenabled,
`theme` = :theme,
`custom_notes` = :custom_notes,
`custom_notes_show` = :custom_notes_show"
@@ -1186,6 +1199,11 @@ if ($page == 'customers'
$perlenabled = intval($_POST['perlenabled']);
}
$dnsenabled = 0;
if (isset($_POST['dnsenabled'])) {
$dnsenabled = intval($_POST['dnsenabled']);
}
$diskspace = $diskspace * 1024;
$traffic = $traffic * 1024 * 1024;
@@ -1317,6 +1335,10 @@ if ($page == 'customers'
$perlenabled = '1';
}
if ($dnsenabled != '0') {
$dnsenabled = '1';
}
if ($phpenabled != $result['phpenabled']
|| $perlenabled != $result['perlenabled']
) {
@@ -1427,6 +1449,7 @@ if ($page == 'customers'
'imap' => $email_imap,
'pop3' => $email_pop3,
'perlenabled' => $perlenabled,
'dnsenabled' => $dnsenabled,
'custom_notes' => $custom_notes,
'custom_notes_show' => $custom_notes_show
);
@@ -1460,6 +1483,7 @@ if ($page == 'customers'
`imap` = :imap,
`pop3` = :pop3,
`perlenabled` = :perlenabled,
`dnsenabled` = :dnsenabled,
`custom_notes` = :custom_notes,
`custom_notes_show` = :custom_notes_show
WHERE `customerid` = :customerid"

View File

@@ -245,6 +245,15 @@ if ($page == 'domains' || $page == 'overview') {
'domainid' => $id
));
// remove possible existing DNS entries
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_DOMAIN_DNS . "`
WHERE `domain_id` = :domainid
");
Database::pexecute($del_stmt, array(
'domainid' => $id
));
triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $log);
$log->logAction(ADM_ACTION, LOG_INFO, "deleted domain/subdomains (#" . $result['id'] . ")");
@@ -2074,6 +2083,9 @@ if ($page == 'domains' || $page == 'overview') {
eval("echo \"" . getTemplate("domains/domains_import") . "\";");
}
}
} elseif ($page == 'domaindnseditor' && Settings::Get('system.dnsenabled') == '1') {
require_once __DIR__.'/dns_editor.php';
}
function formatDomainEntry(&$row, &$idna_convert)

View File

@@ -20,6 +20,11 @@
define('AREA', 'customer');
require './lib/init.php';
// redirect if this customer page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options','domains')) {
redirectTo('customer_index.php');
}
if (isset($_POST['id'])) {
$id = intval($_POST['id']);
} elseif (isset($_GET['id'])) {
@@ -36,7 +41,7 @@ if ($page == 'overview') {
'd.domain' => $lng['domains']['domainname']
);
$paging = new paging($userinfo, TABLE_PANEL_DOMAINS, $fields);
$domains_stmt = Database::prepare("SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isemaildomain`, `d`.`caneditdomain`, `d`.`iswildcarddomain`, `d`.`parentdomainid`, `d`.`letsencrypt`, `d`.`termination_date`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias` FROM `" . TABLE_PANEL_DOMAINS . "` `d`
$domains_stmt = Database::prepare("SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isbinddomain`, `d`.`isemaildomain`, `d`.`caneditdomain`, `d`.`iswildcarddomain`, `d`.`parentdomainid`, `d`.`letsencrypt`, `d`.`termination_date`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias` FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id`
WHERE `d`.`customerid`= :customerid
@@ -232,6 +237,13 @@ if ($page == 'overview') {
);
Database::pexecute($del_stmt, array('domainid' => $id));
// remove possible existing DNS entries
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_DOMAIN_DNS . "`
WHERE `domain_id` = :domainid
");
Database::pexecute($del_stmt, array('domainid' => $id));
inserttask('1');
// Using nameserver, insert a task which rebuilds the server config
@@ -508,7 +520,7 @@ if ($page == 'overview') {
}
} elseif ($action == 'edit' && $id != 0) {
$stmt = Database::prepare("SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isemaildomain`, `d`.`wwwserveralias`, `d`.`iswildcarddomain`,
$stmt = Database::prepare("SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isemaildomain`, `d`.`isbinddomain`, `d`.`wwwserveralias`, `d`.`iswildcarddomain`,
`d`.`parentdomainid`, `d`.`ssl_redirect`, `d`.`aliasdomain`, `d`.`openbasedir`, `d`.`openbasedir_path`, `d`.`letsencrypt`, `pd`.`subcanemaildomain`
FROM `" . TABLE_PANEL_DOMAINS . "` `d`, `" . TABLE_PANEL_DOMAINS . "` `pd`
WHERE `d`.`customerid` = :customerid
@@ -913,4 +925,7 @@ if ($page == 'overview') {
eval("echo \"" . getTemplate("domains/domain_ssleditor") . "\";");
}
} elseif ($page == 'domaindnseditor' && $userinfo['dnsenabled'] == '1' && Settings::Get('system.dnsenabled') == '1') {
require_once __DIR__.'/dns_editor.php';
}

View File

@@ -20,6 +20,11 @@
define('AREA', 'customer');
require './lib/init.php';
// redirect if this customer page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options','email')) {
redirectTo('customer_index.php');
}
if (isset($_POST['id'])) {
$id = intval($_POST['id']);
} elseif (isset($_GET['id'])) {

View File

@@ -19,6 +19,11 @@
define('AREA', 'customer');
require './lib/init.php';
// redirect if this customer page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options','extras')) {
redirectTo('customer_index.php');
}
if (isset($_POST['id'])) {
$id = intval($_POST['id']);
} elseif (isset($_GET['id'])) {
@@ -29,6 +34,12 @@ if ($page == 'overview') {
$log->logAction(USR_ACTION, LOG_NOTICE, "viewed customer_extras");
eval("echo \"" . getTemplate("extras/extras") . "\";");
} elseif ($page == 'htpasswds') {
// redirect if this customer sub-page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options','extras.directoryprotection')) {
redirectTo('customer_index.php');
}
if ($action == '') {
$log->logAction(USR_ACTION, LOG_NOTICE, "viewed customer_extras::htpasswds");
$fields = array(
@@ -262,6 +273,12 @@ if ($page == 'overview') {
}
}
} elseif ($page == 'htaccess') {
// redirect if this customer sub-page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options','extras.pathoptions')) {
redirectTo('customer_index.php');
}
if ($action == '') {
$log->logAction(USR_ACTION, LOG_NOTICE, "viewed customer_extras::htaccess");
$fields = array(
@@ -520,19 +537,36 @@ if ($page == 'overview') {
}
} elseif ($page == 'backup') {
// redirect if this customer sub-page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options','extras.backup')) {
redirectTo('customer_index.php');
}
if (Settings::Get('system.backupenabled') == 1)
{
if ($action == 'abort' && isset($_POST['send']) && $_POST['send'] == 'send') {
$log->logAction(USR_ACTION, LOG_NOTICE, "customer_extras::backup - aborted scheduled backupjob");
$entry = isset($_POST['backup_job_entry']) ? (int)$_POST['backup_job_entry'] : 0;
if ($entry > 0) {
$del_stmt = Database::prepare("DELETE FROM `".TABLE_PANEL_TASKS."` WHERE `id` = :tid");
Database::pexecute($del_stmt, array('tid' => $entry));
standard_success('backupaborted');
}
redirectTo($filename, array('page' => $page, 'action' => '', 's' => $s));
}
if ($action == '') {
$log->logAction(USR_ACTION, LOG_NOTICE, "viewed customer_extras::backup");
// check whether there is a backup-job for this customer
$sel_stmt = Database::prepare("SELECT * FROM `".TABLE_PANEL_TASKS."` WHERE `type` = '20'");
Database::pexecute($sel_stmt);
$existing_backupJob = null;
while ($entry = $sel_stmt->fetch())
{
$data = unserialize($entry['data']);
if ($data['customerid'] == $userinfo['customerid']) {
standard_error('customerhasongoingbackupjob');
$existing_backupJob = $entry;
break;
}
}
@@ -577,11 +611,24 @@ if ($page == 'overview') {
standard_success('backupscheduled');
} else {
if (!empty($existing_backupJob)) {
$action = "abort";
$row = unserialize($entry['data']);
$row['path'] = makeCorrectDir(str_replace($userinfo['documentroot'], "/", $row['destdir']));
$row['backup_web'] = ($row['backup_web'] == '1') ? $lng['panel']['yes'] : $lng['panel']['no'];
$row['backup_mail'] = ($row['backup_mail'] == '1') ? $lng['panel']['yes'] : $lng['panel']['no'];
$row['backup_dbs'] = ($row['backup_dbs'] == '1') ? $lng['panel']['yes'] : $lng['panel']['no'];
}
$pathSelect = makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']);
$backup_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.backup.php';
$backup_form = htmlform::genHTMLForm($backup_data);
$title = $backup_data['backup']['title'];
$image = $backup_data['backup']['image'];
if (!empty($existing_backupJob)) {
// overwrite backup_form after we took everything from it we needed
eval("\$backup_form = \"" . getTemplate("extras/backup_listexisting") . "\";");
}
eval("echo \"" . getTemplate("extras/backup") . "\";");
}
}

View File

@@ -20,6 +20,11 @@
define('AREA', 'customer');
require './lib/init.php';
// redirect if this customer page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options','ftp')) {
redirectTo('customer_index.php');
}
$id = 0;
if (isset($_POST['id'])) {
$id = intval($_POST['id']);

View File

@@ -20,6 +20,11 @@
define('AREA', 'customer');
require './lib/init.php';
// redirect if this customer page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options','extras.logger')) {
redirectTo('customer_index.php');
}
if ($page == 'log'
) {
if ($action == '') {

View File

@@ -20,6 +20,11 @@
define('AREA', 'customer');
require './lib/init.php';
// redirect if this customer page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options','mysql')) {
redirectTo('customer_index.php');
}
// get sql-root access data
Database::needRoot(true);
Database::needSqlData();

View File

@@ -20,6 +20,11 @@
define('AREA', 'customer');
require './lib/init.php';
// redirect if this customer page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options','domains')) {
redirectTo('customer_index.php');
}
if (isset($_POST['id'])) {
$id = intval($_POST['id']);
@@ -327,7 +332,7 @@ if ($page == 'overview') {
$subject = $subticket->Get('subject');
$message = $subticket->Get('message');
$row2 = htmlentities_array($row2);
eval("\$ticket_replies.=\"" . getTemplate("tickets/tickets_tickets_list") . "\";");
}

View File

@@ -20,6 +20,12 @@
define('AREA', 'customer');
$intrafficpage = 1;
require './lib/init.php';
// redirect if this customer page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options','traffic')) {
redirectTo('customer_index.php');
}
$traffic = '';
$month = null;
$year = null;

306
dns_editor.php Normal file
View File

@@ -0,0 +1,306 @@
<?php
if (! defined('AREA'))
die('You cannot access this file directly!');
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Panel
*
*/
// This file is being included in admin_domains and customer_domains
// and therefore does not need to require lib/init.php
$domain_id = isset($_GET['domain_id']) ? (int) $_GET['domain_id'] : null;
$record = isset($_POST['record']['record']) ? trim($_POST['record']['record']) : null;
$type = isset($_POST['record']['type']) ? $_POST['record']['type'] : 'A';
$prio = isset($_POST['record']['prio']) ? (int) $_POST['record']['prio'] : null;
$content = isset($_POST['record']['content']) ? trim($_POST['record']['content']) : null;
$ttl = isset($_POST['record']['ttl']) ? (int) $_POST['record']['ttl'] : 18000;
// get domain-name
$domain = getAllowedDomainEntry($domain_id, AREA, $userinfo, $idna_convert);
// select all entries
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE domain_id = :did");
Database::pexecute($sel_stmt, array(
'did' => $domain_id
));
$dom_entries = $sel_stmt->fetchAll(PDO::FETCH_ASSOC);
$errors = array();
$success_message = "";
// action for adding a new entry
if ($action == 'add_record' && ! empty($_POST)) {
// validation
if (empty($record)) {
$record = "@";
}
$record = strtolower($record);
if ($record != '@' && $record != '*') {
// validate record
if (strpos($record, '--') !== false) {
$errors[] = $lng['error']['domain_nopunycode'];
} else {
$record = $idna_convert->encode($record);
if ($type != 'SRV' && $type != 'TXT') {
$check_dom = $record . '.example.com';
if (! validateDomain($check_dom)) {
$errors[] = sprintf($lng['error']['subdomainiswrong'], $idna_convert->decode($record));
}
}
if (strlen($record) > 63) {
$errors[] = $lng['error']['dns_record_toolong'];
}
}
}
// TODO regex validate content for invalid characters
if ($ttl <= 0) {
$ttl = 18000;
}
if (empty($content)) {
$errors[] = $lng['error']['dns_content_empty'];
}
// types
if ($type == 'A' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
$errors[] = $lng['error']['dns_arec_noipv4'];
} elseif ($type == 'AAAA' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
$errors[] = $lng['error']['dns_aaaarec_noipv6'];
} elseif ($type == 'MX') {
if ($prio === null || $prio < 0) {
$errors[] = $lng['error']['dns_mx_prioempty'];
}
// check for trailing dot
if (substr($content, - 1) == '.') {
// remove it for checks
$content = substr($content, 0, - 1);
}
if (! validateDomain($content)) {
$errors[] = $lng['error']['dns_mx_needdom'];
} else {
// check whether there is a CNAME-record for the same resource
foreach ($dom_entries as $existing_entries) {
$fqdn = $existing_entries['record'] . '.' . $domain;
if ($existing_entries['type'] == 'CNAME' && $fqdn == $content) {
$errors[] = $lng['error']['dns_mx_noalias'];
break;
}
}
}
// append trailing dot (again)
$content .= '.';
} elseif ($type == 'CNAME') {
// check for trailing dot
if (substr($content, - 1) == '.') {
// remove it for checks
$content = substr($content, 0, - 1);
}
if (! validateDomain($content)) {
$errors[] = $lng['error']['dns_cname_invaliddom'];
} else {
// check whether there are RR-records for the same resource
foreach ($dom_entries as $existing_entries) {
if (($existing_entries['type'] == 'A' || $existing_entries['type'] == 'AAAA' || $existing_entries['type'] == 'MX' || $existing_entries['type'] == 'NS') && $existing_entries['record'] == $record) {
$errors[] = $lng['error']['dns_cname_nomorerr'];
break;
}
}
}
// append trailing dot (again)
$content .= '.';
} elseif ($type == 'NS') {
// check for trailing dot
if (substr($content, - 1) == '.') {
// remove it for checks
$content = substr($content, 0, - 1);
}
if (! validateDomain($content)) {
$errors[] = $lng['error']['dns_ns_invaliddom'];
}
// append trailing dot (again)
$content .= '.';
} elseif ($type == 'TXT' && ! empty($content)) {
// check that TXT content is enclosed in " "
$content = encloseTXTContent($content);
} elseif ($type == 'SRV') {
if ($prio === null || $prio < 0) {
$errors[] = $lng['error']['dns_srv_prioempty'];
}
// check only last part of content, as it can look like:
// _service._proto.name. TTL class SRV priority weight port target.
$_split_content = explode(" ", $content);
// SRV content must be [weight] [port] [target]
if (count($_split_content) != 3) {
$errors[] = $lng['error']['dns_srv_invalidcontent'];
}
$target = trim($_split_content[count($_split_content) - 1]);
if ($target != '.') {
// check for trailing dot
if (substr($target, - 1) == '.') {
// remove it for checks
$target = substr($target, 0, - 1);
}
}
if ($target != '.' && ! validateDomain($target)) {
$errors[] = $lng['error']['dns_srv_needdom'];
} else {
// check whether there is a CNAME-record for the same resource
foreach ($dom_entries as $existing_entries) {
$fqdn = $existing_entries['record'] . '.' . $domain;
if ($existing_entries['type'] == 'CNAME' && $fqdn == $target) {
$errors[] = $lng['error']['dns_srv_noalias'];
break;
}
}
}
// append trailing dot (again)
if ($target != '.') {
$content .= '.';
}
}
$new_entry = array(
'record' => $record,
'type' => $type,
'prio' => $prio,
'content' => $content,
'ttl' => $ttl,
'domain_id' => $domain_id
);
ksort($new_entry);
// check for duplicate
foreach ($dom_entries as $existing_entry) {
// compare serialized string of array
$check_entry = $existing_entry;
// new entry has no ID yet
unset($check_entry['id']);
// sort by key
ksort($check_entry);
// format integer fields to real integer (as they are read as string from the DB)
$check_entry['prio'] = (int) $check_entry['prio'];
$check_entry['ttl'] = (int) $check_entry['ttl'];
$check_entry['domain_id'] = (int) $check_entry['domain_id'];
// serialize both
$check_entry = serialize($check_entry);
$new = serialize($new_entry);
// compare
if ($check_entry === $new) {
$errors[] = $lng['error']['dns_duplicate_entry'];
unset($check_entry);
break;
}
}
if (empty($errors)) {
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_DOMAIN_DNS . "` SET
`record` = :record,
`type` = :type,
`prio` = :prio,
`content` = :content,
`ttl` = :ttl,
`domain_id` = :domain_id
");
Database::pexecute($ins_stmt, $new_entry);
$new_entry_id = Database::lastInsertId();
// add temporary to the entries-array (no reread of DB necessary)
$new_entry['id'] = $new_entry_id;
$dom_entries[] = $new_entry;
// success message (inline)
$success_message = $lng['success']['dns_record_added'];
$record = "";
$type = 'A';
$prio = "";
$content = "";
$ttl = "";
// re-generate bind configs
inserttask('4');
} else {
// show $errors
$errors = implode("<br>", $errors);
}
} elseif ($action == 'delete') {
// remove entry
$entry_id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
if ($entry_id > 0) {
$del_stmt = Database::prepare("DELETE FROM `" . TABLE_DOMAIN_DNS . "` WHERE `id` = :id");
Database::pexecute($del_stmt, array(
'id' => $entry_id
));
// remove deleted entry from internal data array (no reread of DB necessary)
$_t = $dom_entries;
foreach ($_t as $idx => $entry) {
if ($entry['id'] == $entry_id) {
unset($dom_entries[$idx]);
break;
}
}
unset($_t);
// success message (inline)
$success_message = $lng['success']['dns_record_deleted'];
// re-generate bind configs
inserttask('4');
}
}
// show editor
$record_list = "";
$existing_entries = "";
$type_select = "";
$entriescount = 0;
if (! empty($dom_entries)) {
$entriescount = count($dom_entries);
foreach ($dom_entries as $entry) {
$entry['content'] = wordwrap($entry['content'], 100, '<br>', true);
eval("\$existing_entries.=\"" . getTemplate("dns_editor/entry_bit", true) . "\";");
}
}
// available types
$type_select_values = array(
'A',
'AAAA',
'NS',
'MX',
'SRV',
'TXT',
'CNAME'
);
asort($type_select_values);
foreach ($type_select_values as $_type) {
$type_select .= makeoption($_type, $_type, $type);
}
eval("\$record_list=\"" . getTemplate("dns_editor/list", true) . "\";");
$zone = createDomainZone($domain_id);
$zonefile = (string) $zone;
eval("echo \"" . getTemplate("dns_editor/index", true) . "\";");

View File

@@ -302,7 +302,7 @@ if ($action == 'login') {
}
$lastqrystr = "";
if (isset($_REQUEST['qrystr']) && $_REQUEST['qrystr'] != "") {
$lastqrystr = strip_tags($_REQUEST['qrystr']);
$lastqrystr = htmlspecialchars($_REQUEST['qrystr'], ENT_QUOTES);
}
eval("echo \"" . getTemplate('login') . "\";");

View File

@@ -23,7 +23,7 @@ CREATE TABLE `ftp_users` (
`shell` varchar(255) NOT NULL default '/bin/false',
`login_enabled` enum('N','Y') NOT NULL default 'N',
`login_count` int(15) NOT NULL default '0',
`last_login` datetime NOT NULL default '0000-00-00 00:00:00',
`last_login` datetime default NULL,
`up_count` int(15) NOT NULL default '0',
`up_bytes` bigint(30) NOT NULL default '0',
`down_count` int(15) NOT NULL default '0',
@@ -191,6 +191,7 @@ CREATE TABLE `panel_customers` (
`pop3` tinyint(1) NOT NULL default '1',
`imap` tinyint(1) NOT NULL default '1',
`perlenabled` tinyint(1) NOT NULL default '0',
`dnsenabled` tinyint(1) NOT NULL default '0',
`theme` varchar(255) NOT NULL default 'Sparkle',
`custom_notes` text,
`custom_notes_show` tinyint(1) NOT NULL default '0',
@@ -376,7 +377,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('admin', 'show_version_login', '0'),
('admin', 'show_version_footer', '0'),
('spf', 'use_spf', '0'),
('spf', 'spf_entry', '@ IN TXT "v=spf1 a mx -all"'),
('spf', 'spf_entry', '"v=spf1 a mx -all"'),
('dkim', 'dkim_algorithm', 'all'),
('dkim', 'dkim_add_adsp', '1'),
('dkim', 'dkim_keylength', '1024'),
@@ -526,6 +527,9 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('system', 'letsencryptreuseold', 0),
('system', 'leenabled', '0'),
('system', 'backupenabled', '0'),
('system', 'dnsenabled', '0'),
('system', 'dns_server', 'bind'),
('system', 'apacheglobaldiropt', ''),
('panel', 'decimal_places', '4'),
('panel', 'adminmail', 'admin@SERVERNAME'),
('panel', 'phpmyadmin_url', ''),
@@ -556,15 +560,15 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('panel', 'password_numeric', '0'),
('panel', 'password_special_char_required', '0'),
('panel', 'password_special_char', '!?<>§$%+#=@'),
('panel', 'version', '0.9.36'),
('panel', 'db_version', '201604270');
('panel', 'version', '0.9.37'),
('panel', 'db_version', '201607210');
DROP TABLE IF EXISTS `panel_tasks`;
CREATE TABLE `panel_tasks` (
`id` int(11) unsigned NOT NULL auto_increment,
`type` int(11) NOT NULL default '0',
`data` text NOT NULL,
`data` text,
PRIMARY KEY (`id`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -855,3 +859,16 @@ CREATE TABLE IF NOT EXISTS `panel_domaintoip` (
PRIMARY KEY (`id_domain`,`id_ipandports`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
DROP TABLE IF EXISTS `domain_dns_entries`;
CREATE TABLE `domain_dns_entries` (
`id` int(20) NOT NULL auto_increment,
`domain_id` int(15) NOT NULL,
`record` varchar(255) NOT NULL,
`type` varchar(10) NOT NULL DEFAULT 'A',
`content` text NOT NULL,
`ttl` int(11) NOT NULL DEFAULT '18000',
`prio` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;

View File

@@ -296,7 +296,7 @@ class FroxlorInstall
$content .= $this->_status_message('begin', $this->_lng['install']['creating_configfile']);
$userdata = "<?php\n";
$userdata .= "//automatically generated userdata.inc.php for Froxlor\n";
$userdata .= "// automatically generated userdata.inc.php for Froxlor\n";
$userdata .= "\$sql['host']='" . addcslashes($this->_data['mysql_host'], "'\\") . "';\n";
$userdata .= "\$sql['user']='" . addcslashes($this->_data['mysql_unpriv_user'], "'\\") . "';\n";
$userdata .= "\$sql['password']='" . addcslashes($this->_data['mysql_unpriv_pass'], "'\\") . "';\n";
@@ -305,6 +305,8 @@ class FroxlorInstall
$userdata .= "\$sql_root[0]['host']='" . addcslashes($this->_data['mysql_host'], "'\\") . "';\n";
$userdata .= "\$sql_root[0]['user']='" . addcslashes($this->_data['mysql_root_user'], "'\\") . "';\n";
$userdata .= "\$sql_root[0]['password']='" . addcslashes($this->_data['mysql_root_pass'], "'\\") . "';\n";
$userdata .= "// enable debugging to browser in case of SQL errors\n";
$userdata .= "\$sql['debug'] = false;\n";
$userdata .= "?>";
// test if we can store the userdata.inc.php in ../lib
@@ -906,7 +908,11 @@ class FroxlorInstall
$content .= $this->_status_message('red', $this->_lng['requirements']['notfound'] . ' (' . PHP_VERSION . ')');
$_die = true;
} else {
$content .= $this->_status_message('green', PHP_VERSION);
if (version_compare("5.6.0", PHP_VERSION, ">=")) {
$content .= $this->_status_message('orange', $this->_lng['requirements']['newerphpprefered'] . ' (' .PHP_VERSION . ')');
} else {
$content .= $this->_status_message('green', PHP_VERSION);
}
}
// Check if magic_quotes_runtime is active | get_magic_quotes_runtime() is always FALSE since 5.4

View File

@@ -24,6 +24,7 @@ $lng['requirements']['notfound'] = 'not found';
$lng['requirements']['notinstalled'] = 'not installed';
$lng['requirements']['activated'] = 'enabled';
$lng['requirements']['phpversion'] = 'PHP version >= 5.3';
$lng['requirements']['newerphpprefered'] = 'Good, but php-5.6 is prefered.';
$lng['requirements']['phpmagic_quotes_runtime'] = 'magic_quotes_runtime...';
$lng['requirements']['phpmagic_quotes_runtime_description'] = 'PHP setting "magic_quotes_runtime" must be set to "Off". We have disabled it temporary for now please fix the coresponding php.ini.';
$lng['requirements']['phppdo'] = 'PHP PDO extension and PDO-MySQL driver...';

View File

@@ -24,6 +24,7 @@ $lng['requirements']['notfound'] = 'nicht gefunden';
$lng['requirements']['notinstalled'] = 'nicht installiert';
$lng['requirements']['activated'] = 'ist aktiviert.';
$lng['requirements']['phpversion'] = 'PHP Version >= 5.3';
$lng['requirements']['newerphpprefered'] = 'Passt, aber php-5.6 wird bevorzugt.';
$lng['requirements']['phpmagic_quotes_runtime'] = 'magic_quotes_runtime';
$lng['requirements']['phpmagic_quotes_runtime_description'] = 'Die PHP Einstellung "magic_quotes_runtime" muss deaktiviert sein ("Off"). Die Einstellung wurde temporär deaktiviert, bitte ändern Sie diese in der entsprechenden php.ini.';
$lng['requirements']['phppdo'] = 'PHP PDO Erweiterung und PDO-MySQL Treiber...';

View File

@@ -19,10 +19,7 @@
$baseLanguage = 'english.lng.php';
// Check if we're in the CLI
if(@php_sapi_name() != 'cli'
&& @php_sapi_name() != 'cgi'
&& @php_sapi_name() != 'cgi-fcgi'
) {
if(@php_sapi_name() !== 'cli') {
die('This script will only work in the shell.');
}

View File

@@ -0,0 +1,417 @@
#!/usr/bin/php
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
*/
// Check if we're in the CLI
if(@php_sapi_name() !== 'cli') {
die('This script will only work in the shell.');
}
// give control to command line handler
try {
CmdLineHandler::processParameters($argc, $argv);
} catch (Exception $e) {
CmdLineHandler::printerr($e->getMessage());
}
class CmdLineHandler
{
/**
* internal variable for passed arguments
*
* @var array
*/
private static $args = null;
/**
* Action object read from commandline/config
*
* @var Action
*/
private $_action = null;
/**
* list of valid parameters/switches
*/
public static $switches = array(
/* 'd', // debug / output information for everything */
'h'
);
// same as --help
public static $params = array(
'switch',
'list',
'froxlor-dir',
'help'
);
/**
* Returns a CmdLineHandler object with given
* arguments from command line
*
* @param int $argc
* @param array $argv
*
* @return CmdLineHandler
*/
public static function processParameters($argc, $argv)
{
return new CmdLineHandler($argc, $argv);
}
/**
* returns the Action object generated in
* the class constructor
*
* @return Action
*/
public function getAction()
{
return $this->_action;
}
/**
* class constructor, validates the command line parameters
* and sets the Action-object if valid
*
* @param int $argc
* @param string[] $argv
*
* @return null
* @throws Exception
*/
private function __construct($argc, $argv)
{
self::$args = $this->_parseArgs($argv);
$this->_action = $this->_createAction();
}
/**
* Parses the arguments given via the command line;
* three types are supported:
* 1.
* --parm1 or --parm2=value
* 2. -xyz (multiple switches in one) or -a=value
* 3. parm1 parm2
*
* The 1. will be mapped as
* ["parm1"] => true, ["parm2"] => "value"
* The 2. as
* ["x"] => true, ["y"] => true, ["z"] => true, ["a"] => "value"
* And the 3. as
* [0] => "parm1", [1] => "parm2"
*
* @param array $argv
*
* @return array
*/
private function _parseArgs($argv)
{
array_shift($argv);
$o = array();
foreach ($argv as $a) {
if (substr($a, 0, 2) == '--') {
$eq = strpos($a, '=');
if ($eq !== false) {
$o[substr($a, 2, $eq - 2)] = substr($a, $eq + 1);
} else {
$k = substr($a, 2);
if (! isset($o[$k])) {
$o[$k] = true;
}
}
} else
if (substr($a, 0, 1) == '-') {
if (substr($a, 2, 1) == '=') {
$o[substr($a, 1, 1)] = substr($a, 3);
} else {
foreach (str_split(substr($a, 1)) as $k) {
if (! isset($o[$k])) {
$o[$k] = true;
}
}
}
} else {
$o[] = $a;
}
}
return $o;
}
/**
* Creates an Action-Object for the Action-Handler
*
* @return Action
* @throws Exception
*/
private function _createAction()
{
// Test for help-switch
if (empty(self::$args) || array_key_exists("help", self::$args) || array_key_exists("h", self::$args)) {
self::printHelp();
// end of execution
}
// check if no unknown parameters are present
foreach (self::$args as $arg => $value) {
if (is_numeric($arg)) {
throw new Exception("Unknown parameter '" . $value . "' in argument list");
} elseif (! in_array($arg, self::$params) && ! in_array($arg, self::$switches)) {
throw new Exception("Unknown parameter '" . $arg . "' in argument list");
}
}
// set debugger switch
if (isset(self::$args["d"]) && self::$args["d"] == true) {
// Debugger::getInstance()->setEnabled(true);
// Debugger::getInstance()->debug("debug output enabled");
}
return new Action(self::$args);
}
public static function printHelp()
{
self::println("");
self::println("Help / command line parameters:");
self::println("");
// commands
self::println("--switch\t\tlets you switch ip-address A with ip-address B");
self::println("\t\t\tExample: --switch=A,B");
self::println("\t\t\tExample: --switch=\"A1,B1 A2,B2 A3,B3 ...\"");
self::println("");
self::println("--list\t\t\tshow all currently used ip-addresses in froxlor");
self::println("");
self::println("--froxlor-dir\t\tpath to froxlor installation");
self::println("\t\t\tExample: --froxlor-dir=/var/www/froxlor/");
self::println("");
self::println("--help\t\t\tshow help screen (this)");
self::println("");
// switches
// self::println("-d\t\t\tenable debug output");
self::println("-h\t\t\tsame as --help");
self::println("");
die(); // end of execution
}
public static function println($msg = "")
{
print $msg . PHP_EOL;
}
private static function _printcolor($msg = "", $color = "0")
{
print "\033[" . $color . "m" . $msg . "\033[0m" . PHP_EOL;
}
public static function printerr($msg = "")
{
self::_printcolor($msg, "31");
}
public static function printsucc($msg = "")
{
self::_printcolor($msg, "32");
}
public static function printwarn($msg = "")
{
self::_printcolor($msg, "33");
}
}
class Action
{
private $_args = null;
private $_name = null;
private $_db = null;
public function __construct($args)
{
$this->_args = $args;
$this->_validate();
}
public function getActionName()
{
return $this->_name;
}
/**
* validates the parsed command line parameters
*
* @throws Exception
*/
private function _validate()
{
$need_config = false;
if (array_key_exists("list", $this->_args) || array_key_exists("switch", $this->_args)) {
$need_config = true;
}
$this->_checkConfigParam($need_config);
$this->_parseConfig();
if (array_key_exists("list", $this->_args)) {
$this->_listIPs();
}
if (array_key_exists("switch", $this->_args)) {
$this->_switchIPs();
}
}
private function _listIPs()
{
$sel_stmt = Database::prepare("SELECT * FROM panel_ipsandports ORDER BY ip ASC, port ASC");
Database::pexecute($sel_stmt);
$ips = $sel_stmt->fetchAll(PDO::FETCH_ASSOC);
$mask = "|%-10.10s |%-50.50s | %10.10s |\n";
printf($mask, str_repeat("-", 10), str_repeat("-", 50), str_repeat("-", 10));
printf($mask, 'id', 'IP address', 'port');
printf($mask, str_repeat("-", 10), str_repeat("-", 50), str_repeat("-", 10));
foreach ($ips as $ipdata) {
printf($mask, $ipdata['id'], $ipdata['ip'], $ipdata['port']);
}
printf($mask, str_repeat("-", 10), str_repeat("-", 50), str_repeat("-", 10));
echo PHP_EOL . PHP_EOL;
}
private function _switchIPs()
{
$ip_list = $this->_args['switch'];
if (empty($ip_list) || is_bool($ip_list)) {
throw new Exception("No paramters given for --switch action.");
}
$ips_to_switch = array();
$ip_list = explode(" ", $ip_list);
foreach ($ip_list as $ips_combo) {
$ip_pair = explode(",", $ips_combo);
if (count($ip_pair) != 2) {
throw new Exception("Invalid parameter given for --switch");
} else {
if (filter_var($ip_pair[0], FILTER_VALIDATE_IP) == false) {
throw new Exception("Invalid source ip address: " . $ip_pair[0]);
}
if (filter_var($ip_pair[1], FILTER_VALIDATE_IP) == false) {
throw new Exception("Invalid target ip address: " . $ip_pair[1]);
}
if ($ip_pair[0] == $ip_pair[1]) {
throw new Exception("Source and target ip address are equal");
}
}
$ips_to_switch[] = $ip_pair;
}
if (count($ips_to_switch) > 0) {
$upd_stmt = Database::prepare("UPDATE panel_ipsandports SET `ip` = :newip WHERE `ip` = :oldip");
// system.ipaddress
$check_sysip_stmt = Database::prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'system' and `varname` = 'ipaddress'");
$check_sysip = Database::pexecute_first($check_sysip_stmt);
// system.mysql_access_host
$check_mysqlip_stmt = Database::prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'system' and `varname` = 'mysql_access_host'");
$check_mysqlip = Database::pexecute_first($check_mysqlip_stmt);
// system.axfrservers
$check_axfrip_stmt = Database::prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'system' and `varname` = 'axfrservers'");
$check_axfrip = Database::pexecute_first($check_axfrip_stmt);
foreach ($ips_to_switch as $ip_pair) {
echo "Switching IP \033[1m" . $ip_pair[0] . "\033[0m to IP \033[1m" . $ip_pair[1] . "\033[0m" . PHP_EOL;
Database::pexecute($upd_stmt, array(
'newip' => $ip_pair[1],
'oldip' => $ip_pair[0]
));
$rows_updated = $upd_stmt->rowCount();
if ($rows_updated == 0) {
CmdLineHandler::printwarn("Note: " . $ip_pair[0] . " not updated to " . $ip_pair[1] . " (possibly no entry found in froxlor database. Use --list to see what IP addresses are added in froxlor");
}
// check whether the system.ipaddress needs updating
if ($check_sysip['value'] == $ip_pair[0]) {
$upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newip WHERE `settinggroup` = 'system' and `varname` = 'ipaddress'");
Database::pexecute($upd2_stmt, array(
'newip' => $ip_pair[1]
));
CmdLineHandler::printsucc("Updated system-ipaddress from '" . $ip_pair[0] . "' to '" . $ip_pair[1] . "'");
}
// check whether the system.mysql_access_host needs updating
if (strstr($check_mysqlip['value'], $ip_pair[0]) !== false) {
$new_mysqlip = str_replace($ip_pair[0], $ip_pair[1], $check_mysqlip['value']);
$upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newmysql WHERE `settinggroup` = 'system' and `varname` = 'mysql_access_host'");
Database::pexecute($upd2_stmt, array(
'newmysql' => $new_mysqlip
));
CmdLineHandler::printsucc("Updated mysql_access_host from '" . $check_mysqlip['value'] . "' to '" . $new_mysqlip . "'");
}
// check whether the system.axfrservers needs updating
if (strstr($check_axfrip['value'], $ip_pair[0]) !== false) {
$new_axfrip = str_replace($ip_pair[0], $ip_pair[1], $check_axfrip['value']);
$upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newaxfr WHERE `settinggroup` = 'system' and `varname` = 'axfrservers'");
Database::pexecute($upd2_stmt, array(
'newaxfr' => $new_axfrip
));
CmdLineHandler::printsucc("Updated axfrservers from '" . $check_axfrip['value'] . "' to '" . $new_axfrip . "'");
}
}
}
echo PHP_EOL;
CmdLineHandler::printwarn("*** ATTENTION *** Remember to replace IP addresses in configuration files if used anywhere.");
CmdLineHandler::printsucc("IP addresses updated");
}
private function _parseConfig()
{
define('FROXLOR_INSTALL_DIR', $this->_args['froxlor-dir']);
if (!file_exists(FROXLOR_INSTALL_DIR . '/lib/classes/database/class.Database.php')) {
throw new Exception("Could not find froxlor's Database class. Is froxlor really installed to '".FROXLOR_INSTALL_DIR."'?");
}
if (!file_exists(FROXLOR_INSTALL_DIR . '/lib/userdata.inc.php')) {
throw new Exception("Could not find froxlor's userdata.inc.php file. You should use this script only with a fully installed and setup froxlor system.");
}
require FROXLOR_INSTALL_DIR . '/lib/classes/database/class.Database.php';
}
private function _checkConfigParam($needed = false)
{
if ($needed) {
if (! isset($this->_args["froxlor-dir"])) {
throw new Exception("No configuration given (missing --froxlor-dir parameter?)");
} elseif (! is_dir($this->_args["froxlor-dir"])) {
throw new Exception("Given --froxlor-dir parameter is not a directory");
} elseif (! file_exists($this->_args["froxlor-dir"])) {
throw new Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')");
} elseif (! is_readable($this->_args["froxlor-dir"])) {
throw new Exception("Given froxlor direcotry cannot be read ('" . $this->_args["froxlor-dir"] . "')");
}
}
}
}

View File

@@ -3320,3 +3320,98 @@ if (isFroxlorVersion('0.9.35.1')) {
updateToVersion('0.9.36');
}
if (isDatabaseVersion('201604270')) {
showUpdateStep("Adding new dns related tables and settings");
$enable_dns = isset($_POST['enable_dns']) ? (int) $_POST['enable_dns'] : "0";
Settings::AddNew("system.dnsenabled", $enable_dns);
Database::query("DROP TABLE IF EXISTS `domain_dns_entries`;");
$sql = "CREATE TABLE `domain_dns_entries` (
`id` int(20) NOT NULL auto_increment,
`domain_id` int(15) NOT NULL,
`record` varchar(255) NOT NULL,
`type` varchar(10) NOT NULL DEFAULT 'A',
`content` text NOT NULL,
`ttl` int(11) NOT NULL DEFAULT '18000',
`prio` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;";
Database::query($sql);
lastStepStatus(0);
updateToDbVersion('201605090');
}
if (isDatabaseVersion('201605090')) {
showUpdateStep("Adjusting SPF record setting");
$current_spf = Settings::Get('spf.spf_entry');
// @ IN TXT "v=spf1 a mx -all"
$new_spf = substr($current_spf, strpos($current_spf, '"'));
Settings::Set('spf.spf_entry', $new_spf, true);
lastStepStatus(0);
updateToDbVersion('201605120');
}
if (isDatabaseVersion('201605120')) {
showUpdateStep("Adding new dns-server setting");
$new_dns_daemon = isset($_POST['new_dns_daemon']) ? $_POST['new_dns_daemon'] : "bind";
Settings::AddNew("system.dns_server", $new_dns_daemon);
lastStepStatus(0);
updateToDbVersion('201605170');
}
if (isDatabaseVersion('201605170')) {
showUpdateStep("Adding new dns-editor setting for customers");
Database::query("ALTER TABLE `".TABLE_PANEL_CUSTOMERS."` ADD `dnsenabled` tinyint(1) NOT NULL default '0' AFTER `perlenabled`;");
lastStepStatus(0);
updateToDbVersion('201605180');
}
if (isDatabaseVersion('201605180')) {
showUpdateStep("Changing tables to be more mysql strict-mode compatible");
Database::query("ALTER TABLE `".TABLE_FTP_USERS."` CHANGE `last_login` `last_login` DATETIME NULL DEFAULT NULL;");
Database::query("ALTER TABLE `".TABLE_PANEL_IPSANDPORTS."` CHANGE `specialsettings` `specialsettings` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;");
Database::query("ALTER TABLE `".TABLE_PANEL_TASKS."` CHANGE `data` `data` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;");
lastStepStatus(0);
updateToDbVersion('201606190');
}
if (isDatabaseVersion('201606190')) {
showUpdateStep("Adding new setting for mod_php users to specify content of the global directory options file");
Settings::AddNew("system.apacheglobaldiropt", "");
lastStepStatus(0);
updateToDbVersion('201607140');
}
if (isFroxlorVersion('0.9.36')) {
showUpdateStep("Updating from 0.9.36 to 0.9.37-rc1", false);
updateToVersion('0.9.37-rc1');
}
if (isDatabaseVersion('201607140')) {
showUpdateStep("Adding new setting to hide certain options in customer panel");
Settings::AddNew("panel.customer_hide_options", "");
lastStepStatus(0);
updateToDbVersion('201607210');
}
if (isFroxlorVersion('0.9.37-rc1')) {
showUpdateStep("Updating from 0.9.37-rc1 to 0.9.37 final", false);
updateToVersion('0.9.37');
}

View File

@@ -18,47 +18,45 @@
/**
* checks if the new-version has some updating to do
*
* @param boolean $has_preconfig pointer to check if any preconfig has to be output
* @param string $return pointer to output string
* @param string $current_version current froxlor version
* @param boolean $has_preconfig
* pointer to check if any preconfig has to be output
* @param string $return
* pointer to output string
* @param string $current_version
* current froxlor version
*
* @return null
*/
function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $current_db_version) {
function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $current_db_version)
{
global $lng;
if(versionInUpdate($current_version, '0.9.4-svn2'))
{
if (versionInUpdate($current_version, '0.9.4-svn2')) {
$has_preconfig = true;
$description = 'Froxlor now enables the usage of a domain-wildcard entry and subdomains for this domain at the same time (subdomains are parsed before the main-domain vhost container).';
$description.= 'This makes it possible to catch all non-existing subdomains with the main vhost but also have the ability to use subdomains for that domain.<br />';
$description.= 'If you would like Froxlor to do so with your domains, the update script can set the correct values for existing domains for you. Note: future domains will have wildcard-entries enabled by default no matter how you decide here.';
$description .= 'This makes it possible to catch all non-existing subdomains with the main vhost but also have the ability to use subdomains for that domain.<br />';
$description .= 'If you would like Froxlor to do so with your domains, the update script can set the correct values for existing domains for you. Note: future domains will have wildcard-entries enabled by default no matter how you decide here.';
$question = '<strong>Do you want to use wildcard-entries for existing domains?:</strong>&nbsp;';
$question.= makeyesno('update_domainwildcardentry', '1', '0', '1');
$question .= makeyesno('update_domainwildcardentry', '1', '0', '1');
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.6-svn2'))
{
if(!PHPMailer::ValidateAddress(Settings::Get('panel.adminmail')))
{
if (versionInUpdate($current_version, '0.9.6-svn2')) {
if (! PHPMailer::ValidateAddress(Settings::Get('panel.adminmail'))) {
$has_preconfig = true;
$description = 'Froxlor uses a newer version of the phpMailerClass and determined that your current admin-mail address is invalid.';
$question = '<strong>Please specify a new admin-email address:</strong>&nbsp;<input type="text" class="text" name="update_adminmail" value="'.Settings::Get('panel.adminmail').'" />';
$question = '<strong>Please specify a new admin-email address:</strong>&nbsp;<input type="text" class="text" name="update_adminmail" value="' . Settings::Get('panel.adminmail') . '" />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}
if(versionInUpdate($current_version, '0.9.6-svn3'))
{
if (versionInUpdate($current_version, '0.9.6-svn3')) {
$has_preconfig = true;
$description = 'You now have the possibility to define default error-documents for your webserver which replace the default webserver error-messages.';
$question = '<strong>Do you want to enable default error-documents?:</strong>&nbsp;';
$question .= makeyesno('update_deferr_enable', '1', '0', '0').'<br /><br />';
if(Settings::Get('system.webserver') == 'apache2')
{
$question .= makeyesno('update_deferr_enable', '1', '0', '0') . '<br /><br />';
if (Settings::Get('system.webserver') == 'apache2') {
$question .= 'Path/URL for error 500:&nbsp;<input type="text" class="text" name="update_deferr_500" /><br /><br />';
$question .= 'Path/URL for error 401:&nbsp;<input type="text" class="text" name="update_deferr_401" /><br /><br />';
$question .= 'Path/URL for error 403:&nbsp;<input type="text" class="text" name="update_deferr_403" /><br /><br />';
@@ -67,37 +65,33 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.6-svn4'))
{
if (versionInUpdate($current_version, '0.9.6-svn4')) {
$has_preconfig = true;
$description = 'You can define a default support-ticket priority level which is pre-selected for new support-tickets.';
$question = '<strong>Which should be the default ticket-priority?:</strong>&nbsp;';
$question .= '<select name="update_deftic_priority">';
$priorities = makeoption($lng['ticket']['high'], '1', '2');
$priorities.= makeoption($lng['ticket']['normal'], '2', '2');
$priorities.= makeoption($lng['ticket']['low'], '3', '2');
$question .= $priorities.'</select>';
$priorities .= makeoption($lng['ticket']['normal'], '2', '2');
$priorities .= makeoption($lng['ticket']['low'], '3', '2');
$question .= $priorities . '</select>';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.6-svn5'))
{
if (versionInUpdate($current_version, '0.9.6-svn5')) {
$has_preconfig = true;
$description = 'If you have more than one PHP configurations defined in Froxlor you can now set a default one which will be used for every domain.';
$question = '<strong>Select default PHP configuration:</strong>&nbsp;';
$question .= '<select name="update_defsys_phpconfig">';
$configs_array = getPhpConfigs();
$configs = '';
foreach($configs_array as $idx => $desc)
{
foreach ($configs_array as $idx => $desc) {
$configs .= makeoption($desc, $idx, '1');
}
$question .= $configs.'</select>';
$question .= $configs . '</select>';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.6-svn6'))
{
if (versionInUpdate($current_version, '0.9.6-svn6')) {
$has_preconfig = true;
$description = 'For the new FTP-quota feature, you can now chose the currently used ftpd-software.';
$question = '<strong>Used FTPd-software:</strong>&nbsp;';
@@ -108,72 +102,63 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.7-svn1'))
{
if (versionInUpdate($current_version, '0.9.7-svn1')) {
$has_preconfig = true;
$description = 'You can now choose whether customers can select the http-redirect code and which of them acts as default.';
$question = '<strong>Allow customer chosen redirects?:</strong>&nbsp;';
$question.= makeyesno('update_customredirect_enable', '1', '0', '1').'<br /><br />';
$question.= '<strong>Select default redirect code (default: empty):</strong>&nbsp;';
$question.= '<select name="update_customredirect_default">';
$redirects = makeoption('--- ('.$lng['redirect_desc']['rc_default'].')', 1, '1');
$redirects.= makeoption('301 ('.$lng['redirect_desc']['rc_movedperm'].')', 2, '1');
$redirects.= makeoption('302 ('.$lng['redirect_desc']['rc_found'].')', 3, '1');
$redirects.= makeoption('303 ('.$lng['redirect_desc']['rc_seeother'].')', 4, '1');
$redirects.= makeoption('307 ('.$lng['redirect_desc']['rc_tempred'].')', 5, '1');
$question .= $redirects.'</select>';
$question .= makeyesno('update_customredirect_enable', '1', '0', '1') . '<br /><br />';
$question .= '<strong>Select default redirect code (default: empty):</strong>&nbsp;';
$question .= '<select name="update_customredirect_default">';
$redirects = makeoption('--- (' . $lng['redirect_desc']['rc_default'] . ')', 1, '1');
$redirects .= makeoption('301 (' . $lng['redirect_desc']['rc_movedperm'] . ')', 2, '1');
$redirects .= makeoption('302 (' . $lng['redirect_desc']['rc_found'] . ')', 3, '1');
$redirects .= makeoption('303 (' . $lng['redirect_desc']['rc_seeother'] . ')', 4, '1');
$redirects .= makeoption('307 (' . $lng['redirect_desc']['rc_tempred'] . ')', 5, '1');
$question .= $redirects . '</select>';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.7-svn2'))
{
if (versionInUpdate($current_version, '0.9.7-svn2')) {
$result = Database::query("SELECT `domain` FROM " . TABLE_PANEL_DOMAINS . " WHERE `documentroot` LIKE '%:%' AND `documentroot` NOT LIKE 'http://%' AND `openbasedir_path` = '0' AND `openbasedir` = '1'");
$wrongOpenBasedirDomain = array();
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$wrongOpenBasedirDomain[] = $row['domain'];
}
if(count($wrongOpenBasedirDomain) > 0)
{
if (count($wrongOpenBasedirDomain) > 0) {
$has_preconfig = true;
$description = 'Resetting the open_basedir to customer - root';
$question = '<strong>Due to a security - issue regarding open_basedir, Froxlor will set the open_basedir for the following domains to the customers root instead of the chosen documentroot:</strong><br />&nbsp;';
$question.= '<ul>';
$question .= '<ul>';
$idna_convert = new idna_convert_wrapper();
foreach($wrongOpenBasedirDomain as $domain)
{
$question.= '<li>' . $idna_convert->decode($domain) . '</li>';
foreach ($wrongOpenBasedirDomain as $domain) {
$question .= '<li>' . $idna_convert->decode($domain) . '</li>';
}
$question.= '</ul>';
$question .= '</ul>';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}
if(versionInUpdate($current_version, '0.9.9-svn1'))
{
if (versionInUpdate($current_version, '0.9.9-svn1')) {
$has_preconfig = true;
$description = 'When entering MX servers to Froxlor there was no mail-, imap-, pop3- and smtp-"A record" created. You can now chose whether this should be done or not.';
$question = '<strong>Do you want these A-records to be created even with MX servers given?:</strong>&nbsp;';
$question.= makeyesno('update_defdns_mailentry', '1', '0', '0');
$question .= makeyesno('update_defdns_mailentry', '1', '0', '0');
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.10-svn1'))
{
if (versionInUpdate($current_version, '0.9.10-svn1')) {
$has_nouser = false;
$has_nogroup = false;
$result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'system' AND `varname` = 'httpuser'");
$result = $result_stmt->fetch(PDO::FETCH_ASSOC);
if(!isset($result) || !isset($result['value']))
{
if (! isset($result) || ! isset($result['value'])) {
$has_preconfig = true;
$has_nouser = true;
$guessed_user = 'www-data';
if(function_exists('posix_getuid')
&& function_exists('posix_getpwuid')
) {
if (function_exists('posix_getuid') && function_exists('posix_getpwuid')) {
$_httpuser = posix_getpwuid(posix_getuid());
$guessed_user = $_httpuser['name'];
}
@@ -182,31 +167,24 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
$result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'system' AND `varname` = 'httpgroup'");
$result = $result_stmt->fetch(PDO::FETCH_ASSOC);
if(!isset($result) || !isset($result['value']))
{
if (! isset($result) || ! isset($result['value'])) {
$has_preconfig = true;
$has_nogroup = true;
$guessed_group = 'www-data';
if(function_exists('posix_getgid')
&& function_exists('posix_getgrgid')
) {
if (function_exists('posix_getgid') && function_exists('posix_getgrgid')) {
$_httpgroup = posix_getgrgid(posix_getgid());
$guessed_group = $_httpgroup['name'];
}
}
if($has_nouser || $has_nogroup)
{
if ($has_nouser || $has_nogroup) {
$description = 'Please enter the correct username/groupname of the webserver on your system We\'re guessing the user but it might not be correct, so please check.';
if($has_nouser)
{
$question = '<strong>Please enter the webservers username:</strong>&nbsp;<input type="text" class="text" name="update_httpuser" value="'.$guessed_user.'" />';
}
elseif($has_nogroup)
{
$question2 = '<strong>Please enter the webservers groupname:</strong>&nbsp;<input type="text" class="text" name="update_httpgroup" value="'.$guessed_group.'" />';
if($has_nouser) {
$question .= '<br /><br />'.$question2;
if ($has_nouser) {
$question = '<strong>Please enter the webservers username:</strong>&nbsp;<input type="text" class="text" name="update_httpuser" value="' . $guessed_user . '" />';
} elseif ($has_nogroup) {
$question2 = '<strong>Please enter the webservers groupname:</strong>&nbsp;<input type="text" class="text" name="update_httpgroup" value="' . $guessed_group . '" />';
if ($has_nouser) {
$question .= '<br /><br />' . $question2;
} else {
$question = $question2;
}
@@ -215,227 +193,202 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
}
}
if(versionInUpdate($current_version, '0.9.10'))
{
if (versionInUpdate($current_version, '0.9.10')) {
$has_preconfig = true;
$description = 'you can now decide whether Froxlor should be reached via hostname/froxlor or directly via the hostname.';
$question = '<strong>Do you want Froxlor to be reached directly via the hostname?:</strong>&nbsp;';
$question.= makeyesno('update_directlyviahostname', '1', '0', '0');
$question .= makeyesno('update_directlyviahostname', '1', '0', '0');
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.11-svn1'))
{
if (versionInUpdate($current_version, '0.9.11-svn1')) {
$has_preconfig = true;
$description = 'It is possible to enhance security with setting a regular expression to force your customers to enter more complex passwords.';
$question = '<strong>Enter a regular expression to force a higher password complexity (leave empty for none):</strong>&nbsp;';
$question.= '<input type="text" class="text" name="update_pwdregex" value="" />';
$question .= '<input type="text" class="text" name="update_pwdregex" value="" />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.11-svn3'))
{
if (versionInUpdate($current_version, '0.9.11-svn3')) {
$has_preconfig = true;
$description = 'As Froxlor can now handle perl, you have to specify where the perl executable is (only if you\'re running lighttpd, else just leave empty).';
$question = '<strong>Path to perl (default \'/usr/bin/perl\'):</strong>&nbsp;';
$question.= '<input type="text" class="text" name="update_perlpath" value="/usr/bin/perl" />';
$question .= '<input type="text" class="text" name="update_perlpath" value="/usr/bin/perl" />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.12-svn1'))
{
if(Settings::Get('system.mod_fcgid') == 1)
{
if (versionInUpdate($current_version, '0.9.12-svn1')) {
if (Settings::Get('system.mod_fcgid') == 1) {
$has_preconfig = true;
$description = 'You can chose whether you want Froxlor to use FCGID itself too now.';
$question = '<strong>Use FCGID for the Froxlor Panel?:</strong>&nbsp;';
$question.= makeyesno('update_fcgid_ownvhost', '1', '0', '0').'<br /><br />';
$question.= '<strong>If \'yes\', please specify local user/group (have to exist, Froxlor does not add them automatically):</strong><br /><br />';
$question.= 'Local user:&nbsp;';
$question.= '<input type="text" class="text" name="update_fcgid_httpuser" value="froxlorlocal" /><br /><br />';
$question.= 'Local group:&nbsp;';
$question.= '<input type="text" class="text" name="update_fcgid_httpgroup" value="froxlorlocal" /><br />';
$question .= makeyesno('update_fcgid_ownvhost', '1', '0', '0') . '<br /><br />';
$question .= '<strong>If \'yes\', please specify local user/group (have to exist, Froxlor does not add them automatically):</strong><br /><br />';
$question .= 'Local user:&nbsp;';
$question .= '<input type="text" class="text" name="update_fcgid_httpuser" value="froxlorlocal" /><br /><br />';
$question .= 'Local group:&nbsp;';
$question .= '<input type="text" class="text" name="update_fcgid_httpgroup" value="froxlorlocal" /><br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}
if(versionInUpdate($current_version, '0.9.12-svn2'))
{
if (versionInUpdate($current_version, '0.9.12-svn2')) {
$has_preconfig = true;
$description = 'Many apache user will have problems using perl/CGI as the customer docroots are not within the suexec path. Froxlor provides a simple workaround for that.';
$question = '<strong>Enable Apache/SuExec/Perl workaround?:</strong>&nbsp;';
$question.= makeyesno('update_perl_suexecworkaround', '1', '0', '0').'<br /><br />';
$question.= '<strong>If \'yes\', please specify a path within the suexec path where Froxlor will create symlinks to customer perl-enabled paths:</strong><br /><br />';
$question.= 'Path for symlinks (must be within suexec path):&nbsp;';
$question.= '<input type="text" class="text" name="update_perl_suexecpath" value="/var/www/cgi-bin/" /><br />';
$question .= makeyesno('update_perl_suexecworkaround', '1', '0', '0') . '<br /><br />';
$question .= '<strong>If \'yes\', please specify a path within the suexec path where Froxlor will create symlinks to customer perl-enabled paths:</strong><br /><br />';
$question .= 'Path for symlinks (must be within suexec path):&nbsp;';
$question .= '<input type="text" class="text" name="update_perl_suexecpath" value="/var/www/cgi-bin/" /><br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.12-svn4'))
{
if((int)Settings::Get('system.awstats_enabled') == 1)
{
if (versionInUpdate($current_version, '0.9.12-svn4')) {
if ((int) Settings::Get('system.awstats_enabled') == 1) {
$has_preconfig = true;
$description = 'Due to different paths of awstats_buildstaticpages.pl and awstats.pl you can set a different path for awstats.pl now.';
$question = '<strong>Path to \'awstats.pl\'?:</strong>&nbsp;';
$question.= '<input type="text" class="text" name="update_awstats_awstatspath" value="'.Settings::Get('system.awstats_path').'" /><br />';
$question .= '<input type="text" class="text" name="update_awstats_awstatspath" value="' . Settings::Get('system.awstats_path') . '" /><br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}
if(versionInUpdate($current_version, '0.9.13-svn1'))
{
if((int)Settings::Get('autoresponder.autoresponder_active') == 1)
{
if (versionInUpdate($current_version, '0.9.13-svn1')) {
if ((int) Settings::Get('autoresponder.autoresponder_active') == 1) {
$has_preconfig = true;
$description = 'Froxlor can now limit the number of autoresponder-entries for each user. Here you can set the value which will be available for each customer (Of course you can change the value for each customer separately after the update).';
$question = '<strong>How many autoresponders should your customers be able to add?:</strong>&nbsp;';
$question.= '<input type="text" class="text" name="update_autoresponder_default" value="0" />&nbsp;'.makecheckbox('update_autoresponder_default', $lng['customer']['unlimited'], '-1', false, 0, true, true).'<br />';
$question .= '<input type="text" class="text" name="update_autoresponder_default" value="0" />&nbsp;' . makecheckbox('update_autoresponder_default', $lng['customer']['unlimited'], '-1', false, 0, true, true) . '<br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}
if(versionInUpdate($current_version, '0.9.13.1'))
{
if((int)Settings::Get('system.mod_fcgid_ownvhost') == 1)
{
if (versionInUpdate($current_version, '0.9.13.1')) {
if ((int) Settings::Get('system.mod_fcgid_ownvhost') == 1) {
$has_preconfig = true;
$description = 'You have FCGID for Froxlor itself activated. You can now specify a PHP-configuration for this.';
$question = '<strong>Select Froxlor-vhost PHP configuration:</strong>&nbsp;';
$question .= '<select name="update_defaultini_ownvhost">';
$configs_array = getPhpConfigs();
$configs = '';
foreach($configs_array as $idx => $desc)
{
foreach ($configs_array as $idx => $desc) {
$configs .= makeoption($desc, $idx, '1');
}
$question .= $configs.'</select>';
$question .= $configs . '</select>';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}
if(versionInUpdate($current_version, '0.9.14-svn3'))
{
if((int)Settings::Get('system.awstats_enabled') == 1)
{
if (versionInUpdate($current_version, '0.9.14-svn3')) {
if ((int) Settings::Get('system.awstats_enabled') == 1) {
$has_preconfig = true;
$description = 'To have icons in AWStats statistic-pages please enter the path to AWStats icons folder.';
$question = '<strong>Path to AWSTats icons folder:</strong>&nbsp;';
$question.= '<input type="text" class="text" name="update_awstats_icons" value="'.Settings::Get('system.awstats_icons').'" />';
$question .= '<input type="text" class="text" name="update_awstats_icons" value="' . Settings::Get('system.awstats_icons') . '" />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}
if(versionInUpdate($current_version, '0.9.14-svn4'))
{
if((int)Settings::Get('system.use_ssl') == 1)
{
if (versionInUpdate($current_version, '0.9.14-svn4')) {
if ((int) Settings::Get('system.use_ssl') == 1) {
$has_preconfig = true;
$description = 'Froxlor now has the possibility to set \'SSLCertificateChainFile\' for the apache webserver.';
$question = '<strong>Enter filename (leave empty for none):</strong>&nbsp;';
$question.= '<input type="text" class="text" name="update_ssl_cert_chainfile" value="'.Settings::Get('system.ssl_cert_chainfile').'" />';
$question .= '<input type="text" class="text" name="update_ssl_cert_chainfile" value="' . Settings::Get('system.ssl_cert_chainfile') . '" />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}
if(versionInUpdate($current_version, '0.9.14-svn6'))
{
if (versionInUpdate($current_version, '0.9.14-svn6')) {
$has_preconfig = true;
$description = 'You can now allow customers to use any of their domains as username for the login.';
$question = '<strong>Do you want to enable domain-login for all customers?:</strong>&nbsp;';
$question.= makeyesno('update_allow_domain_login', '1', '0', '0');
$question .= makeyesno('update_allow_domain_login', '1', '0', '0');
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.14-svn10'))
{
if (versionInUpdate($current_version, '0.9.14-svn10')) {
$has_preconfig = true;
$description = '<strong>This update removes the unsupported real-time option. Additionally the deprecated tables for navigation and cronscripts are removed, any modules using these tables need to be updated to the new structure!</strong>';
$question = '';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.16-svn1'))
{
if (versionInUpdate($current_version, '0.9.16-svn1')) {
$has_preconfig = true;
$description = 'Froxlor now features support for php-fpm.';
$question = '<strong>Do you want to enable php-fpm?:</strong>&nbsp;';
$question.= makeyesno('update_phpfpm_enabled', '1', '0', '0').'<br /><br />';
$question.= 'If \'yes\', please specify the configuration directory:&nbsp;';
$question.= '<input type="text" class="text" name="update_phpfpm_configdir" value="/etc/php-fpm.d/" /><br /><br />';
$question.= 'Please specify the temporary files directory:&nbsp;';
$question.= '<input type="text" class="text" name="update_phpfpm_tmpdir" value="/var/customers/tmp/" /><br /><br />';
$question.= 'Please specify the PEAR directory:&nbsp;';
$question.= '<input type="text" class="text" name="update_phpfpm_peardir" value="/usr/share/php/:/usr/share/php5/" /><br /><br />';
$question.= 'Please specify the php-fpm restart-command:&nbsp;';
$question.= '<input type="text" class="text" name="update_phpfpm_reload" value="/etc/init.d/php-fpm restart" /><br /><br />';
$question.= 'Please specify the php-fpm rocess manager control:&nbsp;';
$question.= '<select name="update_phpfpm_pm">';
$question .= makeyesno('update_phpfpm_enabled', '1', '0', '0') . '<br /><br />';
$question .= 'If \'yes\', please specify the configuration directory:&nbsp;';
$question .= '<input type="text" class="text" name="update_phpfpm_configdir" value="/etc/php-fpm.d/" /><br /><br />';
$question .= 'Please specify the temporary files directory:&nbsp;';
$question .= '<input type="text" class="text" name="update_phpfpm_tmpdir" value="/var/customers/tmp/" /><br /><br />';
$question .= 'Please specify the PEAR directory:&nbsp;';
$question .= '<input type="text" class="text" name="update_phpfpm_peardir" value="/usr/share/php/:/usr/share/php5/" /><br /><br />';
$question .= 'Please specify the php-fpm restart-command:&nbsp;';
$question .= '<input type="text" class="text" name="update_phpfpm_reload" value="/etc/init.d/php-fpm restart" /><br /><br />';
$question .= 'Please specify the php-fpm rocess manager control:&nbsp;';
$question .= '<select name="update_phpfpm_pm">';
$redirects = makeoption('static', 'static', 'static');
$redirects.= makeoption('dynamic', 'dynamic', 'static');
$question .= $redirects.'</select><br /><br />';
$question.= 'Please specify the number of child processes:&nbsp;';
$question.= '<input type="text" class="text" name="update_phpfpm_max_children" value="1" /><br /><br />';
$question.= 'Please specify the number of requests per child before respawning:&nbsp;';
$question.= '<input type="text" class="text" name="update_phpfpm_max_requests" value="0" /><br /><br />';
$question.= '<em>The following settings are only required if you chose process manager = dynamic</em><br /><br />';
$question.= 'Please specify the number of child processes created on startup:&nbsp;';
$question.= '<input type="text" class="text" name="update_phpfpm_start_servers" value="20" /><br /><br />';
$question.= 'Please specify the desired minimum number of idle server processes:&nbsp;';
$question.= '<input type="text" class="text" name="update_phpfpm_min_spare_servers" value="5" /><br /><br />';
$question.= 'Please specify the desired maximum number of idle server processes:&nbsp;';
$question.= '<input type="text" class="text" name="update_phpfpm_max_spare_servers" value="35" /><br />';
$redirects .= makeoption('dynamic', 'dynamic', 'static');
$question .= $redirects . '</select><br /><br />';
$question .= 'Please specify the number of child processes:&nbsp;';
$question .= '<input type="text" class="text" name="update_phpfpm_max_children" value="1" /><br /><br />';
$question .= 'Please specify the number of requests per child before respawning:&nbsp;';
$question .= '<input type="text" class="text" name="update_phpfpm_max_requests" value="0" /><br /><br />';
$question .= '<em>The following settings are only required if you chose process manager = dynamic</em><br /><br />';
$question .= 'Please specify the number of child processes created on startup:&nbsp;';
$question .= '<input type="text" class="text" name="update_phpfpm_start_servers" value="20" /><br /><br />';
$question .= 'Please specify the desired minimum number of idle server processes:&nbsp;';
$question .= '<input type="text" class="text" name="update_phpfpm_min_spare_servers" value="5" /><br /><br />';
$question .= 'Please specify the desired maximum number of idle server processes:&nbsp;';
$question .= '<input type="text" class="text" name="update_phpfpm_max_spare_servers" value="35" /><br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.16-svn2'))
{
if((int)Settings::Get('phpfpm.enabled') == 1)
{
if (versionInUpdate($current_version, '0.9.16-svn2')) {
if ((int) Settings::Get('phpfpm.enabled') == 1) {
$has_preconfig = true;
$description = 'You can chose whether you want Froxlor to use PHP-FPM itself too now.';
$question = '<strong>Use PHP-FPM for the Froxlor Panel?:</strong>&nbsp;';
$question.= makeyesno('update_phpfpm_enabled_ownvhost', '1', '0', '0').'<br /><br />';
$question.= '<strong>If \'yes\', please specify local user/group (have to exist, Froxlor does not add them automatically):</strong><br /><br />';
$question.= 'Local user:&nbsp;';
$question.= '<input type="text" class="text" name="update_phpfpm_httpuser" value="'.Settings::Get('system.mod_fcgid_httpuser').'" /><br /><br />';
$question.= 'Local group:&nbsp;';
$question.= '<input type="text" class="text" name="update_phpfpm_httpgroup" value="'.Settings::Get('system.mod_fcgid_httpgroup').'" /><br />';
$question .= makeyesno('update_phpfpm_enabled_ownvhost', '1', '0', '0') . '<br /><br />';
$question .= '<strong>If \'yes\', please specify local user/group (have to exist, Froxlor does not add them automatically):</strong><br /><br />';
$question .= 'Local user:&nbsp;';
$question .= '<input type="text" class="text" name="update_phpfpm_httpuser" value="' . Settings::Get('system.mod_fcgid_httpuser') . '" /><br /><br />';
$question .= 'Local group:&nbsp;';
$question .= '<input type="text" class="text" name="update_phpfpm_httpgroup" value="' . Settings::Get('system.mod_fcgid_httpgroup') . '" /><br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}
if(versionInUpdate($current_version, '0.9.17-svn1'))
{
if (versionInUpdate($current_version, '0.9.17-svn1')) {
$has_preconfig = true;
$description = 'Select if you want to enable the web- and traffic-reports';
$question = '<strong>Enable?:</strong>&nbsp;';
$question.= makeyesno('update_system_report_enable', '1', '0', '1').'<br /><br />';
$question.= '<strong>If \'yes\', please specify a percentage value for web- and traffic when reports are to be sent:</strong><br /><br />';
$question.= 'Webusage warning level:&nbsp;';
$question.= '<input type="text" class="text" name="update_system_report_webmax" value="90" /><br /><br />';
$question.= 'Traffic warning level:&nbsp;';
$question.= '<input type="text" class="text" name="update_system_report_trafficmax" value="90" /><br />';
$question .= makeyesno('update_system_report_enable', '1', '0', '1') . '<br /><br />';
$question .= '<strong>If \'yes\', please specify a percentage value for web- and traffic when reports are to be sent:</strong><br /><br />';
$question .= 'Webusage warning level:&nbsp;';
$question .= '<input type="text" class="text" name="update_system_report_webmax" value="90" /><br /><br />';
$question .= 'Traffic warning level:&nbsp;';
$question .= '<input type="text" class="text" name="update_system_report_trafficmax" value="90" /><br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.18-svn2'))
{
if (versionInUpdate($current_version, '0.9.18-svn2')) {
$has_preconfig = true;
$description = 'As you can (obviously) see, Froxlor now comes with a new theme. You also have the possibility to switch back to "Classic" if you want to.';
$question = '<strong>Select default panel theme:</strong>&nbsp;';
$question.= '<select name="update_default_theme">';
$question .= '<select name="update_default_theme">';
$themes = getThemes();
foreach($themes as $cur_theme) // $theme is already in use
{
$question.= makeoption($cur_theme, $cur_theme, 'Froxlor');
foreach ($themes as $cur_theme) // $theme is already in use
{
$question .= makeoption($cur_theme, $cur_theme, 'Froxlor');
}
$question.= '</select>';
$question .= '</select>';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if(versionInUpdate($current_version, '0.9.28-svn4'))
{
if (versionInUpdate($current_version, '0.9.28-svn4')) {
$has_preconfig = true;
$description = 'This version introduces a lot of profound changes:';
$description .= '<br /><ul><li>Improving the whole template system</li><li>Full UTF-8 support</li><li><strong>Removing support for the former default theme \'Classic\'</strong></li></ul>';
@@ -444,13 +397,12 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
$description .= 'test this update in a testing environment using your existing data.<br /><br />';
$question = '<strong>Select your preferred Classic Theme replacement:</strong>&nbsp;';
$question.= '<select name="classic_theme_replacement">';
$question .= '<select name="classic_theme_replacement">';
$themes = getThemes();
foreach($themes as $cur_theme)
{
$question.= makeoption($cur_theme, $cur_theme, 'Froxlor');
foreach ($themes as $cur_theme) {
$question .= makeoption($cur_theme, $cur_theme, 'Froxlor');
}
$question.= '</select>';
$question .= '</select>';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
@@ -460,16 +412,16 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
if (Settings::Get('system.webserver') == 'apache2') {
$has_preconfig = true;
$description = 'Froxlor now supports the new Apache 2.4. Please be aware that you need to load additional apache-modules in ordner to use it.<br />';
$description.= '<pre>LoadModule authz_core_module modules/mod_authz_core.so
$description .= '<pre>LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so</pre><br />';
$question = '<strong>Do you want to enable the Apache-2.4 modification?:</strong>&nbsp;';
$question.= makeyesno('update_system_apache24', '1', '0', '0');
$question .= makeyesno('update_system_apache24', '1', '0', '0');
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
} elseif (Settings::Get('system.webserver') == 'nginx') {
$has_preconfig = true;
$description = 'The path to nginx\'s fastcgi_params file is now customizable.<br /><br />';
$question = '<strong>Please enter full path to you nginx/fastcgi_params file (including filename):</strong>&nbsp;';
$question.= '<input type="text" class="text" name="nginx_fastcgi_params" value="/etc/nginx/fastcgi_params" />';
$question .= '<input type="text" class="text" name="nginx_fastcgi_params" value="/etc/nginx/fastcgi_params" />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}
@@ -478,11 +430,11 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
$has_preconfig = true;
$description = 'This version adds an option to append the domain-name to the document-root for domains and subdomains.<br />';
$description = 'This version adds an option to append the domain-name to the document-root for domains and subdomains.<br />';
$description .= 'You can enable or disable this feature anytime from settings -> system settings.<br />';
$question = '<strong>Do you want to automatically append the domain-name to the documentroot of newly created domains?:</strong>&nbsp;';
$question.= makeyesno('update_system_documentroot_use_default_value', '1', '0', '0');
$question .= makeyesno('update_system_documentroot_use_default_value', '1', '0', '0');
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
@@ -491,12 +443,10 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
$has_preconfig = true;
// just an information about the new sendmail parameter (#1134)
$description = 'Froxlor changed the default parameter-set of sendmail (php.ini)<br />';
$description = 'Froxlor changed the default parameter-set of sendmail (php.ini)<br />';
$description .= 'sendmail_path = "/usr/sbin/sendmail -t <strong>-i</strong> -f {CUSTOMER_EMAIL}"<br /><br />';
$description .= 'If you don\'t have any problems with sending mails, you don\'t need to change this';
if (Settings::Get('system.mod_fcgid') == '1'
|| Settings::Get('phpfpm.enabled') == '1'
) {
if (Settings::Get('system.mod_fcgid') == '1' || Settings::Get('phpfpm.enabled') == '1') {
// information about removal of php's safe_mode
$description .= '<br /><br />The php safe_mode flag has been removed as current versions of PHP<br />';
$description .= 'do not support it anymore.<br /><br />';
@@ -509,45 +459,43 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
if (versionInUpdate($current_version, '0.9.29-dev1')) {
// we only need to ask if fcgid|php-fpm is enabled
if (Settings::Get('system.mod_fcgid') == '1'
|| Settings::Get('phpfpm.enabled') == '1'
) {
if (Settings::Get('system.mod_fcgid') == '1' || Settings::Get('phpfpm.enabled') == '1') {
$has_preconfig = true;
$description = 'Standard-subdomains can now be hidden from the php-configuration overview.<br />';
$description = 'Standard-subdomains can now be hidden from the php-configuration overview.<br />';
$question = '<strong>Do you want to hide the standard-subdomains (this can be changed in the settings any time)?:</strong>&nbsp;';
$question.= makeyesno('hide_stdsubdomains', '1', '0', '0');
$question .= makeyesno('hide_stdsubdomains', '1', '0', '0');
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}
if (versionInUpdate($current_version, '0.9.29-dev2')) {
$has_preconfig = true;
$description = 'You can now decide whether admins/customers are able to change the theme<br />';
$description = 'You can now decide whether admins/customers are able to change the theme<br />';
$question = '<strong>If you want to disallow theme-changing, select "no" from the dropdowns:</strong>&nbsp;';
$question.= "Admins: ". makeyesno('allow_themechange_a', '1', '0', '1').'&nbsp;&nbsp;';
$question.= "Customers: ".makeyesno('allow_themechange_c', '1', '0', '1');
$question .= "Admins: " . makeyesno('allow_themechange_a', '1', '0', '1') . '&nbsp;&nbsp;';
$question .= "Customers: " . makeyesno('allow_themechange_c', '1', '0', '1');
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if (versionInUpdate($current_version, '0.9.29-dev3')) {
$has_preconfig = true;
$description = 'There is now a possibility to specify AXFR servers for your bind zone-configuration<br />';
$description = 'There is now a possibility to specify AXFR servers for your bind zone-configuration<br />';
$question = '<strong>Enter a comma-separated list of AXFR servers or leave empty (default):</strong>&nbsp;';
$question.= '<input type="text" class="text" name="system_afxrservers" value="" />';
$question .= '<input type="text" class="text" name="system_afxrservers" value="" />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if (versionInUpdate($current_version, '0.9.29-dev4')) {
$has_preconfig = true;
$description = 'As customers can now specify ssl-certificate data for their domains, you need to specify where the generated files are stored<br />';
$description = 'As customers can now specify ssl-certificate data for their domains, you need to specify where the generated files are stored<br />';
$question = '<strong>Specify the directory for customer ssl-certificates:</strong>&nbsp;';
$question.= '<input type="text" class="text" name="system_customersslpath" value="/etc/ssl/froxlor-custom/" />';
$question .= '<input type="text" class="text" name="system_customersslpath" value="/etc/ssl/froxlor-custom/" />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if (versionInUpdate($current_version, '0.9.29.1-dev3')) {
$has_preconfig = true;
$description = 'The build in logrotation-feature has been removed. Please follow the configuration-instructions for your system to enable logrotating again.';
$description = 'The build in logrotation-feature has been removed. Please follow the configuration-instructions for your system to enable logrotating again.';
$question = '';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
@@ -555,11 +503,9 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
// let the apache+fpm users know that they MUST change their config
// for the domains / webserver to work after the update
if (versionInUpdate($current_version, '0.9.30-dev1')) {
if (Settings::Get('system.webserver') == 'apache2'
&& Settings::Get('phpfpm.enabled') == '1'
) {
if (Settings::Get('system.webserver') == 'apache2' && Settings::Get('phpfpm.enabled') == '1') {
$has_preconfig = true;
$description = 'The PHP-FPM implementation for apache2 has changed. Please look for the "<b>fastcgi.conf</b>" (Debian/Ubuntu) or "<b>70_fastcgi.conf</b>" (Gentoo) within /etc/apache2/ and change it as shown below:<br /><br />';
$description = 'The PHP-FPM implementation for apache2 has changed. Please look for the "<b>fastcgi.conf</b>" (Debian/Ubuntu) or "<b>70_fastcgi.conf</b>" (Gentoo) within /etc/apache2/ and change it as shown below:<br /><br />';
$description .= '<pre class="code-block">&lt;IfModule mod_fastcgi.c&gt;
FastCgiIpcDir /var/lib/apache2/fastcgi/
&lt;Location "/fastcgiphp"&gt;
@@ -575,11 +521,9 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
}
if (versionInUpdate($current_version, '0.9.31-dev2')) {
if (Settings::Get('system.webserver') == 'apache2'
&& Settings::Get('phpfpm.enabled') == '1'
) {
if (Settings::Get('system.webserver') == 'apache2' && Settings::Get('phpfpm.enabled') == '1') {
$has_preconfig = true;
$description = 'The FPM socket directory is now a setting in froxlor. Its default is <b>/var/lib/apache2/fastcgi/</b>.<br/>If you are using <b>/var/run/apache2</b> in the "<b>fastcgi.conf</b>" (Debian/Ubuntu) or "<b>70_fastcgi.conf</b>" (Gentoo) please correct this path accordingly<br />';
$description = 'The FPM socket directory is now a setting in froxlor. Its default is <b>/var/lib/apache2/fastcgi/</b>.<br/>If you are using <b>/var/run/apache2</b> in the "<b>fastcgi.conf</b>" (Debian/Ubuntu) or "<b>70_fastcgi.conf</b>" (Gentoo) please correct this path accordingly<br />';
$question = '';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
@@ -587,50 +531,50 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
if (versionInUpdate($current_version, '0.9.31-dev4')) {
$has_preconfig = true;
$description = 'The template-variable {PASSWORD} has been replaced with {LINK}. Please update your password reset templates!<br />';
$description = 'The template-variable {PASSWORD} has been replaced with {LINK}. Please update your password reset templates!<br />';
$question = '';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if (versionInUpdate($current_version, '0.9.31-dev5')) {
$has_preconfig = true;
$description = 'You can enable/disable error-reporting for admins and customers!<br /><br />';
$description = 'You can enable/disable error-reporting for admins and customers!<br /><br />';
$question = '<strong>Do you want to enable error-reporting for admins? (default: yes):</strong>&nbsp;';
$question.= makeyesno('update_error_report_admin', '1', '0', '1').'<br />';
$question.= '<strong>Do you want to enable error-reporting for customers? (default: no):</strong>&nbsp;';
$question.= makeyesno('update_error_report_customer', '1', '0', '0');
$question .= makeyesno('update_error_report_admin', '1', '0', '1') . '<br />';
$question .= '<strong>Do you want to enable error-reporting for customers? (default: no):</strong>&nbsp;';
$question .= makeyesno('update_error_report_customer', '1', '0', '0');
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if (versionInUpdate($current_version, '0.9.31-rc2')) {
$has_preconfig = true;
$description = 'You can enable/disable the display/usage of the news-feed for admins<br /><br />';
$description = 'You can enable/disable the display/usage of the news-feed for admins<br /><br />';
$question = '<strong>Do you want to enable the news-feed for admins? (default: yes):</strong>&nbsp;';
$question.= makeyesno('update_admin_news_feed', '1', '0', '1').'<br />';
$question .= makeyesno('update_admin_news_feed', '1', '0', '1') . '<br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if (versionInUpdate($current_version, '0.9.32-dev2')) {
$has_preconfig = true;
$description = 'To enable logging of the mail-traffic, you need to set the following settings accordingly<br /><br />';
$description = 'To enable logging of the mail-traffic, you need to set the following settings accordingly<br /><br />';
$question = '<strong>Do you want to enable the traffic collection for mail? (default: yes):</strong>&nbsp;';
$question.= makeyesno('mailtraffic_enabled', '1', '0', '1').'<br />';
$question.= '<strong>Mail Transfer Agent</strong><br />';
$question.= 'Type of your MTA:&nbsp;';
$question.= '<select name="mtaserver">';
$question.= makeoption('Postfix', 'postfix', 'postfix');
$question.= makeoption('Exim4', 'exim4', 'postfix');
$question.= '</select><br />';
$question.= 'Logfile for your MTA:&nbsp;';
$question.= '<input type="text" class="text" name="mtalog" value="/var/log/mail.log" /><br />';
$question.= '<strong>Mail Delivery Agent</strong><br />';
$question.= 'Type of your MDA:&nbsp;';
$question.= '<select name="mdaserver">';
$question.= makeoption('Dovecot', 'dovecot', 'dovecot');
$question.= makeoption('Courier', 'courier', 'dovecot');
$question.= '</select><br /><br />';
$question.= 'Logfile for your MDA:&nbsp;';
$question.= '<input type="text" class="text" name="mdalog" value="/var/log/mail.log" /><br />';
$question .= makeyesno('mailtraffic_enabled', '1', '0', '1') . '<br />';
$question .= '<strong>Mail Transfer Agent</strong><br />';
$question .= 'Type of your MTA:&nbsp;';
$question .= '<select name="mtaserver">';
$question .= makeoption('Postfix', 'postfix', 'postfix');
$question .= makeoption('Exim4', 'exim4', 'postfix');
$question .= '</select><br />';
$question .= 'Logfile for your MTA:&nbsp;';
$question .= '<input type="text" class="text" name="mtalog" value="/var/log/mail.log" /><br />';
$question .= '<strong>Mail Delivery Agent</strong><br />';
$question .= 'Type of your MDA:&nbsp;';
$question .= '<select name="mdaserver">';
$question .= makeoption('Dovecot', 'dovecot', 'dovecot');
$question .= makeoption('Courier', 'courier', 'dovecot');
$question .= '</select><br /><br />';
$question .= 'Logfile for your MDA:&nbsp;';
$question .= '<input type="text" class="text" name="mdalog" value="/var/log/mail.log" /><br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
@@ -638,7 +582,7 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
$has_preconfig = true;
$description = 'Froxlor now generates a cron-configuration file for the cron-daemon. Please set a filename which will be included automatically by your crond (e.g. files in /etc/cron.d/)<br /><br />';
$question = '<strong>Path to the cron-service configuration-file.</strong> This file will be updated regularly and automatically by froxlor.<br />Note: please <b>be sure</b> to use the same filename as for the main froxlor cronjob (default: /etc/cron.d/froxlor)!<br />';
$question.= '<input type="text" class="text" name="crondfile" value="/etc/cron.d/froxlor" /><br />';
$question .= '<input type="text" class="text" name="crondfile" value="/etc/cron.d/froxlor" /><br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
@@ -646,7 +590,7 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
$has_preconfig = true;
$description = 'In order for the new cron.d file to work properly, we need to know about the cron-service reload command.<br /><br />';
$question = '<strong>Please specify the reload-command of your cron-daemon</strong> (default: /etc/init.d/cron reload)<br />';
$question.= '<input type="text" class="text" name="crondreload" value="/etc/init.d/cron reload" /><br />';
$question .= '<input type="text" class="text" name="crondreload" value="/etc/init.d/cron reload" /><br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
@@ -654,17 +598,17 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
$has_preconfig = true;
$description = 'To customize the command which executes the cronjob (php - basically) change the path below according to your system.<br /><br />';
$question = '<strong>Please specify the command to execute cronscripts</strong> (default: "/usr/bin/nice -n 5 /usr/bin/php5 -q")<br />';
$question.= '<input type="text" class="text" name="croncmdline" value="/usr/bin/nice -n 5 /usr/bin/php5 -q" /><br />';
$question .= '<input type="text" class="text" name="croncmdline" value="/usr/bin/nice -n 5 /usr/bin/php5 -q" /><br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if (versionInUpdate($current_version, '0.9.33-dev1')) {
$has_preconfig = true;
$description = 'You can enable/disable the display/usage of the custom newsfeed for customers.<br /><br />';
$description = 'You can enable/disable the display/usage of the custom newsfeed for customers.<br /><br />';
$question = '<strong>Do you want to enable the custom newsfeed for customer? (default: no):</strong>&nbsp;';
$question.= makeyesno('customer_show_news_feed', '1', '0', '0').'<br />';
$question.= '<strong>You have to set the URL for your RSS-feed here, if you have chosen to enable the custom newsfeed on the customer-dashboard:</strong>&nbsp;';
$question.= '<input type="text" class="text" name="customer_news_feed_url" value="" /><br />';
$question .= makeyesno('customer_show_news_feed', '1', '0', '0') . '<br />';
$question .= '<strong>You have to set the URL for your RSS-feed here, if you have chosen to enable the custom newsfeed on the customer-dashboard:</strong>&nbsp;';
$question .= '<input type="text" class="text" name="customer_news_feed_url" value="" /><br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
@@ -672,48 +616,67 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
// only if bind is used - if not the default will be set, which is '0' (off)
if (Settings::get('system.bind_enable') == 1) {
$has_preconfig = true;
$description = 'You can enable/disable the generation of the bind-zone / config for the system hostname.<br /><br />';
$description = 'You can enable/disable the generation of the bind-zone / config for the system hostname.<br /><br />';
$question = '<strong>Do you want to generate a bind-zone for the system-hostname? (default: no):</strong>&nbsp;';
$question.= makeyesno('dns_createhostnameentry', '1', '0', '0').'<br />';
$question .= makeyesno('dns_createhostnameentry', '1', '0', '0') . '<br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}
if (versionInUpdate($current_version, '0.9.33-rc2')) {
$has_preconfig = true;
$description = 'You can chose whether you want to receive an e-mail on cronjob errors. Keep in mind that this can lead to an e-mail being sent every 5 minutes.<br /><br />';
$description = 'You can chose whether you want to receive an e-mail on cronjob errors. Keep in mind that this can lead to an e-mail being sent every 5 minutes.<br /><br />';
$question = '<strong>Do you want to receive cron-errors via mail? (default: no):</strong>&nbsp;';
$question.= makeyesno('system_send_cron_errors', '1', '0', '0').'<br />';
$question .= makeyesno('system_send_cron_errors', '1', '0', '0') . '<br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if (versionInUpdate($current_version, '0.9.34-dev3')) {
$has_preconfig = true;
$description = 'Froxlor now requires the PHP mbstring-extension as we need to be multibyte-character safe in some cases';
$question = '<strong>PHP mbstring</strong> is currently: ';
if (!extension_loaded('mbstring')) {
$question .= '<span class="red">not installed/loaded</span>';
$question .= '<br>Please install the PHP mbstring extension in order to finish the update';
} else {
$question .= '<span class="green">installed/loaded</span>';
}
$question .= '<br>';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
$has_preconfig = true;
$description = 'Froxlor now requires the PHP mbstring-extension as we need to be multibyte-character safe in some cases';
$question = '<strong>PHP mbstring</strong> is currently: ';
if (! extension_loaded('mbstring')) {
$question .= '<span class="red">not installed/loaded</span>';
$question .= '<br>Please install the PHP mbstring extension in order to finish the update';
} else {
$question .= '<span class="green">installed/loaded</span>';
}
$question .= '<br>';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if (versionInUpdate($current_db_version, '201603070')) {
$has_preconfig = true;
$description = 'You can chose whether you want to enable or disable our Let\'s Encrypt implementation.<br />Please remember that you need to go through the webserver-configuration when enabled because this feature needs a special configuration.<br /><br />';
$question = '<strong>Do you want to enable Let\'s Encrypt? (default: yes):</strong>&nbsp;';
$question.= makeyesno('enable_letsencrypt', '1', '0', '1').'<br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
$has_preconfig = true;
$description = 'You can chose whether you want to enable or disable our Let\'s Encrypt implementation.<br />Please remember that you need to go through the webserver-configuration when enabled because this feature needs a special configuration.<br /><br />';
$question = '<strong>Do you want to enable Let\'s Encrypt? (default: yes):</strong>&nbsp;';
$question .= makeyesno('enable_letsencrypt', '1', '0', '1') . '<br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if (versionInUpdate($current_db_version, '201604270')) {
$has_preconfig = true;
$description = 'You can chose whether you want to enable or disable our backup function.<br /><br />';
$description = 'You can chose whether you want to enable or disable our backup function.<br /><br />';
$question = '<strong>Do you want to enable Backup? (default: no):</strong>&nbsp;';
$question.= makeyesno('enable_backup', '1', '0', '0').'<br />';
$question .= makeyesno('enable_backup', '1', '0', '0') . '<br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if (versionInUpdate($current_db_version, '201605090')) {
$has_preconfig = true;
$description = 'You can chose whether you want to enable or disable our DNS editor<br /><br />';
$question = '<strong>Do you want to enable the DNS editor? (default: no):</strong>&nbsp;';
$question .= makeyesno('enable_dns', '1', '0', '0') . '<br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
if (versionInUpdate($current_db_version, '201605170')) {
$has_preconfig = true;
$description = 'Froxlor now supports the dns-daemon Power-DNS, you can chose between bind and powerdns now.';
$question = '<strong>Select dns-daemon you want to use:</strong>&nbsp;';
$question .= '<select name="new_dns_daemon">';
$dnsdaemons = makeoption('Bind9', 'bind', 'bind');
$dnsdaemons .= makeoption('PowerDNS', 'pdns', 'bind');
$question .= $dnsdaemons . '</select>';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
}

1
lib/.gitignore vendored
View File

@@ -1 +0,0 @@
userdata.inc.php

View File

@@ -71,7 +71,7 @@ class ConfigDaemon {
* @var string
*/
public $title;
/**
* Whether this is the default daemon of the service-category
* @var boolean
@@ -321,7 +321,7 @@ class ConfigDaemon {
if (array_key_exists('chown', $attributes)) {
$return[] = array('type' => 'command', 'content' => 'chown ' . $attributes['chown'] . ' "' . $this->_parseContent($attributes['name']) . '"', 'execute' => "post");
}
// If we have more than 1 element, we want to group this stuff for easier processing later
if (count($return) > 1) {
$return = array('type' => 'file', 'subcommands' => $return, 'name' => $this->_parseContent($attributes['name']));
@@ -399,10 +399,11 @@ class ConfigDaemon {
case "false": if ($order == true) { $return = -1; }; break;
case "true": if ($order == false) { $return = -1; }; break;
case "notempty": if ($order == "") { $return = -1; }; break;
case "userexists": if (posix_getpwnam($order) === false) { $return = -1; }; break;
case "groupexists": if (posix_getgrnam($order) === false) { $return = -1; }; break;
case "usernotexists": if (is_array(posix_getpwnam($order))) { $return = -1; }; break;
case "groupnotexists": if (is_array(posix_getgrnam($order))) { $return = -1; }; break;
case "userexists": if (posix_getpwuid($order) === false) { $return = -1; }; break;
case "groupexists": if (posix_getgrgid($order) === false) { $return = -1; }; break;
case "usernotexists": if (is_array(posix_getpwuid($order))) { $return = -1; }; break;
case "groupnotexists": if (is_array(posix_getgrgid($order))) { $return = -1; }; break;
case "usernamenotexists": if (is_array(posix_getpwnam($order))) { $return = -1; }; break;
case "equals": $return = (isset($attributes['value']) && $attributes['value'] == $order ? 0 : -1); break;
}
return $return;

View File

@@ -323,15 +323,18 @@ class Database {
$sql_root = array(0 => array('caption' => 'Default', 'host' => $sql['host'], 'socket' => (isset($sql['socket']) ? $sql['socket'] : null), 'user' => $sql['root_user'], 'password' => $sql['root_password']));
}
$substitutions = array(
$sql['password'] => 'DB_UNPRIV_PWD',
$sql_root[0]['password'] => 'DB_ROOT_PWD',
);
// hide username/password in messages
$error_message = $error->getMessage();
$error_trace = $error->getTraceAsString();
// error-message
$error_message = str_replace($sql['password'], 'DB_UNPRIV_PWD', $error_message);
$error_message = str_replace($sql_root[0]['password'], 'DB_ROOT_PWD', $error_message);
$error_message = self::_substitute($error_message, $substitutions);
// error-trace
$error_trace = str_replace($sql['password'], 'DB_UNPRIV_PWD', $error_trace);
$error_trace = str_replace($sql_root[0]['password'], 'DB_ROOT_PWD', $error_trace);
$error_trace = self::_substitute($error_trace, $substitutions);
if ($error->getCode() == 2003) {
$error_message = "Unable to connect to database. Either the mysql-server is not running or your user/password is wrong.";
@@ -365,6 +368,9 @@ class Database {
@fclose($errlog);
if ($showerror) {
if (empty($sql['debug'])) {
$error_trace = '';
}
// fallback
$theme = 'Sparkle';
@@ -402,4 +408,58 @@ class Database {
die("We are sorry, but a MySQL - error occurred. The administrator may find more information in the syslog");
}
}
/**
* Substitutes patterns in content.
*
* @param string $content
* @param array $substitutions
* @param int $minLength
* @return string
*/
private static function _substitute($content, array $substitutions, $minLength = 6) {
$replacements = array();
foreach ($substitutions as $search => $replace) {
$replacements = $replacements + self::_createShiftedSubstitutions($search, $replace, $minLength);
}
$content = str_replace(
array_keys($replacements),
array_values($replacements),
$content
);
return $content;
}
/**
* Creates substitutions, shifted by length, e.g.
*
* _createShiftedSubstitutions('abcdefgh', 'value', 4):
* array(
* 'abcdefgh' => 'value',
* 'abcdefg' => 'value',
* 'abcdef' => 'value',
* 'abcde' => 'value',
* 'abcd' => 'value',
* )
*
* @param string $search
* @param string $replace
* @param int $minLength
* @return array
*/
private static function _createShiftedSubstitutions($search, $replace, $minLength) {
$substitutions = array();
$length = strlen($search);
if ($length > $minLength) {
for ($shiftedLength = $length; $shiftedLength >= $minLength; $shiftedLength--) {
$substitutions[substr($search, 0, $shiftedLength)] = $replace;
}
}
return $substitutions;
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Classes
*
*/
class DnsEntry
{
public $record;
public $ttl;
public $class = 'IN';
public $type;
public $priority;
public $content;
public function __construct($record = '', $type = 'A', $content = null, $prio = 0, $ttl = 18000, $class = 'IN')
{
$this->record = $record;
$this->type = $type;
$this->content = $content;
$this->priority = $prio;
$this->ttl = $ttl;
$this->class = $class;
}
public function __toString()
{
$result = $this->record . "\t" . $this->ttl . "\t" . $this->class . "\t" . $this->type . "\t" . (($this->priority >= 0 && ($this->type == 'MX' || $this->type == 'SRV')) ? $this->priority . "\t" : "") . $this->content . PHP_EOL;
return $result;
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Classes
*
*/
class DnsZone
{
public $ttl;
public $origin;
public $serial;
public $records;
public function __construct($ttl = 18000, $origin = '', $serial = '', $records = null)
{
$this->ttl = $ttl;
$this->origin = $origin;
$this->serial = $serial;
$this->records = $records;
}
public function __toString()
{
$_zonefile = "\$TTL " . $this->ttl . PHP_EOL;
$_zonefile .= "\$ORIGIN " . $this->origin . "." . PHP_EOL;
if (! empty($this->records)) {
foreach ($this->records as $record) {
$_zonefile .= (string) $record;
}
}
return $_zonefile;
}
}

View File

@@ -3461,3 +3461,4 @@ class idna_convert {
)
);
}

View File

@@ -17,11 +17,12 @@
*
*/
// Source for updates: https://github.com/phlylabs/idna-convert.git
/**
* Class for wrapping a specific idna conversion class and offering a standard interface
* @package Functions
*/
class idna_convert_wrapper
{
/**
@@ -37,7 +38,13 @@ class idna_convert_wrapper
public function __construct()
{
$this->idna_converter = new idna_convert();
// Instantiate it
if (version_compare("5.6.0", PHP_VERSION, ">=")) {
$this->idna_converter = new idna_convert(array('idn_version' => '2008', 'encode_german_sz' => false));
} else {
// use this when using new version of IdnaConverter (which does not work yet)
$this->idna_converter = new Mso\IdnaConvert\IdnaConvert();
}
}
/**
@@ -52,7 +59,12 @@ class idna_convert_wrapper
public function encode($to_encode)
{
return $this->_do_action('encode', $to_encode);
if (version_compare("5.6.0", PHP_VERSION, ">=")) {
return $this->_do_action('encode', $to_encode);
} else {
$to_encode = $this->is_utf8($to_encode) ? $to_encode : utf8_encode($to_encode);
return $this->idna_converter->encode($to_encode);
}
}
/**
@@ -67,7 +79,48 @@ class idna_convert_wrapper
public function decode($to_decode)
{
return $this->_do_action('decode', $to_decode);
if (version_compare("5.6.0", PHP_VERSION, ">=")) {
return $this->_do_action('decode', $to_decode);
} else {
return $this->idna_converter->decode($to_decode);
}
}
/**
* check whether a string is utf-8 encoded or not
*
* @param string $string
*
* @return boolean
*/
public function is_utf8($string = null) {
if (function_exists("mb_detect_encoding")) {
if (mb_detect_encoding($string, 'UTF-8, ISO-8859-1') === 'UTF-8') {
return true;
}
return false;
}
$strlen = strlen($string);
for ($i = 0; $i < $strlen; $i ++) {
$ord = ord($string[$i]);
if ($ord < 0x80)
continue; // 0bbbbbbb
elseif (($ord & 0xE0) === 0xC0 && $ord > 0xC1)
$n = 1; // 110bbbbb (exkl C0-C1)
elseif (($ord & 0xF0) === 0xE0)
$n = 2; // 1110bbbb
elseif (($ord & 0xF8) === 0xF0 && $ord < 0xF5)
$n = 3; // 11110bbb (exkl F5-FF)
else
return false; // ungültiges UTF-8-Zeichen
for ($c = 0; $c < $n; $c ++) // $n Folgebytes? // 10bbbbbb
if (++ $i === $strlen || (ord($string[$i]) & 0xC0) !== 0x80)
// ungültiges UTF-8-Zeichen
return false;
}
// kein ungültiges UTF-8-Zeichen gefunden
return true;
}
/**
@@ -141,5 +194,3 @@ class idna_convert_wrapper
return implode($sepchar, $strings);
}
}
?>

View File

@@ -0,0 +1,186 @@
<?php
/**
* Encoding Helper - convert various encodings to / from UTF-8
* @package IDNA Convert
* @subpackage charset transcoding
* @author Matthias Sommerfeld, <mso@phlylabs.de>
* @copyright 2003-2016 phlyLabs Berlin, http://phlylabs.de
* @version 1.0.0 2016-01-08
*/
namespace Mso\IdnaConvert;
class EncodingHelper
{
/**
* Convert a string from any of various encodings to UTF-8
*
* @param string $string String to encode
*[@param string $encoding Encoding; Default: ISO-8859-1]
*[@param bool $safe_mode Safe Mode: if set to TRUE, the original string is retunred on errors]
* @return string|false The encoded string or false on failure
* @since 0.0.1
*/
public static function toUtf8($string = '', $encoding = 'iso-8859-1', $safe_mode = false)
{
$safe = ($safe_mode) ? $string : false;
if (strtoupper($encoding) == 'UTF-8' || strtoupper($encoding) == 'UTF8') {
return $string;
}
if (strtoupper($encoding) == 'ISO-8859-1') {
return \utf8_encode($string);
} if (strtoupper($encoding) == 'WINDOWS-1252') {
return \utf8_encode(self::map_w1252_iso8859_1($string));
}
if (strtoupper($encoding) == 'UNICODE-1-1-UTF-7') {
$encoding = 'utf-7';
}
if (function_exists('mb_convert_encoding')) {
$conv = @mb_convert_encoding($string, 'UTF-8', strtoupper($encoding));
if ($conv) {
return $conv;
}
}
if (function_exists('iconv')) {
$conv = @iconv(strtoupper($encoding), 'UTF-8', $string);
if ($conv) {
return $conv;
}
}
if (function_exists('libiconv')) {
$conv = @libiconv(strtoupper($encoding), 'UTF-8', $string);
if ($conv) {
return $conv;
}
}
return $safe;
}
/**
* Convert a string from UTF-8 to any of various encodings
*
* @param string $string String to decode
*[@param string $encoding Encoding; Default: ISO-8859-1]
*[@param bool $safe_mode Safe Mode: if set to TRUE, the original string is retunred on errors]
* @return string|false The decoded string or false on failure
* @since 0.0.1
*/
public static function fromUtf8($string = '', $encoding = 'iso-8859-1', $safe_mode = false)
{
$safe = ($safe_mode) ? $string : false;
if (!$encoding) $encoding = 'ISO-8859-1';
if (strtoupper($encoding) == 'UTF-8' || strtoupper($encoding) == 'UTF8') {
return $string;
}
if (strtoupper($encoding) == 'ISO-8859-1') {
return utf8_decode($string);
}
if (strtoupper($encoding) == 'WINDOWS-1252') {
return self::map_iso8859_1_w1252(utf8_decode($string));
}
if (strtoupper($encoding) == 'UNICODE-1-1-UTF-7') {
$encoding = 'utf-7';
}
if (function_exists('mb_convert_encoding')) {
$conv = @mb_convert_encoding($string, strtoupper($encoding), 'UTF-8');
if ($conv) {
return $conv;
}
}
if (function_exists('iconv')) {
$conv = @iconv('UTF-8', strtoupper($encoding), $string);
if ($conv) {
return $conv;
}
}
if (function_exists('libiconv')) {
$conv = @libiconv('UTF-8', strtoupper($encoding), $string);
if ($conv) {
return $conv;
}
}
return $safe;
}
/**
* Special treatment for our guys in Redmond
* Windows-1252 is basically ISO-8859-1 -- with some exceptions, which get accounted for here
*
* @param string $string Your input in Win1252
* @return string The resulting ISO-8859-1 string
* @since 0.0.1
*/
protected static function map_w1252_iso8859_1($string = '')
{
if ($string == '') {
return '';
}
$return = '';
for ($i = 0; $i < strlen($string); ++$i) {
$c = ord($string{$i});
switch ($c) {
case 129: $return .= chr(252); break;
case 132: $return .= chr(228); break;
case 142: $return .= chr(196); break;
case 148: $return .= chr(246); break;
case 153: $return .= chr(214); break;
case 154: $return .= chr(220); break;
case 225: $return .= chr(223); break;
default: $return .= chr($c);
}
}
return $return;
}
/**
* Special treatment for our guys in Redmond
* Windows-1252 is basically ISO-8859-1 -- with some exceptions, which get accounted for here
*
* @param string $string Your input in ISO-8859-1
* @return string The resulting Win1252 string
* @since 0.0.1
*/
protected static function map_iso8859_1_w1252($string = '')
{
if ($string == '') {
return '';
}
$return = '';
for ($i = 0; $i < strlen($string); ++$i) {
$c = ord($string{$i});
switch ($c) {
case 196: $return .= chr(142); break;
case 214: $return .= chr(153); break;
case 220: $return .= chr(154); break;
case 223: $return .= chr(225); break;
case 228: $return .= chr(132); break;
case 246: $return .= chr(148); break;
case 252: $return .= chr(129); break;
default: $return .= chr($c);
}
}
return $return;
}
}

View File

@@ -0,0 +1,405 @@
<?php
// {{{ license
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
//
// +----------------------------------------------------------------------+
// | This library is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as |
// | published by the Free Software Foundation; either version 2.1 of the |
// | License, or (at your option) any later version. |
// | |
// | This library is distributed in the hope that it will be useful, but |
// | WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
// | Lesser General Public License for more details. |
// | |
// | You should have received a copy of the GNU Lesser General Public |
// | License along with this library; if not, write to the Free Software |
// | Foundation, Inc., 51 Franklin St, Boston, MA 02110, United States |
// +----------------------------------------------------------------------+
//
// }}}
/**
* Encode/decode Internationalized Domain Names.
*
* The class allows to convert internationalized domain names
* (see RFC 3490 for details) as they can be used with various registries worldwide
* to be translated between their original (localized) form and their encoded form
* as it will be used in the DNS (Domain Name System).
*
* The class provides two public methods, encode() and decode(), which do exactly
* what you would expect them to do. You are allowed to use complete domain names,
* simple strings and complete email addresses as well. That means, that you might
* use any of the following notations:
*
* - www.nörgler.com
* - xn--nrgler-wxa
* - xn--brse-5qa.xn--knrz-1ra.info
*
* Unicode input might be given as either UTF-8 string, UCS-4 string or UCS-4 array.
* Unicode output is available in the same formats.
* You can select your preferred format via {@link set_paramter()}.
*
* ACE input and output is always expected to be ASCII.
*
* @author Matthias Sommerfeld <mso@phlylabs.de>
* @copyright 2004-2016 phlyLabs Berlin, http://phlylabs.de
* @version 1.0.1-dev 2016-01-12
*/
namespace Mso\IdnaConvert;
class IdnaConvert {
const Version = '1.1.0';
const SubVersion = 'main';
// Internal settings, do not touch!
protected $encoding = 'utf8'; // Default input charset is UTF-8
protected $strictMode = false; // Behave strict or not
protected $idnVersion = '2008'; // Can be either 2003 (old) or 2008 (default)
protected $NamePrepData = null;
protected $UnicodeTranscoder = null;
/**
* the constructor
*
* @param array|null $params Parameters to control the class' behaviour
* @since 0.5.2
*/
public function __construct($params = null)
{
$this->UnicodeTranscoder = new UnicodeTranscoder();
// Kept for backwarsds compatibility. Consider using the setter methods instead.
if (!empty($params) && is_array($params)) {
if (isset($params['encoding'])) {
$this->setEncoding($params['encoding']);
}
if (isset($params['idn_version'])) {
$this->setIdnVersion($params['idn_version']);
}
if (isset($params['strict_mode'])) {
$this->setStrictMode($params['strict_mode']);
}
}
$this->setIdnVersion($this->idnVersion);
}
public function getClassVersion()
{
return self::Version.'-'.self::SubVersion;
}
/**
* @return string
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* @param string $encoding
*/
public function setEncoding($encoding)
{
switch ($encoding) {
case 'utf8':
case 'ucs4_string':
case 'ucs4_array':
$this->encoding = $encoding;
break;
default:
throw new \InvalidArgumentException(sprintf('Invalid encoding %s', $encoding));
}
}
/**
* @return boolean
*/
public function isStrictMode()
{
return $this->strictMode;
}
/**
* @param boolean $strictMode
*/
public function setStrictMode($strictMode)
{
$this->strictMode = ($strictMode) ? true : false;
}
/**
* @return int
*/
public function getIdnVersion()
{
return $this->idnVersion;
}
/**
* @param int $idnVersion
*/
public function setIdnVersion($idnVersion)
{
if (in_array($idnVersion, ['2003', '2008'])) {
if (is_null($this->NamePrepData) || $idnVersion != $this->idnVersion) {
$this->NamePrepData = null; // Ought to destroy the object's reference
// Re-instantiate with different data set
$this->NamePrepData = ($idnVersion == 2003)
? new NamePrepData2003()
: new NamePrepData();
}
$this->idnVersion = $idnVersion;
} else {
throw new \InvalidArgumentException(sprintf('Invalid IDN version %d', $idnVersion));
}
}
/**
* Decode a given ACE domain name
* @param string $input Domain name (ACE string)
* [@param string $one_time_encoding Desired output encoding]
* @return string Decoded Domain name (UTF-8 or UCS-4)
*/
public function decode($input, $one_time_encoding = null)
{
$punyCode = $this->punycodeFactory();
// Optionally set
if ($one_time_encoding) {
switch ($one_time_encoding) {
case 'utf8':
case 'ucs4_string':
case 'ucs4_array':
break;
default:
throw new \InvalidArgumentException(sprintf('Invalid encoding %s', $one_time_encoding));
}
}
// Make sure to drop any newline characters around
$input = trim($input);
// Negotiate input and try to determine, whether it is a plain string,
// an email address or something like a complete URL
if (strpos($input, '@')) { // Maybe it is an email address
// No no in strict mode
if ($this->strictMode) {
throw new \InvalidArgumentException('Only individual domain name parts can be handled in strict mode');
}
list ($email_pref, $input) = explode('@', $input, 2);
$arr = explode('.', $input);
foreach ($arr as $k => $v) {
$conv = $punyCode->decode($v);
if ($conv) {
$arr[$k] = $conv;
}
}
$input = join('.', $arr);
$arr = explode('.', $email_pref);
foreach ($arr as $k => $v) {
$conv = $punyCode->decode($v);
if ($conv) {
$arr[$k] = $conv;
}
}
$email_pref = join('.', $arr);
$return = $email_pref . '@' . $input;
} elseif (preg_match('![:\./]!', $input)) { // Or a complete domain name (with or without paths / parameters)
// No no in strict mode
if ($this->strictMode) {
throw new \InvalidArgumentException('Only individual domain name parts can be handled in strict mode');
}
$parsed = parse_url($input);
if (isset($parsed['host'])) {
$arr = explode('.', $parsed['host']);
foreach ($arr as $k => $v) {
$conv = $punyCode->decode($v);
if ($conv) {
$arr[$k] = $conv;
}
}
$parsed['host'] = join('.', $arr);
$return = (empty($parsed['scheme']) ? '' : $parsed['scheme'] . (strtolower($parsed['scheme']) == 'mailto' ? ':' : '://')).
(empty($parsed['user']) ? '' : $parsed['user'] . (empty($parsed['pass']) ? '' : ':' . $parsed['pass']) . '@').
$parsed['host'].
(empty($parsed['port']) ? '' : ':' . $parsed['port']).
(empty($parsed['path']) ? '' : $parsed['path']).
(empty($parsed['query']) ? '' : '?' . $parsed['query']).
(empty($parsed['fragment']) ? '' : '#' . $parsed['fragment']);
} else { // parse_url seems to have failed, try without it
$arr = explode('.', $input);
foreach ($arr as $k => $v) {
$conv = $punyCode->decode($v);
if ($conv) {
$arr[$k] = $conv;
}
}
$return = join('.', $arr);
}
} else { // Otherwise we consider it being a pure domain name string
$return = $punyCode->decode($input);
if (!$return) {
$return = $input;
}
}
// The output is UTF-8 by default, other output formats need conversion here
// If one time encoding is given, use this, else the objects property
$outputEncoding = ($one_time_encoding) ? $one_time_encoding : $this->encoding;
switch ($outputEncoding) {
case 'utf8':
return $return; // break;
case 'ucs4_string':
return $this->UnicodeTranscoder->convert($return, 'utf8', 'ucs4'); // break;
case 'ucs4_array':
return $this->UnicodeTranscoder->convert($return, 'utf8', 'ucs4array'); // break;
default:
throw new \InvalidArgumentException(sprintf('Unsupported output encoding %s', $outputEncoding));
}
}
/**
* Encode a given UTF-8 domain name
* @param string $decoded Domain name (UTF-8 or UCS-4)
* [@param boolean $one_time_encoding Desired input encoding, see {@link set_parameter}]
* @return string Encoded Domain name (ACE string)
*/
public function encode($decoded, $one_time_encoding = false)
{
// Forcing conversion of input to UCS4 array
// If one time encoding is given, use this, else the objects property
$inputEncoding = $one_time_encoding ? $one_time_encoding : $this->encoding;
switch ($inputEncoding) {
case 'utf8':
$decoded = $this->UnicodeTranscoder->convert($decoded, 'utf8', 'ucs4array');
break;
case 'ucs4_string':
$decoded = $this->UnicodeTranscoder->convert($decoded, 'ucs4', 'ucs4array');
break;
case 'ucs4_array':
break;
default:
throw new \InvalidArgumentException(sprintf('Unsupported input encoding %s', $inputEncoding));
}
// No input, no output, what else did you expect?
if (empty($decoded)) {
return '';
}
$punyCode = $this->punycodeFactory();
// Anchors for iteration
$last_begin = 0;
// Output string
$output = '';
foreach ($decoded as $k => $v) {
// Make sure to use just the plain dot
switch ($v) {
case 0x3002:
case 0xFF0E:
case 0xFF61:
$decoded[$k] = 0x2E;
// Right, no break here, the above are converted to dots anyway
// Stumbling across an anchoring character
case 0x2E:
case 0x2F:
case 0x3A:
case 0x3F:
case 0x40:
// Neither email addresses nor URLs allowed in strict mode
if ($this->strictMode) {
throw new \InvalidArgumentException('Neither email addresses nor URLs are allowed in strict mode.');
} else {
// Skip first char
if ($k) {
$encoded = $punyCode->encode(array_slice($decoded, $last_begin, (($k) - $last_begin)));
if ($encoded) {
$output .= $encoded;
} else {
$output .= $this->UnicodeTranscoder->convert(array_slice($decoded, $last_begin, (($k) - $last_begin)), 'ucs4array', 'utf8');
}
$output .= chr($decoded[$k]);
}
$last_begin = $k + 1;
}
}
}
// Catch the rest of the string
if ($last_begin) {
$inp_len = sizeof($decoded);
$encoded = $punyCode->encode(array_slice($decoded, $last_begin, (($inp_len) - $last_begin)));
if ($encoded) {
$output .= $encoded;
} else {
$output .= $this->UnicodeTranscoder->convert(array_slice($decoded, $last_begin, (($inp_len) - $last_begin)), 'ucs4array', 'utf8');
}
return $output;
} else {
if (false !== ($output = $punyCode->encode($decoded))) {
return $output;
} else {
return $this->UnicodeTranscoder->convert($decoded, 'ucs4array', 'utf8');
}
}
}
/**
* Mitigates a weakness of encode(), which cannot properly handle URIs but instead encodes their
* path or query components, too.
* @param string $uri Expects the URI as a UTF-8 (or ASCII) string
* @return string The URI encoded to Punycode, everything but the host component is left alone
* @since 0.6.4
*/
public function encodeUri($uri)
{
$parsed = parse_url($uri);
if (!isset($parsed['host'])) {
throw new \InvalidArgumentException('The given string does not look like a URI');
}
$arr = explode('.', $parsed['host']);
foreach ($arr as $k => $v) {
$conv = $this->encode($v, 'utf8');
if ($conv) {
$arr[$k] = $conv;
}
}
$parsed['host'] = join('.', $arr);
$return = (empty($parsed['scheme']) ? '' : $parsed['scheme'] . (strtolower($parsed['scheme']) == 'mailto' ? ':' : '://')).
(empty($parsed['user']) ? '' : $parsed['user'] . (empty($parsed['pass']) ? '' : ':' . $parsed['pass']) . '@').
$parsed['host'].
(empty($parsed['port']) ? '' : ':' . $parsed['port']).
(empty($parsed['path']) ? '' : $parsed['path']).
(empty($parsed['query']) ? '' : '?' . $parsed['query']).
(empty($parsed['fragment']) ? '' : '#' . $parsed['fragment']);
return $return;
}
/**
* The actual punycode class is rather costly, as well as passing the huge nameprep database around.
* This factory method allows to ease the burden when dealing with multiple IDN versions.
*
* @return \Mso\IdnaConvert\Punycode
*/
protected function punycodeFactory()
{
static $instances = [];
if (!isset($instances[$this->idnVersion])) {
$instances[$this->idnVersion] = new Punycode($this->NamePrepData, $this->UnicodeTranscoder);
}
return $instances[$this->idnVersion];
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,501 @@
<?php
namespace Mso\IdnaConvert;
class NamePrepData2003 extends NamePrepData implements NamePrepDataInterface
{
public $replaceMaps = [
0x41 => [0x61], 0x42 => [0x62], 0x43 => [0x63],
0x44 => [0x64], 0x45 => [0x65], 0x46 => [0x66], 0x47 => [0x67],
0x48 => [0x68], 0x49 => [0x69], 0x4A => [0x6A], 0x4B => [0x6B],
0x4C => [0x6C], 0x4D => [0x6D], 0x4E => [0x6E], 0x4F => [0x6F],
0x50 => [0x70], 0x51 => [0x71], 0x52 => [0x72], 0x53 => [0x73],
0x54 => [0x74], 0x55 => [0x75], 0x56 => [0x76], 0x57 => [0x77],
0x58 => [0x78], 0x59 => [0x79], 0x5A => [0x7A], 0xB5 => [0x3BC],
0xC0 => [0xE0], 0xC1 => [0xE1], 0xC2 => [0xE2], 0xC3 => [0xE3],
0xC4 => [0xE4], 0xC5 => [0xE5], 0xC6 => [0xE6], 0xC7 => [0xE7],
0xC8 => [0xE8], 0xC9 => [0xE9], 0xCA => [0xEA], 0xCB => [0xEB],
0xCC => [0xEC], 0xCD => [0xED], 0xCE => [0xEE], 0xCF => [0xEF],
0xD0 => [0xF0], 0xD1 => [0xF1], 0xD2 => [0xF2], 0xD3 => [0xF3],
0xD4 => [0xF4], 0xD5 => [0xF5], 0xD6 => [0xF6], 0xD8 => [0xF8],
0xD9 => [0xF9], 0xDA => [0xFA], 0xDB => [0xFB], 0xDC => [0xFC],
0xDD => [0xFD], 0xDE => [0xFE], 0xDF => [0x73, 0x73],
0x100 => [0x101], 0x102 => [0x103], 0x104 => [0x105],
0x106 => [0x107], 0x108 => [0x109], 0x10A => [0x10B],
0x10C => [0x10D], 0x10E => [0x10F], 0x110 => [0x111],
0x112 => [0x113], 0x114 => [0x115], 0x116 => [0x117],
0x118 => [0x119], 0x11A => [0x11B], 0x11C => [0x11D],
0x11E => [0x11F], 0x120 => [0x121], 0x122 => [0x123],
0x124 => [0x125], 0x126 => [0x127], 0x128 => [0x129],
0x12A => [0x12B], 0x12C => [0x12D], 0x12E => [0x12F],
0x130 => [0x69, 0x307], 0x132 => [0x133], 0x134 => [0x135],
0x136 => [0x137], 0x139 => [0x13A], 0x13B => [0x13C],
0x13D => [0x13E], 0x13F => [0x140], 0x141 => [0x142],
0x143 => [0x144], 0x145 => [0x146], 0x147 => [0x148],
0x149 => [0x2BC, 0x6E], 0x14A => [0x14B], 0x14C => [0x14D],
0x14E => [0x14F], 0x150 => [0x151], 0x152 => [0x153],
0x154 => [0x155], 0x156 => [0x157], 0x158 => [0x159],
0x15A => [0x15B], 0x15C => [0x15D], 0x15E => [0x15F],
0x160 => [0x161], 0x162 => [0x163], 0x164 => [0x165],
0x166 => [0x167], 0x168 => [0x169], 0x16A => [0x16B],
0x16C => [0x16D], 0x16E => [0x16F], 0x170 => [0x171],
0x172 => [0x173], 0x174 => [0x175], 0x176 => [0x177],
0x178 => [0xFF], 0x179 => [0x17A], 0x17B => [0x17C],
0x17D => [0x17E], 0x17F => [0x73], 0x181 => [0x253],
0x182 => [0x183], 0x184 => [0x185], 0x186 => [0x254],
0x187 => [0x188], 0x189 => [0x256], 0x18A => [0x257],
0x18B => [0x18C], 0x18E => [0x1DD], 0x18F => [0x259],
0x190 => [0x25B], 0x191 => [0x192], 0x193 => [0x260],
0x194 => [0x263], 0x196 => [0x269], 0x197 => [0x268],
0x198 => [0x199], 0x19C => [0x26F], 0x19D => [0x272],
0x19F => [0x275], 0x1A0 => [0x1A1], 0x1A2 => [0x1A3],
0x1A4 => [0x1A5], 0x1A6 => [0x280], 0x1A7 => [0x1A8],
0x1A9 => [0x283], 0x1AC => [0x1AD], 0x1AE => [0x288],
0x1AF => [0x1B0], 0x1B1 => [0x28A], 0x1B2 => [0x28B],
0x1B3 => [0x1B4], 0x1B5 => [0x1B6], 0x1B7 => [0x292],
0x1B8 => [0x1B9], 0x1BC => [0x1BD], 0x1C4 => [0x1C6],
0x1C5 => [0x1C6], 0x1C7 => [0x1C9], 0x1C8 => [0x1C9],
0x1CA => [0x1CC], 0x1CB => [0x1CC], 0x1CD => [0x1CE],
0x1CF => [0x1D0], 0x1D1 => [0x1D2], 0x1D3 => [0x1D4],
0x1D5 => [0x1D6], 0x1D7 => [0x1D8], 0x1D9 => [0x1DA],
0x1DB => [0x1DC], 0x1DE => [0x1DF], 0x1E0 => [0x1E1],
0x1E2 => [0x1E3], 0x1E4 => [0x1E5], 0x1E6 => [0x1E7],
0x1E8 => [0x1E9], 0x1EA => [0x1EB], 0x1EC => [0x1ED],
0x1EE => [0x1EF], 0x1F0 => [0x6A, 0x30C], 0x1F1 => [0x1F3],
0x1F2 => [0x1F3], 0x1F4 => [0x1F5], 0x1F6 => [0x195],
0x1F7 => [0x1BF], 0x1F8 => [0x1F9], 0x1FA => [0x1FB],
0x1FC => [0x1FD], 0x1FE => [0x1FF], 0x200 => [0x201],
0x202 => [0x203], 0x204 => [0x205], 0x206 => [0x207],
0x208 => [0x209], 0x20A => [0x20B], 0x20C => [0x20D],
0x20E => [0x20F], 0x210 => [0x211], 0x212 => [0x213],
0x214 => [0x215], 0x216 => [0x217], 0x218 => [0x219],
0x21A => [0x21B], 0x21C => [0x21D], 0x21E => [0x21F],
0x220 => [0x19E], 0x222 => [0x223], 0x224 => [0x225],
0x226 => [0x227], 0x228 => [0x229], 0x22A => [0x22B],
0x22C => [0x22D], 0x22E => [0x22F], 0x230 => [0x231],
0x232 => [0x233], 0x345 => [0x3B9], 0x37A => [0x20, 0x3B9],
0x386 => [0x3AC], 0x388 => [0x3AD], 0x389 => [0x3AE],
0x38A => [0x3AF], 0x38C => [0x3CC], 0x38E => [0x3CD],
0x38F => [0x3CE], 0x390 => [0x3B9, 0x308, 0x301],
0x391 => [0x3B1], 0x392 => [0x3B2], 0x393 => [0x3B3],
0x394 => [0x3B4], 0x395 => [0x3B5], 0x396 => [0x3B6],
0x397 => [0x3B7], 0x398 => [0x3B8], 0x399 => [0x3B9],
0x39A => [0x3BA], 0x39B => [0x3BB], 0x39C => [0x3BC],
0x39D => [0x3BD], 0x39E => [0x3BE], 0x39F => [0x3BF],
0x3A0 => [0x3C0], 0x3A1 => [0x3C1], 0x3A3 => [0x3C3],
0x3A4 => [0x3C4], 0x3A5 => [0x3C5], 0x3A6 => [0x3C6],
0x3A7 => [0x3C7], 0x3A8 => [0x3C8], 0x3A9 => [0x3C9],
0x3AA => [0x3CA], 0x3AB => [0x3CB], 0x3B0 => [0x3C5, 0x308, 0x301],
0x3C2 => [0x3C3], 0x3D0 => [0x3B2], 0x3D1 => [0x3B8],
0x3D2 => [0x3C5], 0x3D3 => [0x3CD], 0x3D4 => [0x3CB],
0x3D5 => [0x3C6], 0x3D6 => [0x3C0], 0x3D8 => [0x3D9],
0x3DA => [0x3DB], 0x3DC => [0x3DD], 0x3DE => [0x3DF],
0x3E0 => [0x3E1], 0x3E2 => [0x3E3], 0x3E4 => [0x3E5],
0x3E6 => [0x3E7], 0x3E8 => [0x3E9], 0x3EA => [0x3EB],
0x3EC => [0x3ED], 0x3EE => [0x3EF], 0x3F0 => [0x3BA],
0x3F1 => [0x3C1], 0x3F2 => [0x3C3], 0x3F4 => [0x3B8],
0x3F5 => [0x3B5], 0x400 => [0x450], 0x401 => [0x451],
0x402 => [0x452], 0x403 => [0x453], 0x404 => [0x454],
0x405 => [0x455], 0x406 => [0x456], 0x407 => [0x457],
0x408 => [0x458], 0x409 => [0x459], 0x40A => [0x45A],
0x40B => [0x45B], 0x40C => [0x45C], 0x40D => [0x45D],
0x40E => [0x45E], 0x40F => [0x45F], 0x410 => [0x430],
0x411 => [0x431], 0x412 => [0x432], 0x413 => [0x433],
0x414 => [0x434], 0x415 => [0x435], 0x416 => [0x436],
0x417 => [0x437], 0x418 => [0x438], 0x419 => [0x439],
0x41A => [0x43A], 0x41B => [0x43B], 0x41C => [0x43C],
0x41D => [0x43D], 0x41E => [0x43E], 0x41F => [0x43F],
0x420 => [0x440], 0x421 => [0x441], 0x422 => [0x442],
0x423 => [0x443], 0x424 => [0x444], 0x425 => [0x445],
0x426 => [0x446], 0x427 => [0x447], 0x428 => [0x448],
0x429 => [0x449], 0x42A => [0x44A], 0x42B => [0x44B],
0x42C => [0x44C], 0x42D => [0x44D], 0x42E => [0x44E],
0x42F => [0x44F], 0x460 => [0x461], 0x462 => [0x463],
0x464 => [0x465], 0x466 => [0x467], 0x468 => [0x469],
0x46A => [0x46B], 0x46C => [0x46D], 0x46E => [0x46F],
0x470 => [0x471], 0x472 => [0x473], 0x474 => [0x475],
0x476 => [0x477], 0x478 => [0x479], 0x47A => [0x47B],
0x47C => [0x47D], 0x47E => [0x47F], 0x480 => [0x481],
0x48A => [0x48B], 0x48C => [0x48D], 0x48E => [0x48F],
0x490 => [0x491], 0x492 => [0x493], 0x494 => [0x495],
0x496 => [0x497], 0x498 => [0x499], 0x49A => [0x49B],
0x49C => [0x49D], 0x49E => [0x49F], 0x4A0 => [0x4A1],
0x4A2 => [0x4A3], 0x4A4 => [0x4A5], 0x4A6 => [0x4A7],
0x4A8 => [0x4A9], 0x4AA => [0x4AB], 0x4AC => [0x4AD],
0x4AE => [0x4AF], 0x4B0 => [0x4B1], 0x4B2 => [0x4B3],
0x4B4 => [0x4B5], 0x4B6 => [0x4B7], 0x4B8 => [0x4B9],
0x4BA => [0x4BB], 0x4BC => [0x4BD], 0x4BE => [0x4BF],
0x4C1 => [0x4C2], 0x4C3 => [0x4C4], 0x4C5 => [0x4C6],
0x4C7 => [0x4C8], 0x4C9 => [0x4CA], 0x4CB => [0x4CC],
0x4CD => [0x4CE], 0x4D0 => [0x4D1], 0x4D2 => [0x4D3],
0x4D4 => [0x4D5], 0x4D6 => [0x4D7], 0x4D8 => [0x4D9],
0x4DA => [0x4DB], 0x4DC => [0x4DD], 0x4DE => [0x4DF],
0x4E0 => [0x4E1], 0x4E2 => [0x4E3], 0x4E4 => [0x4E5],
0x4E6 => [0x4E7], 0x4E8 => [0x4E9], 0x4EA => [0x4EB],
0x4EC => [0x4ED], 0x4EE => [0x4EF], 0x4F0 => [0x4F1],
0x4F2 => [0x4F3], 0x4F4 => [0x4F5], 0x4F8 => [0x4F9],
0x500 => [0x501], 0x502 => [0x503], 0x504 => [0x505],
0x506 => [0x507], 0x508 => [0x509], 0x50A => [0x50B],
0x50C => [0x50D], 0x50E => [0x50F], 0x531 => [0x561],
0x532 => [0x562], 0x533 => [0x563], 0x534 => [0x564],
0x535 => [0x565], 0x536 => [0x566], 0x537 => [0x567],
0x538 => [0x568], 0x539 => [0x569], 0x53A => [0x56A],
0x53B => [0x56B], 0x53C => [0x56C], 0x53D => [0x56D],
0x53E => [0x56E], 0x53F => [0x56F], 0x540 => [0x570],
0x541 => [0x571], 0x542 => [0x572], 0x543 => [0x573],
0x544 => [0x574], 0x545 => [0x575], 0x546 => [0x576],
0x547 => [0x577], 0x548 => [0x578], 0x549 => [0x579],
0x54A => [0x57A], 0x54B => [0x57B], 0x54C => [0x57C],
0x54D => [0x57D], 0x54E => [0x57E], 0x54F => [0x57F],
0x550 => [0x580], 0x551 => [0x581], 0x552 => [0x582],
0x553 => [0x583], 0x554 => [0x584], 0x555 => [0x585],
0x556 => [0x586], 0x587 => [0x565, 0x582], 0xE33 => [0xE4D, 0xE32],
0x1E00 => [0x1E01], 0x1E02 => [0x1E03], 0x1E04 => [0x1E05],
0x1E06 => [0x1E07], 0x1E08 => [0x1E09], 0x1E0A => [0x1E0B],
0x1E0C => [0x1E0D], 0x1E0E => [0x1E0F], 0x1E10 => [0x1E11],
0x1E12 => [0x1E13], 0x1E14 => [0x1E15], 0x1E16 => [0x1E17],
0x1E18 => [0x1E19], 0x1E1A => [0x1E1B], 0x1E1C => [0x1E1D],
0x1E1E => [0x1E1F], 0x1E20 => [0x1E21], 0x1E22 => [0x1E23],
0x1E24 => [0x1E25], 0x1E26 => [0x1E27], 0x1E28 => [0x1E29],
0x1E2A => [0x1E2B], 0x1E2C => [0x1E2D], 0x1E2E => [0x1E2F],
0x1E30 => [0x1E31], 0x1E32 => [0x1E33], 0x1E34 => [0x1E35],
0x1E36 => [0x1E37], 0x1E38 => [0x1E39], 0x1E3A => [0x1E3B],
0x1E3C => [0x1E3D], 0x1E3E => [0x1E3F], 0x1E40 => [0x1E41],
0x1E42 => [0x1E43], 0x1E44 => [0x1E45], 0x1E46 => [0x1E47],
0x1E48 => [0x1E49], 0x1E4A => [0x1E4B], 0x1E4C => [0x1E4D],
0x1E4E => [0x1E4F], 0x1E50 => [0x1E51], 0x1E52 => [0x1E53],
0x1E54 => [0x1E55], 0x1E56 => [0x1E57], 0x1E58 => [0x1E59],
0x1E5A => [0x1E5B], 0x1E5C => [0x1E5D], 0x1E5E => [0x1E5F],
0x1E60 => [0x1E61], 0x1E62 => [0x1E63], 0x1E64 => [0x1E65],
0x1E66 => [0x1E67], 0x1E68 => [0x1E69], 0x1E6A => [0x1E6B],
0x1E6C => [0x1E6D], 0x1E6E => [0x1E6F], 0x1E70 => [0x1E71],
0x1E72 => [0x1E73], 0x1E74 => [0x1E75], 0x1E76 => [0x1E77],
0x1E78 => [0x1E79], 0x1E7A => [0x1E7B], 0x1E7C => [0x1E7D],
0x1E7E => [0x1E7F], 0x1E80 => [0x1E81], 0x1E82 => [0x1E83],
0x1E84 => [0x1E85], 0x1E86 => [0x1E87], 0x1E88 => [0x1E89],
0x1E8A => [0x1E8B], 0x1E8C => [0x1E8D], 0x1E8E => [0x1E8F],
0x1E90 => [0x1E91], 0x1E92 => [0x1E93], 0x1E94 => [0x1E95],
0x1E96 => [0x68, 0x331], 0x1E97 => [0x74, 0x308], 0x1E98 => [0x77, 0x30A],
0x1E99 => [0x79, 0x30A], 0x1E9A => [0x61, 0x2BE], 0x1E9B => [0x1E61],
0x1EA0 => [0x1EA1], 0x1EA2 => [0x1EA3], 0x1EA4 => [0x1EA5],
0x1EA6 => [0x1EA7], 0x1EA8 => [0x1EA9], 0x1EAA => [0x1EAB],
0x1EAC => [0x1EAD], 0x1EAE => [0x1EAF], 0x1EB0 => [0x1EB1],
0x1EB2 => [0x1EB3], 0x1EB4 => [0x1EB5], 0x1EB6 => [0x1EB7],
0x1EB8 => [0x1EB9], 0x1EBA => [0x1EBB], 0x1EBC => [0x1EBD],
0x1EBE => [0x1EBF], 0x1EC0 => [0x1EC1], 0x1EC2 => [0x1EC3],
0x1EC4 => [0x1EC5], 0x1EC6 => [0x1EC7], 0x1EC8 => [0x1EC9],
0x1ECA => [0x1ECB], 0x1ECC => [0x1ECD], 0x1ECE => [0x1ECF],
0x1ED0 => [0x1ED1], 0x1ED2 => [0x1ED3], 0x1ED4 => [0x1ED5],
0x1ED6 => [0x1ED7], 0x1ED8 => [0x1ED9], 0x1EDA => [0x1EDB],
0x1EDC => [0x1EDD], 0x1EDE => [0x1EDF], 0x1EE0 => [0x1EE1],
0x1EE2 => [0x1EE3], 0x1EE4 => [0x1EE5], 0x1EE6 => [0x1EE7],
0x1EE8 => [0x1EE9], 0x1EEA => [0x1EEB], 0x1EEC => [0x1EED],
0x1EEE => [0x1EEF], 0x1EF0 => [0x1EF1], 0x1EF2 => [0x1EF3],
0x1EF4 => [0x1EF5], 0x1EF6 => [0x1EF7], 0x1EF8 => [0x1EF9],
0x1F08 => [0x1F00], 0x1F09 => [0x1F01], 0x1F0A => [0x1F02],
0x1F0B => [0x1F03], 0x1F0C => [0x1F04], 0x1F0D => [0x1F05],
0x1F0E => [0x1F06], 0x1F0F => [0x1F07], 0x1F18 => [0x1F10],
0x1F19 => [0x1F11], 0x1F1A => [0x1F12], 0x1F1B => [0x1F13],
0x1F1C => [0x1F14], 0x1F1D => [0x1F15], 0x1F28 => [0x1F20],
0x1F29 => [0x1F21], 0x1F2A => [0x1F22], 0x1F2B => [0x1F23],
0x1F2C => [0x1F24], 0x1F2D => [0x1F25], 0x1F2E => [0x1F26],
0x1F2F => [0x1F27], 0x1F38 => [0x1F30], 0x1F39 => [0x1F31],
0x1F3A => [0x1F32], 0x1F3B => [0x1F33], 0x1F3C => [0x1F34],
0x1F3D => [0x1F35], 0x1F3E => [0x1F36], 0x1F3F => [0x1F37],
0x1F48 => [0x1F40], 0x1F49 => [0x1F41], 0x1F4A => [0x1F42],
0x1F4B => [0x1F43], 0x1F4C => [0x1F44], 0x1F4D => [0x1F45],
0x1F50 => [0x3C5, 0x313], 0x1F52 => [0x3C5, 0x313, 0x300],
0x1F54 => [0x3C5, 0x313, 0x301], 0x1F56 => [0x3C5, 0x313, 0x342],
0x1F59 => [0x1F51], 0x1F5B => [0x1F53], 0x1F5D => [0x1F55],
0x1F5F => [0x1F57], 0x1F68 => [0x1F60], 0x1F69 => [0x1F61],
0x1F6A => [0x1F62], 0x1F6B => [0x1F63], 0x1F6C => [0x1F64],
0x1F6D => [0x1F65], 0x1F6E => [0x1F66], 0x1F6F => [0x1F67],
0x1F80 => [0x1F00, 0x3B9], 0x1F81 => [0x1F01, 0x3B9],
0x1F82 => [0x1F02, 0x3B9], 0x1F83 => [0x1F03, 0x3B9],
0x1F84 => [0x1F04, 0x3B9], 0x1F85 => [0x1F05, 0x3B9],
0x1F86 => [0x1F06, 0x3B9], 0x1F87 => [0x1F07, 0x3B9],
0x1F88 => [0x1F00, 0x3B9], 0x1F89 => [0x1F01, 0x3B9],
0x1F8A => [0x1F02, 0x3B9], 0x1F8B => [0x1F03, 0x3B9],
0x1F8C => [0x1F04, 0x3B9], 0x1F8D => [0x1F05, 0x3B9],
0x1F8E => [0x1F06, 0x3B9], 0x1F8F => [0x1F07, 0x3B9],
0x1F90 => [0x1F20, 0x3B9], 0x1F91 => [0x1F21, 0x3B9],
0x1F92 => [0x1F22, 0x3B9], 0x1F93 => [0x1F23, 0x3B9],
0x1F94 => [0x1F24, 0x3B9], 0x1F95 => [0x1F25, 0x3B9],
0x1F96 => [0x1F26, 0x3B9], 0x1F97 => [0x1F27, 0x3B9],
0x1F98 => [0x1F20, 0x3B9], 0x1F99 => [0x1F21, 0x3B9],
0x1F9A => [0x1F22, 0x3B9], 0x1F9B => [0x1F23, 0x3B9],
0x1F9C => [0x1F24, 0x3B9], 0x1F9D => [0x1F25, 0x3B9],
0x1F9E => [0x1F26, 0x3B9], 0x1F9F => [0x1F27, 0x3B9],
0x1FA0 => [0x1F60, 0x3B9], 0x1FA1 => [0x1F61, 0x3B9],
0x1FA2 => [0x1F62, 0x3B9], 0x1FA3 => [0x1F63, 0x3B9],
0x1FA4 => [0x1F64, 0x3B9], 0x1FA5 => [0x1F65, 0x3B9],
0x1FA6 => [0x1F66, 0x3B9], 0x1FA7 => [0x1F67, 0x3B9],
0x1FA8 => [0x1F60, 0x3B9], 0x1FA9 => [0x1F61, 0x3B9],
0x1FAA => [0x1F62, 0x3B9], 0x1FAB => [0x1F63, 0x3B9],
0x1FAC => [0x1F64, 0x3B9], 0x1FAD => [0x1F65, 0x3B9],
0x1FAE => [0x1F66, 0x3B9], 0x1FAF => [0x1F67, 0x3B9],
0x1FB2 => [0x1F70, 0x3B9], 0x1FB3 => [0x3B1, 0x3B9],
0x1FB4 => [0x3AC, 0x3B9], 0x1FB6 => [0x3B1, 0x342],
0x1FB7 => [0x3B1, 0x342, 0x3B9], 0x1FB8 => [0x1FB0],
0x1FB9 => [0x1FB1], 0x1FBA => [0x1F70], 0x1FBB => [0x1F71],
0x1FBC => [0x3B1, 0x3B9], 0x1FBE => [0x3B9],
0x1FC2 => [0x1F74, 0x3B9], 0x1FC3 => [0x3B7, 0x3B9],
0x1FC4 => [0x3AE, 0x3B9], 0x1FC6 => [0x3B7, 0x342],
0x1FC7 => [0x3B7, 0x342, 0x3B9], 0x1FC8 => [0x1F72],
0x1FC9 => [0x1F73], 0x1FCA => [0x1F74], 0x1FCB => [0x1F75],
0x1FCC => [0x3B7, 0x3B9], 0x1FD2 => [0x3B9, 0x308, 0x300],
0x1FD3 => [0x3B9, 0x308, 0x301], 0x1FD6 => [0x3B9, 0x342],
0x1FD7 => [0x3B9, 0x308, 0x342], 0x1FD8 => [0x1FD0],
0x1FD9 => [0x1FD1], 0x1FDA => [0x1F76],
0x1FDB => [0x1F77], 0x1FE2 => [0x3C5, 0x308, 0x300],
0x1FE3 => [0x3C5, 0x308, 0x301], 0x1FE4 => [0x3C1, 0x313],
0x1FE6 => [0x3C5, 0x342], 0x1FE7 => [0x3C5, 0x308, 0x342],
0x1FE8 => [0x1FE0], 0x1FE9 => [0x1FE1],
0x1FEA => [0x1F7A], 0x1FEB => [0x1F7B],
0x1FEC => [0x1FE5], 0x1FF2 => [0x1F7C, 0x3B9],
0x1FF3 => [0x3C9, 0x3B9], 0x1FF4 => [0x3CE, 0x3B9],
0x1FF6 => [0x3C9, 0x342], 0x1FF7 => [0x3C9, 0x342, 0x3B9],
0x1FF8 => [0x1F78], 0x1FF9 => [0x1F79], 0x1FFA => [0x1F7C],
0x1FFB => [0x1F7D], 0x1FFC => [0x3C9, 0x3B9],
0x20A8 => [0x72, 0x73], 0x2102 => [0x63], 0x2103 => [0xB0, 0x63],
0x2107 => [0x25B], 0x2109 => [0xB0, 0x66], 0x210B => [0x68],
0x210C => [0x68], 0x210D => [0x68], 0x2110 => [0x69],
0x2111 => [0x69], 0x2112 => [0x6C], 0x2115 => [0x6E],
0x2116 => [0x6E, 0x6F], 0x2119 => [0x70], 0x211A => [0x71],
0x211B => [0x72], 0x211C => [0x72], 0x211D => [0x72],
0x2120 => [0x73, 0x6D], 0x2121 => [0x74, 0x65, 0x6C],
0x2122 => [0x74, 0x6D], 0x2124 => [0x7A], 0x2126 => [0x3C9],
0x2128 => [0x7A], 0x212A => [0x6B], 0x212B => [0xE5],
0x212C => [0x62], 0x212D => [0x63], 0x2130 => [0x65],
0x2131 => [0x66], 0x2133 => [0x6D], 0x213E => [0x3B3],
0x213F => [0x3C0], 0x2145 => [0x64], 0x2160 => [0x2170],
0x2161 => [0x2171], 0x2162 => [0x2172], 0x2163 => [0x2173],
0x2164 => [0x2174], 0x2165 => [0x2175], 0x2166 => [0x2176],
0x2167 => [0x2177], 0x2168 => [0x2178], 0x2169 => [0x2179],
0x216A => [0x217A], 0x216B => [0x217B], 0x216C => [0x217C],
0x216D => [0x217D], 0x216E => [0x217E], 0x216F => [0x217F],
0x24B6 => [0x24D0], 0x24B7 => [0x24D1], 0x24B8 => [0x24D2],
0x24B9 => [0x24D3], 0x24BA => [0x24D4], 0x24BB => [0x24D5],
0x24BC => [0x24D6], 0x24BD => [0x24D7], 0x24BE => [0x24D8],
0x24BF => [0x24D9], 0x24C0 => [0x24DA], 0x24C1 => [0x24DB],
0x24C2 => [0x24DC], 0x24C3 => [0x24DD], 0x24C4 => [0x24DE],
0x24C5 => [0x24DF], 0x24C6 => [0x24E0], 0x24C7 => [0x24E1],
0x24C8 => [0x24E2], 0x24C9 => [0x24E3], 0x24CA => [0x24E4],
0x24CB => [0x24E5], 0x24CC => [0x24E6], 0x24CD => [0x24E7],
0x24CE => [0x24E8], 0x24CF => [0x24E9], 0x3371 => [0x68, 0x70, 0x61],
0x3373 => [0x61, 0x75], 0x3375 => [0x6F, 0x76],
0x3380 => [0x70, 0x61], 0x3381 => [0x6E, 0x61],
0x3382 => [0x3BC, 0x61], 0x3383 => [0x6D, 0x61],
0x3384 => [0x6B, 0x61], 0x3385 => [0x6B, 0x62],
0x3386 => [0x6D, 0x62], 0x3387 => [0x67, 0x62],
0x338A => [0x70, 0x66], 0x338B => [0x6E, 0x66],
0x338C => [0x3BC, 0x66], 0x3390 => [0x68, 0x7A],
0x3391 => [0x6B, 0x68, 0x7A], 0x3392 => [0x6D, 0x68, 0x7A],
0x3393 => [0x67, 0x68, 0x7A], 0x3394 => [0x74, 0x68, 0x7A],
0x33A9 => [0x70, 0x61], 0x33AA => [0x6B, 0x70, 0x61],
0x33AB => [0x6D, 0x70, 0x61], 0x33AC => [0x67, 0x70, 0x61],
0x33B4 => [0x70, 0x76], 0x33B5 => [0x6E, 0x76],
0x33B6 => [0x3BC, 0x76], 0x33B7 => [0x6D, 0x76],
0x33B8 => [0x6B, 0x76], 0x33B9 => [0x6D, 0x76],
0x33BA => [0x70, 0x77], 0x33BB => [0x6E, 0x77],
0x33BC => [0x3BC, 0x77], 0x33BD => [0x6D, 0x77],
0x33BE => [0x6B, 0x77], 0x33BF => [0x6D, 0x77],
0x33C0 => [0x6B, 0x3C9], 0x33C1 => [0x6D, 0x3C9], /*
0x33C2 => array(0x61, 0x2E, 0x6D, 0x2E), */
0x33C3 => [0x62, 0x71], 0x33C6 => [0x63, 0x2215, 0x6B, 0x67],
0x33C7 => [0x63, 0x6F, 0x2E], 0x33C8 => [0x64, 0x62],
0x33C9 => [0x67, 0x79], 0x33CB => [0x68, 0x70],
0x33CD => [0x6B, 0x6B], 0x33CE => [0x6B, 0x6D],
0x33D7 => [0x70, 0x68], 0x33D9 => [0x70, 0x70, 0x6D],
0x33DA => [0x70, 0x72], 0x33DC => [0x73, 0x76],
0x33DD => [0x77, 0x62], 0xFB00 => [0x66, 0x66],
0xFB01 => [0x66, 0x69], 0xFB02 => [0x66, 0x6C],
0xFB03 => [0x66, 0x66, 0x69], 0xFB04 => [0x66, 0x66, 0x6C],
0xFB05 => [0x73, 0x74], 0xFB06 => [0x73, 0x74],
0xFB13 => [0x574, 0x576], 0xFB14 => [0x574, 0x565],
0xFB15 => [0x574, 0x56B], 0xFB16 => [0x57E, 0x576],
0xFB17 => [0x574, 0x56D], 0xFF21 => [0xFF41],
0xFF22 => [0xFF42], 0xFF23 => [0xFF43], 0xFF24 => [0xFF44],
0xFF25 => [0xFF45], 0xFF26 => [0xFF46], 0xFF27 => [0xFF47],
0xFF28 => [0xFF48], 0xFF29 => [0xFF49], 0xFF2A => [0xFF4A],
0xFF2B => [0xFF4B], 0xFF2C => [0xFF4C], 0xFF2D => [0xFF4D],
0xFF2E => [0xFF4E], 0xFF2F => [0xFF4F], 0xFF30 => [0xFF50],
0xFF31 => [0xFF51], 0xFF32 => [0xFF52], 0xFF33 => [0xFF53],
0xFF34 => [0xFF54], 0xFF35 => [0xFF55], 0xFF36 => [0xFF56],
0xFF37 => [0xFF57], 0xFF38 => [0xFF58], 0xFF39 => [0xFF59],
0xFF3A => [0xFF5A], 0x10400 => [0x10428], 0x10401 => [0x10429],
0x10402 => [0x1042A], 0x10403 => [0x1042B], 0x10404 => [0x1042C],
0x10405 => [0x1042D], 0x10406 => [0x1042E], 0x10407 => [0x1042F],
0x10408 => [0x10430], 0x10409 => [0x10431], 0x1040A => [0x10432],
0x1040B => [0x10433], 0x1040C => [0x10434], 0x1040D => [0x10435],
0x1040E => [0x10436], 0x1040F => [0x10437], 0x10410 => [0x10438],
0x10411 => [0x10439], 0x10412 => [0x1043A], 0x10413 => [0x1043B],
0x10414 => [0x1043C], 0x10415 => [0x1043D], 0x10416 => [0x1043E],
0x10417 => [0x1043F], 0x10418 => [0x10440], 0x10419 => [0x10441],
0x1041A => [0x10442], 0x1041B => [0x10443], 0x1041C => [0x10444],
0x1041D => [0x10445], 0x1041E => [0x10446], 0x1041F => [0x10447],
0x10420 => [0x10448], 0x10421 => [0x10449], 0x10422 => [0x1044A],
0x10423 => [0x1044B], 0x10424 => [0x1044C], 0x10425 => [0x1044D],
0x1D400 => [0x61], 0x1D401 => [0x62], 0x1D402 => [0x63],
0x1D403 => [0x64], 0x1D404 => [0x65], 0x1D405 => [0x66],
0x1D406 => [0x67], 0x1D407 => [0x68], 0x1D408 => [0x69],
0x1D409 => [0x6A], 0x1D40A => [0x6B], 0x1D40B => [0x6C],
0x1D40C => [0x6D], 0x1D40D => [0x6E], 0x1D40E => [0x6F],
0x1D40F => [0x70], 0x1D410 => [0x71], 0x1D411 => [0x72],
0x1D412 => [0x73], 0x1D413 => [0x74], 0x1D414 => [0x75],
0x1D415 => [0x76], 0x1D416 => [0x77], 0x1D417 => [0x78],
0x1D418 => [0x79], 0x1D419 => [0x7A], 0x1D434 => [0x61],
0x1D435 => [0x62], 0x1D436 => [0x63], 0x1D437 => [0x64],
0x1D438 => [0x65], 0x1D439 => [0x66], 0x1D43A => [0x67],
0x1D43B => [0x68], 0x1D43C => [0x69], 0x1D43D => [0x6A],
0x1D43E => [0x6B], 0x1D43F => [0x6C], 0x1D440 => [0x6D],
0x1D441 => [0x6E], 0x1D442 => [0x6F], 0x1D443 => [0x70],
0x1D444 => [0x71], 0x1D445 => [0x72], 0x1D446 => [0x73],
0x1D447 => [0x74], 0x1D448 => [0x75], 0x1D449 => [0x76],
0x1D44A => [0x77], 0x1D44B => [0x78], 0x1D44C => [0x79],
0x1D44D => [0x7A], 0x1D468 => [0x61], 0x1D469 => [0x62],
0x1D46A => [0x63], 0x1D46B => [0x64], 0x1D46C => [0x65],
0x1D46D => [0x66], 0x1D46E => [0x67], 0x1D46F => [0x68],
0x1D470 => [0x69], 0x1D471 => [0x6A], 0x1D472 => [0x6B],
0x1D473 => [0x6C], 0x1D474 => [0x6D], 0x1D475 => [0x6E],
0x1D476 => [0x6F], 0x1D477 => [0x70], 0x1D478 => [0x71],
0x1D479 => [0x72], 0x1D47A => [0x73], 0x1D47B => [0x74],
0x1D47C => [0x75], 0x1D47D => [0x76], 0x1D47E => [0x77],
0x1D47F => [0x78], 0x1D480 => [0x79], 0x1D481 => [0x7A],
0x1D49C => [0x61], 0x1D49E => [0x63], 0x1D49F => [0x64],
0x1D4A2 => [0x67], 0x1D4A5 => [0x6A], 0x1D4A6 => [0x6B],
0x1D4A9 => [0x6E], 0x1D4AA => [0x6F], 0x1D4AB => [0x70],
0x1D4AC => [0x71], 0x1D4AE => [0x73], 0x1D4AF => [0x74],
0x1D4B0 => [0x75], 0x1D4B1 => [0x76], 0x1D4B2 => [0x77],
0x1D4B3 => [0x78], 0x1D4B4 => [0x79], 0x1D4B5 => [0x7A],
0x1D4D0 => [0x61], 0x1D4D1 => [0x62], 0x1D4D2 => [0x63],
0x1D4D3 => [0x64], 0x1D4D4 => [0x65], 0x1D4D5 => [0x66],
0x1D4D6 => [0x67], 0x1D4D7 => [0x68], 0x1D4D8 => [0x69],
0x1D4D9 => [0x6A], 0x1D4DA => [0x6B], 0x1D4DB => [0x6C],
0x1D4DC => [0x6D], 0x1D4DD => [0x6E], 0x1D4DE => [0x6F],
0x1D4DF => [0x70], 0x1D4E0 => [0x71], 0x1D4E1 => [0x72],
0x1D4E2 => [0x73], 0x1D4E3 => [0x74], 0x1D4E4 => [0x75],
0x1D4E5 => [0x76], 0x1D4E6 => [0x77], 0x1D4E7 => [0x78],
0x1D4E8 => [0x79], 0x1D4E9 => [0x7A], 0x1D504 => [0x61],
0x1D505 => [0x62], 0x1D507 => [0x64], 0x1D508 => [0x65],
0x1D509 => [0x66], 0x1D50A => [0x67], 0x1D50D => [0x6A],
0x1D50E => [0x6B], 0x1D50F => [0x6C], 0x1D510 => [0x6D],
0x1D511 => [0x6E], 0x1D512 => [0x6F], 0x1D513 => [0x70],
0x1D514 => [0x71], 0x1D516 => [0x73], 0x1D517 => [0x74],
0x1D518 => [0x75], 0x1D519 => [0x76], 0x1D51A => [0x77],
0x1D51B => [0x78], 0x1D51C => [0x79], 0x1D538 => [0x61],
0x1D539 => [0x62], 0x1D53B => [0x64], 0x1D53C => [0x65],
0x1D53D => [0x66], 0x1D53E => [0x67], 0x1D540 => [0x69],
0x1D541 => [0x6A], 0x1D542 => [0x6B], 0x1D543 => [0x6C],
0x1D544 => [0x6D], 0x1D546 => [0x6F], 0x1D54A => [0x73],
0x1D54B => [0x74], 0x1D54C => [0x75], 0x1D54D => [0x76],
0x1D54E => [0x77], 0x1D54F => [0x78], 0x1D550 => [0x79],
0x1D56C => [0x61], 0x1D56D => [0x62], 0x1D56E => [0x63],
0x1D56F => [0x64], 0x1D570 => [0x65], 0x1D571 => [0x66],
0x1D572 => [0x67], 0x1D573 => [0x68], 0x1D574 => [0x69],
0x1D575 => [0x6A], 0x1D576 => [0x6B], 0x1D577 => [0x6C],
0x1D578 => [0x6D], 0x1D579 => [0x6E], 0x1D57A => [0x6F],
0x1D57B => [0x70], 0x1D57C => [0x71], 0x1D57D => [0x72],
0x1D57E => [0x73], 0x1D57F => [0x74], 0x1D580 => [0x75],
0x1D581 => [0x76], 0x1D582 => [0x77], 0x1D583 => [0x78],
0x1D584 => [0x79], 0x1D585 => [0x7A], 0x1D5A0 => [0x61],
0x1D5A1 => [0x62], 0x1D5A2 => [0x63], 0x1D5A3 => [0x64],
0x1D5A4 => [0x65], 0x1D5A5 => [0x66], 0x1D5A6 => [0x67],
0x1D5A7 => [0x68], 0x1D5A8 => [0x69], 0x1D5A9 => [0x6A],
0x1D5AA => [0x6B], 0x1D5AB => [0x6C], 0x1D5AC => [0x6D],
0x1D5AD => [0x6E], 0x1D5AE => [0x6F], 0x1D5AF => [0x70],
0x1D5B0 => [0x71], 0x1D5B1 => [0x72], 0x1D5B2 => [0x73],
0x1D5B3 => [0x74], 0x1D5B4 => [0x75], 0x1D5B5 => [0x76],
0x1D5B6 => [0x77], 0x1D5B7 => [0x78], 0x1D5B8 => [0x79],
0x1D5B9 => [0x7A], 0x1D5D4 => [0x61], 0x1D5D5 => [0x62],
0x1D5D6 => [0x63], 0x1D5D7 => [0x64], 0x1D5D8 => [0x65],
0x1D5D9 => [0x66], 0x1D5DA => [0x67], 0x1D5DB => [0x68],
0x1D5DC => [0x69], 0x1D5DD => [0x6A], 0x1D5DE => [0x6B],
0x1D5DF => [0x6C], 0x1D5E0 => [0x6D], 0x1D5E1 => [0x6E],
0x1D5E2 => [0x6F], 0x1D5E3 => [0x70], 0x1D5E4 => [0x71],
0x1D5E5 => [0x72], 0x1D5E6 => [0x73], 0x1D5E7 => [0x74],
0x1D5E8 => [0x75], 0x1D5E9 => [0x76], 0x1D5EA => [0x77],
0x1D5EB => [0x78], 0x1D5EC => [0x79], 0x1D5ED => [0x7A],
0x1D608 => [0x61], 0x1D609 => [0x62], 0x1D60A => [0x63],
0x1D60B => [0x64], 0x1D60C => [0x65], 0x1D60D => [0x66],
0x1D60E => [0x67], 0x1D60F => [0x68], 0x1D610 => [0x69],
0x1D611 => [0x6A], 0x1D612 => [0x6B], 0x1D613 => [0x6C],
0x1D614 => [0x6D], 0x1D615 => [0x6E], 0x1D616 => [0x6F],
0x1D617 => [0x70], 0x1D618 => [0x71], 0x1D619 => [0x72],
0x1D61A => [0x73], 0x1D61B => [0x74], 0x1D61C => [0x75],
0x1D61D => [0x76], 0x1D61E => [0x77], 0x1D61F => [0x78],
0x1D620 => [0x79], 0x1D621 => [0x7A], 0x1D63C => [0x61],
0x1D63D => [0x62], 0x1D63E => [0x63], 0x1D63F => [0x64],
0x1D640 => [0x65], 0x1D641 => [0x66], 0x1D642 => [0x67],
0x1D643 => [0x68], 0x1D644 => [0x69], 0x1D645 => [0x6A],
0x1D646 => [0x6B], 0x1D647 => [0x6C], 0x1D648 => [0x6D],
0x1D649 => [0x6E], 0x1D64A => [0x6F], 0x1D64B => [0x70],
0x1D64C => [0x71], 0x1D64D => [0x72], 0x1D64E => [0x73],
0x1D64F => [0x74], 0x1D650 => [0x75], 0x1D651 => [0x76],
0x1D652 => [0x77], 0x1D653 => [0x78], 0x1D654 => [0x79],
0x1D655 => [0x7A], 0x1D670 => [0x61], 0x1D671 => [0x62],
0x1D672 => [0x63], 0x1D673 => [0x64], 0x1D674 => [0x65],
0x1D675 => [0x66], 0x1D676 => [0x67], 0x1D677 => [0x68],
0x1D678 => [0x69], 0x1D679 => [0x6A], 0x1D67A => [0x6B],
0x1D67B => [0x6C], 0x1D67C => [0x6D], 0x1D67D => [0x6E],
0x1D67E => [0x6F], 0x1D67F => [0x70], 0x1D680 => [0x71],
0x1D681 => [0x72], 0x1D682 => [0x73], 0x1D683 => [0x74],
0x1D684 => [0x75], 0x1D685 => [0x76], 0x1D686 => [0x77],
0x1D687 => [0x78], 0x1D688 => [0x79], 0x1D689 => [0x7A],
0x1D6A8 => [0x3B1], 0x1D6A9 => [0x3B2], 0x1D6AA => [0x3B3],
0x1D6AB => [0x3B4], 0x1D6AC => [0x3B5], 0x1D6AD => [0x3B6],
0x1D6AE => [0x3B7], 0x1D6AF => [0x3B8], 0x1D6B0 => [0x3B9],
0x1D6B1 => [0x3BA], 0x1D6B2 => [0x3BB], 0x1D6B3 => [0x3BC],
0x1D6B4 => [0x3BD], 0x1D6B5 => [0x3BE], 0x1D6B6 => [0x3BF],
0x1D6B7 => [0x3C0], 0x1D6B8 => [0x3C1], 0x1D6B9 => [0x3B8],
0x1D6BA => [0x3C3], 0x1D6BB => [0x3C4], 0x1D6BC => [0x3C5],
0x1D6BD => [0x3C6], 0x1D6BE => [0x3C7], 0x1D6BF => [0x3C8],
0x1D6C0 => [0x3C9], 0x1D6D3 => [0x3C3], 0x1D6E2 => [0x3B1],
0x1D6E3 => [0x3B2], 0x1D6E4 => [0x3B3], 0x1D6E5 => [0x3B4],
0x1D6E6 => [0x3B5], 0x1D6E7 => [0x3B6], 0x1D6E8 => [0x3B7],
0x1D6E9 => [0x3B8], 0x1D6EA => [0x3B9], 0x1D6EB => [0x3BA],
0x1D6EC => [0x3BB], 0x1D6ED => [0x3BC], 0x1D6EE => [0x3BD],
0x1D6EF => [0x3BE], 0x1D6F0 => [0x3BF], 0x1D6F1 => [0x3C0],
0x1D6F2 => [0x3C1], 0x1D6F3 => [0x3B8], 0x1D6F4 => [0x3C3],
0x1D6F5 => [0x3C4], 0x1D6F6 => [0x3C5], 0x1D6F7 => [0x3C6],
0x1D6F8 => [0x3C7], 0x1D6F9 => [0x3C8], 0x1D6FA => [0x3C9],
0x1D70D => [0x3C3], 0x1D71C => [0x3B1], 0x1D71D => [0x3B2],
0x1D71E => [0x3B3], 0x1D71F => [0x3B4], 0x1D720 => [0x3B5],
0x1D721 => [0x3B6], 0x1D722 => [0x3B7], 0x1D723 => [0x3B8],
0x1D724 => [0x3B9], 0x1D725 => [0x3BA], 0x1D726 => [0x3BB],
0x1D727 => [0x3BC], 0x1D728 => [0x3BD], 0x1D729 => [0x3BE],
0x1D72A => [0x3BF], 0x1D72B => [0x3C0], 0x1D72C => [0x3C1],
0x1D72D => [0x3B8], 0x1D72E => [0x3C3], 0x1D72F => [0x3C4],
0x1D730 => [0x3C5], 0x1D731 => [0x3C6], 0x1D732 => [0x3C7],
0x1D733 => [0x3C8], 0x1D734 => [0x3C9], 0x1D747 => [0x3C3],
0x1D756 => [0x3B1], 0x1D757 => [0x3B2], 0x1D758 => [0x3B3],
0x1D759 => [0x3B4], 0x1D75A => [0x3B5], 0x1D75B => [0x3B6],
0x1D75C => [0x3B7], 0x1D75D => [0x3B8], 0x1D75E => [0x3B9],
0x1D75F => [0x3BA], 0x1D760 => [0x3BB], 0x1D761 => [0x3BC],
0x1D762 => [0x3BD], 0x1D763 => [0x3BE], 0x1D764 => [0x3BF],
0x1D765 => [0x3C0], 0x1D766 => [0x3C1], 0x1D767 => [0x3B8],
0x1D768 => [0x3C3], 0x1D769 => [0x3C4], 0x1D76A => [0x3C5],
0x1D76B => [0x3C6], 0x1D76C => [0x3C7], 0x1D76D => [0x3C8],
0x1D76E => [0x3C9], 0x1D781 => [0x3C3], 0x1D790 => [0x3B1],
0x1D791 => [0x3B2], 0x1D792 => [0x3B3], 0x1D793 => [0x3B4],
0x1D794 => [0x3B5], 0x1D795 => [0x3B6], 0x1D796 => [0x3B7],
0x1D797 => [0x3B8], 0x1D798 => [0x3B9], 0x1D799 => [0x3BA],
0x1D79A => [0x3BB], 0x1D79B => [0x3BC], 0x1D79C => [0x3BD],
0x1D79D => [0x3BE], 0x1D79E => [0x3BF], 0x1D79F => [0x3C0],
0x1D7A0 => [0x3C1], 0x1D7A1 => [0x3B8], 0x1D7A2 => [0x3C3],
0x1D7A3 => [0x3C4], 0x1D7A4 => [0x3C5], 0x1D7A5 => [0x3C6],
0x1D7A6 => [0x3C7], 0x1D7A7 => [0x3C8], 0x1D7A8 => [0x3C9],
0x1D7BB => [0x3C3], 0x3F9 => [0x3C3], 0x1D2C => [0x61],
0x1D2D => [0xE6], 0x1D2E => [0x62], 0x1D30 => [0x64],
0x1D31 => [0x65], 0x1D32 => [0x1DD], 0x1D33 => [0x67],
0x1D34 => [0x68], 0x1D35 => [0x69], 0x1D36 => [0x6A],
0x1D37 => [0x6B], 0x1D38 => [0x6C], 0x1D39 => [0x6D],
0x1D3A => [0x6E], 0x1D3C => [0x6F], 0x1D3D => [0x223],
0x1D3E => [0x70], 0x1D3F => [0x72], 0x1D40 => [0x74],
0x1D41 => [0x75], 0x1D42 => [0x77], 0x213B => [0x66, 0x61, 0x78],
0x3250 => [0x70, 0x74, 0x65], 0x32CC => [0x68, 0x67],
0x32CE => [0x65, 0x76], 0x32CF => [0x6C, 0x74, 0x64],
0x337A => [0x69, 0x75], 0x33DE => [0x76, 0x2215, 0x6D],
0x33DF => [0x61, 0x2215, 0x6D]
];
}

View File

@@ -0,0 +1,7 @@
<?php
namespace Mso\IdnaConvert;
interface NamePrepDataInterface
{
}

View File

@@ -0,0 +1,555 @@
<?php
// {{{ license
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
//
// +----------------------------------------------------------------------+
// | This library is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as |
// | published by the Free Software Foundation; either version 2.1 of the |
// | License, or (at your option) any later version. |
// | |
// | This library is distributed in the hope that it will be useful, but |
// | WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
// | Lesser General Public License for more details. |
// | |
// | You should have received a copy of the GNU Lesser General Public |
// | License along with this library; if not, write to the Free Software |
// | Foundation, Inc., 51 Franklin St, Boston, MA 02110, United States |
// +----------------------------------------------------------------------+
//
// }}}
/*
* @author Matthias Sommerfeld <mso@phlylabs.de>
* @copyright 2004-2016 phlyLabs Berlin, http://phlylabs.de
* @version 1.0.1 2016-01-24
*/
namespace Mso\IdnaConvert;
class Punycode implements PunycodeInterface
{
// Internal settings, do not touch!
const punycodePrefix = 'xn--';
const invalidUcs = 0x80000000;
const maxUcs = 0x10FFFF;
const base = 36;
const tMin = 1;
const tMax = 26;
const skew = 38;
const damp = 700;
const initialBias = 72;
const initialN = 0x80;
const sBase = 0xAC00;
const lBase = 0x1100;
const vBase = 0x1161;
const tBase = 0x11A7;
const lCount = 19;
const vCount = 21;
const tCount = 28;
const nCount = 588; // vCount * tCount
const sCount = 11172; // lCount * tCount * vCount
const sLast = self::sBase + self::lCount * self::vCount * self::tCount;
protected static $isMbStringOverload = null;
protected $NamePrepData;
protected $UnicodeTranscoder;
/**
* the constructor
*
* @param $NamePrepData NamePrepDataInterface inject NamePrepData object
* @param $UnicodeTranscoder UnicodeTranscoderInterface inject Unicode Transcoder
* @since 0.5.2
*/
public function __construct(NamePrepDataInterface $NamePrepData, UnicodeTranscoderInterface $UnicodeTranscoder)
{
// populate mbstring overloading cache if not set
if (self::$isMbStringOverload === null) {
self::$isMbStringOverload = (extension_loaded('mbstring') && (ini_get('mbstring.func_overload') & 0x02) === 0x02);
}
$this->NamePrepData = $NamePrepData;
$this->UnicodeTranscoder = $UnicodeTranscoder;
}
/**
* Returns the used prefix for punycode-encoded strings
* @return string
*/
public function getPunycodePrefix()
{
return self::punycodePrefix;
}
/**
* Checks, whether or not the provided string is a valid punycode string
* @param string $encoded
* @return boolean
*/
public function validate($encoded) {
// Check for existence of the prefix
if (strpos($encoded, self::punycodePrefix) !== 0) {
return false;
}
// If nothing is left after the prefix, it is hopeless
if (strlen(trim($encoded)) <= strlen(self::punycodePrefix)) {
return false;
}
return true;
}
/**
* The actual decoding algorithm
* @param string
* @return mixed
*/
public function decode($encoded)
{
if (!$this->validate($encoded)) {
return false;
}
$decoded = [];
// Find last occurence of the delimiter
$delim_pos = strrpos($encoded, '-');
if ($delim_pos > self::byteLength(self::punycodePrefix)) {
for ($k = self::byteLength(self::punycodePrefix); $k < $delim_pos; ++$k) {
$decoded[] = ord($encoded{$k});
}
}
$deco_len = count($decoded);
$enco_len = self::byteLength($encoded);
// Wandering through the strings; init
$is_first = true;
$bias = self::initialBias;
$idx = 0;
$char = self::initialN;
for ($enco_idx = ($delim_pos) ? ($delim_pos + 1) : 0; $enco_idx < $enco_len; ++$deco_len) {
for ($old_idx = $idx, $w = 1, $k = self::base; 1; $k += self::base) {
$digit = $this->decodeDigit($encoded{$enco_idx++});
$idx += $digit * $w;
$t = ($k <= $bias) ? self::tMin :
(($k >= $bias + self::tMax) ? self::tMax : ($k - $bias));
if ($digit < $t) {
break;
}
$w = (int) ($w * (self::base - $t));
}
$bias = $this->adapt($idx - $old_idx, $deco_len + 1, $is_first);
$is_first = false;
$char += (int) ($idx / ($deco_len + 1));
$idx %= ($deco_len + 1);
if ($deco_len > 0) {
// Make room for the decoded char
for ($i = $deco_len; $i > $idx; $i--) {
$decoded[$i] = $decoded[($i - 1)];
}
}
$decoded[$idx++] = $char;
}
return $this->UnicodeTranscoder->ucs4array_utf8($decoded);
}
/**
* The actual encoding algorithm
* @param array $decoded
* @return mixed
*/
public function encode($decoded)
{
// We cannot encode a domain name containing the Punycode prefix
$extract = self::byteLength(self::punycodePrefix);
$check_pref = $this->UnicodeTranscoder->utf8_ucs4array(self::punycodePrefix);
$check_deco = array_slice($decoded, 0, $extract);
if ($check_pref == $check_deco) {
throw new \InvalidArgumentException('This is already a Punycode string');
}
// We will not try to encode strings consisting of basic code points only
$encodable = false;
foreach ($decoded as $k => $v) {
if ($v > 0x7a) {
$encodable = true;
break;
}
}
if (!$encodable) {
return false;
}
// Do NAMEPREP
$decoded = $this->namePrep($decoded);
if (!$decoded || !is_array($decoded)) {
return false; // NAMEPREP failed
}
$deco_len = count($decoded);
if (!$deco_len) {
return false; // Empty array
}
$codecount = 0; // How many chars have been consumed
$encoded = '';
// Copy all basic code points to output
for ($i = 0; $i < $deco_len; ++$i) {
$test = $decoded[$i];
// Will match [-0-9a-zA-Z]
if ((0x2F < $test && $test < 0x40)
|| (0x40 < $test && $test < 0x5B)
|| (0x60 < $test && $test <= 0x7B)
|| (0x2D == $test)) {
$encoded .= chr($decoded[$i]);
$codecount++;
}
}
if ($codecount == $deco_len) {
return $encoded; // All codepoints were basic ones
}
// Start with the prefix; copy it to output
$encoded = self::punycodePrefix . $encoded;
// If we have basic code points in output, add an hyphen to the end
if ($codecount) {
$encoded .= '-';
}
// Now find and encode all non-basic code points
$is_first = true;
$cur_code = self::initialN;
$bias = self::initialBias;
$delta = 0;
while ($codecount < $deco_len) {
// Find the smallest code point >= the current code point and
// remember the last ouccrence of it in the input
for ($i = 0, $next_code = self::maxUcs; $i < $deco_len; $i++) {
if ($decoded[$i] >= $cur_code && $decoded[$i] <= $next_code) {
$next_code = $decoded[$i];
}
}
$delta += ($next_code - $cur_code) * ($codecount + 1);
$cur_code = $next_code;
// Scan input again and encode all characters whose code point is $cur_code
for ($i = 0; $i < $deco_len; $i++) {
if ($decoded[$i] < $cur_code) {
$delta++;
} elseif ($decoded[$i] == $cur_code) {
for ($q = $delta, $k = self::base; 1; $k += self::base) {
$t = ($k <= $bias)
? self::tMin
: (($k >= $bias + self::tMax) ? self::tMax : $k - $bias);
if ($q < $t) {
break;
}
$encoded .= $this->encodeDigit(intval($t + (($q - $t) % (self::base - $t))));
$q = (int) (($q - $t) / (self::base - $t));
}
$encoded .= $this->encodeDigit($q);
$bias = $this->adapt($delta, $codecount + 1, $is_first);
$codecount++;
$delta = 0;
$is_first = false;
}
}
$delta++;
$cur_code++;
}
return $encoded;
}
/**
* Adapt the bias according to the current code point and position
* @param int $delta
* @param int $npoints
* @param int $is_first
* @return int
*/
protected function adapt($delta, $npoints, $is_first)
{
$delta = intval($is_first ? ($delta / self::damp) : ($delta / 2));
$delta += intval($delta / $npoints);
for ($k = 0; $delta > ((self::base - self::tMin) * self::tMax) / 2; $k += self::base) {
$delta = intval($delta / (self::base - self::tMin));
}
return intval($k + (self::base - self::tMin + 1) * $delta / ($delta + self::skew));
}
/**
* Encoding a certain digit
* @param int $d
* @return string
*/
protected function encodeDigit($d)
{
return chr($d + 22 + 75 * ($d < 26));
}
/**
* Decode a certain digit
* @param int $cp
* @return int
*/
protected function decodeDigit($cp)
{
$cp = ord($cp);
if ($cp - 48 < 10) {
return $cp - 22;
}
if ($cp - 65 < 26) {
return $cp - 65;
}
if ($cp - 97 < 26) {
return $cp - 97;
}
return self::base;
}
/**
* Do Nameprep according to RFC3491 and RFC3454
* @param array $input Unicode Characters
* @return string Unicode Characters, Nameprep'd
*/
protected function namePrep($input)
{
$output = [];
//
// Mapping
// Walking through the input array, performing the required steps on each of
// the input chars and putting the result into the output array
// While mapping required chars we apply the canonical ordering
foreach ($input as $v) {
// Map to nothing == skip that code point
if (in_array($v, $this->NamePrepData->mapToNothing)) {
continue;
}
// Try to find prohibited input
if (in_array($v, $this->NamePrepData->prohibit) || in_array($v, $this->NamePrepData->generalProhibited)) {
throw new \InvalidArgumentException(sprintf('NAMEPREP: Prohibited input U+%08X', $v));
}
foreach ($this->NamePrepData->prohibitRanges as $range) {
if ($range[0] <= $v && $v <= $range[1]) {
throw new \InvalidArgumentException(sprintf('NAMEPREP: Prohibited input U+%08X', $v));
}
}
if (0xAC00 <= $v && $v <= 0xD7AF) {
// Hangul syllable decomposition
foreach ($this->hangulDecompose($v) as $out) {
$output[] = (int) $out;
}
} elseif (isset($this->NamePrepData->replaceMaps[$v])) {
foreach ($this->applyCanonicalOrdering($this->NamePrepData->replaceMaps[$v]) as $out) {
$output[] = (int) $out;
}
} else {
$output[] = (int) $v;
}
}
// Before applying any Combining, try to rearrange any Hangul syllables
$output = $this->hangulCompose($output);
//
// Combine code points
//
$last_class = 0;
$last_starter = 0;
$out_len = count($output);
for ($i = 0; $i < $out_len; ++$i) {
$class = $this->getCombiningClass($output[$i]);
if ((!$last_class || $last_class > $class) && $class) {
// Try to match
$seq_len = $i - $last_starter;
$out = $this->combine(array_slice($output, $last_starter, $seq_len));
// On match: Replace the last starter with the composed character and remove
// the now redundant non-starter(s)
if ($out) {
$output[$last_starter] = $out;
if (count($out) != $seq_len) {
for ($j = $i + 1; $j < $out_len; ++$j) {
$output[$j - 1] = $output[$j];
}
unset($output[$out_len]);
}
// Rewind the for loop by one, since there can be more possible compositions
$i--;
$out_len--;
$last_class = ($i == $last_starter) ? 0 : $this->getCombiningClass($output[$i - 1]);
continue;
}
}
// The current class is 0
if (!$class) {
$last_starter = $i;
}
$last_class = $class;
}
return $output;
}
/**
* Decomposes a Hangul syllable
* (see http://www.unicode.org/unicode/reports/tr15/#Hangul
* @param integer 32bit UCS4 code point
* @return array Either Hangul Syllable decomposed or original 32bit value as one value array
*/
protected function hangulDecompose($char)
{
$sindex = (int) $char - self::sBase;
if ($sindex < 0 || $sindex >= self::sCount) {
return [$char];
}
$result = [];
$result[] = (int) self::lBase + $sindex / self::nCount;
$result[] = (int) self::vBase + ($sindex % self::nCount) / self::tCount;
$T = intval(self::tBase + $sindex % self::tCount);
if ($T != self::tBase) {
$result[] = $T;
}
return $result;
}
/**
* Ccomposes a Hangul syllable
* (see http://www.unicode.org/unicode/reports/tr15/#Hangul
* @param array $input Decomposed UCS4 sequence
* @return array UCS4 sequence with syllables composed
*/
protected function hangulCompose($input)
{
$inp_len = count($input);
if (!$inp_len) {
return [];
}
$result = [];
$last = (int) $input[0];
$result[] = $last; // copy first char from input to output
for ($i = 1; $i < $inp_len; ++$i) {
$char = (int) $input[$i];
$sindex = $last - self::sBase;
$lindex = $last - self::lBase;
$vindex = $char - self::vBase;
$tindex = $char - self::tBase;
// Find out, whether two current characters are LV and T
if (0 <= $sindex && $sindex < self::sCount && ($sindex % self::tCount == 0) && 0 <= $tindex && $tindex <= self::tCount) {
// create syllable of form LVT
$last += $tindex;
$result[(count($result) - 1)] = $last; // reset last
continue; // discard char
}
// Find out, whether two current characters form L and V
if (0 <= $lindex && $lindex < self::lCount && 0 <= $vindex && $vindex < self::vCount) {
// create syllable of form LV
$last = (int) self::sBase + ($lindex * self::vCount + $vindex) * self::tCount;
$result[(count($result) - 1)] = $last; // reset last
continue; // discard char
}
// if neither case was true, just add the character
$last = $char;
$result[] = $char;
}
return $result;
}
/**
* Returns the combining class of a certain wide char
* @param integer $char Wide char to check (32bit integer)
* @return integer Combining class if found, else 0
*/
protected function getCombiningClass($char)
{
return isset($this->NamePrepData->normalizeCombiningClasses[$char])
? $this->NamePrepData->normalizeCombiningClasses[$char]
: 0;
}
/**
* Applies the canonical ordering of a decomposed UCS4 sequence
* @param array $input Decomposed UCS4 sequence
* @return array Ordered USC4 sequence
*/
protected function applyCanonicalOrdering($input)
{
$swap = true;
$size = count($input);
while ($swap) {
$swap = false;
$last = $this->getCombiningClass(intval($input[0]));
for ($i = 0; $i < $size - 1; ++$i) {
$next = $this->getCombiningClass(intval($input[$i + 1]));
if ($next != 0 && $last > $next) {
// Move item leftward until it fits
for ($j = $i + 1; $j > 0; --$j) {
if ($this->getCombiningClass(intval($input[$j - 1])) <= $next) {
break;
}
$t = intval($input[$j]);
$input[$j] = intval($input[$j - 1]);
$input[$j - 1] = $t;
$swap = true;
}
// Reentering the loop looking at the old character again
$next = $last;
}
$last = $next;
}
}
return $input;
}
/**
* Do composition of a sequence of starter and non-starter
* @param array $input UCS4 Decomposed sequence
* @return array Ordered USC4 sequence
*/
protected function combine($input)
{
$inp_len = count($input);
if (0 == $inp_len) {
return false;
}
foreach ($this->NamePrepData->replaceMaps as $np_src => $np_target) {
if ($np_target[0] != $input[0]) {
continue;
}
if (count($np_target) != $inp_len) {
continue;
}
$hit = false;
foreach ($input as $k2 => $v2) {
if ($v2 == $np_target[$k2]) {
$hit = true;
} else {
$hit = false;
break;
}
}
if ($hit) {
return $np_src;
}
}
return false;
}
/**
* Gets the length of a string in bytes even if mbstring function
* overloading is turned on
*
* @param string $string the string for which to get the length.
* @return integer the length of the string in bytes.
*/
protected static function byteLength($string)
{
if (self::$isMbStringOverload) {
return mb_strlen($string, '8bit');
}
return strlen((binary) $string);
}
}

View File

@@ -0,0 +1,20 @@
<?php
/*
* @author Matthias Sommerfeld <mso@phlylabs.de>
* @copyright 2004-2016 phlyLabs Berlin, http://phlylabs.de
*/
namespace Mso\IdnaConvert;
interface PunycodeInterface
{
public function __construct(NamePrepDataInterface $NamePrepData, UnicodeTranscoderInterface $UCTC);
public function getPunycodePrefix();
public function decode($encoded);
public function encode($decoded);
}

View File

@@ -0,0 +1,358 @@
<?php
/**
* UCTC - The Unicode Transcoder
*
* Converts between various flavours of Unicode representations like UCS-4 or UTF-8
* Supported schemes:
* - UCS-4 Little Endian / Big Endian / Array (partially)
* - UTF-16 Little Endian / Big Endian (not yet)
* - UTF-8
* - UTF-7
* - UTF-7 IMAP (modified UTF-7)
*
* @package IdnaConvert
* @author Matthias Sommerfeld <mso@phlyLabs.de>
* @copyright 2003-2016 phlyLabs Berlin, http://phlylabs.de
* @version 0.1.1 2016-01-24
*/
namespace Mso\IdnaConvert;
class UnicodeTranscoder implements UnicodeTranscoderInterface
{
private static $mechs = ['ucs4', 'ucs4array', 'utf8', 'utf7', 'utf7imap'];
// unsupported yet: 'ucs4le', 'ucs4be', 'utf16', 'utf16le', 'utf16be'
private static $allow_overlong = false;
private static $safe_mode;
private static $safe_char;
/**
* The actual conversion routine
*
* @param mixed $data The data to convert, usually a string, array when converting from UCS-4 array
* @param string $from Original encoding of the data
* @param string $to Target encoding of the data
* @param bool $safe_mode SafeMode tries to correct invalid codepoints
* @param int $safe_char Unicode Codepoint as placeholder for all otherwise broken characters
* @return mixed False on failure, String or array on success, depending on target encoding
* @access public
* @throws \InvalidArgumentException
* @since 0.0.1
*/
public static function convert($data, $from, $to, $safe_mode = false, $safe_char = 0xFFFC)
{
self::$safe_mode = ($safe_mode) ? true : false;
self::$safe_char = ($safe_char) ? $safe_char : 0xFFFC;
if (self::$safe_mode) {
self::$allow_overlong = true;
}
if (!in_array($from, self::$mechs)) {
throw new \InvalidArgumentException(sprintf('Invalid input format %s', $from));
}
if (!in_array($to, self::$mechs)) {
throw new \InvalidArgumentException(sprintf('Invalid output format %s', $to));
}
if ($from != 'ucs4array') {
$methodName = $from.'_ucs4array';
$data = self::$methodName($data);
}
if ($to != 'ucs4array') {
$methodName = 'ucs4array_'.$to;
$data = self::$methodName($data);
}
return $data;
}
/**
* This converts an UTF-8 encoded string to its UCS-4 representation
*
* @param string $input The UTF-8 string to convert
* @return array Array of 32bit values representing each codepoint
* @throws \InvalidArgumentException
* @access public
*/
public static function utf8_ucs4array($input)
{
$start_byte = $next_byte = 0;
$output = [];
$out_len = 0;
$inp_len = self::byteLength($input);
$mode = 'next';
$test = 'none';
for ($k = 0; $k < $inp_len; ++$k) {
$v = ord($input{$k}); // Extract byte from input string
if ($v < 128) { // We found an ASCII char - put into stirng as is
$output[$out_len] = $v;
++$out_len;
if ('add' == $mode) {
if (self::$safe_mode) {
$output[$out_len - 2] = self::$safe_char;
$mode = 'next';
} else {
throw new \InvalidArgumentException(sprintf('Conversion from UTF-8 to UCS-4 failed: malformed input at byte %d', $k));
}
}
continue;
}
if ('next' == $mode) { // Try to find the next start byte; determine the width of the Unicode char
$start_byte = $v;
$mode = 'add';
$test = 'range';
if ($v >> 5 == 6) { // &110xxxxx 10xxxxx
$next_byte = 0; // Tells, how many times subsequent bitmasks must rotate 6bits to the left
$v = ($v - 192) << 6;
} elseif ($v >> 4 == 14) { // &1110xxxx 10xxxxxx 10xxxxxx
$next_byte = 1;
$v = ($v - 224) << 12;
} elseif ($v >> 3 == 30) { // &11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
$next_byte = 2;
$v = ($v - 240) << 18;
} elseif (self::$safe_mode) {
$mode = 'next';
$output[$out_len] = self::$safe_char;
++$out_len;
continue;
} else {
throw new \InvalidArgumentException(sprintf('This might be UTF-8, but I don\'t understand it at byte %d', $k));
}
if ($inp_len - $k - $next_byte < 2) {
$output[$out_len] = self::$safe_char;
$mode = 'no';
continue;
}
if ('add' == $mode) {
$output[$out_len] = (int)$v;
++$out_len;
continue;
}
}
if ('add' == $mode) {
if (!self::$allow_overlong && $test == 'range') {
$test = 'none';
if (($v < 0xA0 && $start_byte == 0xE0) || ($v < 0x90 && $start_byte == 0xF0) || ($v > 0x8F && $start_byte == 0xF4)) {
throw new \InvalidArgumentException(sprintf('Bogus UTF-8 character detected (out of legal range) at byte %d', $k));
}
}
if ($v >> 6 == 2) { // Bit mask must be 10xxxxxx
$v = ($v - 128) << ($next_byte * 6);
$output[($out_len - 1)] += $v;
--$next_byte;
} else {
if (self::$safe_mode) {
$output[$out_len - 1] = ord(self::$safe_char);
$k--;
$mode = 'next';
continue;
} else {
throw new \InvalidArgumentException(sprintf('Conversion from UTF-8 to UCS-4 failed: malformed input at byte %d', $k));
}
}
if ($next_byte < 0) {
$mode = 'next';
}
}
} // for
return $output;
}
/**
* Convert UCS-4 arary into UTF-8 string
* See utf8_ucs4array() for details
* @param $input array Array of UCS-4 codepoints
* @return string
* @access public
*/
public static function ucs4array_utf8($input)
{
$output = '';
foreach ($input as $k => $v) {
if ($v < 128) { // 7bit are transferred literally
$output .= chr($v);
} elseif ($v < (1 << 11)) { // 2 bytes
$output .= chr(192 + ($v >> 6)) . chr(128 + ($v & 63));
} elseif ($v < (1 << 16)) { // 3 bytes
$output .= chr(224 + ($v >> 12)) . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63));
} elseif ($v < (1 << 21)) { // 4 bytes
$output .= chr(240 + ($v >> 18)) . chr(128 + (($v >> 12) & 63)) . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63));
} elseif (self::$safe_mode) {
$output .= self::$safe_char;
} else {
throw new \InvalidArgumentException(sprintf('Conversion from UCS-4 to UTF-8 failed: malformed input at byte %d', $k));
}
}
return $output;
}
public static function utf7imap_ucs4array($input)
{
return self::utf7_ucs4array(str_replace(',', '/', $input), '&');
}
public static function utf7_ucs4array($input, $sc = '+')
{
$output = [];
$out_len = 0;
$inp_len = self::byteLength($input);
$mode = 'd';
$b64 = '';
for ($k = 0; $k < $inp_len; ++$k) {
$c = $input{$k};
// Ignore zero bytes
if (0 == ord($c)) {
continue;
}
if ('b' == $mode) {
// Sequence got terminated
if (!preg_match('![A-Za-z0-9/' . preg_quote($sc, '!') . ']!', $c)) {
if ('-' == $c) {
if ($b64 == '') {
$output[$out_len] = ord($sc);
$out_len++;
$mode = 'd';
continue;
}
}
$tmp = base64_decode($b64);
$tmp = substr($tmp, -1 * (strlen($tmp) % 2));
for ($i = 0; $i < strlen($tmp); $i++) {
if ($i % 2) {
$output[$out_len] += ord($tmp{$i});
$out_len++;
} else {
$output[$out_len] = ord($tmp{$i}) << 8;
}
}
$mode = 'd';
$b64 = '';
continue;
} else {
$b64 .= $c;
}
}
if ('d' == $mode) {
if ($sc == $c) {
$mode = 'b';
continue;
}
$output[$out_len] = ord($c);
$out_len++;
}
}
return $output;
}
public static function ucs4array_utf7imap($input)
{
return str_replace('/', ',', self::ucs4array_utf7($input, '&'));
}
public static function ucs4array_utf7($input, $sc = '+')
{
$output = '';
$mode = 'd';
$b64 = '';
while (true) {
$v = (!empty($input)) ? array_shift($input) : false;
$is_direct = (false !== $v) ? (0x20 <= $v && $v <= 0x7e && $v != ord($sc)) : true;
if ($mode == 'b') {
if ($is_direct) {
if ($b64 == chr(0) . $sc) {
$output .= $sc . '-';
$b64 = '';
} elseif ($b64) {
$output .= $sc . str_replace('=', '', base64_encode($b64)) . '-';
$b64 = '';
}
$mode = 'd';
} elseif (false !== $v) {
$b64 .= chr(($v >> 8) & 255) . chr($v & 255);
}
}
if ($mode == 'd' && false !== $v) {
if ($is_direct) {
$output .= chr($v);
} else {
$b64 = chr(($v >> 8) & 255) . chr($v & 255);
$mode = 'b';
}
}
if (false === $v && $b64 == '') break;
}
return $output;
}
/**
* Convert UCS-4 array into UCS-4 string (Little Endian at the moment)
* @param $input array UCS-4 code points
* @return string
* @access public
*/
public static function ucs4array_ucs4($input)
{
$output = '';
foreach ($input as $v) {
$output .= chr(($v >> 24) & 255) . chr(($v >> 16) & 255) . chr(($v >> 8) & 255) . chr($v & 255);
}
return $output;
}
/**
* Convert UCS-4 string (LE ar the moment) into UCS-4 array
* @param $input string UCS-4 LE string
* @return array
* @access public
*/
public static function ucs4_ucs4array($input)
{
$output = [];
$inp_len = self::byteLength($input);
// Input length must be dividable by 4
if ($inp_len % 4) {
throw new \InvalidArgumentException('Input UCS4 string is broken');
}
// Empty input - return empty output
if (!$inp_len) return $output;
for ($i = 0, $out_len = -1; $i < $inp_len; ++$i) {
if (!($i % 4)) { // Increment output position every 4 input bytes
$out_len++;
$output[$out_len] = 0;
}
$output[$out_len] += ord($input{$i}) << (8 * (3 - ($i % 4)));
}
return $output;
}
/**
* Gets the length of a string in bytes even if mbstring function
* overloading is turned on
*
* @param string $string the string for which to get the length.
* @return integer the length of the string in bytes.
*/
protected static function byteLength($string)
{
if ((extension_loaded('mbstring') && (ini_get('mbstring.func_overload') & 0x02) === 0x02)) {
return mb_strlen($string, '8bit');
}
return strlen((binary) $string);
}
}

View File

@@ -0,0 +1,40 @@
<?php
/**
* UCTC - The Unicode Transcoder
*
* Converts between various flavours of Unicode representations like UCS-4 or UTF-8
* Supported schemes:
* - UCS-4 Little Endian / Big Endian / Array (partially)
* - UTF-16 Little Endian / Big Endian (not yet)
* - UTF-8
* - UTF-7
* - UTF-7 IMAP (modified UTF-7)
*
* @package IdnaConvert
* @author Matthias Sommerfeld <mso@phlyLabs.de>
* @copyright 2003-2016 phlyLabs Berlin, http://phlylabs.de
* @version 0.1.0 2016-01-08
*/
namespace Mso\IdnaConvert;
interface UnicodeTranscoderInterface
{
public static function convert($data, $from, $to, $safe_mode = false, $safe_char = 0xFFFC);
public static function utf8_ucs4array($input);
public static function ucs4array_utf8($input);
public static function utf7imap_ucs4array($input);
public static function utf7_ucs4array($input, $sc = '+');
public static function ucs4array_utf7imap($input);
public static function ucs4array_utf7($input, $sc = '+');
public static function ucs4array_ucs4($input);
public static function ucs4_ucs4array($input);
}

View File

@@ -132,7 +132,7 @@ class IntegrityCheck {
// Admin uses default-IP
$admips[$row['adminid']] = explode(',', Settings::Get('system.defaultip'));
} else {
$admips[$row['adminid']] = [ $row['ip'] ];
$admips[$row['adminid']] = array($row['ip']);
}
}
}
@@ -292,7 +292,7 @@ class IntegrityCheck {
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$ips[$row['id']] = $row['ip'] . ':' . $row['port'];
}
// Cache all configured domains
$result_stmt = Database::prepare("SELECT `id`, `parentdomainid`, `letsencrypt` FROM `" . TABLE_PANEL_DOMAINS . "` ORDER BY `id` ASC");
$ip_stmt = Database::prepare("SELECT `id_domain`, `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :domainid");
@@ -304,7 +304,7 @@ class IntegrityCheck {
Database::pexecute($ip_stmt, array('domainid' => $row['id']));
while ($iprow = $ip_stmt->fetch(PDO::FETCH_ASSOC)) {
// If the parentdomain has an ip/port assigned which we know is SSL enabled, set the parentdomain to "true"
if (array_key_exists($iprow['id_ipandports'], $ips)) { $parentdomains[$row['id']] = true; }
if (array_key_exists($iprow['id_ipandports'], $ips)) { $parentdomains[$row['id']] = true; }
}
} elseif ($row['letsencrypt'] == 1) {
// All subdomains with enabled letsencrypt enabled are stored
@@ -312,14 +312,14 @@ class IntegrityCheck {
$subdomains[$row['parentdomainid']][] = $row['id'];
}
}
// Check if every parentdomain with enabled letsencrypt as SSL enabled
foreach ($parentdomains as $id => $sslavailable) {
// This parentdomain has no subdomains
if (!isset($subdomains[$id])) { continue; }
// This parentdomain has SSL enabled, doesn't matter what status the subdomains have
if ($sslavailable) { continue; }
// At this point only parentdomains reside which have letsencrypt enabled subdomains
if ($fix) {
// We make a blanket update to all subdomains of this parentdomain, doesn't matter which one is wrong, all have to be disabled
@@ -331,7 +331,7 @@ class IntegrityCheck {
return false;
}
}
if ($fix) {
return $this->SubdomainLetsencrypt();
} else {

View File

@@ -68,8 +68,6 @@ class htmlform
$style = (isset($fielddata['style']) ? ' class="'.$fielddata['style'].'"' : '');
$mandatory = self::_getMandatoryFlag($fielddata);
$data_field = self::_parseDataField($fieldname, $fielddata);
//$data_field = str_replace("\n", "", $data_field);
$data_field = str_replace("\t", "", $data_field);
if (isset($fielddata['has_nextto'])) {
$nexto = array('field' => $fieldname);
$data_field.='{NEXTTOFIELD_'.$fieldname.'}';
@@ -79,7 +77,6 @@ class htmlform
eval("self::\$_form .= \"" . getTemplate("misc/form/table_row", "1") . "\";");
} else {
$data_field = self::_parseDataField($fieldname, $fielddata);
//$data_field = str_replace("\n", "", $data_field);
$data_field = str_replace("\t", "", $data_field);
$data_field = $fielddata['next_to_prefix'].$data_field;
self::$_form = str_replace(

View File

@@ -399,7 +399,7 @@ class paging {
}
$breakorws = ($break ? '<br />' : '&nbsp;');
foreach (array('asc' => $lng['panel']['ascending'], 'desc' => $lng['panel']['decending']) as $sortordertype => $sortorderdescription) {
foreach (array('asc' => $lng['panel']['ascending'], 'desc' => $lng['panel']['descending']) as $sortordertype => $sortorderdescription) {
$orderoptions.= makeoption($sortorderdescription, $sortordertype, $this->sortorder, true, true);
}

View File

@@ -113,7 +113,11 @@ class phpinterface_fpm {
'session.gc_probability',
'variables_order',
'opcache.log_verbosity_level',
'opcache.restrict_api'
'opcache.restrict_api',
'opcache.revalidate_freq',
'opcache.max_accelerated_files',
'opcache.memory_consumption',
'opcache.interned_strings_buffer'
),
'php_admin_flag' => array(
'allow_call_time_pass_reference',
@@ -137,7 +141,8 @@ class phpinterface_fpm {
'opcache.revalidate_path',
'opcache.save_comments',
'opcache.use_cwd',
'opcache.validate_timestamps'
'opcache.validate_timestamps',
'opcache.fast_shutdown'
)
);

View File

@@ -31,7 +31,7 @@ class PHPMailer
* The PHPMailer Version number.
* @var string
*/
public $Version = '5.2.15';
public $Version = '5.2.16';
/**
* Email priority.
@@ -285,7 +285,7 @@ class PHPMailer
/**
* SMTP auth type.
* Options are LOGIN (default), PLAIN, NTLM, CRAM-MD5
* Options are CRAM-MD5, LOGIN, PLAIN, NTLM, XOAUTH2, attempted in that order if not specified
* @var string
*/
public $AuthType = '';
@@ -395,7 +395,7 @@ class PHPMailer
/**
* DKIM Identity.
* Usually the email address used as the source of the email
* Usually the email address used as the source of the email.
* @var string
*/
public $DKIM_identity = '';
@@ -681,7 +681,9 @@ class PHPMailer
} else {
$subject = $this->encodeHeader($this->secureHeader($subject));
}
if (ini_get('safe_mode') || !($this->UseSendmailOptions)) {
//Can't use additional_parameters in safe_mode
//@link http://php.net/manual/en/function.mail.php
if (ini_get('safe_mode') or !$this->UseSendmailOptions) {
$result = @mail($to, $subject, $body, $header);
} else {
$result = @mail($to, $subject, $body, $header, $params);
@@ -1425,9 +1427,9 @@ class PHPMailer
}
$to = implode(', ', $toArr);
if (empty($this->Sender)) {
$params = ' ';
} else {
$params = null;
//This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
if (!empty($this->Sender)) {
$params = sprintf('-f%s', $this->Sender);
}
if ($this->Sender != '' and !ini_get('safe_mode')) {
@@ -1435,7 +1437,7 @@ class PHPMailer
ini_set('sendmail_from', $this->Sender);
}
$result = false;
if ($this->SingleTo && count($toArr) > 1) {
if ($this->SingleTo and count($toArr) > 1) {
foreach ($toArr as $toAddr) {
$result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
$this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From);
@@ -1541,12 +1543,17 @@ class PHPMailer
* @throws phpmailerException
* @return boolean
*/
public function smtpConnect($options = array())
public function smtpConnect($options = null)
{
if (is_null($this->smtp)) {
$this->smtp = $this->getSMTPInstance();
}
//If no options are provided, use whatever is set in the instance
if (is_null($options)) {
$options = $this->SMTPOptions;
}
// Already connected?
if ($this->smtp->connected()) {
return true;
@@ -1616,7 +1623,7 @@ class PHPMailer
if (!$this->smtp->startTLS()) {
throw new phpmailerException($this->lang('connect_host'));
}
// We must resend HELO after tls negotiation
// We must resend EHLO after TLS negotiation
$this->smtp->hello($hello);
}
if ($this->SMTPAuth) {
@@ -2125,12 +2132,12 @@ class PHPMailer
//Can we do a 7-bit downgrade?
if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) {
$bodyEncoding = '7bit';
//All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
$bodyCharSet = 'us-ascii';
}
//If lines are too long, and we're not already using an encoding that will shorten them,
//change to quoted-printable transfer encoding
//change to quoted-printable transfer encoding for the body part only
if ('base64' != $this->Encoding and self::hasLineLongerThanMax($this->Body)) {
$this->Encoding = 'quoted-printable';
$bodyEncoding = 'quoted-printable';
}
@@ -2139,10 +2146,11 @@ class PHPMailer
//Can we do a 7-bit downgrade?
if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) {
$altBodyEncoding = '7bit';
//All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
$altBodyCharSet = 'us-ascii';
}
//If lines are too long, and we're not already using an encoding that will shorten them,
//change to quoted-printable transfer encoding
//change to quoted-printable transfer encoding for the alt body part only
if ('base64' != $altBodyEncoding and self::hasLineLongerThanMax($this->AltBody)) {
$altBodyEncoding = 'quoted-printable';
}
@@ -2246,8 +2254,10 @@ class PHPMailer
$body .= $this->attachAll('attachment', $this->boundary[1]);
break;
default:
// catch case 'plain' and case ''
$body .= $this->encodeString($this->Body, $bodyEncoding);
// Catch case 'plain' and case '', applies to simple `text/plain` and `text/html` body content types
//Reset the `Encoding` property in case we changed it for line length reasons
$this->Encoding = $bodyEncoding;
$body .= $this->encodeString($this->Body, $this->Encoding);
break;
}
@@ -2353,8 +2363,7 @@ class PHPMailer
/**
* Set the message type.
* PHPMailer only supports some preset message types,
* not arbitrary MIME structures.
* PHPMailer only supports some preset message types, not arbitrary MIME structures.
* @access protected
* @return void
*/
@@ -2372,6 +2381,7 @@ class PHPMailer
}
$this->message_type = implode('_', $type);
if ($this->message_type == '') {
//The 'plain' message_type refers to the message having a single body element, not that it is plain-text
$this->message_type = 'plain';
}
}

View File

@@ -30,7 +30,7 @@ class SMTP
* The PHPMailer SMTP version number.
* @var string
*/
const VERSION = '5.2.15';
const VERSION = '5.2.16';
/**
* SMTP line break constant.
@@ -81,7 +81,7 @@ class SMTP
* @deprecated Use the `VERSION` constant instead
* @see SMTP::VERSION
*/
public $Version = '5.2.15';
public $Version = '5.2.16';
/**
* SMTP server port number.
@@ -400,7 +400,7 @@ class SMTP
);
if (empty($authtype)) {
foreach (array('LOGIN', 'CRAM-MD5', 'NTLM', 'PLAIN', 'XOAUTH2') as $method) {
foreach (array('CRAM-MD5', 'LOGIN', 'PLAIN', 'NTLM', 'XOAUTH2') as $method) {
if (in_array($method, $this->server_caps['AUTH'])) {
$authtype = $method;
break;

View File

@@ -124,6 +124,23 @@ class Settings {
return $result;
}
/**
* tests if a setting-value that i s a comma separated list contains an entry
*
* @param string $setting a group and a varname separated by a dot (group.varname)
* @param string $entry the entry that is expected to be in the list
*
* @return boolean true, if the list contains $entry
*/
public function pIsInList($setting = null, $entry = null) {
$s=Settings::Get($setting);
if ($s==null) {
return false;
}
$slist = explode(",",$s);
return in_array($entry, $slist);
}
/**
* update a setting / set a new value
*

View File

@@ -388,15 +388,557 @@ mail IN A <SERVERIP>
<command><![CDATA[rc-update add named default]]></command>
<command><![CDATA[/etc/init.d/named restart]]></command>
</daemon>
<daemon name="powerdns" title="PowerDNS via bind-backend">
<daemon name="powerdns" title="PowerDNS (standalone)">
<install><![CDATA[emerge net-dns/pdns]]></install>
<file name="/etc/powerdns/pdns.conf" backup="true">
<file name="/etc/powerdns/pdns.conf" backup="true" chmod="600">
<content><![CDATA[
# Autogenerated configuration file template
#################################
# allow-axfr-ips Allow zonetransfers only to these subnets
#
allow-axfr-ips=<NAMESERVERS>
allow-axfr-ips=127.0.0.0/8,::1,<NAMESERVERS>
#################################
# allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges.
#
# allow-dnsupdate-from=127.0.0.0/8,::1
#################################
# allow-recursion List of subnets that are allowed to recurse
#
allow-recursion=127.0.0.1
#################################
# also-notify When notifying a domain, also notify these nameservers
#
# also-notify=
#################################
# any-to-tcp Answer ANY queries with tc=1, shunting to TCP
#
# any-to-tcp=no
#################################
# cache-ttl Seconds to store packets in the PacketCache
#
# cache-ttl=20
#################################
# carbon-interval Number of seconds between carbon (graphite) updates
#
# carbon-interval=30
#################################
# carbon-ourname If set, overrides our reported hostname for carbon stats
#
# carbon-ourname=
#################################
# carbon-server If set, send metrics in carbon (graphite) format to this server
#
# carbon-server=
#################################
# chroot If set, chroot to this directory for more security
#
# chroot=
#################################
# config-dir Location of configuration directory (pdns.conf)
#
config-dir=/etc/powerdns
#################################
# config-name Name of this virtual configuration - will rename the binary image
#
# config-name=
#################################
# control-console Debugging switch - don't use
#
# control-console=no
#################################
# daemon Operate as a daemon
#
daemon=yes
#################################
# default-ksk-algorithms Default KSK algorithms
#
# default-ksk-algorithms=rsasha256
#################################
# default-ksk-size Default KSK size (0 means default)
#
# default-ksk-size=0
#################################
# default-soa-mail mail address to insert in the SOA record if none set in the backend
#
# default-soa-mail=
#################################
# default-soa-name name to insert in the SOA record if none set in the backend
#
# default-soa-name=a.misconfigured.powerdns.server
#################################
# default-ttl Seconds a result is valid if not set otherwise
#
# default-ttl=3600
#################################
# default-zsk-algorithms Default ZSK algorithms
#
# default-zsk-algorithms=rsasha256
#################################
# default-zsk-size Default ZSK size (0 means default)
#
# default-zsk-size=0
#################################
# direct-dnskey Fetch DNSKEY RRs from backend during DNSKEY synthesis
#
# direct-dnskey=no
#################################
# disable-axfr Disable zonetransfers but do allow TCP queries
#
# disable-axfr=no
#################################
# disable-axfr-rectify Disable the rectify step during an outgoing AXFR. Only required for regression testing.
#
# disable-axfr-rectify=no
#################################
# disable-tcp Do not listen to TCP queries
#
# disable-tcp=no
#################################
# distributor-threads Default number of Distributor (backend) threads to start
#
# distributor-threads=3
#################################
# do-ipv6-additional-processing Do AAAA additional processing
#
# do-ipv6-additional-processing=yes
#################################
# edns-subnet-processing If we should act on EDNS Subnet options
#
# edns-subnet-processing=no
#################################
# entropy-source If set, read entropy from this file
#
# entropy-source=/dev/urandom
#################################
# experimental-api-key REST API Static authentication key (required for API use)
#
# experimental-api-key=
#################################
# experimental-api-readonly If the JSON API should disallow data modification
#
# experimental-api-readonly=no
#################################
# experimental-dname-processing If we should support DNAME records
#
# experimental-dname-processing=no
#################################
# experimental-dnsupdate Enable/Disable DNS update (RFC2136) support. Default is no.
#
# experimental-dnsupdate=no
#################################
# experimental-json-interface If the webserver should serve JSON data
#
# experimental-json-interface=no
#################################
# experimental-logfile Filename of the log file for JSON parser
#
# experimental-logfile=/var/log/pdns.log
#################################
# forward-dnsupdate A global setting to allow DNS update packages that are for a Slave domain, to be forwarded to the master.
#
# forward-dnsupdate=yes
#################################
# guardian Run within a guardian process
#
guardian=yes
#################################
# include-dir Include *.conf files from this directory
#
# include-dir=
#################################
# launch Which backends to launch and order to query them in
#
# launch=
#################################
# load-modules Load this module - supply absolute or relative path
#
# load-modules=
#################################
# local-address Local IP addresses to which we bind
#
local-address=<SERVERIP>,127.0.0.1
#################################
# local-address-nonexist-fail Fail to start if one or more of the local-address's do not exist on this server
#
# local-address-nonexist-fail=yes
#################################
# local-ipv6 Local IP address to which we bind
#
# local-ipv6=
#################################
# local-ipv6-nonexist-fail Fail to start if one or more of the local-ipv6 addresses do not exist on this server
#
# local-ipv6-nonexist-fail=yes
#################################
# local-port The port on which we listen
#
local-port=53
#################################
# log-dns-details If PDNS should log DNS non-erroneous details
#
log-dns-details=yes
#################################
# log-dns-queries If PDNS should log all incoming DNS queries
#
# log-dns-queries=no
#################################
# logging-facility Log under a specific facility
#
# logging-facility=
#################################
# loglevel Amount of logging. Higher is more. Do not set below 3
#
# loglevel=4
#################################
# lua-prequery-script Lua script with prequery handler
#
# lua-prequery-script=
#################################
# master Act as a master
#
master=yes
#################################
# max-cache-entries Maximum number of cache entries
#
# max-cache-entries=1000000
#################################
# max-ent-entries Maximum number of empty non-terminals in a zone
#
# max-ent-entries=100000
#################################
# max-nsec3-iterations Limit the number of NSEC3 hash iterations
#
# max-nsec3-iterations=500
#################################
# max-queue-length Maximum queuelength before considering situation lost
#
# max-queue-length=5000
#################################
# max-signature-cache-entries Maximum number of signatures cache entries
#
# max-signature-cache-entries=
#################################
# max-tcp-connections Maximum number of TCP connections
#
# max-tcp-connections=10
#################################
# module-dir Default directory for modules
#
module-dir=/usr/lib/powerdns/pdns/
#################################
# negquery-cache-ttl Seconds to store negative query results in the QueryCache
#
# negquery-cache-ttl=60
#################################
# no-shuffle Set this to prevent random shuffling of answers - for regression testing
#
# no-shuffle=off
#################################
# only-notify Only send AXFR NOTIFY to these IP addresses or netmasks
#
# only-notify=0.0.0.0/0,::/0
#################################
# out-of-zone-additional-processing Do out of zone additional processing
#
# out-of-zone-additional-processing=yes
#################################
# overload-queue-length Maximum queuelength moving to packetcache only
#
# overload-queue-length=0
#################################
# pipebackend-abi-version Version of the pipe backend ABI
#
# pipebackend-abi-version=1
#################################
# prevent-self-notification Don't send notifications to what we think is ourself
#
# prevent-self-notification=yes
#################################
# query-cache-ttl Seconds to store query results in the QueryCache
#
# query-cache-ttl=20
#################################
# query-local-address Source IP address for sending queries
#
# query-local-address=0.0.0.0
#################################
# query-local-address6 Source IPv6 address for sending queries
#
# query-local-address6=::
#################################
# query-logging Hint backends that queries should be logged
#
# query-logging=no
#################################
# queue-limit Maximum number of milliseconds to queue a query
#
# queue-limit=1500
#################################
# receiver-threads Default number of receiver threads to start
#
# receiver-threads=1
#################################
# recursive-cache-ttl Seconds to store packets for recursive queries in the PacketCache
#
# recursive-cache-ttl=10
#################################
# recursor If recursion is desired, IP address of a recursing nameserver
#
# recursor=no
#################################
# retrieval-threads Number of AXFR-retrieval threads for slave operation
#
# retrieval-threads=2
#################################
# reuseport Enable higher performance on compliant kernels by using SO_REUSEPORT allowing each receiver thread to open its own socket
#
# reuseport=no
#################################
# security-poll-suffix Domain name from which to query security update notifications
#
# security-poll-suffix=secpoll.powerdns.com.
#################################
# send-root-referral Send out old-fashioned root-referral instead of ServFail in case of no authority
#
# send-root-referral=no
#################################
# server-id Returned when queried for 'server.id' TXT or NSID, defaults to hostname - disabled or custom
#
# server-id=
#################################
# setgid If set, change group id to this gid for more security
#
setgid=pdns
#################################
# setuid If set, change user id to this uid for more security
#
setuid=pdns
#################################
# signing-threads Default number of signer threads to start
#
# signing-threads=3
#################################
# slave Act as a slave
#
# slave=no
#################################
# slave-cycle-interval Reschedule failed SOA serial checks once every .. seconds
#
# slave-cycle-interval=60
#################################
# slave-renotify If we should send out notifications for slaved updates
#
# slave-renotify=no
#################################
# soa-expire-default Default SOA expire
#
# soa-expire-default=604800
#################################
# soa-minimum-ttl Default SOA minimum ttl
#
# soa-minimum-ttl=3600
#################################
# soa-refresh-default Default SOA refresh
#
# soa-refresh-default=10800
#################################
# soa-retry-default Default SOA retry
#
# soa-retry-default=3600
#################################
# socket-dir Where the controlsocket will live
#
socket-dir=/var/run
#################################
# tcp-control-address If set, PowerDNS can be controlled over TCP on this address
#
# tcp-control-address=
#################################
# tcp-control-port If set, PowerDNS can be controlled over TCP on this address
#
# tcp-control-port=53000
#################################
# tcp-control-range If set, remote control of PowerDNS is possible over these networks only
#
# tcp-control-range=127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10
#################################
# tcp-control-secret If set, PowerDNS can be controlled over TCP after passing this secret
#
# tcp-control-secret=
#################################
# traceback-handler Enable the traceback handler (Linux only)
#
# traceback-handler=yes
#################################
# trusted-notification-proxy IP address of incoming notification proxy
#
# trusted-notification-proxy=
#################################
# udp-truncation-threshold Maximum UDP response size before we truncate
#
# udp-truncation-threshold=1680
#################################
# version-string PowerDNS version in packets - full, anonymous, powerdns or custom
#
version-string=powerdns
#################################
# webserver Start a webserver for monitoring
#
# webserver=no
#################################
# webserver-address IP Address of webserver to listen on
#
# webserver-address=127.0.0.1
#################################
# webserver-allow-from Webserver access is only allowed from these subnets
#
# webserver-allow-from=0.0.0.0/0,::/0
#################################
# webserver-password Password required for accessing the webserver
#
# webserver-password=
#################################
# webserver-port Port of webserver to listen on
#
# webserver-port=8081
#################################
# webserver-print-arguments If the webserver should print arguments
#
# webserver-print-arguments=no
# include froxlor-specific config
include-dir=/etc/powerdns/froxlor/
]]>
</content>
</file>
<command><![CDATA[mkdir -p /etc/powerdns/froxlor/]]></command>
<file name="/etc/powerdns/froxlor/pdns_froxlor.conf" chown="root:root"
chmod="600">
<content><![CDATA[
# mysql-settings / you need to create the power-dns database for yourself!
launch=gmysql
gmysql-host=127.0.0.1
gmysql-port=3306
gmysql-dbname=pdns
gmysql-user=powerdns
gmysql-group=client
gmysql-password=
]]>
</content>
</file>
<command><![CDATA[/etc/init.d/pdns restart]]></command>
</daemon>
<daemon name="powerdns_bind" title="PowerDNS via bind-backend">
<install><![CDATA[emerge net-dns/pdns]]></install>
<file name="/etc/powerdns/pdns.conf" backup="true" chmod="600">
<content><![CDATA[
# Autogenerated configuration file template
#################################
# allow-axfr-ips Allow zonetransfers only to these subnets
#
allow-axfr-ips=127.0.0.0/8,::1,<NAMESERVERS>
#################################
# allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges.
@@ -909,12 +1451,13 @@ version-string=powerdns
# webserver-print-arguments=no
# include froxlor-bind-specific config
include=/etc/powerdns/pdns_froxlor.conf
include-dir=/etc/powerdns/froxlor/
]]>
</content>
</file>
<file name="/etc/powerdns/pdns_froxlor.conf" chown="root:0"
chmod="644">
<command><![CDATA[mkdir -p /etc/powerdns/froxlor/]]></command>
<file name="/etc/powerdns/froxlor/pdns_froxlor.conf" chown="root:root"
chmod="600">
<content><![CDATA[
#local-ipv6=YOUR_IPv6_(if_any)
bind-config=<BIND_CONFIG_PATH>named.conf
@@ -3332,7 +3875,7 @@ aliases: files
<commands index="3">
<visibility mode="true">{{settings.phpfpm.enabled_ownvhost}}
</visibility>
<visibility mode="usernotexists">{{settings.phpfpm.vhost_httpuser}}
<visibility mode="usernamenotexists">{{settings.phpfpm.vhost_httpuser}}
</visibility>
<command><![CDATA[groupadd -f {{settings.phpfpm.vhost_httpgroup}}]]></command>
<command><![CDATA[useradd -s /bin/false -g {{settings.phpfpm.vhost_httpgroup}} {{settings.phpfpm.vhost_httpuser}}]]></command>

View File

@@ -373,9 +373,550 @@ exit "$RETVAL"
<command><![CDATA[chmod 0644 {{settings.system.bindconf_directory}}froxlor_bind.conf]]></command>
<command><![CDATA[/etc/init.d/bind9 restart]]></command>
</daemon>
<daemon name="powerdns" title="PowerDNS via bind-backend">
<daemon name="powerdns" title="PowerDNS (standalone)">
<install><![CDATA[apt-get install pdns-server pdns-backend-mysql]]></install>
<file name="/etc/powerdns/pdns.conf" backup="true" chmod="600">
<content><![CDATA[
#################################
# allow-axfr-ips Allow zonetransfers only to these subnets
#
allow-axfr-ips=127.0.0.0/8,::1,<NAMESERVERS>
#################################
# allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges.
#
# allow-dnsupdate-from=127.0.0.0/8,::1
#################################
# allow-recursion List of subnets that are allowed to recurse
#
allow-recursion=127.0.0.1
#################################
# also-notify When notifying a domain, also notify these nameservers
#
# also-notify=
#################################
# any-to-tcp Answer ANY queries with tc=1, shunting to TCP
#
# any-to-tcp=no
#################################
# cache-ttl Seconds to store packets in the PacketCache
#
# cache-ttl=20
#################################
# carbon-interval Number of seconds between carbon (graphite) updates
#
# carbon-interval=30
#################################
# carbon-ourname If set, overrides our reported hostname for carbon stats
#
# carbon-ourname=
#################################
# carbon-server If set, send metrics in carbon (graphite) format to this server
#
# carbon-server=
#################################
# chroot If set, chroot to this directory for more security
#
# chroot=
#################################
# config-dir Location of configuration directory (pdns.conf)
#
config-dir=/etc/powerdns
#################################
# config-name Name of this virtual configuration - will rename the binary image
#
# config-name=
#################################
# control-console Debugging switch - don't use
#
# control-console=no
#################################
# daemon Operate as a daemon
#
daemon=yes
#################################
# default-ksk-algorithms Default KSK algorithms
#
# default-ksk-algorithms=rsasha256
#################################
# default-ksk-size Default KSK size (0 means default)
#
# default-ksk-size=0
#################################
# default-soa-mail mail address to insert in the SOA record if none set in the backend
#
# default-soa-mail=
#################################
# default-soa-name name to insert in the SOA record if none set in the backend
#
# default-soa-name=a.misconfigured.powerdns.server
#################################
# default-ttl Seconds a result is valid if not set otherwise
#
# default-ttl=3600
#################################
# default-zsk-algorithms Default ZSK algorithms
#
# default-zsk-algorithms=rsasha256
#################################
# default-zsk-size Default ZSK size (0 means default)
#
# default-zsk-size=0
#################################
# direct-dnskey Fetch DNSKEY RRs from backend during DNSKEY synthesis
#
# direct-dnskey=no
#################################
# disable-axfr Disable zonetransfers but do allow TCP queries
#
# disable-axfr=no
#################################
# disable-axfr-rectify Disable the rectify step during an outgoing AXFR. Only required for regression testing.
#
# disable-axfr-rectify=no
#################################
# disable-tcp Do not listen to TCP queries
#
# disable-tcp=no
#################################
# distributor-threads Default number of Distributor (backend) threads to start
#
# distributor-threads=3
#################################
# do-ipv6-additional-processing Do AAAA additional processing
#
# do-ipv6-additional-processing=yes
#################################
# edns-subnet-processing If we should act on EDNS Subnet options
#
# edns-subnet-processing=no
#################################
# entropy-source If set, read entropy from this file
#
# entropy-source=/dev/urandom
#################################
# experimental-api-key REST API Static authentication key (required for API use)
#
# experimental-api-key=
#################################
# experimental-api-readonly If the JSON API should disallow data modification
#
# experimental-api-readonly=no
#################################
# experimental-dname-processing If we should support DNAME records
#
# experimental-dname-processing=no
#################################
# experimental-dnsupdate Enable/Disable DNS update (RFC2136) support. Default is no.
#
# experimental-dnsupdate=no
#################################
# experimental-json-interface If the webserver should serve JSON data
#
# experimental-json-interface=no
#################################
# experimental-logfile Filename of the log file for JSON parser
#
# experimental-logfile=/var/log/pdns.log
#################################
# forward-dnsupdate A global setting to allow DNS update packages that are for a Slave domain, to be forwarded to the master.
#
# forward-dnsupdate=yes
#################################
# guardian Run within a guardian process
#
guardian=yes
#################################
# include-dir Include *.conf files from this directory
#
# include-dir=
#################################
# launch Which backends to launch and order to query them in
#
# launch=
#################################
# load-modules Load this module - supply absolute or relative path
#
# load-modules=
#################################
# local-address Local IP addresses to which we bind
#
local-address=<SERVERIP>,127.0.0.1
#################################
# local-address-nonexist-fail Fail to start if one or more of the local-address's do not exist on this server
#
# local-address-nonexist-fail=yes
#################################
# local-ipv6 Local IP address to which we bind
#
# local-ipv6=
#################################
# local-ipv6-nonexist-fail Fail to start if one or more of the local-ipv6 addresses do not exist on this server
#
# local-ipv6-nonexist-fail=yes
#################################
# local-port The port on which we listen
#
# local-port=53
#################################
# log-dns-details If PDNS should log DNS non-erroneous details
#
# log-dns-details=no
#################################
# log-dns-queries If PDNS should log all incoming DNS queries
#
# log-dns-queries=no
#################################
# logging-facility Log under a specific facility
#
# logging-facility=
#################################
# loglevel Amount of logging. Higher is more. Do not set below 3
#
# loglevel=4
#################################
# lua-prequery-script Lua script with prequery handler
#
# lua-prequery-script=
#################################
# master Act as a master
#
master=yes
#################################
# max-cache-entries Maximum number of cache entries
#
# max-cache-entries=1000000
#################################
# max-ent-entries Maximum number of empty non-terminals in a zone
#
# max-ent-entries=100000
#################################
# max-nsec3-iterations Limit the number of NSEC3 hash iterations
#
# max-nsec3-iterations=500
#################################
# max-queue-length Maximum queuelength before considering situation lost
#
# max-queue-length=5000
#################################
# max-signature-cache-entries Maximum number of signatures cache entries
#
# max-signature-cache-entries=
#################################
# max-tcp-connections Maximum number of TCP connections
#
# max-tcp-connections=10
#################################
# module-dir Default directory for modules
#
# module-dir=/usr/lib/TRIPLET/pdns
#################################
# negquery-cache-ttl Seconds to store negative query results in the QueryCache
#
# negquery-cache-ttl=60
#################################
# no-shuffle Set this to prevent random shuffling of answers - for regression testing
#
# no-shuffle=off
#################################
# only-notify Only send AXFR NOTIFY to these IP addresses or netmasks
#
# only-notify=0.0.0.0/0,::/0
#################################
# out-of-zone-additional-processing Do out of zone additional processing
#
# out-of-zone-additional-processing=yes
#################################
# overload-queue-length Maximum queuelength moving to packetcache only
#
# overload-queue-length=0
#################################
# pipebackend-abi-version Version of the pipe backend ABI
#
# pipebackend-abi-version=1
#################################
# prevent-self-notification Don't send notifications to what we think is ourself
#
# prevent-self-notification=yes
#################################
# query-cache-ttl Seconds to store query results in the QueryCache
#
# query-cache-ttl=20
#################################
# query-local-address Source IP address for sending queries
#
# query-local-address=0.0.0.0
#################################
# query-local-address6 Source IPv6 address for sending queries
#
# query-local-address6=::
#################################
# query-logging Hint backends that queries should be logged
#
# query-logging=no
#################################
# queue-limit Maximum number of milliseconds to queue a query
#
# queue-limit=1500
#################################
# receiver-threads Default number of receiver threads to start
#
# receiver-threads=1
#################################
# recursive-cache-ttl Seconds to store packets for recursive queries in the PacketCache
#
# recursive-cache-ttl=10
#################################
# recursor If recursion is desired, IP address of a recursing nameserver
#
# recursor=no
#################################
# retrieval-threads Number of AXFR-retrieval threads for slave operation
#
# retrieval-threads=2
#################################
# reuseport Enable higher performance on compliant kernels by using SO_REUSEPORT allowing each receiver thread to open its own socket
#
# reuseport=no
#################################
# security-poll-suffix Domain name from which to query security update notifications
#
# security-poll-suffix=secpoll.powerdns.com.
#################################
# send-root-referral Send out old-fashioned root-referral instead of ServFail in case of no authority
#
# send-root-referral=no
#################################
# server-id Returned when queried for 'server.id' TXT or NSID, defaults to hostname - disabled or custom
#
# server-id=
#################################
# setgid If set, change group id to this gid for more security
#
setgid=pdns
#################################
# setuid If set, change user id to this uid for more security
#
setuid=pdns
#################################
# signing-threads Default number of signer threads to start
#
# signing-threads=3
#################################
# slave Act as a slave
#
# slave=no
#################################
# slave-cycle-interval Reschedule failed SOA serial checks once every .. seconds
#
# slave-cycle-interval=60
#################################
# slave-renotify If we should send out notifications for slaved updates
#
# slave-renotify=no
#################################
# soa-expire-default Default SOA expire
#
# soa-expire-default=604800
#################################
# soa-minimum-ttl Default SOA minimum ttl
#
# soa-minimum-ttl=3600
#################################
# soa-refresh-default Default SOA refresh
#
# soa-refresh-default=10800
#################################
# soa-retry-default Default SOA retry
#
# soa-retry-default=3600
#################################
# socket-dir Where the controlsocket will live
#
# socket-dir=/var/run
#################################
# tcp-control-address If set, PowerDNS can be controlled over TCP on this address
#
# tcp-control-address=
#################################
# tcp-control-port If set, PowerDNS can be controlled over TCP on this address
#
# tcp-control-port=53000
#################################
# tcp-control-range If set, remote control of PowerDNS is possible over these networks only
#
# tcp-control-range=127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10
#################################
# tcp-control-secret If set, PowerDNS can be controlled over TCP after passing this secret
#
# tcp-control-secret=
#################################
# traceback-handler Enable the traceback handler (Linux only)
#
# traceback-handler=yes
#################################
# trusted-notification-proxy IP address of incoming notification proxy
#
# trusted-notification-proxy=
#################################
# udp-truncation-threshold Maximum UDP response size before we truncate
#
# udp-truncation-threshold=1680
#################################
# version-string PowerDNS version in packets - full, anonymous, powerdns or custom
#
version-string=powerdns
#################################
# webserver Start a webserver for monitoring
#
# webserver=no
#################################
# webserver-address IP Address of webserver to listen on
#
# webserver-address=127.0.0.1
#################################
# webserver-allow-from Webserver access is only allowed from these subnets
#
# webserver-allow-from=0.0.0.0/0,::/0
#################################
# webserver-password Password required for accessing the webserver
#
# webserver-password=
#################################
# webserver-port Port of webserver to listen on
#
# webserver-port=8081
#################################
# webserver-print-arguments If the webserver should print arguments
#
# webserver-print-arguments=no
# include froxlor-bind-specific config
include-dir=/etc/powerdns/froxlor/
]]>
</content>
</file>
<command><![CDATA[mkdir -p /etc/powerdns/froxlor/]]></command>
<file name="/etc/powerdns/froxlor/pdns_froxlor.conf" chown="root:root"
chmod="600">
<content><![CDATA[
# mysql-settings / you need to create the power-dns database for yourself!
launch=gmysql
gmysql-host=127.0.0.1
gmysql-port=3306
gmysql-dbname=pdns
gmysql-user=powerdns
gmysql-group=client
gmysql-password=
]]>
</content>
</file>
<command><![CDATA[/etc/init.d/pdns restart]]></command>
</daemon>
<daemon name="powerdns_bind" title="PowerDNS via bind-backend">
<install><![CDATA[apt-get install pdns-server]]></install>
<file name="/etc/powerdns/pdns.conf" backup="true">
<file name="/etc/powerdns/pdns.conf" backup="true" chmod="600">
<content><![CDATA[
#################################
# allow-axfr-ips Allow zonetransfers only to these subnets
@@ -566,7 +1107,6 @@ guardian=yes
# include-dir Include *.conf files from this directory
#
# include-dir=
include-dir=/etc/powerdns/pdns.d
#################################
# launch Which backends to launch and order to query them in
@@ -894,11 +1434,14 @@ version-string=powerdns
#
# webserver-print-arguments=no
include=/etc/powerdns/pdns.d
# include froxlor-bind-specific config
include-dir=/etc/powerdns/froxlor/
]]>
</content>
</file>
<file name="/etc/powerdns/bindbackend.conf" backup="true">
<command><![CDATA[mkdir -p /etc/powerdns/froxlor/]]></command>
<file name="/etc/powerdns/froxlor/pdns_froxlor.conf" chown="root:root"
chmod="600">
<content><![CDATA[
# Bind backend configuration
@@ -4153,7 +4696,7 @@ aliases: files
<commands index="3">
<visibility mode="true">{{settings.phpfpm.enabled_ownvhost}}
</visibility>
<visibility mode="usernotexists">{{settings.phpfpm.vhost_httpuser}}
<visibility mode="usernamenotexists">{{settings.phpfpm.vhost_httpuser}}
</visibility>
<command><![CDATA[groupadd -f {{settings.phpfpm.vhost_httpgroup}}]]></command>
<command><![CDATA[useradd -s /bin/false -g {{settings.phpfpm.vhost_httpgroup}} {{settings.phpfpm.vhost_httpuser}}]]></command>

View File

@@ -342,9 +342,47 @@ exit "$RETVAL"
<command><![CDATA[chmod 0644 {{settings.system.bindconf_directory}}froxlor_bind.conf]]></command>
<command><![CDATA[/etc/init.d/bind9 restart]]></command>
</daemon>
<daemon name="powerdns" title="PowerDNS via bind-backend">
<daemon name="powerdns" title="PowerDNS (standalone)">
<install><![CDATA[apt-get install pdns-server pdns-backend-mysql]]></install>
<file name="/etc/powerdns/pdns.conf" backup="true" chmod="600">
<content><![CDATA[
allow-axfr-ips=127.0.0.0/8,::1,<NAMESERVERS>
allow-recursion=127.0.0.1
config-dir=/etc/powerdns
daemon=yes
guardian=yes
lazy-recursion=yes
local-port=53
master=yes
module-dir=/usr/lib/powerdns
setgid=pdns
setuid=pdns
socket-dir=/var/run
version-string=powerdns
include-dir=/etc/powerdns/froxlor/
]]>
</content>
</file>
<command><![CDATA[mkdir -p /etc/powerdns/froxlor/]]></command>
<file name="/etc/powerdns/froxlor/pdns_froxlor.conf" chown="root:root"
chmod="600">
<content><![CDATA[
# mysql-settings / you need to create the power-dns database for yourself!
launch=gmysql
gmysql-host=127.0.0.1
gmysql-port=3306
gmysql-dbname=pdns
gmysql-user=powerdns
gmysql-group=client
gmysql-password=
]]>
</content>
</file>
<command><![CDATA[/etc/init.d/pdns restart]]></command>
</daemon>
<daemon name="powerdns_bind" title="PowerDNS via bind-backend">
<install><![CDATA[apt-get install pdns-server]]></install>
<file name="/etc/powerdns/pdns.conf" backup="true">
<file name="/etc/powerdns/pdns.conf" backup="true" chmod="600">
<content><![CDATA[
allow-recursion=127.0.0.1
config-dir=/etc/powerdns
@@ -361,12 +399,13 @@ socket-dir=/var/run
version-string=powerdns
bind-config=<BIND_CONFIG_PATH>named.conf
bind-check-interval=300
include=/etc/powerdns/pdns_froxlor.conf
include-dir=/etc/powerdns/froxlor/
]]>
</content>
</file>
<file name="/etc/powerdns/pdns_froxlor.conf" chown="root:0"
chmod="644">
<command><![CDATA[mkdir -p /etc/powerdns/froxlor/]]></command>
<file name="/etc/powerdns/froxlor/pdns_froxlor.conf" chown="root:root"
chmod="600">
<content><![CDATA[
allow-axfr-ips=<NAMESERVERS>
#local-ipv6=YOUR_IPv6_(if_any)
@@ -1656,7 +1695,7 @@ aliases: files
<commands index="3">
<visibility mode="true">{{settings.phpfpm.enabled_ownvhost}}
</visibility>
<visibility mode="usernotexists">{{settings.phpfpm.vhost_httpuser}}
<visibility mode="usernamenotexists">{{settings.phpfpm.vhost_httpuser}}
</visibility>
<command><![CDATA[groupadd -f {{settings.phpfpm.vhost_httpgroup}}]]></command>
<command><![CDATA[useradd -s /bin/false -g {{settings.phpfpm.vhost_httpgroup}} {{settings.phpfpm.vhost_httpuser}}]]></command>

View File

@@ -375,10 +375,49 @@ exit "$RETVAL"
<command><![CDATA[chmod 0644 {{settings.system.bindconf_directory}}froxlor_bind.conf]]></command>
<command><![CDATA[service bind9 restart]]></command>
</daemon>
<daemon name="powerdns" title="PowerDNS via bind-backend">
<daemon name="powerdns" title="PowerDNS (standalone)">
<install><![CDATA[apt-get install pdns-server pdns-backend-mysql]]></install>
<file name="/etc/powerdns/pdns.conf" backup="true" chmod="600">
<content><![CDATA[
allow-axfr-ips=127.0.0.0/8,::1,<NAMESERVERS>
allow-recursion=127.0.0.1
config-dir=/etc/powerdns
daemon=yes
guardian=yes
lazy-recursion=yes
local-port=53
master=yes
module-dir=/usr/lib/powerdns
setgid=pdns
setuid=pdns
socket-dir=/var/run
version-string=powerdns
include-dir=/etc/powerdns/froxlor/
]]>
</content>
</file>
<command><![CDATA[mkdir -p /etc/powerdns/froxlor/]]></command>
<file name="/etc/powerdns/froxlor/pdns_froxlor.conf" chown="root:root"
chmod="600">
<content><![CDATA[
# mysql-settings / you need to create the power-dns database for yourself!
launch=gmysql
gmysql-host=127.0.0.1
gmysql-port=3306
gmysql-dbname=pdns
gmysql-user=powerdns
gmysql-group=client
gmysql-password=
]]>
</content>
</file>
<command><![CDATA[service pdns restart]]></command>
</daemon>
<daemon name="powerdns_bind" title="PowerDNS via bind-backend">
<install><![CDATA[apt-get install pdns-server]]></install>
<file name="/etc/powerdns/pdns.conf" backup="true">
<content><![CDATA[
allow-axfr-ips=127.0.0.0/8,::1,<NAMESERVERS>
allow-recursion=127.0.0.1
config-dir=/etc/powerdns
daemon=yes
@@ -394,12 +433,13 @@ socket-dir=/var/run
version-string=powerdns
bind-config=<BIND_CONFIG_PATH>named.conf
bind-check-interval=300
include=/etc/powerdns/pdns_froxlor.conf
include-dir=/etc/powerdns/froxlor/
]]>
</content>
</file>
<file name="/etc/powerdns/pdns_froxlor.conf" chown="root:0"
chmod="644">
<command><![CDATA[mkdir -p /etc/powerdns/froxlor/]]></command>
<file name="/etc/powerdns/froxlor/pdns_froxlor.conf" chown="root:root"
chmod="600">
<content><![CDATA[
allow-axfr-ips=<NAMESERVERS>
#local-ipv6=YOUR_IPv6_(if_any)
@@ -1663,7 +1703,7 @@ aliases: files
<commands index="3">
<visibility mode="true">{{settings.phpfpm.enabled_ownvhost}}
</visibility>
<visibility mode="usernotexists">{{settings.phpfpm.vhost_httpuser}}
<visibility mode="usernamenotexists">{{settings.phpfpm.vhost_httpuser}}
</visibility>
<command><![CDATA[groupadd -f {{settings.phpfpm.vhost_httpgroup}}]]></command>
<command><![CDATA[useradd -s /bin/false -g {{settings.phpfpm.vhost_httpgroup}} {{settings.phpfpm.vhost_httpuser}}]]></command>

View File

@@ -415,9 +415,348 @@ exit "$RETVAL"
<command><![CDATA[chmod 0644 {{settings.system.bindconf_directory}}froxlor_bind.conf]]></command>
<command><![CDATA[/etc/init.d/bind9 restart]]></command>
</daemon>
<daemon name="powerdns" title="PowerDNS via bind-backend">
<daemon name="powerdns" title="PowerDNS (standalone)">
<install><![CDATA[apt-get install pdns-server pdns-backend-mysql]]></install>
<file name="/etc/powerdns/pdns.conf" backup="true" chmod="600">
<content><![CDATA[
# Autogenerated configuration file template
#################################
# allow-axfr-ips If enabled, restrict zonetransfers to originate from these
# IP addresses
#
allow-axfr-ips=127.0.0.0/8,::1,<NAMESERVERS>
#################################
# allow-recursion List of netmasks that are allowed to recurse
#
allow-recursion=127.0.0.1
#################################
# allow-recursion-override Local data even about hosts that don't exist will
# override the internet. (on/off)
#
# allow-recursion-override=
#################################
# cache-ttl Seconds to store packets in the PacketCache
#
# cache-ttl=20
#################################
# chroot If set, chroot to this directory for more security
#
# chroot=/var/spool/powerdns
#################################
# config-dir Location of configuration directory (pdns.conf)
#
config-dir=/etc/powerdns
#################################
# config-name Name of this virtual configuration - will rename the binary image
#
# config-name=
#################################
# control-console Debugging switch - don't use
#
# control-console=no
#################################
# daemon Operate as a daemon
#
daemon=yes
#################################
# default-soa-name name to insert in the SOA record if none set in the backend
#
# default-soa-name=a.misconfigured.powerdns.server
#################################
# disable-axfr Disable zonetransfers but do allow TCP queries
#
disable-axfr=yes
#################################
# disable-tcp Do not listen to TCP queries
#
# disable-tcp=no
#################################
# distributor-threads Default number of Distributor (backend) threads to start
#
# distributor-threads=3
#################################
# fancy-records Process URL and MBOXFW records
#
# fancy-records=no
#################################
# guardian Run within a guardian process
#
guardian=yes
#################################
# launch Which backends to launch and order to query them in
#
# launch=
#################################
# lazy-recursion Only recurse if question cannot be answered locally
#
lazy-recursion=yes
#################################
# load-modules Load this module - supply absolute or relative path
#
# load-modules=
#################################
# local-address Local IP address to which we bind
#
local-address=<SERVERIP>,127.0.0.1
#################################
# local-ipv6 Local IP address to which we bind
#
# local-ipv6=
#################################
# local-port The port on which we listen
#
local-port=53
#################################
# log-dns-details If PDNS should log failed update requests
#
log-dns-details=yes
#################################
# log-failed-updates If PDNS should log failed update requests
#
# log-failed-updates=
#################################
# logfile Logfile to use
#
# logfile=/var/log/pdns.log
#################################
# logging-facility Log under a specific facility
#
# logging-facility=
#################################
# loglevel Amount of logging. Higher is more. Do not set below 3
#
# loglevel=4
#################################
# master Act as a master
#
master=yes
#################################
# max-queue-length Maximum queuelength before considering situation lost
#
# max-queue-length=5000
#################################
# max-tcp-connections Maximum number of TCP connections
#
# max-tcp-connections=10
#################################
# module-dir Default directory for modules
#
module-dir=/usr/lib/powerdns
#################################
# negquery-cache-ttl Seconds to store packets in the PacketCache
#
# negquery-cache-ttl=60
#################################
# out-of-zone-additional-processing Do out of zone additional processing
#
# out-of-zone-additional-processing=no
#################################
# query-cache-ttl Seconds to store packets in the PacketCache
#
# query-cache-ttl=20
#################################
# query-logging Hint backends that queries should be logged
#
# query-logging=no
#################################
# queue-limit Maximum number of milliseconds to queue a query
#
# queue-limit=1500
#################################
# query-local-address The IP address to use as a source address for sending
# queries.
# query-local-address=
#################################
# receiver-threads Number of receiver threads to launch
#
# receiver-threads=1
#################################
# recursive-cache-ttl Seconds to store packets in the PacketCache
#
# recursive-cache-ttl=10
#################################
# recursor If recursion is desired, IP address of a recursing nameserver
#
# recursor=
#################################
# setgid If set, change group id to this gid for more security
#
setgid=pdns
#################################
# setuid If set, change user id to this uid for more security
#
setuid=pdns
#################################
# skip-cname Do not perform CNAME indirection for each query
#
# skip-cname=no
#################################
# slave Act as a slave
#
# slave=no
#################################
# slave-cycle-interval Reschedule failed SOA serial checks once every .. seconds
#
# slave-cycle-interval=60
#################################
# smtpredirector Our smtpredir MX host
#
# smtpredirector=a.misconfigured.powerdns.smtp.server
#################################
# soa-minimum-ttl Default SOA mininum ttl
#
# soa-minimum-ttl=3600
#################################
# soa-refresh-default Default SOA refresh
#
# soa-refresh-default=10800
#################################
# soa-retry-default Default SOA retry
#
# soa-retry-default=3600
#################################
# soa-expire-default Default SOA expire
#
# soa-expire-default=604800
#################################
# soa-serial-offset Make sure that no SOA serial is less than this number
#
# soa-serial-offset=0
#################################
# socket-dir Where the controlsocket will live
#
socket-dir=/var/run
#################################
# strict-rfc-axfrs Perform strictly rfc compliant axfrs (very slow)
#
# strict-rfc-axfrs=no
#################################
# urlredirector Where we send hosts to that need to be url redirected
#
# urlredirector=127.0.0.1
#################################
# use-logfile Use a log file
#
# use-logfile=yes
#################################
# webserver Start a webserver for monitoring
#
# webserver=no
#################################
# webserver-address IP Address of webserver to listen on
#
# webserver-address=127.0.0.1
#################################
# webserver-password Password required for accessing the webserver
#
# webserver-password=
#################################
# webserver-port Port of webserver to listen on
#
# webserver-port=8081
#################################
# webserver-print-arguments If the webserver should print arguments
#
# webserver-print-arguments=no
#################################
# wildcard-url Process URL and MBOXFW records
#
# wildcard-url=no
#################################
# wildcards Honor wildcards in the database
#
# wildcards=
#################################
# version-string What should PowerDNS return for version
# allowed methods are anonymous / powerdns / full / custom
version-string=powerdns
# include froxlor-bind-specific config
include-dir=/etc/powerdns/froxlor/
]]>
</content>
</file>
<command><![CDATA[mkdir -p /etc/powerdns/froxlor/]]></command>
<file name="/etc/powerdns/froxlor/pdns_froxlor.conf" chown="root:root"
chmod="600">
<content><![CDATA[
# mysql-settings / you need to create the power-dns database for yourself!
launch=gmysql
gmysql-host=127.0.0.1
gmysql-port=3306
gmysql-dbname=pdns
gmysql-user=powerdns
gmysql-group=client
gmysql-password=
]]>
</content>
</file>
<command><![CDATA[/etc/init.d/pdns restart]]></command>
</daemon>
<daemon name="powerdns_bind" title="PowerDNS via bind-backend">
<install><![CDATA[apt-get install pdns-server]]></install>
<file name="/etc/powerdns/pdns.conf" backup="true">
<file name="/etc/powerdns/pdns.conf" backup="true" chmod="600">
<content><![CDATA[
# Autogenerated configuration file template
#################################
@@ -732,11 +1071,14 @@ socket-dir=/var/run
# allowed methods are anonymous / powerdns / full / custom
version-string=powerdns
include=/etc/powerdns/pdns.d
# include froxlor-bind-specific config
include-dir=/etc/powerdns/froxlor/
]]>
</content>
</file>
<file name="/etc/powerdns/bindbackend.conf" backup="true">
<command><![CDATA[mkdir -p /etc/powerdns/froxlor/]]></command>
<file name="/etc/powerdns/froxlor/pdns_froxlor.conf" chown="root:root"
chmod="600">
<content><![CDATA[
# Bind backend configuration
@@ -5162,7 +5504,7 @@ aliases: files
<commands index="3">
<visibility mode="true">{{settings.phpfpm.enabled_ownvhost}}
</visibility>
<visibility mode="usernotexists">{{settings.phpfpm.vhost_httpuser}}
<visibility mode="usernamenotexists">{{settings.phpfpm.vhost_httpuser}}
</visibility>
<command><![CDATA[groupadd -f {{settings.phpfpm.vhost_httpgroup}}]]></command>
<command><![CDATA[useradd -s /bin/false -g {{settings.phpfpm.vhost_httpgroup}} {{settings.phpfpm.vhost_httpuser}}]]></command>

View File

@@ -257,7 +257,15 @@ return array(
'values' => array(
array ('label' => $lng['panel']['yes'], 'value' => '1')
)
)
),
'dnsenabled' => array(
'label' => $lng['admin']['dnsenabled'].'?',
'type' => 'checkbox',
'values' => array(
array ('label' => $lng['panel']['yes'], 'value' => '1')
),
'visible' => (Settings::Get('system.dnsenabled') == '1' ? true : false)
),
)
)
)

View File

@@ -267,7 +267,16 @@ return array(
array ('label' => $lng['panel']['yes'], 'value' => '1')
),
'value' => array($result['perlenabled'])
)
),
'dnsenabled' => array(
'label' => $lng['admin']['dnsenabled'].'?',
'type' => 'checkbox',
'values' => array(
array ('label' => $lng['panel']['yes'], 'value' => '1')
),
'value' => array($result['dnsenabled']),
'visible' => (Settings::Get('system.dnsenabled') == '1' ? true : false)
),
)
),
'section_d' => array(

View File

@@ -94,6 +94,12 @@ class Autoloader {
dirname(dirname(__FILE__)) . '/install/',
);
if (substr($class, 0, 15) == "Mso\IdnaConvert") {
$class = substr($class, 16);
include_once __DIR__.'/classes/idna/ext/'.$class.'.php';
return true;
}
// now iterate through the paths
foreach ($paths as $path) {
// valid directory?

View File

@@ -0,0 +1,330 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Functions
*
*/
function createDomainZone($domain_id, $froxlorhostname = false, $isMainButSubTo = false)
{
if (!$froxlorhostname)
{
// get domain-name
$dom_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAINS . "` WHERE id = :did");
$domain = Database::pexecute_first($dom_stmt, array(
'did' => $domain_id
));
}
else
{
$domain = $domain_id;
}
if ($domain['isbinddomain'] != '1') {
return;
}
$dom_entries = array();
if (!$froxlorhostname)
{
// select all entries
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE domain_id = :did ORDER BY id ASC");
Database::pexecute($sel_stmt, array(
'did' => $domain_id
));
$dom_entries = $sel_stmt->fetchAll(PDO::FETCH_ASSOC);
}
// check for required records
$required_entries = array();
addRequiredEntry('@', 'A', $required_entries);
addRequiredEntry('@', 'AAAA', $required_entries);
if (! $isMainButSubTo) {
addRequiredEntry('@', 'NS', $required_entries);
}
if ($domain['isemaildomain'] === '1') {
addRequiredEntry('@', 'MX', $required_entries);
if (Settings::Get('system.dns_createmailentry')) {
foreach(['imap', 'pop3', 'mail', 'smtp'] as $record) {
foreach(['AAAA', 'A'] as $type) {
addRequiredEntry($record, $type, $required_entries);
}
}
}
}
// additional required records by setting
if ($domain['iswildcarddomain'] == '1') {
addRequiredEntry('*', 'A', $required_entries);
addRequiredEntry('*', 'AAAA', $required_entries);
} elseif ($domain['wwwserveralias'] == '1') {
addRequiredEntry('www', 'A', $required_entries);
addRequiredEntry('www', 'AAAA', $required_entries);
}
if (!$froxlorhostname)
{
// additional required records for subdomains
$subdomains_stmt = Database::prepare("
SELECT `domain`, `iswildcarddomain`, `wwwserveralias` FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `parentdomainid` = :domainid
");
Database::pexecute($subdomains_stmt, array(
'domainid' => $domain_id
));
while ($subdomain = $subdomains_stmt->fetch(PDO::FETCH_ASSOC)) {
// Listing domains is enough as there currently is no support for choosing
// different ips for a subdomain => use same IPs as toplevel
addRequiredEntry(str_replace('.' . $domain['domain'], '', $subdomain['domain']), 'A', $required_entries);
addRequiredEntry(str_replace('.' . $domain['domain'], '', $subdomain['domain']), 'AAAA', $required_entries);
// Check whether to add a www.-prefix
if ($subdomain['iswildcarddomain'] == '1') {
addRequiredEntry('*.' . str_replace('.' . $domain['domain'], '', $subdomain['domain']), 'A', $required_entries);
addRequiredEntry('*.' . str_replace('.' . $domain['domain'], '', $subdomain['domain']), 'AAAA', $required_entries);
} elseif ($subdomain['wwwserveralias'] == '1') {
addRequiredEntry('www.' . str_replace('.' . $domain['domain'], '', $subdomain['domain']), 'A', $required_entries);
addRequiredEntry('www.' . str_replace('.' . $domain['domain'], '', $subdomain['domain']), 'AAAA', $required_entries);
}
}
}
// additional required records for SPF and DKIM if activated
if ($domain['isemaildomain'] == '1') {
if (Settings::Get('spf.use_spf') == '1') {
// check for SPF content later
addRequiredEntry('@SPF@', 'TXT', $required_entries);
}
if (Settings::Get('dkim.use_dkim') == '1') {
// check for DKIM content later
addRequiredEntry('dkim_' . $domain['dkim_id'] . '._domainkey', 'TXT', $required_entries);
// check for ASDP
if (Settings::Get('dkim.dkim_add_adsp') == "1") {
addRequiredEntry('_adsp._domainkey', 'TXT', $required_entries);
}
}
}
$primary_ns = null;
$zonerecords = array();
// now generate all records and unset the required entries we have
foreach ($dom_entries as $entry) {
if (array_key_exists($entry['type'], $required_entries) && array_key_exists(md5($entry['record']), $required_entries[$entry['type']])) {
unset($required_entries[$entry['type']][md5($entry['record'])]);
}
if (Settings::Get('spf.use_spf') == '1' && $entry['type'] == 'TXT' && $entry['record'] == '@' && strtolower(substr($entry['content'], 0, 7)) == '"v=spf1') {
// unset special spf required-entry
unset($required_entries[$entry['type']][md5("@SPF@")]);
}
if (empty($primary_ns) && $entry['type'] == 'NS') {
// use the first NS entry as primary ns
$primary_ns = $entry['content'];
}
$zonerecords[] = new DnsEntry($entry['record'], $entry['type'], $entry['content'], $entry['prio'], $entry['ttl']);
}
// add missing required entries
if (! empty($required_entries)) {
// A / AAAA records
if (array_key_exists("A", $required_entries) || array_key_exists("AAAA", $required_entries)) {
if ($froxlorhostname) {
// use all available IP's for the froxlor-hostname
$result_ip_stmt = Database::prepare("
SELECT `ip` FROM `" . TABLE_PANEL_IPSANDPORTS . "` GROUP BY `ip`
");
Database::pexecute($result_ip_stmt);
} else {
$result_ip_stmt = Database::prepare("
SELECT `p`.`ip` AS `ip`
FROM `" . TABLE_PANEL_IPSANDPORTS . "` `p`, `" . TABLE_DOMAINTOIP . "` `di`
WHERE `di`.`id_domain` = :domainid AND `p`.`id` = `di`.`id_ipandports`
GROUP BY `p`.`ip`;
");
Database::pexecute($result_ip_stmt, array(
'domainid' => $domain_id
));
}
$all_ips = $result_ip_stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($all_ips as $ip) {
foreach ($required_entries as $type => $records) {
foreach ($records as $record) {
if ($type == 'A' && filter_var($ip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) {
$zonerecords[] = new DnsEntry($record, 'A', $ip['ip']);
} elseif ($type == 'AAAA' && filter_var($ip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) {
$zonerecords[] = new DnsEntry($record, 'AAAA', $ip['ip']);
}
}
}
}
unset($required_entries['A']);
unset($required_entries['AAAA']);
}
// NS records
if (array_key_exists("NS", $required_entries)) {
if (Settings::Get('system.nameservers') != '') {
$nameservers = explode(',', Settings::Get('system.nameservers'));
foreach ($nameservers as $nameserver) {
$nameserver = trim($nameserver);
// append dot to hostname
if (substr($nameserver, - 1, 1) != '.') {
$nameserver .= '.';
}
foreach ($required_entries as $type => $records) {
if ($type == 'NS') {
foreach ($records as $record) {
if (empty($primary_ns)) {
// use the first NS entry as primary ns
$primary_ns = $nameserver;
}
$zonerecords[] = new DnsEntry($record, 'NS', $nameserver);
}
}
}
}
unset($required_entries['NS']);
}
}
// MX records
if (array_key_exists("MX", $required_entries)) {
if (Settings::Get('system.mxservers') != '') {
$mxservers = explode(',', Settings::Get('system.mxservers'));
foreach ($mxservers as $mxserver) {
if (substr($mxserver, - 1, 1) != '.') {
$mxserver .= '.';
}
// split in prio and server
$mx_details = explode(" ", $mxserver);
if (count($mx_details) == 1) {
$mx_details[1] = $mx_details[0];
$mx_details[0] = 10;
}
foreach ($required_entries as $type => $records) {
if ($type == 'MX') {
foreach ($records as $record) {
$zonerecords[] = new DnsEntry($record, 'MX', $mx_details[1], $mx_details[0]);
}
}
}
}
unset($required_entries['MX']);
}
}
// TXT (SPF and DKIM)
if (array_key_exists("TXT", $required_entries)) {
if (Settings::Get('dkim.use_dkim') == '1') {
$dkim_entries = generateDkimEntries($domain);
}
foreach ($required_entries as $type => $records) {
if ($type == 'TXT') {
foreach ($records as $record) {
if ($record == '@SPF@') {
$txt_content = Settings::Get('spf.spf_entry');
$zonerecords[] = new DnsEntry('@', 'TXT', encloseTXTContent($txt_content));
} elseif ($record == 'dkim_' . $domain['dkim_id'] . '._domainkey' && ! empty($dkim_entries)) {
// check for multiline entry
$multiline = false;
if (substr($dkim_entries[0], 0, 1) == '(') {
$multiline = true;
}
$zonerecords[] = new DnsEntry($record, 'TXT', encloseTXTContent($dkim_entries[0], $multiline));
} elseif ($record == '_adsp._domainkey' && ! empty($dkim_entries) && isset($dkim_entries[1])) {
$zonerecords[] = new DnsEntry($record, 'TXT', encloseTXTContent($dkim_entries[1]));
}
}
}
}
}
}
if (empty($primary_ns)) {
// TODO log error: no NS given, use system-hostname
$primary_ns = Settings::Get('system.hostname');
}
if (! $isMainButSubTo) {
$date = date('Ymd');
$domain['bindserial'] = (preg_match('/^' . $date . '/', $domain['bindserial']) ?
$domain['bindserial'] + 1 :
$date . '00');
if (!$froxlorhostname) {
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
`bindserial` = :serial
WHERE `id` = :id
");
Database::pexecute($upd_stmt, array('serial' => $domain['bindserial'], 'id' => $domain['id']));
}
$soa_content = $primary_ns . " " . escapeSoaAdminMail(Settings::Get('panel.adminmail')) . " (" . PHP_EOL;
$soa_content .= $domain['bindserial'] . "\t; serial" . PHP_EOL;
// TODO for now, dummy time-periods
$soa_content .= "1800\t; refresh (30 mins)" . PHP_EOL;
$soa_content .= "900\t; retry (15 mins)" . PHP_EOL;
$soa_content .= "604800\t; expire (7 days)" . PHP_EOL;
$soa_content .= "1200\t)\t; minimum (20 mins)";
$soa_record = new DnsEntry('@', 'SOA', $soa_content);
array_unshift($zonerecords, $soa_record);
}
$zone = new DnsZone((int) Settings::Get('system.defaultttl'), $domain['domain'], $domain['bindserial'], $zonerecords);
return $zone;
}
function addRequiredEntry($record = '@', $type = 'A', &$required)
{
if (! isset($required[$type])) {
$required[$type] = array();
}
$required[$type][md5($record)] = $record;
}
function encloseTXTContent($txt_content, $isMultiLine = false)
{
// check that TXT content is enclosed in " "
if ($isMultiLine == false && Settings::Get('system.dns_server') != 'pdns') {
if (substr($txt_content, 0, 1) != '"') {
$txt_content = '"' . $txt_content;
}
if (substr($txt_content, - 1) != '"') {
$txt_content .= '"';
}
}
if (Settings::Get('system.dns_server') == 'pdns') {
// no quotation for PowerDNS
if (substr($txt_content, 0, 1) == '"') {
$txt_content = substr($txt_content, 1);
}
if (substr($txt_content, - 1) == '"') {
$txt_content = substr($txt_content, 0, -1);
}
}
return $txt_content;
}
function escapeSoaAdminMail($email)
{
$mail_parts = explode("@", $email);
$escpd_mail = str_replace(".", "\.", $mail_parts[0]).".".$mail_parts[1].".";
return $escpd_mail;
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Functions
*
*/
function generateDkimEntries($domain)
{
$zone_dkim = array();
if (Settings::Get('dkim.use_dkim') == '1' && $domain['dkim'] == '1' && $domain['dkim_pubkey'] != '') {
// start
$dkim_txt = 'v=DKIM1;';
// algorithm
$algorithm = explode(',', Settings::Get('dkim.dkim_algorithm'));
$alg = '';
foreach ($algorithm as $a) {
if ($a == 'all') {
break;
} else {
$alg .= $a . ':';
}
}
if ($alg != '') {
$alg = substr($alg, 0, - 1);
$dkim_txt .= 'h=' . $alg . ';';
}
// notes
if (trim(Settings::Get('dkim.dkim_notes') != '')) {
$dkim_txt .= 'n=' . trim(Settings::Get('dkim.dkim_notes')) . ';';
}
// key
$dkim_txt .= 'k=rsa;p=' . trim(preg_replace('/-----BEGIN PUBLIC KEY-----(.+)-----END PUBLIC KEY-----/s', '$1', str_replace("\n", '', $domain['dkim_pubkey']))) . ';';
// service-type
if (Settings::Get('dkim.dkim_servicetype') == '1') {
$dkim_txt .= 's=email;';
}
// end-part
$dkim_txt .= 't=s';
if (Settings::Get('system.dns_server') == 'pdns') {
// PowerDNS does not need/want splitted content
$txt_record_split = $dkim_txt;
} else {
// split if necessary
$txt_record_split = '';
$lbr = 50;
for ($pos = 0; $pos <= strlen($dkim_txt) - 1; $pos += $lbr) {
$txt_record_split .= (($pos == 0) ? '("' : "\t\t\t\t\t \"") . substr($dkim_txt, $pos, $lbr) . (($pos >= strlen($dkim_txt) - $lbr) ? '")' : '"') . "\n";
}
}
// dkim-entry
$zone_dkim[] = $txt_record_split;
// adsp-entry
if (Settings::Get('dkim.dkim_add_adsp') == "1") {
$adsp = '"dkim=';
switch ((int) Settings::Get('dkim.dkim_add_adsppolicy')) {
case 0:
$adsp .= 'unknown"';
break;
case 1:
$adsp .= 'all"';
break;
case 2:
$adsp .= 'discardable"';
break;
}
$zone_dkim[] = $adsp;
}
}
return $zone_dkim;
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Functions
*
*/
function getAllowedDomainEntry($domain_id, $area = 'customer', $userinfo, &$idna_convert)
{
$dom_data = array(
'did' => $domain_id
);
$where_clause = '';
if ($area == 'admin') {
if ($userinfo['domains_see_all'] != '1') {
$where_clause = '`adminid` = :uid AND ';
$dom_data['uid'] = $userinfo['userid'];
}
} else {
$where_clause = '`customerid` = :uid AND ';
$dom_data['uid'] = $userinfo['userid'];
}
$dom_stmt = Database::prepare("
SELECT domain, isbinddomain
FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE " . $where_clause . " id = :did
");
$domain = Database::pexecute_first($dom_stmt, $dom_data);
if ($domain) {
if ($domain['isbinddomain'] != '1') {
standard_error('dns_domain_nodns');
}
return $idna_convert->decode($domain['domain']);
}
standard_error('dns_notfoundorallowed');
}

View File

@@ -21,7 +21,8 @@ function getFormFieldData($fieldname, $fielddata, &$input)
{
if(is_array($fielddata) && isset($fielddata['type']) && $fielddata['type'] != '' && function_exists('getFormFieldData' . ucfirst($fielddata['type'])))
{
$newfieldvalue = call_user_func('getFormFieldData' . ucfirst($fielddata['type']), $fieldname, $fielddata, $input);
$gfdFunc = 'getFormFieldData' . ucfirst($fielddata['type']);
$newfieldvalue = $gfdFunc($fieldname, $fielddata, $input);
}
else
{
@@ -38,6 +39,6 @@ function getFormFieldData($fieldname, $fielddata, &$input)
$newfieldvalue = false;
}
}
return trim($newfieldvalue);
}

View File

@@ -48,11 +48,12 @@ return array (
'email' => array (
'url' => 'customer_email.php',
'label' => $lng['menue']['email']['email'],
'show_element' => ( !Settings::IsInList('panel.customer_hide_options','email') ),
'elements' => array (
array (
'url' => 'customer_email.php?page=emails',
'label' => $lng['menue']['email']['emails'],
'required_resources' => 'emails',
'required_resources' => 'emails'
),
array (
'url' => 'customer_email.php?page=emails&action=add',
@@ -71,6 +72,7 @@ return array (
'mysql' => array (
'url' => 'customer_mysql.php',
'label' => $lng['menue']['mysql']['mysql'],
'show_element' => ( !Settings::IsInList('panel.customer_hide_options','mysql') ),
'elements' => array (
array (
'url' => 'customer_mysql.php?page=mysqls',
@@ -89,6 +91,7 @@ return array (
'domains' => array (
'url' => 'customer_domains.php',
'label' => $lng['menue']['domains']['domains'],
'show_element' => ( !Settings::IsInList('panel.customer_hide_options','domains') ),
'elements' => array (
array (
'url' => 'customer_domains.php?page=domains',
@@ -99,6 +102,7 @@ return array (
'ftp' => array (
'url' => 'customer_ftp.php',
'label' => $lng['menue']['ftp']['ftp'],
'show_element' => ( !Settings::IsInList('panel.customer_hide_options','ftp') ),
'elements' => array (
array (
'url' => 'customer_ftp.php?page=accounts',
@@ -115,30 +119,34 @@ return array (
'extras' => array (
'url' => 'customer_extras.php',
'label' => $lng['menue']['extras']['extras'],
'show_element' => ( !Settings::IsInList('panel.customer_hide_options','extras') ),
'elements' => array (
array (
'url' => 'customer_extras.php?page=htpasswds',
'label' => $lng['menue']['extras']['directoryprotection'],
'show_element' => ( !Settings::IsInList('panel.customer_hide_options','extras.directoryprotection') ),
),
array (
'url' => 'customer_extras.php?page=htaccess',
'label' => $lng['menue']['extras']['pathoptions'],
'show_element' => ( !Settings::IsInList('panel.customer_hide_options','extras.pathoptions') ),
),
array (
'url' => 'customer_logger.php?page=log',
'label' => $lng['menue']['logger']['logger'],
'show_element' => ( Settings::Get('logger.enabled') == true )
'show_element' => ( Settings::Get('logger.enabled') == true ) && ( !Settings::IsInList('panel.customer_hide_options','extras.logger') ),
),
array (
'url' => 'customer_extras.php?page=backup',
'label' => $lng['menue']['extras']['backup'],
'show_element' => ( Settings::Get('system.backupenabled') == true ),
'show_element' => ( Settings::Get('system.backupenabled') == true ) && ( !Settings::IsInList('panel.customer_hide_options','extras.backup') ),
),
),
),
'traffic' => array (
'url' => 'customer_traffic.php',
'label' => $lng['menue']['traffic']['traffic'],
'show_element' => ( !Settings::IsInList('panel.customer_hide_options','traffic') ),
'elements' => array (
array (
'url' => 'customer_traffic.php?page=current',

View File

@@ -50,5 +50,6 @@ define('TABLE_PANEL_REDIRECTCODES', 'redirect_codes');
define('TABLE_PANEL_DOMAINREDIRECTS', 'domain_redirect_codes');
define('TABLE_PANEL_DOMAIN_SSL_SETTINGS', 'domain_ssl_settings');
define('TABLE_DOMAINTOIP', 'panel_domaintoip');
define('TABLE_DOMAIN_DNS', 'domain_dns_entries');
require dirname(__FILE__).'/version.inc.php';

View File

@@ -16,10 +16,10 @@
*/
// Main version variable
$version = '0.9.36';
$version = '0.9.37';
// Database version (YYYYMMDDC where C is a daily counter)
$dbversion = '201604270';
$dbversion = '201607210';
// Distribution branding-tag (used for Debian etc.)
$branding = '';

View File

@@ -394,7 +394,7 @@ $lng['serversettings']['defaultip']['title'] = 'Standaard IP/Poort';
$lng['serversettings']['defaultip']['description'] = 'Wat is de standaard IP/Poort combinatie?';
$lng['domains']['statstics'] = 'Gebruiks Statistieken';
$lng['panel']['ascending'] = 'oplopend';
$lng['panel']['decending'] = 'aflopend';
$lng['panel']['descending'] = 'aflopend';
$lng['panel']['search'] = 'Zoeken';
$lng['panel']['used'] = 'gebruikt';

View File

@@ -22,17 +22,17 @@
*/
$lng['translator'] = '';
$lng['panel']['edit'] = 'edit';
$lng['panel']['delete'] = 'delete';
$lng['panel']['create'] = 'create';
$lng['panel']['save'] = 'save';
$lng['panel']['yes'] = 'yes';
$lng['panel']['no'] = 'no';
$lng['panel']['edit'] = 'Edit';
$lng['panel']['delete'] = 'Delete';
$lng['panel']['create'] = 'Create';
$lng['panel']['save'] = 'Save';
$lng['panel']['yes'] = 'Yes';
$lng['panel']['no'] = 'No';
$lng['panel']['emptyfornochanges'] = 'empty for no changes';
$lng['panel']['emptyfordefault'] = 'empty for defaults';
$lng['panel']['path'] = 'Path';
$lng['panel']['toggle'] = 'Toggle';
$lng['panel']['next'] = 'next';
$lng['panel']['next'] = 'Next';
$lng['panel']['dirsmissing'] = 'Can not find or read the directory!';
/**
@@ -344,10 +344,10 @@ $lng['serversettings']['apachereload_command']['title'] = 'Webserver reload comm
$lng['serversettings']['apachereload_command']['description'] = 'What\'s the webserver command to reload configfiles?';
$lng['serversettings']['bindenable']['title'] = 'Enable Nameserver';
$lng['serversettings']['bindenable']['description'] = 'Here the Nameserver can be enabled and disabled globaly.';
$lng['serversettings']['bindconf_directory']['title'] = 'Bind config directory';
$lng['serversettings']['bindconf_directory']['description'] = 'Where should bind configfiles be saved?';
$lng['serversettings']['bindreload_command']['title'] = 'Bind reload command';
$lng['serversettings']['bindreload_command']['description'] = 'What\'s the bind command to reload bind configfiles?';
$lng['serversettings']['bindconf_directory']['title'] = 'Dns server config directory';
$lng['serversettings']['bindconf_directory']['description'] = 'Where should dns-server configfiles be saved?';
$lng['serversettings']['bindreload_command']['title'] = 'DNS server reload command';
$lng['serversettings']['bindreload_command']['description'] = 'What\'s the command to reload the dns server daemon?';
$lng['serversettings']['vmail_uid']['title'] = 'Mails-UID';
$lng['serversettings']['vmail_uid']['description'] = 'Which UserID should mails have?';
$lng['serversettings']['vmail_gid']['title'] = 'Mails-GID';
@@ -437,7 +437,7 @@ $lng['serversettings']['defaultip']['title'] = 'Default IP/Port';
$lng['serversettings']['defaultip']['description'] = 'Select all IP-addresses you want to use as default for new domains';
$lng['domains']['statstics'] = 'Usage Statistics';
$lng['panel']['ascending'] = 'ascending';
$lng['panel']['decending'] = 'decending';
$lng['panel']['descending'] = 'descending';
$lng['panel']['search'] = 'Search';
$lng['panel']['used'] = 'used';
@@ -477,7 +477,7 @@ $lng['serversettings']['deactivateddocroot']['description'] = 'When a user is de
// ADDED IN 1.2.16-svn4
$lng['panel']['reset'] = 'discard changes';
$lng['panel']['reset'] = 'Discard changes';
$lng['admin']['accountsettings'] = 'Account settings';
$lng['admin']['panelsettings'] = 'Panel settings';
$lng['admin']['systemsettings'] = 'System settings';
@@ -779,8 +779,11 @@ $lng['message']['noreceipients'] = 'No e-mail has been sent because there are no
$lng['admin']['sslsettings'] = 'SSL settings';
$lng['cronjobs']['notyetrun'] = 'Not yet run';
$lng['serversettings']['default_vhostconf']['title'] = 'Default vHost-settings';
$lng['serversettings']['default_vhostconf']['description'] = 'The content of this field will be included into this ip/port vHost container directly. Attention: The code won\'t be checked for any errors. If it contains errors, webserver might not start again!';
$lng['serversettings']['default_vhostconf_domain']['description'] = 'The content of this field will be included into the domain vHost container directly. Attention: The code won\'t be checked for any errors. If it contains errors, webserver might not start again!';
$lng['admin']['specialsettings_replacements'] = "You can use the following variables:<br/><code>{DOMAIN}</code>, <code>{DOCROOT}</code>, <code>{CUSTOMER}</code>, <code>{IP}</code>, <code>{PORT}</code>, <code>{SCHEME}</code><br/>";
$lng['serversettings']['default_vhostconf']['description'] = 'The content of this field will be included into this ip/port vHost container directly. '.$lng['admin']['specialsettings_replacements'].' Attention: The code won\'t be checked for any errors. If it contains errors, webserver might not start again!';
$lng['serversettings']['apache_globaldiropt']['title'] = 'Directory options for customer-prefix';
$lng['serversettings']['apache_globaldiropt']['description'] = 'The content of this field will be included into the 05_froxlor_dirfix_nofcgid.conf apache config. If empty, the default value is used:<br><br>apache >=2.4<br><code>Require all granted<br>AllowOverride All</code><br><br>apache <=2.2<br><code>Order allow,deny<br>allow from all</code>';
$lng['serversettings']['default_vhostconf_domain']['description'] = 'The content of this field will be included into the domain vHost container directly. '.$lng['admin']['specialsettings_replacements'].' Attention: The code won\'t be checked for any errors. If it contains errors, webserver might not start again!';
$lng['error']['invalidip'] = 'Invalid IP address: %s';
$lng['serversettings']['decimal_places'] = 'Number of decimal places in traffic/webspace output';
@@ -1273,7 +1276,7 @@ $lng['admin']['ipsandports']['ssl_cert_chainfile']['description'] = 'Mostly CA_B
$lng['admin']['ipsandports']['docroot']['title'] = 'Custom docroot (empty = point to Froxlor)';
$lng['admin']['ipsandports']['docroot']['description'] = 'You can define a custom document-root (the destination for a request) for this ip/port combination here.<br /><strong>ATTENTION:</strong> Please be careful with what you enter here!';
$lng['serversettings']['login_domain_login'] = 'Allow login with domains';
$lng['panel']['unlock'] = 'unlock';
$lng['panel']['unlock'] = 'Unlock';
$lng['question']['customer_reallyunlock'] = 'Do you really want to unlock customer %s?';
// ADDED IN FROXLOR 0.9.15
@@ -1314,8 +1317,10 @@ $lng['phpfpm']['ownvhost']['description'] = 'If enabled, Froxlor will also be ru
// ADDED IN FROXLOR 0.9.17
$lng['crondesc']['cron_usage_report'] = 'Web- and traffic-reports';
$lng['serversettings']['report']['report'] = 'Enable sending of reports about web- and traffic-usage';
$lng['serversettings']['report']['webmax'] = 'Warning-level in percent for webspace';
$lng['serversettings']['report']['trafficmax'] = 'Warning-level in percent for traffic';
$lng['serversettings']['report']['webmax']['title'] = 'Warning-level in percent for webspace';
$lng['serversettings']['report']['webmax']['description'] = 'Valid values are 0 up to 150. Setting this value to 0 disables this report.';
$lng['serversettings']['report']['trafficmax']['title'] = 'Warning-level in percent for traffic';
$lng['serversettings']['report']['trafficmax']['description'] = 'Valid values are 0 up to 150. Setting this value to 0 disables this report.';
$lng['mails']['trafficmaxpercent']['mailbody'] = 'Dear {NAME},\n\nyou used {TRAFFICUSED} MB of your available {TRAFFIC} MB of traffic.\nThis is more than {MAX_PERCENT}%.\n\nYours sincerely, your administrator';
$lng['mails']['trafficmaxpercent']['subject'] = 'Reaching your traffic limit';
$lng['admin']['templates']['trafficmaxpercent'] = 'Notification mail for customers when given maximum of percent of traffic is exhausted';
@@ -1733,8 +1738,8 @@ $lng['serversettings']['ssl']['ssl_cipher_list']['description'] = 'This is a lis
// Added in Froxlor 0.9.31
$lng['panel']['dashboard'] = 'Dashboard';
$lng['panel']['assigned'] = 'assigned';
$lng['panel']['available'] = 'available';
$lng['panel']['assigned'] = 'Assigned';
$lng['panel']['available'] = 'Available';
$lng['customer']['services'] = 'Services';
$lng['serversettings']['phpfpm_settings']['ipcdir']['title'] = 'FastCGI IPC directory';
$lng['serversettings']['phpfpm_settings']['ipcdir']['description'] = 'The directory where the php-fpm sockets will be stored by the webserver.<br />This directory has to be readable for the webserver';
@@ -1852,9 +1857,6 @@ $lng['integrity_check']['SubdomainSslRedirect'] = 'False SSL-redirect flag for n
$lng['integrity_check']['FroxlorLocalGroupMemberForFcgidPhpFpm'] = 'froxlor-user in the customer groups (for FCGID/php-fpm)';
$lng['integrity_check']['WebserverGroupMemberForFcgidPhpFpm'] = 'Webserver-user in the customer groups (for FCGID/php-fpm)';
$lng['integrity_check']['SubdomainLetsencrypt'] = 'Main domains with no SSL-Port assigned don\'t have any subdomains with active SSL redirect';
$lng['admin']['specialsettings_replacements'] = "You can use the following variables:<br/><code>{DOMAIN}</code>, <code>{DOCROOT}</code>, <code>{CUSTOMER}</code>, <code>{IP}</code>, <code>{PORT}</code>, <code>{SCHEME}</code><br/>";
$lng['serversettings']['default_vhostconf']['description'] = 'The content of this field will be included into this ip/port vHost container directly. '.$lng['admin']['specialsettings_replacements'].' Attention: The code won\'t be checked for any errors. If it contains errors, webserver might not start again!';
$lng['serversettings']['default_vhostconf_domain']['description'] = 'The content of this field will be included into the domain vHost container directly. '.$lng['admin']['specialsettings_replacements'].' Attention: The code won\'t be checked for any errors. If it contains errors, webserver might not start again!';
$lng['admin']['mod_fcgid_umask']['title'] = 'Umask (default: 022)';
// Added for apcuinfo
@@ -1981,6 +1983,7 @@ $lng['extras']['backup_mail'] = 'Backup mail-data';
$lng['extras']['backup_dbs'] = 'Backup databases';
$lng['error']['customerhasongoingbackupjob'] = 'There is already a backup job waiting to be processed, please be patient.';
$lng['success']['backupscheduled'] = 'Your backup job has been scheduled. Please wait for it to be processed';
$lng['success']['backupaborted'] = 'Your scheduled backup has been cancelled';
$lng['crondesc']['cron_backup'] = 'Process backup jobs';
$lng['error']['backupfunctionnotenabled'] = 'The backup function is not enabled';
$lng['serversettings']['backupenabled']['title'] = "Enable backup for customers";
@@ -1989,4 +1992,37 @@ $lng['extras']['path_protection_label'] = '<strong class="red">Important</strong
$lng['extras']['path_protection_info'] = '<strong class="red">We strongly recommend protecting the given path, see "Extras" -> "Directory protection"</strong>';
$lng['tasks']['backup_customerfiles'] = 'Backup job for customer %loginname%';
$lng['error']['dns_domain_nodns'] = 'DNS is not enabled for this domain';
$lng['error']['dns_content_empty'] = 'No content given';
$lng['error']['dns_arec_noipv4'] = 'No valid IP address for A-record given';
$lng['error']['dns_aaaarec_noipv6'] = 'No valid IP address for AAAA-record given';
$lng['error']['dns_mx_prioempty'] = 'Invalid MX priority given';
$lng['error']['dns_mx_needdom'] = 'The MX content value must be a valid domain-name';
$lng['error']['dns_mx_noalias'] = 'The MX-content value cannot be an CNAME entry.';
$lng['error']['dns_cname_invaliddom'] = 'Invalid domain-name for CNAME record';
$lng['error']['dns_cname_nomorerr'] = 'There already exists a resource-record with the same record-name. It cannot be used as CNAME.';
$lng['error']['dns_ns_invaliddom'] = 'Invalid domain-name for NS record';
$lng['error']['dns_srv_prioempty'] = 'Invalid SRV priority given';
$lng['error']['dns_srv_invalidcontent'] = 'Invalid SRV content, must contain of fields weight, port and target, e.g.: 5 5060 sipserver.example.com.';
$lng['error']['dns_srv_needdom'] = 'The SRV target value must be a valid domain-name';
$lng['error']['dns_srv_noalias'] = 'The SRV-target value cannot be an CNAME entry.';
$lng['error']['dns_duplicate_entry'] = 'Record already exists';
$lng['success']['dns_record_added'] = 'Record added successfully';
$lng['success']['dns_record_deleted'] = 'Record deleted successfully';
$lng['dnseditor']['edit'] = 'edit DNS';
$lng['dnseditor']['records'] = 'records';
$lng['error']['dns_notfoundorallowed'] = 'Domain not found or no permission';
$lng['serversettings']['dnseditorenable']['title'] = 'Enable DNS editor';
$lng['serversettings']['dnseditorenable']['description'] = 'Allows admins and customer to manage domain dns entries';
$lng['dns']['howitworks'] = 'Here you can manage DNS entries for your domain. Note that froxlor will automatically generate NS/MX/A/AAAA records for you. The custom entries are prefered, only missing entries will be automatically generated.';
$lng['serversettings']['dns_server']['title'] = 'DNS server daemon';
$lng['serversettings']['dns_server']['description'] = 'Remember that daemons have to be configured using froxlors configuration templates';
$lng['error']['domain_nopunycode'] = 'You must not specify punycode (IDNA). The domain will automatically be converted';
$lng['admin']['dnsenabled'] = 'Enable DNS editor';
$lng['error']['dns_record_toolong'] = 'Records/labels can only be up to 63 characters';
// Added in froxlor 0.9.7-rc1
$lng['serversettings']['panel_customer_hide_options']['title'] = 'Hide menu items and traffic charts in customer panel';
$lng['serversettings']['panel_customer_hide_options']['description'] = 'Select items to hide in customer panel. To select multiple options, hold down CTRL while selecting.';

View File

@@ -427,7 +427,7 @@ $lng['serversettings']['defaultip']['title'] = 'IP / Port par défaut';
$lng['serversettings']['defaultip']['description'] = 'Quel est l\'IP / Port par défaut ?';
$lng['domains']['statstics'] = 'Fréquentation';
$lng['panel']['ascending'] = 'ascendant';
$lng['panel']['decending'] = 'descendant';
$lng['panel']['descending'] = 'descendant';
$lng['panel']['search'] = 'Rechercher';
$lng['panel']['used'] = 'utilisé';

View File

@@ -341,10 +341,10 @@ $lng['serversettings']['apachereload_command']['title'] = 'Webserver-Reload-Comm
$lng['serversettings']['apachereload_command']['description'] = 'Wie heißt das Skript zum Neuladen der Webserver-Konfigurationsdateien?';
$lng['serversettings']['bindenable']['title'] = 'Nameserver aktivieren';
$lng['serversettings']['bindenable']['description'] = 'Hier können Sie den Nameserver global aktivieren bzw. deaktivieren.';
$lng['serversettings']['bindconf_directory']['title'] = 'Bind-Config-Directory';
$lng['serversettings']['bindconf_directory']['description'] = 'Wo liegen die Bind-Konfigurationsdateien?';
$lng['serversettings']['bindreload_command']['title'] = 'Bind-Reload-Command';
$lng['serversettings']['bindreload_command']['description'] = 'Wie heißt das Skript zum Neuladen der Bind-Konfigurationsdateien?';
$lng['serversettings']['bindconf_directory']['title'] = 'DNS-Server Konfigurationsordner';
$lng['serversettings']['bindconf_directory']['description'] = 'Wo liegen die DNS-Server Konfigurationsdateien?';
$lng['serversettings']['bindreload_command']['title'] = 'DNS-Server Reload-Befehl';
$lng['serversettings']['bindreload_command']['description'] = 'Wie heißt das Skript zum Neuladen der DNS-Server Konfigurationsdateien?';
$lng['serversettings']['vmail_uid']['title'] = 'Mail-UID';
$lng['serversettings']['vmail_uid']['description'] = 'Welche UID sollen die E-Mails haben?';
$lng['serversettings']['vmail_gid']['title'] = 'Mail-GID';
@@ -433,7 +433,7 @@ $lng['serversettings']['defaultip']['title'] = 'Standard-IP/Port';
$lng['serversettings']['defaultip']['description'] = 'Welche IP/Port-Kombination sollen standardmäßig verwendet werden?';
$lng['domains']['statstics'] = 'Statistiken';
$lng['panel']['ascending'] = 'aufsteigend';
$lng['panel']['decending'] = 'absteigend';
$lng['panel']['descending'] = 'absteigend';
$lng['panel']['search'] = 'Suche';
$lng['panel']['used'] = 'genutzt';
@@ -775,8 +775,11 @@ $lng['message']['noreceipients'] = 'Es wurde keine E-Mail versendet da sich kein
$lng['admin']['sslsettings'] = 'SSL-Einstellungen';
$lng['cronjobs']['notyetrun'] = 'Bisher nicht gestartet';
$lng['serversettings']['default_vhostconf']['title'] = 'Standard vHost-Einstellungen';
$lng['serversettings']['default_vhostconf']['description'] = 'Der Inhalt dieses Feldes wird direkt in den IP/Port-vHost-Container übernommen.<br /><strong>ACHTUNG:</strong> Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Der Webserver könnte nicht mehr starten!';
$lng['serversettings']['default_vhostconf_domain']['description'] = 'Der Inhalt dieses Feldes wird direkt in jeden Domain-vHost-Container übernommen.<br /><strong>ACHTUNG:</strong> Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Der Webserver könnte nicht mehr starten!';
$lng['admin']['specialsettings_replacements'] = "Die folgenden Variablen können verwendet werden:<br/><code>{DOMAIN}</code>, <code>{DOCROOT}</code>, <code>{CUSTOMER}</code>, <code>{IP}</code>, <code>{PORT}</code>, <code>{SCHEME}</code><br/>";
$lng['serversettings']['default_vhostconf']['description'] = 'Der Inhalt dieses Feldes wird direkt in den IP/Port-vHost-Container übernommen. '.$lng['admin']['specialsettings_replacements'].'<br /><strong>ACHTUNG:</strong> Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Der Webserver könnte nicht mehr starten!';
$lng['serversettings']['default_vhostconf_domain']['description'] = 'Der Inhalt dieses Feldes wird direkt in jeden Domain-vHost-Container übernommen. '. $lng['admin']['specialsettings_replacements'].'<strong>ACHTUNG:</strong> Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Der Webserver könnte nicht mehr starten!';
$lng['serversettings']['apache_globaldiropt']['title'] = 'Kunden-Prefix Ordner-Optionen';
$lng['serversettings']['apache_globaldiropt']['description'] = 'Der Inhalt dieses Feldes wird in die 05_froxlor_dirfix_nofcgid.conf Apache Konfigurationsdatei eingefügt. Wenn leer werden folgende Standardwerte verwendet:<br><br>apache >=2.4<br><code>Require all granted<br>AllowOverride All</code><br><br>apache <=2.2<br><code>Order allow,deny<br>allow from all</code>';
$lng['error']['invalidip'] = 'Ungültige IP-Adresse: "%s"';
$lng['serversettings']['decimal_places'] = 'Nachkommastellen bei der Ausgabe von Traffic/Webspace';
@@ -1293,8 +1296,10 @@ $lng['phpfpm']['ownvhost']['description'] = 'Wenn verwendet, wird Froxlor selbst
// ADDED IN FROXLOR 0.9.17
$lng['crondesc']['cron_usage_report'] = 'Webspace- und Trafficreport';
$lng['serversettings']['report']['report'] = 'Aktiviere das Senden von Reports über Webspace- und Trafficverbrauch';
$lng['serversettings']['report']['webmax'] = 'Warn-Level in Prozent für Webspace';
$lng['serversettings']['report']['trafficmax'] = 'Warn-Level in Prozent für Traffic';
$lng['serversettings']['report']['webmax']['title'] = 'Warn-Level in Prozent für Webspace';
$lng['serversettings']['report']['webmax']['description'] = 'Gültige Werte sind von 0 bis 150. Der Wert 0 deaktiviert diesen Report.';
$lng['serversettings']['report']['trafficmax']['title'] = 'Warn-Level in Prozent für Traffic';
$lng['serversettings']['report']['trafficmax']['description'] = 'Gültige Werte sind von 0 bis 150. Der Wert 0 deaktiviert diesen Report.';
$lng['mails']['trafficmaxpercent']['mailbody'] = 'Sehr geehrte(r) {NAME},\n\nSie haben bereits {TRAFFICUSED} MB von Ihren insgesamt {TRAFFIC} MB Traffic verbraucht.\nDies sind mehr als {MAX_PERCENT}%.\n\nVielen Dank,\nIhr Administrator';
$lng['mails']['trafficmaxpercent']['subject'] = 'Sie erreichen bald Ihr Traffic-Limit';
$lng['admin']['templates']['trafficmaxpercent'] = 'Hinweismail für Kunden, wenn sie die angegebenen Prozent des Traffics verbraucht haben';
@@ -1578,9 +1583,6 @@ $lng['integrity_check']['SubdomainSslRedirect'] = 'Falsches SSL-redirect Flag be
$lng['integrity_check']['FroxlorLocalGroupMemberForFcgidPhpFpm'] = 'froxlor-Benutzer in Kunden-Gruppen (f&uuml;r FCGID/php-fpm)';
$lng['integrity_check']['WebserverGroupMemberForFcgidPhpFpm'] = 'Webserver-Benutzer in Kunden-Gruppen (f&uuml;r FCGID/php-fpm)';
$lng['integrity_check']['SubdomainLetsencrypt'] = 'Hauptdomains ohne zugewiesenen SSL-Port haben keine Subdomain mit aktiviertem SSL-Redirect';
$lng['admin']['specialsettings_replacements'] = "Die folgenden Variablen können verwendet werden:<br/><code>{DOMAIN}</code>, <code>{DOCROOT}</code>, <code>{CUSTOMER}</code>, <code>{IP}</code>, <code>{PORT}</code>, <code>{SCHEME}</code><br/>";
$lng['serversettings']['default_vhostconf']['description'] = 'Der Inhalt dieses Feldes wird direkt in den IP/Port-vHost-Container übernommen. '.$lng['admin']['specialsettings_replacements'].'<br /><strong>ACHTUNG:</strong> Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Der Webserver könnte nicht mehr starten!';
$lng['serversettings']['default_vhostconf_domain']['description'] = 'Der Inhalt dieses Feldes wird direkt in jeden Domain-vHost-Container übernommen. '. $lng['admin']['specialsettings_replacements'].'<strong>ACHTUNG:</strong> Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Der Webserver könnte nicht mehr starten!';
$lng['admin']['mod_fcgid_umask']['title'] = 'Umask (Standard: 022)';
// Added for let's encrypt
@@ -1634,6 +1636,7 @@ $lng['extras']['backup_mail'] = 'E-Mail Daten sichern';
$lng['extras']['backup_dbs'] = 'Datenbanken sichern';
$lng['error']['customerhasongoingbackupjob'] = 'Es gibt noch einen austehenden Backup-Job. Bitte haben Sie etwas Geduld.';
$lng['success']['backupscheduled'] = 'Ihre Sicherung wurde erfolgreich geplant. Bitte warten Sie nun, bis diese abgearbeitet wurde.';
$lng['success']['backupaborted'] = 'Die geplante Sicherung wurde abgebrochen';
$lng['crondesc']['cron_backup'] = 'Ausstehende Sicherungen erstellen';
$lng['error']['backupfunctionnotenabled'] = 'Die Sicherungs-Funktion is nicht aktiviert';
$lng['serversettings']['backupenabled']['title'] = "Backup für Kunden aktivieren";
@@ -1642,4 +1645,36 @@ $lng['extras']['path_protection_label'] = '<strong class="red">Wichtig</strong>'
$lng['extras']['path_protection_info'] = '<strong class="red">Wir raten dringend dazu den angegebenen Pfad zu schützen, siehe "Extras" -> "Verzeichnisschutz"</strong>';
$lng['tasks']['backup_customerfiles'] = 'Datensicherung für Kunde %loginname%';
$lng['error']['dns_domain_nodns'] = 'DNS ist für diese Domain nicht aktiviert';
$lng['error']['dns_content_empty'] = 'Keinen Inhalt angegeben';
$lng['error']['dns_arec_noipv4'] = 'Kein gültige IP Adresse für A-Eintrag angegeben';
$lng['error']['dns_aaaarec_noipv6'] = 'Kein gültige IP Adresse für AAAA-Eintrag angegeben';
$lng['error']['dns_mx_prioempty'] = 'Ungültige MX Priorität angegeben';
$lng['error']['dns_mx_needdom'] = 'Der Wert des MX Eintrags muss ein gültiger Domainname sein';
$lng['error']['dns_mx_noalias'] = 'Der MX Eintrag darf kein CNAME Eintrag sein.';
$lng['error']['dns_cname_invaliddom'] = 'Ungültiger Domain-Name für CNAME Eintrag';
$lng['error']['dns_cname_nomorerr'] = 'Es existiert bereits ein Eintrag mit dem gleichen Namen. Dieser Eintrag kann daher nicht für CNAME genutzt werden.';
$lng['error']['dns_ns_invaliddom'] = 'Ungültiger Domain-Name für NS Eintrag';
$lng['error']['dns_srv_prioempty'] = 'Ungültige SRV Priorität angegeben';
$lng['error']['dns_srv_invalidcontent'] = 'Ungültiger Wert des SRV Eintrags, dieser muss aus den Feldern: weight, port und target, bestehen. Bsp.: 5 5060 sipserver.example.com.';
$lng['error']['dns_srv_needdom'] = 'Der Wert des SRV Eintrags muss ein gültiger Domainname sein';
$lng['error']['dns_srv_noalias'] = 'Der SRV Eintrag darf kein CNAME Eintrag sein..';
$lng['error']['dns_duplicate_entry'] = 'Eintrag existiert bereits';
$lng['success']['dns_record_added'] = 'Eintrag erfolgreich hinzugefügt';
$lng['success']['dns_record_deleted'] = 'Eintrag erfolgreich entfernt';
$lng['dnseditor']['edit'] = 'DNS editieren';
$lng['dnseditor']['records'] = 'Einträge';
$lng['error']['dns_notfoundorallowed'] = 'Domain nicht gefunden oder keine Berechtigung';
$lng['serversettings']['dnseditorenable']['title'] = 'DNS Editor aktivieren';
$lng['serversettings']['dnseditorenable']['description'] = 'Erlaubt es Admins und Kunden die DNS Einträge Ihrer Domains zu verwalten';
$lng['dns']['howitworks'] = 'Hier können DNS Einträge für die Domain verwaltet werden. Beachte das Froxlor automatisch NS/MX/A/AAAA Einträge generiert. Die benutzerdefinierten Einträge werden bevorzugt, nur fehlende Einträge werden automatisch generiert.';
$lng['serversettings']['dns_server']['title'] = 'DNS Server Dienst';
$lng['serversettings']['dns_server']['description'] = 'Dienste müssen mit den froxlor Konfigurationstemplates konfiguriert werden';
$lng['error']['domain_nopunycode'] = 'Die Eingabe von Punycode (IDNA) ist nicht notwendig. Die Domain wird automatisch konvertiert.';
$lng['admin']['dnsenabled'] = 'Zugriff auf DNS Editor';
$lng['error']['dns_record_toolong'] = 'Records/Labels können maximal 63 Zeichen lang sein';
// Added in froxlor 0.9.37-rc1
$lng['serversettings']['panel_customer_hide_options']['title'] = 'Menüpunkte und Traffic-Charts im Kundenbereich ausblenden';
$lng['serversettings']['panel_customer_hide_options']['description'] = 'Wählen Sie hier die gewünschten Menüpunkte und Traffic-Charts aus, welche im Kundenbereich ausgeblendet werden sollen. Für Mehrfachauswahl, halten Sie während der Auswahl STRG gedrückt.';

View File

@@ -422,7 +422,7 @@ $lng['serversettings']['defaultip']['title'] = 'IP/Porta default';
$lng['serversettings']['defaultip']['description'] = 'Qual\'è la combinazione IP/Porta default?';
$lng['domains']['statstics'] = 'Statistiche d\'utilizzo';
$lng['panel']['ascending'] = 'ascendente';
$lng['panel']['decending'] = 'discendente';
$lng['panel']['descending'] = 'discendente';
$lng['panel']['search'] = 'Cerca';
$lng['panel']['used'] = 'utilizzato';

View File

@@ -419,7 +419,7 @@ $lng['serversettings']['defaultip']['title'] = 'IP/Porta Padrão';
$lng['serversettings']['defaultip']['description'] = 'Qual é a IP/Porta Padrão?';
$lng['domains']['statstics'] = 'Estatísticas de Uso';
$lng['panel']['ascending'] = 'Crescente';
$lng['panel']['decending'] = 'Decrescente';
$lng['panel']['descending'] = 'Decrescente';
$lng['panel']['search'] = 'Procurar';
$lng['panel']['used'] = 'Usado';
$lng['panel']['translator'] = 'Tradutor';

View File

@@ -412,7 +412,7 @@ $lng['serversettings']['defaultip']['title'] = 'Förvald IP/Port';
$lng['serversettings']['defaultip']['description'] = 'Vilken är den förvalda IP/Port kombinationen?';
$lng['domains']['statstics'] = 'Användarstatistik';
$lng['panel']['ascending'] = 'Stigande';
$lng['panel']['decending'] = 'Fallande';
$lng['panel']['descending'] = 'Fallande';
$lng['panel']['search'] = 'Sök';
$lng['panel']['used'] = 'använd';

View File

@@ -0,0 +1,258 @@
<?php
/***
* Class DnsBase
*
* Base class for all DNS server configs
*
*/
abstract class DnsBase
{
protected $_logger = false;
protected $_ns = array();
protected $_mx = array();
protected $_axfr = array();
abstract public function writeConfigs();
public function __construct($logger)
{
$this->_logger = $logger;
if (Settings::Get('system.nameservers') != '') {
$nameservers = explode(',', Settings::Get('system.nameservers'));
foreach ($nameservers as $nameserver) {
$nameserver = trim($nameserver);
// DNS servers might be multi homed; allow transfer from all ip
// addresses of the DNS server
$nameserver_ips = gethostbynamel($nameserver);
// append dot to hostname
if (substr($nameserver, - 1, 1) != '.') {
$nameserver .= '.';
}
// ignore invalid responses
if (! is_array($nameserver_ips)) {
// act like gethostbyname() and return unmodified hostname on error
$nameserver_ips = array(
$nameserver
);
}
$this->_ns[] = array(
'hostname' => $nameserver,
'ips' => $nameserver_ips
);
}
}
if (Settings::Get('system.mxservers') != '') {
$mxservers = explode(',', Settings::Get('system.mxservers'));
foreach ($mxservers as $mxserver) {
if (substr($mxserver, - 1, 1) != '.') {
$mxserver .= '.';
}
$this->_mx[] = $mxserver;
}
}
// AXFR server #100
if (Settings::Get('system.axfrservers') != '') {
$axfrservers = explode(',', Settings::Get('system.axfrservers'));
foreach ($axfrservers as $axfrserver) {
$this->_axfr[] = trim($axfrserver);
}
}
}
protected function getDomainList()
{
$result_domains_stmt = Database::query(
"
SELECT
`d`.`id`,
`d`.`domain`,
`d`.`isemaildomain`,
`d`.`iswildcarddomain`,
`d`.`wwwserveralias`,
`d`.`customerid`,
`d`.`zonefile`,
`d`.`bindserial`,
`d`.`dkim`,
`d`.`dkim_id`,
`d`.`dkim_pubkey`,
`d`.`ismainbutsubto`,
`c`.`loginname`,
`c`.`guid`
FROM
`" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`)
WHERE
`d`.`isbinddomain` = '1'
ORDER BY
`d`.`domain` ASC
");
$domains = array();
// don't use fetchall() to be able to set the first column to the domain id and use it later on to set the rows'
// array of direct children without having to search the outer array
while ($domain = $result_domains_stmt->fetch(PDO::FETCH_ASSOC)) {
$domains[$domain["id"]] = $domain;
}
// frolxor-hostname (#1090)
if (Settings::get('system.dns_createhostnameentry') == 1) {
$hostname_arr = array(
'id' => 'none',
'domain' => Settings::Get('system.hostname'),
'isbinddomain' => '1',
'isemaildomain' => Settings::Get('system.dns_createmailentry'),
'customerid' => 'none',
'loginname' => 'froxlor.panel',
'bindserial' => date('Ymd') . '00',
'dkim' => '0',
'iswildcarddomain' => '1',
'ismainbutsubto' => '0',
'zonefile' => '',
'froxlorhost' => '1'
);
$domains['none'] = $hostname_arr;
}
if (empty($domains)) {
return null;
}
// collect domain IDs of direct child domains as arrays in ['children'] column
foreach (array_keys($domains) as $key) {
if (! isset($domains[$key]['children'])) {
$domains[$key]['children'] = array();
}
if ($domains[$key]['ismainbutsubto'] > 0) {
if (isset($domains[ $domains[$key]['ismainbutsubto'] ])) {
$domains[ $domains[$key]['ismainbutsubto'] ]['children'][] = $domains[$key]['id'];
} else {
$this->_logger->logAction(CRON_ACTION, LOG_ERR,
'Database inconsistency: domain ' . $domain['domain'] . ' (ID #' . $key .
') is set to to be subdomain to non-existent domain ID #' .
$domains[$key]['ismainbutsubto'] .
'. No DNS record(s) will be created for this domain.');
}
}
}
$this->_logger->logAction(CRON_ACTION, LOG_DEBUG,
str_pad('domId', 9, ' ') . str_pad('domain', 40, ' ') .
'ismainbutsubto ' . str_pad('parent domain', 40, ' ') .
"list of child domain ids");
foreach ($domains as $domain) {
$logLine =
str_pad($domain['id'], 9, ' ') .
str_pad($domain['domain'], 40, ' ') .
str_pad($domain['ismainbutsubto'], 15, ' ') .
str_pad(((isset($domains[ $domain['ismainbutsubto'] ])) ?
$domains[ $domain['ismainbutsubto'] ]['domain'] :
'-'), 40, ' ') .
join(', ', $domain['children']);
$this->_logger->logAction(CRON_ACTION, LOG_DEBUG, $logLine);
}
return $domains;
}
public function reloadDaemon()
{
// reload DNS daemon
$cmd = Settings::Get('system.bindreload_command');
$cmdStatus = 1;
safe_exec(escapeshellcmd($cmd), $cmdStatus);
if ($cmdStatus === 0) {
$this->_logger->logAction(CRON_ACTION, LOG_INFO, Settings::Get('system.dns_server') . ' daemon reloaded');
} else {
$this->_logger->logAction(CRON_ACTION, LOG_ERR, 'Error while running `' . $cmd .
'`: exit code (' . $cmdStatus . ') - please check your system logs');
}
}
public function writeDKIMconfigs()
{
if (Settings::Get('dkim.use_dkim') == '1') {
if (! file_exists(makeCorrectDir(Settings::Get('dkim.dkim_prefix')))) {
$this->_logger->logAction(CRON_ACTION, LOG_NOTICE, 'mkdir -p ' . escapeshellarg(makeCorrectDir(Settings::Get('dkim.dkim_prefix'))));
safe_exec('mkdir -p ' . escapeshellarg(makeCorrectDir(Settings::Get('dkim.dkim_prefix'))));
}
$dkimdomains = '';
$dkimkeys = '';
$result_domains_stmt = Database::query("
SELECT `id`, `domain`, `dkim`, `dkim_id`, `dkim_pubkey`, `dkim_privkey`
FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `dkim` = '1' ORDER BY `id` ASC
");
while ($domain = $result_domains_stmt->fetch(PDO::FETCH_ASSOC)) {
$privkey_filename = makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim_' . $domain['dkim_id']);
$pubkey_filename = makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim_' . $domain['dkim_id'] . '.public');
if ($domain['dkim_privkey'] == '' || $domain['dkim_pubkey'] == '') {
$max_dkim_id_stmt = Database::query("SELECT MAX(`dkim_id`) as `max_dkim_id` FROM `" . TABLE_PANEL_DOMAINS . "`");
$max_dkim_id = $max_dkim_id_stmt->fetch(PDO::FETCH_ASSOC);
$domain['dkim_id'] = (int) $max_dkim_id['max_dkim_id'] + 1;
$privkey_filename = makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim_' . $domain['dkim_id']);
safe_exec('openssl genrsa -out ' . escapeshellarg($privkey_filename) . ' ' . Settings::Get('dkim.dkim_keylength'));
$domain['dkim_privkey'] = file_get_contents($privkey_filename);
safe_exec("chmod 0640 " . escapeshellarg($privkey_filename));
$pubkey_filename = makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim_' . $domain['dkim_id'] . '.public');
safe_exec('openssl rsa -in ' . escapeshellarg($privkey_filename) . ' -pubout -outform pem -out ' . escapeshellarg($pubkey_filename));
$domain['dkim_pubkey'] = file_get_contents($pubkey_filename);
safe_exec("chmod 0664 " . escapeshellarg($pubkey_filename));
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
`dkim_id` = :dkimid,
`dkim_privkey` = :privkey,
`dkim_pubkey` = :pubkey
WHERE `id` = :id
");
$upd_data = array(
'dkimid' => $domain['dkim_id'],
'privkey' => $domain['dkim_privkey'],
'pubkey' => $domain['dkim_pubkey'],
'id' => $domain['id']
);
Database::pexecute($upd_stmt, $upd_data);
}
if (! file_exists($privkey_filename) && $domain['dkim_privkey'] != '') {
$privkey_file_handler = fopen($privkey_filename, "w");
fwrite($privkey_file_handler, $domain['dkim_privkey']);
fclose($privkey_file_handler);
safe_exec("chmod 0640 " . escapeshellarg($privkey_filename));
}
if (! file_exists($pubkey_filename) && $domain['dkim_pubkey'] != '') {
$pubkey_file_handler = fopen($pubkey_filename, "w");
fwrite($pubkey_file_handler, $domain['dkim_pubkey']);
fclose($pubkey_file_handler);
safe_exec("chmod 0664 " . escapeshellarg($pubkey_filename));
}
$dkimdomains .= $domain['domain'] . "\n";
$dkimkeys .= "*@" . $domain['domain'] . ":" . $domain['domain'] . ":" . $privkey_filename . "\n";
}
$dkimdomains_filename = makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/' . Settings::Get('dkim.dkim_domains'));
$dkimdomains_file_handler = fopen($dkimdomains_filename, "w");
fwrite($dkimdomains_file_handler, $dkimdomains);
fclose($dkimdomains_file_handler);
$dkimkeys_filename = makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/' . Settings::Get('dkim.dkim_dkimkeys'));
$dkimkeys_file_handler = fopen($dkimkeys_filename, "w");
fwrite($dkimkeys_file_handler, $dkimkeys);
fclose($dkimkeys_file_handler);
safe_exec(escapeshellcmd(Settings::Get('dkim.dkimrestart_command')));
$this->_logger->logAction(CRON_ACTION, LOG_INFO, 'Dkim-milter reloaded');
}
}
}

View File

@@ -1,163 +1,48 @@
<?php if (!defined('MASTER_CRONJOB')) die('You cannot access this file directly!');
<?php
if (! defined('MASTER_CRONJOB'))
die('You cannot access this file directly!');
/**
* This file is part of the Froxlor project.
* Copyright (c) 2003-2009 the SysCP Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
* Copyright (c) 2016 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Florian Lippert <flo@syscp.org> (2003-2009)
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
*/
class bind extends DnsBase
{
class bind {
public $logger = false;
public $nameservers = array();
public $mxservers = array();
public $axfrservers = array();
private $_bindconf_file = "";
private $_known_filenames = array();
private $_bindconf_file = '';
public function writeConfigs()
{
// tell the world what we are doing
$this->_logger->logAction(CRON_ACTION, LOG_INFO, 'Task4 started - Rebuilding froxlor_bind.conf');
public function __construct($logger) {
// clean up
$this->_cleanZonefiles();
$this->logger = $logger;
if (Settings::Get('system.nameservers') != '') {
$nameservers = explode(',', Settings::Get('system.nameservers'));
foreach ($nameservers as $nameserver) {
$nameserver = trim($nameserver);
// DNS servers might be multi homed; allow transfer from all ip
// addresses of the DNS server
$nameserver_ips = gethostbynamel($nameserver);
// append dot to hostname
if (substr($nameserver, -1, 1) != '.') {
$nameserver.= '.';
}
// ignore invalid responses
if (!is_array($nameserver_ips)) {
// act like gethostbyname() and return unmodified hostname on error
$nameserver_ips = array($nameserver);
}
$this->nameservers[] = array(
'hostname' => $nameserver,
'ips' => $nameserver_ips
);
}
// check for subfolder in bind-config-directory
if (! file_exists(makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/'))) {
$this->_logger->logAction(CRON_ACTION, LOG_NOTICE, 'mkdir ' . escapeshellarg(makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/')));
safe_exec('mkdir -p ' . escapeshellarg(makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/')));
}
if (Settings::Get('system.mxservers') != '') {
$mxservers = explode(',', Settings::Get('system.mxservers'));
foreach ($mxservers as $mxserver) {
if (substr($mxserver, -1, 1) != '.') {
$mxserver.= '.';
}
$this->mxservers[] = $mxserver;
}
}
// AXFR server #100
if (Settings::Get('system.axfrservers') != '') {
$axfrservers = explode(',', Settings::Get('system.axfrservers'));
foreach ($axfrservers as $axfrserver) {
$this->axfrservers[] = trim($axfrserver);
}
}
}
public function writeConfigs() {
$this->logger->logAction(CRON_ACTION, LOG_INFO, 'Task4 started - Rebuilding froxlor_bind.conf');
if (!file_exists(makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/'))) {
$this->logger->logAction(CRON_ACTION, LOG_NOTICE, 'mkdir ' . escapeshellarg(makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/')));
safe_exec('mkdir ' . escapeshellarg(makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/')));
}
$this->_known_filenames = array();
$this->_bindconf_file = '# ' . Settings::Get('system.bindconf_directory') . 'froxlor_bind.conf' . "\n" .
'# Created ' . date('d.m.Y H:i') . "\n" .
'# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n";
$result_domains_stmt = Database::query("
SELECT `d`.`id`, `d`.`domain`, `d`.`isemaildomain`, `d`.`iswildcarddomain`, `d`.`wwwserveralias`, `d`.`customerid`,
`d`.`zonefile`, `d`.`bindserial`, `d`.`dkim`, `d`.`dkim_id`, `d`.`dkim_pubkey`, `d`.`ismainbutsubto`,
`c`.`loginname`, `c`.`guid`
FROM `" . TABLE_PANEL_DOMAINS . "` `d` LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`)
WHERE `d`.`isbinddomain` = '1' ORDER BY `d`.`domain` ASC
");
$domains = array();
// don't use fetchall() to be able to set the first column to the domain id and use it later on to set the rows'
// array of direct children without having to search the outer array
while ($domain = $result_domains_stmt->fetch(PDO::FETCH_ASSOC)) {
$domains[$domain["id"]] = $domain;
}
// frolxor-hostname (#1090)
if (Settings::get('system.dns_createhostnameentry') == 1) {
$hostname_arr = array(
'id' => 'none',
'domain' => Settings::Get('system.hostname'),
'isemaildomain' => Settings::Get('system.dns_createmailentry'),
'customerid' => 'none',
'loginname' => 'froxlor.panel',
'bindserial' => date('Ymd').'00',
'dkim' => '0',
'iswildcarddomain' => '1',
'ismainbutsubto' => '0',
'zonefile' => '',
'froxlorhost' => '1'
);
$domains['none'] = $hostname_arr;
}
$domains = $this->getDomainList();
if (empty($domains)) {
$this->logger->logAction(CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, skipping...');
$this->_logger->logAction(CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, skipping...');
return;
}
// collect domain IDs of direct child domains as arrays in ['children'] column
foreach (array_keys($domains) as $key) {
if (!isset($domains[$key]['children'])) {
$domains[$key]['children'] = array();
}
if ($domains[$key]['ismainbutsubto'] > 0) {
if (isset($domains[ $domains[$key]['ismainbutsubto'] ])) {
$domains[ $domains[$key]['ismainbutsubto'] ]['children'][] = $domains[$key]['id'];
} else {
$this->logger->logAction(CRON_ACTION, LOG_ERR,
'Database inconsistency: domain ' . $domain['domain'] . ' (ID #' . $key .
') is set to to be subdomain to non-existent domain ID #' .
$domains[$key]['ismainbutsubto'] .
'. No DNS record(s) will be created for this domain.');
}
}
}
$this->logger->logAction(CRON_ACTION, LOG_DEBUG,
str_pad('domId', 9, ' ') . str_pad('domain', 40, ' ') .
'ismainbutsubto ' . str_pad('parent domain', 40, ' ') .
"list of child domain ids");
foreach ($domains as $domain) {
$logLine =
str_pad($domain['id'], 9, ' ') .
str_pad($domain['domain'], 40, ' ') .
str_pad($domain['ismainbutsubto'], 15, ' ') .
str_pad(((isset($domains[ $domain['ismainbutsubto'] ])) ?
$domains[ $domain['ismainbutsubto'] ]['domain'] :
'-'), 40, ' ') .
join(', ', $domain['children']);
$this->logger->logAction(CRON_ACTION, LOG_DEBUG, $logLine);
}
$bindconf_file = '# ' . Settings::Get('system.bindconf_directory') . 'froxlor_bind.conf' . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n\n";
foreach ($domains as $domain) {
if ($domain['ismainbutsubto'] > 0) {
@@ -170,451 +55,114 @@ class bind {
$bindconf_file_handler = fopen(makeCorrectFile(Settings::Get('system.bindconf_directory') . '/froxlor_bind.conf'), 'w');
fwrite($bindconf_file_handler, $this->_bindconf_file);
fclose($bindconf_file_handler);
$this->logger->logAction(CRON_ACTION, LOG_INFO, 'froxlor_bind.conf written');
safe_exec(escapeshellcmd(Settings::Get('system.bindreload_command')));
$this->logger->logAction(CRON_ACTION, LOG_INFO, 'Bind9 reloaded');
$domains_dir = makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/');
if (file_exists($domains_dir)
&& is_dir($domains_dir)) {
$domain_file_dirhandle = opendir($domains_dir);
while (false !== ($domain_filename = readdir($domain_file_dirhandle))) {
$full_filename = makeCorrectFile($domains_dir . '/' . $domain_filename);
if ($domain_filename != '.'
&& $domain_filename != '..'
&& !in_array($domain_filename, $this->_known_filenames)
&& is_file($full_filename)
&& file_exists($full_filename)) {
$this->logger->logAction(CRON_ACTION, LOG_WARNING, 'Deleting ' . $domain_filename);
unlink(makeCorrectFile($domains_dir . '/' . $domain_filename));
}
}
}
$this->logger->logAction(CRON_ACTION, LOG_INFO, 'Task4 finished');
$this->_logger->logAction(CRON_ACTION, LOG_INFO, 'froxlor_bind.conf written');
$this->reloadDaemon();
$this->_logger->logAction(CRON_ACTION, LOG_INFO, 'Task4 finished');
}
private function walkDomainList($domain, $domains) {
$zonefile = '';
private function walkDomainList($domain, $domains)
{
$zoneContent = '';
$subzones = '';
foreach($domain['children'] as $child_domain_id) {
$subzones.= $this->walkDomainList($domains[$child_domain_id], $domains);
foreach ($domain['children'] as $child_domain_id) {
$subzones .= $this->walkDomainList($domains[$child_domain_id], $domains);
}
if ($domain['zonefile'] == '') {
// check for system-hostname
$isFroxlorHostname = false;
if (isset($domain['froxlorhost']) && $domain['froxlorhost'] == 1) {
$isFroxlorHostname = true;
}
if ($domain['ismainbutsubto'] == 0) {
$zonefile = $this->generateZone($domain);
$zoneContent = (string) createDomainZone(($domain['id'] == 'none') ?
$domain :
$domain['id'],
$isFroxlorHostname);
$domain['zonefile'] = 'domains/' . $domain['domain'] . '.zone';
$zonefile_name = makeCorrectFile(Settings::Get('system.bindconf_directory') . '/' . $domain['zonefile']);
$this->_known_filenames[] = basename($zonefile_name);
$zonefile_name = makeCorrectFile(Settings::Get('system.bindconf_directory') . '/' .
$domain['zonefile']);
$zonefile_handler = fopen($zonefile_name, 'w');
fwrite($zonefile_handler, $zonefile.$subzones);
fwrite($zonefile_handler, $zoneContent . $subzones);
fclose($zonefile_handler);
$this->logger->logAction(CRON_ACTION, LOG_INFO, '`' . $zonefile_name . '` zone written');
$this->_logger->logAction(CRON_ACTION, LOG_INFO, '`' . $zonefile_name . '` written');
$this->_bindconf_file .= $this->_generateDomainConfig($domain);
} else {
return $this->generateZone($domain);
return (string) createDomainZone(($domain['id'] == 'none') ?
$domain :
$domain['id'],
$isFroxlorHostname,
true);
}
} else {
$this->logger->logAction(CRON_ACTION, LOG_INFO, 'Added zonefile ' . $domain['zonefile'] . ' for domain ' . $domain['domain'] .
' - Note that you will also have to handle ALL records for ALL subdomains.');
$this->_logger->logAction(CRON_ACTION, LOG_INFO,
'Added zonefile ' . $domain['zonefile'] . ' for domain ' . $domain['domain'] .
' - Note that you will also have to handle ALL records for ALL subdomains.');
$this->_bindconf_file .= $this->_generateDomainConfig($domain);
}
}
private function _generateDomainConfig($domain = array()) {
if (isset($domain['froxlorhost']) && $domain['froxlorhost'] === '1') {
$froxlorhost = true;
} else {
$froxlorhost = false;
}
private function _generateDomainConfig($domain = array())
{
$this->_logger->logAction(CRON_ACTION, LOG_DEBUG, 'Generating dns config for ' . $domain['domain']);
$bindconf_file = '# Domain ID: ' . $domain['id'] . ' - CustomerID: ' . $domain['customerid'] . ' - CustomerLogin: ' . $domain['loginname'] . "\n";
$bindconf_file.= 'zone "' . $domain['domain'] . '" in {' . "\n";
$bindconf_file.= ' type master;' . "\n";
$bindconf_file.= ' file "' . makeCorrectFile(Settings::Get('system.bindconf_directory') . '/' . $domain['zonefile']) . '";' . "\n";
$bindconf_file.= ' allow-query { any; };' . "\n";
$bindconf_file .= 'zone "' . $domain['domain'] . '" in {' . "\n";
$bindconf_file .= ' type master;' . "\n";
$bindconf_file .= ' file "' . makeCorrectFile(Settings::Get('system.bindconf_directory') . '/' . $domain['zonefile']) . '";' . "\n";
$bindconf_file .= ' allow-query { any; };' . "\n";
if (count($this->nameservers) > 0
|| count($this->axfrservers) > 0
) {
if (count($this->_ns) > 0 || count($this->_axfr) > 0) {
// open allow-transfer
$bindconf_file.= ' allow-transfer {' . "\n";
$bindconf_file .= ' allow-transfer {' . "\n";
// put nameservers in allow-transfer
if (count($this->nameservers) > 0) {
foreach ($this->nameservers as $ns) {
foreach($ns["ips"] as $ip) {
$bindconf_file.= ' ' . $ip . ";\n";
if (count($this->_ns) > 0) {
foreach ($this->_ns as $ns) {
foreach ($ns["ips"] as $ip) {
$bindconf_file .= ' ' . $ip . ";\n";
}
}
}
// AXFR server #100
if (count($this->axfrservers) > 0) {
foreach ($this->axfrservers as $axfrserver) {
if (count($this->_axfr) > 0) {
foreach ($this->_axfr as $axfrserver) {
if (validate_ip($axfrserver, true) !== false) {
$bindconf_file.= ' ' . $axfrserver . ';' . "\n";
$bindconf_file .= ' ' . $axfrserver . ';' . "\n";
}
}
}
// close allow-transfer
$bindconf_file.= ' };' . "\n";
$bindconf_file .= ' };' . "\n";
}
$bindconf_file.= '};' . "\n";
$bindconf_file.= "\n";
$bindconf_file .= '};' . "\n";
$bindconf_file .= "\n";
return $bindconf_file;
}
/**
* generate bind zone content.
*
* @param array $domain
*
* @return string
*/
protected function generateZone($domain) {
if (isset($domain['froxlorhost']) && $domain['froxlorhost'] === '1') {
$froxlorhost = true;
} else {
$froxlorhost = false;
}
private function _cleanZonefiles()
{
$config_dir = makeCorrectFile(Settings::Get('system.bindconf_directory') . '/domains/');
// Array to save all ips needed in the records (already including IN A/AAAA)
$ip_a_records = array();
// Array to save DNS records
$records = array();
$this->_logger->logAction(CRON_ACTION, LOG_INFO, 'Cleaning dns zone files from ' . $config_dir);
$domainidquery = '';
$query_params = array();
if (!$froxlorhost) {
// check directory
if (@is_dir($config_dir)) {
$domainidquery = "`di`.`id_domain` = :domainid AND ";
$query_params['domainid'] = $domain['id'];
// create directory iterator
$its = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($config_dir));
$result_ip_stmt = Database::prepare("
SELECT `p`.`ip` AS `ip`
FROM `".TABLE_PANEL_IPSANDPORTS."` `p`, `".TABLE_DOMAINTOIP."` `di`
WHERE ".$domainidquery."`p`.`id` = `di`.`id_ipandports`
GROUP BY `p`.`ip`;
");
} else {
// use all available IP's for the froxlor-hostname
$result_ip_stmt = Database::prepare("
SELECT `ip` FROM `".TABLE_PANEL_IPSANDPORTS."` GROUP BY `ip`
");
}
Database::pexecute($result_ip_stmt, $query_params);
while ($ip = $result_ip_stmt->fetch(PDO::FETCH_ASSOC)) {
if (filter_var($ip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$ip_a_records[] = "A\t\t" . $ip['ip'];
}
elseif (filter_var($ip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$ip_a_records[] = "AAAA\t\t" . $ip['ip'];
}
else {
return ";Error in at least one IP Address (".$ip['ip']."), could not create zonefile!";
}
}
if ($domain['ismainbutsubto'] == 0) {
$date = date('Ymd');
$bindserial = (preg_match('/^' . $date . '/', $domain['bindserial']) ? $domain['bindserial'] + 1 : $date . '00');
if (!$froxlorhost) {
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
`bindserial` = :serial
WHERE `id` = :id
");
Database::pexecute($upd_stmt, array('serial' => $bindserial, 'id' => $domain['id']));
}
$zonefile = '$TTL ' . (int)Settings::Get('system.defaultttl') . "\n";
if (count($this->nameservers) == 0) {
$zonefile.= '@ IN SOA ns ' . str_replace('@', '.', Settings::Get('panel.adminmail')) . '. (' . "\n";
} else {
$zonefile.= '@ IN SOA ' . $this->nameservers[0]['hostname'] . ' ' . str_replace('@', '.', Settings::Get('panel.adminmail')) . '. (' . "\n";
}
$zonefile.= ' ' . $bindserial . ' ; serial' . "\n" . ' 8H ; refresh' . "\n" . ' 2H ; retry' . "\n" . ' 1W ; expiry' . "\n" . ' 11h) ; minimum' . "\n";
// no nameservers given, use all of the A/AAAA entries
if (count($this->nameservers) == 0) {
$zonefile .= '@ IN NS ns' . "\n";
foreach ($ip_a_records as $ip_a_record) {
$zonefile .= 'ns IN ' . $ip_a_record . "\n";
}
} else {
foreach ($this->nameservers as $nameserver) {
$zonefile.= '@ IN NS ' . trim($nameserver['hostname']) . "\n";
// iterate through all subdirs, look for zone files and delete them
foreach ($its as $it) {
if ($it->isFile()) {
// remove file
safe_exec('rm -f ' . escapeshellarg(makeCorrectFile($its->getPathname())));
}
}
} else {
$zonefile = '$ORIGIN ' . $domain["domain"] . ".\n";
}
if ($domain['isemaildomain'] === '1') {
if (count($this->mxservers) == 0) {
$zonefile.= '@ IN MX 10 mail' . "\n";
$records[] = 'mail';
if ($domain['iswildcarddomain'] != '1') {
$records[] = 'imap';
$records[] = 'smtp';
$records[] = 'pop3';
}
} else {
foreach ($this->mxservers as $mxserver) {
$zonefile.= '@ IN MX ' . trim($mxserver) . "\n";
}
if (Settings::Get('system.dns_createmailentry') == '1') {
$records[] = 'mail';
if ($domain['iswildcarddomain'] != '1') {
$records[] = 'imap';
$records[] = 'smtp';
$records[] = 'pop3';
}
}
}
/*
* @TODO domain-based spf-settings
*/
if (Settings::Get('spf.use_spf') == '1'
/*&& $domain['spf'] == '1' */
) {
$zonefile.= Settings::Get('spf.spf_entry') . "\n";
if (in_array('mail', $records)) {
$zonefile.= str_replace('@', 'mail', Settings::Get('spf.spf_entry')) . "\n";
}
}
}
/**
* generate dkim-zone-entries
*/
$zonefile.= $this->generateDkim($domain);
if (!$froxlorhost) {
$nssubdomains_stmt = Database::prepare("
SELECT `domain` FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `isbinddomain` = '1' AND `ismainbutsubto` = '0' AND `domain` LIKE :domain
");
Database::pexecute($nssubdomains_stmt, array('domain' => '%.' . $domain['domain']));
while ($nssubdomain = $nssubdomains_stmt->fetch(PDO::FETCH_ASSOC)) {
if (preg_match('/^[^\.]+\.' . preg_quote($domain['domain'], '/') . '/', $nssubdomain['domain'])) {
$nssubdomain = str_replace('.' . $domain['domain'], '', $nssubdomain['domain']);
if (count($this->nameservers) == 0) {
$zonefile.= $nssubdomain . ' IN NS ns.' . $nssubdomain . "\n";
} else {
foreach ($this->nameservers as $nameserver) {
$zonefile.= $nssubdomain . ' IN NS ' . trim($nameserver['hostname']) . "\n";
}
}
}
}
}
$records[] = '@';
if ($domain['iswildcarddomain'] == '1') {
$records[] = '*';
} else if ($domain['wwwserveralias'] == '1') {
$records[] = 'www';
}
if (!$froxlorhost) {
$subdomains_stmt = Database::prepare("
SELECT `domain` FROM `".TABLE_PANEL_DOMAINS."`
WHERE `parentdomainid` = :domainid
");
Database::pexecute($subdomains_stmt, array('domainid' => $domain['id']));
while ($subdomain = $subdomains_stmt->fetch(PDO::FETCH_ASSOC)) {
// Listing domains is enough as there currently is no support for choosing
// different ips for a subdomain => use same IPs as toplevel
$records[] = str_replace('.' . $domain['domain'], '', $subdomain['domain']);
// Check whether to add a www.-prefix
if ($domain['wwwserveralias'] == '1') {
$records[] = 'www.'.str_replace('.' . $domain['domain'], '', $subdomain['domain']);
}
}
}
// Create DNS-Records for every name we have saved
foreach ($records as $record) {
// we create an entry for every ip we have saved
foreach ($ip_a_records as $ip_a_record) {
$zonefile.= $record . "\tIN\t" . $ip_a_record . "\n";
}
}
return $zonefile;
}
private function generateDkim($domain) {
$zone_dkim = '';
if (Settings::Get('dkim.use_dkim') == '1'
&& $domain['dkim'] == '1'
&& $domain['dkim_pubkey'] != '') {
// start
$dkim_txt = 'v=DKIM1;';
// algorithm
$algorithm = explode(',', Settings::Get('dkim.dkim_algorithm'));
$alg = '';
foreach ($algorithm as $a) {
if ($a == 'all') {
break;
} else {
$alg.=$a.':';
}
}
if ($alg != '') {
$alg = substr($alg, 0, -1);
$dkim_txt.= 'h='.$alg.';';
}
// notes
if (trim(Settings::Get('dkim.dkim_notes') != '')) {
$dkim_txt.= 'n='.trim(Settings::Get('dkim.dkim_notes')).';';
}
// key
$dkim_txt.= 'k=rsa;p='.trim(preg_replace('/-----BEGIN PUBLIC KEY-----(.+)-----END PUBLIC KEY-----/s', '$1', str_replace("\n", '', $domain['dkim_pubkey']))).';';
// service-type
if (Settings::Get('dkim.dkim_servicetype') == '1') {
$dkim_txt.= 's=email;';
}
// end-part
$dkim_txt.='t=s';
// split if necessary
$txt_record_split='';
$lbr=50;
for ($pos=0; $pos<=strlen($dkim_txt)-1; $pos+=$lbr) {
$txt_record_split.= (($pos==0) ? '("' : "\t\t\t\t\t \"") . substr($dkim_txt, $pos, $lbr) . (($pos>=strlen($dkim_txt)-$lbr) ? '")' : '"' ) ."\n";
}
// dkim-entry
$zone_dkim .= 'dkim_' . $domain['dkim_id'] . '._domainkey IN TXT ' . $txt_record_split;
// adsp-entry
if (Settings::Get('dkim.dkim_add_adsp') == "1") {
$zone_dkim .= '_adsp._domainkey IN TXT "dkim=';
switch ((int)Settings::Get('dkim.dkim_add_adsppolicy')) {
case 0:
$zone_dkim .= 'unknown"'. "\n";
break;
case 1:
$zone_dkim .= 'all"'. "\n";
break;
case 2:
$zone_dkim .= 'discardable"'. "\n";
break;
}
}
}
return $zone_dkim;
}
public function writeDKIMconfigs() {
if (Settings::Get('dkim.use_dkim') == '1') {
if (!file_exists(makeCorrectDir(Settings::Get('dkim.dkim_prefix')))) {
$this->logger->logAction(CRON_ACTION, LOG_NOTICE, 'mkdir -p ' . escapeshellarg(makeCorrectDir(Settings::Get('dkim.dkim_prefix'))));
safe_exec('mkdir -p ' . escapeshellarg(makeCorrectDir(Settings::Get('dkim.dkim_prefix'))));
}
$dkimdomains = '';
$dkimkeys = '';
$result_domains_stmt = Database::query("
SELECT `id`, `domain`, `dkim`, `dkim_id`, `dkim_pubkey`, `dkim_privkey`
FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `dkim` = '1' ORDER BY `id` ASC
");
while ($domain = $result_domains_stmt->fetch(PDO::FETCH_ASSOC)) {
$privkey_filename = makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim_' . $domain['dkim_id']);
$pubkey_filename = makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim_' . $domain['dkim_id'] . '.public');
if ($domain['dkim_privkey'] == ''
|| $domain['dkim_pubkey'] == '') {
$max_dkim_id_stmt = Database::query("SELECT MAX(`dkim_id`) as `max_dkim_id` FROM `" . TABLE_PANEL_DOMAINS . "`");
$max_dkim_id = $max_dkim_id_stmt->fetch(PDO::FETCH_ASSOC);
$domain['dkim_id'] = (int)$max_dkim_id['max_dkim_id'] + 1;
$privkey_filename = makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim_' . $domain['dkim_id']);
safe_exec('openssl genrsa -out ' . escapeshellarg($privkey_filename) . ' ' . Settings::Get('dkim.dkim_keylength'));
$domain['dkim_privkey'] = file_get_contents($privkey_filename);
safe_exec("chmod 0640 " . escapeshellarg($privkey_filename));
$pubkey_filename = makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim_' . $domain['dkim_id'] . '.public');
safe_exec('openssl rsa -in ' . escapeshellarg($privkey_filename) . ' -pubout -outform pem -out ' . escapeshellarg($pubkey_filename));
$domain['dkim_pubkey'] = file_get_contents($pubkey_filename);
safe_exec("chmod 0664 " . escapeshellarg($pubkey_filename));
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
`dkim_id` = :dkimid,
`dkim_privkey` = :privkey,
`dkim_pubkey` = :pubkey
WHERE `id` = :id
");
$upd_data = array(
'dkimid' => $domain['dkim_id'],
'privkey' => $domain['dkim_privkey'],
'pubkey' => $domain['dkim_pubkey'],
'id' => $domain['id']
);
Database::pexecute($upd_stmt, $upd_data);
}
if (!file_exists($privkey_filename)
&& $domain['dkim_privkey'] != '') {
$privkey_file_handler = fopen($privkey_filename, "w");
fwrite($privkey_file_handler, $domain['dkim_privkey']);
fclose($privkey_file_handler);
safe_exec("chmod 0640 " . escapeshellarg($privkey_filename));
}
if (!file_exists($pubkey_filename)
&& $domain['dkim_pubkey'] != '') {
$pubkey_file_handler = fopen($pubkey_filename, "w");
fwrite($pubkey_file_handler, $domain['dkim_pubkey']);
fclose($pubkey_file_handler);
safe_exec("chmod 0664 " . escapeshellarg($pubkey_filename));
}
$dkimdomains.= $domain['domain'] . "\n";
$dkimkeys.= "*@" . $domain['domain'] . ":" . $domain['domain'] . ":" . $privkey_filename . "\n";
}
$dkimdomains_filename = makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/' . Settings::Get('dkim.dkim_domains'));
$dkimdomains_file_handler = fopen($dkimdomains_filename, "w");
fwrite($dkimdomains_file_handler, $dkimdomains);
fclose($dkimdomains_file_handler);
$dkimkeys_filename = makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/' . Settings::Get('dkim.dkim_dkimkeys'));
$dkimkeys_file_handler = fopen($dkimkeys_filename, "w");
fwrite($dkimkeys_file_handler, $dkimkeys);
fclose($dkimkeys_file_handler);
safe_exec(escapeshellcmd(Settings::Get('dkim.dkimrestart_command')));
$this->logger->logAction(CRON_ACTION, LOG_INFO, 'Dkim-milter reloaded');
}
}
}

View File

@@ -0,0 +1,257 @@
<?php
if (! defined('MASTER_CRONJOB'))
die('You cannot access this file directly!');
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
*/
class pdns extends DnsBase
{
private $pdns_db = null;
public function writeConfigs()
{
// tell the world what we are doing
$this->_logger->logAction(CRON_ACTION, LOG_INFO, 'Task4 started - Refreshing DNS database');
// connect to db
$this->_connectToPdnsDb();
// clean up
$this->_clearZoneTables();
$domains = $this->getDomainList();
if (empty($domains)) {
$this->_logger->logAction(CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, skipping...');
return;
}
foreach ($domains as $domain) {
if ($domain['ismainbutsubto'] > 0) {
// domains with ismainbutsubto>0 are handled by recursion within walkDomainList()
continue;
}
$this->walkDomainList($domain, $domains);
}
$this->_logger->logAction(CRON_ACTION, LOG_INFO, 'PowerDNS database updated');
$this->reloadDaemon();
$this->_logger->logAction(CRON_ACTION, LOG_INFO, 'Task4 finished');
}
private function walkDomainList($domain, $domains)
{
$zoneContent = '';
$subzones = array();
foreach ($domain['children'] as $child_domain_id) {
$subzones[] = $this->walkDomainList($domains[$child_domain_id], $domains);
}
if ($domain['zonefile'] == '') {
// check for system-hostname
$isFroxlorHostname = false;
if (isset($domain['froxlorhost']) && $domain['froxlorhost'] == 1) {
$isFroxlorHostname = true;
}
if ($domain['ismainbutsubto'] == 0) {
$zoneContent = createDomainZone(($domain['id'] == 'none') ?
$domain :
$domain['id'],
$isFroxlorHostname);
if (count($subzones)) {
foreach ($subzones as $subzone) {
$zoneContent->records[] = $subzone;
}
}
$pdnsDomId = $this->_insertZone($zoneContent->origin, $zoneContent->serial);
$this->_insertRecords($pdnsDomId, $zoneContent->records, $zoneContent->origin);
$this->_insertAllowedTransfers($pdnsDomId);
$this->_logger->logAction(CRON_ACTION, LOG_INFO, 'DB entries stored for zone `' . $domain['domain'] . '`');
} else {
return createDomainZone(($domain['id'] == 'none') ?
$domain :
$domain['id'],
$isFroxlorHostname,
true);
}
} else {
$this->_logger->logAction(CRON_ACTION, LOG_ERROR,
'Zonefiles are NOT supported when PowerDNS is selected as DNS daemon (triggered by: ' .
$domain['domain'] . ')');
$this->_bindconf_file .= $this->_generateDomainConfig($domain);
}
}
private function _clearZoneTables()
{
$this->_logger->logAction(CRON_ACTION, LOG_INFO, 'Cleaning dns zone entries from database');
$this->pdns_db->query("TRUNCATE TABLE `records`");
$this->pdns_db->query("TRUNCATE TABLE `domains`");
$this->pdns_db->query("TRUNCATE TABLE `domainmetadata`");
}
private function _insertZone($domainname, $serial = 0)
{
$ins_stmt = $this->pdns_db->prepare("
INSERT INTO domains set `name` = :domainname, `notified_serial` = :serial, `type` = 'NATIVE'
");
$ins_stmt->execute(array('domainname' => $domainname, 'serial' => $serial));
$lastid = $this->pdns_db->lastInsertId();
return $lastid;
}
private function _insertRecords($domainid = 0, $records, $origin)
{
$changedate = date('Ymds', time());
$ins_stmt = $this->pdns_db->prepare("
INSERT INTO records set
`domain_id` = :did,
`name` = :rec,
`type` = :type,
`content` = :content,
`ttl` = :ttl,
`prio` = :prio,
`disabled` = '0',
`change_date` = :changedate
");
foreach ($records as $record)
{
if ($record instanceof DnsZone) {
$this->_insertRecords($domainid, $record->records, $record->origin);
continue;
}
if ($record->record == '@') {
$_record = $origin;
}
else
{
$_record = $record->record.".".$origin;
}
$ins_data = array(
'did' => $domainid,
'rec' => $_record,
'type' => $record->type,
'content' => $record->content,
'ttl' => $record->ttl,
'prio' => $record->priority,
'changedate' => $changedate
);
$ins_stmt->execute($ins_data);
}
}
private function _insertAllowedTransfers($domainid)
{
$ins_stmt = $this->pdns_db->prepare("
INSERT INTO domainmetadata set `domain_id` = :did, `kind` = 'ALLOW-AXFR-FROM', `content` = :value
");
$ins_data = array(
'did' => $domainid
);
if (count($this->_ns) > 0 || count($this->_axfr) > 0) {
// put nameservers in allow-transfer
if (count($this->_ns) > 0) {
foreach ($this->_ns as $ns) {
foreach ($ns["ips"] as $ip) {
$ins_data['value'] = $ip;
$ins_stmt->execute($ins_data);
}
}
}
// AXFR server #100
if (count($this->_axfr) > 0) {
foreach ($this->_axfr as $axfrserver) {
if (validate_ip($axfrserver, true) !== false) {
$ins_data['value'] = $axfrserver;
$ins_stmt->execute($ins_data);
}
}
}
}
}
private function _connectToPdnsDb()
{
// get froxlor pdns config
$cf = Settings::Get('system.bindconf_directory').'/froxlor/pdns_froxlor.conf';
$config = makeCorrectFile($cf);
if (!file_exists($config))
{
$this->_logger->logAction(CRON_ACTION, LOG_ERROR, 'PowerDNS configuration file ('.$config.') not found. Did you go through the configuration templates?');
die('PowerDNS configuration file ('.$config.') not found. Did you go through the configuration templates?'.PHP_EOL);
}
$lines = file($config);
$mysql_data = array();
foreach ($lines as $line)
{
$line = trim($line);
if (strtolower(substr($line, 0, 6)) == 'gmysql')
{
$namevalue = explode("=", $line);
$mysql_data[$namevalue[0]] = $namevalue[1];
}
}
// build up connection string
$driver = 'mysql';
$dsn = $driver.":";
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'set names utf8');
$attributes = array('ATTR_ERRMODE' => 'ERRMODE_EXCEPTION');
$dbconf = array();
$dbconf["dsn"] = array(
'dbname' => $mysql_data["gmysql-dbname"],
'charset' => 'utf8'
);
if (isset($mysql_data['gmysql-socket']) && !empty($mysql_data['gmysql-socket'])) {
$dbconf["dsn"]['unix_socket'] = makeCorrectFile($mysql_data['gmysql-socket']);
} else {
$dbconf["dsn"]['host'] = $mysql_data['gmysql-host'];
$dbconf["dsn"]['port'] = $mysql_data['gmysql-port'];
}
// add options to dsn-string
foreach ($dbconf["dsn"] as $k => $v) {
$dsn .= $k."=".$v.";";
}
// clean up
unset($dbconf);
// try to connect
try {
$this->pdns_db = new PDO($dsn, $mysql_data['gmysql-user'], $mysql_data['gmysql-password'], $options);
} catch (PDOException $e) {
die($e->getMessage());
}
// set attributes
foreach ($attributes as $k => $v) {
$this->pdns_db->setAttribute(constant("PDO::".$k), constant("PDO::".$v));
}
}
}

View File

@@ -81,13 +81,23 @@ class apache extends HttpConfigBase {
}
$this->virtualhosts_data[$vhosts_filename].= ' <Directory "' . makeCorrectDir(Settings::Get('system.documentroot_prefix')) . '">' . "\n";
// >=apache-2.4 enabled?
if (Settings::Get('system.apache24') == '1') {
$this->virtualhosts_data[$vhosts_filename].= ' Require all granted' . "\n";
$this->virtualhosts_data[$vhosts_filename].= ' AllowOverride All' . "\n";
} else {
$this->virtualhosts_data[$vhosts_filename].= ' Order allow,deny' . "\n";
$this->virtualhosts_data[$vhosts_filename].= ' allow from all' . "\n";
// check for custom values, see #1638
$custom_opts = Settings::Get('system.apacheglobaldiropt');
if (!empty($custom_opts))
{
$this->virtualhosts_data[$vhosts_filename].= $custom_opts . "\n";
}
else
{
// >=apache-2.4 enabled?
if (Settings::Get('system.apache24') == '1') {
$this->virtualhosts_data[$vhosts_filename].= ' Require all granted' . "\n";
$this->virtualhosts_data[$vhosts_filename].= ' AllowOverride All' . "\n";
} else {
$this->virtualhosts_data[$vhosts_filename].= ' Order allow,deny' . "\n";
$this->virtualhosts_data[$vhosts_filename].= ' allow from all' . "\n";
}
}
$this->virtualhosts_data[$vhosts_filename].= ' </Directory>' . "\n";
}

View File

@@ -671,7 +671,7 @@ class nginx extends HttpConfigBase {
$path_options .= "\t\t" . 'autoindex on;' . "\n";
$this->vhost_root_autoindex = false;
}
// $path_options.= "\t\t" . 'try_files $uri $uri/ @rewrites;'."\n";
// check if we have a htpasswd for this path
// (damn nginx does not like more than one
// 'location'-part with the same path)
@@ -859,9 +859,17 @@ class nginx extends HttpConfigBase {
$this->_deactivated = false;
}
$webroot_text .= "\t" . 'index index.php index.html index.htm;'."\n";
$webroot_text .= "\n\t".'location / {'."\n";
$webroot_text .= "\t\t" . 'try_files $uri $uri/ @rewrites;'."\n";
if ($domain['phpenabled'] == '1')
{
$webroot_text .= "\t" . 'index index.php index.html index.htm;'."\n";
$webroot_text .= "\t\t" . 'try_files $uri $uri/ @rewrites;'."\n";
}
else
{
$webroot_text .= "\t" . 'index index.html index.htm;'."\n";
}
if ($this->vhost_root_autoindex) {
$webroot_text .= "\t\t".'autoindex on;'."\n";
@@ -869,9 +877,12 @@ class nginx extends HttpConfigBase {
}
$webroot_text .= "\t".'}'."\n\n";
$webroot_text .= "\tlocation @rewrites {\n";
$webroot_text .= "\t\trewrite ^ /index.php last;\n";
$webroot_text .= "\t}\n\n";
if ($domain['phpenabled'] == '1')
{
$webroot_text .= "\tlocation @rewrites {\n";
$webroot_text .= "\t\trewrite ^ /index.php last;\n";
$webroot_text .= "\t}\n\n";
}
return $webroot_text;
}

View File

@@ -19,6 +19,7 @@
// necessary includes
require_once makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.dns.10.bind.php');
require_once makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.dns.20.pdns.php');
require_once makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.http.10.apache.php');
require_once makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.http.15.apache_fcgid.php');
require_once makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.http.20.lighttpd.php');
@@ -179,8 +180,11 @@ while ($row = $result_tasks_stmt->fetch(PDO::FETCH_ASSOC)) {
* TYPE=4 MEANS THAT SOMETHING IN THE BIND CONFIG HAS CHANGED. REBUILD froxlor_bind.conf IF BIND IS ENABLED
*/
elseif ($row['type'] == '4' && (int)Settings::Get('system.bind_enable') != 0) {
$dnssrv = Settings::Get('system.dns_server');
if (!isset($nameserver)) {
$nameserver = new bind($cronlog);
$nameserver = new $dnssrv($cronlog);
}
if (Settings::Get('dkim.use_dkim') == '1') {

View File

@@ -139,7 +139,7 @@ while ($row_database = $databases_stmt->fetch(PDO::FETCH_ASSOC)) {
// sum up result
$mysqlusage_all[$row_database['customerid']] += floatval($mysql_usage_row['customerusage']);
} else {
echo "Seems like the database " . $row_database['databasename'] . " had been removed manually.\n";
$cronlog->logAction(CRON_ACTION, LOG_WARNING, "Seems like the database " . $row_database['databasename'] . " had been removed manually.");
}
}

View File

@@ -15,194 +15,197 @@
*
*/
/**
* report about diskusage for customers
*/
$result_stmt = Database::query("
SELECT `c`.`customerid`, `c`.`adminid`, `c`.`name`, `c`.`firstname`,
`c`.`company`, `c`.`diskspace`, `c`.`diskspace_used`, `c`.`email`, `c`.`def_language`,
`a`.`name` AS `adminname`, `a`.`email` AS `adminmail`
FROM `" . TABLE_PANEL_CUSTOMERS . "` AS `c`
LEFT JOIN `" . TABLE_PANEL_ADMINS . "` AS `a`
ON `a`.`adminid` = `c`.`adminid`
WHERE `c`.`diskspace` > '0' AND `c`.`reportsent` <> '2'
");
if ((int)Settings::Get('system.report_webmax') > 0)
{
/**
* report about diskusage for customers
*/
$result_stmt = Database::query("
SELECT `c`.`customerid`, `c`.`adminid`, `c`.`name`, `c`.`firstname`,
`c`.`company`, `c`.`diskspace`, `c`.`diskspace_used`, `c`.`email`, `c`.`def_language`,
`a`.`name` AS `adminname`, `a`.`email` AS `adminmail`
FROM `" . TABLE_PANEL_CUSTOMERS . "` AS `c`
LEFT JOIN `" . TABLE_PANEL_ADMINS . "` AS `a`
ON `a`.`adminid` = `c`.`adminid`
WHERE `c`.`diskspace` > '0' AND `c`.`reportsent` <> '2'
");
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if (isset($row['diskspace'])
&& $row['diskspace_used'] != null
&& $row['diskspace_used'] > 0
&& (($row['diskspace_used'] * 100) / $row['diskspace']) >= (int)Settings::Get('system.report_webmax')
) {
if (isset($row['diskspace'])
&& $row['diskspace_used'] != null
&& $row['diskspace_used'] > 0
&& (($row['diskspace_used'] * 100) / $row['diskspace']) >= (int)Settings::Get('system.report_webmax')
) {
$rep_userinfo = array(
'name' => $row['name'],
'firstname' => $row['firstname'],
'company' => $row['company']
);
$replace_arr = array(
'SALUTATION' => getCorrectUserSalutation($rep_userinfo),
'NAME' => $row['name'], // < keep this for compatibility
'DISKAVAILABLE' => round(($row['diskspace'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'DISKUSED' => round($row['diskspace_used'] / 1024, 2), /* traffic is stored in KB, template uses MB */
'USAGE_PERCENT' => round(($row['diskspace_used'] * 100) / $row['diskspace'], 2),
'MAX_PERCENT' => Settings::Get('system.report_webmax')
);
$rep_userinfo = array(
'name' => $row['name'],
'firstname' => $row['firstname'],
'company' => $row['company']
);
$replace_arr = array(
'SALUTATION' => getCorrectUserSalutation($rep_userinfo),
'NAME' => $row['name'], // < keep this for compatibility
'DISKAVAILABLE' => round(($row['diskspace'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'DISKUSED' => round($row['diskspace_used'] / 1024, 2), /* traffic is stored in KB, template uses MB */
'USAGE_PERCENT' => round(($row['diskspace_used'] * 100) / $row['diskspace'], 2),
'MAX_PERCENT' => Settings::Get('system.report_webmax')
);
$lngfile_stmt = Database::prepare("
SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "`
WHERE `language` = :deflang
");
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => $row['def_language']));
$lngfile_stmt = Database::prepare("
SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "`
WHERE `language` = :deflang
");
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => $row['def_language']));
if ($lngfile !== null) {
$langfile = $lngfile['file'];
} else {
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => Settings::Get('panel.standardlanguage')));
$langfile = $lngfile['file'];
if ($lngfile !== null) {
$langfile = $lngfile['file'];
} else {
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => Settings::Get('panel.standardlanguage')));
$langfile = $lngfile['file'];
}
// include english language file (fallback)
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/lng/english.lng.php');
// include admin/customer language file
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/' . $langfile);
// Get mail templates from database; the ones from 'admin' are fetched for fallback
$result2_stmt = Database::prepare("
SELECT `value` FROM `" . TABLE_PANEL_TEMPLATES . "`
WHERE `adminid` = :adminid
AND `language` = :lang
AND `templategroup` = 'mails' AND `varname` = :varname
");
$result2_data = array(
'adminid' => $row['adminid'],
'lang' => $row['def_language'],
'varname' => 'diskmaxpercent_subject'
);
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'diskmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
try {
$mail->SetFrom($row['adminmail'], $row['adminname']);
$mail->Subject = $mail_subject;
$mail->AltBody = $mail_body;
$mail->MsgHTML(nl2br($mail_body));
$mail->AddAddress($row['email'], $row['name']);
$mail->Send();
} catch(phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$cronlog->logAction(CRON_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
echo "Error sending mail: " . $mailerr_msg . "\n";
}
$mail->ClearAddresses();
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `reportsent` = '2'
WHERE `customerid` = :customerid
");
Database::pexecute($upd_stmt, array('customerid' => $row['customerid']));
}
// include english language file (fallback)
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/lng/english.lng.php');
// include admin/customer language file
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/' . $langfile);
// Get mail templates from database; the ones from 'admin' are fetched for fallback
$result2_stmt = Database::prepare("
SELECT `value` FROM `" . TABLE_PANEL_TEMPLATES . "`
WHERE `adminid` = :adminid
AND `language` = :lang
AND `templategroup` = 'mails' AND `varname` = :varname
");
$result2_data = array(
'adminid' => $row['adminid'],
'lang' => $row['def_language'],
'varname' => 'diskmaxpercent_subject'
);
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'diskmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
try {
$mail->SetFrom($row['adminmail'], $row['adminname']);
$mail->Subject = $mail_subject;
$mail->AltBody = $mail_body;
$mail->MsgHTML(nl2br($mail_body));
$mail->AddAddress($row['email'], $row['name']);
$mail->Send();
} catch(phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$cronlog->logAction(CRON_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
echo "Error sending mail: " . $mailerr_msg . "\n";
}
$mail->ClearAddresses();
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `reportsent` = '2'
WHERE `customerid` = :customerid
");
Database::pexecute($upd_stmt, array('customerid' => $row['customerid']));
}
}
/**
* report about diskusage for admins/reseller
*/
$result_stmt = Database::query("
SELECT `a`.* FROM `" . TABLE_PANEL_ADMINS . "` `a` WHERE `a`.`reportsent` <> '2'
");
/**
* report about diskusage for admins/reseller
*/
$result_stmt = Database::query("
SELECT `a`.* FROM `" . TABLE_PANEL_ADMINS . "` `a` WHERE `a`.`reportsent` <> '2'
");
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if (isset($row['diskspace'])
&& $row['diskspace_used'] != null
&& $row['diskspace_used'] > 0
&& (($row['diskspace_used'] * 100) / $row['diskspace']) >= (int)Settings::Get('system.report_webmax')
) {
if (isset($row['diskspace'])
&& $row['diskspace_used'] != null
&& $row['diskspace_used'] > 0
&& (($row['diskspace_used'] * 100) / $row['diskspace']) >= (int)Settings::Get('system.report_webmax')
) {
$replace_arr = array(
'NAME' => $row['name'],
'DISKAVAILABLE' => ($row['diskspace'] / 1024), /* traffic is stored in KB, template uses MB */
'DISKUSED' => round($row['diskspace_used'] / 1024, 2), /* traffic is stored in KB, template uses MB */
'USAGE_PERCENT' => ($row['diskspace_used'] * 100) / $row['diskspace'],
'MAX_PERCENT' => Settings::Get('system.report_webmax')
);
$replace_arr = array(
'NAME' => $row['name'],
'DISKAVAILABLE' => ($row['diskspace'] / 1024), /* traffic is stored in KB, template uses MB */
'DISKUSED' => round($row['diskspace_used'] / 1024, 2), /* traffic is stored in KB, template uses MB */
'USAGE_PERCENT' => ($row['diskspace_used'] * 100) / $row['diskspace'],
'MAX_PERCENT' => Settings::Get('system.report_webmax')
);
$lngfile_stmt = Database::prepare("
SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "`
WHERE `language` = :deflang
");
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => $row['def_language']));
$lngfile_stmt = Database::prepare("
SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "`
WHERE `language` = :deflang
");
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => $row['def_language']));
if ($lngfile !== null) {
$langfile = $lngfile['file'];
} else {
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => Settings::Get('panel.standardlanguage')));
$langfile = $lngfile['file'];
if ($lngfile !== null) {
$langfile = $lngfile['file'];
} else {
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => Settings::Get('panel.standardlanguage')));
$langfile = $lngfile['file'];
}
// include english language file (fallback)
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/lng/english.lng.php');
// include admin/customer language file
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/' . $langfile);
// Get mail templates from database; the ones from 'admin' are fetched for fallback
$result2_stmt = Database::prepare("
SELECT `value` FROM `" . TABLE_PANEL_TEMPLATES . "`
WHERE `adminid` = :adminid
AND `language` = :lang
AND `templategroup` = 'mails' AND `varname` = :varname
");
$result2_data = array(
'adminid' => $row['adminid'],
'lang' => $row['def_language'],
'varname' => 'diskmaxpercent_subject'
);
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'diskmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
try {
$mail->SetFrom($row['email'], $row['name']);
$mail->Subject = $mail_subject;
$mail->AltBody = $mail_body;
$mail->MsgHTML(nl2br($mail_body));
$mail->AddAddress($row['email'], $row['name']);
$mail->Send();
} catch(phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$cronlog->logAction(CRON_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
echo "Error sending mail: " . $mailerr_msg . "\n";
}
$mail->ClearAddresses();
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_ADMINS . "` SET `reportsent` = '2'
WHERE `adminid` = :adminid
");
Database::pexecute($upd_stmt, array('adminid' => $row['adminid']));
}
// include english language file (fallback)
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/lng/english.lng.php');
// include admin/customer language file
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/' . $langfile);
// Get mail templates from database; the ones from 'admin' are fetched for fallback
$result2_stmt = Database::prepare("
SELECT `value` FROM `" . TABLE_PANEL_TEMPLATES . "`
WHERE `adminid` = :adminid
AND `language` = :lang
AND `templategroup` = 'mails' AND `varname` = :varname
");
$result2_data = array(
'adminid' => $row['adminid'],
'lang' => $row['def_language'],
'varname' => 'diskmaxpercent_subject'
);
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'diskmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
try {
$mail->SetFrom($row['email'], $row['name']);
$mail->Subject = $mail_subject;
$mail->AltBody = $mail_body;
$mail->MsgHTML(nl2br($mail_body));
$mail->AddAddress($row['email'], $row['name']);
$mail->Send();
} catch(phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$cronlog->logAction(CRON_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
echo "Error sending mail: " . $mailerr_msg . "\n";
}
$mail->ClearAddresses();
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_ADMINS . "` SET `reportsent` = '2'
WHERE `adminid` = :adminid
");
Database::pexecute($upd_stmt, array('adminid' => $row['adminid']));
}
}
} // webmax > 0

View File

@@ -34,289 +34,291 @@ if (PHPMailer::ValidateAddress(Settings::Get('panel.adminmail')) !== false) {
}
}
// Warn the customers at xx% traffic-usage
if ((int)Settings::Get('system.report_trafficmax') > 0)
{
// Warn the customers at xx% traffic-usage
$result_stmt = Database::prepare("
SELECT `c`.`customerid`, `c`.`adminid`, `c`.`name`, `c`.`firstname`,
`c`.`company`, `c`.`traffic`, `c`.`email`, `c`.`def_language`,
`a`.`name` AS `adminname`, `a`.`email` AS `adminmail`,
(SELECT SUM(`t`.`http` + `t`.`ftp_up` + `t`.`ftp_down` + `t`.`mail`)
FROM `" . TABLE_PANEL_TRAFFIC . "` `t`
WHERE `t`.`customerid` = `c`.`customerid` AND `t`.`year` = :year AND `t`.`month` = :month
) as `traffic_used`
FROM `" . TABLE_PANEL_CUSTOMERS . "` AS `c`
LEFT JOIN `" . TABLE_PANEL_ADMINS . "` AS `a`
ON `a`.`adminid` = `c`.`adminid` WHERE `c`.`reportsent` <> '1'
");
$result_stmt = Database::prepare("
SELECT `c`.`customerid`, `c`.`adminid`, `c`.`name`, `c`.`firstname`,
`c`.`company`, `c`.`traffic`, `c`.`email`, `c`.`def_language`,
`a`.`name` AS `adminname`, `a`.`email` AS `adminmail`,
(SELECT SUM(`t`.`http` + `t`.`ftp_up` + `t`.`ftp_down` + `t`.`mail`)
FROM `" . TABLE_PANEL_TRAFFIC . "` `t`
WHERE `t`.`customerid` = `c`.`customerid` AND `t`.`year` = :year AND `t`.`month` = :month
) as `traffic_used`
FROM `" . TABLE_PANEL_CUSTOMERS . "` AS `c`
LEFT JOIN `" . TABLE_PANEL_ADMINS . "` AS `a`
ON `a`.`adminid` = `c`.`adminid` WHERE `c`.`reportsent` <> '1'
");
$result_data = array(
'year' => date("Y", $yesterday),
'month' => date("m", $yesterday)
);
Database::pexecute($result_stmt, $result_data);
$result_data = array(
'year' => date("Y", $yesterday),
'month' => date("m", $yesterday)
);
Database::pexecute($result_stmt, $result_data);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if (isset($row['traffic'])
&& $row['traffic'] > 0
&& $row['traffic_used'] != null
&& (($row['traffic_used'] * 100) / $row['traffic']) >= (int)Settings::Get('system.report_trafficmax')
) {
$rep_userinfo = array(
'name' => $row['name'],
'firstname' => $row['firstname'],
'company' => $row['company']
);
$replace_arr = array(
'SALUTATION' => getCorrectUserSalutation($rep_userinfo),
'NAME' => $row['name'], // < keep this for compatibility
'TRAFFIC' => round(($row['traffic'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'TRAFFICUSED' => round(($row['traffic_used'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'USAGE_PERCENT' => round(($row['traffic_used'] * 100) / $row['traffic'], 2),
'MAX_PERCENT' => Settings::Get('system.report_trafficmax')
);
if (isset($row['traffic'])
&& $row['traffic'] > 0
&& $row['traffic_used'] != null
&& (($row['traffic_used'] * 100) / $row['traffic']) >= (int)Settings::Get('system.report_trafficmax')
) {
$rep_userinfo = array(
'name' => $row['name'],
'firstname' => $row['firstname'],
'company' => $row['company']
);
$replace_arr = array(
'SALUTATION' => getCorrectUserSalutation($rep_userinfo),
'NAME' => $row['name'], // < keep this for compatibility
'TRAFFIC' => round(($row['traffic'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'TRAFFICUSED' => round(($row['traffic_used'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'USAGE_PERCENT' => round(($row['traffic_used'] * 100) / $row['traffic'], 2),
'MAX_PERCENT' => Settings::Get('system.report_trafficmax')
);
$lngfile_stmt = Database::prepare("
SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "`
WHERE `language` = :deflang
");
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => $row['def_language']));
$lngfile_stmt = Database::prepare("
SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "`
WHERE `language` = :deflang
");
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => $row['def_language']));
if ($lngfile !== null) {
$langfile = $lngfile['file'];
} else {
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => Settings::Get('panel.standardlanguage')));
$langfile = $lngfile['file'];
}
if ($lngfile !== null) {
$langfile = $lngfile['file'];
} else {
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => Settings::Get('panel.standardlanguage')));
$langfile = $lngfile['file'];
// include english language file (fallback)
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/lng/english.lng.php');
// include admin/customer language file
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/' . $langfile);
// Get mail templates from database; the ones from 'admin' are fetched for fallback
$result2_stmt = Database::prepare("
SELECT `value` FROM `" . TABLE_PANEL_TEMPLATES . "`
WHERE `adminid` = :adminid
AND `language` = :lang
AND `templategroup` = 'mails' AND `varname` = :varname
");
$result2_data = array(
'adminid' => $row['adminid'],
'lang' => $row['def_language'],
'varname' => 'trafficmaxpercent_subject'
);
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'trafficmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
try {
$mail->SetFrom($row['adminmail'], $row['adminname']);
$mail->Subject = $mail_subject;
$mail->AltBody = $mail_body;
$mail->MsgHTML(nl2br($mail_body));
$mail->AddAddress($row['email'], $row['firstname'] . ' ' . $row['name']);
$mail->Send();
} catch(phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$cronlog->logAction(CRON_ACTION, LOG_ERR, 'Error sending mail: ' . $mailerr_msg);
echo 'Error sending mail: ' . $mailerr_msg . "\n";
}
$mail->ClearAddresses();
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `reportsent` = '1'
WHERE `customerid` = :customerid
");
Database::pexecute($upd_stmt, array('customerid' => $row['customerid']));
}
// include english language file (fallback)
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/lng/english.lng.php');
// include admin/customer language file
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/' . $langfile);
// Get mail templates from database; the ones from 'admin' are fetched for fallback
$result2_stmt = Database::prepare("
SELECT `value` FROM `" . TABLE_PANEL_TEMPLATES . "`
WHERE `adminid` = :adminid
AND `language` = :lang
AND `templategroup` = 'mails' AND `varname` = :varname
");
$result2_data = array(
'adminid' => $row['adminid'],
'lang' => $row['def_language'],
'varname' => 'trafficmaxpercent_subject'
);
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'trafficmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
try {
$mail->SetFrom($row['adminmail'], $row['adminname']);
$mail->Subject = $mail_subject;
$mail->AltBody = $mail_body;
$mail->MsgHTML(nl2br($mail_body));
$mail->AddAddress($row['email'], $row['firstname'] . ' ' . $row['name']);
$mail->Send();
} catch(phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$cronlog->logAction(CRON_ACTION, LOG_ERR, 'Error sending mail: ' . $mailerr_msg);
echo 'Error sending mail: ' . $mailerr_msg . "\n";
}
$mail->ClearAddresses();
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `reportsent` = '1'
WHERE `customerid` = :customerid
");
Database::pexecute($upd_stmt, array('customerid' => $row['customerid']));
}
}
// Warn the admins at xx% traffic-usage
$result_stmt = Database::prepare("
SELECT `a`.*,
(SELECT SUM(`t`.`http` + `t`.`ftp_up` + `t`.`ftp_down` + `t`.`mail`)
FROM `" . TABLE_PANEL_TRAFFIC_ADMINS . "` `t`
WHERE `t`.`adminid` = `a`.`adminid` AND `t`.`year` = :year AND `t`.`month` = :month
) as `traffic_used_total`
FROM `" . TABLE_PANEL_ADMINS . "` `a` WHERE `a`.`reportsent` = '0'
");
$result_data = array(
'year' => date("Y", $yesterday),
'month' => date("m", $yesterday)
);
Database::pexecute($result_stmt, $result_data);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if (isset($row['traffic'])
&& $row['traffic'] > 0
&& (($row['traffic_used_total'] * 100) / $row['traffic']) >= (int)Settings::Get('system.report_trafficmax')
) {
$replace_arr = array(
'NAME' => $row['name'],
'TRAFFIC' => round(($row['traffic'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'TRAFFICUSED' => round(($row['traffic_used_total'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'USAGE_PERCENT' => round(($row['traffic_used_total'] * 100) / $row['traffic'], 2),
'MAX_PERCENT' => Settings::Get('system.report_trafficmax')
);
$lngfile_stmt = Database::prepare("
SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "`
WHERE `language` = :deflang
");
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => $row['def_language']));
if ($lngfile !== null) {
$langfile = $lngfile['file'];
} else {
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => Settings::Get('panel.standardlanguage')));
$langfile = $lngfile['file'];
}
// include english language file (fallback)
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/lng/english.lng.php');
// include admin/customer language file
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/' . $langfile);
// Get mail templates from database; the ones from 'admin' are fetched for fallback
$result2_stmt = Database::prepare("
SELECT `value` FROM `" . TABLE_PANEL_TEMPLATES . "`
WHERE `adminid` = :adminid
AND `language` = :lang
AND `templategroup` = 'mails' AND `varname` = :varname
");
$resul2_data = array(
'adminid' => $row['adminid'],
'lang' => $row['def_language'],
'varname' => 'trafficmaxpercent_subject'
);
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['subject']), $replace_arr));
$resul2_data['varname'] = 'trafficmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
try {
$mail->SetFrom($row['email'], $row['name']);
$mail->Subject = $mail_subject;
$mail->AltBody = $mail_body;
$mail->MsgHTML(nl2br($mail_body));
$mail->AddAddress($row['email'], $row['name']);
$mail->Send();
} catch(phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$cronlog->logAction(CRON_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
echo "Error sending mail: " . $mailerr_msg . "\n";
}
$mail->ClearAddresses();
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_ADMINS . "` SET `reportsent` = '1'
WHERE `adminid` = :adminid
");
Database::pexecute($upd_stmt, array('adminid' => $row['adminid']));
}
// Another month, let's build our report
if (date('d') == '01') {
// Warn the admins at xx% traffic-usage
$result_stmt = Database::prepare("
SELECT `a`.*,
(SELECT SUM(`t`.`http` + `t`.`ftp_up` + `t`.`ftp_down` + `t`.`mail`)
FROM `" . TABLE_PANEL_TRAFFIC_ADMINS . "` `t`
WHERE `t`.`adminid` = `a`.`adminid` AND `t`.`year` = :year AND `t`.`month` = :month
) as `traffic_used_total`
FROM `" . TABLE_PANEL_ADMINS . "` `a` WHERE `a`.`reportsent` = '0'
");
$mail_subject = 'Trafficreport ' . date("m/y", $yesterday) . ' for ' . $row['name'];
$mail_body = 'Trafficreport ' . date("m/y", $yesterday) . ' for ' . $row['name'] . "\n";
$mail_body.= '---------------------------------------------------------------' . "\n";
$mail_body.= 'Loginname Traffic used (Percent) | Traffic available' . "\n";
$customers_stmt = Database::prepare("
SELECT `c`.*,
(SELECT SUM(`t`.`http` + `t`.`ftp_up` + `t`.`ftp_down` + `t`.`mail`)
FROM `" . TABLE_PANEL_TRAFFIC . "` `t`
WHERE `t`.`customerid` = `c`.`customerid` AND `t`.`year` = :year AND `t`.`month` = :month
) as `traffic_used_total`
FROM `" . TABLE_PANEL_CUSTOMERS . "` `c` WHERE `c`.`adminid` = :adminid
");
$customers_data = array(
'year' => date("Y", $yesterday),
'month' => date("m", $yesterday),
'adminid' => $row['adminid']
);
Database::pexecute($customers_stmt, $customers_data);
$result_data = array(
'year' => date("Y", $yesterday),
'month' => date("m", $yesterday)
);
Database::pexecute($result_stmt, $result_data);
while ($customer = $customers_stmt->fetch(PDO::FETCH_ASSOC)) {
$t = $customer['traffic_used_total']/1048576;
if ($customer['traffic'] > 0) {
$p = (($customer['traffic_used_total'] * 100) / $customer['traffic'] );
$tg = $customer['traffic']/1048576;
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if (isset($row['traffic'])
&& $row['traffic'] > 0
&& (($row['traffic_used_total'] * 100) / $row['traffic']) >= (int)Settings::Get('system.report_trafficmax')
) {
$replace_arr = array(
'NAME' => $row['name'],
'TRAFFIC' => round(($row['traffic'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'TRAFFICUSED' => round(($row['traffic_used_total'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'USAGE_PERCENT' => round(($row['traffic_used_total'] * 100) / $row['traffic'], 2),
'MAX_PERCENT' => Settings::Get('system.report_trafficmax')
);
$lngfile_stmt = Database::prepare("
SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "`
WHERE `language` = :deflang
");
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => $row['def_language']));
if ($lngfile !== null) {
$langfile = $lngfile['file'];
} else {
$lngfile = Database::pexecute_first($lngfile_stmt, array('deflang' => Settings::Get('panel.standardlanguage')));
$langfile = $lngfile['file'];
}
// include english language file (fallback)
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/lng/english.lng.php');
// include admin/customer language file
include_once makeCorrectFile(FROXLOR_INSTALL_DIR . '/' . $langfile);
// Get mail templates from database; the ones from 'admin' are fetched for fallback
$result2_stmt = Database::prepare("
SELECT `value` FROM `" . TABLE_PANEL_TEMPLATES . "`
WHERE `adminid` = :adminid
AND `language` = :lang
AND `templategroup` = 'mails' AND `varname` = :varname
");
$resul2_data = array(
'adminid' => $row['adminid'],
'lang' => $row['def_language'],
'varname' => 'trafficmaxpercent_subject'
);
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['subject']), $replace_arr));
$resul2_data['varname'] = 'trafficmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(replace_variables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
try {
$mail->SetFrom($row['email'], $row['name']);
$mail->Subject = $mail_subject;
$mail->AltBody = $mail_body;
$mail->MsgHTML(nl2br($mail_body));
$mail->AddAddress($row['email'], $row['name']);
$mail->Send();
} catch(phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$cronlog->logAction(CRON_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
echo "Error sending mail: " . $mailerr_msg . "\n";
}
$mail->ClearAddresses();
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_ADMINS . "` SET `reportsent` = '1'
WHERE `adminid` = :adminid
");
Database::pexecute($upd_stmt, array('adminid' => $row['adminid']));
}
// Another month, let's build our report
if (date('d') == '01') {
$mail_subject = 'Trafficreport ' . date("m/y", $yesterday) . ' for ' . $row['name'];
$mail_body = 'Trafficreport ' . date("m/y", $yesterday) . ' for ' . $row['name'] . "\n";
$mail_body.= '---------------------------------------------------------------' . "\n";
$mail_body.= 'Loginname Traffic used (Percent) | Traffic available' . "\n";
$customers_stmt = Database::prepare("
SELECT `c`.*,
(SELECT SUM(`t`.`http` + `t`.`ftp_up` + `t`.`ftp_down` + `t`.`mail`)
FROM `" . TABLE_PANEL_TRAFFIC . "` `t`
WHERE `t`.`customerid` = `c`.`customerid` AND `t`.`year` = :year AND `t`.`month` = :month
) as `traffic_used_total`
FROM `" . TABLE_PANEL_CUSTOMERS . "` `c` WHERE `c`.`adminid` = :adminid
");
$customers_data = array(
'year' => date("Y", $yesterday),
'month' => date("m", $yesterday),
'adminid' => $row['adminid']
);
Database::pexecute($customers_stmt, $customers_data);
while ($customer = $customers_stmt->fetch(PDO::FETCH_ASSOC)) {
$t = $customer['traffic_used_total']/1048576;
if ($customer['traffic'] > 0) {
$p = (($customer['traffic_used_total'] * 100) / $customer['traffic'] );
$tg = $customer['traffic']/1048576;
$str = sprintf('%00.1f GB ( %00.1f %% )', $t, $p);
$mail_body.= sprintf('%-15s', $customer['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . sprintf('%00.1f GB', $tg) . "\n";
} else if ($customer['traffic'] == 0) {
$str = sprintf('%00.1f GB ( - )', $t);
$mail_body.= sprintf('%-15s', $customer['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . '0' . "\n";
} else {
$str = sprintf('%00.1f GB ( - )', $t);
$mail_body.= sprintf('%-15s', $customer['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . 'unlimited' . "\n";
}
}
$mail_body.= '---------------------------------------------------------------' . "\n";
$t = $row['traffic_used_total']/1048576;
if ($row['traffic'] > 0) {
$p = (($row['traffic_used_total'] * 100) / $row['traffic']);
$tg = $row['traffic']/1048576;
$str = sprintf('%00.1f GB ( %00.1f %% )', $t, $p);
$mail_body.= sprintf('%-15s', $customer['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . sprintf('%00.1f GB', $tg) . "\n";
} else if ($customer['traffic'] == 0) {
$mail_body.= sprintf('%-15s', $row['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . sprintf('%00.1f GB', $tg) . "\n";
} else if ($row['traffic'] == 0) {
$str = sprintf('%00.1f GB ( - )', $t);
$mail_body.= sprintf('%-15s', $customer['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . '0' . "\n";
$mail_body.= sprintf('%-15s', $row['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . '0' . "\n";
} else {
$str = sprintf('%00.1f GB ( - )', $t);
$mail_body.= sprintf('%-15s', $customer['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . 'unlimited' . "\n";
$mail_body.= sprintf('%-15s', $row['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . 'unlimited' . "\n";
}
$_mailerror = false;
try {
$mail->SetFrom($row['email'], $row['name']);
$mail->Subject = $mail_subject;
$mail->Body = $mail_body;
$mail->AddAddress($row['email'], $row['name']);
$mail->Send();
} catch(phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$cronlog->logAction(CRON_ACTION, LOG_ERR, 'Error sending mail: ' . $mailerr_msg);
echo 'Error sending mail: ' . $mailerr_msg . "\n";
}
$mail->ClearAddresses();
}
$mail_body.= '---------------------------------------------------------------' . "\n";
$t = $row['traffic_used_total']/1048576;
if ($row['traffic'] > 0) {
$p = (($row['traffic_used_total'] * 100) / $row['traffic']);
$tg = $row['traffic']/1048576;
$str = sprintf('%00.1f GB ( %00.1f %% )', $t, $p);
$mail_body.= sprintf('%-15s', $row['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . sprintf('%00.1f GB', $tg) . "\n";
} else if ($row['traffic'] == 0) {
$str = sprintf('%00.1f GB ( - )', $t);
$mail_body.= sprintf('%-15s', $row['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . '0' . "\n";
} else {
$str = sprintf('%00.1f GB ( - )', $t);
$mail_body.= sprintf('%-15s', $row['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . 'unlimited' . "\n";
}
$_mailerror = false;
try {
$mail->SetFrom($row['email'], $row['name']);
$mail->Subject = $mail_subject;
$mail->Body = $mail_body;
$mail->AddAddress($row['email'], $row['name']);
$mail->Send();
} catch(phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$cronlog->logAction(CRON_ACTION, LOG_ERR, 'Error sending mail: ' . $mailerr_msg);
echo 'Error sending mail: ' . $mailerr_msg . "\n";
}
$mail->ClearAddresses();
}
}
} // trafficmax > 0
// include diskspace-usage report, #466
include dirname(__FILE__).'/cron_usage.inc.diskspace.php';

View File

@@ -1,4 +0,0 @@
!Froxlor/
!Sparkle/
Froxlor/assets/img/logo_custom.png
!misc/

View File

@@ -20,8 +20,13 @@
<a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'edit', 'id' => $row['id']))}">
<img src="templates/{$theme}/assets/img/icons/edit.png" alt="{$lng['panel']['edit']}" title="{$lng['panel']['edit']}" />
</a>
<if $row['isbinddomain'] == '1' && Settings::Get('system.bind_enable') == '1' && Settings::Get('system.dnsenabled') == '1'>
&nbsp;<a href="{$linker->getLink(array('section' => 'domains', 'page' => 'domaindnseditor', 'domain_id' => $row['id']))}">
<img src="templates/{$theme}/assets/img/icons/dns_edit.png" alt="{$lng['dnseditor']['edit']}" title="{$lng['dnseditor']['edit']}" />
</a>
</if>
<if $row['letsencrypt'] == '1'>
<img src="templates/{$theme}/assets/img/icons/ssl_letsencrypt.png" alt="{$lng['panel']['letsencrypt']}" title="{$lng['panel']['letsencrypt']}" />
&nbsp;<img src="templates/{$theme}/assets/img/icons/ssl_letsencrypt.png" alt="{$lng['panel']['letsencrypt']}" title="{$lng['panel']['letsencrypt']}" />
</if>
<if !(isset($row['domainaliasid']) && $row['domainaliasid'] != 0) && $row['id'] != Settings::Get('system.hostname_id')>
<if !(isset($row['standardsubdomain']) && $row['standardsubdomain'] == $row['id'])>

View File

@@ -4,6 +4,9 @@ $header
<h2>
<img src="templates/{$theme}/assets/img/icons/domain_edit_big.png" alt="{$title}" />&nbsp;
{$title}
<if $result['isbinddomain'] == '1' && Settings::Get('system.bind_enable') == '1' && Settings::Get('system.dnsenabled') == '1'>
&nbsp;(<small><a href="{$linker->getLink(array('section' => 'domains', 'page' => 'domaindnseditor', 'domain_id' => $id))}">{$lng['dnseditor']['edit']}</a></small>)
</if>
</h2>
</header>

View File

@@ -601,6 +601,12 @@ input[type="password"] {
background:#fff url(../img/icons/lock.png) no-repeat 5px 4px;
}
input[class="small"] {
width:auto;
margin-top: 5px;
}
/*
* BUTTONS
*/
@@ -1513,3 +1519,19 @@ fieldset.file {
table.hl tbody tr.domain-hostname:hover {
background-color: rgb(64, 150, 238);
}
td.size-5 {
width: 5%;
}
td.size-10 {
width: 10%;
}
td.size-20 {
width: 20%;
}
td.size-50 {
width: 50%;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -93,9 +93,9 @@ $(document).ready(function() {
};
$.plot('#ftpchart', ftpdata, options);
$.plot('#httpchart', httpdata, options);
$.plot('#mailchart', maildata, options);
$('#ftpchart').plot(ftpdata, options);
$('#httpchart').plot(httpdata, options);
$('#mailchart').plot(maildata, options);
$("<div id='tooltip'></div>").css({
position: "absolute",

View File

@@ -1,14 +1,15 @@
<if $row['termination_date'] != ''>
<tr class="{$row['termination_css']}">
<tr class="{$row['termination_css']}">
</if>
<if $row['termination_date'] == ''>
<tr>
<tr>
</if>
<td><a href="http://{$row['domain']}" target="_blank">{$row['domain']}</a>
<if $row['termination_date'] != ''>
<br><small><div class="red">({$lng['domains']['termination_date_overview']} {$row['termination_date']})</div></small>
</if>
</td>
<td>
<a href="http://{$row['domain']}" target="_blank">{$row['domain']}</a>
<if $row['termination_date'] != ''>
<br><small><div class="red">({$lng['domains']['termination_date_overview']} {$row['termination_date']})</div></small>
</if>
</td>
<td>
<if $row['aliasdomain'] == ''>{$row['documentroot']}</if>
<if isset($row['aliasdomainid']) && $row['aliasdomainid'] != 0>{$lng['domains']['aliasdomain']} {$row['aliasdomain']}</if>
@@ -24,6 +25,11 @@
<img src="templates/{$theme}/assets/img/icons/delete.png" alt="{$lng['panel']['delete']}" title="{$lng['panel']['delete']}" />
</a>&nbsp;
</if>
<if $row['isbinddomain'] == '1' && $userinfo['dnsenabled'] == '1' && $row['caneditdomain'] == '1' && Settings::Get('system.bind_enable') == '1' && Settings::Get('system.dnsenabled') == '1'>
<a href="{$linker->getLink(array('section' => 'domains', 'page' => 'domaindnseditor', 'domain_id' => $row['id']))}">
<img src="templates/{$theme}/assets/img/icons/dns_edit.png" alt="{$lng['dnseditor']['edit']}" title="{$lng['dnseditor']['edit']}" />
</a>&nbsp;
</if>
<if $show_ssledit == 1>
<a href="{$linker->getLink(array('section' => 'domains', 'page' => 'domainssleditor', 'action' => 'view', 'id' => $row['id']))}">
<img src="templates/{$theme}/assets/img/icons/ssl_<if $row['domain_hascert'] == 1>customer</if><if $row['domain_hascert'] == 2>shared</if><if $row['domain_hascert'] == 0>global</if>.png" alt="{$lng['panel']['ssleditor']}" title="{$lng['panel']['ssleditor']}" />

View File

@@ -4,6 +4,9 @@ $header
<h2>
<img src="templates/{$theme}/assets/img/icons/domain_edit_big.png" alt="{$title}" />&nbsp;
{$title}
<if $result['isbinddomain'] == '1' && $userinfo['dnsenabled'] == '1' && Settings::Get('system.bind_enable') == '1' && Settings::Get('system.dnsenabled') == '1'>
&nbsp;(<small><a href="{$linker->getLink(array('section' => 'domains', 'page' => 'domaindnseditor', 'domain_id' => $id))}">{$lng['dnseditor']['edit']}</a></small>)
</if>
</h2>
</header>

View File

@@ -7,6 +7,15 @@ $header
</h2>
</header>
<if !empty($existing_backupJob)>
<div class="messagewrapperfull">
<div class="warningcontainer bradius">
<div class="warningtitle">{$lng['admin']['warning']}</div>
<div class="warning">{$lng['error']['customerhasongoingbackupjob']}</div>
</div>
</div>
</if>
<section>
<form action="{$linker->getLink(array('section' => 'extras'))}" method="post" enctype="application/x-www-form-urlencoded">

View File

@@ -0,0 +1,26 @@
<thead>
<tr>
<th>{$lng['panel']['path']}</th>
<th>{$lng['extras']['backup_web']}</th>
<th>{$lng['extras']['backup_mail']}</th>
<th>{$lng['extras']['backup_dbs']}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{$row['path']}</td>
<td>{$row['backup_web']}</td>
<td>{$row['backup_mail']}</td>
<td>{$row['backup_dbs']}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4">
<p>
<input type="hidden" name="backup_job_entry" value="{$existing_backupJob['id']}" />
<input type="submit" value="{$lng['panel']['abort']}" class="nobutton" />
</p>
</td>
</tr>
</tfoot>

View File

@@ -37,12 +37,18 @@ $header
</form>
<div id="charts" class="hidden">
<h3>HTTP {$lng['admin']['traffic']} ({$lng['traffic']['months']['total']} {$traffic_complete['http']})</h3>
<div id="httpchart" class="trafficchart"></div>
<h3>FTP {$lng['admin']['traffic']} ({$lng['traffic']['months']['total']} {$traffic_complete['ftp']})</h3>
<div id="ftpchart" class="trafficchart"></div>
<h3>Mail {$lng['admin']['traffic']} ({$lng['traffic']['months']['total']} {$traffic_complete['mail']})</h3>
<div id="mailchart" class="trafficchart"></div>
<if !Settings::IsInList('panel.customer_hide_options','traffic.http')>
<h3>HTTP {$lng['admin']['traffic']} ({$lng['traffic']['months']['total']} {$traffic_complete['http']})</h3>
<div id="httpchart" class="trafficchart"></div>
</if>
<if !Settings::IsInList('panel.customer_hide_options','traffic.ftp')>
<h3>FTP {$lng['admin']['traffic']} ({$lng['traffic']['months']['total']} {$traffic_complete['ftp']})</h3>
<div id="ftpchart" class="trafficchart"></div>
</if>
<if !Settings::IsInList('panel.customer_hide_options','traffic.mail')>
<h3>Mail {$lng['admin']['traffic']} ({$lng['traffic']['months']['total']} {$traffic_complete['mail']})</h3>
<div id="mailchart" class="trafficchart"></div>
</if>
</div>
</article>
$footer

View File

@@ -31,12 +31,18 @@ $header
</tbody>
</table>
<div id="charts" class="hidden">
<h3>HTTP {$lng['admin']['traffic']} ({$lng['traffic']['months']['total']} {$traffic_complete['http']})</h3>
<div id="httpchart" class="trafficchart"></div>
<h3>FTP {$lng['admin']['traffic']} ({$lng['traffic']['months']['total']} {$traffic_complete['ftp']})</h3>
<div id="ftpchart" class="trafficchart"></div>
<h3>Mail {$lng['admin']['traffic']} ({$lng['traffic']['months']['total']} {$traffic_complete['mail']})</h3>
<div id="mailchart" class="trafficchart"></div>
<if !Settings::IsInList('panel.customer_hide_options','traffic.http')>
<h3>HTTP {$lng['admin']['traffic']} ({$lng['traffic']['months']['total']} {$traffic_complete['http']})</h3>
<div id="httpchart" class="trafficchart"></div>
</if>
<if !Settings::IsInList('panel.customer_hide_options','traffic.ftp')>
<h3>FTP {$lng['admin']['traffic']} ({$lng['traffic']['months']['total']} {$traffic_complete['ftp']})</h3>
<div id="ftpchart" class="trafficchart"></div>
</if>
<if !Settings::IsInList('panel.customer_hide_options','traffic.mail')>
<h3>Mail {$lng['admin']['traffic']} ({$lng['traffic']['months']['total']} {$traffic_complete['mail']})</h3>
<div id="mailchart" class="trafficchart"></div>
</if>
</div>
</article>
$footer

View File

@@ -0,0 +1,10 @@
<tr>
<td>{$entry['record']}</td>
<td>{$entry['type']}</td>
<td><if ($entry['prio'] <= 0 && $entry['type'] != 'MX' && $entry['type'] != 'SRV')>&nbsp;<else>{$entry['prio']}</if></td>
<td>{$entry['content']}</td>
<td>{$entry['ttl']}</td>
<td>
<a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'delete', 'domain_id' => $domain_id, 'id' => $entry['id']))}"><img src="templates/{$theme}/assets/img/icons/delete.png" alt="{$lng['panel']['delete']}" title="{$lng['panel']['delete']}" /></a>
</td>
</tr>

39
templates/Sparkle/dns_editor/index.tpl vendored Normal file
View File

@@ -0,0 +1,39 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/domain_edit_big.png" alt="" />&nbsp;
DNS Editor&nbsp;(<a href="{$linker->getLink(array('section' => 'domains', 'page' => 'domains', 'action' => 'edit', 'id' => $domain_id))}">{$domain}</a>, {$entriescount} {$lng['dnseditor']['records']})
</h2>
</header>
<div class="messagewrapperfull">
<div class="warningcontainer bradius">
<div class="warningtitle">{$lng['admin']['warning']}</div>
<div class="warning">{$lng['dns']['howitworks']}</div>
</div>
</div>
<if !empty($errors)>
<div class="errorcontainer bradius">
<div class="errortitle">{$lng['error']['error']}</div>
<div class="error">{$errors}</div>
</div>
</if>
<if !empty($success_message)>
<div class="successcontainer bradius">
<div class="successtitle">{$lng['success']['success']}</div>
<div class="success">{$success_message}</div>
</div>
</if>
<section>
{$record_list}
</section>
</article>
<br><br>
<textarea rows="20" class="filecontent">{$zonefile}</textarea>
$footer

25
templates/Sparkle/dns_editor/list.tpl vendored Normal file
View File

@@ -0,0 +1,25 @@
<form method="post" action="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'add_record', 'domain_id' => $domain_id))}">
<table class="full hl">
<thead>
<tr>
<th class="size-20">Record</th>
<th class="size-5">Type</th>
<th class="size-5">Priority</th>
<th class="size-50">Content</th>
<th class="size-10">TTL</th>
<th class="size-10">&nbsp;</th>
</tr>
</thead>
<tbody>
<tr>
<td><input id="dns_record" type="text" name="record[record]" class="small" placeholder="Record" value="{$record}" /></td>
<td><select id="dns_type" name="record[type]" class="small">{$type_select}</select></td>
<td><input id="dns_mxp" type="text" name="record[prio]" class="small" placeholder="MX priority" value="{$prio}" /></td>
<td><input id="dns_content" type="text" name="record[content]" class="small" placeholder="Content" value="{$content}" /></td>
<td><input id="dns_ttl" type="text" name="record[ttl]" class="small" placeholder="18000" value="{$ttl}" /></td>
<td><input type="submit" class="submitsearch" value="add" name="add" /></td>
</tr>
{$existing_entries}
</tbody>
</table>
</form>