diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88eacf309..d4fd0b722 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,32 +43,3 @@ jobs: with: name: TorrentPier-master path: ${{ steps.create-zip.outputs.ZIP_NAME }} - - deploy: - name: 🎉 Deploy - runs-on: ubuntu-22.04 - steps: - - name: 🚚 Get latest code - uses: actions/checkout@v4 - - - name: 🔩 Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.2' - - - name: 🖇 Install Composer dependencies - run: composer install --no-dev --no-progress --prefer-dist --optimize-autoloader - - - name: 📂 Sync files - uses: SamKirkland/FTP-Deploy-Action@v4.3.5 - with: - server: ${{ secrets.FTP_SERVER }} - username: ${{ secrets.FTP_USERNAME }} - password: ${{ secrets.FTP_PASSWORD }} - server-dir: ${{ secrets.FTP_DIR }} - protocol: ${{ secrets.FTP_PROTOCOL }} - port: ${{ secrets.FTP_PORT }} - exclude: | - **/.git* - **/.git*/** - .env diff --git a/CHANGELOG.md b/CHANGELOG.md index 6efa73e56..deebe3d07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,37 @@ # 📖 Change Log +## [v2.8.3](https://github.com/torrentpier/torrentpier/compare/v2.8.2..v2.8.3) (2025-07-03) + +### 🚀 Features + +- *(lang)* Added `RTL` languages support ([#2031](https://github.com/torrentpier/torrentpier/pull/2031)) - ([fd46d3d](https://github.com/torrentpier/torrentpier/commit/fd46d3d04ad3ab1453256b2ab620508e2ba33586)) +- *(updater)* Added exceptions logging ([#2026](https://github.com/torrentpier/torrentpier/pull/2026)) - ([51f2c70](https://github.com/torrentpier/torrentpier/commit/51f2c70d81b910012cdecd111b5b92c1dfd0d6f6)) + +### 🚜 Refactor + +- *(TorrentFileList)* Reduce duplication in root directory unset logic ([#2027](https://github.com/torrentpier/torrentpier/pull/2027)) - ([d4d8210](https://github.com/torrentpier/torrentpier/commit/d4d82101dd67c9f4cd86e0f6f909495696974354)) + + +## [v2.8.2](https://github.com/torrentpier/torrentpier/compare/v2.8.1..v2.8.2) (2025-06-30) + +### 🐛 Bug Fixes + +- *(TorrentFileList)* Avoid `array_merge` reindexing for numeric folder names ([#2014](https://github.com/torrentpier/torrentpier/pull/2014)) - ([915e1d8](https://github.com/torrentpier/torrentpier/commit/915e1d817c61d2a4f0691b24ec1bc6577a9cd44b)) + +### 🚜 Refactor + +- Use `DEFAULT_CHARSET` constant instead of hardcoded string ([#2011](https://github.com/torrentpier/torrentpier/pull/2011)) - ([7ac3359](https://github.com/torrentpier/torrentpier/commit/7ac335974baa44a8575bebb71ae2fbc0902d10e7)) + + +## [v2.8.1](https://github.com/torrentpier/torrentpier/compare/v2.8.0..v2.8.1) (2025-06-24) + +### 🐛 Bug Fixes + +- *(filelist)* `Undefined property: FileTree::$length` when v2 torrent only ([#2004](https://github.com/torrentpier/torrentpier/pull/2004)) - ([7f4cc9d](https://github.com/torrentpier/torrentpier/commit/7f4cc9d3b9a5b87100f710cc60f636d6e7d5a34e)) +- *(ip-api)* Add error handling and logging for freeipapi.com requests ([#2006](https://github.com/torrentpier/torrentpier/pull/2006)) - ([f1d6e74](https://github.com/torrentpier/torrentpier/commit/f1d6e74e5d4c74b6e12e9e742f60f62e71783d11)) + + ## [v2.8.0](https://github.com/torrentpier/torrentpier/compare/v2.7.0..v2.8.0) (2025-06-21) ### 🐛 Bug Fixes diff --git a/admin/index.php b/admin/index.php index 3d3ddba58..33cb3411d 100644 --- a/admin/index.php +++ b/admin/index.php @@ -90,7 +90,7 @@ if (isset($_GET['pane']) && $_GET['pane'] == 'left') { 'NEW_VERSION_SIZE' => $update_data['latest_version_size'], 'NEW_VERSION_DL_LINK' => $update_data['latest_version_dl_link'], 'NEW_VERSION_LINK' => $update_data['latest_version_link'], - 'NEW_VERSION_MD5' => $update_data['latest_version_checksum'] + 'NEW_VERSION_HASH' => $update_data['latest_version_checksum'] ]); } diff --git a/bt/announce.php b/bt/announce.php index ea1cca19a..3c74e554f 100644 --- a/bt/announce.php +++ b/bt/announce.php @@ -115,7 +115,7 @@ $stopped = ($event === 'stopped'); // Check info_hash length if (strlen($info_hash) !== 20) { - msg_die('Invalid info_hash: ' . (mb_check_encoding($info_hash, 'UTF8') ? $info_hash : $info_hash_hex)); + msg_die('Invalid info_hash: ' . (mb_check_encoding($info_hash, DEFAULT_CHARSET) ? $info_hash : $info_hash_hex)); } /** @@ -257,7 +257,7 @@ if ($lp_info) { // Verify if torrent registered on tracker and user authorized if (empty($row['topic_id'])) { - msg_die('Torrent not registered, info_hash = ' . (mb_check_encoding($info_hash, 'UTF8') ? $info_hash : $info_hash_hex)); + msg_die('Torrent not registered, info_hash = ' . (mb_check_encoding($info_hash, DEFAULT_CHARSET) ? $info_hash : $info_hash_hex)); } if (empty($row['user_id'])) { msg_die('Please LOG IN and RE-DOWNLOAD this torrent (user not found)'); diff --git a/bt/scrape.php b/bt/scrape.php index dd94ab8ff..d11ea0981 100644 --- a/bt/scrape.php +++ b/bt/scrape.php @@ -32,7 +32,7 @@ $info_hash_hex = bin2hex($info_hash); // Check info_hash length if (strlen($info_hash) !== 20) { - msg_die('Invalid info_hash: ' . (mb_check_encoding($info_hash, 'UTF8') ? $info_hash : $info_hash_hex)); + msg_die('Invalid info_hash: ' . (mb_check_encoding($info_hash, DEFAULT_CHARSET) ? $info_hash : $info_hash_hex)); } // Handle multiple hashes @@ -97,7 +97,7 @@ if (!empty($info_hash_count)) { // Verify if torrent registered on tracker if (empty($torrents)) { - msg_die('Torrent not registered, info_hash = ' . (mb_check_encoding($info_hash, 'UTF8') ? $info_hash : $info_hash_hex)); + msg_die('Torrent not registered, info_hash = ' . (mb_check_encoding($info_hash, DEFAULT_CHARSET) ? $info_hash : $info_hash_hex)); } die(\Arokettu\Bencode\Bencode::encode($torrents)); diff --git a/filelist.php b/filelist.php index 81a241d20..b07e319c6 100644 --- a/filelist.php +++ b/filelist.php @@ -82,7 +82,7 @@ if (IS_GUEST && $torrent->isPrivate()) { // Get torrent files $files = $torrent->$t_version_field()->$t_files_field(); -if ($meta_v1 && $meta_v2) { +if ($meta_v2) { $files = new \RecursiveIteratorIterator($files); // Flatten the list } @@ -102,19 +102,6 @@ foreach ($files as $file) { $torrent_name = !empty($t_name = $torrent->getName()) ? str_short(htmlCHR($t_name), 200) : $lang['UNKNOWN']; $torrent_size = humn_size($row['size'], 2); -// Get announcers list -$announcers_list = $torrent->getAnnounceList()->toArray(); -$announcers_count = 0; -foreach ($announcers_list as $announcer) { - $announcers_count++; - $row_class = ($announcers_count % 2) ? 'row1' : 'row2'; - $template->assign_block_vars('announcers', [ - 'ROW_NUMBER' => $announcers_count, - 'ROW_CLASS' => $row_class, - 'ANNOUNCER' => $announcer[0] - ]); -} - // Output page $template->assign_vars([ 'PAGE_TITLE' => "$torrent_name (" . $torrent_size . ")", diff --git a/library/attach_mod/displaying_torrent.php b/library/attach_mod/displaying_torrent.php index edded7f47..18c6a5bbf 100644 --- a/library/attach_mod/displaying_torrent.php +++ b/library/attach_mod/displaying_torrent.php @@ -475,6 +475,8 @@ if ($tor_reged && $tor_info) { if ($infoByIP = infoByIP((!empty($peer['ipv6']) ? $peer['ipv6'] : $peer['ip']), $peer['port'])) { if (!empty($infoByIP['countryCode'])) { $peerCountry = render_flag($infoByIP['countryCode'], false); + } else { + $peerCountry = $lang['NOT_AVAILABLE']; } } } diff --git a/library/config.php b/library/config.php index 581eb532a..75732614c 100644 --- a/library/config.php +++ b/library/config.php @@ -18,8 +18,8 @@ $reserved_port = env('TP_PORT', 80); $bb_cfg = []; // Version info -$bb_cfg['tp_version'] = 'v2.8.0'; -$bb_cfg['tp_release_date'] = '21-06-2025'; +$bb_cfg['tp_version'] = 'v2.8.3'; +$bb_cfg['tp_release_date'] = '03-07-2025'; $bb_cfg['tp_release_codename'] = 'Cattle'; // Increase version number after changing JS or CSS @@ -204,6 +204,7 @@ $bb_cfg['lang'] = [ 'ar' => [ 'name' => 'Arabic', 'locale' => 'ar_SA.UTF-8', + 'rtl' => true, ], 'hy' => [ 'name' => 'Armenian', @@ -280,6 +281,7 @@ $bb_cfg['lang'] = [ 'he' => [ 'name' => 'Hebrew', 'locale' => 'he_IL.UTF-8', + 'rtl' => true, ], 'hi' => [ 'name' => 'Hindi', diff --git a/library/includes/datastore/build_check_updates.php b/library/includes/datastore/build_check_updates.php index 416a9d4f7..bdad01400 100644 --- a/library/includes/datastore/build_check_updates.php +++ b/library/includes/datastore/build_check_updates.php @@ -16,9 +16,16 @@ if (!config()->get('tp_updater_settings.enabled')) { } $data = []; +$data[] = ['latest_check_timestamp' => TIMENOW]; -$updaterDownloader = new \TorrentPier\Updater(); -$updaterDownloader = $updaterDownloader->getLastVersion(config()->get('tp_updater_settings.allow_pre_releases')); +try { + $updaterDownloader = new \TorrentPier\Updater(); + $updaterDownloader = $updaterDownloader->getLastVersion(config()->get('tp_updater_settings.allow_pre_releases')); +} catch (Exception $exception) { + bb_log('[Updater] Exception: ' . $exception->getMessage() . LOG_LF); + $this->store('check_updates', $data); + return; +} $getVersion = \TorrentPier\Helpers\VersionHelper::removerPrefix($updaterDownloader['tag_name']); $currentVersion = \TorrentPier\Helpers\VersionHelper::removerPrefix(config()->get('tp_version')); @@ -26,6 +33,7 @@ $currentVersion = \TorrentPier\Helpers\VersionHelper::removerPrefix(config()->ge // Has update! if (\z4kn4fein\SemVer\Version::greaterThan($getVersion, $currentVersion)) { $latestBuildFileLink = $updaterDownloader['assets'][0]['browser_download_url']; + $SHAFileHash = $updaterDownloader['assets'][0]['digest'] ?? ''; // Check updater file $updaterFile = readUpdaterFile(); @@ -39,10 +47,12 @@ if (\z4kn4fein\SemVer\Version::greaterThan($getVersion, $currentVersion)) { ]), UPDATER_FILE, replace_content: true); } - // Get MD5 checksum + // Get MD5 / sha256 checksum $buildFileChecksum = ''; - if (isset($latestBuildFileLink)) { - $buildFileChecksum = strtoupper(md5_file($latestBuildFileLink)); + if (!empty($SHAFileHash)) { + $buildFileChecksum = $SHAFileHash; + } else { + $buildFileChecksum = 'MD5: ' . strtoupper(md5_file($latestBuildFileLink)); } // Build data array @@ -56,5 +66,4 @@ if (\z4kn4fein\SemVer\Version::greaterThan($getVersion, $currentVersion)) { ]; } -$data[] = ['latest_check_timestamp' => TIMENOW]; $this->store('check_updates', $data); diff --git a/library/includes/functions.php b/library/includes/functions.php index 6398907c9..c0302e66b 100644 --- a/library/includes/functions.php +++ b/library/includes/functions.php @@ -2196,19 +2196,26 @@ function infoByIP(string $ipAddress, int $port = 0): array } $context = stream_context_create($contextOptions); - $response = file_get_contents(config()->get('ip2country_settings.endpoint') . $ipAddress, context: $context); - if ($response !== false) { - $json = json_decode($response, true); + try { + $response = file_get_contents(config()->get('ip2country_settings.endpoint') . $ipAddress, context: $context); - if (is_array($json) && !empty($json)) { - $data = [ - 'ipVersion' => $json['ipVersion'], - 'countryCode' => $json['countryCode'], - 'continent' => $json['continent'], - 'continentCode' => $json['continentCode'] - ]; + if ($response !== false) { + $json = json_decode($response, true); + + if (is_array($json) && !empty($json)) { + $data = [ + 'ipVersion' => $json['ipVersion'], + 'countryCode' => $json['countryCode'], + 'continent' => $json['continent'], + 'continentCode' => $json['continentCode'] + ]; + } + } else { + bb_log("[FreeIPAPI] Failed to get IP info for: $ipAddress" . LOG_LF); } + } catch (Exception $e) { + bb_log("[FreeIPAPI] " . $e->getMessage() . LOG_LF); } if (empty($data)) { diff --git a/library/includes/page_header.php b/library/includes/page_header.php index e3bdc3e12..1ecfbafe6 100644 --- a/library/includes/page_header.php +++ b/library/includes/page_header.php @@ -117,6 +117,7 @@ $template->assign_vars([ 'USER_HIDE_CAT' => (BB_SCRIPT == 'index'), 'USER_LANG' => $userdata['user_lang'], + 'USER_LANG_DIRECTION' => (isset($bb_cfg['lang'][$userdata['user_lang']]['rtl']) && $bb_cfg['lang'][$userdata['user_lang']]['rtl'] === true) ? 'rtl' : 'ltr', 'INCLUDE_BBCODE_JS' => !empty($page_cfg['include_bbcode_js']), 'USER_OPTIONS_JS' => IS_GUEST ? '{}' : json_encode($user->opt_js, JSON_THROW_ON_ERROR), diff --git a/library/includes/ucp/register.php b/library/includes/ucp/register.php index 53d5bae2b..62f1f7ed0 100644 --- a/library/includes/ucp/register.php +++ b/library/includes/ucp/register.php @@ -142,6 +142,7 @@ switch ($mode) { if (!$pr_data = DB()->fetch_row($sql)) { bb_die($lang['PROFILE_NOT_FOUND']); } + $pr_data['user_birthday'] = $pr_data['user_birthday']->format('Y-m-d'); if (IN_DEMO_MODE && isset($_COOKIE['user_lang'])) { $pr_data['user_lang'] = $_COOKIE['user_lang']; } diff --git a/library/includes/ucp/viewprofile.php b/library/includes/ucp/viewprofile.php index 3d4605e68..e9f8903a7 100644 --- a/library/includes/ucp/viewprofile.php +++ b/library/includes/ucp/viewprofile.php @@ -30,6 +30,8 @@ if (!$profiledata = get_userdata($_GET[POST_USERS_URL], profile_view: true)) { bb_die($lang['NO_USER_ID_SPECIFIED']); } +$profiledata['user_birthday'] = $profiledata['user_birthday']->format('Y-m-d'); + if (!$ranks = $datastore->get('ranks')) { $datastore->update('ranks'); $ranks = $datastore->get('ranks'); diff --git a/src/Legacy/Common/User.php b/src/Legacy/Common/User.php index 52bfafc01..77e844004 100644 --- a/src/Legacy/Common/User.php +++ b/src/Legacy/Common/User.php @@ -232,6 +232,7 @@ class User } } + $this->data['user_birthday'] = $this->data['user_birthday']->format('Y-m-d'); return $this->data; } diff --git a/src/Legacy/TorrentFileList.php b/src/Legacy/TorrentFileList.php index b3fcaeccc..26617a595 100644 --- a/src/Legacy/TorrentFileList.php +++ b/src/Legacy/TorrentFileList.php @@ -53,8 +53,10 @@ class TorrentFileList $this->build_filelist_array(); if ($this->multiple) { - if (!empty($this->files_ary['/'])) { - $this->files_ary = array_merge($this->files_ary, $this->files_ary['/']); + if (isset($this->files_ary['/'])) { + if (!empty($this->files_ary['/'])) { + $this->files_ary = $this->files_ary + $this->files_ary['/']; + } unset($this->files_ary['/']); } $filelist = $html->array2html($this->files_ary); diff --git a/src/Updater.php b/src/Updater.php index 5ccba7843..3d64db47d 100644 --- a/src/Updater.php +++ b/src/Updater.php @@ -38,6 +38,13 @@ class Updater */ public string $savePath; + /** + * LTS version pattern (v2.8.*) + * + * @var string + */ + private const LTS_VERSION_PATTERN = '/^v2\.8\.\d+$/'; + /** * Stream context * @@ -130,23 +137,67 @@ class Updater } /** - * Returns information of latest TorrentPier version available + * Returns information of latest TorrentPier LTS version (v2.8.*) available + * + * @param bool $allowPreReleases + * @return array + * @throws Exception + */ + public function getLastVersion(bool $allowPreReleases = true): array + { + // Filter releases to get only LTS versions (v2.8.*) + $ltsVersions = array_filter($this->jsonResponse, function ($release) { + return preg_match(self::LTS_VERSION_PATTERN, $release['tag_name']); + }); + + if (empty($ltsVersions)) { + throw new Exception('No LTS versions (v2.8.*) found'); + } + + // Sort LTS versions by version number (descending) + usort($ltsVersions, function ($a, $b) { + return version_compare($b['tag_name'], $a['tag_name']); + }); + + if (!$allowPreReleases) { + foreach ($ltsVersions as $release) { + if (isset($release['prerelease']) && $release['prerelease']) { + continue; + } + return $release; + } + + // If no stable LTS versions found + throw new Exception('No stable LTS versions (v2.8.*) found'); + } + + return $ltsVersions[0]; + } + + /** + * Get all available LTS versions (v2.8.*) * * @param bool $allowPreReleases * @return array */ - public function getLastVersion(bool $allowPreReleases = true): array + public function getAllLTSVersions(bool $allowPreReleases = true): array { - if (!$allowPreReleases) { - foreach ($this->jsonResponse as $index) { - if (isset($index['prerelease']) && $index['prerelease']) { - continue; - } + // Filter releases to get only LTS versions (v2.8.*) + $ltsVersions = array_filter($this->jsonResponse, function ($release) use ($allowPreReleases) { + $isLTSVersion = preg_match(self::LTS_VERSION_PATTERN, $release['tag_name']); - return $index; + if (!$allowPreReleases && isset($release['prerelease']) && $release['prerelease']) { + return false; } - } - return $this->jsonResponse[0]; + return $isLTSVersion; + }); + + // Sort LTS versions by version number (descending) + usort($ltsVersions, function ($a, $b) { + return version_compare($b['tag_name'], $a['tag_name']); + }); + + return array_values($ltsVersions); } } diff --git a/styles/templates/admin/index.tpl b/styles/templates/admin/index.tpl index 3c8f30941..f29030591 100644 --- a/styles/templates/admin/index.tpl +++ b/styles/templates/admin/index.tpl @@ -1,7 +1,7 @@ - +
@@ -160,7 +160,7 @@# | -{L_BT_FLIST_ANNOUNCERS} | -
---|---|
{announcers.ROW_NUMBER} | -{announcers.ANNOUNCER} | -
{L_BT_FLIST_ANNOUNCERS_NOTICE} | -