Compare commits

..

No commits in common. "master" and "v2.4.2" have entirely different histories.

512 changed files with 12350 additions and 44029 deletions

View file

@ -1,7 +0,0 @@
9766c534bddad8e82e6d19f9bad5cf70b9887f9a
92ce77ec0ec703c08a659419087a373f76e711f7
2d53efc945c7747be1755d0b66557a86bdc12cbd
602137b65129b817811b80975a369ebde3270c6d
4eb26ae37e1f4c82a45961517ffeb54c20200408
e59adce848a9e10ee5775254045cbbd915236b8b
9e0a64108d62236ab07b3f8d10e8c78269b8e1d1

View file

@ -1,11 +1,10 @@
# Common params
TP_HOST=example.com
TP_PORT=80
APP_ENV=production
APP_ENV=local
APP_CRON_ENABLED=true
APP_DEMO_MODE=false
# Database credentials
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=torrentpier

35
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,35 @@
---
name: Bug report
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View file

@ -1,62 +0,0 @@
name: Bug Report
description: File a bug report
title: "[Bug]"
labels: [Bug]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
The more detailed this bug report is, the faster it can be reviewed and fixed.
- type: input
id: version-torrentpier
attributes:
label: TorrentPier Version
description: TorrentPier version your using?
placeholder: 2.4.0
validations:
required: true
- type: input
id: version-php-os
attributes:
label: PHP & Platform
description: Exact PHP and Platform (OS) versions your using.
placeholder: 8.2.2 - Ubuntu 22.04 x64
validations:
required: true
- type: checkboxes
id: requirements
attributes:
label: Have you done this?
options:
- label: I am willing to share my stack trace and logs
required: true
- label: I can suggest a fix as a Pull Request
required: false
- type: textarea
id: expectation
attributes:
label: Expectation
description: Write what you expect to (correctly) happen.
placeholder: When I do this, I expect to this to happen.
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: Write what (incorrectly) happens instead.
placeholder: Instead, when I do this, I receive that.
validations:
required: true
- type: textarea
id: logs
attributes:
label: Stack trace & logs
description: |
If you have a stack trace, you can copy it here. You may hide sensitive information.
Including a stack trace when reporting an error 500 is required.
placeholder: This is automatically formatted into code, no need for backticks.
render: shell
validations:
required: false

View file

@ -1,7 +0,0 @@
---
name: Feature / Enhancement request
about: Suggest an idea for TorrentPier
title: "[Feature]"
labels: [Feature, Enhancement]
assignees: ''
---

View file

@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View file

@ -1,80 +0,0 @@
name: Continuous Deployment
on:
push:
tags:
- "v*.*.*"
jobs:
generate-changelog:
name: Generate changelog
runs-on: ubuntu-22.04
outputs:
release_body: ${{ steps.git-cliff.outputs.content }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate a changelog
uses: orhun/git-cliff-action@v4
id: git-cliff
with:
config: cliff.toml
args: -vv --latest --no-exec --github-repo ${{ github.repository }}
- name: Print the changelog
run: cat "${{ steps.git-cliff.outputs.changelog }}"
release:
name: Create release
needs: [ generate-changelog ]
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Set the release version
shell: bash
run: echo "RELEASE_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV
- 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: Cleanup
run: php _cleanup.php && rm _cleanup.php
- name: Create archive
id: create-zip
run: |
ZIP_NAME="torrentpier-v${{ env.RELEASE_VERSION }}.zip"
zip -r "$ZIP_NAME" . -x ".git/*"
echo "ZIP_NAME=$ZIP_NAME" >> $GITHUB_OUTPUT
- name: Publish to GitHub
if: ${{ !contains(github.ref, '-') }}
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.create-zip.outputs.ZIP_NAME }}
overwrite: true
tag: ${{ github.ref }}
release_name: "v${{ env.RELEASE_VERSION }}"
body: "${{ needs.generate-changelog.outputs.release_body }}"
- name: Publish to GitHub (pre-release)
if: ${{ contains(github.ref, '-') }}
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.create-zip.outputs.ZIP_NAME }}
overwrite: true
tag: ${{ github.ref }}
release_name: "v${{ env.RELEASE_VERSION }}"
body: "${{ needs.generate-changelog.outputs.release_body }}"
prerelease: true

View file

@ -1,45 +0,0 @@
name: Continuous Integration
on:
push:
branches:
- master
jobs:
nightly:
name: Nightly builds 📦
runs-on: ubuntu-22.04
steps:
- name: Checkout 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: Get commit hash 🔗
id: get-commit-hash
run: |
COMMIT_HASH=$(git rev-parse --short HEAD)
echo "COMMIT_HASH=$COMMIT_HASH" >> $GITHUB_OUTPUT
- name: Cleanup
run: php _cleanup.php && rm _cleanup.php
- name: Create archive 🗞
id: create-zip
run: |
ZIP_NAME="torrentpier-${{ steps.get-commit-hash.outputs.COMMIT_HASH }}.zip"
zip -r "$ZIP_NAME" . -x ".git/*"
echo "ZIP_NAME=$ZIP_NAME" >> $GITHUB_OUTPUT
- name: Upload Archive 📤
uses: actions/upload-artifact@v4
with:
name: TorrentPier-master
path: ${{ steps.create-zip.outputs.ZIP_NAME }}

View file

@ -1,41 +0,0 @@
name: Changelog generation
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
changelog:
name: Changelog generation
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: master
token: ${{ secrets.REPO_TOKEN }}
- name: Generate a changelog
uses: orhun/git-cliff-action@v4
id: git-cliff
with:
config: cliff.toml
args: v2.4.6-alpha.4.. --verbose
env:
OUTPUT: CHANGELOG.md
GITHUB_REPO: ${{ github.repository }}
- name: Print the changelog
run: cat "${{ steps.git-cliff.outputs.changelog }}"
- name: Commit changelog
run: |
git checkout master
git config --local user.name 'belomaxorka'
git config --local user.email 'roman25052006.kelesh@gmail.com'
set +e
git add CHANGELOG.md
git commit -m "changelog: Update CHANGELOG.md 📖"
git push https://${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git master

9
.gitignore vendored
View file

@ -1,26 +1,23 @@
### IDE ###
.idea
.vscode
### TorrentPier ###
*.log
install.php_*
composer-setup.php
.env
.php_cs.cache
composer.phar
configs/local.php
data/avatars
data/uploads
internal_data/atom
internal_data/cache
internal_data/log
internal_data/updater.json
sitemap
internal_data/triggers
library/config.local.php
vendor
### Archives ###
*.phar
*.log
*.rar
*.tar
*.gz

File diff suppressed because it is too large Load diff

144
CLAUDE.md
View file

