Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/back/Legacy/Log.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static function formatRows(array $rows, string $break = '<br />', bool $r
public static function get(string $break = '<br />'): string
{
if (count(self::$log)) {
return self::formatRows(rows: self::$log, break: $break);
return self::formatRows(rows: self::$log, break: $break, replace: true);
}

return '';
Expand Down
21 changes: 16 additions & 5 deletions src/back/WebTLO.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ public function getReleaseLink(): string
$pattern = /** @lang text */
'Web-TLO <a href="%s" target="_blank">%s</a>';

return sprintf($pattern, $this->versionUrl(), $this->version);
return sprintf(
$pattern,
htmlspecialchars($this->versionUrl(), ENT_QUOTES, 'UTF-8'),
htmlspecialchars($this->version, ENT_QUOTES, 'UTF-8')
);
}

public function getCommitLink(): string
Expand All @@ -124,15 +128,19 @@ public function getCommitLink(): string
$pattern = /** @lang text */
'<a class="version-sha" href="%s" target="_blank">#%s</a>';

return sprintf($pattern, $this->commitUrl(), $this->sha);
return sprintf(
$pattern,
htmlspecialchars($this->commitUrl(), ENT_QUOTES, 'UTF-8'),
htmlspecialchars($this->sha, ENT_QUOTES, 'UTF-8')
);
}

public function getWikiLink(): string
{
$pattern = /** @lang text */
'<a href="%s" target="_blank">Web-TLO wiki</a>';

return sprintf($pattern, $this->wiki);
return sprintf($pattern, htmlspecialchars($this->wiki, ENT_QUOTES, 'UTF-8'));
}

public function appVersionLine(): string
Expand Down Expand Up @@ -201,13 +209,16 @@ public function getInstallation(): string

$result = [];
foreach ($about as $key => $value) {
$safeKey = htmlspecialchars($key, ENT_QUOTES, 'UTF-8');
$safeValue = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');

$requirement = self::REQUIREMENTS[$key] ?? null;
if (!empty($requirement)) {
$isVersionValid = version_compare($value, $requirement, '>=');

$value = sprintf('<span class="%s">%s<span>', $isVersionValid ? 'text-success' : 'text-danger', $value);
$safeValue = sprintf('<span class="%s">%s</span>', $isVersionValid ? 'text-success' : 'text-danger', $safeValue);
}
$result[] = sprintf('<li>%s: %s</li>', $key, $value);
$result[] = sprintf('<li>%s: %s</li>', $safeKey, $safeValue);
}

return implode('', $result);
Expand Down
9 changes: 5 additions & 4 deletions src/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
App::create();
DB::create();
} catch (Exception $e) {
$initError = $e->getMessage();
$initError = 'Database initialization error. Check logs for details.';
error_log('WebTLO init error: ' . $e->getMessage());
}

// 2. Загружаем конфиг и рисуем селекторы.
Expand Down Expand Up @@ -243,7 +244,7 @@ function cfg_numeric_value($cfg): Closure

<head>
<meta charset="utf-8" />
<title>web-TLO-<?= $webtlo->version ?? 'unknown' ?></title>
<title>web-TLO-<?= htmlspecialchars($webtlo->version ?? 'unknown', ENT_QUOTES, 'UTF-8') ?></title>

<script src="scripts/jquery.lib/js.cookie.min.js"></script>
<script src="scripts/jquery.lib/jquery.1.12.4.min.js"></script>
Expand All @@ -270,7 +271,7 @@ function cfg_numeric_value($cfg): Closure
<li id="menu_manual" class="menu"><a href="#manual" class="menu">О программе</a></li>
</ul>
<div id="new_version_available">
<span id="current_version"><?= "v$webtlo->version" ?? '' ?></span>
<span id="current_version"><?= htmlspecialchars("v" . ($webtlo->version ?? ''), ENT_QUOTES, 'UTF-8') ?></span>
<span id="new_version_description"></span>
</div>
<div id="content">
Expand Down Expand Up @@ -1203,7 +1204,7 @@ class="torrent-client-props spinner-peers" type="text" size="10"
<ol class="footnote">
<li>Указанные настройки влияют исключительно на выполнение соответствующих фоновых задач. <br />
Запуск задач должен быть настроен самостоятельно (cron или планировщик windows). <br />
За подробностями обратитесь к <a target="_blank" href="<?= $webtlo->wiki . "/configuration/automation-scripts/" ?>">этой</a> странице.</li>
За подробностями обратитесь к <a target="_blank" href="<?= htmlspecialchars($webtlo->wiki . "/configuration/automation-scripts/", ENT_QUOTES, 'UTF-8') ?>">этой</a> странице.</li>
<li>Необходимо настроить автозапуск control.php</li>
</ol>
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/php/actions/add_topics_to_client.php
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,8 @@
$log->info($result);
$log->info('-- DONE --');
} catch (Exception $e) {
$result = $e->getMessage();
error_log('add_topics_to_client error: ' . $e->getMessage());
$result = 'An error occurred while adding topics';
Log::append($result);
}

Expand Down
6 changes: 6 additions & 0 deletions src/php/actions/clear_log_content.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
return;
}

// Sanitize: use basename to prevent path traversal and validate allowed characters
$log_file = basename($log_file);
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $log_file)) {
return;
}

$log_file = Helper::getLogDir() . DIRECTORY_SEPARATOR . $log_file . '.log';

