18 Commits

Author SHA1 Message Date
Wruczek b71ca1848c Dump version to dev-2.0.1 2019-01-09 12:14:57 +01:00
Wruczek 895e36c8ec Added new languages, updated translations, changed sql installation
Separated language in db dump, makes it easier for me to update
Added commit alongside the version in the generated config file
2019-01-09 12:09:15 +01:00
Wruczek 65ae062a96 New bans page format
- Favor showing banned user's name if available
- Support for MyTSID bans
- Show the ban type alongside it (is it a UID / IP / MyTSID ban?)
- Fixed a bug that caused the banned-ip alerts to not display if user's last name was known
2019-01-09 11:22:36 +01:00
Wruczek 7ac6d34e7b Added escape method to Utils 2019-01-09 11:15:07 +01:00
Wruczek a1eafee419 Updated MySQL schema with new translations
Huge thanks to @bykidi for the quick help with Russian translation!
2019-01-05 20:20:28 +01:00
Wruczek fa17ce4858 Revert the totalconnections update, its not available without db info 2019-01-05 20:14:02 +01:00
Wruczek 81495b21c4 Added the no reason set message on the bans page 2019-01-05 15:30:26 +01:00
Wruczek c7371b0fc0 Added favicon 2019-01-05 13:19:50 +01:00
Wruczek a9ff982c45 Small fixes
- added totalconnections to the client info API
- fixed width on datatables
2019-01-04 14:44:01 +01:00
Wruczek d8fec04d81 Added a shortened commit hash along the version
The commit value is replaced when building the zip file
2018-12-30 04:27:43 +01:00
Wruczek e1e95639ad Added tip about chmod, when file permission fail 2018-12-30 03:01:01 +01:00
Wruczek 8e606ad331 Fixed "headers already sent" error in installer 2018-12-29 17:52:07 +01:00
Wruczek ecdc0e6540 Added translation link 2018-12-29 02:48:29 +01:00
Robin 65e6a3634f Added link to German Readme
* Update README.md

Add a Link to the German Readme

* Update body.latte

Add a Link to the Contributors Page in the Copyright.

* Update body.latte

* Update README.md