@ -1,144 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
TorrentPier is a BitTorrent tracker engine written in PHP, designed for hosting BitTorrent communities with forum functionality. The project is in active modernization, transitioning from legacy code to modern PHP practices while maintaining backward compatibility.
## Technology Stack & Architecture
- **PHP 8.2+** with modern features
- **MySQL/MariaDB/Percona** database
- **Nette Database** with backward-compatible wrapper
- **Composer** for dependency management
- **Custom BitTorrent tracker** implementation
## Key Directory Structure
- `/src/` - Modern PHP classes (PSR-4 autoloaded as `TorrentPier\`)
- `/library/` - Core application logic and legacy code
- `/admin/` - Administrative interface
- `/bt/` - BitTorrent tracker functionality (announce.php, scrape.php)
- `/styles/` - Templates, CSS, JS, images
- `/internal_data/` - Cache, logs, compiled templates
- `/install/` - Installation scripts and configuration examples
- `/migrations/` - Database migration files (Phinx)
## Entry Points & Key Files
- `index.php` - Main forum homepage
- `tracker.php` - Torrent search/browse interface
- `bt/announce.php` - BitTorrent announce endpoint
- `bt/scrape.php` - BitTorrent scrape endpoint
- `admin/index.php` - Administrative panel
- `cron.php` - Background task runner (CLI only)
- `install.php` - Installation script (CLI only)
## Development Commands
### Installation & Setup
```bash
# Automated installation (CLI)
php install.php
# Install dependencies
composer install
# Update dependencies
composer update
```
### Maintenance & Operations
```bash
# Run background maintenance tasks
php cron.php
```
### Code Quality
The project uses **StyleCI** with PSR-2 preset for code style enforcement. StyleCI configuration is in `.styleci.yml` targeting `src/` directory.
## Modern Architecture Components
### Database Layer (`/src/Database/`)
- **Nette Database** with full old SqlDb backward compatibility
- Singleton pattern accessible via `DB()` function
- Support for multiple database connections and debug functionality
- Migration path to ORM-style Explorer queries
### Cache System (`/src/Cache/`)
- **Unified caching** using Nette Caching internally
- 100% backward compatibility with existing `CACHE()` and $datastore calls
- Supports file, SQLite, memory, and Memcached storage
- Advanced features: memoization, cache dependencies
### Configuration Management
- Environment-based config with `.env` files
- Singleton `Config` class accessible via `config()` function
- Local overrides supported via `library/config.local.php`
## Configuration Files
- `.env` - Environment variables (copy from `.env.example`)
- `library/config.php` - Main application configuration
- `library/config.local.php` - Local configuration overrides
- `composer.json` - Dependencies and PSR-4 autoloading
## Development Workflow
### CI/CD Pipeline
- **GitHub Actions** for automated testing and deployment
- **StyleCI** for code style enforcement
- **Dependabot** for dependency updates
- **FTP deployment** to demo environment
### Installation Methods
1. **Automated**: `php install.php` (recommended)
2. **Composer**: `composer create-project torrentpier/torrentpier`
3. **Manual**: Git clone + `composer install` + database setup
## Database & Schema
- **Database migrations** managed via Phinx in `/migrations/` directory
- Initial schema: `20250619000001_initial_schema.php`
- Initial seed data: `20250619000002_seed_initial_data.php`
- UTF-8 (utf8mb4) character set required
- Multiple database alias support for different components
### Migration Commands
```bash
# Run all pending migrations
php vendor/bin/phinx migrate --configuration=phinx.php
# Check migration status
php vendor/bin/phinx status --configuration=phinx.php
# Mark migrations as applied (for existing installations)
php vendor/bin/phinx migrate --fake --configuration=phinx.php
```
## Legacy Compatibility Strategy
The codebase maintains 100% backward compatibility while introducing modern alternatives:
- **Database layer**: Existing old SqlDb calls work while new code can use Nette Database
- **Cache system**: All existing `CACHE()` and $datastore calls preserved while adding modern features
- **Configuration**: Legacy config access maintained alongside new singleton pattern
This approach allows gradual modernization without breaking existing functionality - critical for a mature application with existing deployments.
## Security & Performance
- **Environment-based secrets** management via `.env`
- **CDN/proxy support** (Cloudflare, Fastly)
- **Input sanitization** and CSRF protection
- **Advanced caching** with multiple storage backends
- **Rate limiting** and IP-based restrictions
## BitTorrent Tracker Features
- **BitTorrent v1 & v2** support
- **TorrServer integration** capability
- **Client ban system** for problematic torrent clients
- **Scrape support** for tracker statistics
When working with this codebase, prioritize understanding the legacy compatibility approach and modern architecture patterns. Always test both legacy and modern code paths when making changes to core systems.

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2005-2025 TorrentPier
Copyright (c) 2005-2024 TorrentPier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

171
README.md
View file

@ -2,156 +2,108 @@
<p align="center">
Bull-powered BitTorrent tracker engine
<br/>
<br>
</p>
<p align="center">
<a href="https://github.com/torrentpier/torrentpier/blob/master/LICENSE"><img src="https://img.shields.io/github/license/torrentpier/torrentpier" alt="License"></a>
<a href="https://packagist.org/packages/torrentpier/torrentpier"><img src="https://img.shields.io/packagist/stars/torrentpier/torrentpier" alt="Stars Packagist"></a>
<a href="https://github.com/torrentpier/torrentpier/actions"><img src="https://img.shields.io/github/actions/workflow/status/torrentpier/torrentpier/phpmd.yml" alt="Build status"></a>
<a href="https://crowdin.com/project/torrentpier"><img src="https://badges.crowdin.net/torrentpier/localized.svg" alt="Crowdin"></a>
<a href="https://nightly.link/torrentpier/torrentpier/workflows/ci/master/TorrentPier-master"><img src="https://img.shields.io/badge/Nightly%20release-gray?logo=hackthebox&logoColor=fff" alt="TorrentPier nightly"></a>
<a href="https://packagist.org/packages/torrentpier/torrentpier"><img src="https://img.shields.io/packagist/dt/torrentpier/torrentpier" alt="Downloads"></a>
<a href="https://packagist.org/packages/torrentpier/torrentpier"><img src="https://img.shields.io/packagist/v/torrentpier/torrentpier" alt="Version"></a>
<a href="https://github.com/torrentpier/torrentpier/releases"><img src="https://img.shields.io/github/release-date/torrentpier/torrentpier" alt="Last release"></a>
<img src="https://img.shields.io/github/repo-size/torrentpier/torrentpier" alt="Size">
<a href="https://github.com/SamKirkland/FTP-Deploy-Action"><img src="https://img.shields.io/badge/Deployed to TorrentPier Demo with-FTP DEPLOY ACTION-%3CCOLOR%3E?color=2b9348" alt="Deployed to TorrentPier Demo with FTP Deploy Action"></a>
</p>
## 🐂 About TorrentPier
TorrentPier — bull-powered BitTorrent Public/Private tracker engine, written in PHP. High speed, simple modifications, load-balanced
architecture. In addition, we have a very helpful
[official support forum](https://torrentpier.com), where it's possible to get support and download modifications for the engine.
TorrentPier — bull-powered BitTorrent Public/Private tracker engine, written in php. High speed, simple modification, high load
architecture. In addition, we have very helpful
[official support forum](https://torrentpier.com), where it's possible to get any support and download modifications for engine.
## 🌈 Current status
TorrentPier is currently in active development. The goal is to remove all legacy code and rewrite the existing code to
modern specifications. If you want to delve deep into the code, check our [issues](https://github.com/torrentpier/torrentpier/issues)
and go from there. The documentation will be translated to English in the near future, currently Russian is the main language.
TorrentPier is currently in active development. The goal is to remove all legacy code and rewrite existing to
modern standards. If you want to go deep on the code, check our [issues](https://github.com/torrentpier/torrentpier/issues)
and go from there. The documentation will be translated into english in the near future, currently russian is the main language of it.
## ✨ Features
* Rich forum with browsing/moderation tools
* Rich forum browsing/moderation tools
* High-load capable, heavily configurable announcer
* Scrape support
* FreeLeech
* [TorrServer integration](https://github.com/YouROK/TorrServer) support
* BitTorrent v2 support
* Event-based invite system
* Bonus points
* Polling system
* PM/DM system
* Multilingual support (Russian and English are currently fully supported, with others in the future)
* Atom/RSS feeds
* ... and so MUCH MORE!
* Polls system
* PM system
* Multilingual support
* Atom feeds
* and MUCH MORE!
## 🖥️ Demo
* URL: https://torrentpier.duckdns.org
* Username: `admin`
* Password: `admin`
* Username: admin
* Password: admin
> [!NOTE]
> Demo resets every 24 hours!
Demo is reset every 24 hours!
## 🔧 Requirements
* Apache / nginx ([example config](install/nginx.conf)) / caddy ([example config](install/Caddyfile))
* MySQL 5.5.3 or above (including MySQL 8.0+) / MariaDB 10.0 or above / Percona
* PHP: 8.2 / 8.3 / 8.4
* PHP Extensions: mbstring, gd, bcmath, intl, tidy (optional), xml, xmlwriter
* Apache / nginx
* MySQL 5.5.3 or above / MariaDB 10.0 or above / Percona
* PHP: 8.1 / 8.2
* PHP Extensions: mbstring, bcmath, intl, tidy (optional), xml, xmlwriter
* Crontab (Recommended)
## 💾 Installation
For the installation, select one of the installation variants below:
### Quick (Clean install) 🚀
Check out our [autoinstall](https://github.com/torrentpier/autoinstall) repository with detailed instructions.
> [!NOTE]
> Thanks to [Sergei Solovev](https://github.com/SeAnSolovev) for this installation script ❤️
### Quick (For web-panels) ☕️
1. Select the folder where you want TorrentPier installed
```shell
cd /path/to/public_html
```
2. Download the latest version of TorrentPier
```shell
sudo git clone https://github.com/torrentpier/torrentpier.git .
```
3. After completing, execute the command below and follow the instructions
```shell
php install.php
```
4. Voila! ✨
### Manual 🔩
For installation, you need to follow a few simple steps:
1. Install [Composer](https://getcomposer.org/)
2. Run the following command to create the TorrentPier project
```shell
composer create-project torrentpier/torrentpier
```
3. [Check our system requirements](#-requirements)
4. After, run this command in the project directory to install Composer dependencies
```shell
composer install
```
5. Edit database configuration settings in the environment (`.env.example`), after, rename to `.env`
6. Create a database and run migrations to set up the schema
```shell
php vendor/bin/phinx migrate --configuration=phinx.php
```
7. Provide write permissions to the specified folders:
* `data/avatars`, `data/uploads`, `data/uploads/thumbs`
* `internal_data/atom`, `internal_data/cache`, `internal_data/log`, `internal_data/triggers`
* `sitemap`
8. Voila! ✨
2. Run `composer create-project torrentpier/torrentpier`
3. After run `composer install` on the project directory
4. Create database and import dump located at **install/sql/mysql.sql**
5. Edit database configuration settings in the environment (`.env.example`, after rename to `.env`)
6. Edit domain name and domain port in the configuration file or a local copy (`$reserved_name` and `$reserved_port`)
7. Edit this files:
1. **favicon.png** (change on your own)
2. **robots.txt** (change the addresses in lines `Host` and `Sitemap` on your own)
3. **opensearch_desc.xml** (change the description and address on your own)
4. **opensearch_desc_bt.xml** (change the description and address on your own)
8. Log in to the forum with **admin/admin** login/password and finish setting up via admin panel
> [!TIP]
> You can automate steps 4-7 by running `php install.php` instead, which will guide you through the setup process interactively.
## 🔑 Access rights on folders and files
> [!IMPORTANT]
> The specific settings depend on the server you are using, but in general we recommend chmod **0755** for folders, and chmod **0644** for the files in them.
You must provide write permissions to the specified folders:
* `data/avatars`
* `data/uploads`
* `data/uploads/thumbs`
* `internal_data/atom`
* `internal_data/cache`
* `internal_data/log`
* `internal_data/triggers`
* `sitemap`
### Additional steps 👣
The specific settings depend on the server you are using, but in general case we recommend chmod **0755** for folders,
and chmod **0644** for files in them. If you are not sure, leave it as is.
1. Edit these files:
* `favicon.png` (change to your own)
* `robots.txt` (change the addresses in lines `Host` and `Sitemap` to your own)
2. Log in to the forum using the **admin/admin** login/password, and finish setting up via admin panel. Don't forget to change your password!
## 🔐 Security
## 🔐 Security vulnerabilities
If you discover a security vulnerability within TorrentPier, please follow our [security policy](https://github.com/torrentpier/torrentpier/security/policy), so we can address it promptly.
## 🧪 Testing
TorrentPier includes a comprehensive testing suite built with **Pest PHP**. Run tests to ensure code quality and system reliability:
```shell
# Run all tests
./vendor/bin/pest
# Run with coverage
./vendor/bin/pest --coverage
```
For detailed testing documentation, see [tests/README.md](tests/README.md).
If you discover any security related issues, please email [admin@torrentpier.com](mailto:admin@torrentpier.com) or [roman25052006.kelesh@gmail.com](mailto:roman25052006.kelesh@gmail.com) instead of using the issue tracker.
## 📌 Our recommendations
* *It's recommended to run `cron.php`.* - For significant tracker speed increase it may be required to replace the built-in cron.php with an operating system daemon.
* *Local configuration copy.* - You can override the settings using the local configuration file `library/config.local.php`.
* *The recommended way to run cron.php.* - For significant tracker speed increase may be required to replace built-in cron.php by operating system daemon.
* *Local configuration copy.* - You can override the settings using local configuration file **library/config.local.php**.
## 💚 Contributing / Contributors
Please read our [contributing policy](CONTRIBUTING.md) and [code of conduct](CODE_OF_CONDUCT.md) for details, and the process for
submitting pull requests to us. But we are always ready to review your pull-request for compliance with
these requirements. Just send it!
Please read [CONTRIBUTING.md](CONTRIBUTING.md) and [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md) for details, and the process for
submitting pull requests to us. But we are always ready to renew your pull-request for compliance with
these requirements. Just send it.
<a href="https://github.com/torrentpier/torrentpier/graphs/contributors">
<img src="https://contrib.rocks/image?repo=torrentpier/torrentpier" alt="Contributors"/>
@ -161,30 +113,29 @@ Made with [contrib.rocks](https://contrib.rocks).
## 💞 Sponsoring
Support this project by becoming a sponsor or a backer.
Support this project by becoming a sponsor or a backer.
[![OpenCollective sponsors](https://opencollective.com/torrentpier/sponsors/badge.svg)](https://opencollective.com/torrentpier)
[![OpenCollective backers](https://opencollective.com/torrentpier/backers/badge.svg)](https://opencollective.com/torrentpier)
<details>
<summary>Monero</summary>
```
42zJE3FDvN8foP9QYgDrBjgtd7h2FipGCGmAcmG5VFQuRkJBGMbCvoLSmivepmAMEgik2E8MPWUzKaoYsGCtmhvL7ZN73jh
```
42zJE3FDvN8foP9QYgDrBjgtd7h2FipGCGmAcmG5VFQuRkJBGMbCvoLSmivepmAMEgik2E8MPWUzKaoYsGCtmhvL7ZN73jh
</details>
<details>
<summary>YooMoney</summary>
<summary>Bitcoin</summary>
bc1qselchy0nnh7xl99glfffedqp7p9gpvatdr9dz9
</details>
```
4100118022415720
```
<details>
<summary>ЮMoney</summary>
4100118022415720
</details>
## 📦 Versioning
We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/torrentpier/torrentpier/tags).
We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/torrentpier/torrentpier/tags).
## 📖 License

View file

@ -1,13 +0,0 @@
# Security Policy
## Versions
Due to the nature of our project - being open source - we have decided to patch only the latest major release (currently v2.4.x) for security vulnerabilities.
## How to disclose
Please disclose security issues by mailing [admin@torrentpier.com](mailto:admin@torrentpier.com).
## What we do
Any submitted security issue will be checked thoroughly by our development team. A fix for the issue and a transparent information on GitHub about the issue existing will be released. You can view any previously identified issues on our [GitHub Security Page](https://github.com/torrentpier/torrentpier/security/advisories). New major versions of TorrentPier will also receive a security audit to verify our efforts on providing a secure application.

File diff suppressed because it is too large Load diff

View file

@ -1,57 +0,0 @@
<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
if (!defined('BB_ROOT')) {
define('BB_ROOT', __DIR__ . DIRECTORY_SEPARATOR);
define('BB_PATH', BB_ROOT);
}
// Check CLI mode
if (PHP_SAPI != 'cli') {
exit;
}
if (!function_exists('removeFile')) {
// Get all constants
require_once BB_ROOT . 'library/defines.php';
// Include CLI functions
require INC_DIR . '/functions_cli.php';
}
$items = [
'.github',
'.cliffignore',
'.editorconfig',
'.gitignore',
'.styleci.yml',
'_release.php',
'CHANGELOG.md',
'CLAUDE.md',
'cliff.toml',
'CODE_OF_CONDUCT.md',
'CONTRIBUTING.md',
'crowdin.yml',
'HISTORY.md',
'phpunit.xml',
'README.md',
'SECURITY.md',
'tests',
'UPGRADE_GUIDE.md'
];
foreach ($items as $item) {
$path = BB_ROOT . $item;
if (is_file($path)) {
removeFile($path);
} elseif (is_dir($path)) {
removeDir($path);
}
}

View file

@ -1,130 +0,0 @@
<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
define('BB_ROOT', __DIR__ . DIRECTORY_SEPARATOR);
define('BB_PATH', BB_ROOT);
// Check CLI mode
if (PHP_SAPI != 'cli') {
die('Please run <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">php ' . basename(__FILE__) . '</code> in CLI mode');
}
// Get all constants
require_once BB_ROOT . 'library/defines.php';
// Include CLI functions
require INC_DIR . '/functions_cli.php';
// Welcoming message
out("--- Release creation tool ---\n", 'info');
$configFile = BB_PATH . '/library/config.php';
if (!is_file($configFile)) {
out('- Config file ' . basename($configFile) . ' not found', 'error');
exit;
}
if (!is_readable($configFile)) {
out('- Config file ' . basename($configFile) . ' is not readable', 'error');
exit;
}
if (!is_writable($configFile)) {
out('- Config file ' . basename($configFile) . ' is not writable', 'error');
exit;
}
// Ask for version
fwrite(STDOUT, 'Enter version number (e.g, v2.4.0): ');
$version = trim(fgets(STDIN));
if (empty($version)) {
out("- Version cannot be empty. Please enter a valid version number", 'error');
exit;
} else {
// Add 'v' prefix if missing
if (!str_starts_with($version, 'v')) {
$version = 'v' . $version;
}
out("- Using version: $version", 'info');
}
// Ask for version emoji
fwrite(STDOUT, 'Enter version emoji: ');
$versionEmoji = trim(fgets(STDIN));
if (!empty($versionEmoji)) {
out("- Using version emoji: $versionEmoji", 'info');
}
// Ask for release date or use today's date
fwrite(STDOUT, "Enter release date (e.g. 25-05-2025), leave empty to use today's date: ");
$date = trim(fgets(STDIN));
if (empty($date)) {
$date = date('d-m-Y');
out("- Using current date: $date", 'info');
} else {
// Validate date format (dd-mm-yyyy)
$dateObj = DateTime::createFromFormat('d-m-Y', $date);
if (!$dateObj || $dateObj->format('d-m-Y') !== $date) {
out("- Invalid date format. Expected format: DD-MM-YYYY", 'error');
exit;
}
out("- Using date: $date", 'info');
}
// Read config file content
$content = file_get_contents($configFile);
// Update version
$content = preg_replace(
"/\\\$bb_cfg\['tp_version'\]\s*=\s*'[^']*';/",
"\$bb_cfg['tp_version'] = '$version';",
$content
);
// Update release date
$content = preg_replace(
"/\\\$bb_cfg\['tp_release_date'\]\s*=\s*'[^']*';/",
"\$bb_cfg['tp_release_date'] = '$date';",
$content
);
// Save updated config
$bytesWritten = file_put_contents($configFile, $content);
if ($bytesWritten === false) {
out("- Failed to write to config file", 'error');
exit;
}
if ($bytesWritten === 0) {
out("- Config file was not updated (0 bytes written)", 'error');
exit;
}
out("\n- Config file has been updated!", 'success');
// Update CHANGELOG.md
runProcess('npx git-cliff v2.4.6-alpha.4.. --config cliff.toml --tag "' . $version . '" > CHANGELOG.md');
// Git add & commit
runProcess('git add -A && git commit -m "release: ' . escapeshellarg($version) . (!empty($versionEmoji) ? (' ' . $versionEmoji) : '') . '"');
// Git tag
runProcess("git tag -a \"$version\" -m \"Release $version\"");
runProcess("git tag -v \"$version\"");
// Git push
runProcess("git push origin master");
runProcess("git push origin $version");
out("\n- Release $version has been successfully prepared, committed and pushed!", 'success');

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -69,44 +69,44 @@ $order_by = '';
if ($view === 'username') {
switch ($mode) {
case 'username':
$order_by = 'ORDER BY u.username ' . $sort_order . ' LIMIT ' . $start . ', ' . config()->get('topics_per_page');
$order_by = 'ORDER BY u.username ' . $sort_order . ' LIMIT ' . $start . ', ' . $bb_cfg['topics_per_page'];
break;
case 'attachments':
$order_by = 'ORDER BY total_attachments ' . $sort_order . ' LIMIT ' . $start . ', ' . config()->get('topics_per_page');
$order_by = 'ORDER BY total_attachments ' . $sort_order . ' LIMIT ' . $start . ', ' . $bb_cfg['topics_per_page'];
break;
case 'filesize':
$order_by = 'ORDER BY total_size ' . $sort_order . ' LIMIT ' . $start . ', ' . config()->get('topics_per_page');
$order_by = 'ORDER BY total_size ' . $sort_order . ' LIMIT ' . $start . ', ' . $bb_cfg['topics_per_page'];
break;
default:
$mode = 'attachments';
$sort_order = 'DESC';
$order_by = 'ORDER BY total_attachments ' . $sort_order . ' LIMIT ' . $start . ', ' . config()->get('topics_per_page');
$order_by = 'ORDER BY total_attachments ' . $sort_order . ' LIMIT ' . $start . ', ' . $bb_cfg['topics_per_page'];
break;
}
} elseif ($view === 'attachments') {
switch ($mode) {
case 'real_filename':
$order_by = 'ORDER BY a.real_filename ' . $sort_order . ' LIMIT ' . $start . ', ' . config()->get('topics_per_page');
$order_by = 'ORDER BY a.real_filename ' . $sort_order . ' LIMIT ' . $start . ', ' . $bb_cfg['topics_per_page'];
break;
case 'comment':
$order_by = 'ORDER BY a.comment ' . $sort_order . ' LIMIT ' . $start . ', ' . config()->get('topics_per_page');
$order_by = 'ORDER BY a.comment ' . $sort_order . ' LIMIT ' . $start . ', ' . $bb_cfg['topics_per_page'];
break;
case 'extension':
$order_by = 'ORDER BY a.extension ' . $sort_order . ' LIMIT ' . $start . ', ' . config()->get('topics_per_page');
$order_by = 'ORDER BY a.extension ' . $sort_order . ' LIMIT ' . $start . ', ' . $bb_cfg['topics_per_page'];
break;
case 'filesize':
$order_by = 'ORDER BY a.filesize ' . $sort_order . ' LIMIT ' . $start . ', ' . config()->get('topics_per_page');
$order_by = 'ORDER BY a.filesize ' . $sort_order . ' LIMIT ' . $start . ', ' . $bb_cfg['topics_per_page'];
break;
case 'downloads':
$order_by = 'ORDER BY a.download_count ' . $sort_order . ' LIMIT ' . $start . ', ' . config()->get('topics_per_page');
$order_by = 'ORDER BY a.download_count ' . $sort_order . ' LIMIT ' . $start . ', ' . $bb_cfg['topics_per_page'];
break;
case 'post_time':
$order_by = 'ORDER BY a.filetime ' . $sort_order . ' LIMIT ' . $start . ', ' . config()->get('topics_per_page');
$order_by = 'ORDER BY a.filetime ' . $sort_order . ' LIMIT ' . $start . ', ' . $bb_cfg['topics_per_page'];
break;
default:
$mode = 'a.real_filename';
$sort_order = 'ASC';
$order_by = 'ORDER BY a.real_filename ' . $sort_order . ' LIMIT ' . $start . ', ' . config()->get('topics_per_page');
$order_by = 'ORDER BY a.real_filename ' . $sort_order . ' LIMIT ' . $start . ', ' . $bb_cfg['topics_per_page'];
break;
}
}
@ -422,7 +422,11 @@ if ($view === 'attachments') {
$row = DB()->sql_fetchrow($result);
DB()->sql_freeresult($result);
$post_title = str_short($row['topic_title'], 30);
$post_title = $row['topic_title'];
if (strlen($post_title) > 32) {
$post_title = str_short($post_title, 30);
}
$view_topic = BB_ROOT . POST_URL . $ids[$j]['post_id'] . '#' . $ids[$j]['post_id'];
@ -470,8 +474,8 @@ if ($view === 'attachments') {
}
// Generate Pagination
if ($do_pagination && $total_rows > config()->get('topics_per_page')) {
generate_pagination('admin_attach_cp.php?view=' . $view . '&amp;mode=' . $mode . '&amp;order=' . $sort_order . '&amp;uid=' . $uid, $total_rows, config()->get('topics_per_page'), $start);
if ($do_pagination && $total_rows > $bb_cfg['topics_per_page']) {
generate_pagination('admin_attach_cp.php?view=' . $view . '&amp;mode=' . $mode . '&amp;order=' . $sort_order . '&amp;uid=' . $uid, $total_rows, $bb_cfg['topics_per_page'], $start);
}
print_page('admin_attach_cp.tpl', 'admin');

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -61,7 +61,6 @@ switch ($mode) {
'CONFIG_MODS' => true,
'MAGNET_LINKS_ENABLED' => $new['magnet_links_enabled'],
'MAGNET_LINKS_FOR_GUESTS' => $new['magnet_links_for_guests'],
'GENDER' => $new['gender'],
'CALLSEED' => $new['callseed'],
'TOR_STATS' => $new['tor_stats'],
@ -136,8 +135,8 @@ switch ($mode) {
'POSTS_PER_PAGE' => $new['posts_per_page'],
'HOT_TOPIC' => $new['hot_threshold'],
'DEFAULT_DATEFORMAT' => $new['default_dateformat'],
'LANG_SELECT' => \TorrentPier\Legacy\Common\Select::language($new['default_lang'], 'default_lang'),
'TIMEZONE_SELECT' => \TorrentPier\Legacy\Common\Select::timezone($new['board_timezone'], 'board_timezone'),
'LANG_SELECT' => \TorrentPier\Legacy\Select::language($new['default_lang'], 'default_lang'),
'TIMEZONE_SELECT' => \TorrentPier\Legacy\Select::timezone($new['board_timezone'], 'board_timezone'),
'MAX_LOGIN_ATTEMPTS' => $new['max_login_attempts'],
'LOGIN_RESET_TIME' => $new['login_reset_time'],
'PRUNE_ENABLE' => (bool)$new['prune_enable'],

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -26,7 +26,7 @@ $cfg = [];
* All config names with default values
*/
$default_cfg_str = array(
'bt_announce_url' => 'https://torrentpier.duckdns.org/bt/',
'bt_announce_url' => 'http://demo.torrentpier.com/bt/',
);
$default_cfg_bool = array(

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -188,8 +188,7 @@ switch ($mode) {
}
if ($submit) {
$mode2 = $_POST['mode'] ?? '';
if ($mode2 == 'list') {
if ($_POST['mode'] == 'list') {
if ($cron_action == 'run' && $jobs) {
\TorrentPier\Legacy\Admin\Cron::run_jobs($jobs);
} elseif ($cron_action == 'delete' && $jobs) {
@ -199,12 +198,12 @@ if ($submit) {
}
redirect('admin/' . basename(__FILE__) . '?mode=list');
} elseif (\TorrentPier\Legacy\Admin\Cron::validate_cron_post($_POST) == 1) {
if ($mode2 == 'edit') {
if ($_POST['mode'] == 'edit') {
\TorrentPier\Legacy\Admin\Cron::update_cron_job($_POST);
} elseif ($mode2 == 'add') {
} elseif ($_POST['mode'] == 'add') {
\TorrentPier\Legacy\Admin\Cron::insert_cron_job($_POST);
} else {
bb_die("Invalid mode: $mode2");
bb_die('Mode error');
}
redirect('admin/' . basename(__FILE__) . '?mode=list');

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -123,7 +123,6 @@ if ($submit) {
}
$datastore->update('cat_forums');
CACHE('bb_cache')->rm();
bb_die($lang['FORUM_AUTH_UPDATED'] . '<br /><br />' . sprintf($lang['CLICK_RETURN_FORUMAUTH'], '<a href="' . 'admin_forumauth.php' . '">', '</a>'));
}
@ -208,7 +207,7 @@ if (empty($forum_id)) {
}
$adv_mode = empty($adv) ? '1' : '0';
$switch_mode = "admin_forumauth.php?" . POST_FORUM_URL . "=$forum_id&amp;adv=$adv_mode";
$switch_mode = "admin_forumauth.php?f=$forum_id&amp;adv=$adv_mode";
$switch_mode_text = empty($adv) ? $lang['ADVANCED_MODE'] : $lang['SIMPLE_MODE'];
$u_switch_mode = '<a href="' . $switch_mode . '">' . $switch_mode_text . '</a>';

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -153,7 +153,6 @@ if ($submit) {
}
$datastore->update('cat_forums');
CACHE('bb_cache')->rm();
bb_die($lang['FORUM_AUTH_UPDATED'] . '<br /><br />' . sprintf($lang['CLICK_RETURN_FORUMAUTH'], '<a href="admin_forumauth_list.php">', '</a>'));
} // End of submit

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -115,8 +115,8 @@ if ($mode) {
if ($parent = get_forum_data($forum_parent)) {
$cat_id = $parent['cat_id'];
}
} elseif (isset($_REQUEST[POST_CAT_URL])) {
$cat_id = (int)$_REQUEST[POST_CAT_URL];
} elseif (isset($_REQUEST['c'])) {
$cat_id = (int)$_REQUEST['c'];
}
$catlist = get_list('category', $cat_id, true);
@ -223,7 +223,7 @@ if ($mode) {
$datastore->update('cat_forums');
CACHE('bb_cache')->rm();
bb_die($lang['FORUMS_UPDATED'] . '<br /><br />' . sprintf($lang['CLICK_RETURN_FORUMADMIN'], '<a href="admin_forums.php?' . POST_CAT_URL . '=' . $cat_id . '">', '</a>') . '<br /><br />' . sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>'));
bb_die($lang['FORUMS_UPDATED'] . '<br /><br />' . sprintf($lang['CLICK_RETURN_FORUMADMIN'], '<a href="admin_forums.php?c=' . $cat_id . '">', '</a>') . '<br /><br />' . sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>'));
break;
@ -312,7 +312,7 @@ if ($mode) {
$message = $lang['FORUMS_UPDATED'] . '<br /><br />';
$message .= $fix ? "$fix<br /><br />" : '';
$message .= sprintf($lang['CLICK_RETURN_FORUMADMIN'], '<a href="admin_forums.php?' . POST_CAT_URL . '=' . $cat_id . '">', '</a>') . '<br /><br />' . sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>');
$message .= sprintf($lang['CLICK_RETURN_FORUMADMIN'], '<a href="admin_forums.php?c=' . $cat_id . '">', '</a>') . '<br /><br />' . sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>');
bb_die($message);
break;
@ -322,7 +322,7 @@ if ($mode) {
// Create a category in the DB
//
if (!$new_cat_title = trim($_POST['categoryname'])) {
bb_die($lang['CATEGORY_NAME_EMPTY']);
bb_die('Category name is empty');
}
check_name_dup('cat', $new_cat_title);
@ -347,12 +347,12 @@ if ($mode) {
//
// Show form to edit a category
//
$cat_id = (int)$_GET[POST_CAT_URL];
$cat_id = (int)$_GET['c'];
$cat_info = get_info('category', $cat_id);
$hidden_fields = array(
'mode' => 'modcat',
POST_CAT_URL => $cat_id,
'c' => $cat_id,
);
$template->assign_vars(array(
@ -370,10 +370,10 @@ if ($mode) {
// Modify a category in the DB
//
if (!$new_cat_title = trim($_POST['cat_title'])) {
bb_die($lang['CATEGORY_NAME_EMPTY']);
bb_die('Category name is empty');
}
$cat_id = (int)$_POST[POST_CAT_URL];
$cat_id = (int)$_POST['c'];
$row = get_info('category', $cat_id);
$cur_cat_title = $row['cat_title'];
@ -401,7 +401,7 @@ if ($mode) {
//
// Show form to delete a forum
//
$forum_id = (int)$_GET[POST_FORUM_URL];
$forum_id = (int)$_GET['f'];
$move_to_options = '<option value="-1">' . $lang['DELETE_ALL_POSTS'] . '</option>';
$move_to_options .= sf_get_list('forum', $forum_id, 0);
@ -486,7 +486,7 @@ if ($mode) {
case 'deletecat':
// Show form to delete a category
$cat_id = (int)$_GET[POST_CAT_URL];
$cat_id = (int)$_GET['c'];
$catinfo = get_info('category', $cat_id);
$categories_count = $catinfo['number'];
@ -634,7 +634,7 @@ if ($mode) {
case 'cat_order':
$move = (int)$_GET['move'];
$cat_id = (int)$_GET[POST_CAT_URL];
$cat_id = (int)$_GET['c'];
DB()->query('
UPDATE ' . BB_CATEGORIES . " SET
@ -650,7 +650,7 @@ if ($mode) {
break;
case 'forum_sync':
\TorrentPier\Legacy\Admin\Common::sync('forum', (int)$_GET[POST_FORUM_URL]);
\TorrentPier\Legacy\Admin\Common::sync('forum', (int)$_GET['f']);
$datastore->update('cat_forums');
CACHE('bb_cache')->rm();
@ -681,7 +681,7 @@ if (!$mode || $show_main_page) {
$where_cat_sql = $req_cat_id = '';
if ($c =& $_REQUEST[POST_CAT_URL]) {
if ($c =& $_REQUEST['c']) {
if ($c !== 'all') {
$req_cat_id = (int)$c;
$where_cat_sql = "WHERE cat_id = $req_cat_id";
@ -709,7 +709,7 @@ if (!$mode || $show_main_page) {
$bgr_class_over = 'prow3';
$template->assign_vars(array(
'U_ALL_FORUMS' => 'admin_forums.php?' . POST_CAT_URL . '=all',
'U_ALL_FORUMS' => 'admin_forums.php?c=all',
'FORUMS_COUNT' => $total_forums,
));
@ -723,12 +723,12 @@ if (!$mode || $show_main_page) {
'CAT_ID' => $cat_id,
'CAT_DESC' => htmlCHR($category_rows[$i]['cat_title']),
'U_CAT_EDIT' => "admin_forums.php?mode=editcat&amp;" . POST_CAT_URL . "=$cat_id",
'U_CAT_DELETE' => "admin_forums.php?mode=deletecat&amp;" . POST_CAT_URL . "=$cat_id",
'U_CAT_MOVE_UP' => "admin_forums.php?mode=cat_order&amp;move=-15&amp;" . POST_CAT_URL . "=$cat_id",
'U_CAT_MOVE_DOWN' => "admin_forums.php?mode=cat_order&amp;move=15&amp;" . POST_CAT_URL . "=$cat_id",
'U_VIEWCAT' => "admin_forums.php?" . POST_CAT_URL . "=$cat_id",
'U_CREATE_FORUM' => "admin_forums.php?mode=addforum&amp;" . POST_CAT_URL . "=$cat_id",
'U_CAT_EDIT' => "admin_forums.php?mode=editcat&amp;c=$cat_id",
'U_CAT_DELETE' => "admin_forums.php?mode=deletecat&amp;c=$cat_id",
'U_CAT_MOVE_UP' => "admin_forums.php?mode=cat_order&amp;move=-15&amp;c=$cat_id",
'U_CAT_MOVE_DOWN' => "admin_forums.php?mode=cat_order&amp;move=15&amp;c=$cat_id",
'U_VIEWCAT' => "admin_forums.php?c=$cat_id",
'U_CREATE_FORUM' => "admin_forums.php?mode=addforum&amp;c=$cat_id",
));
for ($j = 0; $j < $total_forums; $j++) {
@ -755,12 +755,12 @@ if (!$mode || $show_main_page) {
'FORUM_NAME_CLASS' => $forum_rows[$j]['forum_parent'] ? 'genmed' : 'gen',
'ADD_SUB_HREF' => !$forum_rows[$j]['forum_parent'] ? "admin_forums.php?mode=addforum&amp;forum_parent={$forum_rows[$j]['forum_id']}" : '',
'U_VIEWFORUM' => BB_ROOT . FORUM_URL . $forum_id,
'U_FORUM_EDIT' => "admin_forums.php?mode=editforum&amp;" . POST_FORUM_URL . "=$forum_id",
'U_FORUM_PERM' => "admin_forumauth.php?" . POST_FORUM_URL . "=$forum_id",
'U_FORUM_DELETE' => "admin_forums.php?mode=deleteforum&amp;" . POST_FORUM_URL . "=$forum_id",
'U_FORUM_MOVE_UP' => "admin_forums.php?mode=forum_order&amp;move=-15&amp;" . POST_FORUM_URL . "=$forum_id&amp;" . POST_CAT_URL . "=$req_cat_id",
'U_FORUM_MOVE_DOWN' => "admin_forums.php?mode=forum_order&amp;move=15&amp;" . POST_FORUM_URL . "=$forum_id&amp;" . POST_CAT_URL . "=$req_cat_id",
'U_FORUM_RESYNC' => "admin_forums.php?mode=forum_sync&amp;" . POST_FORUM_URL . "=$forum_id",
'U_FORUM_EDIT' => "admin_forums.php?mode=editforum&amp;f=$forum_id",
'U_FORUM_PERM' => "admin_forumauth.php?f=$forum_id",
'U_FORUM_DELETE' => "admin_forums.php?mode=deleteforum&amp;f=$forum_id",
'U_FORUM_MOVE_UP' => "admin_forums.php?mode=forum_order&amp;move=-15&amp;f=$forum_id&amp;c=$req_cat_id",
'U_FORUM_MOVE_DOWN' => "admin_forums.php?mode=forum_order&amp;move=15&amp;f=$forum_id&amp;c=$req_cat_id",
'U_FORUM_RESYNC' => "admin_forums.php?mode=forum_sync&amp;f=$forum_id",
));
}
}
@ -865,7 +865,7 @@ function get_list($mode, $id, $select)
if ($row[$idfield] == $id) {
$s = ' selected';
}
$catlist .= '<option value="' . $row[$idfield] . '"' . $s . '>&nbsp;' . str_short(htmlCHR($row[$namefield]), 60) . '</option>\n';
$catlist .= '<option value="' . $row[$idfield] . '"' . $s . '>&nbsp;' . htmlCHR(str_short($row[$namefield], 60)) . '</option>\n';
}
return $catlist;
@ -1102,7 +1102,7 @@ function sf_get_list($mode, $exclude = 0, $select = 0)
$selected = ($fid == $select) ? HTML_SELECTED : '';
$disabled = ($fid == $exclude && !$forum_parent) ? HTML_DISABLED : '';
$style = $disabled ? ' style="color: gray" ' : (($fid == $exclude) ? ' style="color: darkred" ' : '');
$opt .= '<option value="' . $fid . '" ' . $selected . $disabled . $style . '>' . ($f['forum_parent'] ? HTML_SF_SPACER : '') . str_short(htmlCHR($f['forum_name']), 60) . "&nbsp;</option>\n";
$opt .= '<option value="' . $fid . '" ' . $selected . $disabled . $style . '>' . ($f['forum_parent'] ? HTML_SF_SPACER : '') . htmlCHR(str_short($f['forum_name'], 60)) . "&nbsp;</option>\n";
}
$opt .= '</optgroup>';

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -14,10 +14,10 @@ if (!empty($setmodules)) {
require __DIR__ . '/pagestart.php';
$datastore->enqueue([
$datastore->enqueue(array(
'moderators',
'cat_forums',
]);
));
$log_action->init();
@ -36,9 +36,9 @@ $url = basename(__FILE__);
// Key names
$type_key = 'type';
$forum_key = POST_FORUM_URL;
$topic_key = POST_TOPIC_URL;
$user_key = POST_USERS_URL;
$forum_key = 'f';
$topic_key = 't';
$user_key = 'u';
$datetime_key = 'dt'; // value should be strtotime() time ("2006-06-25" etc.)
$daysback_key = 'db';
$sort_key = 'sort';
@ -151,7 +151,7 @@ if ($var =& $_REQUEST[$daysback_key] && $var != $def_days) {
$url = url_arg($url, $daysback_key, $daysback_val);
}
if ($var =& $_REQUEST[$datetime_key] && $var != $def_datetime) {
$tz = TIMENOW + (3600 * config()->get('board_timezone'));
$tz = TIMENOW + (3600 * $bb_cfg['board_timezone']);
if (($tmp_timestamp = strtotime($var, $tz)) > 0) {
$datetime_val = $tmp_timestamp;
$url = url_arg($url, $datetime_key, date($dt_format, $datetime_val));
@ -225,9 +225,6 @@ if ($log_rowset) {
case $log_type['mod_topic_unlock']:
case $log_type['mod_topic_set_downloaded']:
case $log_type['mod_topic_unset_downloaded']:
case $log_type['mod_topic_change_tor_status']:
case $log_type['mod_topic_change_tor_type']:
case $log_type['mod_topic_tor_unregister']:
case $log_type['mod_topic_renamed']:
case $log_type['mod_post_delete']:
case $log_type['mod_post_pin']:

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -14,7 +14,7 @@ if (!empty($setmodules)) {
require __DIR__ . '/pagestart.php';
if (!config()->get('emailer.enabled')) {
if (!$bb_cfg['emailer']['enabled']) {
bb_die($lang['EMAILER_DISABLED']);
}
@ -23,7 +23,7 @@ set_time_limit(1200);
$subject = trim(request_var('subject', ''));
$message = (string)request_var('message', '');
$group_id = (int)request_var(POST_GROUPS_URL, 0);
$reply_to = (string)request_var('reply_to', config()->get('board_email'));
$reply_to = (string)request_var('reply_to', $bb_cfg['board_email']);
$message_type = (string)request_var('message_type', '');
$errors = $user_id_sql = [];
@ -40,7 +40,12 @@ if (isset($_POST['submit'])) {
}
if (!$errors) {
$banned_users = ($get_banned_users = get_banned_users()) ? (', ' . implode(', ', $get_banned_users)) : '';
$sql = DB()->fetch_rowset('SELECT ban_userid FROM ' . BB_BANLIST . ' WHERE ban_userid != 0');
foreach ($sql as $row) {
$user_id_sql[] = ',' . $row['ban_userid'];
}
$user_id_sql = implode('', $user_id_sql);
if ($group_id != -1) {
$user_list = DB()->fetch_rowset('
@ -50,14 +55,14 @@ if (isset($_POST['submit'])) {
AND ug.user_pending = 0
AND u.user_id = ug.user_id
AND u.user_active = 1
AND u.user_id NOT IN(" . EXCLUDED_USERS . $banned_users . ')
AND u.user_id NOT IN(" . EXCLUDED_USERS . $user_id_sql . ')
');
} else {
$user_list = DB()->fetch_rowset('
SELECT username, user_email, user_lang
FROM ' . BB_USERS . '
WHERE user_active = 1
AND user_id NOT IN(' . EXCLUDED_USERS . $banned_users . ')
AND user_id NOT IN(' . EXCLUDED_USERS . $user_id_sql . ')
');
}

View file

@ -1,79 +0,0 @@
<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
if (!empty($setmodules)) {
if (IS_SUPER_ADMIN) {
$module['GENERAL']['MIGRATIONS_STATUS'] = basename(__FILE__);
}
return;
}
require __DIR__ . '/pagestart.php';
if (!IS_SUPER_ADMIN) {
bb_die(__('ONLY_FOR_SUPER_ADMIN'));
}
use TorrentPier\Database\MigrationStatus;
// Initialize migration status
$migrationStatus = new MigrationStatus();
$status = $migrationStatus->getMigrationStatus();
$schemaInfo = $migrationStatus->getSchemaInfo();
// Template variables
$template->assign_vars([
'PAGE_TITLE' => __('MIGRATIONS_STATUS'),
'CURRENT_TIME' => date('Y-m-d H:i:s'),
// Migration status individual fields
'MIGRATION_TABLE_EXISTS' => $status['table_exists'],
'MIGRATION_CURRENT_VERSION' => $status['current_version'],
'MIGRATION_APPLIED_COUNT' => count($status['applied_migrations']),
'MIGRATION_PENDING_COUNT' => count($status['pending_migrations']),
// Setup status fields
'SETUP_REQUIRES_SETUP' => $status['requires_setup'] ?? false,
'SETUP_TYPE' => $status['setup_status']['type'] ?? __('UNKNOWN'),
'SETUP_MESSAGE' => $status['setup_status']['message'] ?? '',
'SETUP_ACTION_REQUIRED' => $status['setup_status']['action_required'] ?? false,
'SETUP_INSTRUCTIONS' => $status['setup_status']['instructions'] ?? '',
// Schema info individual fields
'SCHEMA_DATABASE_NAME' => $schemaInfo['database_name'],
'SCHEMA_TABLE_COUNT' => $schemaInfo['table_count'],
'SCHEMA_SIZE_MB' => $schemaInfo['size_mb'],
]);
// Assign migration data for template
if (!empty($status['applied_migrations'])) {
foreach ($status['applied_migrations'] as $i => $migration) {
$template->assign_block_vars('applied_migrations', [
'VERSION' => $migration['version'],
'NAME' => $migration['migration_name'] ?? __('UNKNOWN'),
'START_TIME' => $migration['start_time'] ?? __('UNKNOWN'),
'END_TIME' => $migration['end_time'] ?? __('UNKNOWN'),
'ROW_CLASS' => ($i % 2) ? 'row1' : 'row2'
]);
}
}
if (!empty($status['pending_migrations'])) {
foreach ($status['pending_migrations'] as $i => $migration) {
$template->assign_block_vars('pending_migrations', [
'VERSION' => $migration['version'],
'NAME' => $migration['name'],
'FILENAME' => $migration['filename'],
'ROW_CLASS' => ($i % 2) ? 'row1' : 'row2'
]);
}
}
// Output template using standard admin pattern
print_page('admin_migrations.tpl', 'admin');

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -29,10 +29,6 @@ if (isset($_GET['mode']) || isset($_POST['mode'])) {
}
}
if ($mode == 'delete' && isset($_POST['cancel'])) {
$mode = '';
}
if ($mode != '') {
if ($mode == 'edit' || $mode == 'add') {
//
@ -87,7 +83,7 @@ if ($mode != '') {
// The rank image has to be a jpg, gif or png
//
if ($rank_image != '') {
if (!preg_match('/(\.gif|\.png|\.jpg|\.jpeg|\.bmp|\.webp|\.avif\.ico)$/is', $rank_image)) {
if (!preg_match('/(\.gif|\.png|\.jpg|\.jpeg|\.bmp|\.webp|\.ico)$/is', $rank_image)) {
$rank_image = '';
}
}
@ -127,40 +123,29 @@ if ($mode != '') {
// Ok, they want to delete their rank
//
$confirmed = isset($_POST['confirm']);
if (isset($_POST['id']) || isset($_GET['id'])) {
$rank_id = isset($_POST['id']) ? (int)$_POST['id'] : (int)$_GET['id'];
} else {
$rank_id = 0;
}
if ($confirmed) {
if ($rank_id) {
$sql = 'DELETE FROM ' . BB_RANKS . " WHERE rank_id = $rank_id";
if ($rank_id) {
$sql = 'DELETE FROM ' . BB_RANKS . " WHERE rank_id = $rank_id";
if (!$result = DB()->sql_query($sql)) {
bb_die('Could not delete rank data');
}
$sql = 'UPDATE ' . BB_USERS . " SET user_rank = 0 WHERE user_rank = $rank_id";
if (!$result = DB()->sql_query($sql)) {
bb_die($lang['NO_UPDATE_RANKS']);
}
$datastore->update('ranks');
bb_die($lang['RANK_REMOVED'] . '<br /><br />' . sprintf($lang['CLICK_RETURN_RANKADMIN'], '<a href="admin_ranks.php">', '</a>') . '<br /><br />' . sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>'));
} else {
bb_die($lang['MUST_SELECT_RANK']);
if (!$result = DB()->sql_query($sql)) {
bb_die('Could not delete rank data');
}
} else {
$hidden_fields = '<input type="hidden" name="mode" value="' . $mode . '" />';
$hidden_fields .= '<input type="hidden" name="id" value="' . $rank_id . '" />';
print_confirmation([
'FORM_ACTION' => 'admin_ranks.php',
'HIDDEN_FIELDS' => $hidden_fields,
]);
$sql = 'UPDATE ' . BB_USERS . " SET user_rank = 0 WHERE user_rank = $rank_id";
if (!$result = DB()->sql_query($sql)) {
bb_die($lang['NO_UPDATE_RANKS']);
}
$datastore->update('ranks');
bb_die($lang['RANK_REMOVED'] . '<br /><br />' . sprintf($lang['CLICK_RETURN_RANKADMIN'], '<a href="admin_ranks.php">', '</a>') . '<br /><br />' . sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>'));
} else {
bb_die($lang['MUST_SELECT_RANK']);
}
} else {
bb_die('Invalid mode');

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

View file

@ -1,45 +0,0 @@
<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
if (!empty($setmodules)) {
$module['MODS']['ROBOTS_TXT_EDITOR_TITLE'] = basename(__FILE__);
return;
}
require __DIR__ . '/pagestart.php';
$robots_file = BB_ROOT . 'robots.txt';
// Обработка сохранения
if (isset($_POST['save'])) {
$robots_txt = $_POST['robots_txt'] ?? '';
if (!is_writable($robots_file) && is_file($robots_file)) {
bb_die('File robots.txt is not writable #1');
}
$bytes = file_put_contents($robots_file, $robots_txt);
if ($bytes === false) {
bb_die('Could not write robots.txt #2');
}
bb_die($lang['ROBOTS_TXT_UPDATED_SUCCESSFULLY'] . '<br /><br />' . sprintf($lang['CLICK_RETURN_ROBOTS_TXT_CONFIG'], '<a href="admin_robots.php">', '</a>') . '<br /><br />' . sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>'));
}
$current_content = '';
if (is_file($robots_file)) {
$current_content = file_get_contents($robots_file);
}
$template->assign_vars([
'S_ACTION' => 'admin_robots.php',
'ROBOTS_TXT' => htmlCHR($current_content),
]);
print_page('admin_robots.tpl', 'admin');

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -14,7 +14,7 @@ if (!empty($setmodules)) {
require __DIR__ . '/pagestart.php';
$sql = "SELECT * FROM " . BB_CONFIG . " WHERE config_name IN('sitemap_time', 'static_sitemap')";
$sql = 'SELECT * FROM ' . BB_CONFIG;
if (!$result = DB()->sql_query($sql)) {
bb_die('Could not query config information in admin_sitemap');
@ -39,7 +39,7 @@ if (!$result = DB()->sql_query($sql)) {
}
}
$s_mess = $lang['SITEMAP_CREATED'] . ': <b>' . bb_date($new['sitemap_time'], config()->get('post_date_format')) . '</b> ' . $lang['SITEMAP_AVAILABLE'] . ': <a href="' . make_url('sitemap/sitemap.xml') . '" target="_blank">' . make_url('sitemap/sitemap.xml') . '</a>';
$s_mess = $lang['SITEMAP_CREATED'] . ': <b>' . bb_date($new['sitemap_time'], $bb_cfg['post_date_format']) . '</b> ' . $lang['SITEMAP_AVAILABLE'] . ': <a href="' . make_url('sitemap/sitemap.xml') . '" target="_blank">' . make_url('sitemap/sitemap.xml') . '</a>';
$message = is_file(SITEMAP_DIR . '/sitemap.xml') ? $s_mess : $lang['SITEMAP_NOT_CREATED'];
$template->assign_vars([

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -22,11 +22,7 @@ if (isset($_POST['mode']) || isset($_GET['mode'])) {
$mode = '';
}
if ($mode == 'delete' && isset($_POST['cancel'])) {
$mode = '';
}
$pathToSmilesDir = BB_ROOT . config()->get('smilies_path');
$pathToSmilesDir = BB_ROOT . $bb_cfg['smilies_path'];
$delimeter = '=+:';
$s_hidden_fields = '';
$smiley_paks = $smiley_images = [];
@ -178,28 +174,17 @@ if (isset($_GET['import_pack']) || isset($_POST['import_pack'])) {
} elseif ($mode != '') {
switch ($mode) {
case 'delete':
$confirmed = isset($_POST['confirm']);
$smiley_id = (!empty($_POST['id'])) ? $_POST['id'] : $_GET['id'];
$smiley_id = (int)$smiley_id;
if ($confirmed) {
$sql = 'DELETE FROM ' . BB_SMILIES . ' WHERE smilies_id = ' . $smiley_id;
$result = DB()->sql_query($sql);
if (!$result) {
bb_die('Could not delete smiley');
}
$datastore->update('smile_replacements');
bb_die($lang['SMILEY_DEL_SUCCESS'] . '<br /><br />' . sprintf($lang['CLICK_RETURN_SMILEADMIN'], '<a href="admin_smilies.php">', '</a>') . '<br /><br />' . sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>'));
} else {
$hidden_fields = '<input type="hidden" name="mode" value="' . $mode . '" />';
$hidden_fields .= '<input type="hidden" name="id" value="' . $smiley_id . '" />';
print_confirmation([
'FORM_ACTION' => 'admin_smilies.php',
'HIDDEN_FIELDS' => $hidden_fields,
]);
$sql = 'DELETE FROM ' . BB_SMILIES . ' WHERE smilies_id = ' . $smiley_id;
$result = DB()->sql_query($sql);
if (!$result) {
bb_die('Could not delete smiley');
}
$datastore->update('smile_replacements');
bb_die($lang['SMILEY_DEL_SUCCESS'] . '<br /><br />' . sprintf($lang['CLICK_RETURN_SMILEADMIN'], '<a href="admin_smilies.php">', '</a>') . '<br /><br />' . sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>'));
break;
case 'edit':

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -17,15 +17,15 @@ require INC_DIR . '/bbcode.php';
$preview = isset($_POST['preview']);
if (isset($_POST['post']) && (config()->get('terms') !== $_POST['message'])) {
if (isset($_POST['post']) && ($bb_cfg['terms'] !== $_POST['message'])) {
bb_update_config(['terms' => $_POST['message']]);
bb_die($lang['TERMS_UPDATED_SUCCESSFULLY'] . '<br /><br />' . sprintf($lang['CLICK_RETURN_TERMS_CONFIG'], '<a href="admin_terms.php">', '</a>') . '<br /><br />' . sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>'));
bb_die($lang['CONFIG_UPDATED']);
}
$template->assign_vars([
'S_ACTION' => 'admin_terms.php',
'EXT_LINK_NW' => config()->get('ext_link_new_win'),
'MESSAGE' => $preview ? $_POST['message'] : config()->get('terms'),
'EXT_LINK_NW' => $bb_cfg['ext_link_new_win'],
'MESSAGE' => $preview ? $_POST['message'] : $bb_cfg['terms'],
'PREVIEW_HTML' => $preview ? bbcode2html($_POST['message']) : '',
]);

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -20,9 +20,9 @@ $max_forum_name_length = 50;
$yes_sign = '&radic;';
$no_sign = 'x';
$group_id = isset($_REQUEST[POST_GROUPS_URL]) ? (int)$_REQUEST[POST_GROUPS_URL] : 0;
$user_id = isset($_REQUEST[POST_USERS_URL]) ? (int)$_REQUEST[POST_USERS_URL] : 0;
$cat_id = isset($_REQUEST[POST_CAT_URL]) ? (int)$_REQUEST[POST_CAT_URL] : 0;
$group_id = isset($_REQUEST['g']) ? (int)$_REQUEST['g'] : 0;
$user_id = isset($_REQUEST['u']) ? (int)$_REQUEST['u'] : 0;
$cat_id = isset($_REQUEST['c']) ? (int)$_REQUEST['c'] : 0;
$mode = isset($_REQUEST['mode']) ? (string)$_REQUEST['mode'] : '';
$submit = isset($_REQUEST['submit']);
@ -87,7 +87,7 @@ if ($submit && $mode == 'user') {
\TorrentPier\Legacy\Group::delete_permissions($group_id, $user_id);
$message = $lang['AUTH_UPDATED'] . '<br /><br />';
$message .= sprintf($lang['CLICK_RETURN_USERAUTH'], '<a href="admin_ug_auth.php?mode=' . $mode . '&' . POST_USERS_URL . '=' . $user_id . '">', '</a>') . '<br /><br />';
$message .= sprintf($lang['CLICK_RETURN_USERAUTH'], '<a href="admin_ug_auth.php?mode=' . $mode . '&u=' . $user_id . '">', '</a>') . '<br /><br />';
$message .= sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>');
bb_die($message);
@ -103,7 +103,7 @@ if ($submit && $mode == 'user') {
\TorrentPier\Legacy\Group::delete_permissions($group_id, $user_id);
$message = $lang['AUTH_UPDATED'] . '<br /><br />';
$message .= sprintf($lang['CLICK_RETURN_USERAUTH'], '<a href="admin_ug_auth.php?mode=' . $mode . '&' . POST_USERS_URL . '=' . $user_id . '">', '</a>') . '<br /><br />';
$message .= sprintf($lang['CLICK_RETURN_USERAUTH'], '<a href="admin_ug_auth.php?mode=' . $mode . '&u=' . $user_id . '">', '</a>') . '<br /><br />';
$message .= sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>');
bb_die($message);
@ -131,7 +131,7 @@ if ($submit && $mode == 'user') {
$l_auth_return = ($mode == 'user') ? $lang['CLICK_RETURN_USERAUTH'] : $lang['CLICK_RETURN_GROUPAUTH'];
$message = $lang['AUTH_UPDATED'] . '<br /><br />';
$message .= sprintf($l_auth_return, '<a href="admin_ug_auth.php?mode=' . $mode . '&' . POST_USERS_URL . '=' . $user_id . '">', '</a>') . '<br /><br />';
$message .= sprintf($l_auth_return, '<a href="admin_ug_auth.php?mode=' . $mode . '&u=' . $user_id . '">', '</a>') . '<br /><br />';
$message .= sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>');
bb_die($message);
@ -159,7 +159,7 @@ elseif ($submit && $mode == 'group' && (!empty($_POST['auth']) && is_array($_POS
$l_auth_return = $lang['CLICK_RETURN_GROUPAUTH'];
$message = $lang['AUTH_UPDATED'] . '<br /><br />';
$message .= sprintf($l_auth_return, '<a href="admin_ug_auth.php?mode=' . $mode . '&' . POST_GROUPS_URL . '=' . $group_id . '">', '</a>') . '<br /><br />';
$message .= sprintf($l_auth_return, '<a href="admin_ug_auth.php?mode=' . $mode . '&g=' . $group_id . '">', '</a>') . '<br /><br />';
$message .= sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>');
bb_die($message);
@ -185,7 +185,7 @@ if ($mode == 'user' && (!empty($_POST['username']) || $user_id)) {
$datastore->update('cat_forums');
$forums = $datastore->get('cat_forums');
}
$base_url = basename(__FILE__) . "?mode=user&amp;" . POST_USERS_URL . "=$user_id";
$base_url = basename(__FILE__) . "?mode=user&amp;u=$user_id";
$ug_data = $this_userdata;
$ug_data['session_logged_in'] = 1;
@ -197,10 +197,10 @@ if ($mode == 'user' && (!empty($_POST['username']) || $user_id)) {
$template->assign_block_vars('c', array(
'CAT_ID' => $c_id,
'CAT_TITLE' => $forums['cat_title_html'][$c_id],
'CAT_HREF' => "$base_url&amp;" . POST_CAT_URL . "=$c_id",
'CAT_HREF' => "$base_url&amp;c=$c_id",
));
if (!$c =& $_REQUEST[POST_CAT_URL] or !in_array($c, array('all', $c_id)) or empty($c_data['forums'])) {
if (!$c =& $_REQUEST['c'] or !in_array($c, array('all', $c_id)) or empty($c_data['forums'])) {
continue;
}
@ -304,7 +304,7 @@ if ($mode == 'user' && (!empty($_POST['username']) || $user_id)) {
$datastore->update('cat_forums');
$forums = $datastore->get('cat_forums');
}
$base_url = basename(__FILE__) . "?mode=group&amp;" . POST_GROUPS_URL . "=$group_id";
$base_url = basename(__FILE__) . "?mode=group&amp;g=$group_id";
$ug_data = array('group_id' => $group_id);
$u_access = auth(AUTH_ALL, AUTH_LIST_ALL, $ug_data);
@ -313,10 +313,10 @@ if ($mode == 'user' && (!empty($_POST['username']) || $user_id)) {
$template->assign_block_vars('c', array(
'CAT_ID' => $c_id,
'CAT_TITLE' => $forums['cat_title_html'][$c_id],
'CAT_HREF' => "$base_url&amp;" . POST_CAT_URL . "=$c_id",
'CAT_HREF' => "$base_url&amp;c=$c_id",
));
if (!($c =& $_REQUEST[POST_CAT_URL]) || !in_array($c, array('all', $c_id)) || empty($c_data['forums'])) {
if (!($c =& $_REQUEST['c']) || !in_array($c, array('all', $c_id)) || empty($c_data['forums'])) {
continue;
}
@ -381,7 +381,7 @@ if ($mode == 'user' && (!empty($_POST['username']) || $user_id)) {
$s_hidden_fields = '
<input type="hidden" name="mode" value="' . $mode . '" />
<input type="hidden" name="' . POST_GROUPS_URL . '" value="' . $group_id . '" />
<input type="hidden" name="g" value="' . $group_id . '" />
';
$template->assign_vars(array(
@ -419,8 +419,8 @@ $template->assign_vars(array(
'YES_SIGN' => $yes_sign,
'NO_SIGN' => $no_sign,
'S_AUTH_ACTION' => 'admin_ug_auth.php',
'SELECTED_CAT' => !empty($_REQUEST[POST_CAT_URL]) ? $_REQUEST[POST_CAT_URL] : '',
'U_ALL_FORUMS' => !empty($base_url) ? "$base_url&amp;" . POST_CAT_URL . "=all" : '',
'SELECTED_CAT' => !empty($_REQUEST['c']) ? $_REQUEST['c'] : '',
'U_ALL_FORUMS' => !empty($base_url) ? "$base_url&amp;c=all" : '',
));
print_page('admin_ug_auth.tpl', 'admin');

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -52,8 +52,8 @@ if (!isset($_REQUEST['dosearch'])) {
}
}
$language_list = \TorrentPier\Legacy\Common\Select::language('', 'language_type');
$timezone_list = \TorrentPier\Legacy\Common\Select::timezone('', 'timezone_type');
$language_list = \TorrentPier\Legacy\Select::language('', 'language_type');
$timezone_list = \TorrentPier\Legacy\Select::timezone('', 'timezone_type');
$sql = 'SELECT f.forum_id, f.forum_name, f.forum_parent, c.cat_id, c.cat_title
FROM ( ' . BB_FORUMS . ' AS f INNER JOIN ' . BB_CATEGORIES . ' AS c ON c.cat_id = f.cat_id )
@ -252,7 +252,8 @@ if (!isset($_REQUEST['dosearch'])) {
$text = sprintf($lang['SEARCH_FOR_USERNAME'], strip_tags(htmlspecialchars(stripslashes($username))));
$username = str_replace('*', '%', trim(strip_tags(strtolower($username))));
$username = str_replace("\*", '%', trim(strip_tags(strtolower($username))));
if (str_contains($username, '%')) {
$op = 'LIKE';
} else {
@ -272,7 +273,8 @@ if (!isset($_REQUEST['dosearch'])) {
$text = sprintf($lang['SEARCH_FOR_EMAIL'], strip_tags(htmlspecialchars(stripslashes($email))));
$email = str_replace('*', '%', trim(strip_tags(strtolower($email))));
$email = str_replace("\*", '%', trim(strip_tags(strtolower($email))));
if (str_contains($email, '%')) {
$op = 'LIKE';
} else {
@ -566,7 +568,8 @@ if (!isset($_REQUEST['dosearch'])) {
$text = strip_tags(htmlspecialchars(stripslashes($userfield_value)));
$userfield_value = str_replace('*', '%', trim(strip_tags(strtolower($userfield_value))));
$userfield_value = str_replace("\*", '%', trim(strip_tags(strtolower($userfield_value))));
if (str_contains($userfield_value, '%')) {
$op = 'LIKE';
} else {
@ -841,10 +844,10 @@ if (!isset($_REQUEST['dosearch'])) {
if ($page == 1) {
$offset = 0;
} else {
$offset = (($page - 1) * config()->get('topics_per_page'));
$offset = (($page - 1) * $bb_cfg['topics_per_page']);
}
$limit = "LIMIT $offset, " . config()->get('topics_per_page');
$limit = "LIMIT $offset, " . $bb_cfg['topics_per_page'];
$select_sql .= " $limit";
@ -859,7 +862,7 @@ if (!isset($_REQUEST['dosearch'])) {
bb_die($lang['SEARCH_NO_RESULTS']);
}
}
$num_pages = ceil($total_pages['total'] / config()->get('topics_per_page'));
$num_pages = ceil($total_pages['total'] / $bb_cfg['topics_per_page']);
$pagination = '';

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -14,8 +14,8 @@ if (!empty($setmodules)) {
require __DIR__ . '/pagestart.php';
if (!config()->get('use_word_censor')) {
bb_die('Word censor disabled <br /><br /> (use_word_censor in config.php)');
if (!$bb_cfg['use_word_censor']) {
bb_die('Word censor disabled <br /><br /> ($bb_cfg[\'use_word_censor\'] in config.php)');
}
$mode = request_var('mode', '');
@ -80,8 +80,7 @@ if ($mode != '') {
bb_die('Could not insert data into words table');
}
$datastore->update('censor');
censor()->reload(); // Reload the singleton instance with updated words
CACHE('bb_cache')->rm('censored');
$message .= '<br /><br />' . sprintf($lang['CLICK_RETURN_WORDADMIN'], '<a href="admin_words.php">', '</a>') . '<br /><br />' . sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>');
bb_die($message);
@ -95,8 +94,7 @@ if ($mode != '') {
bb_die('Could not remove data from words table');
}
$datastore->update('censor');
censor()->reload(); // Reload the singleton instance with updated words
CACHE('bb_cache')->rm('censored');
bb_die($lang['WORD_REMOVED'] . '<br /><br />' . sprintf($lang['CLICK_RETURN_WORDADMIN'], '<a href="admin_words.php">', '</a>') . '<br /><br />' . sprintf($lang['CLICK_RETURN_ADMIN_INDEX'], '<a href="index.php?pane=right">', '</a>'));
} else {

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -15,12 +15,6 @@ if (!$stats = $datastore->get('stats')) {
$stats = $datastore->get('stats');
}
// Check for updates
if (!$update_data = $datastore->get('check_updates')) {
$datastore->update('check_updates');
$update_data = $datastore->get('check_updates');
}
// Generate relevant output
if (isset($_GET['pane']) && $_GET['pane'] == 'left') {
$module = [];
@ -78,28 +72,16 @@ if (isset($_GET['pane']) && $_GET['pane'] == 'left') {
} elseif (isset($_GET['pane']) && $_GET['pane'] == 'right') {
$template->assign_vars([
'TPL_ADMIN_MAIN' => true,
'ADMIN_LOCK' => (bool)config()->get('board_disable'),
'ADMIN_LOCK' => (bool)$bb_cfg['board_disable'],
'ADMIN_LOCK_CRON' => is_file(BB_DISABLED),
]);
// Check for updates
if (isset($update_data['available_update'])) {
$template->assign_block_vars('updater', [
'UPDATE_AVAILABLE' => $update_data['available_update'],
'NEW_VERSION_NUMBER' => $update_data['latest_version'],
'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_HASH' => $update_data['latest_version_checksum']
]);
}
// Get forum statistics
$total_posts = $stats['postcount'];
$total_topics = $stats['topiccount'];
$total_users = $stats['usercount'];
$start_date = bb_date(config()->get('board_startdate'));
$boarddays = (TIMENOW - config()->get('board_startdate')) / 86400;
$start_date = bb_date($bb_cfg['board_startdate']);
$boarddays = (TIMENOW - $bb_cfg['board_startdate']) / 86400;
$posts_per_day = sprintf('%.2f', $total_posts / $boarddays);
$topics_per_day = sprintf('%.2f', $total_topics / $boarddays);
@ -107,10 +89,10 @@ if (isset($_GET['pane']) && $_GET['pane'] == 'left') {
$avatar_dir_size = 0;
if ($avatar_dir = opendir(config()->get('avatars.upload_path'))) {
if ($avatar_dir = opendir($bb_cfg['avatars']['upload_path'])) {
while ($file = readdir($avatar_dir)) {
if ($file != '.' && $file != '..') {
$avatar_dir_size += @filesize(config()->get('avatars.upload_path') . $file);
$avatar_dir_size += @filesize($bb_cfg['avatars']['upload_path'] . $file);
}
}
closedir($avatar_dir);
@ -187,7 +169,7 @@ if (isset($_GET['pane']) && $_GET['pane'] == 'left') {
'STARTED' => bb_date($onlinerow_reg[$i]['session_start'], 'd-M-Y H:i', false),
'LASTUPDATE' => bb_date($onlinerow_reg[$i]['user_session_time'], 'd-M-Y H:i', false),
'IP_ADDRESS' => $reg_ip,
'U_WHOIS_IP' => config()->get('whois_info') . $reg_ip,
'U_WHOIS_IP' => $bb_cfg['whois_info'] . $reg_ip,
]);
}
}
@ -206,7 +188,7 @@ if (isset($_GET['pane']) && $_GET['pane'] == 'left') {
'STARTED' => bb_date($onlinerow_guest[$i]['session_start'], 'd-M-Y H:i', false),
'LASTUPDATE' => bb_date($onlinerow_guest[$i]['session_time'], 'd-M-Y H:i', false),
'IP_ADDRESS' => $guest_ip,
'U_WHOIS_IP' => config()->get('whois_info') . $guest_ip,
'U_WHOIS_IP' => $bb_cfg['whois_info'] . $guest_ip,
]);
}
}
@ -218,7 +200,7 @@ if (isset($_GET['pane']) && $_GET['pane'] == 'left') {
} else {
// Generate frameset
$template->assign_vars([
'CONTENT_ENCODING' => DEFAULT_CHARSET,
'CONTENT_ENCODING' => $bb_cfg['charset'],
'TPL_ADMIN_FRAMESET' => true,
]);
send_no_cache_headers();

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -31,8 +31,7 @@ echo '<html><body><head></head>';
echo '<br /><br /><table border="1" cellspacing="0" cellpadding="6" align="center">';
foreach ($sql as $i => $query) {
$result = DB()->fetch_row($query);
$row = array_values($result)[0]; // Get first column value
$row = mysqli_fetch_row(DB()->query($query))[0];
$row = ($i == 2) ? humn_size($row) : $row;
echo "<tr><td>{$lang['TR_STATS'][$i]}</td><td><b>$row</b></td>";
}
@ -40,7 +39,7 @@ foreach ($sql as $i => $query) {
echo '</table>';
echo '<div align="center"><pre>';
echo 'gen time: <b>' . sprintf('%.3f', array_sum(explode(' ', microtime())) - TIMESTART) . "</b> sec\n";
echo 'gen time: <b>' . sprintf('%.4f', array_sum(explode(' ', microtime())) - TIMESTART) . "</b> sec\n";
echo '</pre></div>';
echo '</body></html>';

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -21,7 +21,7 @@ if (!IS_ADMIN) {
$peers_in_last_minutes = [30, 15, 5, 1];
$peers_in_last_sec_limit = 300;
$announce_interval = (int)config()->get('announce_interval');
$announce_interval = (int)$bb_cfg['announce_interval'];
$stat = [];
define('TMP_TRACKER_TABLE', 'tmp_tracker');
@ -52,7 +52,7 @@ $stat += DB()->fetch_row('SELECT COUNT(DISTINCT user_id) AS u_bt_active FROM ' .
// All bt-users
$stat += DB()->fetch_row('SELECT COUNT(*) AS u_bt_all FROM ' . BB_BT_USERS);
// All bb-users
$stat += DB()->fetch_row('SELECT COUNT(*) AS u_bb_all FROM ' . BB_USERS . ' WHERE user_id != ' . BOT_UID);
$stat += DB()->fetch_row('SELECT COUNT(*) AS u_bb_all FROM ' . BB_USERS);
// Active torrents
$stat += DB()->fetch_row('SELECT COUNT(DISTINCT topic_id) AS tor_active FROM ' . TMP_TRACKER_TABLE);
// With seeder
@ -70,7 +70,7 @@ foreach ($peers_in_last_minutes as $t) {
}
// Last xx seconds
$peers_in_last_sec = [];
$rowset = DB()->fetch_rowset('SELECT COUNT(*) AS peers FROM ' . TMP_TRACKER_TABLE . ' ORDER BY update_time DESC LIMIT ' . $peers_in_last_sec_limit);
$rowset = DB()->fetch_rowset('SELECT COUNT(*) AS peers FROM ' . TMP_TRACKER_TABLE . ' GROUP BY update_time ORDER BY update_time DESC LIMIT ' . $peers_in_last_sec_limit);
foreach ($rowset as $cnt => $row) {
$peers_in_last_sec[] = sprintf('%3s', $row['peers']) . (($cnt && !(++$cnt % 15)) ? " \n" : '');
}
@ -116,7 +116,7 @@ if ($client_full || !$stats_cache = CACHE('tr_cache')->get('tracker_clients_stat
$n = 1;
foreach (array_slice($clients_percentage, 0, $numwant) as $client => $value) {
$client_list .= ($client_full) ? ("$client => $value<br/>") : "$n. " . get_user_torrent_client($client) . " $value<br/>";
$client_list .= ($client_full) ? ("$client => $value<br>") : "$n. " . get_user_torrent_client($client) . " $value<br>";
$n++;
}
@ -164,16 +164,16 @@ echo "\n
<td align=center>
$client_list
<br/>
<br>
\n";
echo (count($clients_percentage) > $numwant) ? ('<a href="' . 'tracker.php?client_numwant=' . ($numwant + 100) . '">' . 'Show more' . '</a><br/>') : '';
echo $client_full ? '<br/><b>Get more length and numbers via modifying the parameters in the url<b>' : (!empty($client_list) ? '<a href="tracker.php?client_length=6&client_numwant=10">Peer_ids with more length (version debugging)</a>' : '');
echo (count($clients_percentage) > $numwant) ? ('<a href="' . 'tracker.php?client_numwant=' . ($numwant + 100) . '">' . 'Show more' . '</a><br>') : '';
echo $client_full ? '<br><b>Get more length and numbers via modifying the parameters in the url<b>' : (!empty($client_list) ? '<a href="tracker.php?client_length=6&client_numwant=10">Peer_ids with more length (version debugging)</a>' : '');
echo '</td></tr>';
echo '</table>';
echo !$client_full ? '<p style = "text-align:right;">Simple stats for clients are being cached for one hour.</p>' : '';
echo '<div align="center"><pre>';
echo 'gen time: <b>' . sprintf('%.3f', array_sum(explode(' ', microtime())) - TIMESTART) . "</b> sec\n";
echo 'gen time: <b>' . sprintf('%.4f', array_sum(explode(' ', microtime())) - TIMESTART) . "</b> sec\n";
echo '</pre></div>';
echo '</body></html>';

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -41,5 +41,5 @@ $ajax->exec();
/**
* @deprecated ajax_common
* Dirty class removed from here since 2.2.0
* To add new actions see at src/Ajax.php
* To add new actions see at src/Legacy/Ajax.php
*/

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,15 +11,15 @@ define('IN_TRACKER', true);
define('BB_ROOT', './../');
require dirname(__DIR__) . '/common.php';
// Check User-Agent for existence
$userAgent = (string)$_SERVER['HTTP_USER_AGENT'];
if (empty($userAgent)) {
global $bb_cfg;
if (empty($_SERVER['HTTP_USER_AGENT'])) {
header('Location: http://127.0.0.1', true, 301);
die;
}
$announce_interval = config()->get('announce_interval');
$passkey_key = config()->get('passkey_key');
$announce_interval = $bb_cfg['announce_interval'];
$passkey_key = $bb_cfg['passkey_key'];
// Recover info_hash
if (isset($_GET['?info_hash']) && !isset($_GET['info_hash'])) {
@ -65,26 +65,10 @@ if (strlen($peer_id) !== 20) {
}
// Check for client ban
if (config()->get('client_ban.enabled')) {
$targetClient = [];
foreach (config()->get('client_ban.clients') as $clientId => $banReason) {
if ($bb_cfg['client_ban']['enabled']) {
foreach ($bb_cfg['client_ban']['clients'] as $clientId => $reason) {
if (str_starts_with($peer_id, $clientId)) {
$targetClient = [
'peer_id' => $clientId,
'ban_reason' => $banReason
];
break;
}
}
if (config()->get('client_ban.only_allow_mode')) {
if (empty($targetClient['peer_id'])) {
msg_die('Your BitTorrent client has been banned!');
}
} else {
if (!empty($targetClient['peer_id'])) {
msg_die(empty($targetClient['ban_reason']) ? 'Your BitTorrent client has been banned!' : $targetClient['ban_reason']);
msg_die($reason);
}
}
}
@ -94,87 +78,44 @@ if (!isset($info_hash)) {
msg_die('info_hash was not provided');
}
/**
* Verify event
*
* @see https://github.com/HDInnovations/UNIT3D-Community-Edition/blob/c64275f0b5dcb3c4c845d5204871adfe24f359d6/app/Http/Controllers/AnnounceController.php#L275
*/
$event = strtolower((string)$event);
if (!in_array($event, ['started', 'completed', 'stopped', 'paused', ''])) {
msg_die('Invalid event: ' . $event);
}
// Store info hash in hex format
$info_hash_hex = bin2hex($info_hash);
// Store peer id
$peer_id_sql = preg_replace('/[^a-zA-Z0-9\-\_]/', '', $peer_id);
// Stopped event
$stopped = ($event === 'stopped');
// Check info_hash length
if (strlen($info_hash) !== 20) {
msg_die('Invalid info_hash: ' . (mb_check_encoding($info_hash, DEFAULT_CHARSET) ? $info_hash : $info_hash_hex));
msg_die('Invalid info_hash: ' . (mb_check_encoding($info_hash, 'UTF8') ? $info_hash : $info_hash_hex));
}
/**
* Block system-reserved ports since 99.9% of the time they're fake and thus not connectable
* Some clients will send port of 0 on 'stopped' events. Let them through as they won't receive peers anyway.
*
* @see https://github.com/HDInnovations/UNIT3D-Community-Edition/blob/c64275f0b5dcb3c4c845d5204871adfe24f359d6/app/Http/Controllers/AnnounceController.php#L284
*/
if (
!isset($port)
|| !is_numeric($port)
|| ($port < 1024 && !$stopped)
|| $port > 0xFFFF
|| (!empty(config()->get('disallowed_ports')) && in_array($port, config()->get('disallowed_ports')))
) {
if (!isset($port) || $port < 0 || $port > 0xFFFF) {
msg_die('Invalid port: ' . $port);
}
if (!isset($uploaded) || !is_numeric($uploaded) || $uploaded < 0) {
if (!isset($uploaded) || $uploaded < 0) {
msg_die('Invalid uploaded value: ' . $uploaded);
}
if (!isset($downloaded) || !is_numeric($downloaded) || $downloaded < 0) {
if (!isset($downloaded) || $downloaded < 0) {
msg_die('Invalid downloaded value: ' . $downloaded);
}
if (!isset($left) || !is_numeric($left) || $left < 0) {
if (!isset($left) || $left < 0) {
msg_die('Invalid left value: ' . $left);
}
/**
* Check User-Agent length
*
* @see https://github.com/HDInnovations/UNIT3D-Community-Edition/blob/c64275f0b5dcb3c4c845d5204871adfe24f359d6/app/Http/Controllers/AnnounceController.php#L177
*/
if (strlen($userAgent) > 64) {
msg_die('User-Agent must be less than 64 characters long');
}
/**
* Block Browser by checking the User-Agent
*
* @see https://github.com/HDInnovations/UNIT3D-Community-Edition/blob/c64275f0b5dcb3c4c845d5204871adfe24f359d6/app/Http/Controllers/AnnounceController.php#L182
*/
if (preg_match('/(Mozilla|Browser|Chrome|Safari|AppleWebKit|Opera|Links|Lynx|Bot|Unknown)/i', $userAgent)) {
msg_die('Browser disallowed');
}
// IP
$ip = $_SERVER['REMOTE_ADDR'];
// 'ip' query handling
if (!config()->get('ignore_reported_ip') && isset($_GET['ip']) && $ip !== $_GET['ip']) {
if (!config()->get('verify_reported_ip') && isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
if (!$bb_cfg['ignore_reported_ip'] && isset($_GET['ip']) && $ip !== $_GET['ip']) {
if (!$bb_cfg['verify_reported_ip'] && isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$x_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
if ($x_ip === $_GET['ip']) {
$filteredIp = filter_var($x_ip, FILTER_VALIDATE_IP);
if ($filteredIp !== false && (config()->get('allow_internal_ip') || !filter_var($filteredIp, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))) {
if ($filteredIp !== false && ($bb_cfg['allow_internal_ip'] || !filter_var($filteredIp, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))) {
$ip = $filteredIp;
}
}
@ -201,6 +142,9 @@ if ($ip_version === 'ipv6') {
// Peer unique id
$peer_hash = hash('xxh128', $passkey . $info_hash_hex . $port);
// Events
$stopped = ($event === 'stopped');
// Set seeder & complete
$complete = $seeder = ($left == 0) ? 1 : 0;
@ -239,17 +183,16 @@ if ($lp_info) {
/**
* Currently torrent clients send truncated v2 hashes (the design raises questions).
* @see https://github.com/bittorrent/bittorrent.org/issues/145#issuecomment-1720040343
* https://github.com/bittorrent/bittorrent.org/issues/145#issuecomment-1720040343
*/
$info_hash_where = "WHERE tor.info_hash = '$info_hash_sql' OR SUBSTRING(tor.info_hash_v2, 1, 20) = '$info_hash_sql'";
$passkey_sql = DB()->escape($passkey);
$sql = "
SELECT tor.topic_id, tor.poster_id, tor.tor_type, tor.tor_status, tor.info_hash, tor.info_hash_v2, bt.*, u.user_level
SELECT tor.topic_id, tor.poster_id, tor.tor_type, tor.info_hash, tor.info_hash_v2, u.*
FROM " . BB_BT_TORRENTS . " tor
LEFT JOIN " . BB_BT_USERS . " bt ON bt.auth_key = '$passkey_sql'
LEFT JOIN " . BB_USERS . " u ON u.user_id = bt.user_id
LEFT JOIN " . BB_BT_USERS . " u ON u.auth_key = '$passkey_sql'
$info_hash_where
LIMIT 1
";
@ -257,7 +200,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, DEFAULT_CHARSET) ? $info_hash : $info_hash_hex));
msg_die('Torrent not registered, info_hash = ' . (mb_check_encoding($info_hash, 'UTF8') ? $info_hash : $info_hash_hex));
}
if (empty($row['user_id'])) {
msg_die('Please LOG IN and RE-DOWNLOAD this torrent (user not found)');
@ -265,28 +208,16 @@ if ($lp_info) {
// Assign variables
$user_id = $row['user_id'];
define('IS_GUEST', (int)$user_id === GUEST_UID);
define('IS_ADMIN', !IS_GUEST && (int)$row['user_level'] === ADMIN);
define('IS_MOD', !IS_GUEST && (int)$row['user_level'] === MOD);
define('IS_GROUP_MEMBER', !IS_GUEST && (int)$row['user_level'] === GROUP_MEMBER);
define('IS_USER', !IS_GUEST && (int)$row['user_level'] === USER);
define('IS_SUPER_ADMIN', IS_ADMIN && isset(config()->get('super_admins')[$user_id]));
define('IS_AM', IS_ADMIN || IS_MOD);
$topic_id = $row['topic_id'];
$releaser = (int)($user_id == $row['poster_id']);
$tor_type = $row['tor_type'];
$tor_status = $row['tor_status'];
// Check tor status
if (!IS_AM && isset(config()->get('tor_frozen')[$tor_status]) && !(isset(config()->get('tor_frozen_author_download')[$tor_status]) && $releaser)) {
msg_die('Torrent frozen and cannot be downloaded');
}
// Check hybrid status
if (!empty($row['info_hash']) && !empty($row['info_hash_v2'])) {
$stat_protocol = match ((int)config()->get('tracker.hybrid_stat_protocol')) {
$stat_protocol = match ($bb_cfg['tracker']['hybrid_stat_protocol']) {
1 => $row['info_hash'],
2 => substr($row['info_hash_v2'], 0, 20),
default => $row['info_hash'] // 1
default => $row['info_hash']
};
if ($info_hash !== $stat_protocol) {
$hybrid_unrecord = true; // This allows us to announce only for one info-hash
@ -294,18 +225,15 @@ if ($lp_info) {
}
// Ratio limits
if ((RATIO_ENABLED || config()->get('tracker.limit_concurrent_ips')) && !$stopped) {
$user_ratio = get_bt_ratio($row);
if ($user_ratio === null) {
$user_ratio = 1;
}
if ((TR_RATING_LIMITS || $bb_cfg['tracker']['limit_concurrent_ips']) && !$stopped) {
$user_ratio = ($row['u_down_total'] && $row['u_down_total'] > MIN_DL_FOR_RATIO) ? ($row['u_up_total'] + $row['u_up_release'] + $row['u_up_bonus']) / $row['u_down_total'] : 1;
$rating_msg = '';
if (!$seeder) {
foreach (config()->get('rating') as $ratio => $limit) {
foreach ($bb_cfg['rating'] as $ratio => $limit) {
if ($user_ratio < $ratio) {
config()->set('tracker.limit_active_tor', 1);
config()->set('tracker.limit_leech_count', $limit);
$bb_cfg['tracker']['limit_active_tor'] = 1;
$bb_cfg['tracker']['limit_leech_count'] = $limit;
$rating_msg = " (ratio < $ratio)";
break;
}
@ -313,29 +241,29 @@ if ($lp_info) {
}
// Limit active torrents
if (!isset(config()->get('unlimited_users')[$user_id]) && config()->get('tracker.limit_active_tor') && ((config()->get('tracker.limit_seed_count') && $seeder) || (config()->get('tracker.limit_leech_count') && !$seeder))) {
if (!isset($bb_cfg['unlimited_users'][$user_id]) && $bb_cfg['tracker']['limit_active_tor'] && (($bb_cfg['tracker']['limit_seed_count'] && $seeder) || ($bb_cfg['tracker']['limit_leech_count'] && !$seeder))) {
$sql = "SELECT COUNT(DISTINCT topic_id) AS active_torrents
FROM " . BB_BT_TRACKER . "
WHERE user_id = $user_id
AND seeder = $seeder
AND topic_id != $topic_id";
if (!$seeder && config()->get('tracker.leech_expire_factor') && $user_ratio < 0.5) {
$sql .= " AND update_time > " . (TIMENOW - 60 * config()->get('tracker.leech_expire_factor'));
if (!$seeder && $bb_cfg['tracker']['leech_expire_factor'] && $user_ratio < 0.5) {
$sql .= " AND update_time > " . (TIMENOW - 60 * $bb_cfg['tracker']['leech_expire_factor']);
}
$sql .= " GROUP BY user_id";
if ($row = DB()->fetch_row($sql)) {
if ($seeder && config()->get('tracker.limit_seed_count') && $row['active_torrents'] >= config()->get('tracker.limit_seed_count')) {
msg_die('Only ' . config()->get('tracker.limit_seed_count') . ' torrent(s) allowed for seeding');
} elseif (!$seeder && config()->get('tracker.limit_leech_count') && $row['active_torrents'] >= config()->get('tracker.limit_leech_count')) {
msg_die('Only ' . config()->get('tracker.limit_leech_count') . ' torrent(s) allowed for leeching' . $rating_msg);
if ($seeder && $bb_cfg['tracker']['limit_seed_count'] && $row['active_torrents'] >= $bb_cfg['tracker']['limit_seed_count']) {
msg_die('Only ' . $bb_cfg['tracker']['limit_seed_count'] . ' torrent(s) allowed for seeding');
} elseif (!$seeder && $bb_cfg['tracker']['limit_leech_count'] && $row['active_torrents'] >= $bb_cfg['tracker']['limit_leech_count']) {
msg_die('Only ' . $bb_cfg['tracker']['limit_leech_count'] . ' torrent(s) allowed for leeching' . $rating_msg);
}
}
}
// Limit concurrent IPs
if (config()->get('tracker.limit_concurrent_ips') && ((config()->get('tracker.limit_seed_ips') && $seeder) || (config()->get('tracker.limit_leech_ips') && !$seeder))) {
if ($bb_cfg['tracker']['limit_concurrent_ips'] && (($bb_cfg['tracker']['limit_seed_ips'] && $seeder) || ($bb_cfg['tracker']['limit_leech_ips'] && !$seeder))) {
$sql = "SELECT COUNT(DISTINCT ip) AS ips
FROM " . BB_BT_TRACKER . "
WHERE topic_id = $topic_id
@ -343,16 +271,16 @@ if ($lp_info) {
AND seeder = $seeder
AND $ip_version != '$ip_sql'";
if (!$seeder && config()->get('tracker.leech_expire_factor')) {
$sql .= " AND update_time > " . (TIMENOW - 60 * config()->get('tracker.leech_expire_factor'));
if (!$seeder && $bb_cfg['tracker']['leech_expire_factor']) {
$sql .= " AND update_time > " . (TIMENOW - 60 * $bb_cfg['tracker']['leech_expire_factor']);
}
$sql .= " GROUP BY topic_id";
if ($row = DB()->fetch_row($sql)) {
if ($seeder && config()->get('tracker.limit_seed_ips') && $row['ips'] >= config()->get('tracker.limit_seed_ips')) {
msg_die('You can seed only from ' . config()->get('tracker.limit_seed_ips') . " IP's");
} elseif (!$seeder && config()->get('tracker.limit_leech_ips') && $row['ips'] >= config()->get('tracker.limit_leech_ips')) {
msg_die('You can leech only from ' . config()->get('tracker.limit_leech_ips') . " IP's");
if ($seeder && $bb_cfg['tracker']['limit_seed_ips'] && $row['ips'] >= $bb_cfg['tracker']['limit_seed_ips']) {
msg_die('You can seed only from ' . $bb_cfg['tracker']['limit_seed_ips'] . " IP's");
} elseif (!$seeder && $bb_cfg['tracker']['limit_leech_ips'] && $row['ips'] >= $bb_cfg['tracker']['limit_leech_ips']) {
msg_die('You can leech only from ' . $bb_cfg['tracker']['limit_leech_ips'] . " IP's");
}
}
}
@ -376,7 +304,7 @@ $up_add = ($lp_info && $uploaded > $lp_info['uploaded']) ? $uploaded - $lp_info[
$down_add = ($lp_info && $downloaded > $lp_info['downloaded']) ? $downloaded - $lp_info['downloaded'] : 0;
// Gold/Silver releases
if (config()->get('tracker.gold_silver_enabled') && $down_add) {
if ($bb_cfg['tracker']['gold_silver_enabled'] && $down_add) {
if ($tor_type == TOR_TYPE_GOLD) {
$down_add = 0;
} // Silver releases
@ -386,7 +314,7 @@ if (config()->get('tracker.gold_silver_enabled') && $down_add) {
}
// Freeleech
if (config()->get('tracker.freeleech') && $down_add) {
if ($bb_cfg['tracker']['freeleech'] && $down_add) {
$down_add = 0;
}
@ -464,8 +392,8 @@ $output = CACHE('tr_cache')->get(PEERS_LIST_PREFIX . $topic_id);
if (!$output) {
// Retrieve peers
$numwant = (int)config()->get('tracker.numwant');
$compact_mode = (config()->get('tracker.compact_mode') || !empty($compact));
$numwant = (int)$bb_cfg['tracker']['numwant'];
$compact_mode = ($bb_cfg['tracker']['compact_mode'] || !empty($compact));
$rowset = DB()->fetch_rowset("
SELECT ip, ipv6, port
@ -510,7 +438,7 @@ if (!$output) {
$seeders = $leechers = $client_completed = 0;
if (config()->get('tracker.scrape')) {
if ($bb_cfg['tracker']['scrape']) {
$row = DB()->fetch_row("
SELECT seeders, leechers, completed
FROM " . BB_BT_TRACKER_SNAP . "

1
bt/includes/.htaccess Normal file
View file

@ -0,0 +1 @@
Require all denied

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,9 +11,11 @@ if (!defined('IN_TRACKER')) {
die(basename(__FILE__));
}
global $bb_cfg;
// Exit if tracker is disabled
if (config()->get('tracker.bt_off')) {
msg_die(config()->get('tracker.bt_off_reason'));
if ($bb_cfg['tracker']['bt_off']) {
msg_die($bb_cfg['tracker']['bt_off_reason']);
}
//

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,9 @@ define('IN_TRACKER', true);
define('BB_ROOT', './../');
require dirname(__DIR__) . '/common.php';
if (!config()->get('tracker.scrape')) {
global $bb_cfg;
if (!$bb_cfg['tracker']['scrape']) {
msg_die('Please disable SCRAPE!');
}
@ -32,7 +34,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, DEFAULT_CHARSET) ? $info_hash : $info_hash_hex));
msg_die('Invalid info_hash: ' . (mb_check_encoding($info_hash, 'UTF8') ? $info_hash : $info_hash_hex));
}
// Handle multiple hashes
@ -58,15 +60,15 @@ foreach ($info_hash_array[1] as $hash) {
$info_hash_count = count($info_hashes);
if (!empty($info_hash_count)) {
if ($info_hash_count > config()->get('max_scrapes')) {
$info_hashes = array_slice($info_hashes, 0, config()->get('max_scrapes'));
if ($info_hash_count > $bb_cfg['max_scrapes']) {
$info_hashes = array_slice($info_hashes, 0, $bb_cfg['max_scrapes']);
}
$info_hashes_sql = implode('\', \'', $info_hashes);
/**
* Currently torrent clients send truncated v2 hashes (the design raises questions).
* @see https://github.com/bittorrent/bittorrent.org/issues/145#issuecomment-1720040343
* https://github.com/bittorrent/bittorrent.org/issues/145#issuecomment-1720040343
*/
$info_hash_where = "tor.info_hash IN ('$info_hashes_sql') OR SUBSTRING(tor.info_hash_v2, 1, 20) IN ('$info_hashes_sql')";
@ -97,7 +99,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, DEFAULT_CHARSET) ? $info_hash : $info_hash_hex));
msg_die('Torrent not registered, info_hash = ' . (mb_check_encoding($info_hash, 'UTF8') ? $info_hash : $info_hash_hex));
}
die(\Arokettu\Bencode\Bencode::encode($torrents));

View file

@ -1,126 +0,0 @@
# git-cliff ~ TorrentPier configuration file
# https://git-cliff.org/docs/configuration
#
# Lines starting with "#" are comments.
# Configuration options are organized into tables and keys.
# See documentation for more information on available options.
[remote.github]
owner = "torrentpier"
repo = "torrentpier"
[changelog]
# template for the changelog header
header = """
[![TorrentPier](https://raw.githubusercontent.com/torrentpier/.github/refs/heads/main/versions/Cattle.png)](https://github.com/torrentpier)\n
# 📖 Change Log\n
"""
# template for the changelog body
# https://keats.github.io/tera/docs/#introduction
body = """
{%- macro remote_url() -%}
https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}
{%- endmacro -%}
{%- macro nightly_url() -%}
https://nightly.link/{{ remote.github.owner }}/{{ remote.github.repo }}/workflows/ci/master/TorrentPier-master
{%- endmacro -%}
{% macro print_commit(commit) -%}
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
{% if commit.breaking %}[**breaking**] {% endif %}\
{{ commit.message | upper_first }} - \
([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
{% endmacro -%}
{% if version %}\
{% if previous.version %}\
## [{{ version }}]\
({{ self::remote_url() }}/compare/{{ previous.version }}..{{ version }}) ({{ timestamp | date(format="%Y-%m-%d") }})
{% else %}\
## {{ version }} ({{ timestamp | date(format="%Y-%m-%d") }})
{% endif %}\
{% else %}\
## [nightly]({{ self::nightly_url() }})
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits
| filter(attribute="scope")
| sort(attribute="scope") %}
{{ self::print_commit(commit=commit) }}
{%- endfor %}
{% for commit in commits %}
{%- if not commit.scope -%}
{{ self::print_commit(commit=commit) }}
{% endif -%}
{% endfor -%}
{% endfor -%}
{%- if github -%}
{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
## New Contributors ❤️
{% endif %}\
{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}
* @{{ contributor.username }} made their first contribution
{%- if contributor.pr_number %} in \
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
{%- endif %}
{%- endfor -%}
{%- endif %}
"""
# template for the changelog footer
footer = """
"""
# remove the leading and trailing whitespace from the templates
trim = true
# postprocessors
postprocessors = [
{ pattern = '<REPO>', replace = "https://github.com/torrentpier/torrentpier" }, # replace repository URL
]
[git]
# parse the commits based on https://www.conventionalcommits.org
conventional_commits = true
# filter out the commits that are not conventional
filter_unconventional = true
# process each line of a commit as an individual commit
split_commits = false
# regex for preprocessing the commit messages
commit_preprocessors = [
# Replace issue numbers
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](<REPO>/pull/${2}))" },
# Check spelling of the commit with https://github.com/crate-ci/typos
# If the spelling is incorrect, it will be automatically fixed.
# { pattern = '.*', replace_command = 'typos --write-changes -' },
]
# regex for parsing and grouping commits
commit_parsers = [
{ message = "^feat", group = "<!-- 0 -->🚀 Features" },
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
{ message = "^doc", group = "<!-- 3 -->📚 Documentation" },
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
{ message = "^ignore|^release|^changelog", skip = true },
{ message = "^chore|^ci|^misc", group = "<!-- 7 -->⚙️ Miscellaneous" },
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
{ message = "^revert", group = "<!-- 9 -->◀️ Revert" },
{ message = "^crowdin|^crodwin", group = "<!-- 10 -->🈳 New translations" }, # crowdin pulls supporting
{ message = "^Composer", group = "<!-- 11 -->📦 Dependencies" }, # dependabot pulls supporting
{ message = "^rem|^drop|^removed", group = "<!-- 12 -->🗑️ Removed" },
{ message = ".*", group = "<!-- 13 -->💼 Other" },
]
# protect breaking changes from being skipped due to matching a skipping commit_parser
protect_breaking_commits = false
# filter out the commits that are not matched by commit parsers
filter_commits = false
# regex for matching git tags
tag_pattern = "v[0-9].*"
# sort the tags topologically
topo_order = false
# sort the commits inside sections by oldest/newest order
sort_commits = "newest"

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -54,7 +54,7 @@ require_once BB_PATH . '/library/defines.php';
// Composer
if (!is_file(BB_PATH . '/vendor/autoload.php')) {
die('🔩 Manual install: <a href="https://getcomposer.org/download/" target="_blank" rel="noreferrer" style="color:#0a25bb;">Install composer</a> and run <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">composer install</code>.<br/>☕️ Quick install: Run <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">php install.php</code> in CLI mode.');
die('Please <a href="https://getcomposer.org/download/" target="_blank" rel="noreferrer" style="color:#0a25bb;">install composer</a> and run <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">composer install</code>');
}
require_once BB_PATH . '/vendor/autoload.php';
@ -75,7 +75,7 @@ try {
$dotenv = Dotenv\Dotenv::createMutable(BB_PATH);
$dotenv->load();
} catch (\Dotenv\Exception\InvalidPathException $pathException) {
die('🔩 Manual install: Rename from <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">.env.example</code> to <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">.env</code>, and configure it.<br/>☕️ Quick install: Run <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">php install.php</code> in CLI mode.');
die('Please rename from <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">.env.example</code> to <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">.env</code>, and configure it');
}
// Load config
@ -86,137 +86,87 @@ if (is_file(BB_PATH . '/library/config.local.php')) {
require_once BB_PATH . '/library/config.local.php';
}
/** @noinspection PhpUndefinedVariableInspection */
// Initialize Config singleton, bb_cfg from global file config
$config = \TorrentPier\Config::init($bb_cfg);
/**
* Get the Config instance
*
* @return \TorrentPier\Config
* Progressive error reporting
*/
function config(): \TorrentPier\Config
{
return \TorrentPier\Config::getInstance();
}
/**
* Get the Censor instance
*
* @return \TorrentPier\Censor
*/
function censor(): \TorrentPier\Censor
{
return \TorrentPier\Censor::getInstance();
}
/**
* Get the Dev instance
*
* @return \TorrentPier\Dev
*/
function dev(): \TorrentPier\Dev
{
return \TorrentPier\Dev::getInstance();
}
/**
* Get the Language instance
*
* @return \TorrentPier\Language
*/
function lang(): \TorrentPier\Language
{
return \TorrentPier\Language::getInstance();
}
/**
* Get a language string (shorthand for lang()->get())
*
* @param string $key Language key, supports dot notation (e.g., 'DATETIME.TODAY')
* @param mixed $default Default value if key doesn't exist
* @return mixed Language string or default value
*/
function __(string $key, mixed $default = null): mixed
{
return \TorrentPier\Language::getInstance()->get($key, $default);
}
/**
* Echo a language string (shorthand for echo __())
*
* @param string $key Language key, supports dot notation
* @param mixed $default Default value if key doesn't exist
* @return void
*/
function _e(string $key, mixed $default = null): void
{
echo \TorrentPier\Language::getInstance()->get($key, $default);
}
/**
* Initialize debug
*/
define('APP_ENV', env('APP_ENV', 'production'));
if (APP_ENV === 'development') {
define('DBG_USER', true); // forced debug
} else {
define('DBG_USER', isset($_COOKIE[COOKIE_DBG]));
}
(\TorrentPier\Dev::init());
\TorrentPier\Dev::initDebug();
/**
* Server variables initialize
*/
$server_protocol = config()->get('cookie_secure') ? 'https://' : 'http://';
$server_port = in_array((int)config()->get('server_port'), [80, 443], true) ? '' : ':' . config()->get('server_port');
define('FORUM_PATH', config()->get('script_path'));
define('FULL_URL', $server_protocol . config()->get('server_name') . $server_port . config()->get('script_path'));
$server_protocol = $bb_cfg['cookie_secure'] ? 'https://' : 'http://';
$server_port = in_array((int)$bb_cfg['server_port'], [80, 443], true) ? '' : ':' . $bb_cfg['server_port'];
define('FORUM_PATH', $bb_cfg['script_path']);
define('FULL_URL', $server_protocol . $bb_cfg['server_name'] . $server_port . $bb_cfg['script_path']);
unset($server_protocol, $server_port);
// Initialize the new DB factory with database configuration
TorrentPier\Database\DatabaseFactory::init(config()->get('db'), config()->get('db_alias', []));
// Board / tracker shared constants and functions
define('BB_BT_TORRENTS', 'bb_bt_torrents');
define('BB_BT_TRACKER', 'bb_bt_tracker');
define('BB_BT_TRACKER_SNAP', 'bb_bt_tracker_snap');
define('BB_BT_USERS', 'bb_bt_users');
define('BT_AUTH_KEY_LENGTH', 20);
define('DL_STATUS_RELEASER', -1);
define('DL_STATUS_DOWN', 0);
define('DL_STATUS_COMPLETE', 1);
define('DL_STATUS_CANCEL', 3);
define('DL_STATUS_WILL', 4);
define('TOR_TYPE_GOLD', 1);
define('TOR_TYPE_SILVER', 2);
define('GUEST_UID', -1);
define('BOT_UID', -746);
/**
* Get the Database instance
*
* @param string $db_alias
* @return \TorrentPier\Database\Database
* Database
*/
function DB(string $db_alias = 'db'): \TorrentPier\Database\Database
{
return TorrentPier\Database\DatabaseFactory::getInstance($db_alias);
}
$DBS = new TorrentPier\Legacy\Dbs($bb_cfg);
// Initialize Unified Cache System
TorrentPier\Cache\UnifiedCacheSystem::getInstance(config()->all());
/**
* Get cache manager instance (replaces legacy cache system)
*
* @param string $cache_name
* @return \TorrentPier\Cache\CacheManager
*/
function CACHE(string $cache_name): \TorrentPier\Cache\CacheManager
function DB(string $db_alias = 'db')
{
return TorrentPier\Cache\UnifiedCacheSystem::getInstance()->get_cache_obj($cache_name);
global $DBS;
return $DBS->get_db_obj($db_alias);
}
/**
* Get datastore manager instance (replaces legacy datastore system)
*
* @return \TorrentPier\Cache\DatastoreManager
* Cache
*/
function datastore(): \TorrentPier\Cache\DatastoreManager
$CACHES = new TorrentPier\Legacy\Caches($bb_cfg);
function CACHE(string $cache_name)
{
return TorrentPier\Cache\UnifiedCacheSystem::getInstance()->getDatastore(config()->get('datastore_type', 'file'));
global $CACHES;
return $CACHES->get_cache_obj($cache_name);
}
/**
* Backward compatibility: Global datastore variable
* This allows existing code to continue using global $datastore
* Datastore
*/
$datastore = datastore();
switch ($bb_cfg['datastore_type']) {
case 'memcache':
$datastore = new TorrentPier\Legacy\Datastore\Memcache($bb_cfg['cache']['memcache'], $bb_cfg['cache']['prefix']);
break;
case 'sqlite':
$default_cfg = [
'db_file_path' => $bb_cfg['cache']['db_dir'] . 'datastore.sqlite.db',
'pconnect' => true,
'con_required' => true,
];
$datastore = new TorrentPier\Legacy\Datastore\Sqlite($default_cfg, $bb_cfg['cache']['prefix']);
break;
case 'redis':
$datastore = new TorrentPier\Legacy\Datastore\Redis($bb_cfg['cache']['redis'], $bb_cfg['cache']['prefix']);
break;
case 'filecache':
default:
$datastore = new TorrentPier\Legacy\Datastore\File($bb_cfg['cache']['db_dir'] . 'datastore/', $bb_cfg['cache']['prefix']);
}
// Functions
function utime()
@ -224,7 +174,7 @@ function utime()
return array_sum(explode(' ', microtime()));
}
function bb_log($msg, $file_name = 'logs', $return_path = false)
function bb_log($msg, $file_name, $return_path = false)
{
if (is_array($msg)) {
$msg = implode(LOG_LF, $msg);
@ -288,11 +238,6 @@ function mkdir_rec($path, $mode): bool
return mkdir_rec(dirname($path), $mode) && mkdir($path, $mode);
}
function verify_id($id, $length): bool
{
return (is_string($id) && preg_match('#^[a-zA-Z0-9]{' . $length . '}$#', $id));
}
function clean_filename($fname)
{
static $s = ['\\', '/', ':', '*', '?', '"', '<', '>', '|', ' '];
@ -308,7 +253,7 @@ function clean_filename($fname)
* @param ?string $charset
* @return string
*/
function htmlCHR($txt, bool $double_encode = false, int $quote_style = ENT_QUOTES, ?string $charset = DEFAULT_CHARSET): string
function htmlCHR($txt, bool $double_encode = false, int $quote_style = ENT_QUOTES, ?string $charset = 'UTF-8'): string
{
return (string)htmlspecialchars($txt ?? '', $quote_style, $charset, $double_encode);
}
@ -319,7 +264,7 @@ function htmlCHR($txt, bool $double_encode = false, int $quote_style = ENT_QUOTE
*/
function str_compact($str)
{
return preg_replace('/\s\s+/', ' ', trim($str ?? ''));
return preg_replace('#\s+#u', ' ', trim($str ?? ''));
}
/**
@ -343,20 +288,6 @@ function make_rand_str(int $length = 10): string
return $randomString;
}
/**
* Calculates user ratio
*
* @param array $btu
* @return float|null
*/
function get_bt_ratio(array $btu): ?float
{
return
(!empty($btu['u_down_total']) && $btu['u_down_total'] > MIN_DL_FOR_RATIO)
? round((($btu['u_up_total'] + $btu['u_up_release'] + $btu['u_up_bonus']) / $btu['u_down_total']), 2)
: null;
}
function array_deep(&$var, $fn, $one_dimensional = false, $array_only = false, $timeout = false)
{
if ($timeout) {
@ -399,12 +330,6 @@ function hide_bb_path(string $path): string
return ltrim(str_replace(BB_PATH, '', $path), '/\\');
}
/**
* Returns memory usage statistic
*
* @param string $param
* @return int|void
*/
function sys(string $param)
{
switch ($param) {
@ -417,15 +342,6 @@ function sys(string $param)
}
}
/**
* Some shared defines
*/
// Initialize demo mode
define('IN_DEMO_MODE', env('APP_DEMO_MODE', false));
// Ratio status
define('RATIO_ENABLED', TR_RATING_LIMITS && MIN_DL_FOR_RATIO > 0);
// Initialization
if (!defined('IN_TRACKER')) {
// Init board
@ -433,9 +349,9 @@ if (!defined('IN_TRACKER')) {
} else {
define('DUMMY_PEER', pack('Nn', \TorrentPier\Helpers\IPHelper::ip2long($_SERVER['REMOTE_ADDR']), !empty($_GET['port']) ? (int)$_GET['port'] : random_int(1000, 65000)));
define('PEER_HASH_EXPIRE', round(config()->get('announce_interval') * (0.85 * config()->get('tracker.expire_factor'))));
define('PEERS_LIST_EXPIRE', round(config()->get('announce_interval') * 0.7));
define('SCRAPE_LIST_EXPIRE', round(config()->get('scrape_interval') * 0.7));
define('PEER_HASH_EXPIRE', round($bb_cfg['announce_interval'] * (0.85 * $bb_cfg['tracker']['expire_factor'])));
define('PEERS_LIST_EXPIRE', round($bb_cfg['announce_interval'] * 0.7));
define('SCRAPE_LIST_EXPIRE', round($bb_cfg['scrape_interval'] * 0.7));
define('PEER_HASH_PREFIX', 'peer_');
define('PEERS_LIST_PREFIX', 'peers_list_');

View file

@ -17,16 +17,6 @@
"homepage": "https://github.com/Exileum",
"role": "Developer"
},
{
"name": "Diolektor",
"homepage": "https://github.com/diolektor",
"role": "Developer"
},
{
"name": "PheRum",
"homepage": "https://github.com/PheRum",
"role": "Developer"
},
{
"name": "belomaxorka",
"email": "roman25052006.kelesh@gmail.com",
@ -46,56 +36,43 @@
"forum": "https://torrentpier.com"
},
"require": {
"php": ">=8.2",
"php": "^8.1",
"ext-bcmath": "*",
"ext-ctype": "*",
"ext-curl": "*",
"ext-intl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-mysqli": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"arokettu/bencode": "^4.1.0",
"arokettu/monsterid": "^4.1.0",
"arokettu/random-polyfill": "1.0.2",
"arokettu/torrent-file": "^5.2.1",
"belomaxorka/captcha": "1.*",
"bugsnag/bugsnag": "^v3.29.1",
"claviska/simpleimage": "^4.0",
"egulias/email-validator": "^4.0.1",
"filp/whoops": "^2.15",
"gemorroj/m3u-parser": "^6.0.1",
"gigablah/sphinxphp": "2.0.8",
"google/recaptcha": "^1.3",
"jacklul/monolog-telegram": "^3.1",
"josantonius/cookie": "^2.0",
"league/flysystem": "^3.28",
"longman/ip-tools": "1.2.1",
"monolog/monolog": "^3.4",
"nette/caching": "^3.3",
"nette/database": "^3.2",
"php-curl-class/php-curl-class": "^12.0.0",
"robmorgan/phinx": "^0.16.9",
"samdark/sitemap": "2.4.1",
"symfony/mailer": "^7.3",
"symfony/polyfill": "v1.32.0",
"vlucas/phpdotenv": "^5.5",
"z4kn4fein/php-semver": "^v3.0.0"
"symfony/mailer": "^6.3",
"vlucas/phpdotenv": "^5.5"
},
"require-dev": {
"mockery/mockery": "^1.6",
"pestphp/pest": "^3.8",
"symfony/var-dumper": "^7.3"
"symfony/var-dumper": "^6.3"
},
"autoload": {
"psr-4": {
"TorrentPier\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"config": {
"sort-packages": true,
"optimize-autoloader": true,
"allow-plugins": {
"pestphp/pest-plugin": true,
"php-http/discovery": true
}
"optimize-autoloader": true
},
"minimum-stability": "stable",
"prefer-stable": true

5722
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

3
data/uploads/.htaccess Normal file
View file

@ -0,0 +1,3 @@
php_flag engine off
RemoveHandler .php .php5 .php4 .php3 .phtml .pl .asp
AddType text/plain .php .php .htm .html .phtml .pl .asp

26
dl.php
View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -20,12 +20,11 @@ $datastore->enqueue([
$download_id = request_var('id', 0);
$thumbnail = request_var('thumb', 0);
$m3u = isset($_GET['m3u']) && $_GET['m3u'];
// Send file to browser
function send_file_to_browser($attachment, $upload_dir)
{
global $lang;
global $bb_cfg, $lang;
$filename = $upload_dir . '/' . $attachment['physical_filename'];
$gotit = false;
@ -53,7 +52,7 @@ function send_file_to_browser($attachment, $upload_dir)
header('Pragma: public');
$real_filename = clean_filename(basename($attachment['real_filename']));
$mimetype = $attachment['mimetype'] . ';';
$charset = 'charset=' . DEFAULT_CHARSET . ';';
$charset = "charset={$bb_cfg['charset']};";
// Send out the Headers
header("Content-Type: $mimetype $charset name=\"$real_filename\"");
@ -101,18 +100,9 @@ if (!($attachment = DB()->sql_fetchrow($result))) {
$attachment['physical_filename'] = basename($attachment['physical_filename']);
// Re-define $attachment['physical_filename'] for thumbnails
if ($thumbnail) {
// Re-define $attachment['physical_filename'] for thumbnails
$attachment['physical_filename'] = THUMB_DIR . '/t_' . $attachment['physical_filename'];
} elseif ($m3u) {
// Check m3u file exist
if (!$m3uFile = (new \TorrentPier\TorrServerAPI())->getM3UPath($download_id)) {
bb_die($lang['ERROR_NO_ATTACHMENT']);
}
$attachment['physical_filename'] = $attachment['real_filename'] = basename($m3uFile);
$attachment['mimetype'] = mime_content_type($m3uFile);
$attachment['extension'] = str_replace('.', '', \TorrentPier\TorrServerAPI::M3U['extension']);
}
DB()->sql_freeresult($result);
@ -161,7 +151,7 @@ if (!$authorised) {
$datastore->rm('cat_forums');
// Check tor status
if (!IS_AM && ($attachment['mimetype'] === TORRENT_MIMETYPE)) {
if (!IS_AM && str_contains($attachment['mimetype'], 'bittorrent')) {
$sql = 'SELECT tor_status, poster_id FROM ' . BB_BT_TORRENTS . ' WHERE attach_id = ' . (int)$attachment['attach_id'];
if (!($result = DB()->sql_query($sql))) {
@ -170,7 +160,7 @@ if (!IS_AM && ($attachment['mimetype'] === TORRENT_MIMETYPE)) {
$row = DB()->sql_fetchrow($result);
if (isset(config()->get('tor_frozen')[$row['tor_status']]) && !(isset(config()->get('tor_frozen_author_download')[$row['tor_status']]) && $userdata['user_id'] === $row['poster_id'])) {
if (isset($bb_cfg['tor_frozen'][$row['tor_status']]) && !(isset($bb_cfg['tor_frozen_author_download'][$row['tor_status']]) && $userdata['user_id'] === $row['poster_id'])) {
bb_die($lang['TOR_STATUS_FORBIDDEN'] . $lang['TOR_STATUS_NAME'][$row['tor_status']]);
}
@ -204,7 +194,7 @@ if (isset($download_mode[$attachment['extension']])) {
}
// Update download count
if (!$m3u && !$thumbnail && is_file(realpath($upload_dir . '/' . $attachment['physical_filename']))) {
if (!$thumbnail && is_file(realpath($upload_dir . '/' . $attachment['physical_filename']))) {
$sql = 'UPDATE ' . BB_ATTACHMENTS_DESC . ' SET download_count = download_count + 1 WHERE attach_id = ' . (int)$attachment['attach_id'];
if (!DB()->sql_query($sql)) {
@ -219,7 +209,7 @@ switch ($download_mode) {
header('Location: ' . $url);
exit;
case INLINE_LINK:
if (IS_GUEST && !config()->get('captcha.disabled') && !bb_captcha('check')) {
if (IS_GUEST && !$bb_cfg['captcha']['disabled'] && !bb_captcha('check')) {
global $template;
$redirect_url = $_POST['redirect_url'] ?? $_SERVER['HTTP_REFERER'] ?? '/';

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,8 +11,8 @@ define('BB_SCRIPT', 'dl_list');
require __DIR__ . '/common.php';
$forum_id = $_REQUEST[POST_FORUM_URL] ?? 0;
$topic_id = $_REQUEST[POST_TOPIC_URL] ?? 0;
$forum_id = isset($_REQUEST[POST_FORUM_URL]) ? (int)$_REQUEST[POST_FORUM_URL] : 0;
$topic_id = isset($_REQUEST[POST_TOPIC_URL]) ? (int)$_REQUEST[POST_TOPIC_URL] : 0;
$mode = isset($_REQUEST['mode']) ? (string)$_REQUEST['mode'] : '';
$confirmed = isset($_POST['confirm']);
@ -52,7 +52,7 @@ $user->session_start();
set_die_append_msg();
// Check if user logged in
if (IS_GUEST) {
if (!$userdata['session_logged_in']) {
redirect(LOGIN_URL . "?redirect=$redirect_type&$redirect");
}
@ -79,7 +79,7 @@ if ($mode == 'dl_delete' && $topic_id) {
if (!$confirmed) {
$hidden_fields = [
POST_TOPIC_URL => $topic_id,
't' => $topic_id,
'mode' => 'dl_delete',
];

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -34,11 +34,11 @@ if ($mode === 'get_feed_url' && ($type === 'f' || $type === 'u') && $id >= 0) {
bb_simple_die($lang['ATOM_ERROR'] . ' #1');
}
}
if (is_file(config()->get('atom.path') . '/f/' . $id . '.atom') && filemtime(config()->get('atom.path') . '/f/' . $id . '.atom') > $timecheck) {
redirect(config()->get('atom.url') . '/f/' . $id . '.atom');
if (is_file($bb_cfg['atom']['path'] . '/f/' . $id . '.atom') && filemtime($bb_cfg['atom']['path'] . '/f/' . $id . '.atom') > $timecheck) {
redirect($bb_cfg['atom']['url'] . '/f/' . $id . '.atom');
} else {
if (\TorrentPier\Legacy\Atom::update_forum_feed($id, $forum_data)) {
redirect(config()->get('atom.url') . '/f/' . $id . '.atom');
redirect($bb_cfg['atom']['url'] . '/f/' . $id . '.atom');
} else {
bb_simple_die($lang['ATOM_NO_FORUM']);
}
@ -52,11 +52,11 @@ if ($mode === 'get_feed_url' && ($type === 'f' || $type === 'u') && $id >= 0) {
if (!$username = get_username($id)) {
bb_simple_die($lang['ATOM_ERROR'] . ' #3');
}
if (is_file(config()->get('atom.path') . '/u/' . floor($id / 5000) . '/' . ($id % 100) . '/' . $id . '.atom') && filemtime(config()->get('atom.path') . '/u/' . floor($id / 5000) . '/' . ($id % 100) . '/' . $id . '.atom') > $timecheck) {
redirect(config()->get('atom.url') . '/u/' . floor($id / 5000) . '/' . ($id % 100) . '/' . $id . '.atom');
if (is_file($bb_cfg['atom']['path'] . '/u/' . floor($id / 5000) . '/' . ($id % 100) . '/' . $id . '.atom') && filemtime($bb_cfg['atom']['path'] . '/u/' . floor($id / 5000) . '/' . ($id % 100) . '/' . $id . '.atom') > $timecheck) {
redirect($bb_cfg['atom']['url'] . '/u/' . floor($id / 5000) . '/' . ($id % 100) . '/' . $id . '.atom');
} else {
if (\TorrentPier\Legacy\Atom::update_user_feed($id, $username)) {
redirect(config()->get('atom.url') . '/u/' . floor($id / 5000) . '/' . ($id % 100) . '/' . $id . '.atom');
redirect($bb_cfg['atom']['url'] . '/u/' . floor($id / 5000) . '/' . ($id % 100) . '/' . $id . '.atom');
} else {
bb_simple_die($lang['ATOM_NO_USER']);
}

View file

@ -2,42 +2,37 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
define('BB_SCRIPT', 'filelist');
require __DIR__ . '/common.php';
// Start session management
$user->session_start();
if (config()->get('bt_disable_dht') && IS_GUEST) {
bb_die($lang['BT_PRIVATE_TRACKER'], 403);
if ($bb_cfg['bt_disable_dht'] && IS_GUEST) {
bb_simple_die($lang['BT_PRIVATE_TRACKER'], 403);
}
$topic_id = isset($_GET[POST_TOPIC_URL]) ? (int)$_GET[POST_TOPIC_URL] : 0;
$topic_id = !empty($_GET['topic']) ? (int)$_GET['topic'] : false;
if (!$topic_id) {
bb_die($lang['INVALID_TOPIC_ID'], 404);
bb_simple_die($lang['INVALID_TOPIC_ID'], 404);
}
$sql = 'SELECT t.forum_id, t.attach_id, t.info_hash, t.info_hash_v2, t.size, ad.physical_filename
$sql = 'SELECT t.attach_id, t.info_hash, t.info_hash_v2, t.size, ad.physical_filename
FROM ' . BB_BT_TORRENTS . ' t
LEFT JOIN ' . BB_ATTACHMENTS_DESC . ' ad
ON t.attach_id = ad.attach_id
WHERE t.topic_id = ' . $topic_id . '
LIMIT 1';
if (!$row = DB()->fetch_row($sql)) {
bb_die($lang['INVALID_TOPIC_ID_DB'], 404);
}
$row = DB()->fetch_row($sql);
// Check rights
$is_auth = auth(AUTH_ALL, $row['forum_id'], $userdata);
if (!$is_auth['auth_view']) {
bb_die($lang['SORRY_AUTH_VIEW_ATTACH'], 403);
if (empty($row['physical_filename'])) {
bb_simple_die($lang['INVALID_TOPIC_ID_DB'], 404);
}
// Protocol meta
@ -50,12 +45,14 @@ $t_files_field = $meta_v2 ? 'getFileTree' : 'getFiles';
$t_hash_field = $meta_v2 ? 'piecesRoot' : 'sha1';
$file_path = get_attachments_dir() . '/' . $row['physical_filename'];
if (!is_file($file_path)) {
bb_die($lang['TOR_NOT_FOUND'], 410);
bb_simple_die($lang['TOR_NOT_FOUND'], 410);
}
$file_contents = file_get_contents($file_path);
if (config()->get('flist_max_files')) {
if ($bb_cfg['flist_max_files']) {
$filetree_pos = $meta_v2 ? strpos($file_contents, '9:file tree') : false;
$files_pos = $meta_v1 ? strpos($file_contents, '5:files', $filetree_pos) : false;
@ -65,53 +62,161 @@ if (config()->get('flist_max_files')) {
$file_count = substr_count($file_contents, '6:length', $files_pos);
}
if ($file_count > config()->get('flist_max_files')) {
bb_die(sprintf($lang['BT_FLIST_LIMIT'], config()->get('flist_max_files'), $file_count), 410);
if ($file_count > $bb_cfg['flist_max_files']) {
bb_simple_die(sprintf($lang['BT_FLIST_LIMIT'], $bb_cfg['flist_max_files'], $file_count), 410);
}
}
try {
$torrent = \Arokettu\Torrent\TorrentFile::loadFromString($file_contents);
} catch (\Exception $e) {
bb_die(htmlCHR("{$lang['TORFILE_INVALID']}: {$e->getMessage()}"), 410);
bb_simple_die(htmlCHR("{$lang['TORFILE_INVALID']}: {$e->getMessage()}"), 410);
}
if (IS_GUEST && $torrent->isPrivate()) {
bb_die($lang['BT_PRIVATE_TORRENT'], 403);
bb_simple_die($lang['BT_PRIVATE_TORRENT'], 403);
}
// Get torrent files
$files = $torrent->$t_version_field()->$t_files_field();
if ($meta_v2) {
if ($meta_v1 && $meta_v2) {
$files = new \RecursiveIteratorIterator($files); // Flatten the list
}
$files_count = 0;
$allFiles = '';
foreach ($files as $file) {
$files_count++;
$row_class = ($files_count % 2) ? 'row1' : 'row2';
$template->assign_block_vars('filelist', [
'ROW_NUMBER' => $files_count,
'ROW_CLASS' => $row_class,
'FILE_PATH' => clean_tor_dirname(implode('/', $file->path)),
'FILE_LENGTH' => humn_size($file->length, 2),
'FILE_HASH' => $file->$t_hash_field ?? '-'
]);
$allFiles .= '<tr><td>' . clean_tor_dirname(implode('/', $file->path)) . '</td><td>' . humn_size($file->length, 2) . '</td><td>' . $file->$t_hash_field . '</td></tr>';
}
$torrent_name = !empty($t_name = $torrent->getName()) ? str_short(htmlCHR($t_name), 200) : $lang['UNKNOWN'];
$torrent_size = humn_size($row['size'], 2);
$data = [
'name' => !empty($t_name = $torrent->getName()) ? htmlCHR(substr($t_name, 0, 255)) : 'undefined',
'client' => !empty($creator = $torrent->getCreatedBy()) ? htmlCHR(substr($creator, 0, 20)) : 'unknown client',
'date' => (!empty($dt = $torrent->getCreationDate()) && is_numeric($creation_date = $dt->getTimestamp())) ? date('d-M-Y H:i (e)', $creation_date) : 'unknown',
'size' => humn_size($row['size'], 2),
'file_count' => iterator_count($files),
'site_url' => FULL_URL,
'topic_url' => TOPIC_URL . $topic_id,
];
// Output page
$template->assign_vars([
'PAGE_TITLE' => "$torrent_name (" . $torrent_size . ")",
'FILES_COUNT' => sprintf($lang['BT_FLIST_FILE_PATH'], declension(iterator_count($files), 'files')),
'TORRENT_CREATION_DATE' => (!empty($dt = $torrent->getCreationDate()) && is_numeric($creation_date = $dt->getTimestamp())) ? date('d-M-Y H:i (e)', $creation_date) : $lang['UNKNOWN'],
'TORRENT_CLIENT' => !empty($creator = $torrent->getCreatedBy()) ? htmlCHR($creator) : $lang['UNKNOWN'],
'TORRENT_PRIVATE' => $torrent->isPrivate() ? $lang['YES'] : $lang['NO'],
header('Cache-Control: public, max-age=3600');
'BTMR_NOTICE' => sprintf($lang['BT_FLIST_BTMR_NOTICE'], 'https://github.com/kovalensky/tmrr'),
'U_TOPIC' => TOPIC_URL . $topic_id,
]);
echo <<<EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=0.1, maximum-scale=1.0" />
<meta name="robots" content="index" />
<meta name="description" content="File listing for topic - $topic_id | {$data['name']} ({$data['size']})" />
<meta property="og:description" content="File listing for topic - $topic_id | {$data['name']} ({$data['size']})" />
<meta property="og:site_name" content="{$bb_cfg['sitename']}" />
<meta name="generator" content="TorrentPier" />
<meta name="version" content="{$bb_cfg['tp_version']}" />
<link rel="shortcut icon" href="favicon.png" type="image/x-icon" />
<link rel="search" type="application/opensearchdescription+xml" href="{$data['site_url']}opensearch_desc.xml" title="{$bb_cfg['sitename']} (Forum)" />
<link rel="search" type="application/opensearchdescription+xml" href="{$data['site_url']}opensearch_desc_bt.xml" title="{$bb_cfg['sitename']} (Tracker)" />
print_page('filelist.tpl');
<title>{$data['name']} ({$data['size']}) | {$bb_cfg['sitename']}</title>
</head>
<body>
<style>
body {
background-color: #1f1f1f; color: #ffffff;
}
hr {
border: 0;
height: 0;
border-bottom: 1px solid #acacac;
}
table {
table-layout: auto;
border: none;
width: auto;
margin: 20px auto;
font-family: "Segoe UI", "Noto Sans", Helvetica, sans-serif;
background-color: #2c2c2c;
}
th, td {
padding: 10px;
text-align: left;
color: #acacac;
width: auto;
}
td {
border: 3px solid #353535;
}
th {
background-color: #1f1f1f;
width: auto;
}
p {
color: #b3b3b3;
}
a {
text-decoration: none;
color: #1d9100;
}
sup {
color: #aa8000;
}
.tooltip {
position: relative;
}
.tooltip .tooltiptext {
visibility: hidden;
position: absolute;
z-index: 1;
top: 0;
opacity: 0;
transition: opacity 0.7s;
width: 400px;
background-color: #111;
color: #acacac;
text-align: left;
border-radius: 5px;
padding: 5px;
}
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 0.97;
}
</style>
<a href="{$data['site_url']}{$data['topic_url']}" style="font-family: monospace; color: #569904;">&larr; Back to the topic</a>
<center>
<h2 style="color: #b3b3b3; font-family: monospace;">Name: {$data['name']} | Date: {$data['date']} | Size: {$data['size']}</h2>
<p>
<p style="font-family: Calibri, sans-serif;">Created by: <i title="Torrent client's name">{$data['client']}</i></p>
</p>
<hr>
<table>
<tr>
<th>Path ({$data['file_count']} files)</th>
<th>Size</th>
<th class="tooltip" style="width: auto;">
BTMR hash
<sup>?
<span class="tooltiptext">
BitTorrent Merkle Root is a hash of a file embedded in torrents with BitTorrent v2 support, tracker users can extract, calculate them, also download deduplicated torrents using desktop tools such as
<a href="https://github.com/kovalensky/tmrr" target="_blank" referrerpolicy="origin">Torrent Merkle Root Reader.</a>
</span>
</sup>
</th>
</tr>
{$allFiles}
</table>
<p style="color: #b3b3b3; font-family: Calibri, sans-serif;">Generated by <a href="https://github.com/torrentpier/torrentpier" target="_blank" referrerpolicy="origin" title="Bull-powered BitTorrent tracker engine">TorrentPier</a></p>
</center>
</body>
</html>
EOF;

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -24,7 +24,7 @@ set_die_append_msg();
$group_id = isset($_REQUEST[POST_GROUPS_URL]) ? (int)$_REQUEST[POST_GROUPS_URL] : null;
$start = isset($_REQUEST['start']) ? abs((int)$_REQUEST['start']) : 0;
$per_page = config()->get('group_members_per_page');
$per_page = $bb_cfg['group_members_per_page'];
$view_mode = isset($_REQUEST['view']) ? (string)$_REQUEST['view'] : null;
$rel_limit = 50;
@ -103,7 +103,7 @@ if (!$group_id) {
$options = '';
foreach ($params as $name => $data) {
$text = str_short(rtrim(htmlCHR($name)), HTML_SELECT_MAX_LENGTH);
$text = htmlCHR(str_short(rtrim($name), HTML_SELECT_MAX_LENGTH));
$members = ($data['m']) ? $lang['MEMBERS_IN_GROUP'] . ': ' . $data['m'] : $lang['NO_GROUP_MEMBERS'];
$candidates = ($data['c']) ? $lang['PENDING_MEMBERS'] . ': ' . $data['c'] : $lang['NO_PENDING_GROUP_MEMBERS'];
@ -168,7 +168,7 @@ if (!$group_id) {
\TorrentPier\Legacy\Group::add_user_into_group($group_id, $userdata['user_id'], 1, TIMENOW);
if (config()->get('group_send_email')) {
if ($bb_cfg['group_send_email']) {
// Sending email
$emailer = new TorrentPier\Emailer();
@ -224,7 +224,7 @@ if (!$group_id) {
\TorrentPier\Legacy\Group::add_user_into_group($group_id, $row['user_id']);
if (config()->get('group_send_email')) {
if ($bb_cfg['group_send_email']) {
// Sending email
$emailer = new TorrentPier\Emailer();
@ -273,10 +273,10 @@ if (!$group_id) {
}
}
// Email users when they are approved
if (!empty($_POST['approve']) && config()->get('group_send_email')) {
if (!empty($_POST['approve']) && $bb_cfg['group_send_email']) {
$sql_select = "SELECT username, user_email, user_lang
FROM " . BB_USERS . "
WHERE user_id IN($sql_in)";
FROM " . BB_USERS . "
WHERE user_id IN($sql_in)";
if (!$result = DB()->sql_query($sql_select)) {
bb_die('Could not get user email information');
@ -396,7 +396,7 @@ if (!$group_id) {
'U_SEARCH_RELEASES' => "tracker.php?srg=$group_id",
'U_GROUP_RELEASES' => GROUP_URL . $group_id . "&view=releases",
'U_GROUP_MEMBERS' => GROUP_URL . $group_id . "&view=members",
'U_GROUP_CONFIG' => "group_edit.php?" . POST_GROUPS_URL . "=$group_id",
'U_GROUP_CONFIG' => "group_edit.php?g=$group_id",
'RELEASE_GROUP' => (bool)$group_info['release_group'],
'GROUP_TYPE' => $group_type,
@ -573,7 +573,7 @@ if (!$group_id) {
$template->assign_block_vars('pending', [
'ROW_CLASS' => $row_class,
'AVATAR_IMG' => $pending_info['avatar'],
'USER' => profile_url($member),
'USER' => profile_url($pending_info),
'FROM' => $pending_info['from'],
'JOINED' => $pending_info['joined'],
'JOINED_RAW' => $pending_info['joined_raw'],

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -35,10 +35,10 @@ if ($group_id) {
if ($is_moderator) {
// Avatar
if ($submit) {
if (!empty($_FILES['avatar']['name']) && config()->get('group_avatars.up_allowed')) {
if (!empty($_FILES['avatar']['name']) && $bb_cfg['group_avatars']['up_allowed']) {
$upload = new TorrentPier\Legacy\Common\Upload();
if ($upload->init(config()->get('group_avatars'), $_FILES['avatar']) and $upload->store('avatar', ['user_id' => GROUP_AVATAR_MASK . $group_id, 'avatar_ext_id' => $group_info['avatar_ext_id']])) {
if ($upload->init($bb_cfg['group_avatars'], $_FILES['avatar']) and $upload->store('avatar', ['user_id' => GROUP_AVATAR_MASK . $group_id, 'avatar_ext_id' => $group_info['avatar_ext_id']])) {
$avatar_ext_id = (int)$upload->file_ext_id;
DB()->query("UPDATE " . BB_GROUPS . " SET avatar_ext_id = $avatar_ext_id WHERE group_id = $group_id LIMIT 1");
} else {
@ -76,7 +76,7 @@ if ($is_moderator) {
'S_HIDDEN_FIELDS' => $s_hidden_fields,
'S_GROUP_CONFIG_ACTION' => "group_edit.php?" . POST_GROUPS_URL . "=$group_id",
'AVATAR_EXPLAIN' => sprintf($lang['AVATAR_EXPLAIN'], config()->get('group_avatars.max_width'), config()->get('group_avatars.max_height'), humn_size(config()->get('group_avatars.max_size'))),
'AVATAR_EXPLAIN' => sprintf($lang['AVATAR_EXPLAIN'], $bb_cfg['group_avatars']['max_width'], $bb_cfg['group_avatars']['max_height'], humn_size($bb_cfg['group_avatars']['max_size'])),
'AVATAR_IMG' => get_avatar(GROUP_AVATAR_MASK . $group_id, $group_info['avatar_ext_id']),
]);

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -31,25 +31,18 @@ $datastore->enqueue([
'cat_forums'
]);
if (config()->get('show_latest_news')) {
$datastore->enqueue([
'latest_news'
]);
if ($bb_cfg['show_latest_news']) {
$datastore->enqueue('latest_news');
}
if (config()->get('show_network_news')) {
$datastore->enqueue([
'network_news'
]);
if ($bb_cfg['show_network_news']) {
$datastore->enqueue('network_news');
}
// Init userdata
$user->session_start();
// Set meta description
$page_cfg['meta_description'] = config()->get('site_desc');
// Init main vars
$viewcat = isset($_GET[POST_CAT_URL]) ? (int)$_GET[POST_CAT_URL] : 0;
$viewcat = isset($_GET['c']) ? (int)$_GET['c'] : 0;
$lastvisit = IS_GUEST ? TIMENOW : $userdata['user_lastvisit'];
// Caching output
@ -57,7 +50,7 @@ $req_page = 'index_page';
$req_page .= $viewcat ? "_c{$viewcat}" : '';
define('REQUESTED_PAGE', $req_page);
caching_output(IS_GUEST, 'send', REQUESTED_PAGE . '_guest_' . config()->get('default_lang'));
caching_output(IS_GUEST, 'send', REQUESTED_PAGE . '_guest_' . $bb_cfg['default_lang']);
$hide_cat_opt = isset($user->opt_js['h_cat']) ? (string)$user->opt_js['h_cat'] : 0;
$hide_cat_user = array_flip(explode('-', $hide_cat_opt));
@ -68,15 +61,13 @@ $tracking_topics = get_tracks('topic');
$tracking_forums = get_tracks('forum');
// Statistics
$stats = $datastore->get('stats');
if ($stats === false) {
if (!$stats = $datastore->get('stats')) {
$datastore->update('stats');
$stats = $datastore->get('stats');
}
// Forums data
$forums = $datastore->get('cat_forums');
if ($forums === false) {
if (!$forums = $datastore->get('cat_forums')) {
$datastore->update('cat_forums');
$forums = $datastore->get('cat_forums');
}
@ -85,7 +76,6 @@ $forum_name_html = $forums['forum_name_html'];
$anon = GUEST_UID;
$excluded_forums_csv = $user->get_excluded_forums(AUTH_VIEW);
$excluded_forums_array = $excluded_forums_csv ? explode(',', $excluded_forums_csv) : [];
$only_new = $user->opt_js['only_new'];
// Validate requested category id
@ -179,8 +169,7 @@ if (!$cat_forums = CACHE('bb_cache')->get($cache_name)) {
// Obtain list of moderators
$moderators = [];
$mod = $datastore->get('moderators');
if ($mod === false) {
if (!$mod = $datastore->get('moderators')) {
$datastore->update('moderators');
$mod = $datastore->get('moderators');
}
@ -262,7 +251,7 @@ foreach ($cat_forums as $cid => $c) {
'LAST_TOPIC_ID' => $f['last_topic_id'],
'LAST_TOPIC_TIP' => $f['last_topic_title'],
'LAST_TOPIC_TITLE' => str_short($f['last_topic_title'], $last_topic_max_len),
'LAST_POST_TIME' => bb_date($f['last_post_time'], config()->get('last_post_date_format')),
'LAST_POST_TIME' => bb_date($f['last_post_time'], $bb_cfg['last_post_date_format']),
'LAST_POST_USER' => profile_url(['username' => str_short($f['last_post_username'], 15), 'user_id' => $f['last_post_user_id'], 'user_rank' => $f['last_post_user_rank']]),
]);
}
@ -278,7 +267,7 @@ $template->assign_vars([
'TOTAL_TOPICS' => sprintf($lang['POSTED_TOPICS_TOTAL'], $stats['topiccount']),
'TOTAL_POSTS' => sprintf($lang['POSTED_ARTICLES_TOTAL'], $stats['postcount']),
'TOTAL_USERS' => sprintf($lang['REGISTERED_USERS_TOTAL'], $stats['usercount']),
'TOTAL_GENDER' => config()->get('gender') ? sprintf(
'TOTAL_GENDER' => $bb_cfg['gender'] ? sprintf(
$lang['USERS_TOTAL_GENDER'],
$stats['male'],
$stats['female'],
@ -287,22 +276,22 @@ $template->assign_vars([
'NEWEST_USER' => sprintf($lang['NEWEST_USER'], profile_url($stats['newestuser'])),
// Tracker stats
'TORRENTS_STAT' => config()->get('tor_stats') ? sprintf(
'TORRENTS_STAT' => $bb_cfg['tor_stats'] ? sprintf(
$lang['TORRENTS_STAT'],
$stats['torrentcount'],
humn_size($stats['size'])
) : '',
'PEERS_STAT' => config()->get('tor_stats') ? sprintf(
'PEERS_STAT' => $bb_cfg['tor_stats'] ? sprintf(
$lang['PEERS_STAT'],
$stats['peers'],
$stats['seeders'],
$stats['leechers']
) : '',
'SPEED_STAT' => config()->get('tor_stats') ? sprintf(
'SPEED_STAT' => $bb_cfg['tor_stats'] ? sprintf(
$lang['SPEED_STAT'],
humn_size($stats['speed']) . '/s'
) : '',
'SHOW_MOD_INDEX' => config()->get('show_mod_index'),
'SHOW_MOD_INDEX' => $bb_cfg['show_mod_index'],
'FORUM_IMG' => $images['forum'],
'FORUM_NEW_IMG' => $images['forum_new'],
'FORUM_LOCKED_IMG' => $images['forum_locked'],
@ -315,21 +304,20 @@ $template->assign_vars([
'U_SEARCH_SELF_BY_MY' => "search.php?uid={$userdata['user_id']}&amp;o=1",
'U_SEARCH_LATEST' => 'search.php?search_id=latest',
'U_SEARCH_UNANSWERED' => 'search.php?search_id=unanswered',
'U_ATOM_FEED' => is_file(config()->get('atom.path') . '/f/0.atom') ? make_url(config()->get('atom.url') . '/f/0.atom') : false,
'U_ATOM_FEED' => is_file($bb_cfg['atom']['path'] . '/f/0.atom') ? make_url($bb_cfg['atom']['url'] . '/f/0.atom') : false,
'SHOW_LAST_TOPIC' => $show_last_topic,
'BOARD_START' => config()->get('show_board_start_index') ? ($lang['BOARD_STARTED'] . ':&nbsp;' . '<b>' . bb_date(config()->get('board_startdate')) . '</b>') : false,
'BOARD_START' => $bb_cfg['show_board_start_index'] ? ($lang['BOARD_STARTED'] . ':&nbsp;' . '<b>' . bb_date($bb_cfg['board_startdate']) . '</b>') : false,
]);
// Set tpl vars for bt_userdata
if (config()->get('bt_show_dl_stat_on_index') && !IS_GUEST) {
if ($bb_cfg['bt_show_dl_stat_on_index'] && !IS_GUEST) {
show_bt_userdata($userdata['user_id']);
}
// Latest news
if (config()->get('show_latest_news')) {
$latest_news = $datastore->get('latest_news');
if ($latest_news === false) {
if ($bb_cfg['show_latest_news']) {
if (!$latest_news = $datastore->get('latest_news')) {
$datastore->update('latest_news');
$latest_news = $datastore->get('latest_news');
}
@ -337,13 +325,9 @@ if (config()->get('show_latest_news')) {
$template->assign_vars(['SHOW_LATEST_NEWS' => true]);
foreach ($latest_news as $news) {
if (in_array($news['forum_id'], $excluded_forums_array)) {
continue;
}
$template->assign_block_vars('news', [
'NEWS_TOPIC_ID' => $news['topic_id'],
'NEWS_TITLE' => str_short(censor()->censorString($news['topic_title']), config()->get('max_news_title')),
'NEWS_TITLE' => str_short($wordCensor->censorString($news['topic_title']), $bb_cfg['max_news_title']),
'NEWS_TIME' => bb_date($news['topic_time'], 'd-M', false),
'NEWS_IS_NEW' => is_unread($news['topic_time'], $news['topic_id'], $news['forum_id']),
]);
@ -351,9 +335,8 @@ if (config()->get('show_latest_news')) {
}
// Network news
if (config()->get('show_network_news')) {
$network_news = $datastore->get('network_news');
if ($network_news === false) {
if ($bb_cfg['show_network_news']) {
if (!$network_news = $datastore->get('network_news')) {
$datastore->update('network_news');
$network_news = $datastore->get('network_news');
}
@ -361,20 +344,16 @@ if (config()->get('show_network_news')) {
$template->assign_vars(['SHOW_NETWORK_NEWS' => true]);
foreach ($network_news as $net) {
if (in_array($net['forum_id'], $excluded_forums_array)) {
continue;
}
$template->assign_block_vars('net', [
'NEWS_TOPIC_ID' => $net['topic_id'],
'NEWS_TITLE' => str_short(censor()->censorString($net['topic_title']), config()->get('max_net_title')),
'NEWS_TITLE' => str_short($wordCensor->censorString($net['topic_title']), $bb_cfg['max_net_title']),
'NEWS_TIME' => bb_date($net['topic_time'], 'd-M', false),
'NEWS_IS_NEW' => is_unread($net['topic_time'], $net['topic_id'], $net['forum_id']),
]);
}
}
if (config()->get('birthday_check_day') && config()->get('birthday_enabled')) {
if ($bb_cfg['birthday_check_day'] && $bb_cfg['birthday_enabled']) {
$week_list = $today_list = [];
$week_all = $today_all = false;
@ -388,9 +367,9 @@ if (config()->get('birthday_check_day') && config()->get('birthday_enabled')) {
$week_list[] = profile_url($week) . ' <span class="small">(' . birthday_age(date('Y-m-d', strtotime('-1 year', strtotime($week['user_birthday'])))) . ')</span>';
}
$week_all = $week_all ? '&nbsp;<a class="txtb" href="#" onclick="ajax.exec({action: \'index_data\', mode: \'birthday_week\'}); return false;" title="' . $lang['ALL'] . '">...</a>' : '';
$week_list = sprintf($lang['BIRTHDAY_WEEK'], config()->get('birthday_check_day'), implode(', ', $week_list)) . $week_all;
$week_list = sprintf($lang['BIRTHDAY_WEEK'], $bb_cfg['birthday_check_day'], implode(', ', $week_list)) . $week_all;
} else {
$week_list = sprintf($lang['NOBIRTHDAY_WEEK'], config()->get('birthday_check_day'));
$week_list = sprintf($lang['NOBIRTHDAY_WEEK'], $bb_cfg['birthday_check_day']);
}
if (!empty($stats['birthday_today_list'])) {

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -16,9 +16,8 @@ $user->session_start();
$info = [];
$htmlDir = LANG_DIR . 'html/';
$show = isset($_REQUEST['show']) ? (string)$_REQUEST['show'] : '';
switch ($show) {
switch ((string)$_REQUEST['show'] ?? 'not_found') {
case 'advert':
$info['title'] = $lang['ADVERT'];
$info['src'] = 'advert.html';
@ -44,7 +43,7 @@ switch ($show) {
$require = is_file($htmlDir . $info['src']) ? ($htmlDir . $info['src']) : false;
$template->assign_vars([
'PAGE_TITLE' => mb_strtoupper($info['title'], DEFAULT_CHARSET),
'PAGE_TITLE' => mb_strtoupper($info['title'], 'UTF-8'),
'REQUIRE' => $require ? file_get_contents($require) : $lang['NOT_FOUND'],
]);

View file

@ -1,331 +0,0 @@
<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
define('BB_ROOT', __DIR__ . DIRECTORY_SEPARATOR);
define('BB_PATH', BB_ROOT);
// Check CLI mode
if (PHP_SAPI != 'cli') {
die('Please run <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">php ' . basename(__FILE__) . '</code> in CLI mode');
}
// Get all constants
require_once BB_ROOT . 'library/defines.php';
// Include CLI functions
require INC_DIR . '/functions_cli.php';
/**
* System requirements
*/
const CHECK_REQUIREMENTS = [
'php_min_version' => '8.2.0',
'ext_list' => [
'json',
'curl',
'readline',
'mysqli',
'bcmath',
'mbstring',
'intl',
'xml',
'xmlwriter',
'zip',
'gd'
],
];
// Welcoming message
out("--- TorrentPier Installer ---\n", 'info');
// Checking extensions
out("- Checking installed extensions...", 'info');
// [1] Check PHP Version
if (!version_compare(PHP_VERSION, CHECK_REQUIREMENTS['php_min_version'], '>=')) {
out("- TorrentPier requires PHP version " . CHECK_REQUIREMENTS['php_min_version'] . "+ Your PHP version " . PHP_VERSION, 'warning');
}
// [2] Check installed PHP Extensions on server
foreach (CHECK_REQUIREMENTS['ext_list'] as $ext) {
if (!extension_loaded($ext)) {
out("- ext-$ext not installed. Check out php.ini file", 'error');
if (!defined('EXTENSIONS_NOT_INSTALLED')) {
define('EXTENSIONS_NOT_INSTALLED', true);
}
} else {
out("- ext-$ext installed!");
}
}
if (!defined('EXTENSIONS_NOT_INSTALLED')) {
out("- All extensions are installed!\n", 'success');
} else {
exit;
}
// Check if already installed
if (is_file(BB_ROOT . '.env')) {
out('- TorrentPier already installed', 'warning');
echo 'Are you sure want to re-install TorrentPier? [y/N]: ';
if (str_starts_with(mb_strtolower(trim(readline())), 'y')) {
out("\n- Re-install process started...", 'info');
// environment
if (is_file(BB_ROOT . '.env')) {
if (unlink(BB_ROOT . '.env')) {
out('- Environment file successfully removed!');
} else {
out('- Cannot remove environment (.env) file. Delete it manually', 'error');
exit;
}
}
// composer.phar
if (is_file(BB_ROOT . 'composer.phar')) {
if (unlink(BB_ROOT . 'composer.phar')) {
out("- composer.phar file successfully removed!");
} else {
out('- Cannot remove composer.phar file. Delete it manually', 'error');
exit;
}
}
// composer dir
if (is_dir(BB_ROOT . 'vendor')) {
removeDir(BB_ROOT . 'vendor', true);
if (!is_dir(BB_ROOT . 'vendor')) {
out("- Composer directory successfully removed!");
} else {
out('- Cannot remove Composer directory. Delete it manually', 'error');
exit;
}
}
out("- Re-install process completed!\n", 'success');
out('- Starting installation...', 'info');
} else {
exit;
}
}
// Applying permissions
out("- Applying permissions for folders...", 'info');
chmod_r(BB_ROOT . 'data', 0755, 0644);
chmod_r(BB_ROOT . 'internal_data', 0755, 0644);
chmod_r(BB_ROOT . 'sitemap', 0755, 0644);
out("- Permissions successfully applied!\n", 'success');
// Check composer installation
if (!is_file(BB_ROOT . 'vendor/autoload.php')) {
out('- Hmm, it seems there are no Composer dependencies', 'info');
// Downloading composer
if (!is_file(BB_ROOT . 'composer.phar')) {
out('- Downloading Composer...', 'info');
if (copy('https://getcomposer.org/installer', BB_ROOT . 'composer-setup.php')) {
out("- Composer successfully downloaded!\n", 'success');
runProcess('php ' . BB_ROOT . 'composer-setup.php --install-dir=' . BB_ROOT);
} else {
out('- Cannot download Composer. Please, download it (composer.phar) manually', 'error');
exit;
}
if (is_file(BB_ROOT . 'composer-setup.php')) {
if (unlink(BB_ROOT . 'composer-setup.php')) {
out("- Composer installation file successfully removed!\n", 'success');
} else {
out('- Cannot remove Composer installation file (composer-setup.php). Please, delete it manually', 'warning');
}
}
} else {
out("- composer.phar file found!\n", 'success');
}
// Installing dependencies
if (is_file(BB_ROOT . 'composer.phar')) {
out('- Installing dependencies...', 'info');
runProcess('php ' . BB_ROOT . 'composer.phar install --no-interaction --no-ansi');
define('COMPOSER_COMPLETED', true);
} else {
out('- composer.phar not found. Please, download it (composer.phar) manually', 'error');
exit;
}
} else {
out('- Composer dependencies are present!', 'success');
out("- Note: Remove 'vendor' folder if you want to re-install dependencies\n");
}
// Check composer dependencies
if (defined('COMPOSER_COMPLETED')) {
if (is_file(BB_ROOT . 'vendor/autoload.php')) {
out("- Completed! Composer dependencies are installed!\n", 'success');
} else {
exit;
}
}
// Preparing ENV
if (is_file(BB_ROOT . '.env.example') && !is_file(BB_ROOT . '.env')) {
if (copy(BB_ROOT . '.env.example', BB_ROOT . '.env')) {
out("- Environment file created!\n", 'success');
} else {
out('- Cannot create environment file', 'error');
exit;
}
}
// Editing ENV file
$DB_HOST = 'localhost';
$DB_PORT = 3306;
$DB_DATABASE = '';
$DB_USERNAME = '';
$DB_PASSWORD = '';
if (is_file(BB_ROOT . '.env')) {
out("--- Configuring TorrentPier ---", 'info');
$envContent = file_get_contents(BB_ROOT . '.env');
if ($envContent === false) {
out('- Cannot open environment file', 'error');
exit;
}
$envLines = explode("\n", $envContent);
$editedLines = [];
foreach ($envLines as $line) {
if (trim($line) !== '' && !str_starts_with($line, '#')) {
$parts = explode('=', $line, 2);
$key = trim($parts[0]);
$value = (!empty($parts[1]) && $key !== 'DB_PASSWORD') ? trim($parts[1]) : '';
out("\nCurrent value of $key: $value", 'debug');
echo "Enter a new value for $key (or leave empty to not change): ";
$newValue = trim(readline());
if (!empty($newValue) || $key === 'DB_PASSWORD') {
if ($key === 'TP_HOST') {
if (!preg_match('/^https?:\/\//', $newValue)) {
$newValue = 'https://' . $newValue;
}
$newValue = parse_url($newValue, PHP_URL_HOST);
}
$line = "$key=$newValue";
$$key = $newValue;
} else {
$$key = $value;
}
}
$editedLines[] = $line;
}
$newEnvContent = implode("\n", $editedLines);
if (file_put_contents(BB_ROOT . '.env', $newEnvContent)) {
out("- TorrentPier successfully configured!\n", 'success');
} else {
out('- Cannot save environment file', 'error');
exit;
}
} else {
out('- Environment file not found', 'error');
exit;
}
if (!empty($DB_HOST) && !empty($DB_DATABASE) && !empty($DB_USERNAME)) {
out("--- Checking environment settings ---\n", 'info');
// Connecting to database
out("- Trying connect to MySQL...", 'info');
// Checking mysqli extension installed
if (!extension_loaded('mysqli')) {
out('- ext-mysqli not found. Check out php.ini file', 'error');
exit;
}
// Connect to MySQL server
try {
$conn = new mysqli($DB_HOST, $DB_USERNAME, $DB_PASSWORD, port: $DB_PORT);
} catch (mysqli_sql_exception $exception) {
out("- Connection failed: {$exception->getMessage()}", 'error');
exit;
}
if (!$conn->connect_error) {
out('- Connected successfully!', 'success');
}
// Creating database if not exist
if ($conn->query("CREATE DATABASE IF NOT EXISTS $DB_DATABASE CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci")) {
out('- Database created successfully!', 'success');
} else {
out("- Cannot create database: $DB_DATABASE", 'error');
exit;
}
$conn->select_db($DB_DATABASE);
// Close database connection - migrations will handle their own connections
$conn->close();
// Run database migrations
out('- Setting up database using migrations...', 'info');
// Check if phinx.php exists
if (!is_file(BB_ROOT . 'phinx.php')) {
out('- Migration configuration (phinx.php) not found', 'error');
exit;
}
// Run migrations
$migrationResult = runProcess('php vendor/bin/phinx migrate --configuration=' . BB_ROOT . 'phinx.php');
if ($migrationResult !== 0) {
out('- Database migration failed', 'error');
exit;
}
out("- Database setup completed!\n", 'success');
// Autofill host in robots.txt
$robots_txt_file = BB_ROOT . 'robots.txt';
if (isset($TP_HOST) && is_file($robots_txt_file)) {
$content = file_get_contents($robots_txt_file);
$content = str_replace('example.com', $TP_HOST, $content);
file_put_contents($robots_txt_file, $content);
}
if (isset($APP_ENV) && $APP_ENV === 'local') {
if (!is_file(BB_ROOT . 'library/config.local.php')) {
if (copy(BB_ROOT . 'library/config.php', BB_ROOT . 'library/config.local.php')) {
out('- Local configuration file created!', 'success');
} else {
out('- Cannot create library/config.local.php file. You can create it manually, just copy config.php and rename it to config.local.php', 'warning');
}
}
} else {
if (rename(__FILE__, __FILE__ . '_' . hash('xxh128', time()))) {
out("- Installation file renamed!", 'success');
} else {
out('- Cannot rename installation file (' . __FILE__ . '). Please, rename it manually for security reasons', 'warning');
}
}
// Cleanup...
if (is_file(BB_ROOT . '_cleanup.php')) {
out("\n--- Finishing installation (Cleanup) ---\n", 'info');
out('The cleanup process will remove:');
out('- Development documentation (README, CHANGELOG)', 'debug');
out('- Git configuration files', 'debug');
out('- CI/CD pipelines and code analysis tools', 'debug');
out('- Translation and contribution guidelines', 'debug');
echo 'Do you want to delete these files permanently? [y/N]: ';
if (str_starts_with(mb_strtolower(trim(readline())), 'y')) {
out("\n- Cleanup...", 'info');
require_once BB_ROOT . '_cleanup.php';
unlink(BB_ROOT . '_cleanup.php');
} else {
out('- Skipping...', 'info');
}
}
out("\n- Voila! Good luck & have fun!", 'success');
}

1
install/.htaccess Normal file
View file

@ -0,0 +1 @@
Require all denied

View file

@ -1,27 +0,0 @@
# Example Caddy configuration for TorrentPier
example.com {
root * /path/to/root
encode gzip zstd
php_fastcgi unix//run/php/php-fpm.sock
try_files {path} {path}/ /index.php?{query}
file_server
@blocked {
path /install/* /internal_data/* /library/*
path /.ht* /.en*
path /.git/*
path *.sql *.tpl *.db *.inc *.log *.md
}
respond @blocked 404
redir /sitemap.xml /sitemap/sitemap.xml
@html_css_js {
path *.html *.css *.js *.json *.xml *.txt
}
header @html_css_js Content-Type "{mime}; charset=utf-8"
}
# Refer to the Caddy docs for more information:
# https://caddyserver.com/docs/caddyfile

View file

@ -1,39 +0,0 @@
# Example nginx configuration for TorrentPier
server {
listen 80; # port
server_name example.com; # your domain
root /path/to/root; # folder with TorrentPier installed
index index.php;
charset utf-8;
location / {
try_files \$uri \$uri/ /index.php?\$args;
}
location ~ \/(install|internal_data|library)\/ {
return 404;
}
location ~ /\.(ht|en) {
return 404;
}
location ~ /\.git {
return 404;
}
location ~ \.(.*sql|tpl|db|inc|log|md)$ {
return 404;
}
rewrite ^/sitemap.xml$ /sitemap/sitemap.xml;
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
include fastcgi_params;
}
}

1495
install/sql/mysql.sql Normal file

File diff suppressed because it is too large Load diff

57
install/sql/ocelot.sql Normal file
View file

@ -0,0 +1,57 @@
SET SQL_MODE = "";
-- ----------------------------
-- Table structure for `bb_bt_tracker`
-- ----------------------------
DROP TABLE IF EXISTS `bb_bt_tracker`;
CREATE TABLE IF NOT EXISTS `bb_bt_tracker`
(
`peer_hash` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`topic_id` mediumint(8) unsigned NOT NULL DEFAULT '0',
`peer_id` varchar(20) NOT NULL,
`user_id` mediumint(9) NOT NULL DEFAULT '0',
`ip` varchar(42) NOT NULL DEFAULT '0',
`ipv6` varchar(32) DEFAULT NULL,
`port` smallint(5) unsigned NOT NULL DEFAULT '0',
`client` varchar(51) NOT NULL DEFAULT 'Unknown',
`seeder` tinyint(1) NOT NULL DEFAULT '0',
`releaser` tinyint(1) NOT NULL DEFAULT '0',
`tor_type` tinyint(1) NOT NULL DEFAULT '0',
`uploaded` bigint(20) unsigned NOT NULL DEFAULT '0',
`downloaded` bigint(20) unsigned NOT NULL DEFAULT '0',
`remain` bigint(20) unsigned NOT NULL DEFAULT '0',
`speed_up` mediumint(8) unsigned NOT NULL DEFAULT '0',
`speed_down` mediumint(8) unsigned NOT NULL DEFAULT '0',
`up_add` bigint(20) unsigned NOT NULL DEFAULT '0',
`down_add` bigint(20) unsigned NOT NULL DEFAULT '0',
`update_time` int(11) NOT NULL DEFAULT '0',
`complete_percent` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`peer_hash`),
KEY `topic_id` (`topic_id`),
KEY `user_id` (`user_id`)
) ENGINE = MyISAM
DEFAULT CHARSET = utf8;
-- ----------------------------
-- Records of bb_bt_tracker
-- ----------------------------
-- ----------------------------
-- Table structure for `bb_bt_tracker_snap`
-- ----------------------------
DROP TABLE IF EXISTS `bb_bt_tracker_snap`;
CREATE TABLE IF NOT EXISTS `bb_bt_tracker_snap`
(
`topic_id` mediumint(8) unsigned NOT NULL DEFAULT '0',
`seeders` mediumint(8) unsigned NOT NULL DEFAULT '0',
`leechers` mediumint(8) unsigned NOT NULL DEFAULT '0',
`speed_up` int(10) unsigned NOT NULL DEFAULT '0',
`speed_down` int(10) unsigned NOT NULL DEFAULT '0',
`complete` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`topic_id`)
) ENGINE = MyISAM
DEFAULT CHARSET = utf8;
-- ----------------------------
-- Records of bb_bt_tracker_snap
-- ----------------------------

1
internal_data/cache/.htaccess vendored Normal file
View file

@ -0,0 +1 @@
Require all denied

View file

View file

@ -0,0 +1 @@
Require all denied

View file

@ -0,0 +1 @@
Require all denied

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,7 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $lang, $user;
global $bb_cfg, $lang, $user;
if (!$mode = (string)$this->request['mode']) {
$this->ajax_die('invalid mode (empty)');

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,9 +11,9 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $userdata, $lang;
global $bb_cfg, $userdata, $lang;
if (!config()->get('callseed')) {
if (!$bb_cfg['callseed']) {
$this->ajax_die($lang['MODULE_OFF']);
}
@ -27,16 +27,14 @@ if (!$t_data = topic_info($topic_id)) {
$forum_id = $t_data['forum_id'];
if ($t_data['seeders'] >= 3) {
if ($t_data['seeders'] > 2) {
$this->ajax_die(sprintf($lang['CALLSEED_HAVE_SEED'], $t_data['seeders']));
} elseif ($t_data['call_seed_time'] >= (TIMENOW - 86400)) {
} elseif ($t_data['call_seed_time'] > (TIMENOW - 86400)) {
$time_left = delta_time($t_data['call_seed_time'] + 86400, TIMENOW, 'days');
$this->ajax_die(sprintf($lang['CALLSEED_MSG_SPAM'], $time_left));
} elseif (isset(config()->get('tor_no_tor_act')[$t_data['tor_status']])) {
$this->ajax_die($lang['NOT_AVAILABLE']);
}
$banned_users = ($get_banned_users = get_banned_users()) ? (', ' . implode(', ', $get_banned_users)) : '';
$get_banned_users = get_banned_users() ? (', ' . implode(', ', get_banned_users())) : '';
$user_list = DB()->fetch_rowset("
SELECT DISTINCT dl.user_id, u.user_opt, tr.user_id as active_dl
@ -45,7 +43,7 @@ $user_list = DB()->fetch_rowset("
LEFT JOIN " . BB_BT_TRACKER . " tr ON(tr.user_id = dl.user_id)
WHERE dl.topic_id = $topic_id
AND dl.user_status IN (" . DL_STATUS_COMPLETE . ", " . DL_STATUS_DOWN . ")
AND dl.user_id NOT IN ({$userdata['user_id']}, " . EXCLUDED_USERS . $banned_users . ")
AND dl.user_id NOT IN ({$userdata['user_id']}, " . EXCLUDED_USERS . $get_banned_users . ")
AND u.user_active = 1
GROUP BY dl.user_id
");
@ -75,7 +73,7 @@ function topic_info($topic_id)
$sql = "
SELECT
tor.poster_id, tor.forum_id, tor.attach_id, tor.call_seed_time, tor.tor_status,
tor.poster_id, tor.forum_id, tor.attach_id, tor.call_seed_time,
t.topic_title, sn.seeders
FROM " . BB_BT_TORRENTS . " tor
LEFT JOIN " . BB_TOPICS . " t USING(topic_id)

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,7 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $userdata, $lang, $log_action;
global $userdata, $bb_cfg, $lang;
if (!$attach_id = (int)$this->request['attach_id']) {
$this->ajax_die($lang['EMPTY_ATTACH_ID']);
@ -22,7 +22,7 @@ if (!$mode = (string)$this->request['mode']) {
}
$comment = false;
if (config()->get('tor_comment')) {
if ($bb_cfg['tor_comment']) {
$comment = (string)$this->request['comment'];
}
@ -44,7 +44,7 @@ switch ($mode) {
case 'status':
$new_status = (int)$this->request['status'];
// Check status validity
// Валидность статуса
if (!isset($lang['TOR_STATUS_NAME'][$new_status])) {
$this->ajax_die($lang['TOR_STATUS_FAILED']);
}
@ -55,17 +55,17 @@ switch ($mode) {
$this->ajax_die($lang['NOT_MODERATOR']);
}
// Error if same status
// Тот же статус
if ($tor['tor_status'] == $new_status) {
$this->ajax_die($lang['TOR_STATUS_DUB']);
}
// Prohibition on changing/assigning CH-status by moderator
// Запрет на изменение/присвоение CH-статуса модератором
if ($new_status == TOR_CLOSED_CPHOLD && !IS_ADMIN) {
$this->ajax_die($lang['TOR_DONT_CHANGE']);
}
// Check rights to change status
// Права на изменение статуса
if ($tor['tor_status'] == TOR_CLOSED_CPHOLD) {
if (!IS_ADMIN) {
$this->verify_mod_rights($tor['forum_id']);
@ -75,7 +75,7 @@ switch ($mode) {
$this->verify_mod_rights($tor['forum_id']);
}
// Confirmation of status change set by another moderator
// Подтверждение изменения статуса, выставленного другим модератором
if ($tor['tor_status'] != TOR_NOT_APPROVED && $tor['checked_user_id'] != $userdata['user_id'] && $tor['checked_time'] + 2 * 3600 > TIMENOW) {
if (empty($this->request['confirmed'])) {
$msg = $lang['TOR_STATUS_OF'] . " {$lang['TOR_STATUS_NAME'][$tor['tor_status']]}\n\n";
@ -87,24 +87,12 @@ switch ($mode) {
\TorrentPier\Legacy\Torrent::change_tor_status($attach_id, $new_status);
// Log action
$log_msg = sprintf($lang['TOR_STATUS_LOG_ACTION'], config()->get('tor_icons')[$new_status] . ' <b> ' . $lang['TOR_STATUS_NAME'][$new_status] . '</b>', config()->get('tor_icons')[$tor['tor_status']] . ' <b> ' . $lang['TOR_STATUS_NAME'][$tor['tor_status']] . '</b>');
if ($comment && $comment != $lang['COMMENT']) {
$log_msg .= "<br/>{$lang['COMMENT']}: <b>$comment</b>.";
}
$log_action->mod('mod_topic_change_tor_status', [
'forum_id' => $tor['forum_id'],
'topic_id' => $tor['topic_id'],
'topic_title' => $tor['topic_title'],
'log_msg' => $log_msg . '<br/>-------------',
]);
$this->response['status'] = $bb_cfg['tor_icons'][$new_status] . ' <b> ' . $lang['TOR_STATUS_NAME'][$new_status] . '</b> &middot; ' . profile_url($userdata) . ' &middot; <i>' . delta_time(TIMENOW) . $lang['TOR_BACK'] . '</i>';
$this->response['status'] = config()->get('tor_icons')[$new_status] . ' <b> ' . $lang['TOR_STATUS_NAME'][$new_status] . '</b> &middot; ' . profile_url($userdata) . ' &middot; <i>' . delta_time(TIMENOW) . $lang['TOR_BACK'] . '</i>';
if (config()->get('tor_comment') && (($comment && $comment != $lang['COMMENT']) || in_array($new_status, config()->get('tor_reply')))) {
if ($bb_cfg['tor_comment'] && (($comment && $comment != $lang['COMMENT']) || in_array($new_status, $bb_cfg['tor_reply']))) {
if ($tor['poster_id'] > 0) {
$subject = sprintf($lang['TOR_MOD_TITLE'], $tor['topic_title']);
$message = sprintf($lang['TOR_MOD_MSG'], get_username($tor['poster_id']), make_url(TOPIC_URL . $tor['topic_id']), config()->get('tor_icons')[$new_status] . ' ' . $lang['TOR_STATUS_NAME'][$new_status]);
$message = sprintf($lang['TOR_MOD_MSG'], get_username($tor['poster_id']), make_url(TOPIC_URL . $tor['topic_id']), $bb_cfg['tor_icons'][$new_status] . ' ' . $lang['TOR_STATUS_NAME'][$new_status]);
if ($comment && $comment != $lang['COMMENT']) {
$message .= "\n\n[b]" . $lang['COMMENT'] . '[/b]: ' . $comment;
@ -117,7 +105,7 @@ switch ($mode) {
break;
case 'status_reply':
if (!config()->get('tor_comment')) {
if (!$bb_cfg['tor_comment']) {
$this->ajax_die($lang['MODULE_OFF']);
}

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,7 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $userdata, $lang, $log_action;
global $userdata, $bb_cfg, $lang;
if (!isset($this->request['attach_id'])) {
$this->ajax_die($lang['EMPTY_ATTACH_ID']);
@ -19,11 +19,31 @@ if (!isset($this->request['attach_id'])) {
if (!isset($this->request['type'])) {
$this->ajax_die('empty type');
}
$attach_id = (int)$this->request['attach_id'];
$type = (string)$this->request['type'];
if (!$torrent = \TorrentPier\Legacy\Torrent::get_torrent_info($attach_id)) {
$torrent = DB()->fetch_row("
SELECT
a.post_id, d.physical_filename, d.extension, d.tracker_status,
t.topic_first_post_id,
p.poster_id, p.topic_id, p.forum_id,
f.allow_reg_tracker
FROM
" . BB_ATTACHMENTS . " a,
" . BB_ATTACHMENTS_DESC . " d,
" . BB_POSTS . " p,
" . BB_TOPICS . " t,
" . BB_FORUMS . " f
WHERE
a.attach_id = $attach_id
AND d.attach_id = $attach_id
AND p.post_id = a.post_id
AND t.topic_id = p.topic_id
AND f.forum_id = p.forum_id
LIMIT 1
");
if (!$torrent) {
$this->ajax_die($lang['INVALID_ATTACH_ID']);
}
@ -43,25 +63,12 @@ switch ($type) {
case 'unset_silver_gold':
if ($type == 'set_silver') {
$tor_type = TOR_TYPE_SILVER;
$tor_type_lang = $lang['SILVER'];
} elseif ($type == 'set_gold') {
$tor_type = TOR_TYPE_GOLD;
$tor_type_lang = $lang['GOLD'];
} else {
$tor_type = TOR_TYPE_DEFAULT;
$tor_type_lang = "{$lang['UNSET_GOLD_TORRENT']} / {$lang['UNSET_SILVER_TORRENT']}";
$tor_type = 0;
}
\TorrentPier\Legacy\Torrent::change_tor_type($attach_id, $tor_type);
// Log action
$log_action->mod('mod_topic_change_tor_type', [
'forum_id' => $torrent['forum_id'],
'topic_id' => $torrent['topic_id'],
'topic_title' => $torrent['topic_title'],
'log_msg' => sprintf($lang['TOR_TYPE_LOG_ACTION'], $tor_type_lang),
]);
$title = $lang['CHANGE_TOR_TYPE'];
$url = make_url(TOPIC_URL . $torrent['topic_id']);
break;
@ -89,7 +96,7 @@ switch ($type) {
$this->prompt_for_confirm($lang['DEL_MOVE_TORRENT']);
}
\TorrentPier\Legacy\Torrent::delete_torrent($attach_id);
$url = make_url("modcp.php?" . POST_TOPIC_URL . "={$torrent['topic_id']}&mode=move&sid={$userdata['session_id']}");
$url = make_url("modcp.php?t={$torrent['topic_id']}&mode=move&sid={$userdata['session_id']}");
break;
}

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -32,7 +32,7 @@ foreach ($bf['user_opt'] as $opt_name => $opt_bit) {
DB()->query("UPDATE " . BB_USERS . " SET user_opt = {$u_data['user_opt']} WHERE user_id = $user_id LIMIT 1");
// Remove data from cache
// Удаляем данные из кеша
\TorrentPier\Sessions::cache_rm_user_sessions($user_id);
$this->response['resp_html'] = $lang['SAVED'];

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -28,11 +28,11 @@ if ($rank_id != 0 && !isset($ranks[$rank_id])) {
$this->ajax_die("invalid rank_id: $rank_id");
}
DB()->query("UPDATE " . BB_USERS . " SET user_rank = $rank_id WHERE user_id = $user_id LIMIT 1");
DB()->query("UPDATE " . BB_USERS . " SET user_rank = $rank_id WHERE user_id = $user_id");
\TorrentPier\Sessions::cache_rm_user_sessions($user_id);
$user_rank = $rank_id ? '<span class="' . $ranks[$rank_id]['rank_style'] . '">' . $ranks[$rank_id]['rank_title'] . '</span>' : '';
$user_rank = ($rank_id) ? '<span class="' . $ranks[$rank_id]['rank_style'] . '">' . $ranks[$rank_id]['rank_title'] . '</span>' : '';
$this->response['html'] = $rank_id ? $lang['AWARDED_RANK'] . "<b> $user_rank </b>" : $lang['SHOT_RANK'];
$this->response['rank_name'] = $rank_id ? $user_rank : $lang['USER'];
$this->response['html'] = ($rank_id) ? $lang['AWARDED_RANK'] . "<b> $user_rank </b>" : $lang['SHOT_RANK'];
$this->response['rank_name'] = ($rank_id) ? $user_rank : $lang['USER'];

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,7 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $userdata, $lang;
global $bb_cfg, $userdata, $lang;
if (!$group_id = (int)$this->request['group_id'] or !$group_info = \TorrentPier\Legacy\Group::get_group_data($group_id)) {
$this->ajax_die($lang['NO_GROUP_ID_SPECIFIED']);
@ -51,4 +51,4 @@ switch ($mode) {
}
$value_sql = DB()->escape($value, true);
DB()->query("UPDATE " . BB_GROUPS . " SET $mode = $value_sql WHERE group_id = $group_id LIMIT 1");
DB()->query("UPDATE " . BB_GROUPS . " SET $mode = $value_sql WHERE group_id = $group_id");

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,7 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $lang;
global $bb_cfg, $lang;
if (!$user_id = (int)$this->request['user_id'] or !$profiledata = get_userdata($user_id)) {
$this->ajax_die($lang['NO_USER_ID_SPECIFIED']);
@ -55,17 +55,18 @@ switch ($field) {
break;
case 'user_gender':
if (!config()->get('gender')) {
if (!$bb_cfg['gender']) {
$this->ajax_die($lang['MODULE_OFF']);
}
if (!isset($lang['GENDER_SELECT'][$value])) {
$this->ajax_die($lang['ERROR']);
} else {
$this->response['new_value'] = $lang['GENDER_SELECT'][$value];
}
$this->response['new_value'] = $lang['GENDER_SELECT'][$value];
break;
case 'user_birthday':
if (!config()->get('birthday_enabled')) {
if (!$bb_cfg['birthday_enabled']) {
$this->ajax_die($lang['MODULE_OFF']);
}
$birthday_date = date_parse($value);
@ -73,10 +74,10 @@ switch ($field) {
if (!empty($birthday_date['year'])) {
if (strtotime($value) >= TIMENOW) {
$this->ajax_die($lang['WRONG_BIRTHDAY_FORMAT']);
} elseif (bb_date(TIMENOW, 'Y', false) - $birthday_date['year'] > config()->get('birthday_max_age')) {
$this->ajax_die(sprintf($lang['BIRTHDAY_TO_HIGH'], config()->get('birthday_max_age')));
} elseif (bb_date(TIMENOW, 'Y', false) - $birthday_date['year'] < config()->get('birthday_min_age')) {
$this->ajax_die(sprintf($lang['BIRTHDAY_TO_LOW'], config()->get('birthday_min_age')));
} elseif (bb_date(TIMENOW, 'Y', false) - $birthday_date['year'] > $bb_cfg['birthday_max_age']) {
$this->ajax_die(sprintf($lang['BIRTHDAY_TO_HIGH'], $bb_cfg['birthday_max_age']));
} elseif (bb_date(TIMENOW, 'Y', false) - $birthday_date['year'] < $bb_cfg['birthday_min_age']) {
$this->ajax_die(sprintf($lang['BIRTHDAY_TO_LOW'], $bb_cfg['birthday_min_age']));
}
}
@ -104,9 +105,20 @@ switch ($field) {
$this->response['new_value'] = $this->request['value'];
break;
case 'user_from':
case 'user_occ':
case 'user_interests':
$this->response['new_value'] = htmlCHR($value);
$value = htmlCHR($value);
$this->response['new_value'] = $value;
break;
case 'user_regdate':
case 'user_lastvisit':
$tz = TIMENOW + (3600 * $bb_cfg['board_timezone']);
if (($value = strtotime($value, $tz)) < $bb_cfg['board_startdate'] or $value > TIMENOW) {
$this->ajax_die($lang['INVALID_DATE'] . $this->request['value']);
}
$this->response['new_value'] = bb_date($value, 'Y-m-d H:i', false);
break;
case 'u_up_total':
@ -152,7 +164,7 @@ switch ($field) {
}
$value_sql = DB()->escape($value, true);
DB()->query("UPDATE $table SET $field = $value_sql WHERE user_id = $user_id LIMIT 1");
DB()->query("UPDATE $table SET $field = $value_sql WHERE user_id = $user_id");
\TorrentPier\Sessions::cache_rm_user_sessions($user_id);

View file

@ -1,154 +0,0 @@
<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $lang;
if (!config()->get('torr_server.enabled')) {
$this->ajax_die($lang['MODULE_OFF']);
}
if (config()->get('torr_server.disable_for_guest') && IS_GUEST) {
$this->ajax_die($lang['NEED_TO_LOGIN_FIRST']);
}
$attach_id = $this->request['attach_id'] ?? '';
if (empty($attach_id) || !is_numeric($attach_id)) {
$this->ajax_die($lang['INVALID_ATTACH_ID']);
}
$file_index = $this->request['file_index'] ?? '';
if (empty($file_index) || !is_numeric($file_index)) {
$this->ajax_die("Invalid file index: $file_index");
}
if (!$info_hash = (string)$this->request['info_hash'] or !ctype_xdigit($info_hash)) {
$this->ajax_die("Invalid info_hash: $info_hash");
}
$isAudio = isset($this->request['is_audio']) && $this->request['is_audio'];
// Get ffprobe info from TorrServer
$ffpInfo = (new \TorrentPier\TorrServerAPI())->getFfpInfo($info_hash, $file_index, $attach_id);
$ffpInfo = $ffpInfo->{$file_index};
if (isset($ffpInfo->streams)) {
// Video codec information
$videoCodecIndex = array_search('video', array_column($ffpInfo->streams, 'codec_type'));
if (is_int($videoCodecIndex)) {
$videoCodecInfo = $ffpInfo->streams[$videoCodecIndex];
}
// Audio codec information
$audioTracks = array_filter($ffpInfo->streams, function ($e) {
return $e->codec_type === 'audio';
});
// Audio tracks information
$audioDub = array_map(function ($stream) {
global $lang;
$result = '<span class="warnColor2">' . sprintf($lang['AUDIO_TRACK'], (!isset($stream->index) || $stream->index === 0) ? 1 : $stream->index) . '</span><br/>';
if (isset($stream->tags->language)) {
if (isset($stream->tags->title)) {
$result .= '<b>' . mb_strtoupper($stream->tags->language, DEFAULT_CHARSET) . ' (' . $stream->tags->title . ')' . '</b>';
} else {
$result .= '<b>' . mb_strtoupper($stream->tags->language, DEFAULT_CHARSET) . '</b>';
}
$result .= '<br/>';
}
if (!empty($stream->codec_name)) {
$result .= sprintf($lang['AUDIO_CODEC'], $stream->codec_long_name, mb_strtoupper($stream->codec_name, DEFAULT_CHARSET)) . '<br/>';
}
if (!empty($stream->bit_rate)) {
$result .= sprintf($lang['BITRATE'], humn_bitrate((int)$stream->bit_rate)) . '<br/>';
}
if (!empty($stream->sample_rate)) {
$result .= sprintf($lang['SAMPLE_RATE'], humn_sample_rate((int)$stream->sample_rate)) . '<br/>';
}
if (!empty($stream->channels)) {
$result .= sprintf($lang['CHANNELS'], $stream->channels) . '<br/>';
}
if (!empty($stream->channel_layout)) {
$result .= sprintf($lang['CHANNELS_LAYOUT'], $stream->channel_layout);
}
return $result;
}, $audioTracks);
// Generate output data
$data = [
'filesize' => sprintf($lang['FILESIZE'] . ': <b>%s</b>', humn_size($ffpInfo->format->size)),
'resolution' => (!$isAudio && isset($videoCodecInfo)) ? sprintf($lang['RESOLUTION'], $videoCodecInfo->width . 'x' . $videoCodecInfo->height) : '',
'video_codec' => (!$isAudio && isset($videoCodecInfo->codec_name)) ? sprintf($lang['VIDEO_CODEC'], $videoCodecInfo->codec_long_name, mb_strtoupper($videoCodecInfo->codec_name, DEFAULT_CHARSET)) : '',
'audio_dub' => implode('<hr/>', $audioDub)
];
// Validate output data
$result = '<hr/>';
if (!empty($data['resolution'])) {
$result .= $data['resolution'] . '<br/>';
}
if (!empty($data['filesize'])) {
$result .= $data['filesize'] . '<br/>';
}
if (!empty($data['video_codec'])) {
$result .= $data['video_codec'];
}
if (!empty($data['audio_dub'])) {
$result .= '<hr/>' . $data['audio_dub'];
}
$this->response['ffprobe_data'] = $result;
}
/**
* Bitrate to human-readable format
*
* @param int $bitrate
* @param string $space
* @return string
*/
function humn_bitrate(int $bitrate, string $space = '&nbsp;'): string
{
if ($bitrate >= 1000000) {
$unit = 'Mbps';
$bitrate /= 1000000;
} elseif ($bitrate >= 1000) {
$unit = 'kbps';
$bitrate /= 1000;
} else {
$unit = 'bps';
}
return sprintf('%d', commify($bitrate)) . $space . $unit;
}
/**
* Sample rate to human-readable format
*
* @param int $sample_rate
* @param string $space
* @return string
*/
function humn_sample_rate(int $sample_rate, string $space = '&nbsp;'): string
{
if ($sample_rate >= 1000000) {
$unit = 'Mhz';
} elseif ($sample_rate >= 1000) {
$unit = 'kHz';
} else {
$unit = 'Hz';
}
return sprintf('%.1f', commify($sample_rate)) . $space . $unit;
}
$this->response['file_index'] = $file_index;

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -38,18 +38,17 @@ switch ($mode) {
$href = GROUP_URL . $row['group_id'];
if (IS_ADMIN) {
$href .= "&amp;" . POST_USERS_URL . "=$user_id";
$href .= "&amp;u=$user_id";
$link = '<a href="' . $href . '" class="' . $class . '" target="_blank">' . htmlCHR($row['group_name']) . '</a>';
$html[] = $link;
} else {
// hidden group and the user himself is not a member of it
// скрытая группа и сам юзер не является ее членом
if ($row['group_type'] == GROUP_HIDDEN && !$row['can_view']) {
continue;
}
if ($row['group_moderator'] == $user->id) {
// the user himself is the moderator of this group
$class .= ' selfMod';
$href .= "&amp;" . POST_USERS_URL . "=$user_id";
$href .= "&amp;u=$user_id"; // сам юзер модератор этой группы
}
$link = '<a href="' . $href . '" class="' . $class . '" target="_blank">' . htmlCHR($row['group_name']) . '</a>';
$html[] = $link;

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,7 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $lang, $userdata, $datastore;
global $bb_cfg, $lang, $userdata, $datastore;
if (!$mode = (string)$this->request['mode']) {
$this->ajax_die('invalid mode (empty)');
@ -20,10 +20,10 @@ if (!$mode = (string)$this->request['mode']) {
$html = '';
switch ($mode) {
case 'birthday_week':
$stats = $datastore->get('stats');
$datastore->enqueue([
'stats'
]);
$stats = $datastore->get('stats');
$users = [];
@ -31,17 +31,17 @@ switch ($mode) {
foreach ($stats['birthday_week_list'] as $week) {
$users[] = profile_url($week) . ' <span class="small">(' . birthday_age(date('Y-m-d', strtotime('-1 year', strtotime($week['user_birthday'])))) . ')</span>';
}
$html = sprintf($lang['BIRTHDAY_WEEK'], config()->get('birthday_check_day'), implode(', ', $users));
$html = sprintf($lang['BIRTHDAY_WEEK'], $bb_cfg['birthday_check_day'], implode(', ', $users));
} else {
$html = sprintf($lang['NOBIRTHDAY_WEEK'], config()->get('birthday_check_day'));
$html = sprintf($lang['NOBIRTHDAY_WEEK'], $bb_cfg['birthday_check_day']);
}
break;
case 'birthday_today':
$stats = $datastore->get('stats');
$datastore->enqueue([
'stats'
]);
$stats = $datastore->get('stats');
$users = [];
@ -59,7 +59,8 @@ switch ($mode) {
$forum_id = (int)$this->request['forum_id'];
$datastore->enqueue([
'moderators'
'moderators',
'cat_forums'
]);
$moderators = [];
@ -83,80 +84,7 @@ switch ($mode) {
$datastore->rm('moderators');
break;
case 'null_ratio':
if (!config()->get('ratio_null_enabled') || !RATIO_ENABLED) {
$this->ajax_die($lang['MODULE_OFF']);
}
if (empty($this->request['confirmed'])) {
$this->prompt_for_confirm($lang['BT_NULL_RATIO_ALERT']);
}
$user_id = (int)$this->request['user_id'];
if (!IS_ADMIN && $user_id != $userdata['user_id']) {
$this->ajax_die($lang['NOT_AUTHORISED']);
}
$btu = get_bt_userdata($user_id);
$ratio_nulled = (bool)$btu['ratio_nulled'];
$user_ratio = get_bt_ratio($btu);
if (($user_ratio === null) && !IS_ADMIN) {
$this->ajax_die($lang['BT_NULL_RATIO_NONE']);
}
if ($ratio_nulled && !IS_ADMIN) {
$this->ajax_die($lang['BT_NULL_RATIO_AGAIN']);
}
if (($user_ratio >= config()->get('ratio_to_null')) && !IS_ADMIN) {
$this->ajax_die(sprintf($lang['BT_NULL_RATIO_NOT_NEEDED'], config()->get('ratio_to_null')));
}
$ratio_nulled_sql = !IS_ADMIN ? ', ratio_nulled = 1' : '';
DB()->query("UPDATE " . BB_BT_USERS . " SET u_up_total = 0, u_down_total = 0, u_up_release = 0, u_up_bonus = 0 $ratio_nulled_sql WHERE user_id = " . $user_id);
CACHE('bb_cache')->rm('btu_' . $user_id);
$this->ajax_die($lang['BT_NULL_RATIO_SUCCESS']);
break;
case 'releaser_stats':
if (IS_GUEST) {
$this->ajax_die($lang['NEED_TO_LOGIN_FIRST']);
}
$user_id = (int)$this->request['user_id'];
$sql = "
SELECT COUNT(tor.poster_id) as total_releases, SUM(tor.size) as total_size, SUM(tor.complete_count) as total_complete, SUM(ad.download_count) as total_dl_count
FROM " . BB_BT_TORRENTS . " tor
LEFT JOIN " . BB_USERS . " u ON(u.user_id = tor.poster_id)
LEFT JOIN " . BB_ATTACHMENTS_DESC . " ad ON(ad.attach_id = tor.attach_id)
LEFT JOIN " . BB_BT_USERS . " ut ON(ut.user_id = tor.poster_id)
WHERE u.user_id = $user_id
GROUP BY tor.poster_id
LIMIT 1
";
$total_releases_size = $total_releases = $total_releases_completed = $total_releases_downloaded = 0;
if ($row = DB()->fetch_row($sql)) {
$total_releases = $row['total_releases'];
$total_releases_size = $row['total_size'];
$total_releases_downloaded = $row['total_dl_count'];
$total_releases_completed = $row['total_complete'];
}
$html = '[
' . $lang['RELEASES'] . ': <span class="seed bold">' . $total_releases . '</span> |
' . $lang['RELEASER_STAT_SIZE'] . ' <span class="seed bold">' . humn_size($total_releases_size) . '</span> |
' . $lang['DOWNLOADED'] . ': <span title="' . $lang['COMPLETED'] . ':&nbsp;' . declension((int)$total_releases_completed, 'times') . '" class="seed bold">' . declension((int)$total_releases_downloaded, 'times') . '</span> ]';
break;
case 'get_traf_stats':
if (!RATIO_ENABLED) {
$this->ajax_die($lang['MODULE_OFF']);
}
if (IS_GUEST) {
$this->ajax_die($lang['NEED_TO_LOGIN_FIRST']);
}
$user_id = (int)$this->request['user_id'];
$btu = get_bt_userdata($user_id);
$profiledata = get_userdata($user_id);
@ -172,7 +100,7 @@ switch ($mode) {
<th>' . $lang['UPLOADED'] . '</th>
<th>' . $lang['RELEASED'] . '</th>
<th>' . $lang['BONUS'] . '</th>';
$html .= config()->get('seed_bonus_enabled') ? '<th>' . $lang['SEED_BONUS'] . '</th>' : '';
$html .= ($bb_cfg['seed_bonus_enabled']) ? '<th>' . $lang['SEED_BONUS'] . '</th>' : '';
$html .= '</tr>
<tr class="row1">
<td>' . $lang['TOTAL_TRAF'] . '</td>
@ -180,17 +108,17 @@ switch ($mode) {
<td id="u_up_total"><span class="editable bold seedmed">' . humn_size($btu['u_up_total']) . '</span></td>
<td id="u_up_release"><span class="editable bold seedmed">' . humn_size($btu['u_up_release']) . '</span></td>
<td id="u_up_bonus"><span class="editable bold seedmed">' . humn_size($btu['u_up_bonus']) . '</span></td>';
$html .= config()->get('seed_bonus_enabled') ? '<td id="user_points"><span class="editable bold points">' . $profiledata['user_points'] . '</b></td>' : '';
$html .= ($bb_cfg['seed_bonus_enabled']) ? '<td id="user_points"><span class="editable bold points">' . $profiledata['user_points'] . '</b></td>' : '';
$html .= '</tr>
<tr class="row5">
<td colspan="1">' . $lang['MAX_SPEED'] . '</td>
<td colspan="2">' . $lang['DL_DL_SPEED'] . ': ' . $speed_down . '</span></td>
<td colspan="2">' . $lang['DL_UL_SPEED'] . ': ' . $speed_up . '</span></td>';
$html .= config()->get('seed_bonus_enabled') ? '<td colspan="1"></td>' : '';
$html .= ($bb_cfg['seed_bonus_enabled']) ? '<td colspan="1"></td>' : '';
$html .= '</tr>';
$this->response['user_ratio'] = '
<th><a href="' . config()->get('ratio_url_help') . '" class="bold">' . $lang['USER_RATIO'] . '</a>:</th>
<th><a href="' . $bb_cfg['ratio_url_help'] . '" class="bold">' . $lang['USER_RATIO'] . '</a>:</th>
<td>' . $user_ratio . '</td>
';
break;

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,7 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $userdata, $lang;
global $userdata, $lang, $bb_cfg;
if (!$mode = (string)$this->request['mode']) {
$this->ajax_die('invalid mode (empty)');
@ -19,7 +19,7 @@ if (!$mode = (string)$this->request['mode']) {
switch ($mode) {
case 'clear_cache':
foreach (config()->get('cache.engines') as $cache_name => $cache_val) {
foreach ($bb_cfg['cache']['engines'] as $cache_name => $cache_val) {
CACHE($cache_name)->rm();
}
@ -48,20 +48,20 @@ switch ($mode) {
$this->response['template_cache_html'] = '<span class="seed bold">' . $lang['ALL_TEMPLATE_CLEARED'] . '</span>';
break;
case 'indexer':
exec("indexer --config " . config()->get('sphinx_config_path') . " --all --rotate", $result);
exec("indexer --config {$bb_cfg['sphinx_config_path']} --all --rotate", $result);
if (!is_file(config()->get('sphinx_config_path') . ".log")) {
file_put_contents(config()->get('sphinx_config_path') . ".log", "##############################" . date("H:i:s", TIMENOW) . "##############################\r\n\r\n\r\n\r\n", FILE_APPEND);
if (!is_file($bb_cfg['sphinx_config_path'] . ".log")) {
file_put_contents($bb_cfg['sphinx_config_path'] . ".log", "##############################" . date("H:i:s", TIMENOW) . "##############################\r\n\r\n\r\n\r\n", FILE_APPEND);
}
file_put_contents(config()->get('sphinx_config_path') . ".log", "##############################" . date("H:i:s", TIMENOW) . "##############################\r\n", FILE_APPEND);
file_put_contents($bb_cfg['sphinx_config_path'] . ".log", "##############################" . date("H:i:s", TIMENOW) . "##############################\r\n", FILE_APPEND);
foreach ($result as $row) {
file_put_contents(config()->get('sphinx_config_path') . ".log", $row . "\r\n", FILE_APPEND);
file_put_contents($bb_cfg['sphinx_config_path'] . ".log", $row . "\r\n", FILE_APPEND);
}
file_put_contents(config()->get('sphinx_config_path') . ".log", "\r\n", FILE_APPEND);
file_put_contents(config()->get('sphinx_config_path') . ".log", "\r\n", FILE_APPEND);
file_put_contents($bb_cfg['sphinx_config_path'] . ".log", "\r\n", FILE_APPEND);
file_put_contents($bb_cfg['sphinx_config_path'] . ".log", "\r\n", FILE_APPEND);
$this->response['indexer_html'] = '<span class="seed bold">' . $lang['INDEXER'] . '</span>';
break;

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,7 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $userdata, $lang;
global $userdata, $lang, $bb_cfg;
if (!$mode = (string)$this->request['mode']) {
$this->ajax_die('invalid mode (empty)');

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,7 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $userdata, $lang, $datastore, $log_action;
global $userdata, $bb_cfg, $lang, $datastore, $log_action;
if (!$mode = (string)$this->request['mode']) {
$this->ajax_die('invalid mode (empty)');
@ -22,7 +22,7 @@ switch ($mode) {
$topics = (string)$this->request['topic_ids'];
$status = (int)$this->request['status'];
// Check status validity
// Валидность статуса
if (!isset($lang['TOR_STATUS_NAME'][$status])) {
$this->ajax_die($lang['TOR_STATUS_FAILED']);
}
@ -30,29 +30,9 @@ switch ($mode) {
$topic_ids = DB()->fetch_rowset("SELECT attach_id FROM " . BB_BT_TORRENTS . " WHERE topic_id IN($topics)", 'attach_id');
foreach ($topic_ids as $attach_id) {
$tor = DB()->fetch_row("
SELECT
tor.forum_id, tor.topic_id, t.topic_title, tor.tor_status
FROM " . BB_BT_TORRENTS . " tor
INNER JOIN " . BB_TOPICS . " t ON(t.topic_id = tor.topic_id)
WHERE tor.attach_id = $attach_id LIMIT 1");
if (!$tor) {
$this->ajax_die($lang['TORRENT_FAILED']);
}
\TorrentPier\Legacy\Torrent::change_tor_status($attach_id, $status);
// Log action
$log_msg = sprintf($lang['TOR_STATUS_LOG_ACTION'], config()->get('tor_icons')[$status] . ' <b> ' . $lang['TOR_STATUS_NAME'][$status] . '</b>', config()->get('tor_icons')[$tor['tor_status']] . ' <b> ' . $lang['TOR_STATUS_NAME'][$tor['tor_status']] . '</b>');
$log_action->mod('mod_topic_change_tor_status', [
'forum_id' => $tor['forum_id'],
'topic_id' => $tor['topic_id'],
'topic_title' => $tor['topic_title'],
'log_msg' => $log_msg . '<br/>-------------',
]);
}
$this->response['status'] = config()->get('tor_icons')[$status];
$this->response['status'] = $bb_cfg['tor_icons'][$status];
$this->response['topics'] = explode(',', $topics);
break;
@ -77,20 +57,16 @@ switch ($mode) {
DB()->query("UPDATE " . BB_TOPICS . " SET topic_title = '$topic_title_sql' WHERE topic_id = $topic_id LIMIT 1");
// Update the news cache on the index page
$news_forums = array_flip(explode(',', config()->get('latest_news_forum_id')));
if (isset($news_forums[$t_data['forum_id']]) && config()->get('show_latest_news')) {
$datastore->enqueue([
'latest_news'
]);
// Обновление кеша новостей на главной
$news_forums = array_flip(explode(',', $bb_cfg['latest_news_forum_id']));
if (isset($news_forums[$t_data['forum_id']]) && $bb_cfg['show_latest_news']) {
$datastore->enqueue('latest_news');
$datastore->update('latest_news');
}
$net_forums = array_flip(explode(',', config()->get('network_news_forum_id')));
if (isset($net_forums[$t_data['forum_id']]) && config()->get('show_network_news')) {
$datastore->enqueue([
'network_news'
]);
$net_forums = array_flip(explode(',', $bb_cfg['network_news_forum_id']));
if (isset($net_forums[$t_data['forum_id']]) && $bb_cfg['show_network_news']) {
$datastore->enqueue('network_news');
$datastore->update('network_news');
}
@ -98,7 +74,6 @@ switch ($mode) {
$log_action->mod('mod_topic_renamed', [
'forum_id' => $t_data['forum_id'],
'topic_id' => $topic_id,
'topic_id_new' => $topic_id,
'topic_title' => $old_title,
'topic_title_new' => $new_title
]);
@ -151,8 +126,8 @@ switch ($mode) {
} else {
$user_reg_ip = \TorrentPier\Helpers\IPHelper::long2ip_extended($profiledata['user_reg_ip']);
$user_last_ip = \TorrentPier\Helpers\IPHelper::long2ip_extended($profiledata['user_last_ip']);
$reg_ip = '<a href="' . config()->get('whois_info') . $user_reg_ip . '" class="gen" target="_blank">' . $user_reg_ip . '</a>';
$last_ip = '<a href="' . config()->get('whois_info') . $user_last_ip . '" class="gen" target="_blank">' . $user_last_ip . '</a>';
$reg_ip = '<a href="' . $bb_cfg['whois_info'] . $user_reg_ip . '" class="gen" target="_blank">' . $user_reg_ip . '</a>';
$last_ip = '<a href="' . $bb_cfg['whois_info'] . $user_last_ip . '" class="gen" target="_blank">' . $user_last_ip . '</a>';
}
$this->response['ip_list_html'] = '
@ -172,5 +147,5 @@ switch ($mode) {
break;
default:
$this->ajax_die('Invalid mode: ' . $mode);
$this->ajax_die('Invalid mode');
}

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,7 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $lang, $userdata;
global $lang, $bb_cfg, $userdata, $wordCensor;
if (!isset($this->request['type'])) {
$this->ajax_die('empty type');
@ -76,17 +76,16 @@ switch ($this->request['type']) {
$message = "[quote=\"" . $quote_username . "\"][qpost=" . $post['post_id'] . "]" . $post['post_text'] . "[/quote]\r";
// hide user passkey
$message = preg_replace('#(?<=[\?&;]' . config()->get('passkey_key') . '=)[a-zA-Z0-9]#', 'passkey', $message);
$message = preg_replace('#(?<=\?uk=)[a-zA-Z0-9](?=&)#', 'passkey', $message);
// hide sid
$message = preg_replace('#(?<=[\?&;]sid=)[a-zA-Z0-9]#', 'sid', $message);
$message = censor()->censorString($message);
$message = $wordCensor->censorString($message);
if ($post['post_id'] == $post['topic_first_post_id']) {
$message = "[quote]" . $post['topic_title'] . "[/quote]\r";
}
if (mb_strlen($message, DEFAULT_CHARSET) > 1000) {
$this->response['redirect'] = make_url(POSTING_URL . '?mode=quote&' . POST_POST_URL . '=' . $post_id);
if (mb_strlen($message, 'UTF-8') > 1000) {
$this->response['redirect'] = make_url(POSTING_URL . '?mode=quote&p=' . $post_id);
}
$this->response['quote'] = true;
@ -112,18 +111,18 @@ switch ($this->request['type']) {
if ($post['poster_id'] != $userdata['user_id'] && !$is_auth['auth_mod']) {
$this->ajax_die($lang['EDIT_OWN_POSTS']);
}
if ((mb_strlen($post['post_text'], DEFAULT_CHARSET) > 1000) || $post['post_attachment'] || ($post['topic_first_post_id'] == $post_id)) {
$this->response['redirect'] = make_url(POSTING_URL . '?mode=editpost&' . POST_POST_URL . '=' . $post_id);
if ((mb_strlen($post['post_text'], 'UTF-8') > 1000) || $post['post_attachment'] || ($post['topic_first_post_id'] == $post_id)) {
$this->response['redirect'] = make_url(POSTING_URL . '?mode=editpost&p=' . $post_id);
} elseif ($this->request['type'] == 'editor') {
$text = (string)$this->request['text'];
$text = prepare_message($text);
if (mb_strlen($text) > 2) {
if ($text != $post['post_text']) {
if (config()->get('max_smilies')) {
$count_smilies = substr_count(bbcode2html($text), '<img class="smile" src="' . config()->get('smilies_path'));
if ($count_smilies > config()->get('max_smilies')) {
$this->ajax_die(sprintf($lang['MAX_SMILIES_PER_POST'], config()->get('max_smilies')));
if ($bb_cfg['max_smilies']) {
$count_smilies = substr_count(bbcode2html($text), '<img class="smile" src="' . $bb_cfg['smilies_path']);
if ($count_smilies > $bb_cfg['max_smilies']) {
$this->ajax_die(sprintf($lang['MAX_SMILIES_PER_POST'], $bb_cfg['max_smilies']));
}
}
DB()->query("UPDATE " . BB_POSTS_TEXT . " SET post_text = '" . DB()->escape($text) . "' WHERE post_id = $post_id LIMIT 1");
@ -179,7 +178,7 @@ switch ($this->request['type']) {
<input title="Alt+Enter" name="preview" type="submit" value="' . $lang['PREVIEW'] . '">
<input type="button" onclick="edit_post(' . $post_id . ');" value="' . $lang['CANCEL'] . '">
<input type="button" onclick="edit_post(' . $post_id . ', \'editor\', $(\'#message-' . $post_id . '\').val()); return false;" class="bold" value="' . $lang['SUBMIT'] . '">
</div><hr/>
</div><hr>
<script type="text/javascript">
var bbcode = new BBCode("message-' . $post_id . '");
var ctrl = "ctrl";
@ -225,7 +224,7 @@ switch ($this->request['type']) {
$sql = "SELECT MAX(p.post_time) AS last_post_time FROM " . BB_POSTS . " p WHERE $where_sql";
if ($row = DB()->fetch_row($sql) and $row['last_post_time']) {
if ($userdata['user_level'] == USER) {
if ((TIMENOW - $row['last_post_time']) < config()->get('flood_interval')) {
if ((TIMENOW - $row['last_post_time']) < $bb_cfg['flood_interval']) {
$this->ajax_die($lang['FLOOD_ERROR']);
}
}
@ -251,10 +250,10 @@ switch ($this->request['type']) {
}
}
if (config()->get('max_smilies')) {
$count_smilies = substr_count(bbcode2html($message), '<img class="smile" src="' . config()->get('smilies_path'));
if ($count_smilies > config()->get('max_smilies')) {
$this->ajax_die(sprintf($lang['MAX_SMILIES_PER_POST'], config()->get('max_smilies')));
if ($bb_cfg['max_smilies']) {
$count_smilies = substr_count(bbcode2html($message), '<img class="smile" src="' . $bb_cfg['smilies_path']);
if ($count_smilies > $bb_cfg['max_smilies']) {
$this->ajax_die(sprintf($lang['MAX_SMILIES_PER_POST'], $bb_cfg['max_smilies']));
}
}
@ -272,7 +271,7 @@ switch ($this->request['type']) {
'post_text' => $message
]);
if (config()->get('topic_notify_enabled')) {
if ($bb_cfg['topic_notify_enabled']) {
$notify = !empty($this->request['notify']);
\TorrentPier\Legacy\Post::user_notification('reply', $post, $post['topic_title'], $post['forum_id'], $topic_id, $notify);
}

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,7 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $lang;
global $bb_cfg, $lang;
if (!$mode = (string)$this->request['mode']) {
$this->ajax_die('invalid mode (empty)');
@ -24,12 +24,28 @@ switch ($mode) {
case 'create':
$map->createSitemap();
if (is_file(SITEMAP_DIR . '/sitemap.xml')) {
$html .= $lang['SITEMAP_CREATED'] . ': <b>' . bb_date(TIMENOW, config()->get('post_date_format')) . '</b> ' . $lang['SITEMAP_AVAILABLE'] . ': <a href="' . make_url('sitemap/sitemap.xml') . '" target="_blank">' . make_url('sitemap/sitemap.xml') . '</a>';
$html .= $lang['SITEMAP_CREATED'] . ': <b>' . bb_date(TIMENOW, $bb_cfg['post_date_format']) . '</b> ' . $lang['SITEMAP_AVAILABLE'] . ': <a href="' . make_url('sitemap/sitemap.xml') . '" target="_blank">' . make_url('sitemap/sitemap.xml') . '</a>';
} else {
$html .= $lang['SITEMAP_NOT_CREATED'];
}
break;
case 'search_update':
if (!is_file(SITEMAP_DIR . '/sitemap.xml')) {
$map->createSitemap();
}
$map_link = make_url(hide_bb_path(SITEMAP_DIR . '/sitemap.xml'));
foreach ($bb_cfg['sitemap_sending'] as $source_name => $source_link) {
if ($map->sendSitemap($source_link, $map_link)) {
$html .= '<br />' . $lang['SITEMAP_NOTIFY_SEARCH'] . '&nbsp;' . $source_name . ' : <span style="color: green;">' . $lang['SITEMAP_SENT'] . '</span>';
} else {
$html .= '<br />' . $lang['SITEMAP_NOTIFY_SEARCH'] . '&nbsp;' . $source_name . ' : <span style="color: red;">' . $lang['SITEMAP_ERROR'] . '</span> URL: <a href="' . $source_link . urlencode($map_link) . '" target="_blank">' . $source_link . $map_link . '</a>';
}
}
break;
default:
$this->ajax_die("Invalid mode: $mode");
}

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,9 +11,9 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $lang, $userdata;
global $bb_cfg, $lang, $userdata;
if (!config()->get('tor_thank')) {
if (!$bb_cfg['tor_thank']) {
$this->ajax_die($lang['MODULE_OFF']);
}
@ -25,47 +25,39 @@ if (!$topic_id = (int)$this->request['topic_id']) {
$this->ajax_die($lang['INVALID_TOPIC_ID']);
}
if (!$poster_id = (int)$this->request['poster_id']) {
$this->ajax_die($lang['NO_USER_ID_SPECIFIED']);
}
switch ($mode) {
case 'add':
if (IS_GUEST) {
if (!IS_GUEST) {
if (DB()->fetch_row('SELECT poster_id FROM ' . BB_BT_TORRENTS . " WHERE topic_id = $topic_id AND poster_id = " . $userdata['user_id'])) {
$this->ajax_die($lang['LIKE_OWN_POST']);
}
if (DB()->fetch_row('SELECT topic_id FROM ' . BB_THX . " WHERE topic_id = $topic_id AND user_id = " . $userdata['user_id'])) {
$this->ajax_die($lang['LIKE_ALREADY']);
}
$columns = 'topic_id, user_id, time';
$values = "$topic_id, {$userdata['user_id']}, " . TIMENOW;
DB()->query('INSERT IGNORE INTO ' . BB_THX . " ($columns) VALUES ($values)");
break;
} else {
$this->ajax_die($lang['NEED_TO_LOGIN_FIRST']);
}
if ($poster_id == $userdata['user_id']) {
$this->ajax_die($lang['LIKE_OWN_POST']);
}
if (DB()->fetch_row('SELECT topic_id FROM ' . BB_THX . " WHERE topic_id = $topic_id AND user_id = " . $userdata['user_id'])) {
$this->ajax_die($lang['LIKE_ALREADY']);
}
$columns = 'topic_id, user_id, time';
$values = "$topic_id, {$userdata['user_id']}, " . TIMENOW;
DB()->query('INSERT IGNORE INTO ' . BB_THX . " ($columns) VALUES ($values)");
// Limit voters per topic
$thanks_count = DB()->fetch_row('SELECT COUNT(*) as thx FROM ' . BB_THX . " WHERE topic_id = $topic_id")['thx'];
if ($thanks_count > (int)config()->get('tor_thank_limit_per_topic')) {
DB()->query('DELETE FROM ' . BB_THX . " WHERE topic_id = $topic_id ORDER BY time ASC LIMIT 1");
}
break;
case 'get':
if (IS_GUEST && !config()->get('tor_thanks_list_guests')) {
if (!IS_GUEST || $bb_cfg['tor_thanks_list_guests']) {
$sql = DB()->fetch_rowset('SELECT u.username, u.user_rank, u.user_id, t.* FROM ' . BB_THX . ' t, ' . BB_USERS . " u WHERE t.topic_id = $topic_id AND t.user_id = u.user_id");
$user_list = [];
foreach ($sql as $row) {
$user_list[] = '<b>' . profile_url($row) . ' <i>(' . bb_date($row['time']) . ')</i></b>';
}
$this->response['html'] = join(', ', $user_list) ?: $lang['NO_LIKES'];
break;
} else {
$this->ajax_die($lang['NEED_TO_LOGIN_FIRST']);
}
$user_list = [];
$sql = DB()->fetch_rowset('SELECT u.username, u.user_rank, u.user_id, t.* FROM ' . BB_THX . ' t, ' . BB_USERS . " u WHERE t.topic_id = $topic_id AND t.user_id = u.user_id");
foreach ($sql as $row) {
$user_list[] = '<b>' . profile_url($row) . ' <i>(' . bb_date($row['time']) . ')</i></b>';
}
$this->response['html'] = implode(', ', $user_list) ?: $lang['NO_LIKES'];
break;
default:
$this->ajax_die('Invalid mode: ' . $mode);
}

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -116,7 +116,7 @@ switch ($mode) {
$new_tpl_id = $tpl_id;
$this->response['msg'] = "Включен шаблон $tpl_name";
}
DB()->query("UPDATE " . BB_FORUMS . " SET forum_tpl_id = $new_tpl_id WHERE forum_id = $forum_id LIMIT 1");
DB()->query("UPDATE " . BB_FORUMS . " SET forum_tpl_id = $new_tpl_id WHERE forum_id = $forum_id");
break;
// сохранение изменений
@ -127,7 +127,7 @@ switch ($mode) {
$msg .= 'Шаблон был отредактирован: ' . html_ent_decode($last_edit_by_username) . ', ' . bb_date($tpl_data['tpl_last_edit_tm'], 'd-M-y H:i');
$this->ajax_die($msg);
}
$sql = "UPDATE " . BB_TOPIC_TPL . " SET " . DB()->build_array('UPDATE', $sql_args) . " WHERE tpl_id = $tpl_id LIMIT 1";
$sql = "UPDATE " . BB_TOPIC_TPL . " SET " . DB()->build_array('UPDATE', $sql_args) . " WHERE tpl_id = $tpl_id";
if (!DB()->query($sql)) {
$sql_error = DB()->sql_error();
}

View file

@ -2,7 +2,7 @@
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
@ -11,7 +11,7 @@ if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $lang, $userdata;
global $bb_cfg, $lang, $userdata;
if (!$mode = (string)$this->request['mode']) {
$this->ajax_die('invalid mode (empty)');
@ -47,11 +47,6 @@ switch ($mode) {
}
break;
case 'check_country':
$country = (string)$this->request['country'];
$html = render_flag($country);
break;
default:
$this->ajax_die('Invalid mode: ' . $mode);
}

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