if (file_exists($log_file)) {
Expand Down
2 changes: 1 addition & 1 deletion src/php/actions/exclude_topics.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@

echo 'Обновление "чёрного списка" раздач успешно завершено';
} catch (Exception $e) {
echo $e->getMessage();
echo $result ?? 'Error occurred';
}
5 changes: 3 additions & 2 deletions src/php/actions/exec_actions_topics.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@

$result = "Действие '$action->value' выполнено. За подробностями обратитесь к журналу";
} catch (Exception $e) {
$result = $e->getMessage();
error_log('exec_actions_topics error: ' . $e->getMessage());
$result = 'An error occurred while executing the action';
if (isset($log)) {
$log->error($result);
$log->error($e->getMessage());
} else {
Log::append($result);
}
Expand Down
3 changes: 2 additions & 1 deletion src/php/actions/get_filtered_list_topics.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@
$returnObject['log'] = $e->getMessage();
$returnObject['validate'] = $e->getClass();
} catch (Exception $e) {
$returnObject['log'] = $e->getMessage();
error_log('get_filtered_list_topics error: ' . $e->getMessage());
$returnObject['log'] = 'An error occurred while processing the request';
}
$returnObject['details'] = Log::get();

Expand Down
3 changes: 2 additions & 1 deletion src/php/actions/get_list_subsections.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@

echo json_encode($forums, JSON_UNESCAPED_UNICODE);
} catch (Exception $e) {
error_log('get_list_subsections error: ' . $e->getMessage());
echo json_encode([
[
'value' => -1,
'label' => $e->getMessage(),
'label' => 'An error occurred while loading subsections',
],
]);
}
6 changes: 6 additions & 0 deletions src/php/actions/get_log_content.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
return;
}

// Sanitize: use basename to prevent path traversal and validate allowed characters
$log_file = basename($log_file);
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $log_file)) {
return;
}

$log_file = Helper::getLogDir() . DIRECTORY_SEPARATOR . $log_file . '.log';

if (file_exists($log_file)) {
Expand Down
6 changes: 3 additions & 3 deletions src/php/actions/get_reports.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@
}
$log->info('-- DONE --');
} catch (Throwable $e) {
$message = $e->getMessage();
error_log('get_reports error: ' . $e->getMessage());
if (isset($log)) {
$log->error($message);
$log->error($e->getMessage());
$log->info('-- DONE --');
}

$output .= '<br />' . $message;
$output .= '<br />An error occurred while generating the report';
}

$reports_result['report'] = $output;
Expand Down
5 changes: 3 additions & 2 deletions src/php/actions/get_reports_hashes.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@
$output = array_map(fn($el) => $el[$hashIndex], $result['kept_releases']);
}
} catch (Throwable $e) {
$error = $e->getMessage();
error_log('get_reports_hashes error: ' . $e->getMessage());
$error = 'An error occurred while fetching report hashes';
if (isset($log)) {
$log->warning($error);
$log->warning($e->getMessage());
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/php/actions/get_statistics.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@
'tfoot' => $tfoot,
];
} catch (Exception $e) {
$statistics_result['tbody'] = '<tr><th colspan="12">' . $e->getMessage() . '</th></tr>';
error_log('get_statistics error: ' . $e->getMessage());
$statistics_result['tbody'] = '<tr><th colspan="12">An error occurred while loading statistics</th></tr>';
}

echo json_encode($statistics_result, JSON_UNESCAPED_UNICODE);
3 changes: 2 additions & 1 deletion src/php/actions/get_torrent_files.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@
$log->info($result);
$log->info('-- DONE --');
} catch (Exception $e) {
$result = $e->getMessage();
error_log('get_torrent_files error: ' . $e->getMessage());
$result = 'An error occurred while downloading torrent files';
Log::append($result);
}

Expand Down
5 changes: 4 additions & 1 deletion src/php/actions/tor_client_is_online.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
$isOnline ? 'text-success' : 'text-danger'
);
} catch (Exception $e) {
$status = sprintf('Не удалось проверить доступность торрент-клиента "%s"', $params['comment'] ?? 'unknown');
$status = sprintf(
'Не удалось проверить доступность торрент-клиента "%s"',
htmlspecialchars($params['comment'] ?? 'unknown', ENT_QUOTES, 'UTF-8')
);
}

echo json_encode([
Expand Down
13 changes: 11 additions & 2 deletions src/scripts/jquery.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,19 @@ function setUITheme(){
jqueryUIStyle.appendTo("head");
}

function escapeHtml(text) {
var div = document.createElement('div');
div.appendChild(document.createTextNode(text));
return div.innerHTML;
}

function showNewVersion(newVersionNumber, newVersionLink, whatsNew) {
var safeVersion = escapeHtml(newVersionNumber);
var safeLink = encodeURI(newVersionLink);
var safeWhatsNew = escapeHtml(whatsNew);
$("#new_version_description")
.attr("title", whatsNew)
.append(`(Доступно обновление: <a id="new_version_link" target="_blank" href="${newVersionLink}">v${newVersionNumber}</a>)`);
.attr("title", safeWhatsNew)
.append('(Доступно обновление: <a id="new_version_link" target="_blank" href="' + safeLink + '">v' + safeVersion + '</a>)');
}

// http://stackoverflow.com/a/6832721/50079
Expand Down