* Update README.md
2018-12-28 22:45:06 +01:00
Wruczek 38103fdaf6 Added .htaccess with deny to the private directory 2018-12-28 11:02:53 +01:00
Wruczek a267b15054 Create README.md 2018-12-27 23:23:13 +01:00
Wruczek f01824d84d Removed a typo 2018-12-27 23:02:40 +01:00
Wruczek d065b6d962 Use website title in the footer 2018-12-27 22:59:58 +01:00
21 changed files with 1767 additions and 320 deletions
+1
View File
@@ -1,5 +1,6 @@
.idea
PROTOTYPING
tools
src/installer/cache
src/private/cache
src/private/vendor
+42
View File
@@ -0,0 +1,42 @@
<p align="center">
<b><a href="https://imgur.com/a/3vfIPJQ" target="_blank">View more screenshots</a>
</p>
[![Website screenshot](https://i.imgur.com/FuDJyGU.png?2)](https://imgur.com/a/3vfIPJQ)
<p align="center">
<a href="https://imgur.com/a/3vfIPJQ" target="_blank">View more screenshots</a> |
<a href="https://github.com/Wruczek/ts-website/wiki/%5BDE%5D-Readme-%7C-Liesmich-%5B2.x%5D" target="_blank">🇩🇪 Deutsches Readme</a>
</p>
<p align="center">
<b>Need help? <a href="https://t.me/tswebsite">Join our telegram group</a></b> for news, announcements, help and general chat about ts-website.
</p>
<hr>
**ts-website** - free website for your TeamSpeak 3 server<br>
<hr>
#### Useful links
- [Demo](https://ts.wruczek.tech/)
- [Installation instructions](https://github.com/Wruczek/ts-website/wiki/%5BEN%5D-Website-Installation)
- [Wiki](https://github.com/Wruczek/ts-website/wiki)
- [Report Issues / Suggestions](https://github.com/Wruczek/ts-website/issues/new)
- [Translate ts-website](https://wruczek.oneskyapp.com/collaboration/project/325562)
- **[ts-website Telegram group](https://t.me/tswebsite) - support, announcements, and general chat**
#### Main Features
- News page, dynamic server status, customizable admin status, server viewer, group assigner, ban list, rules, FAQ, impressum
- Ability for users to login with their TeamSpeak identity
- Multiple languages with auto-detection for default language
- Supports for PHP 5 and 7, Apache 2 and nginx
- Modern and responsive design
- Caching
- Free and Open source, under GPL-3.0
### Other stuff
I am happy to take any programming-related requests, add additional features or modify the code to suit your needs for a small donation :) I am experienced at Java, PHP, HTML, CSS, Javascript, SQL, server configurations ect.
For business enquiries only: **wruczekk** at **gmail.com**, for anything else please join our [Telegram group](https://t.me/ts-website).
+53 -11
View File
@@ -18,32 +18,74 @@ if ($banlist !== null) {
$data = [];
foreach ($banlist as $ban) {
// Bans abbreviations:
// if we see a UID, IP or MyTSID ban, and we know
// the nickname of the banned user, we will show
// the user's name and then the type of ban
// that should be enough info for most users.
// it is possible to hover over the ban type to
// view the exact ban target
//
// for example, Wruczek got banned on his UID. we know that
// his last nickname was "Wruczek", so we simply show, that
// the ban is issued for:
// Wruczek (UID)
// after hovering over the "UID", you will see the exact UID
//
// if we dont know the last name of the banned user, we
// will just show the UID, IP or MyTSID
$name = "(cannot determine a name)";
$target = "(unknown)";
$lastNickname = Utils::escape($ban["lastnickname"]);
$filter = "";
$abbreviation = null;
if ($ban["lastnickname"]) {
$name = (string)$ban["lastnickname"];
} else if ($ban["uid"]) {
$name = new Html("<code>" . $ban["uid"] . "</code>");
} else if ($ban["name"]) {
$name = (string)$ban["name"];
} else if ($ban["ip"]) {
$ip = str_replace("\\", "", (string) $ban["ip"]);
if ($ban["ip"]) {
$ip = str_replace("\\", "", (string)$ban["ip"]);
try {
$name = Utils::censorIpAddress($ip);
$ip = Utils::censorIpAddress($ip);
} catch (\Exception $e) {}
if ($lastNickname) {
$abbreviation = [$ip, "IP"];
} else {
$target = $ip;
}
if ($ip === Utils::getClientIp()) {
$ipbanned = [
"invoker" => (string)$ban["invokername"],
"reason" => (string)$ban["reason"]
];
}
} else if ($ban["uid"]) {
if ($lastNickname) {
$abbreviation = [$ban["uid"], "UID"];
} else {
$target = new Html("<code>" . $ban["uid"] . "</code>");
}
} else if ($ban["name"]) {
$target = $ban["name"];
} else if (!empty($ban["mytsid"])) { // empty, older TS servers dont have MYTS bans, so the key might not exist
if ($lastNickname) {
$abbreviation = [$ban["mytsid"], "MyTSID"];
} else {
$target = new Html("<code>" . $ban["mytsid"] . "</code>");
}
}
if ($abbreviation) {
$html = '%s (<span class="bans-highlight" data-toggle="tooltip" title="%s">%s</span>)';
$target = new Html(sprintf($html, $lastNickname, $abbreviation[0], $abbreviation[1]));
// make sure that the "full" data is also searchable in DataTables
$filter = "{$abbreviation[0]} $lastNickname";
}
$data[] = [
"name" => $name,
"filter" => $filter,
"target" => $target,
"reason" => (string)$ban["reason"],
"invoker" => (string)$ban["invokername"],
"created" => $ban["created"],
+5
View File
@@ -178,6 +178,11 @@ body {
align-items: center;
}
.bans-highlight {
color: #e83e8c;
font-family: var(--font-family-monospace);
}
/* Responsive datatables styles */
table.dataTable>tbody>tr.child ul.dtr-details>li:first-child {
+1 -259
View File
@@ -50,20 +50,6 @@ INSERT INTO `DBPREFIXfaq` (`faqid`, `langid`, `question`, `answer`, `lastmodify`
(2, 1, 'How can I configure the FAQ?', 'An administrator can add, edit and remove questions in <a href=\"admin\">admin panel</a>.', '2018-12-26 12:33:18'),
(3, 1, 'Question 3', 'Answer 3 in <b>HTML</b>', '2018-12-26 13:10:32');
DROP TABLE IF EXISTS `DBPREFIXlanguages`;
CREATE TABLE `DBPREFIXlanguages` (
`langid` int(11) NOT NULL,
`englishname` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`nativename` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`langcode` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'In this format: https://bit.ly/2MCGg6M',
`isdefault` tinyint(1) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `DBPREFIXlanguages` (`langid`, `englishname`, `nativename`, `langcode`, `isdefault`) VALUES
(1, 'English', 'English', 'en', 1),
(2, 'English (US)', 'English (US)', 'en-us', 0),
(3, 'Polish', 'Polski', 'pl', 0);
DROP TABLE IF EXISTS `DBPREFIXnews`;
CREATE TABLE `DBPREFIXnews` (
`newsid` int(11) NOT NULL,
@@ -75,239 +61,7 @@ CREATE TABLE `DBPREFIXnews` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `DBPREFIXnews` (`newsid`, `title`, `langid`, `added`, `edited`, `content`) VALUES
(1, 'Welcome to ts-website!', 1, '2018-12-26 13:10:32', NULL, '<b>Hi there!</b> If you are reading this, it means that TS-website has been installed successfully.<br>\r\nYou can login to your <a href=\"admin\">ACP</a> to configure many parts of it.<br>\r\nNeed help? Join our <a href=\"https://t.me/tswebsite\" target=\"_blank\">Telegram group</a> for support.\r\nHave a good day!');
DROP TABLE IF EXISTS `DBPREFIXtranslations`;
CREATE TABLE `DBPREFIXtranslations` (
`id` int(10) NOT NULL,
`langid` int(10) NOT NULL,
`identifier` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL,
`value` text COLLATE utf8mb4_unicode_ci NOT NULL,
`comment` text COLLATE utf8mb4_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `DBPREFIXtranslations` (`id`, `langid`, `identifier`, `value`, `comment`) VALUES
(1, 1, 'AUTHORS', 'Wruczek <wruczekk@gmail.com>', 'Language authors'),
(2, 3, 'AUTHORS', 'Wruczek <wruczekk@gmail.com>', NULL),
(3, 1, 'COOKIEALERT_MESSAGE', '<b>Do you like cookies?</b> &#x1F36A; We use cookies to ensure you get the best experience on our website. <a href=\"http://cookiesandyou.com/\" target=\"_blank\">Learn more</a>', 'Remember to change link to a website in your language'),
(4, 3, 'COOKIEALERT_MESSAGE', '<b>Lubisz ciasteczka?</b> &#x1F36A; Używamy ciasteczek, aby zapewnić najwyższą jakość usług. <a href=\"http://wszystkoociasteczkach.pl/\" target=\"_blank\">Dowiedz się więcej</a>', NULL),
(5, 1, 'COOKIEALERT_AGREE', 'I agree', NULL),
(6, 3, 'COOKIEALERT_AGREE', 'Zgadzam się', NULL),
(7, 1, 'OUTDATED_DATA', '<b>Warning!</b> Some information cannot be obtained now. Showing outdated data from {0}.', '{0} will be replaced with fuzzy date (for example \"8 hours ago\"). Please try to match the your message grammatically'),
(8, 3, 'OUTDATED_DATA', '<b>Uwaga!</b> Niektóre dane nie mogą być teraz uzyskane. Pokazuje nieaktualne dane z {0}.', NULL),
(9, 1, 'SHOW_PROBLEMS', 'Show problems', NULL),
(10, 3, 'SHOW_PROBLEMS', 'Pokaż problemy', NULL),
(11, 1, 'PROBLEMS_DESCRIPTION', 'Problems encountered while connecting to the TeamSpeak server', NULL),
(12, 3, 'PROBLEMS_DESCRIPTION', 'Problemy napotkane podczas próby połączenia się z serwerem TeamSpeak', NULL),
(13, 1, 'NO_JAVASCRIPT_ENABLED', 'This website will not work without <a href=\"https://www.enable-javascript.com/\" target=\"_blank\">JavaScript enabled</a>.', 'Remember to change the website address to include instructions in your language'),
(14, 3, 'NO_JAVASCRIPT_ENABLED', 'Ta stronie nie będzie działać bez <a href=\"https://www.enable-javascript.com/pl/\" target=\"_blank\">włączonej obsługi JavaScript</a>.', NULL),
(15, 1, 'CANNOT_GET_DATA', 'Cannot get data for \"{0}\"! Please contact website owner.', '{0} will be replaced with component name that cannot be refreshed (for example banlist or viewer)'),
(16, 3, 'CANNOT_GET_DATA', 'Nie mogę pobrać informacji o \"{0}\"! Skontaktuj się z właścicielem strony.', NULL),
(17, 1, 'NO_REASON_SET', '<b>(no reason set)</b>', 'Please keep the \"<b>\" tags in place, as they help to distinguish a placeholder form a real message'),
(18, 3, 'NO_REASON_SET', '<b>(brak powodu)</b>', NULL),
(19, 1, 'BANS_HEADER_NAME', 'Name / IP / UID', NULL),
(20, 3, 'BANS_HEADER_NAME', 'Nazwa / IP / UID', NULL),
(21, 1, 'BANS_HEADER_REASON', 'Reason', NULL),
(22, 3, 'BANS_HEADER_REASON', 'Powód', NULL),
(23, 1, 'BANS_HEADER_INVOKER', 'Banned by', NULL),
(24, 3, 'BANS_HEADER_INVOKER', 'Zbanowany przez', NULL),
(25, 1, 'BANS_HEADER_BANDATE', 'Ban date', NULL),
(26, 3, 'BANS_HEADER_BANDATE', 'Data zbanowania', NULL),
(27, 1, 'BANS_HEADER_EXPIRES', 'Expires', NULL),
(28, 3, 'BANS_HEADER_EXPIRES', 'Wygasa', NULL),
(29, 1, 'DATATABLES_LANGUAGE_NAME', 'English', 'This language will be used to load language file for DataTables. Please choose a language from this list: https://datatables.net/plug-ins/i18n/#Translations.\r\n\r\nIf chosen correctly, this url: \"//cdn.datatables.net/plug-ins/1.10.12/i18n/{NAME}.json\" should return a valid JSON object with translations. For example: \"//cdn.datatables.net/plug-ins/1.10.12/i18n/English.json\"'),
(30, 3, 'DATATABLES_LANGUAGE_NAME', 'Polish', NULL),
(31, 1, 'BANS_NEVEREXPIRES', 'Never', NULL),
(32, 3, 'BANS_NEVEREXPIRES', 'Nigdy', NULL),
(33, 1, 'STATUS_ADDRESS', 'Address:', ''),
(34, 3, 'STATUS_ADDRESS', 'Adres:', NULL),
(35, 1, 'STATUS_CLIENTS_ONLINE', 'Online:', NULL),
(36, 3, 'STATUS_CLIENTS_ONLINE', 'Online:', NULL),
(37, 1, 'STATUS_RESERVED_SLOTS', '{0} reserved slots', NULL),
(38, 3, 'STATUS_RESERVED_SLOTS', '{0} zarezerwowanych slotów', NULL),
(39, 1, 'STATUS_TOP_ONLINE', 'Top online:', NULL),
(40, 3, 'STATUS_TOP_ONLINE', 'Rekord online:', NULL),
(41, 1, 'STATUS_TOP_ONLINE_DESC', 'Achieved on {0}', NULL),
(42, 3, 'STATUS_TOP_ONLINE_DESC', 'Ustanowiono {0}', NULL),
(43, 1, 'STATUS_UPTIME', 'Uptime:', NULL),
(44, 3, 'STATUS_UPTIME', 'Uptime:', NULL),
(45, 1, 'STATUS_VERSION', 'Version:', NULL),
(46, 3, 'STATUS_VERSION', 'Wersja:', NULL),
(47, 1, 'STATUS_VERSION_DESC', '{0} on {1}', NULL),
(48, 3, 'STATUS_VERSION_DESC', '{0} na {1}', NULL),
(49, 1, 'STATUS_PING', 'Avg. ping:', NULL),
(50, 3, 'STATUS_PING', 'Śr. ping:', NULL),
(51, 1, 'STATUS_PACKETLOSS', 'Avg. packet loss:', NULL),
(52, 3, 'STATUS_PACKETLOSS', 'Śr. utrata pakietów:', NULL),
(53, 1, 'STATUS_ERROR', 'Cannot retrieve server status', NULL),
(54, 3, 'STATUS_ERROR', 'Błąd podczas wczytywania statusu serwera', NULL),
(55, 1, 'STATUS_PANEL_TITLE', 'Server status', NULL),
(56, 3, 'STATUS_PANEL_TITLE', 'Status serwera', NULL),
(57, 1, 'MOMENTJS_LANG', 'en-gb', 'Language for Moment.js, full list: https://github.com/moment/moment/tree/develop/locale'),
(58, 2, 'MOMENTJS_LANG', 'en-us', NULL),
(59, 3, 'MOMENTJS_LANG', 'pl', NULL),
(60, 1, 'LOGIN_CONFIRMATION_CODE', 'Hi, here\'s your confirmation code to login: [b]{0}[/b]', 'You can use BBCode. Use {0} for the confirmation code.'),
(61, 3, 'LOGIN_CONFIRMATION_CODE', 'Cześć, oto twój kod potwierdzający logowanie: [b]{0}[/b]', NULL),
(62, 1, 'UNSUPPORTED_BROWSER', 'Your browser is not supported. Please switch to the latest version of Chrome, Firefox, Safari or Edge to use this website.', ''),
(63, 3, 'UNSUPPORTED_BROWSER', 'Twoja przeglądarka nie jest wspierana. Zainstaluj najnowszą wersję Chrome, Firefox, Safari lub Edge by korzystać z tej strony.', NULL),
(64, 1, 'DATATABLES_PLACEHOLDER_SEARCH', 'Search...', NULL),
(65, 3, 'DATATABLES_PLACEHOLDER_SEARCH', 'Szukaj...', NULL),
(66, 1, 'WEBSITE_TITLE', ' | TS-website English Language', NULL),
(67, 3, 'WEBSITE_TITLE', ' | TS-website Język Polski', NULL),
(68, 1, 'ADMIN_STATUS_ONLINE', 'Online', NULL),
(69, 3, 'ADMIN_STATUS_ONLINE', 'Online', NULL),
(70, 1, 'ADMIN_STATUS_AWAY', 'Away', NULL),
(71, 3, 'ADMIN_STATUS_AWAY', 'Zaraz wracam', NULL),
(72, 1, 'ADMIN_STATUS_OFFLINE', 'Offline', NULL),
(73, 3, 'ADMIN_STATUS_OFFLINE', 'Offline', NULL),
(76, 1, 'ADMIN_STATUS_EMPTY_GROUP', 'Nothing to show', NULL),
(77, 3, 'ADMIN_STATUS_EMPTY_GROUP', 'Nic do pokazania', NULL),
(78, 1, 'ADMIN_STATUS_EMPTY_STATUS', 'Admin status is empty', NULL),
(79, 3, 'ADMIN_STATUS_EMPTY_STATUS', 'Status administracji jest pusty', NULL),
(80, 1, 'ASSIGNER_PANEL_TITLE', 'Group assigner', NULL),
(81, 3, 'ASSIGNER_PANEL_TITLE', 'Przydzielanie grup', NULL),
(82, 1, 'ASSIGNER_TITLE', 'Group assigner', NULL),
(83, 3, 'ASSIGNER_TITLE', 'Przydzielanie grup', NULL),
(84, 1, 'BANS_EMPTY', 'Banlist is empty', NULL),
(85, 3, 'BANS_EMPTY', 'Lista banów jest pusta', NULL),
(86, 1, 'BANS_TITLE', 'Banlist', NULL),
(87, 3, 'BANS_TITLE', 'Lista banów', NULL),
(88, 1, 'BANS_PANEL_TITLE', 'Banlist', NULL),
(89, 3, 'BANS_PANEL_TITLE', 'Lista banów', NULL),
(90, 1, 'BANS_BANNED_ALERT_TITLE', 'Your IP has been banned by {0}', NULL),
(91, 3, 'BANS_BANNED_ALERT_TITLE', 'Twoje IP zostało zbanowane przez {0}', NULL),
(92, 1, 'BANS_BANNED_ALERT_REASON', 'Reason: {0}', NULL),
(93, 3, 'BANS_BANNED_ALERT_REASON', 'Powód: {0}', NULL),
(94, 1, 'BANS_VIEW_MORE_TIP', 'Click on a row to view more details about a ban', NULL),
(95, 3, 'BANS_VIEW_MORE_TIP', 'Kliknij na wiersz by pokazać więcej informacji o banie', NULL),
(96, 1, 'RULES_TITLE', 'Rules', NULL),
(97, 3, 'RULES_TITLE', 'Regulamin', NULL),
(98, 1, 'RULES_PANEL_TITLE', 'Rules', NULL),
(99, 3, 'RULES_PANEL_TITLE', 'Regulamin', NULL),
(100, 1, 'FAQ_COPY_LINK', 'Copy link to that answer', NULL),
(101, 3, 'FAQ_COPY_LINK', 'Kopiuj link do tej odpowiedzi', NULL),
(102, 1, 'FAQ_PANEL_TITLE', 'FAQ', NULL),
(103, 3, 'FAQ_PANEL_TITLE', 'FAQ', NULL),
(104, 1, 'FAQ_TITLE', 'FAQ', NULL),
(105, 3, 'FAQ_TITLE', 'FAQ', NULL),
(106, 1, 'FAQ_COPY_LINK_SUCCESS', 'Copied!', NULL),
(107, 3, 'FAQ_COPY_LINK_SUCCESS', 'Skopiowano!', NULL),
(108, 1, 'FAQ_COPY_LINK_ERROR', 'Error!', NULL),
(109, 3, 'FAQ_COPY_LINK_ERROR', 'Błąd!', NULL),
(110, 1, 'HOME_TITLE', 'News', NULL),
(111, 3, 'HOME_TITLE', 'Aktualności', NULL),
(112, 1, 'HOME_PANEL_TITLE', 'News', NULL),
(113, 3, 'HOME_PANEL_TITLE', 'Aktualności', NULL),
(114, 1, 'HOME_EMPTY', 'No news available at this moment', NULL),
(115, 3, 'HOME_EMPTY', 'Brak atualności', NULL),
(116, 1, 'HOME_INVALID_PAGE', 'Invalid page number', NULL),
(117, 3, 'HOME_INVALID_PAGE', 'Zły numer strony', NULL),
(118, 1, 'HOME_PREVIOUS_NEWS', 'Previous', 'This value is only used by assistive technologies (screen readers ect.)'),
(119, 3, 'HOME_PREVIOUS_NEWS', 'Poprzednia', NULL),
(120, 1, 'HOME_NEXT_NEWS', 'Next', 'This value is only used by assistive technologies (screen readers ect.)'),
(121, 3, 'HOME_NEXT_NEWS', 'Następna', NULL),
(122, 1, 'ADMIN_STATUS_PANEL_TITLE', 'Admin status', NULL),
(123, 3, 'ADMIN_STATUS_PANEL_TITLE', 'Status administracji', NULL),
(124, 1, 'ADMIN_STATUS_HIDE_OFFLINE_TIP', 'Hide offline admins', NULL),
(125, 3, 'ADMIN_STATUS_HIDE_OFFLINE_TIP', 'Ukryj administratorów offline', NULL),
(126, 1, 'ADMIN_STATUS_SHOW_OFFLINE_TIP', 'Show offline admins', NULL),
(127, 3, 'ADMIN_STATUS_SHOW_OFFLINE_TIP', 'Pokaż administratorów offline', NULL),
(128, 1, 'ADMIN_STATUS_ERROR', 'Admin status error', NULL),
(129, 3, 'ADMIN_STATUS_ERROR', 'Błąd statusu administracji', NULL),
(130, 1, 'NAV_TOGGLE', 'Toggle navigation', 'This value is only used by assistive technologies (screen readers ect.)'),
(131, 3, 'NAV_TOGGLE', 'Przełącz nawigację', NULL),
(132, 1, 'NAV_VIEWER', 'Viewer', NULL),
(133, 3, 'NAV_VIEWER', 'Podgląd', NULL),
(134, 1, 'NAV_ASSIGNER', 'Assigner', NULL),
(135, 3, 'NAV_ASSIGNER', 'Grupy', NULL),
(136, 1, 'NAV_BANS', 'Bans', NULL),
(137, 3, 'NAV_BANS', 'Bany', NULL),
(138, 1, 'NAV_RULES', 'Rules', NULL),
(139, 3, 'NAV_RULES', 'Regulamin', NULL),
(140, 1, 'NAV_FAQ', 'FAQ', NULL),
(141, 3, 'NAV_FAQ', 'FAQ', NULL),
(142, 1, 'NAV_ACCOUNT_LOGIN', 'Login', NULL),
(143, 3, 'NAV_ACCOUNT_LOGIN', 'Zaloguj się', NULL),
(144, 1, 'NAV_ACCOUNT_LOGOUT', 'Logout', NULL),
(145, 3, 'NAV_ACCOUNT_LOGOUT', 'Wyloguj się', NULL),
(146, 1, 'VIEWER_TITLE', 'Server viewer', NULL),
(147, 3, 'VIEWER_TITLE', 'Podgląd serwera', NULL),
(148, 1, 'VIEWER_PANEL_TITLE', 'Server viewer', NULL),
(149, 3, 'VIEWER_PANEL_TITLE', 'Podgląd serwera', NULL),
(150, 1, 'VIEWER_SHOW_EMPTY', 'Show empty channels', NULL),
(151, 3, 'VIEWER_SHOW_EMPTY', 'Pokaż puste kanały', NULL),
(152, 1, 'VIEWER_HIDE_EMPTY', 'Hide empty channels', NULL),
(153, 3, 'VIEWER_HIDE_EMPTY', 'Ukryj puste kanały', NULL),
(154, 1, 'VIEWER_TIP_ALERT', 'Click on a channel to join it. Hover over a user to check their info', NULL),
(155, 3, 'VIEWER_TIP_ALERT', 'Kliknij na kanał, by na niego dołączyć. Nakieruj na użytkownika, by sprawdzić informacje o nim', NULL),
(158, 1, 'ARIA_CLOSE', 'Close', 'This value is only used by assistive technologies (screen readers ect.)'),
(159, 3, 'ARIA_CLOSE', 'Zamknij', NULL),
(160, 1, 'VIEWER_ERROR', 'Viewer error', NULL),
(161, 3, 'VIEWER_ERROR', 'Błąd podglądu', NULL),
(162, 1, 'VIEWER_CONNECTION_CONFIRMATION', 'Do you want to connect to this channel?', NULL),
(163, 3, 'VIEWER_CONNECTION_CONFIRMATION', 'Czy chcesz dołączyć na ten kanał?', NULL),
(164, 1, 'VIEWER_CLIENT_LASTACTIVE', 'Last active:', NULL),
(165, 3, 'VIEWER_CLIENT_LASTACTIVE', 'Aktywny:', NULL),
(166, 1, 'VIEWER_CLIENT_ONLINE', 'Online time:', NULL),
(167, 3, 'VIEWER_CLIENT_ONLINE', 'Online przez:', NULL),
(168, 1, 'VIEWER_CLIENT_JOINED', 'First joined:', NULL),
(169, 3, 'VIEWER_CLIENT_JOINED', 'Dołączył:', NULL),
(170, 1, 'VIEWER_CLIENT_TITLE', 'Client info', NULL),
(171, 3, 'VIEWER_CLIENT_TITLE', 'Informacje o kliencie', NULL),
(172, 1, 'VIEWER_SERVER_ICON', 'Server icon', NULL),
(173, 3, 'VIEWER_SERVER_ICON', 'Ikona serwera', NULL),
(174, 1, 'VIEWER_DEFAULT_CHANNEL', 'Default channel', NULL),
(175, 3, 'VIEWER_DEFAULT_CHANNEL', 'Kanał domyślny', NULL),
(176, 1, 'VIEWER_CHANNEL_UNSUB1', ', unsubscribed', 'Please note that this string starts with \", \"'),
(177, 3, 'VIEWER_CHANNEL_UNSUB1', ', odsubskrybowany', NULL),
(178, 1, 'VIEWER_CHANNEL_OCCUPIED', 'Fully occupied', NULL),
(179, 3, 'VIEWER_CHANNEL_OCCUPIED', 'Zajęty', NULL),
(180, 1, 'VIEWER_CHANNEL_PASSWORD', 'Password-protected', NULL),
(181, 3, 'VIEWER_CHANNEL_PASSWORD', 'Zabezpieczony hasłem', NULL),
(182, 1, 'VIEWER_CHANNEL_UNSUB2', 'Unsubscribed', NULL),
(183, 3, 'VIEWER_CHANNEL_UNSUB2', 'Odsubskrybowany', NULL),
(184, 1, 'VIEWER_CHANNEL_ICON', 'Channel icon', NULL),
(185, 3, 'VIEWER_CHANNEL_ICON', 'Ikona kanału', NULL),
(186, 1, 'VIEWER_CHANNEL_MODERATED', 'Moderated', NULL),
(187, 3, 'VIEWER_CHANNEL_MODERATED', 'Moderowany', NULL),
(188, 1, 'VIEWER_CHANNEL_MUSIC_CODED', 'Music codec', NULL),
(189, 3, 'VIEWER_CHANNEL_MUSIC_CODED', 'Kodek muzyczny', NULL),
(190, 1, 'VIEWER_CLIENT_AWAY', 'Away', NULL),
(191, 3, 'VIEWER_CLIENT_AWAY', 'Zaraz wracam', NULL),
(194, 1, 'VIEWER_CLIENT_OUTPUT_DISABLED', 'Sound disabled', NULL),
(195, 3, 'VIEWER_CLIENT_OUTPUT_DISABLED', 'Głos wyłączony', NULL),
(196, 1, 'VIEWER_CLIENT_OUTPUT_MUTED', 'Deafened', NULL),
(197, 3, 'VIEWER_CLIENT_OUTPUT_MUTED', 'Głos wyciszony', NULL),
(198, 1, 'VIEWER_CLIENT_MIC_DISABLED', 'Microphone disabled', NULL),
(199, 3, 'VIEWER_CLIENT_MIC_DISABLED', 'Mikrofon wyłączony', NULL),
(200, 1, 'VIEWER_CLIENT_MIC_MUTED', 'Muted', NULL),
(201, 3, 'VIEWER_CLIENT_MIC_MUTED', 'Mikrofon wyciszony', NULL),
(202, 1, 'VIEWER_CLIENT_COMMANDER', 'Channel commander', NULL),
(203, 3, 'VIEWER_CLIENT_COMMANDER', 'Dowódca kanału', NULL),
(204, 1, 'VIEWER_CLIENT_ICON', 'Client icon', NULL),
(205, 3, 'VIEWER_CLIENT_ICON', 'Ikona klienta', NULL),
(206, 1, 'VIEWER_CLIENT_PRIORITY_SPEAKER', 'Priority speaker', NULL),
(207, 3, 'VIEWER_CLIENT_PRIORITY_SPEAKER', 'Mówca priorytetowy', NULL),
(208, 1, 'VIEWER_CLIENT_TALK_POWER_GRANTED', 'Talk power granted', NULL),
(209, 3, 'VIEWER_CLIENT_TALK_POWER_GRANTED', 'Moc konwersacji przyznana', NULL),
(210, 1, 'VIEWER_CLIENT_TALK_POWER_INSUFFICIENT', 'Insufficient talk power', NULL),
(211, 3, 'VIEWER_CLIENT_TALK_POWER_INSUFFICIENT', 'Niewystarczająca moc konwersacji', NULL),
(212, 1, 'ASSIGNER_NOT_LOGGED_IN', 'Log in before using group assigner', NULL),
(213, 3, 'ASSIGNER_NOT_LOGGED_IN', 'Zaloguj się przed przydzielaniem grup', NULL),
(214, 1, 'ASSIGNER_LOGIN_BUTTON', 'Login', NULL),
(215, 3, 'ASSIGNER_LOGIN_BUTTON', 'Zaloguj się', NULL),
(216, 1, 'ASSIGNER_SAVE_BUTTON', 'Save', NULL),
(217, 3, 'ASSIGNER_SAVE_BUTTON', 'Zapisz', NULL),
(218, 1, 'ASSIGNER_INVALID_GROUPS', 'Invalid group settings', NULL),
(219, 3, 'ASSIGNER_INVALID_GROUPS', 'Nieprawidłowe ustawienia grup', NULL),
(220, 1, 'ASSIGNER_NOT_CONFIGURED', 'Group assigner is not configured by the website administrator', NULL),
(221, 3, 'ASSIGNER_NOT_CONFIGURED', 'Przydzielanie grup nie jest skonfigurowane przez administratora strony', NULL),
(222, 1, 'ASSIGNER_SAVE_SUCCESS', 'Your groups have been updated', NULL),
(223, 3, 'ASSIGNER_SAVE_SUCCESS', 'Twoje grupy zostały zaktualizowane', NULL),
(224, 1, 'ASSIGNER_SAVE_ERROR', 'Group change error', NULL),
(225, 3, 'ASSIGNER_SAVE_ERROR', 'Błąd zmiany grup', NULL),
(226, 1, 'ASSIGNER_SAVE_NO_CHANGE', 'No changes has been made', NULL),
(227, 3, 'ASSIGNER_SAVE_NO_CHANGE', 'Nie wprowadzono żadnych zmian', NULL);
(1, 'Welcome to ts-website!', 1, '2018-12-26 03:10:32', NULL, '<b>Hi there!</b> If you are reading this, it means that TS-website has been installed successfully.<br>\r\nYou can login to your <a href=\"admin\">ACP</a> to configure many parts of it.<br>\r\nNeed help? Join our <a href=\"https://t.me/tswebsite\" target=\"_blank\">Telegram group</a> for support.\r\nHave a good day!');
ALTER TABLE `DBPREFIXconfig`
@@ -316,25 +70,13 @@ ALTER TABLE `DBPREFIXconfig`
ALTER TABLE `DBPREFIXfaq`
ADD PRIMARY KEY (`faqid`);
ALTER TABLE `DBPREFIXlanguages`
ADD PRIMARY KEY (`langid`);
ALTER TABLE `DBPREFIXnews`
ADD PRIMARY KEY (`newsid`);
ALTER TABLE `DBPREFIXtranslations`
ADD PRIMARY KEY (`id`);
ALTER TABLE `DBPREFIXfaq`
MODIFY `faqid` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
ALTER TABLE `DBPREFIXlanguages`
MODIFY `langid` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
ALTER TABLE `DBPREFIXnews`
MODIFY `newsid` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
ALTER TABLE `DBPREFIXtranslations`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=228;
COMMIT;
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -22,6 +22,10 @@ error_reporting(E_ALL);
set_time_limit(0);
$stepNumber = empty($_GET["step"]) || !file_exists(__DIR__ . "/pages/" . (int)$_GET["step"] . ".php") ? 1 : (int) $_GET["step"];
ob_start();
require __DIR__ . "/pages/$stepNumber.php";
$pageContent = ob_get_clean();
?>
<!DOCTYPE html>
<html>
@@ -80,7 +84,7 @@ $stepNumber = empty($_GET["step"]) || !file_exists(__DIR__ . "/pages/" . (int)$_
</ul>
</div>
<?php require_once __DIR__ . "/pages/$stepNumber.php" ?>
<?= $pageContent ?>
</div>
<script>
+6 -1
View File
@@ -117,7 +117,12 @@
<div class="card">
<div class="card-body">
<h4 class="card-title text-center">Welcome to TS-website <?= __TSWEBSITE_VERSION ?> Installer!</h4>
<h4 class="card-title text-center mb-0">Welcome to TS-website Installer!</h4>
<p class="card-text text-center text-muted font-italic mb-5">
Version <?= __TSWEBSITE_VERSION ?> (<?= __TSWEBSITE_COMMIT ?>)
</p>
<p class="card-text">This wizard will guide you through the installation process of TS-website.</p>
<p class="card-text text-danger" id="hidejs">Please enable Javascript before continuing!</p>
<p class="card-text">
+21 -4
View File
@@ -11,6 +11,11 @@ if(!empty($_POST["allow-metrics-checkbox"])) {
<div class="card-body">
<h4 class="card-title text-center">Requirements check</h4>
<div class="alert alert-dark text-center mb-3" id="filePermError" style="display: none">
Looks like you have failed file permission checks. Try running:<br>
<code>sudo chown -R www-data:www-data "<?= realpath(__BASE_DIR) ?>"</code>
</div>
<div class="text-center mb-2">
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#requirementsTableCollapse">
Show details
@@ -38,6 +43,11 @@ if(!empty($_POST["allow-metrics-checkbox"])) {
<script>
// Show requirements table on error
$("#requirementsTableCollapse").collapse("show")
<?php if(defined("FILE_PERM_ERROR")) { ?>
// Show file permission fix tip
$("#filePermError").show()
<?php } ?>
</script>
<?php } else { ?>
<div class="text-center">
@@ -131,13 +141,13 @@ function checkRequirements() {
// file / directory writable checks
{
// path => true if file, false if directory
$paths = [
$paths = array(
__CONFIG_FILE => true,
__INSTALLER_LOCK_FILE => true,
__CACHE_DIR => false,
__CACHE_DIR . "/templates" => false,
__CACHE_DIR . "/servericons" => false,
];
);
foreach ($paths as $path => $isFile) {
$exists = file_exists($path);
@@ -161,7 +171,13 @@ function checkRequirements() {
if(!$exists)
$msg = ($isFile ? "File" : "Directory") . " <code>$realpath</code> does not exists, please create it";
showCheckResult("Is <code>$basename</code> writable?", $exists && $writable ? 0 : 2, $msg);
$success = $exists && $writable;
if (!$success && !defined("FILE_PERM_ERROR")) {
define("FILE_PERM_ERROR", true);
}
showCheckResult("Is <code>$basename</code> writable?", $success ? 0 : 2, $msg);
}
}
@@ -232,8 +248,9 @@ function showCheckResult($name, $state, $resulttext) {
} else {
$attr = "fa-times-circle color-danger";
if(!defined("CANNOT_INSTALL"))
if(!defined("CANNOT_INSTALL")) {
define("CANNOT_INSTALL", true);
}
}
?>
+36 -21
View File
@@ -44,24 +44,39 @@ if (!empty($_POST)) {
if (isset($dbconfig)) {
try {
$db = new Medoo($dbconfig);
$sqlfile = $usingMysql ? "dbinstall_mysql" : "dbinstall_sqlite";
$sqlquery = file_get_contents(__DIR__ . "/../$sqlfile.sql");
if($sqlquery === false) {
$errormessage = "Cannot read $sqlfile.sql file!";
$sqlfiles = [];
if ($usingMysql) {
$sqlfiles = [
"dbinstall_mysql",
"dbinstall_mysql_lang"
];
} else {
// no other option yet
}
foreach ($sqlfiles as $file) {
$sqlquery = file_get_contents(__DIR__ . "/../$file.sql");
if($sqlquery === false) {
throw new Exception("Cannot read SQL file: $file.sql");
}
$sqlquery = str_replace("DBPREFIX", $dbprefix, $sqlquery);
$sqlresult = $db->pdo->exec($sqlquery);
if($sqlresult === false) {
if ($sqlresult === false) {
throw new Exception("EXEC returned false");
}
}
$phpcode = <<<EOT
// if all queries succeeded, create a config file and save connection info there
$phpcode = <<<EOT
<?php
/*
* TS-website database config file
* Generated at %s with TS-website %s
* Generated at %s with TS-website %s (%s)
*/
return [
@@ -69,24 +84,24 @@ return [
];
EOT;
$confarray = "";
$confarray = "";
// Add all variables to the config
foreach ($dbconfig as $key => $value) {
$confarray .= sprintf(' "%s" => "%s",' . PHP_EOL, addcslashes($key, '"'), addcslashes($value, '"'));
}
// Add all variables to the config
foreach ($dbconfig as $key => $value) {
$confarray .= sprintf(' "%s" => "%s",' . PHP_EOL, addcslashes($key, '"'), addcslashes($value, '"'));
}
// Remove semicolon and new line from the end
$confarray = rtrim($confarray, "," . PHP_EOL);
// Remove semicolon and new line from the end
$confarray = rtrim($confarray, "," . PHP_EOL);
// Replace all variables with sprintf
$phpcode = sprintf($phpcode, date("d-m-Y H:i:s"), __TSWEBSITE_VERSION, $confarray);
// Replace all variables with sprintf
$phpcode = sprintf($phpcode, date("d-m-Y H:i:s"), __TSWEBSITE_VERSION, __TSWEBSITE_COMMIT, $confarray);
if(file_put_contents(__CONFIG_FILE, $phpcode) === false) {
$errormessage = "Cannot write to <code>" . __CONFIG_FILE . "</code>! Please check the file/directory permissions";
} else {
header("Location: ?step=" . ($stepNumber + 1));
}
if(file_put_contents(__CONFIG_FILE, $phpcode) === false) {
$errormessage = "Cannot write to <code>" . __CONFIG_FILE . "</code>! Please check the file/directory permissions";
} else {
// redirect to next step on success
header("Location: ?step=" . ($stepNumber + 1));
}
} catch (Exception $e) {
$errormessage = htmlspecialchars("Error " . $e->getCode() . ": " . $e->getMessage());
+1
View File
@@ -13,6 +13,7 @@ if(!empty($_COOKIE["tsw_allow_metrics"])) {
$data = [
"tswVersion" => __TSWEBSITE_VERSION,
"tswCommit" => __TSWEBSITE_COMMIT,
"phpVersion" => PHP_VERSION,
"os" => sprintf("%s %s %s %s", php_uname("s"), php_uname("r"), php_uname("v"), php_uname("m")), // no hostname
"webServer" => $_SERVER["SERVER_SOFTWARE"],
+1
View File
@@ -0,0 +1 @@
deny from all
View File
@@ -2,7 +2,6 @@
namespace Wruczek\TSWebsite\Utils\Language;
use function htmlspecialchars;
use Wruczek\PhpFileCache\PhpFileCache;
use Wruczek\TSWebsite\Utils\DatabaseUtils;
use Wruczek\TSWebsite\Utils\SingletonTait;
+3 -3
View File
@@ -165,13 +165,13 @@ class TemplateUtils {
}
} else if (is_string($parameter)) {
// NEEDS to start with a space!
$attributes = ' integrity="' . htmlspecialchars($parameter) . '" crossorigin="anonymous"';
$attributes = ' integrity="' . Utils::escape($parameter) . '" crossorigin="anonymous"';
}
if ($resourceType === "stylesheet") {
echo '<link rel="stylesheet" href="' . htmlspecialchars($url) . '"' . $attributes . '>';
echo '<link rel="stylesheet" href="' . Utils::escape($url) . '"' . $attributes . '>';
} else if ($resourceType === "script") {
echo '<script src="' . htmlspecialchars($url) . '"' . $attributes . '></script>';
echo '<script src="' . Utils::escape($url) . '"' . $attributes . '></script>';
} else {
throw new \InvalidArgumentException("$resourceType is not a valid resource type");
}
+12 -3
View File
@@ -9,12 +9,21 @@ use Wruczek\TSWebsite\News\INewsStore;
/**
* Class Utils
* @package Wruczek\TSWebsite\Utils
* @author Wruczek 2017
* @author Wruczek 2017 - 2019
*/
class Utils {
private function __construct() {}
/**
* Escapes HTML characters with htmlspecialchars
* @param $string string String to be escaped
* @return string escaped string
*/
public static function escape($string) {
return htmlspecialchars((string) $string, ENT_QUOTES, "UTF-8");
}
/**
* Strips the first line from string
* https://stackoverflow.com/a/7740485
@@ -100,7 +109,7 @@ class Utils {
*/
public static function getClientIp($useCfip = null) {
if ($useCfip === null) {
$useCfip = (bool) Config::get("usingcloudflare");
$useCfip = Config::get("usingcloudflare");
}
// If IPv6 localhost, return IPv4 localhost
@@ -108,7 +117,7 @@ class Utils {
return "127.0.0.1";
}
if (!empty($_SERVER["HTTP_CF_CONNECTING_IP"]) && $useCfip) {
if ($useCfip && !empty($_SERVER["HTTP_CF_CONNECTING_IP"])) {
return $_SERVER["HTTP_CF_CONNECTING_IP"];
}
+8 -7
View File
@@ -4,6 +4,7 @@ namespace Wruczek\TSWebsite;
use function __get;
use TeamSpeak3;
use Wruczek\TSWebsite\Utils\Utils;
class ViewerRenderer {
@@ -77,7 +78,7 @@ EOD;
$this->add(
$html,
$this->getIcon("server_green.svg"),
htmlspecialchars($this->serverInfo["virtualserver_name"]),
Utils::escape($this->serverInfo["virtualserver_name"]),
$suffixIcons
);
@@ -99,8 +100,8 @@ EOD;
$path = "api/geticon.php?iconid=" . (int) $name;
}
$ttip = $tooltip ? ' data-toggle="tooltip" title="' . htmlspecialchars($tooltip) . '"' : "";
return '<img class="icon" src="' . $path . '" alt="' . htmlspecialchars($alt) . '"' . $ttip . '>';
$ttip = $tooltip ? ' data-toggle="tooltip" title="' . Utils::escape($tooltip) . '"' : "";
return '<img class="icon" src="' . $path . '" alt="' . Utils::escape($alt) . '"' . $ttip . '>';
}
/**
@@ -162,7 +163,7 @@ EOD;
$channel->getId(),
$channel->isSpacer() ? "" : ' tabindex="0"',
$channelIcon,
htmlspecialchars($channelDisplayName),
Utils::escape($channelDisplayName),
$suffixIcons
);
@@ -222,7 +223,7 @@ EOD;
$clientName = implode(" ", $beforeName); // prefix groups
$clientName .= " {$client["client_nickname"]} "; // nickname
$clientName .= implode(" ", $afterName); // suffix groups
$clientName = htmlspecialchars(trim($clientName)); // trim and sanitize
$clientName = Utils::escape(trim($clientName)); // trim and sanitize
$this->add(
$html,
@@ -286,7 +287,7 @@ EOD;
}
if($client["client_away"]) {
return $this->getIcon("away.svg", htmlspecialchars($client["client_away_message"]) ?: __get("VIEWER_CLIENT_AWAY"));
return $this->getIcon("away.svg", Utils::escape($client["client_away_message"]) ?: __get("VIEWER_CLIENT_AWAY"));
}
if(!$client["client_output_hardware"]) {
@@ -340,7 +341,7 @@ EOD;
// to show the group with a "broken-image" icons.
}
$html .= $this->getIcon($icon, htmlspecialchars($group["name"]));
$html .= $this->getIcon($icon, Utils::escape($group["name"]));
}
if($client["client_icon_id"]) {
+2 -1
View File
@@ -1,5 +1,6 @@
<?php
define("__TSWEBSITE_VERSION", "dev-2.0.0");
define("__TSWEBSITE_VERSION", "dev-2.0.1");
define("__TSWEBSITE_COMMIT", "no-commit");
define("__BASE_DIR", __DIR__ . "/../..");
define("__PRIVATE_DIR", __BASE_DIR . "/private");
define("__CACHE_DIR", __PRIVATE_DIR . "/cache");
+2 -1
View File
@@ -4,6 +4,7 @@ use Wruczek\TSWebsite\Config;
use Wruczek\TSWebsite\ServerIconCache;
use Wruczek\TSWebsite\Utils\CsrfUtils;
use Wruczek\TSWebsite\Utils\Language\LanguageUtils;
use Wruczek\TSWebsite\Utils\Utils;
session_name("tswebsite_sessionid");
@@ -71,7 +72,7 @@ if(!isset($_SESSION["userlanguageid"])) {
try {
return LanguageUtils::i()->translate($identifier, $args);
} catch (\Exception $e) {
return "(unknown translation for " . htmlspecialchars($identifier) . ")";
return "(unknown translation for " . Utils::escape($identifier) . ")";
}
}
}
+10 -4
View File
@@ -35,10 +35,10 @@
</div>
{/if}
<table id="banlist" class="table table-responsive">
<table id="banlist" class="table display dt-responsive no-wrap" width="100%">
<thead>
<tr>
<th data-priority="1">{_"BANS_HEADER_NAME"}</th>
<th data-priority="1">{_"BANS_HEADER_TARGET"}</th>
<th data-priority="3">{_"BANS_HEADER_REASON"}</th>
<th>{_"BANS_HEADER_INVOKER"}</th>
<th>{_"BANS_HEADER_BANDATE"}</th>
@@ -49,8 +49,14 @@
{foreach $banlist as $ban}
{var $expiretime = $ban["created"] + $ban["duration"]}
<tr>
<td>{$ban["name"]}</td>
<td>{$ban["reason"]}</td>
<td data-filter="{$ban["filter"]}">{$ban["target"]}</td>
<td>
{if $ban["reason"]}
{$ban["reason"]}
{else}
{_"NO_REASON_SET"|noescape}
{/if}
</td>
<td>{$ban["invoker"]}</td>
<td data-order="{$ban["created"]}">{$ban["created"]|fullDate}</td>
<td data-order="{$ban["duration"]}">{$ban["duration"] ? ($expiretime|fuzzyDateAbbr) : ("BANS_NEVEREXPIRES"|translate)}</td>
+4 -3
View File
@@ -12,6 +12,7 @@ $navActiveIndex = isset($navActiveIndex) ? (int) $navActiveIndex : 0;
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="generator" content="TS-website {\__TSWEBSITE_VERSION} by Wruczek / https://github.com/Wruczek/ts-website">
<meta name="csrf-token" content="{$csrfToken}">
<link rel="shortcut icon" href="img/icons/defaulticon-16.png">
<!-- TODO make it use the language variable "WEBSITE_TITLE" after the ACP update -->
<title>{$title} | {$config["website_title"]}</title>
@@ -146,9 +147,9 @@ $navActiveIndex = isset($navActiveIndex) ? (int) $navActiveIndex : 0;
<footer class="footer d-md-flex">
<div>
&copy; WebsiteTitle.tech {date("Y")}
&copy; {$config["website_title"]} {date("Y")}
{if $config["imprint_enabled"]}3
{if $config["imprint_enabled"]}
&mdash; <a href="{$config["imprint_url"]}">imprint</a>
{/if}
</div>
@@ -210,7 +211,7 @@ $navActiveIndex = isset($navActiveIndex) ? (int) $navActiveIndex : 0;
{block footerbottom}{/block}
<!--
TS-website {\__TSWEBSITE_VERSION} by Wruczek
TS-website {\__TSWEBSITE_VERSION} ({\__TSWEBSITE_COMMIT}) by Wruczek
Generated in {@$tplutils::getRenderTime()} s
MySQL queries: {$sqlCount}
-->