Complete overhaul of the configuration architecture

This commit is contained in:
Spine
2021-12-29 15:01:05 +00:00
parent 57ee9eebf9
commit 870e18785d
28 changed files with 1193 additions and 679 deletions

View File

@@ -25,9 +25,7 @@ while ! mysql -h mysql -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "show databases;"
fi;
done
if [ ! -f /var/www/classes/config.php ]; then
bash /var/www/.docker/web/generate-config.sh
fi
[ -f /var/www/lib/config.override.php ] || bash /var/www/.docker/web/generate-config.sh
echo "Run migrations..."
if ! FKEY_MY_DATABASE=1 LOCK_MY_DATABASE=1 /var/www/vendor/bin/phinx migrate; then

View File

@@ -1,22 +0,0 @@
s/'SITE_NAME', *'/&Gazelle Dev/
s/'SITE_HOST', *'/&localhost/
s|'(SITE_URL)', *'https://'.SITE_HOST|'\1', 'http://'.SITE_HOST.':8080'|
s|'(SERVER_ROOT(_LIVE)?)', *'/path|'\1', '/var/www|
s|'ANNOUNCE_HTTP_URL', *'|&http://localhost:34000|
s|'ANNOUNCE_HTTPS_URL', *'|&https://localhost:3400|
s/('SQLHOST', *')localhost/\1mysql/
s/('SPHINX(QL)?_HOST', *')(localhost|127\.0\.0\.1)/\1sphinxsearch/
s|('host' *=>) *'unix:///var/run/memcached.sock'(, *'port' *=>) *0|\1 'memcached'\2 11211|
s/('(DEBUG_MODE|DISABLE_IRC)',) *false/\1 true/
s|'SOURCE', *'|&DEV|
s|'TRACKER_SECRET', *'|&00000000000000000000000000000000|
s|'TRACKER_REPORTKEY', *'|&00000000000000000000000000000000|
s/('TRACKER_HOST', *')localhost/\1ocelot/

View File

@@ -1,18 +1,14 @@
#!/usr/bin/env bash
#!/bin/bash
THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
set -euo pipefail
TARGET=${THIS_DIR}/../../classes/config.php
if [ -f ${TARGET} ]; then
exit 0;
fi
LIB_DIR="$(dirname "${BASH_SOURCE[0]}")/../../lib"
SOURCE="${LIB_DIR}/config.devel.example.php"
TARGET="${LIB_DIR}/config.override.php"
[ -f ${TARGET} ] && exit 0
echo "GENERATING GAZELLE CONFIG..."
echo ""
sed -Ef $THIS_DIR/generate-config.sed \
-e "s/('SQL(LOGIN|_PHINX_USER)', *')/\1${MYSQL_USER}/" \
-e "s/('SQL(_PHINX_)?PASS', *')/\1${MYSQL_PASSWORD}/" \
${THIS_DIR}/../../classes/config.template.php > ${TARGET}
echo ""
(
perl -ple 's/""/q{"} . qx(head \/dev\/urandom|tr -dc 0-9A-Za-z|head -c 16) . q{"}/e' "${SOURCE}"
date +"define('SITE_LAUNCH_YEAR', %Y);"
) > "${TARGET}"

2
.gitignore vendored
View File

@@ -24,7 +24,7 @@ __MACOSX/
/public/static/font/
/public/static/local/
/vendor
/classes/config.php
/lib/config.override.php
/mix-manifest.json
/mix.js.map
/yarn-error.log

View File

@@ -19,6 +19,11 @@ needs. Gazelle is written in PHP, Twig, JavaScript, and MySQL.
* [GCC/G++](http://gcc.gnu.org/) (4.7+ required; 4.8.1+ recommended)
* [Boost](http://www.boost.org/) (1.55.0+ required)
## Gazelle/Ocelot Compile-time Dependencies
* [Git](http://git-scm.com/) (required)
* [GCC/G++](http://gcc.gnu.org/) (4.7+ required; 4.8.1+ recommended)
* [Boost](http://www.boost.org/) (1.55.0+ required)
_Note: This list may not be exhaustive._
## Logchecker
@@ -61,7 +66,14 @@ Bullseye. A volume is mounted from the base of the git repository at
`/var/www` in the container. Changes to the source code are
immediately served without rebuilding or restarting.
## Going further
You can access the site by viewing `http://localhost:8080`
The first account is 'admin' and has the highest level of access
to the site installation. The second account is 'user' and has
standard user access. The passwords for both accounts are literally
'password' (without the quotes). If you want to change these before
building, edit db/seeds/InitialUserSeeder.php first.
The 'admin' account might not have all the permissions that have
been added recently. Navigate to the /tools.php?action=permissions
page and tick everything.
@@ -72,8 +84,7 @@ The following ports are forwarded:
* 3306 -> 36000 (mysql)
* 34000 -> 34000 (ocelot)
You can access the site by viewing `http://localhost:8080`
## Going further
You may want to install additional packages:
* `apt update`
* `apt install less procps vim`

View File

@@ -99,7 +99,7 @@ class Donation extends \Gazelle\Base {
}
// Assign them to the Donor secondary class if it hasn't already been done
$inviteForNewDonor = $xbtAmount > 0 ? DONOR_FIRST_INVITE_COUNT * $this->addDonorStatus($UserID) : 0;
$inviteForNewDonor = $xbtAmount > 0 ? DONOR_INVITES * $this->addDonorStatus($UserID) : 0;
// Now that their rank and total rank has been set, we can calculate their special rank and invites
$column = [];

View File

@@ -3,7 +3,7 @@
* This array is the backbone of the reports system.
* Important thing to note about the array:
* 1. When coding for a non music site, you need to ensure that the top level of the
* array lines up with the $Categories array in your config.php.
* array lines up with the CATEGORIES array in lib/config.php.
* 2. The first sub array contains resolves that are present on every report type
* regardless of category.
* 3. The only part that shouldn't be self-explanatory is that for the tracks field in

View File

@@ -115,7 +115,7 @@ class Tracker {
* @return array with stats in named keys or empty if the request failed
*/
private function get_stats($Type, $Params = false): array {
if (!TRACKER_REPORTKEY) {
if (DISABLE_TRACKER) {
return [];
}
$Get = TRACKER_REPORTKEY . '/report?';

View File

@@ -309,7 +309,7 @@ class UserCreator extends Base {
}
/**
* Create salted crypt hash for a given string
* Create a password hash of a plaintext password.
*/
static public function hashPassword(string $plaintext): string {
return password_hash(hash('sha256', $plaintext), PASSWORD_DEFAULT);

View File

@@ -1,552 +0,0 @@
<?php
// NOTE: When editing this file, please make-sure to update the generate-config.sh file for docker!
// Main settings
define('SITE_NAME', ''); //The name of your site
define('SITE_HOST', ''); // The host for your site (e.g. localhost, orpheus.network)
define('SITE_URL', 'https://'.SITE_HOST); // The base URL to access the site (e.g. http://localhost:8080, https://orpheus.network)
//define('ALT_SITE_HOST', ''); // Alternative hostname for site, such as for beta deploy (e.g. beta.localhost)
//define('ALT_SITE_URL', 'https://' . ALT_SITE_HOST); // This should be uncommented out if you are providing a second way to access site code, e.g. beta site
define('MAIL_HOST', 'mail.'.SITE_HOST); // The host to use for mail delivery (e.g. mail.orpheus.network)
define('SERVER_ROOT', '/path'); //The root of the server, used for includes, purpose is to shorten the path string
define('SERVER_ROOT_LIVE', '/path'); //Only needed on the beta site when accessing unmocked resources, otherwise == SERVER_ROOT
define('BETA', false); //Only needed on the beta site when different code paths are necessary
define('ANNOUNCE_HTTP_URL', '');
define('ANNOUNCE_HTTPS_URL', '');
define('HTTP_PROXY', false);
define('REFERRAL_BOUNCER', ''); // URL to the bouncer including trailing /.
define('REFERRAL_KEY', hash('sha512', '')); //Random key. Used for encrypting traffic to/from the boucner.
define('REFERRAL_SEND_EMAIL', false); // Whether to send invite emails for referrals.
define('REFERRAL_SITES', ['ABC', 'DEF']);
define('RECOVERY', false);
define('RECOVERY_BUFFER', false); // is buffer from previous site restituted
define('RECOVERY_SALT', '');
define('RECOVERY_PATH', '');
define('RECOVERY_DB', '');
define('RECOVERY_MAPPING_TABLE', 'users_' . RECOVERY_DB . '_mapping');
define('RECOVERY_IRC_TABLE', 'users_' . RECOVERY_DB . '_irc');
define('RECOVERY_AUTOVALIDATE', true);
define('RECOVERY_AUTOVALIDATE_LIMIT', 20);
define('RECOVERY_ADMIN_ID', 17); // hermes
define('RECOVERY_ADMIN_NAME', 'RecoveryBot');
define('RECOVERY_BUFFER_REASSIGN_LIMIT', 100);
define('RECOVERY_PAIR_SALT', '');
define('SOURCE', ''); // source flag to use for torrent files. should be unique from other sites to enable easy cross seeding.
define('GRANDFATHER_SOURCE', ''); // flag to use for grandfathering torrents. useful if expecting torrents from a defunct site.
define('GRANDFATHER_OLD_SOURCE', strtotime('1970-01-01')); // End date to allow source flag from previous site.
define('GRANDFATHER_NO_SOURCE', strtotime('1970-01-01')); // End date to ignore source flag.
define('MAX_PATH_LEN', 200); // Maximum filename length for torrent files and in archives
define('MAX_PREV_TORRENT_ID', 0); // Lowest torrent ID of previous site incarnation.
define('FAKE_USERAGENT', 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.1 Safari/537.11');
define('SEEDBOX_SALT', '8EQKRWZqA5DMVwpAqQKRCiMm5xaucsPePseXwZhm88T8PyyuAkjVgTLrAMWWeB8W'); // change me
define('AVATAR_SALT', 'BEapyctddrananytAqnkqccFgEntBdgf'); // change me
define('AVATAR_WIDTH', 150);
define('SIMILAR_WIDTH', 720);
define('SIMILAR_HEIGHT', 500);
define('LOGIN_ATTEMPT_BACKOFF', [
0,
30,
90,
60 * 5, // 5 minutes
60 * 15,
3600 * 3, // 3 hours
3600 * 6,
86400,
86400 * 3,
86400 * 7,
]);
// Allows you to run static content off another server. Default is usually what you want.
define('STATIC_SERVER', 'static');
// Keys
define('ENCKEY', ''); //Random key. The key for encryption
define('SCHEDULE_KEY', ''); // Random key. This key must be the argument to schedule.php for the schedule to work.
define('RSS_HASH', ''); //Random key. Used for generating unique RSS auth key.
// MySQL details
define('SQLHOST', 'localhost'); //The MySQL host ip/fqdn
define('SQLLOGIN', '');//The MySQL login
define('SQLPASS', ''); //The MySQL password
define('SQL_PHINX_USER', ''); // User to use for Phinx migrations
define('SQL_PHINX_PASS', ''); // Pass to use for Phinx migrations
define('SQLDB', 'gazelle'); //The MySQL database to use
define('SQLPORT', 3306); //The MySQL port to connect on
define('SQLSOCK', false); // Socket mysql is listening on, usually /var/run/mysqld/mysqld.sock
define('GZPG_HOST', 'pg');
define('GZPG_PORT', 54321);
define('GZPG_DB', 'gzpg');
define('GZPG_USER', 'gus');
define('GZPG_PASSWORD', 'gazpg');
// Sphinx details
define('SPHINX_HOST', 'localhost');
define('SPHINX_PORT', 9312);
define('SPHINXQL_HOST', '127.0.0.1');
define('SPHINXQL_PORT', 9306);
define('SPHINXQL_SOCK', false);
define('SPHINX_MAX_MATCHES', 1000); // Must be <= the server's max_matches variable (default 1000)
// Ocelot details
define('DISABLE_TRACKER', false);
define('TRACKER_HOST', 'localhost');
define('TRACKER_PORT', 2710);
define('TRACKER_SECRET', ''); // Must be 32 characters and match site_password in Ocelot's config.cpp
define('TRACKER_REPORTKEY', ''); // Must be 32 characters and match report_password in Ocelot's config.cpp
// Last.fm settings
define('LASTFM_API_KEY', null);
// Site settings
define('DEBUG_EMAIL', false); //Set to true to write messages to TMPDIR instead of delivering
define('DEBUG_MODE', false); //Set to false if you dont want everyone to see debug information, can be overriden with 'site_debug'
define('DEBUG_WARNINGS', true); //Set to true if you want to see PHP warnings in the footer
define('DEBUG_UPLOAD_NOTIFICATION', false); // Set to true to dump notification trigger results
define('SHOW_PUBLIC_INDEX', true); // Show the public index.php landing page
define('OPEN_REGISTRATION', true); //Set to false to disable open registration, true to allow anyone to register
define('OPEN_EXTERNAL_REFERRALS', false); //Set to false to disable external tracker referrals, true to allow them
define('USER_LIMIT', 5000); //The maximum number of users the site can have, 0 for no limit
define('STARTING_UPLOAD', 3221225472); //Upload given to newly registered users, in bytes using IEC standard (1024 bytes per KiB)
define('BYTES_PER_FREELEECH_TOKEN', 536870912); // Amount of bytes to use per token
define('STACKABLE_FREELEECH_TOKENS', true); // Allow stacking tokens
define('FREELEECH_TOKEN_EXPIRY_DAYS', 30); // Number of days before an activated token expires
define('REQUEST_TAX', 0.0); //Percentage Tax (0 - 1) to charge users on making requests
define('REQUEST_MIN', 20 * 1024 * 1024); // Minimum request vote
define('STARTING_INVITES', 0); //# of invites to give to newly registered users
define('BLOCK_TOR', false); //Set to true to block Tor users
define('BLOCK_OPERA_MINI', false); //Set to true to block Opera Mini proxy
define('DONOR_INVITES', 2);
define('IP_OVERLAPS', 5); // Threshold for duplicate IPs
define('MIN_INVITE_CLASS', 150); // Minimum class allowed to purchase invites
define('USER_TITLE_LENGTH', 1024); // The maximum length of a custom user title
define('SYSTEM_USER_ID', 17); // ID for user to create "system" threads under (e.g. Edit Requests)
define('STAFF_FORUM_ID', 5); // ID of principal Staff forum (for polls)
define('TRASH_FORUM_ID', 4); // ID of forum to send threads to when trash button is pressed
define('EDITING_FORUM_ID', 34); // ID of forum to send editing requests to
define('AOTM_FORUM_ID', 51); // ID of the Album of The Month forum
define('VANITY_HOUSE_FORUM_ID', 18); // Vanity House forum
define('CLIENT_WHITELIST_FORUM_ID', 680); // Client whitelist suggestion forum
define("PARANOIA_HIDE", 0);
define("PARANOIA_ALLOWED", 1);
define("PARANOIA_OVERRIDDEN", 2);
define("PARANOIA_PREVIEW_USER", 1); // change to an unprivileged staff account
define("PARANOIA_OVERRIDE", [
'downloaded' => 'users_mod',
'uploaded' => 'users_mod',
'lastseen' => 'users_mod',
'ratio' => 'users_mod',
'requiredratio' => 'users_mod',
'hide_donor_heart' => 'users_mod',
'bonuspoints' => 'admin_bp_history',
'torrentcomments' => 'site_moderate_forums',
'invitedcount' => 'users_view_invites',
'snatched' => 'users_view_torrents_snatchlist',
'snatched+' => 'users_view_torrents_snatchlist',
'leeching' => 'users_view_seedleech',
'leeching+' => 'users_view_seedleech',
'seeding' => 'users_view_seedleech',
'seeding+' => 'users_view_seedleech',
'uploads' => 'users_view_seedleech',
'uploads+' => 'users_view_seedleech',
]);
define('USER_TORRENT_DELETE_MAX', 3);
define('USER_TORRENT_DELETE_HOURS', 24);
define('DELETE_USER_STATS_DAILY_DAY', 15); // retain how many days worth of hourly granularity
define('DELETE_USER_STATS_MONTHLY_DAY', 120); // retain how many days worth of daily granularity
define('FEATURE_EMAIL_REENABLE', true);
// Name of class Class ID (NOT level)
define('USER', 2);
define('MEMBER', 3);
define('POWER', 4);
define('ELITE', 5);
define('TORRENT_MASTER', 7);
define('POWER_TM', 22);
define('ELITE_TM', 23);
define('ULTIMATE_TM', 48);
define('FORUM_MOD', 28);
define('MOD', 11);
define('SYSOP', 15);
define('DONOR', 20);
define('FLS_TEAM', 23);
define('INTERVIEWER', 30);
define('RECRUITER', 41);
define('VIP', 6);
// Locked account constant
define('STAFF_LOCKED', 1);
define('STAFF_LEVEL', 820); // least permissions.Level of staff
// Pagination
define('BOOKMARKS_PER_PAGE', 20);
define('COLLAGES_PER_PAGE', 25);
define('CONTEST_ENTRIES_PER_PAGE', 50);
define('FRIENDS_PER_PAGE', 20);
define('INVITES_PER_PAGE', 50);
define('ITEMS_PER_PAGE', 50);
define('IPS_PER_PAGE', 50);
define('LOG_ENTRIES_PER_PAGE', 50);
define('MESSAGES_PER_PAGE', 25);
define('PEERS_PER_PAGE', 100);
define('POSTS_PER_PAGE', 25);
define('REPORTS_PER_PAGE', '10');
define('REQUESTS_PER_PAGE', 25);
define('TOPICS_PER_PAGE', 50);
define('TORRENTS_PER_PAGE', 50);
define('TORRENT_COMMENTS_PER_PAGE', 10);
define('USERS_PER_PAGE', 50);
define('WIKI_ARTICLES_PER_PAGE', 25);
define('AJAX_USERS_PER_PAGE', 30);
// Cache catalogues
define('THREAD_CATALOGUE', 500); // Limit to THREAD_CATALOGUE posts per cache key.
// IRC settings
define('DISABLE_IRC', false);
define('IRC_SOCKET_LISTEN_PORT', 51010);
define('IRC_SOCKET_LISTEN_ADDRESS', 'localhost');
define('BOT_NICK', '');
define('BOT_SERVER', ''); // IRC server address. Used for onsite chat tool.
define('BOT_PORT', 6667);
define('BOT_CHAN', '#mygazelle');
define('ADMIN_CHAN', '#admin');
define('LAB_CHAN', '#lab');
define('STATUS_CHAN', '#status');
define('MOD_CHAN', '#staff');
define('BOT_DISABLED_CHAN', '#disabled'); // Channel to refer disabled users to.
define('BOT_REPORT_CHAN', '#reports');
// Push server settings
define('PUSH_SOCKET_LISTEN_ADDRESS', '127.0.0.1');
define('PUSH_SOCKET_LISTEN_PORT', 6789);
// Miscellaneous values
define('RANK_ONE_COST', 5);
define('RANK_TWO_COST', 10);
define('RANK_THREE_COST', 15);
define('RANK_FOUR_COST', 20);
define('RANK_FIVE_COST', 30);
define('MAX_RANK', 6);
define('MAX_EXTRA_RANK', 8);
define('DONOR_FORUM_RANK', 6);
define('DONOR_FORUM', null); // donor forum id
define('MAX_SPECIAL_RANK', 3);
define('BONUS_AWARD_FLAC_PERFECT', 400);
define('BONUS_AWARD_FLAC', 30);
define('BONUS_AWARD_MP3', 30);
define('BONUS_AWARD_OTHER', 10);
define('BONUS_POOL_TAX_STD', 0.9);
define('BONUS_POOL_TAX_ELITE', 0.8);
define('BONUS_POOL_TAX_TM', 0.7);
define('BONUS_POOL_TAX_STAFF', 0.5);
define('DEBUG_CONTEST_PAYOUT', true); // set to true to test
define('INDEX_WIKI_PAGE_ID', 1);
define('RULES_WIKI_PAGE_ID', 127);
define('SOURCE_FLAG_WIKI_PAGE_ID', 113);
define('TMPDIR', '/tmp');
define('FORUM_REVEAL_VOTER', []);
define('STORAGE_PATH_TORRENT', '/var/lib/gazelle/torrent');
define('STORAGE_PATH_RIPLOG', '/var/lib/gazelle/riplog');
define('STORAGE_PATH_RIPLOGHTML', '/var/lib/gazelle/riploghtml');
//Useful: http://www.robtex.com/cnet/
define('ALLOWED_PROXY', [
//Opera Turbo (may include Opera-owned IP addresses that aren't used for Turbo, but shouldn't run much risk of exploitation)
'64.255.180.*', //Norway
'64.255.164.*', //Norway
'80.239.242.*', //Poland
'80.239.243.*', //Poland
'91.203.96.*', //Norway
'94.246.126.*', //Norway
'94.246.127.*', //Norway
'195.189.142.*', //Norway
'195.189.143.*', //Norway
]);
define('CATEGORY', ['Music', 'Applications', 'E-Books', 'Audiobooks', 'E-Learning Videos', 'Comedy', 'Comics']);
define('CATEGORY_GROUPED', array_intersect(['Music'], CATEGORY));
define('CATEGORY_ICON', ['music.png', 'apps.png', 'ebook.png', 'audiobook.png', 'elearning.png', 'comedy.png', 'comics.png']);
define('FORMAT', [
'MP3',
'FLAC',
'Ogg Vorbis',
'AAC',
'AC3',
'DTS'
]);
define('ENCODING', [
'Lossless',
'24bit Lossless',
'V0 (VBR)',
'V1 (VBR)',
'V2 (VBR)',
'320',
'256',
'192',
'160',
'128',
'96',
'64',
'APS (VBR)',
'APX (VBR)',
'q8.x (VBR)',
'Other'
]);
define('MEDIA', [
'CD',
'WEB',
'Vinyl',
'DVD',
'BD',
'Soundboard',
'SACD',
'DAT',
'Cassette',
]);
define('HOMEPAGE_TAG_IGNORE', [0]); // set to 'test' tag to ignore staff test uploads
define('ICON_ALL', "\xe2\x9c\x85");
define('ICON_NONE', "\xf0\x9f\x9a\xab");
define('ICON_TOGGLE', "\xf0\x9f\x94\x81");
define('ICON_PADLOCK', "\xF0\x9F\x94\x92");
define('ICON_STAR', "\xE2\x98\x85");
define('ICON_BLACK_SQUARE', "\xE2\x96\xA0");
define('ICON_WHITE_SQUARE', "\xE2\x96\xA1");
define('COLLAGE', [
0 => 'Personal',
1 => 'Theme',
2 => 'Genre Introduction',
3 => 'Discography',
4 => 'Label',
5 => 'Staff picks',
6 => 'Charts',
7 => 'Artists',
8 => 'Awards',
9 => 'Series',
]);
define('COLLAGE_PERSONAL_ID', 0);
define('COLLAGE_ARTISTS_ID', 7);
define('COLLAGE_SAMPLE_THRESHOLD', 4);
define('PERSONAL_COLLAGE_SAMPLE_THRESHOLD', 4);
define('ZIP_GROUP', [
0 => 'MP3 (VBR) - High Quality',
1 => 'MP3 (VBR) - Low Quality',
2 => 'MP3 (CBR)',
3 => 'FLAC - Lossless',
4 => 'Others',
]);
define('ZIP_OPTION', [
'00' => [0, 0, 'V0'],
'01' => [0, 1, 'APX'],
'02' => [0, 2, '256'],
'03' => [0, 3, 'V1'],
'10' => [1, 0, '224'],
'11' => [1, 1, 'V2'],
'12' => [1, 2, 'APS'],
'13' => [1, 3, '192'],
'20' => [2, 0, '320'],
'21' => [2, 1, '256'],
'22' => [2, 2, '224'],
'23' => [2, 3, '192'],
'24' => [2, 4, '160'],
'25' => [2, 5, '128'],
'26' => [2, 6, '96'],
'27' => [2, 7, '64'],
'30' => [3, 0, 'FLAC / 24bit / Vinyl'],
'31' => [3, 1, 'FLAC / 24bit / DVD'],
'32' => [3, 2, 'FLAC / 24bit / SACD'],
'33' => [3, 3, 'FLAC / 24bit / WEB'],
'34' => [3, 4, 'FLAC / Log (100) / Cue'],
'35' => [3, 5, 'FLAC / Log (100)'],
'36' => [3, 6, 'FLAC / Log'],
'37' => [3, 7, 'FLAC / WEB'],
'38' => [3, 8, 'FLAC'],
'40' => [4, 0, 'DTS'],
'42' => [4, 2, 'AAC - 320'],
'43' => [4, 3, 'AAC - 256'],
'44' => [4, 4, 'AAC - q5.5'],
'45' => [4, 5, 'AAC - q5'],
'46' => [4, 6, 'AAC - 192'],
]);
define('CAPTCHA_FONT', [
'ARIBLK.TTF',
'IMPACT.TTF',
'TREBUC.TTF',
'TREBUCBD.TTF',
'TREBUCBI.TTF',
'TREBUCIT.TTF',
'VERDANA.TTF',
'VERDANAB.TTF',
'VERDANAI.TTF',
'VERDANAZ.TTF',
]);
define('CAPTCHA_BG', [
'captcha1.png',
'captcha2.png',
'captcha3.png',
'captcha4.png',
'captcha5.png',
'captcha6.png',
'captcha7.png',
'captcha8.png',
'captcha9.png',
]);
// Memcached details
define('MEMCACHE_HOST_LIST', [
// unix sockets are fast, and other people can't telnet into them
['host' => 'unix:///var/run/memcached.sock', 'port' => 0, 'buckets' => 1],
]);
define('CACHE_ID', 'ops');
// Deny cache access to keys without specified permission
define('CACHE_PERMISSION', [
'api_apps' => 'site_debug',
'catalogue' => 'site_debug'
]);
define('CACHE_BULK_FLUSH', 500);
define('CACHE_RESPONSE', [
0 => 'success',
1 => 'failure/delete ok',
16 => 'not found',
]);
define('CACHE_DB', [
'artist' => ['table' => 'artists_group', 'pk' => 'ArtistID'],
'collage' => ['table' => 'collages', 'pk' => 'ID'],
'torrent-group' => ['table' => 'torrents_group', 'pk' => 'ID'],
'user' => ['table' => 'users_main', 'pk' => 'ID'],
]);
define('CACHE_NAMESPACE', [
'artist' => [
'a1' => 'artist_%d',
'a2' => 'artist_comments_%d',
'a3' => 'artist_comments_%d_catalogue_0',
'a4' => 'artist_groups_%d',
'a5' => 'artists_collages_%d',
'a6' => 'artists_requests_%d',
'a7' => 'similar_positions_%d',
],
'collage' => [
'c1' => 'collage_%d',
'c2' => 'collage_display_%d',
'c3' => 'collage_subs_user_%d',
'c4' => 'collage_subs_user_new_%d',
],
'torrent-group' => [
'g1' => 'torrents_collages_%d',
'g2' => 'torrent_collages_personal_%d',
'g3' => 'torrents_cover_art_%d',
'g4' => 'torrents_details_%d',
'g5' => 'torrent_group_%d',
'g6' => 'torrent_group_light_%d',
'g7' => 'groups_artists_%d',
'g8' => 'tg_%d',
'g9' => 'tlist_%d',
],
'user' => [
'u1' => 'bookmarks_group_ids_%d',
'u2' => 'donor_info_%d',
'u3' => 'inbox_new_%d',
'u4' => 'u_%d',
'u6' => 'user_stats_%d',
'u7' => 'user_statgraphs_%d',
'u8' => 'user_tokens_%d',
],
]);
define('SITE_LAUNCH_YEAR', 2018);
define('ARTIST_MAIN', 1);
define('ARTIST_GUEST', 2);
define('ARTIST_REMIXER', 3);
define('ARTIST_COMPOSER', 4);
define('ARTIST_CONDUCTOR', 5);
define('ARTIST_DJ', 6);
define('ARTIST_PRODUCER', 7);
define('ARTIST_ARRANGER', 8);
define('ARTIST_TYPE', [
ARTIST_MAIN => 'Main',
ARTIST_GUEST => 'Guest',
ARTIST_REMIXER => 'Remixer',
ARTIST_COMPOSER => 'Composer',
ARTIST_CONDUCTOR => 'Conductor',
ARTIST_DJ => 'DJ/Compiler',
ARTIST_PRODUCER => 'Producer',
ARTIST_ARRANGER => 'Arranger',
]);
define('ARTIST_SECTION_ARRANGER', 1020);
define('ARTIST_SECTION_PRODUCER', 1021);
define('ARTIST_SECTION_COMPOSER', 1022);
define('ARTIST_SECTION_REMIXER', 1023);
define('ARTIST_SECTION_GUEST', 1024);
define('RANDOM_ARTIST_MIN_ENTRIES', 1);
define('RANDOM_COLLAGE_MIN_ENTRIES', 1);
define('RANDOM_TORRENT_MIN_SEEDS', 0);
define('IP_REGEXP', '/\b(?:\d{1,3}\.){3}\d{1,3}\b/');
define('URL_REGEXP_STEM', '((?:f|ht)tps?:\/\/)(?:' . str_replace('/', '', IP_REGEXP) . '|[\w-]+(?:\.[\w-]+)+)(?::\d{1,5})?(?:\/\S*)');
define('URL_REGEXP', '/^' . URL_REGEXP_STEM . '$/i');
define('CSS_REGEXP', '/^' . URL_REGEXP_STEM . '\.css(?:\?\S*)?$/i');
define('IMAGE_REGEXP', '/\b(' . URL_REGEXP_STEM . '\.(?:gif|png|webm|jpe?g|tiff?)(\?\S*)?)\b/i');
define('SITELINK_REGEXP', '(?:' . preg_quote(SITE_URL, '/') . (defined('ALT_SITE_URL') ? '|' . preg_quote(ALT_SITE_URL, '/') : '') . ')');
define('ARTIST_REGEXP', '/^' . SITELINK_REGEXP . '\/artist\.php\?.*?\bid=(?P<id>\d+)$/');
define('TGROUP_REGEXP', '/^' . SITELINK_REGEXP . '\/torrents\.php\?.*?\bid=(?P<id>\d+)\b/');
define('TORRENT_REGEXP', '/^' . SITELINK_REGEXP . '\/torrents\.php\?.*?\btorrentid=(?P<id>\d+)\b/');
define('EMAIL_REGEXP', '/^[\w-]+(?:\.[\w-]+)*(?:\+[.\w-]+)?@[\w-]+(?:\.[\w-]+)+$/');
define('USERNAME_REGEXP', '/\b(?:[01]$(*PRUNE)(*FAIL)|(?P<username>[\w.]{1,20}))\b/');
define('IMAGE_HOST_BANNED', ['badhost.example.com']);
define('IMAGE_HOST_RECOMMENDED', ['goodhost.example.com']);
define('DONOR_RANK_PRICE', 10);
define('DONOR_FIRST_INVITE_COUNT', 2);
define('TAG_OFFICIAL_COLUMNS', 4);
define('RANKING_WEIGHT', [
'uploaded' => [ 8, 'DataUpload'],
'downloaded' => [20, 'DataDownload'],
'uploads' => [25, 'Uploads'],
'requests' => [10, 'RequestsFilled'],
'posts' => [ 3, 'ForumPosts'],
'bounty' => [ 4, 'BountySpent'],
'artists' => [ 1, 'ArtistsAdded'],
'collage' => [ 5, 'CollageContribution'],
'votes' => [ 5, 'ReleaseVotes'],
'bonus' => [ 6, 'BonusPoints'],
'comment-t' => [18, 'CommentTorrent'],
]);
define('SHOW_LOGO', true);

View File

@@ -193,7 +193,7 @@ class DB_MYSQL {
public function connect() {
if (!$this->LinkID) {
$this->LinkID = mysqli_connect($this->Server, $this->User, $this->Pass, $this->Database, $this->Port, $this->Socket); // defined in config.php
$this->LinkID = mysqli_connect($this->Server, $this->User, $this->Pass, $this->Database, $this->Port, $this->Socket);
if (!$this->LinkID) {
$this->Errno = mysqli_connect_errno();
$this->Error = mysqli_connect_error();

View File

@@ -11,15 +11,17 @@
/*------------------------------------------------------*/
/********************************************************/
require_once(__DIR__ . '/../lib/bootstrap.php');
use Gazelle\Util\{Crypto, Irc, Text};
use Gazelle\Util\Crypto;
use Gazelle\Util\Irc;
use Gazelle\Util\Text;
// Deal with dumbasses
if (isset($_REQUEST['info_hash']) && isset($_REQUEST['peer_id'])) {
die('d14:failure reason40:Invalid .torrent, try downloading again.e');
}
require_once('../lib/bootstrap.php');
// Get the user's actual IP address if they're proxied.
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])
&& proxyCheck($_SERVER['REMOTE_ADDR'])
@@ -146,8 +148,6 @@ if (!empty($_SERVER['HTTP_AUTHORIZATION']) && $Document === 'ajax') {
}
if (!is_null($Viewer)) {
$viewerId = $Viewer->id();
// Change necessary triggers in external components
if ($Viewer->permitted('admin_clear_cache')) {
$Cache->enableCacheClear();

View File

@@ -275,7 +275,7 @@ class Text {
return false;
}
$Host = $URLInfo['host'];
if (empty($URLInfo['port']) && ($Host === SITE_HOST || (defined('ALT_SITE_HOST') && $Host === ALT_SITE_HOST))) {
if (empty($URLInfo['port']) && in_array($Host, [SITE_HOST, ALT_SITE_HOST])) {
$URL = '';
if (!empty($URLInfo['path'])) {
$URL .= ltrim($URLInfo['path'], '/'); // Things break if the path starts with '//'
@@ -298,7 +298,7 @@ class Text {
if (
!$info
|| empty($info['host'])
|| ($info['host'] !== SITE_HOST && (!defined('ALT_SITE_HOST') || $info['host'] !== ALT_SITE_HOST))
|| !in_array($info['host'], [SITE_HOST, ALT_SITE_HOST])
) {
return null;
}

View File

@@ -25,7 +25,7 @@ These mysql roles should be configured with different passwords and used in
the following places:
/etc/sphinxsearch/sphinx.conf
/var/www/gazelle/classes/config.php
/var/www/gazelle/lib/config.override.php
/var/www/ocelot/ocelot.conf
In practice, the roles will probably have specific IP addresses. localhost

View File

@@ -1,72 +1,79 @@
INSTALLATION NOTES
Note: We make no guarantee of completeness or accuracy of these install notes. The most up-to-date notes on a basic
install setup is found through our docker-compose.yml setup we use for development. Please reference it before asking
questions.
Note: We make no guarantee of completeness or accuracy of these install notes.
The most up-to-date notes on a basic install setup is found through our
docker-compose.yml setup we use for development. Please reference it before
asking questions.
Note: If overwhelmed by the these instructions, we urge you to NOT run a tracker in production. Doing such requires
more additional steps not covered here (setting up proxies, tunneling, LUKS encryption, TCP tuning, etc.) that messing
Note: If overwhelmed by the these instructions, we urge you to NOT run a tracker
in production. Doing such requires more additional steps not covered here
(setting up proxies, tunneling, LUKS encryption, TCP tuning, etc.) that messing
up would put the privacy / security of both yourself and your users at risk.
1. Install the PHP and JS dependencies to run / setup the site:
The docker installation does all this for you, but in production you need
to do this by hand.
1. First, install the PHP and JS dependencies to setup and run the site.
composer install
yarn install
2. First, you will need to setup the following services:
2. Install and setup the following services:
* MySQL
* memcached
* sphinxsearch
Depending on your OS, these may be available in the package manager. You can see
what versions of the above we support by looking at our [docker-compose.yml](../docker-compose.yml)
what versions of the above we support by looking at our docker-compose.yml
configuration.
For setting up memcached, we recommend giving it multiple threads and several GB of RAM, for example:
3. For up memcached, we recommend giving it multiple threads and several
gigs of RAM, for example:
memcached -d -m 5120 -s /var/run/memcached.sock -a 0777 -t4 -C -u nobody
This will give memcached 4 threads and 5GB of RAM. Tune this accordingly depending on how large your server
is, and traffic you get, but a the more RAM you give memcached, the quicker Gazelle will run as it heavily
relies on caching.
This will give memcached 4 threads and 5GB of RAM. Tune this accordingly
depending on how large your server and how many users you have. Look at
your cache eviction. If you are seeing hundreds of items evicted per second,
you need to scale up drastically. If you are seeing zero evictions, you
have allocated too much RAM and should scale down. Ideally you should only
see expired unfetched activity.
For sphinxsearch, we recommend you use the included sphinx.conf which can be found under .docker/sphinxsearch/sphinx.conf.
You can copy this to /etc/sphinx/sphinx.conf. You need to fill in the details of the SQL server though!
4. Create the required Mysql roles according to 01-MysqlRoles.txt
Use www.random.org to generate passwords.
You might also need to create the /var/lib/sphinx folder.
5. Review lib/config.php. Edit lib/config.override.php as needed.
You should be able to launch boris from the command line.
For documentation, read http://www.sphinxsearch.com/docs/current.html
After you've installed sphinx, create the indices:
/usr/bin/indexer -c /etc/sphinx/sphinx.conf --all
3. Configure config variables. First, you will want to copy over the template file ([classes/config.template.php](../classes/config.template.php))
to `classes/config.php`, and then go through and configure to your needs. See the comments within that file on what you will need to change.
4. After configuring the config.php file in the step above (or minimially the SQL* variables), you can use phinx to setup your DB by running:
6. Run the phinx migrations and seeds to populate the database.
vendor/bin/phinx migrate
5. Generate stylesheets and their previews by running the following:
7. Configure Sphinx - we recommend you use the included .docker/sphinxsearch/sphinx.conf
You can copy this to /etc/sphinx/sphinx.conf. You need to fill in the
details of the SQL server from lib/config.override.php and you may need to
create the `/var/lib/sphinx` folder.
More information is available at: https://sphinxsearch.com/docs/current.html
Run the indexer to finish the setup:
/usr/bin/indexer -c /etc/sphinx/sphinx.conf --all
8. Generate stylesheets and their previews by running the following:
yarn build
Note, to generate the previews requires a chrome instance to be installed onto the computer.
Note, generating the previews requires a Chrome instance on the host.
6. Setup your web server. We recommend using nginx (https://www.nginx.com/). A sample configuration for nginx can be found in .docker/web/nginx.conf.
9. Setup your web server. We recommend using nginx (https://www.nginx.com/).
A sample configuration for nginx can be found in .docker/web/nginx.conf.
7. Sign up. The first user is made a SysOp!
10. Set up cron jobs. You need a cron job for the scheduler, a cron job for
the peerupdate (all groups are cached, but the peer counts change often,
so peerupdate is a script to update them), and the two Sphinx indices.
8. Set up cron jobs. You need a cron job for the schedule, a cron job for the peerupdate (all groups are cached, but the peer counts change often,
so peerupdate is a script to update them), and the two Sphinx indices. These are our cron jobs. SCHEDULE_KEY is the same as in classes/config.php:
see docs/crontab
0,15,30,45 * * * * /usr/bin/php /var/www/vhosts/what/schedule.php SCHEDULE_KEY >> /root/schedule.log
10,25,40,55 * * * * /usr/bin/php /var/www/vhosts/what/peerupdate.php SCHEDULE_KEY >> /root/peerupdate.log
* * * * * /usr/bin/indexer -c /etc/sphinx/sphinx.conf --rotate delta requests_delta log_delta >/dev/null
5 0,12 * * * /usr/bin/indexer -c /etc/sphinx/sphinx.conf --rotate --all >>/root/sphinx-indexer.log
An example cron script can be seen in .docker/web/crontab
9. Start modifying stuff. Hopefully, everything will have gone smoothly so far and nothing will have exploded (ha ha ha)
11. Start modifying stuff. Hopefully, everything will have gone smoothly so far
and nothing will have exploded (ha ha ha)

7
docs/crontab Normal file
View File

@@ -0,0 +1,7 @@
# These are our cron jobs.
# Replace SCHEDULE_KEY with the value referenced in lib/config.php / lib/config.override.php
0,15,30,45 * * * * /usr/bin/php /var/www/scripts/schedule.php SCHEDULE_KEY >> /root/schedule.log
10,25,40,55 * * * * /usr/bin/php /var/www/scripts/peerupdate.php SCHEDULE_KEY >> /root/peerupdate.log
* * * * * /usr/bin/indexer -c /etc/sphinx/sphinx.conf --rotate delta requests_delta log_delta >/dev/null
5 */2 * * * /usr/bin/indexer -c /etc/sphinx/sphinx.conf --rotate --all >>/root/sphinx-indexer.log

View File

@@ -5,7 +5,7 @@
$now = microtime(true); // To track how long a page takes to create
if (!defined('SITE_NAME')) {
require_once(__DIR__ . '/../classes/config.php');
require_once(__DIR__ . '/config.php');
require_once(__DIR__ . '/../lib/util.php');
require_once(__DIR__ . '/../vendor/autoload.php');
}

View File

@@ -0,0 +1,25 @@
<?php
// Copy these variables to your config.override.php in a development environment.
// Change as required.
define('SITE_URL', 'http://localhost:8080');
define('DISABLE_TRACKER', true);
define('DISABLE_IRC', true);
define('DEBUG_EMAIL', true);
define('DEBUG_MODE', true);
define('DEBUG_WARNINGS', true);
define('DEBUG_UPLOAD_NOTIFICATION', true);
define('OPEN_REGISTRATION', true);
define('MEMCACHE_HOST_LIST', [['host' => 'memcached', 'port' => 11211, 'buckets' => 1]]);
define('ENCKEY', "");
define('SCHEDULE_KEY', "");
define('RSS_HASH', "");
define('SEEDBOX_SALT', "");
define('AVATAR_SALT', "");

996
lib/config.php Normal file
View File

@@ -0,0 +1,996 @@
<?php
/* This file defines all the configuration required to run a Gazelle
* installation. Much can be left as-is in development. For production, a
* number of keys will need to be changed. This is done in the
* config.override.php file which must reside in the same directory as this
* file. (You can also also create an override.php file for development/staging
* environments if required).
*
* The declarations in this file must all follow the format:
*
* defined('FOO') or define('FOO', 'bar');
*
* The override file then only need declare:
*
* define('FOO', 'rat');
*
* to change to a site-specific value. These gymnastics are necessary
* because a redefinition of a constant causes PHP to complain.
*
* Pro-tip: the development.config.php and production.config.php provide
* the list of constants that will most likely need to appear in a
* config.override.php file. The docker installation takes care of this
* automatically.
*
* When adding a new value, consider whether the setting is appropriate for
* production directly, or whether it is a secret and therefore needs to be
* overridden. The less things that have to be overridden, the easier things
* become.
*
* You are expected to read this file in its entirety before setting out.
*/
if (file_exists(__DIR__ . '/config.override.php')) {
require_once(__DIR__ . '/config.override.php');
}
// ------------------------------------------------------------------------
// General settings. It is more than likely that you will need to change
// these in production.
// The name of your site!
defined('SITE_NAME') or define('SITE_NAME', 'Gazelle');
// The DNS name (A record) of your site.
defined('SITE_HOST') or define('SITE_HOST', 'localhost');
// The URL of the site. There is no capability to offer both SSL and
// non-SSL versions of the site in production. In the development
// environment you will need to override this to http (unless you
// want to set up your own CA).
defined('SITE_URL') or define('SITE_URL', 'https://' . SITE_HOST);
// The year the site was launched. This will be generated automatically
// in the Docker environment. You only need to copy it to the production
// override afterwards.
defined('SITE_LAUNCH_YEAR') or define('SITE_LAUNCH_YEAR', 2018);
// Is this the beta version of the site?
defined('BETA') or define('BETA', false);
// Path for storing temporary files (should be moved out of the root partition)
defined('TMPDIR') or define('TMPDIR', '/tmp');
// Paths for storing uploaded assets outside the database. See scripts/generate-storage-dirs
// Should also be moved out of the root partition.
defined('STORAGE_PATH_TORRENT') or define('STORAGE_PATH_TORRENT', '/var/lib/gazelle/torrent');
defined('STORAGE_PATH_RIPLOG') or define('STORAGE_PATH_RIPLOG', '/var/lib/gazelle/riplog');
defined('STORAGE_PATH_RIPLOGHTML') or define('STORAGE_PATH_RIPLOGHTML', '/var/lib/gazelle/riploghtml');
// Host static assets (images, css, js) on another server.
// In development it is just a folder
defined('STATIC_SERVER') or define('STATIC_SERVER', 'static');
// Where is the repository physically stored (and hence where the document
// root lives). This is needed so that Gazelle knows where static assets are,
// in order to stat them for cache-busting via modification timestamps.
defined('SERVER_ROOT') or define('SERVER_ROOT', '/var/www');
// If you are running a beta version and you really need to know where the
// production files are, set the path here. The only reason that this is
// still needed is if you are storing riplogs in the document root and
// serving them directly. On a new installation this may be left as-is.
defined('SERVER_ROOT') or define('SERVER_ROOT', '/var/www');
defined('SERVER_ROOT_LIVE') or define('SERVER_ROOT_LIVE', SERVER_ROOT);
// System account used to generate Editing Requests.
defined('SYSTEM_USER_ID') or define('SYSTEM_USER_ID', 17);
// User with no privileges to a show a user what their paranoia looks like.
defined('PARANOIA_PREVIEW_USER') or define('PARANOIA_PREVIEW_USER', SYSTEM_USER_ID);
// Alternative hostname for site, such as for beta deploy (e.g. beta.example.com)
// This is important for BB code rendering to recognize our own urls as local,
// regardless of which one is used (e.g. pasted in a forum).
defined('ALT_SITE_HOST') or define('ALT_SITE_HOST', SITE_HOST);
defined('ALT_SITE_URL') or define('ALT_SITE_URL', SITE_URL);
// ------------------------------------------------------------------------
// Secrets
// ALL OF THESE MUST BE OVERRIDDEN
// Symmetric encryption key for cookies and API tokens. Changing this after
// the site is launched will invalidate everyone's sessions and tokens.
// This may be what you need in the event of a compromise.
defined('ENCKEY') or define('ENCKEY', 'thisisfine');
// This value must be passed as an argument on the crontab entry of schedule.php.
// It may be changed at any time as long as both places are kept in synch.
defined('SCHEDULE_KEY') or define('SCHEDULE_KEY', 'thisisfine');
// Extra salt added into RSS authentication
defined('RSS_HASH') or define('RSS_HASH', 'thisisfine');
// Seedbox ids are hashified with this salt.
defined('SEEDBOX_SALT') or define('SEEDBOX_SALT', 'thisisfine');
// User avatars are hashed with this salt.
defined('AVATAR_SALT') or define('AVATAR_SALT', 'thisisfine');
// ------------------------------------------------------------------------
// MySQL settings
// None of these values need to be adjusted for the local Docker
// environment. It is assumed that all will be changed in production.
// Hostname of the mysql instance.
defined('SQLHOST') or define('SQLHOST', 'mysql');
// The TCP port to use.
defined('SQLPORT') or define('SQLPORT', 3306);
// The socket to use. See the php documentation on mysqli::connect
// to understand how these fit together. If the database and PHP interpreter
// are running on the same host then you want to use a socket.
defined('SQLSOCK') or define('SQLSOCK', false);
// The name of the database schema.
defined('SQLDB') or define('SQLDB', 'gazelle');
// The username of the website account. See the docs/01-MysqlRoles.txt
// document for details on what roles need to be configured.
defined('SQLLOGIN') or define('SQLLOGIN', 'gazelle');
// The password of the above account.
defined('SQLPASS') or define('SQLPASS', 'password');
// The username of the Phinx account (used for schema modifications).
// In production, this account will have a different set of grants compared
// to the website account (so that if the website account is compromised, it
// cannot be used to drop tables or any other malicious activities).
defined('SQL_PHINX_USER') or define('SQL_PHINX_USER', SQLLOGIN);
// Password of the above.
defined('SQL_PHINX_PASS') or define('SQL_PHINX_PASS', SQLPASS);
// ------------------------------------------------------------------------
// Postgresql settings
// Hostname of the Postgresql backend
defined('GZPG_HOST') or define('GZPG_HOST', 'pg');
// Default port of the backend.
// No need to change unless you're running on a non-standard port.
defined('GZPG_PORT') or define('GZPG_PORT', 5432);
// Name of the default schema
defined('GZPG_DB') or define('GZPG_DB', 'gzpg');
// Role name used by the website (with limited privileges)
defined('GZPG_USER') or define('GZPG_USER', 'pguser');
// Password of the above
defined('GZPG_PASSWORD') or define('GZPG_PASSWORD', 'pgpw');
// ------------------------------------------------------------------------
// Sphinx settings
// Hostname of the Sphinx fulltext search engine. The hostnames
// will probably need to be changed in production but the default
// port numbers will be fine.
defined('SPHINX_HOST') or define('SPHINX_HOST', 'sphinxsearch');
// Default port of the above.
defined('SPHINX_PORT') or define('SPHINX_PORT', 9312);
// Hostname of the Sphinx query endpoint.
defined('SPHINXQL_HOST') or define('SPHINXQL_HOST', SPHINX_HOST);
// Default port of the above.
defined('SPHINXQL_PORT') or define('SPHINXQL_PORT', 9306);
// Socket path, if communicating over localhost.
defined('SPHINXQL_SOCK') or define('SPHINXQL_SOCK', false);
// The maximum match count must not exceed the Sphinx configuration
// (Default is 1000).
defined('SPHINX_MAX_MATCHES') or define('SPHINX_MAX_MATCHES', 1000);
// ------------------------------------------------------------------------
// Ocelot settings
// If you have not set Ocelot up in the development environment then this
// should be overridden and set to true.
defined('DISABLE_TRACKER') or define('DISABLE_TRACKER', false);
// Hostname of the Ocelot instance
defined('TRACKER_HOST') or define('TRACKER_HOST', 'localhost');
// TCP port of the Ocelot instance
// Must match the Ocelot configuration
defined('TRACKER_PORT') or define('TRACKER_PORT', 34000);
// Shared secret that is compiled into Ocelot (see config.cpp). Must
// be exactly 32 alphanumeric characters.
defined('TRACKER_SECRET') or define('TRACKER_SECRET', 'abcdefghijklmnopqrstuvwxyz123456');
// Second shared secret that is compiled into Ocelot (see config.cpp). Must
// be exactly 32 alphanumeric characters.
defined('TRACKER_REPORTKEY') or define('TRACKER_REPORTKEY', 'abcdefghijklmnopqrstuvwxyz123456');
// Announce URLs for users. Some clients cannot do HTTPS, and some people
// persist in using these clients, which is a great pity.
define('ANNOUNCE_HTTP_URL', 'http://' . TRACKER_HOST);
define('ANNOUNCE_HTTPS_URL', 'https://' . TRACKER_HOST);
// ------------------------------------------------------------------------
// Memcached settings
// On production, you probably want the memcached instance to be sitting on
// the same host as the PHP interpreter. In which case you may leave this as-is.
defined('MEMCACHE_HOST_LIST') or define('MEMCACHE_HOST_LIST', [
['host' => 'unix:///var/run/memcached.sock', 'port' => 0, 'buckets' => 1],
]);
// Memcached prefix (if ever you need to run another namespace in the same
// memcached instance).
defined('CACHE_ID') or define('CACHE_ID', 'ops');
// ------------------------------------------------------------------------
// Email settings
// The DNS name (MX record) of your email hostname.
defined('MAIL_HOST') or define('MAIL_HOST', 'mail.' . SITE_HOST);
// Set to true in a development environment. Instead of delivery, messages
// will be written to files in TMPDIR.
defined('DEBUG_EMAIL') or define('DEBUG_EMAIL', false);
// ------------------------------------------------------------------------
// IRC settings
defined('DISABLE_IRC') or define('DISABLE_IRC', false);
defined('IRC_SOCKET_LISTEN_ADDRESS') or define('IRC_SOCKET_LISTEN_ADDRESS', 'localhost');
defined('IRC_SOCKET_LISTEN_PORT') or define('IRC_SOCKET_LISTEN_PORT', 51010);
defined('BOT_NICK') or define('BOT_NICK', 'Rippy');
defined('BOT_SERVER') or define('BOT_SERVER', 'localhost');
defined('BOT_PORT') or define('BOT_PORT', 7000);
defined('BOT_CHAN') or define('BOT_CHAN', '#mygazelle');
defined('ADMIN_CHAN') or define('ADMIN_CHAN', '#admin');
defined('LAB_CHAN') or define('LAB_CHAN', '#lab');
defined('STATUS_CHAN') or define('STATUS_CHAN', '#status');
defined('MOD_CHAN') or define('MOD_CHAN', '#staff');
defined('BOT_DISABLED_CHAN') or define('BOT_DISABLED_CHAN', '#blocked');
defined('BOT_REPORT_CHAN') or define('BOT_REPORT_CHAN', '#reports');
// ------------------------------------------------------------------------
// Push server settings
defined('PUSH_SOCKET_LISTEN_ADDRESS') or define('PUSH_SOCKET_LISTEN_ADDRESS', 'localhost');
defined('PUSH_SOCKET_LISTEN_PORT') or define('PUSH_SOCKET_LISTEN_PORT', 6789);
// ------------------------------------------------------------------------
// Site settings
// Leaving these as is will work, but you will probably want to change them
// either in development or production, or both. Any defines that are likely
// to require a change will be listed in the example override files.
// When in doubt, read the source.
// Display the site logo on the public pages.
defined('SHOW_LOGO') or define('SHOW_LOGO', true);
// How many enabled users are allowed? (Set to 0 for unlimited).
defined('USER_LIMIT') or define('USER_LIMIT', 5000);
// Set to false if you want to display the login form directly.
defined('SHOW_PUBLIC_INDEX') or define('SHOW_PUBLIC_INDEX', true);
// Can J. Random User create their own account?
defined('OPEN_REGISTRATION') or define('OPEN_REGISTRATION', false);
// Can inactive users enable themselves automatically?
defined('FEATURE_EMAIL_REENABLE') or define('FEATURE_EMAIL_REENABLE', false);
// Refuse connections from Tor exit nodes?
defined('BLOCK_TOR') or define('BLOCK_TOR', true);
// Connect to remote resources with curl via a proxy
defined('HTTP_PROXY') or define('HTTP_PROXY', false);
// Block Opera Mini proxy?
defined('BLOCK_OPERA_MINI') or define('BLOCK_OPERA_MINI', true);
// Should PHP errors be shown in the output?
defined('DEBUG_MODE') or define('DEBUG_MODE', false);
// Can developer+ see PHP warnings in the site footer?
defined('DEBUG_WARNINGS') or define('DEBUG_WARNINGS', true);
// Do upload notifications need to be traced? (Results written to TMPDIR)
defined('DEBUG_UPLOAD_NOTIFICATION') or define('DEBUG_UPLOAD_NOTIFICATION', false);
// Do contest payouts need to be tested?
// Results are always written to TMPDIR/payout-contest-<id>.txt
// If true, no PMs sent to users, no db updates performed.
defined('DEBUG_CONTEST_PAYOUT') or define('DEBUG_CONTEST_PAYOUT', false);
// if null, no attempt will be made to contact the last.fm website.
defined('LASTFM_API_KEY') or define('LASTFM_API_KEY', null);
// Fake useragent (to override default cURL useragent string).
defined('FAKE_USERAGENT') or define('FAKE_USERAGENT', 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.1 Safari/537.11');
// How much upload buffer to members start out with? (3 GiB)
defined('STARTING_UPLOAD') or define('STARTING_UPLOAD', 3 * 1024 * 1024 * 1024);
// Can freeleech (FL) tokens be stacked?
defined('STACKABLE_FREELEECH_TOKENS') or define('STACKABLE_FREELEECH_TOKENS', true);
// What size does a token represent? (512 MiB)
defined('BYTES_PER_FREELEECH_TOKEN') or define('BYTES_PER_FREELEECH_TOKEN', 512 * 1024 * 1024);
// How long does an activated token last before it is purged?
defined('FREELEECH_TOKEN_EXPIRY_DAYS') or define('FREELEECH_TOKEN_EXPIRY_DAYS', 30);
// How much buffer does a request vote represent?
defined('REQUEST_MIN') or define('REQUEST_MIN', 100 * 1024 * 1024); // 100 MiB
// How much request buffer is removed as tax? (0 = none, 0.1 = 10%, 0.25 = 25% and so on).
defined('REQUEST_TAX') or define('REQUEST_TAX', 0.0);
// Retain this many days of hourly snapshots.
defined('DELETE_USER_STATS_DAILY_DAY') or define('DELETE_USER_STATS_DAILY_DAY', 15);
// Retain this many months of daily snapshots.
defined('DELETE_USER_STATS_MONTHLY_DAY') or define('DELETE_USER_STATS_MONTHLY_DAY', 120);
// How many invites do new users receive?
defined('STARTING_INVITES') or define('STARTING_INVITES', 0);
// How many invites does a Donor receive?
defined('DONOR_INVITES') or define('DONOR_INVITES', 2);
// How much fiat currency is required to acquire a donor point
defined('DONOR_RANK_PRICE') or define('DONOR_RANK_PRICE', 10);
// Minimum permission.Level allowed to purchase invites.
defined('MIN_INVITE_CLASS') or define('MIN_INVITE_CLASS', 150);
// Lowest permissions.Level of staff user classes
defined('STAFF_LEVEL') or define('STAFF_LEVEL', 820);
// Threshold for detecting duplicate IP addresses.
defined('IP_OVERLAPS') or define('IP_OVERLAPS', 5);
// Maximum length of a pathname in torrent files and zip archives.
defined('MAX_PATH_LEN') or define('MAX_PATH_LEN', 200);
// How many collages to list on a group page when it appears in many collages.
defined('COLLAGE_SAMPLE_THRESHOLD') or define('COLLAGE_SAMPLE_THRESHOLD', 4);
// How many personal collages to list on a group page when it appears in many collages.
defined('PERSONAL_COLLAGE_SAMPLE_THRESHOLD') or define('PERSONAL_COLLAGE_SAMPLE_THRESHOLD', 4);
// Number of groups an artist must have to be selected at random.
defined('RANDOM_ARTIST_MIN_ENTRIES') or define('RANDOM_ARTIST_MIN_ENTRIES', 3);
// Number of entries a collage must have to be selected at random.
defined('RANDOM_COLLAGE_MIN_ENTRIES') or define('RANDOM_COLLAGE_MIN_ENTRIES', 5);
// Number of seeds a torrent must have to be selected at random.
defined('RANDOM_TORRENT_MIN_SEEDS') or define('RANDOM_TORRENT_MIN_SEEDS', 3);
// How many torrents can a user delete before they must take a break?
defined('USER_TORRENT_DELETE_MAX') or define('USER_TORRENT_DELETE_MAX', 3);
// How long a break must a user take if they delete too many torrents?
defined('USER_TORRENT_DELETE_HOURS') or define('USER_TORRENT_DELETE_HOURS', 24);
// Which image hosts are acceptable and which aren't?
defined('IMAGE_HOST_BANNED') or define('IMAGE_HOST_BANNED', ['badhost.example.com']);
defined('IMAGE_HOST_RECOMMENDED') or define('IMAGE_HOST_RECOMMENDED', ['goodhost.example.com']);
// What are the relative weights of user percentiles, in order to calculate
// the overall percentile rank.
defined('RANKING_WEIGHT') or define('RANKING_WEIGHT', [
'uploaded' => [ 8, 'DataUpload'],
'downloaded' => [20, 'DataDownload'],
'uploads' => [25, 'Uploads'],
'requests' => [10, 'RequestsFilled'],
'posts' => [ 3, 'ForumPosts'],
'bounty' => [ 4, 'BountySpent'],
'artists' => [ 1, 'ArtistsAdded'],
'collage' => [ 5, 'CollageContribution'],
'votes' => [ 5, 'ReleaseVotes'],
'bonus' => [ 6, 'BonusPoints'],
'comment-t' => [18, 'CommentTorrent'],
]);
// Successive login failures generate increasing delays.
defined('LOGIN_ATTEMPT_BACKOFF') or define('LOGIN_ATTEMPT_BACKOFF', [
0,
30,
90,
60 * 5, // 5 minutes
60 * 15,
3600 * 3, // 3 hours
3600 * 6,
86400,
86400 * 3,
86400 * 7,
]);
// Set to TagID of 'test' to ignore uploads tagged with 'test' for the
// recent uploads widget.
defined('HOMEPAGE_TAG_IGNORE') or define('HOMEPAGE_TAG_IGNORE', [0]);
// ------------------------------------------------------------------------
// Inactivity reaper settings
//
// There are two types of reaping: uploads that are never announced by
// the initial uploader (never seeded), and uploads that were seeded for
// for a while and since then the size of the swarm has dropped to zero
// (unseeded). To eliminate reaping completely, the corresponding
// scheduled tasks should be disabled.
// It is easier to specify the first and second unseeded notifications
// in terms of the interval remaining until reaping.
define('MAX_NEVER_SEEDED_PER_RUN', 1000);
define('REMOVE_NEVER_SEEDED_HOUR', 72);
define('NOTIFY_NEVER_SEEDED_INITIAL_HOUR', 8); // 8 hours after upload
define('NOTIFY_NEVER_SEEDED_FINAL_HOUR', REMOVE_NEVER_SEEDED_HOUR - 24);
define('MAX_UNSEEDED_PER_RUN', 1000);
define('REMOVE_UNSEEDED_HOUR', 24 * 28); // 28 days
define('NOTIFY_UNSEEDED_INITIAL_HOUR', REMOVE_UNSEEDED_HOUR - (24 * 10));
define('NOTIFY_UNSEEDED_FINAL_HOUR', REMOVE_UNSEEDED_HOUR - (24 * 3));
// ------------------------------------------------------------------------
// Source flag settings
// Source flag for torrent files. Should be unique across the wider tracker
// space to enable easy cross-seeding.
defined('SOURCE') or define('SOURCE', 'OPS');
// Acceptable source flag from a prior site.
defined('GRANDFATHER_SOURCE') or define('GRANDFATHER_SOURCE', '');
// Epoch time of cut-off for accepting grandfathered source flags.
defined('GRANDFATHER_OLD_SOURCE') or define('GRANDFATHER_OLD_SOURCE', 0);
// Epoch time of cut-off for accepting torrents with no source flags (useful if you
// introduce source flags after launch).
defined('GRANDFATHER_NO_SOURCE') or define('GRANDFATHER_NO_SOURCE', 0);
// ------------------------------------------------------------------------
// Bonus point settings
// Points awarded for uploads.
defined('BONUS_AWARD_FLAC_PERFECT') or define('BONUS_AWARD_FLAC_PERFECT', 400);
defined('BONUS_AWARD_FLAC') or define('BONUS_AWARD_FLAC', 30);
defined('BONUS_AWARD_MP3') or define('BONUS_AWARD_MP3', 30);
defined('BONUS_AWARD_OTHER') or define('BONUS_AWARD_OTHER', 10);
// Tax when donating to bonus pools.
defined('BONUS_POOL_TAX_STD') or define('BONUS_POOL_TAX_STD', 0.9);
defined('BONUS_POOL_TAX_ELITE') or define('BONUS_POOL_TAX_ELITE', 0.8);
defined('BONUS_POOL_TAX_TM') or define('BONUS_POOL_TAX_TM', 0.7);
defined('BONUS_POOL_TAX_STAFF') or define('BONUS_POOL_TAX_STAFF', 0.5);
// ------------------------------------------------------------------------
// Pagination
defined('BOOKMARKS_PER_PAGE') or define('BOOKMARKS_PER_PAGE', 20);
defined('COLLAGES_PER_PAGE') or define('COLLAGES_PER_PAGE', 25);
defined('CONTEST_ENTRIES_PER_PAGE') or define('CONTEST_ENTRIES_PER_PAGE', 50);
defined('FRIENDS_PER_PAGE') or define('FRIENDS_PER_PAGE', 20);
defined('INVITES_PER_PAGE') or define('INVITES_PER_PAGE', 50);
defined('ITEMS_PER_PAGE') or define('ITEMS_PER_PAGE', 50);
defined('IPS_PER_PAGE') or define('IPS_PER_PAGE', 50);
defined('LOG_ENTRIES_PER_PAGE') or define('LOG_ENTRIES_PER_PAGE', 50);
defined('MESSAGES_PER_PAGE') or define('MESSAGES_PER_PAGE', 25);
defined('PEERS_PER_PAGE') or define('PEERS_PER_PAGE', 100);
defined('POSTS_PER_PAGE') or define('POSTS_PER_PAGE', 25);
defined('REPORTS_PER_PAGE') or define('REPORTS_PER_PAGE', 10);
defined('REQUESTS_PER_PAGE') or define('REQUESTS_PER_PAGE', 25);
defined('TOPICS_PER_PAGE') or define('TOPICS_PER_PAGE', 50);
defined('TORRENTS_PER_PAGE') or define('TORRENTS_PER_PAGE', 50);
defined('TORRENT_COMMENTS_PER_PAGE') or define('TORRENT_COMMENTS_PER_PAGE', 10);
defined('USERS_PER_PAGE') or define('USERS_PER_PAGE', 50);
defined('WIKI_ARTICLES_PER_PAGE') or define('WIKI_ARTICLES_PER_PAGE', 25);
defined('AJAX_USERS_PER_PAGE') or define('AJAX_USERS_PER_PAGE', 30);
// ------------------------------------------------------------------------
// User Referral settings
// Can people from approved trackers create their own account?
defined('OPEN_EXTERNAL_REFERRALS') or define('OPEN_EXTERNAL_REFERRALS', false);
// Where to forward cURL queries for referrals (URL with trailiing slash).
defined('REFERRAL_BOUNCER') or define('REFERRAL_BOUNCER', '');
// Symmetric encryption key for bouncer communication.
defined('REFERRAL_KEY') or define('REFERRAL_KEY', hash('sha512', 'sekret'));
// Should referrals send invitation emails.
defined('REFERRAL_SEND_EMAIL') or define('REFERRAL_SEND_EMAIL', false);
// Code names of referral sites (must match the db).
defined('REFERRAL_SITES') or define('REFERRAL_SITES', ['ABC', 'DEF']);
// ------------------------------------------------------------------------
// Recovery settings
// Is recovery open?
defined('RECOVERY') or define('RECOVERY', false);
// Is buffer from the previous site restituted to recovered users?
defined('RECOVERY_BUFFER') or define('RECOVERY_BUFFER', false);
// Random salt for generating temporary filenames
defined('RECOVERY_SALT') or define('RECOVERY_SALT', 'thisisfine');
// Where are uploads for recovery proof stored?
defined('RECOVERY_PATH') or define('RECOVERY_PATH', '');
// Highest torrent id from a previous incarnation
defined('MAX_PREV_TORRENT_ID') or define('MAX_PREV_TORRENT_ID', 0);
// In which database schema are the users of the previous site stored?
defined('RECOVERY_DB') or define('RECOVERY_DB', '');
// Which table stores the old/new user mappings?
defined('RECOVERY_MAPPING_TABLE') or define('RECOVERY_MAPPING_TABLE', 'users_' . RECOVERY_DB . '_mapping');
// Which table stores proof about prior IRC users?
defined('RECOVERY_IRC_TABLE') or define('RECOVERY_IRC_TABLE', 'users_' . RECOVERY_DB . '_irc');
// Are recovery requests that validate correctly automatically accepted?
defined('RECOVERY_AUTOVALIDATE') or define('RECOVERY_AUTOVALIDATE', true);
// How many validations are performed per scheduled run?
defined('RECOVERY_AUTOVALIDATE_LIMIT') or define('RECOVERY_AUTOVALIDATE_LIMIT', 20);
// Which user issues recovery invites?
defined('RECOVERY_ADMIN_ID') or define('RECOVERY_ADMIN_ID', SYSTEM_USER_ID);
// What name is given to the recovery inviter?
defined('RECOVERY_ADMIN_NAME') or define('RECOVERY_ADMIN_NAME', 'RecoveryBot');
// How many pending people can be reassigned buffer in a single run?
defined('RECOVERY_BUFFER_REASSIGN_LIMIT') or define('RECOVERY_BUFFER_REASSIGN_LIMIT', 100);
// Security check to prevent <form> stuffing
defined('RECOVERY_PAIR_SALT') or define('RECOVERY_PAIR_SALT', 'thisisfine');
// ------------------------------------------------------------------------
// Permission.ID labels
// Permission ID of primary class.
defined('USER') or define('USER', 2);
defined('MEMBER') or define('MEMBER', 3);
defined('POWER') or define('POWER', 4);
defined('ELITE') or define('ELITE', 5);
defined('TORRENT_MASTER') or define('TORRENT_MASTER', 7);
defined('POWER_TM') or define('POWER_TM', 22);
defined('ELITE_TM') or define('ELITE_TM', 23);
defined('ULTIMATE_TM') or define('ULTIMATE_TM', 48);
defined('FORUM_MOD') or define('FORUM_MOD', 28);
defined('MOD') or define('MOD', 11);
defined('SYSOP') or define('SYSOP', 15);
// Permission ID of secondary class.
defined('DONOR') or define('DONOR', 20);
defined('FLS_TEAM') or define('FLS_TEAM', 23);
defined('INTERVIEWER') or define('INTERVIEWER', 30);
defined('RECRUITER') or define('RECRUITER', 41);
defined('VIP') or define('VIP', 6);
// ------------------------------------------------------------------------
// Well-known forum settings
// The secret Donor forum.
defined('DONOR_FORUM') or define('DONOR_FORUM', 70);
// Where Edit Requests are sent.
defined('EDITING_FORUM_ID') or define('EDITING_FORUM_ID', 34);
// Staff forum (for polls that display the names of voters).
defined('STAFF_FORUM_ID') or define('STAFF_FORUM_ID', 5);
// Forums where voter names are revealed.
defined('FORUM_REVEAL_VOTER') or define('FORUM_REVEAL_VOTER', []);
// Where trashed threads go.
defined('TRASH_FORUM_ID') or define('TRASH_FORUM_ID', 4);
// The Album of the Month (AotM) forum.
defined('AOTM_FORUM_ID') or define('AOTM_FORUM_ID', 51);
// The Showcase (Vanity House) forum.
defined('VANITY_HOUSE_FORUM_ID') or define('VANITY_HOUSE_FORUM_ID', 18);
// The client whitelist suggestion forum.
defined('CLIENT_WHITELIST_FORUM_ID') or define('CLIENT_WHITELIST_FORUM_ID', 680);
// Number of thread posts per cache key.
defined('THREAD_CATALOGUE') or define('THREAD_CATALOGUE', 500);
// ------------------------------------------------------------------------
// Well-known Wiki pages
// The index page (to prevent it from ever being deleted).
defined('INDEX_WIKI_PAGE_ID') or define('INDEX_WIKI_PAGE_ID', 1);
// The rules page.
defined('RULES_WIKI_PAGE_ID') or define('RULES_WIKI_PAGE_ID', 127);
// Information about Source Flags.
defined('SOURCE_FLAG_WIKI_PAGE_ID') or define('SOURCE_FLAG_WIKI_PAGE_ID', 113);
// ------------------------------------------------------------------------
// None of the settings below here should need to be changed. They are here
// simply to not have them in the code, either because they are magic
// numbers or they are used in more than place. Any changes here will most
// likely require a corresonding change in the code or stylesheets.
// ------------------------------------------------------------------------
// Maximum length of a custom user title.
defined('USER_TITLE_LENGTH') or define('USER_TITLE_LENGTH', 1024);
// Magic constant of locked accounts.
defined('STAFF_LOCKED') or define('STAFF_LOCKED', 1);
// Width of avatars (as displayed in forums and profile page).
defined('AVATAR_WIDTH') or define('AVATAR_WIDTH', 150);
// Width of similar artists map.
defined('SIMILAR_WIDTH') or define('SIMILAR_WIDTH', 720);
// Height of similar artists map.
defined('SIMILAR_HEIGHT') or define('SIMILAR_HEIGHT', 500);
// Number of columns in the official tags toolbox
defined('TAG_OFFICIAL_COLUMNS') or define('TAG_OFFICIAL_COLUMNS', 4);
// ------------------------------------------------------------------------
// Upload configuration
// Upload categories.
defined('CATEGORY') or define('CATEGORY', [
'Music',
'Applications',
'E-Books',
'Audiobooks',
'E-Learning Videos',
'Comedy',
'Comics'
]);
defined('CATEGORY_GROUPED') or define('CATEGORY_GROUPED', array_intersect(['Music'], CATEGORY));
// Icons of upload categories.
defined('CATEGORY_ICON') or define('CATEGORY_ICON', [
'music.png',
'apps.png',
'ebook.png',
'audiobook.png',
'elearning.png',
'comedy.png',
'comics.png'
]);
// Allowed upload formats.
defined('FORMAT') or define('FORMAT', [
'MP3',
'FLAC',
'Ogg Vorbis',
'AAC',
'AC3',
'DTS'
]);
// Allowed upload encodings.
defined('ENCODING') or define('ENCODING', [
'Lossless',
'24bit Lossless',
'V0 (VBR)',
'V1 (VBR)',
'V2 (VBR)',
'320',
'256',
'192',
'160',
'128',
'96',
'64',
'APS (VBR)',
'APX (VBR)',
'q8.x (VBR)',
'Other'
]);
// Allowed upload media.
defined('MEDIA') or define('MEDIA', [
'CD',
'WEB',
'Vinyl',
'DVD',
'BD',
'Soundboard',
'SACD',
'DAT',
'Cassette',
]);
// ------------------------------------------------------------------------
// Paranoia
// Magic constants for paranoia.
defined('PARANOIA_HIDE') or define('PARANOIA_HIDE', 0);
defined('PARANOIA_ALLOWED') or define('PARANOIA_ALLOWED', 1);
defined('PARANOIA_OVERRIDDEN') or define('PARANOIA_OVERRIDDEN', 2);
// What permissions allow a viewer to override a user's paranoia?
defined('PARANOIA_OVERRIDE') or define('PARANOIA_OVERRIDE', [
'downloaded' => 'users_mod',
'uploaded' => 'users_mod',
'lastseen' => 'users_mod',
'ratio' => 'users_mod',
'requiredratio' => 'users_mod',
'hide_donor_heart' => 'users_mod',
'bonuspoints' => 'admin_bp_history',
'torrentcomments' => 'site_moderate_forums',
'invitedcount' => 'users_view_invites',
'snatched' => 'users_view_torrents_snatchlist',
'snatched+' => 'users_view_torrents_snatchlist',
'leeching' => 'users_view_seedleech',
'leeching+' => 'users_view_seedleech',
'seeding' => 'users_view_seedleech',
'seeding+' => 'users_view_seedleech',
'uploads' => 'users_view_seedleech',
'uploads+' => 'users_view_seedleech',
]);
// ------------------------------------------------------------------------
// Artist configuration
defined('ARTIST_MAIN') or define('ARTIST_MAIN', 1);
defined('ARTIST_GUEST') or define('ARTIST_GUEST', 2);
defined('ARTIST_REMIXER') or define('ARTIST_REMIXER', 3);
defined('ARTIST_COMPOSER') or define('ARTIST_COMPOSER', 4);
defined('ARTIST_CONDUCTOR') or define('ARTIST_CONDUCTOR', 5);
defined('ARTIST_DJ') or define('ARTIST_DJ', 6);
defined('ARTIST_PRODUCER') or define('ARTIST_PRODUCER', 7);
defined('ARTIST_ARRANGER') or define('ARTIST_ARRANGER', 8);
defined('ARTIST_TYPE') or define('ARTIST_TYPE', [
ARTIST_MAIN => 'Main',
ARTIST_GUEST => 'Guest',
ARTIST_REMIXER => 'Remixer',
ARTIST_COMPOSER => 'Composer',
ARTIST_CONDUCTOR => 'Conductor',
ARTIST_DJ => 'DJ/Compiler',
ARTIST_PRODUCER => 'Producer',
ARTIST_ARRANGER => 'Arranger',
]);
defined('ARTIST_SECTION_ARRANGER') or define('ARTIST_SECTION_ARRANGER', 1020);
defined('ARTIST_SECTION_PRODUCER') or define('ARTIST_SECTION_PRODUCER', 1021);
defined('ARTIST_SECTION_COMPOSER') or define('ARTIST_SECTION_COMPOSER', 1022);
defined('ARTIST_SECTION_REMIXER') or define('ARTIST_SECTION_REMIXER', 1023);
defined('ARTIST_SECTION_GUEST') or define('ARTIST_SECTION_GUEST', 1024);
// ------------------------------------------------------------------------
// Collage configuration
defined('COLLAGE') or define('COLLAGE', [
0 => 'Personal',
1 => 'Theme',
2 => 'Genre Introduction',
3 => 'Discography',
4 => 'Label',
5 => 'Staff picks',
6 => 'Charts',
7 => 'Artists',
8 => 'Awards',
9 => 'Series',
]);
defined('COLLAGE_PERSONAL_ID') or define('COLLAGE_PERSONAL_ID', 0);
defined('COLLAGE_ARTISTS_ID') or define('COLLAGE_ARTISTS_ID', 7);
// ------------------------------------------------------------------------
// Donor configuration. Any changes here will need to be reflected in the
// wiki documentation.
defined('RANK_ONE_COST') or define('RANK_ONE_COST', 5);
defined('RANK_TWO_COST') or define('RANK_TWO_COST', 10);
defined('RANK_THREE_COST') or define('RANK_THREE_COST', 15);
defined('RANK_FOUR_COST') or define('RANK_FOUR_COST', 20);
defined('RANK_FIVE_COST') or define('RANK_FIVE_COST', 30);
defined('MAX_RANK') or define('MAX_RANK', 6);
defined('MAX_EXTRA_RANK') or define('MAX_EXTRA_RANK', 8);
defined('DONOR_FORUM_RANK') or define('DONOR_FORUM_RANK', 6);
defined('MAX_SPECIAL_RANK') or define('MAX_SPECIAL_RANK', 3);
// ------------------------------------------------------------------------
// Cache settings
// Grant cache access to specific keys based on site permission
defined('CACHE_PERMISSION') or define('CACHE_PERMISSION', [
'api_apps' => 'site_debug',
'catalogue' => 'site_debug',
]);
defined('CACHE_BULK_FLUSH') or define('CACHE_BULK_FLUSH', 500);
defined('CACHE_RESPONSE') or define('CACHE_RESPONSE', [
0 => 'success',
1 => 'failure/delete ok',
16 => 'not found',
]);
defined('CACHE_DB') or define('CACHE_DB', [
'artist' => ['table' => 'artists_group', 'pk' => 'ArtistID'],
'collage' => ['table' => 'collages', 'pk' => 'ID'],
'torrent' => ['table' => 'torrents', 'pk' => 'ID'],
'torrent-group' => ['table' => 'torrents_group', 'pk' => 'ID'],
'user' => ['table' => 'users_main', 'pk' => 'ID'],
]);
defined('CACHE_NAMESPACE') or define('CACHE_NAMESPACE', [
'artist' => [
'a1' => 'artist_%d',
'a2' => 'artist_comments_%d',
'a3' => 'artist_comments_%d_catalogue_0',
'a4' => 'artist_groups_%d',
'a5' => 'artists_collages_%d',
'a6' => 'artists_requests_%d',
'a7' => 'similar_positions_%d',
],
'collage' => [
'c1' => 'collage_%d',
'c2' => 'collage_display_%d',
'c3' => 'collage_subs_user_%d',
'c4' => 'collage_subs_user_new_%d',
],
'torrent-group' => [
'g1' => 'torrents_collages_%d',
'g2' => 'torrent_collages_personal_%d',
'g3' => 'torrents_cover_art_%d',
'g4' => 'torrents_details_%d',
'g5' => 'torrent_group_%d',
'g6' => 'torrent_group_light_%d',
'g7' => 'groups_artists_%d',
'g8' => 'tg_%d',
'g9' => 'tlist_%d',
],
'torrent' => [
't1' => 't2_%d',
],
'user' => [
'u1' => 'bookmarks_group_ids_%d',
'u2' => 'donor_info_%d',
'u3' => 'inbox_new_%d',
'u4' => 'u_%d',
'u5' => 'user_info_%d',
'u6' => 'user_info_heavy_%d',
'u7' => 'user_stats_%d',
'u8' => 'user_statgraphs_%d',
'u9' => 'user_tokens_%d',
],
]);
// ------------------------------------------------------------------------
// Common regexp patterns
defined('IP_REGEXP') or define('IP_REGEXP', '/\b(?:\d{1,3}\.){3}\d{1,3}\b/');
defined('URL_REGEXP_STEM') or define('URL_REGEXP_STEM', '((?:f|ht)tps?:\/\/)(?:' . str_replace('/', '', IP_REGEXP) . '|[\w-]+(?:\.[\w-]+)+)(?::\d{1,5})?(?:\/\S*)');
defined('URL_REGEXP') or define('URL_REGEXP', '/^' . URL_REGEXP_STEM . '$/i');
defined('CSS_REGEXP') or define('CSS_REGEXP', '/^' . URL_REGEXP_STEM . '\.css(?:\?\S*)$/i');
defined('IMAGE_REGEXP') or define('IMAGE_REGEXP', '/\b(' . URL_REGEXP_STEM . '\.(?:gif|png|webm|jpe?g|tiff?)(\?\S*)?)\b/i');
defined('SITELINK_REGEXP') or define('SITELINK_REGEXP', '(?:' . preg_quote(SITE_URL, '/') . (defined('ALT_SITE_URL') ? '|' . preg_quote(ALT_SITE_URL, '/') : '') . ')');
defined('ARTIST_REGEXP') or define('ARTIST_REGEXP', '/^' . SITELINK_REGEXP . '\/artist\.php\?.*?\bid=(?P<id>\d+)$/');
defined('TGROUP_REGEXP') or define('TGROUP_REGEXP', '/^' . SITELINK_REGEXP . '\/torrents\.php\?.*?\bid=(?P<id>\d+)\b/');
defined('TORRENT_REGEXP') or define('TORRENT_REGEXP', '/^' . SITELINK_REGEXP . '\/torrents\.php\?.*?\btorrentid=(?P<id>\d+)\b/');
defined('EMAIL_REGEXP') or define('EMAIL_REGEXP', '/^[\w-]+(?:\.[\w-]+)*(?:\+[.\w-]+)?@[\w-]+(?:\.[\w-]+)+$/');
defined('USERNAME_REGEXP') or define('USERNAME_REGEXP', '/\b(?:[01]$(*PRUNE)(*FAIL)|(?P<username>[\w.]{1,20}))\b/');
// ------------------------------------------------------------------------
// Common icons (emoji)
defined('ICON_ALL') or define('ICON_ALL', "\xe2\x9c\x85");
defined('ICON_NONE') or define('ICON_NONE', "\xf0\x9f\x9a\xab");
defined('ICON_TOGGLE') or define('ICON_TOGGLE', "\xf0\x9f\x94\x81");
defined('ICON_PADLOCK') or define('ICON_PADLOCK', "\xF0\x9F\x94\x92");
defined('ICON_STAR') or define('ICON_STAR', "\xE2\x98\x85");
defined('ICON_BLACK_SQUARE') or define('ICON_BLACK_SQUARE', "\xE2\x96\xA0");
defined('ICON_WHITE_SQUARE') or define('ICON_WHITE_SQUARE', "\xE2\x96\xA1");
// ------------------------------------------------------------------------
// Collector settings
defined('ZIP_GROUP') or define('ZIP_GROUP', [
0 => 'MP3 (VBR) - High Quality',
1 => 'MP3 (VBR) - Low Quality',
2 => 'MP3 (CBR)',
3 => 'FLAC - Lossless',
4 => 'Others',
]);
defined('ZIP_OPTION') or define('ZIP_OPTION', [
'00' => [0, 0, 'V0'],
'01' => [0, 1, 'APX'],
'02' => [0, 2, '256'],
'03' => [0, 3, 'V1'],
'10' => [1, 0, '224'],
'11' => [1, 1, 'V2'],
'12' => [1, 2, 'APS'],
'13' => [1, 3, '192'],
'20' => [2, 0, '320'],
'21' => [2, 1, '256'],
'22' => [2, 2, '224'],
'23' => [2, 3, '192'],
'24' => [2, 4, '160'],
'25' => [2, 5, '128'],
'26' => [2, 6, '96'],
'27' => [2, 7, '64'],
'30' => [3, 0, 'FLAC / 24bit / Vinyl'],
'31' => [3, 1, 'FLAC / 24bit / DVD'],
'32' => [3, 2, 'FLAC / 24bit / SACD'],
'33' => [3, 3, 'FLAC / 24bit / WEB'],
'34' => [3, 4, 'FLAC / Log (100) / Cue'],
'35' => [3, 5, 'FLAC / Log (100)'],
'36' => [3, 6, 'FLAC / Log'],
'37' => [3, 7, 'FLAC / WEB'],
'38' => [3, 8, 'FLAC'],
'40' => [4, 0, 'DTS'],
'42' => [4, 2, 'AAC - 320'],
'43' => [4, 3, 'AAC - 256'],
'44' => [4, 4, 'AAC - q5.5'],
'45' => [4, 5, 'AAC - q5'],
'46' => [4, 6, 'AAC - 192'],
]);
// ------------------------------------------------------------------------
// Captcha settings
defined('CAPTCHA_FONT') or define('CAPTCHA_FONT', [
'ARIBLK.TTF',
'IMPACT.TTF',
'TREBUC.TTF',
'TREBUCBD.TTF',
'TREBUCBI.TTF',
'TREBUCIT.TTF',
'VERDANA.TTF',
'VERDANAB.TTF',
'VERDANAI.TTF',
'VERDANAZ.TTF',
]);
defined('CAPTCHA_BG') or define('CAPTCHA_BG', [
'captcha1.png',
'captcha2.png',
'captcha3.png',
'captcha4.png',
'captcha5.png',
'captcha6.png',
'captcha7.png',
'captcha8.png',
'captcha9.png',
]);
// ------------------------------------------------------------------------
// Opera Turbo (may include Opera-owned IP addresses that aren't used for Turbo, but shouldn't run much risk of exploitation)
// Useful: http://www.robtex.com/cnet/
defined('ALLOWED_PROXY') or define('ALLOWED_PROXY', [
'64.255.180.*', //Norway
'64.255.164.*', //Norway
'80.239.242.*', //Poland
'80.239.243.*', //Poland
'91.203.96.*', //Norway
'94.246.126.*', //Norway
'94.246.127.*', //Norway
'195.189.142.*', //Norway
'195.189.143.*', //Norway
]);

View File

@@ -0,0 +1,52 @@
<?php
// Copy these variables to your config.override.php in a production environment.
// Change as required.
define('SITE_NAME', 'Gazelle');
define('SITE_HOST', 'localhost');
define('SITE_LAUNCH_YEAR', 2018);
define('SOURCE', 'GZL');
define('TMPDIR', '/tmp');
define('STORAGE_PATH_TORRENT', '/var/lib/gazelle/torrent');
define('STORAGE_PATH_RIPLOG', '/var/lib/gazelle/riplog');
define('STORAGE_PATH_RIPLOGHTML', '/var/lib/gazelle/riploghtml');
define('TRACKER_HOST', 'tracker.example.com');
define('TRACKER_PORT', 12345);
define('SQLHOST', '10.0.0.1');
define('BOT_SERVER', 'irc.example.com');
// If your database is on the same host as the PHP interpreter
define('SQLSOCK', '/var/run/mysqld/mysqld.sock');
define('SQLDB', 'thisisfine');
define('SQLLOGIN', 'thisisfine');
define('SQLPASS', 'thisisfine');
define('SQL_PHINX_USER', 'thisis.phinx');
define('SQL_PHINX_PASS', 'thisis.phinx');
define('SPHINX_HOST', 'sphinx.example.com');
define('SPHINXQL_HOST', SPHINX_HOST);
// If sphinx is running on the same host as the PHP interpreter
define('SPHINXQL_SOCK', '/var/run/sphinx.sock');
define('TRACKER_SECRET', '0123456789abcdef0123456789abcdef01');
define('TRACKER_REPORTKEY', '0123456789abcdef0123456789abcdef01');
define('ENCKEY', 'thisisfine');
define('SCHEDULE_KEY', 'thisisfine');
define('RSS_HASH', 'thisisfine');
define('SEEDBOX_SALT', 'thisisfine');
define('AVATAR_SALT', 'thisisfine');
define('PARANOIA_PREVIEW_USER', 1);
define('IMAGE_HOST_BANNED', ['badhost.example.com']);
define('IMAGE_HOST_RECOMMENDED', ['goodhost.example.com']);

12
lib/stub/memcached.stub Normal file
View File

@@ -0,0 +1,12 @@
<?php
/**
* On a development machine, the php-memcached package is not necesssarily
* installed, but it is present in the Docker container. Running phpstan will
* therefore complain about "Class 'Memcached' not found/".
*
* This file addresses that problem.
*/
class Memcached {
}

View File

@@ -1,6 +1,6 @@
<?php
require_once(__DIR__ . '/classes/config.php');
require_once(__DIR__ . '/lib/config.php');
return
[

View File

@@ -1,31 +1,24 @@
includes:
- phpstan-baseline.neon
- phpstan-baseline.neon
parameters:
level: 3
stubFiles:
- lib/stub/memcached.stub
bootstrapFiles:
- classes/config.template.php
- lib/bootstrap.php
- lib/config.php
scanFiles:
- lib/bootstrap.php
- lib/util.php
paths:
- app
- classes
- db
- scripts
excludePaths:
- classes/pushserver.class.php
- design
- sections
parallel:
maximumNumberOfProcesses: 1
# The ignored error in theory should not occur on PHP 7.3 with php-gd, but
# we have had it happen nevertheless on some developer machines. Given its
# our only ignored error, we are fine having this error happen optionally
# for developers. If we add more ignored errors, we should readdress this
# setting, and if the error still occurs for people
reportUnmatchedIgnoredErrors: false
ignoreErrors:
-
message: '/(Constant IMG_BMP|Function imagebmp) not found\./'
path: app/Image.php
# lib/bootstrap.php declares these variables, and thus available everywhere.
- '/Variable \$(Cache|DB|Debug|Twig) might not be defined\./'

View File

@@ -1,10 +1,4 @@
<?php
/*-- Feed Start Class ----------------------------------*/
/*------------------------------------------------------*/
/* Simplified version of script_start, used for the */
/* sitewide RSS system. */
/*------------------------------------------------------*/
/********************************************************/
// Prevent people from clearing feeds
if (isset($_GET['clearcache'])) {
@@ -15,8 +9,8 @@ require_once(__DIR__ . '/../lib/bootstrap.php');
header('Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0');
header('Pragma:');
header('Expires: '.date('D, d M Y H:i:s', time() + (2 * 60 * 60)).' GMT');
header('Last-Modified: '.date('D, d M Y H:i:s').' GMT');
header('Expires: ' . date('D, d M Y H:i:s', time() + (2 * 60 * 60)) . ' GMT');
header('Last-Modified: ' . date('D, d M Y H:i:s') . ' GMT');
$Feed = new Feed;
$Feed->UseSSL = (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443);

View File

@@ -2,7 +2,7 @@
header('Content-type: application/opensearchdescription+xml');
require_once(__DIR__ . '/../lib/bootstrap.php');
require_once(__DIR__ . '/../lib/config.php');
$Type = in_array(($_GET['type'] ?? ''), ['torrents','artists','requests','forums','users','wiki','log'])
? $_GET['type']

View File

@@ -14,7 +14,7 @@
* try it :)
*/
require_once(__DIR__ . '/../classes/config.php');
require_once(__DIR__ . '/../lib/config.php');
array_shift($argv);
$multi = count($argv) > 1;

View File

@@ -1,6 +1,7 @@
<?php
require_once(__DIR__ . '/../lib/bootstrap.php');
$Cache->disableLocalCache();
$torMan = new Gazelle\Manager\Torrent;
$max = $DB->scalar("SELECT max(ID) FROM torrents");

View File

@@ -4,10 +4,6 @@
require_once(__DIR__ . '/../lib/bootstrap.php');
use Gazelle\Util\Crypto;
set_include_path(SERVER_ROOT);
$in = fopen($argv[1], 'r');
$row = fgets($in);