1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147 |
- <?php
- #declare(strict_types=1);
-
- /**
- * Take upload
- *
- * This pages handles the backend of the torrent upload function.
- * It checks the data, and if it all validates, it builds the torrent file,
- * then writes the data to the database and the torrent to the disk.
- */
-
- $ENV = ENV::go();
- $Feed = new Feed;
- $Validate = new Validate;
-
- require_once "$ENV->SERVER_ROOT/classes/feed.class.php";
- require_once "$ENV->SERVER_ROOT/classes/validate.class.php";
- require_once "$ENV->SERVER_ROOT/sections/torrents/functions.php";
-
- enforce_login();
- authorize();
-
-
- /**
- * Set $Properties array
- *
- * This is used if the form doesn't validate,
- * and when the time comes to enter it into the database.
- *
- * todo: Do something about this mess
- */
-
- $Properties = [];
- $Type = $Categories[(int) $_POST['type']];
- $TypeID = $_POST['type'] + 1;
-
- $Properties['CategoryID'] = $TypeID;
- $Properties['CategoryName'] = $Type;
-
- $Properties['Title'] = $_POST['title']; # Title1
- $Properties['Title2'] = $_POST['title_rj']; # Title2
- $Properties['TitleJP'] = $_POST['title_jp']; # Title3
- $Properties['CatalogueNumber'] = isset($_POST['catalogue']) ? $_POST['catalogue'] : '';
-
- $Properties['Year'] = $_POST['year'];
- $Properties['Studio'] = isset($_POST['studio']) ? $_POST['studio'] : '';
- $Properties['Series'] = isset($_POST['series']) ? $_POST['series'] : '';
- $Properties['Container'] = isset($_POST['container']) ? $_POST['container'] : '';
- $Properties['Media'] = $_POST['media'];
- $Properties['Codec'] = isset($_POST['codec']) ? $_POST['codec'] : '';
-
- if (!($_POST['resolution'] ?? false)) {
- $_POST['resolution'] = $_POST['ressel'] ?? '';
- }
-
- $Properties['Resolution'] = $_POST['resolution'] ?? '';
- $Properties['Version'] = $_POST['version'] ?? '';
- $Properties['Censored'] = (isset($_POST['censored'])) ? '1' : '0';
- $Properties['Anonymous'] = (isset($_POST['anonymous'])) ? '1' : '0';
- $Properties['Archive'] = (isset($_POST['archive']) && $_POST['archive'] !== '---') ? $_POST['archive'] : '';
-
- if (isset($_POST['library_image'])) {
- $Properties['LibraryImage'] = $_POST['library_image'];
- }
-
- if (isset($_POST['tags'])) {
- $Properties['TagList'] = implode(',', array_unique(explode(',', str_replace(' ', '', $_POST['tags']))));
- }
-
- if (isset($_POST['image'])) {
- $Properties['Image'] = $_POST['image'];
- }
-
- if (isset($_POST['release'])) {
- $Properties['ReleaseGroup'] = $_POST['release'];
- }
-
- $Properties['GroupDescription'] = trim($_POST['album_desc']);
- $Properties['TorrentDescription'] = $_POST['release_desc'];
- $Properties['Screenshots'] = isset($_POST['screenshots']) ? $_POST['screenshots'] : '';
- $Properties['Mirrors'] = isset($_POST['mirrors']) ? $_POST['mirrors'] : '';
- $Properties['Seqhash'] = isset($_POST['seqhash']) ? $_POST['seqhash'] : '';
-
- if ($_POST['album_desc']) {
- $Properties['GroupDescription'] = trim($_POST['album_desc']);
- } elseif ($_POST['desc']) {
- $Properties['GroupDescription'] = trim($_POST['desc']);
- }
-
- if (isset($_POST['groupid'])) {
- $Properties['GroupID'] = $_POST['groupid'];
- }
-
- if (isset($Properties['GroupID'])) {
- $Properties['Artists'] = Artists::get_artist($Properties['GroupID']);
- }
-
- if (empty($_POST['artists'])) {
- $Err = "You didn't enter any creators";
- } else {
- $Artists = $_POST['artists'];
- }
-
- if (!empty($_POST['requestid'])) {
- $RequestID = $_POST['requestid'];
- $Properties['RequestID'] = $RequestID;
- }
-
-
- /**
- * Validate data in upload form
- */
-
- # Submit button
- $Validate->SetFields(
- 'type',
- '1',
- 'inarray',
- 'Please select a valid type.',
- array('inarray' => array_keys($Categories))
- );
-
- # torrents_group.category_id
- $Validate->SetFields(
- 'type',
- '1',
- 'inarray',
- 'Please select a valid type.',
- array('inarray' => array_keys($Categories))
- );
-
- if (!$_POST['groupid']) {
- # torrents_group.identifier
- $Validate->SetFields(
- 'catalogue',
- '0',
- 'string',
- 'Accession Number must be between 0 and 50 characters.',
- array('maxlength' => 50, 'minlength' => 0)
- );
-
- # torrents.Version
- $Validate->SetFields(
- 'version',
- '0',
- 'string',
- 'Version must be between 0 and 10 characters.',
- array('maxlength' => 10, 'minlength' => 0)
- );
-
- # torrents_group.title
- $Validate->SetFields(
- 'title',
- '1',
- 'string',
- 'Torrent Title must be between 10 and 255 characters.',
- array('maxlength' => 255, 'minlength' => 10)
- );
-
- # torrents_group.subject
- $Validate->SetFields(
- 'title_rj',
- '0',
- 'string',
- 'Organism must be between 0 and 255 characters.',
- array('maxlength' => 255, 'minlength' => 0)
- );
-
- # torrents_group.object
- $Validate->SetFields(
- 'title_jp',
- '0',
- 'string',
- 'Strain/Variety must be between 0 and 255 characters.',
- array('maxlength' => 255, 'minlength' => 0)
- );
-
- # torrents_group.workgroup
- $Validate->SetFields(
- 'studio',
- '1',
- 'string',
- 'Department/Lab must be between 0 and 100 characters.',
- array('maxlength' => 100, 'minlength' => 0)
- );
-
- # torrents_group.location
- $Validate->SetFields(
- 'series',
- '0',
- 'string',
- 'Location must be between 0 and 100 characters.',
- array('maxlength' => 100, 'minlength' => 0)
- );
-
- /* todo: Fix the year validation
- # torrents_group.year
- $Validate->SetFields(
- 'year',
- '1',
- 'number',
- 'The year of the original release must be entered.',
- array('maxlength' => 4, 'minlength' => 4)
- );
- */
-
- # torrents.Media
- $Validate->SetFields(
- 'media',
- '1',
- 'inarray',
- 'Please select a valid platform.',
- array('inarray' => $ENV->META->Platforms)
- );
-
- /*
- # torrents.Container
- $Validate->SetFields(
- 'container',
- '1',
- 'inarray',
- 'Please select a valid format.',
- array('inarray' => array_merge($Containers, $ContainersGames))
- );
- */
-
- # torrents.Resolution
- $Validate->SetFields(
- 'resolution',
- '1',
- 'string',
- 'Scope must be between 4 and 20 characters.',
- array('maxlength' => 20, 'minlength' => 4)
- );
-
- # torrents_group.tag_list
- $Validate->SetFields(
- 'tags',
- '1',
- 'string',
- 'You must enter at least five tags. Maximum length is 500 characters.',
- array('maxlength' => 500, 'minlength' => 10)
- );
-
- # torrents_group.picture
- $Validate->SetFields(
- 'image',
- '0',
- 'link',
- 'The image URL you entered was invalid.',
- array('maxlength' => 255, 'minlength' => 10) # x.yz/a.bc
- );
- }
-
- # torrents_group.description
- $Validate->SetFields(
- 'album_desc',
- '1',
- 'string',
- 'The description must be between 100 and 65535 characters.',
- array('maxlength' => 65535, 'minlength' => 100)
- );
-
- /* todo: Fix the Group ID validation
- # torrents_group.id
- $Validate->SetFields(
- 'groupid',
- '0',
- 'number',
- 'Group ID was not numeric.'
- );
- */
-
- $Err = $Validate->ValidateForm($_POST); // Validate the form
-
- # todo: Move all this validation code to the Validate class
- if (count(explode(',', $Properties['TagList'])) < 5) {
- $Err = 'You must enter at least 5 tags.';
- }
-
- if (!(isset($_POST['title']) || isset($_POST['title_rj']) || isset($_POST['title_jp']))) {
- $Err = 'You must enter at least one title.';
- }
-
- $File = $_FILES['file_input']; // This is our torrent file
- $TorrentName = $File['tmp_name'];
-
- if (!is_uploaded_file($TorrentName) || !filesize($TorrentName)) {
- $Err = 'No torrent file uploaded, or file is empty.';
- } elseif (substr(strtolower($File['name']), strlen($File['name']) - strlen('.torrent')) !== '.torrent') {
- $Err = "You seem to have put something other than a torrent file into the upload field. (".$File['name'].").";
- }
-
- // Multiple artists!
- $LogName = '';
- if (empty($Properties['GroupID']) && empty($ArtistForm)) {
- $ArtistNames = [];
- $ArtistForm = [];
- for ($i = 0; $i < count($Artists); $i++) {
- if (trim($Artists[$i]) !== '') {
- if (!in_array($Artists[$i], $ArtistNames)) {
- $ArtistForm[$i] = array('name' => Artists::normalise_artist_name($Artists[$i]));
- array_push($ArtistNames, $ArtistForm[$i]['name']);
- }
- }
- }
- $LogName .= Artists::display_artists($ArtistForm, false, true, false);
- } elseif (empty($ArtistForm)) {
- $DB->query("
- SELECT ta.ArtistID, ag.Name
- FROM torrents_artists AS ta
- JOIN artists_group AS ag ON ta.ArtistID = ag.ArtistID
- WHERE ta.GroupID = ?
- ORDER BY ag.Name ASC", $Properties['GroupID']);
-
- $ArtistForm = [];
- while (list($ArtistID, $ArtistName) = $DB->next_record(MYSQLI_BOTH, false)) {
- array_push($ArtistForm, array('id' => $ArtistID, 'name' => display_str($ArtistName)));
- array_push($ArtistsUnescaped, array('name' => $ArtistName));
- }
- $LogName .= Artists::display_artists($ArtistsUnescaped, false, true, false);
- }
-
- if ($Err) { // Show the upload form, with the data the user entered
- $UploadForm = $Type;
- require_once SERVER_ROOT.'/sections/upload/upload.php' ;
- error(400, $NoHTML = true);
- }
-
- ImageTools::blacklisted($Properties['Image']);
-
-
- /**
- * Make variables ready for database input
- *
- * Prepared SQL statements do this for us,
- * so there is nothing to do here anymore.
- */
- $T = $Properties;
-
-
- /**
- * Generate torrent file
- */
-
- $Tor = new BencodeTorrent($TorrentName, true);
- $PublicTorrent = $Tor->make_private(); // The torrent is now private
- $UnsourcedTorrent = $Tor->make_sourced(); // The torrent now has the source field set
- $InfoHash = pack('H*', $Tor->info_hash());
-
- if (isset($Tor->Dec['encrypted_files'])) {
- $Err = 'This torrent contains an encrypted file list which is not supported here.';
- }
-
- // File list and size
- list($TotalSize, $FileList) = $Tor->file_list();
- $NumFiles = count($FileList);
- $TmpFileList = [];
- $TooLongPaths = [];
- $DirName = (isset($Tor->Dec['info']['files']) ? Format::make_utf8($Tor->get_name()) : '');
- check_name($DirName); // Check the folder name against the blacklist
- foreach ($FileList as $File) {
- list($Size, $Name) = $File;
- // Check file name and extension against blacklist/whitelist
- check_file($Type, $Name);
- // Make sure the filename is not too long
- if (mb_strlen($Name, 'UTF-8') + mb_strlen($DirName, 'UTF-8') + 1 > 255) { # MAX_FILENAME_LENGTH
- $TooLongPaths[] = "$DirName/$Name";
- }
- // Add file info to array
- $TmpFileList[] = Torrents::filelist_format_file($File);
- }
- if (count($TooLongPaths) > 0) {
- $Names = implode(' <br />', $TooLongPaths);
- $Err = "The torrent contained one or more files with too long a name:<br /> $Names";
- }
- $FilePath = $DirName;
- $FileString = implode("\n", $TmpFileList);
- $Debug->set_flag('upload: torrent decoded');
-
- if (!empty($Err)) { // Show the upload form, with the data the user entered
- $UploadForm = $Type;
- include(SERVER_ROOT.'/sections/upload/upload.php');
- error();
- }
-
- //******************************************************************************//
- //--------------- Autofill format and archive ----------------------------------//
-
- if ($T['Container'] === 'Autofill') {
- # torrents.Container
- $T['Container'] = $Validate->ParseExtensions(
- # $FileList
- $Tor->file_list(),
-
- # $Category
- $T['CategoryName'],
-
- # $FileTypes
- $T['FileTypes'],
- );
- }
-
- if ($T['Archive'] === 'Autofill') {
- # torrents.Archive
- $T['Archive'] = $Validate->ParseExtensions(
- # $FileList
- $Tor->file_list(),
-
- # $Category
- array_keys($ENV->META->Formats->Archives),
-
- # $FileTypes
- array_merge($ENV->META->Formats->Archives),
- );
- }
-
- //******************************************************************************//
- //--------------- Start database stuff -----------------------------------------//
-
- $Body = $T['GroupDescription'];
-
- // Trickery
- if (!preg_match('/^'.IMAGE_REGEX.'$/i', $T['Image'])) {
- $T['Image'] = '';
- }
-
- // Does it belong in a group?
- if ($T['GroupID']) {
- $DB->prepare_query("
- SELECT
- `id`,
- `picture`,
- `description`,
- `revision_id`,
- `title`,
- `year`,
- `tag_list`
- FROM
- `torrents_group`
- WHERE
- `id` = ?
- ", $T['GroupID']);
- $DB->exec_prepared_query();
-
- if ($DB->has_results()) {
- // Don't escape tg.title. It's written directly to the log table
- list($GroupID, $WikiImage, $WikiBody, $RevisionID, $T['Title'], $T['Year'], $T['TagList']) = $DB->next_record(MYSQLI_NUM, array(4));
- $T['TagList'] = str_replace(array(' ', '.', '_'), array(', ', '.', '.'), $T['TagList']);
-
- if (!$T['Image'] && $WikiImage) {
- $T['Image'] = $WikiImage;
- }
-
- if (strlen($WikiBody) > strlen($Body)) {
- $Body = $WikiBody;
- if (!$T['Image'] || $T['Image'] === $WikiImage) {
- $NoRevision = true;
- }
- }
- $T['Artist'] = Artists::display_artists(Artists::get_artist($GroupID), false, false);
- }
- }
-
- if (!isset($GroupID) || !$GroupID) {
- foreach ($ArtistForm as $Num => $Artist) {
- // The album hasn't been uploaded. Try to get the artist IDs
- $DB->query("
- SELECT
- ArtistID,
- Name
- FROM artists_group
- WHERE Name = ?", $Artist['name']);
-
- if ($DB->has_results()) {
- while (list($ArtistID, $Name) = $DB->next_record(MYSQLI_NUM, false)) {
- if (!strcasecmp($Artist['name'], $Name)) {
- $ArtistForm[$Num] = ['id' => $ArtistID, 'name' => $Name];
- break;
- }
- }
- }
- }
- }
-
- // Needs to be here as it isn't set for add format until now
- $LogName .= $T['Title'];
-
- // For notifications. Take note now whether it's a new group
- $IsNewGroup = !isset($GroupID) || !$GroupID;
-
- //----- Start inserts
- if ((!isset($GroupID) || !$GroupID)) {
- // Array to store which artists we have added already, to prevent adding an artist twice
- $ArtistsAdded = [];
-
- foreach ($ArtistForm as $Num => $Artist) {
- if (!isset($Artist['id']) || !$Artist['id']) {
- if (isset($ArtistsAdded[strtolower($Artist['name'])])) {
- $ArtistForm[$Num] = $ArtistsAdded[strtolower($Artist['name'])];
- } else {
- // Create artist
- $DB->query("
- INSERT INTO artists_group (Name)
- VALUES ( ? )", $Artist['name']);
-
- $ArtistID = $DB->inserted_id();
- $Cache->increment('stats_artist_count');
-
- $ArtistForm[$Num] = array('id' => $ArtistID, 'name' => $Artist['name']);
- $ArtistsAdded[strtolower($Artist['name'])] = $ArtistForm[$Num];
- }
- }
- }
- unset($ArtistsAdded);
- }
-
- if (!isset($GroupID) || !$GroupID) {
- // Create torrent group
- $DB->query(
- "
- INSERT INTO torrents_group
- (`category_id`, `title`, `subject`, `object`, `year`,
- `location`, `workgroup`, `identifier`, `timestamp`,
- `description`, `picture`)
- VALUES
- ( ?, ?, ?, ?, ?,
- ?, ?, ?, NOW(),
- ?, ? )",
- $T['CategoryID'],
- $T['Title'],
- $T['Title2'],
- $T['TitleJP'],
- $T['Year'],
- $T['Series'],
- $T['Studio'],
- $T['CatalogueNumber'],
- $Body,
- $T['Image']
- );
-
- $GroupID = $DB->inserted_id();
- foreach ($ArtistForm as $Num => $Artist) {
- $DB->query("
- INSERT IGNORE INTO torrents_artists (GroupID, ArtistID, UserID)
- VALUES ( ?, ?, ? )", $GroupID, $Artist['id'], $LoggedUser['ID']);
-
- $Cache->increment('stats_album_count');
- $Cache->delete_value('artist_groups_'.$Artist['id']);
- }
- $Cache->increment('stats_group_count');
-
-
- /**
- * DOI numbers
- *
- * Add optional citation info.
- * todo: Query Semantic Scholar in the scheduler.
- * THESE ARE ASSOCIATED WITH TORRENT GROUPS.s
- */
- if (!empty($T['Screenshots'])) {
- $Screenshots = $Validate->textarea2array($T['Screenshots'], $ENV->DOI_REGEX);
- $Screenshots = array_slice($Screenshots, 0, 10);
-
- foreach ($Screenshots as $Screenshot) {
- $DB->query("
- INSERT INTO `literature`
- (`group_id`, `user_id`, `timestamp`, `doi`)
- VALUES (?, ?, NOW(), ?)", $GroupID, $LoggedUser['ID'], $Screenshot);
- }
- }
- }
-
- # Main if/else
- else {
- $DB->query("
- UPDATE torrents_group
- SET `timestamp` = NOW()
- WHERE `id` = ?", $GroupID);
-
- $Cache->delete_value("torrent_group_$GroupID");
- $Cache->delete_value("torrents_details_$GroupID");
- $Cache->delete_value("detail_files_$GroupID");
- }
-
- // Description
- if (!isset($NoRevision) || !$NoRevision) {
- $DB->query("
- INSERT INTO wiki_torrents
- (PageID, Body, UserID, Summary, Time, Image)
- VALUES
- ( ?, ?, ?, 'Uploaded new torrent', NOW(), ? )", $GroupID, $T['GroupDescription'], $LoggedUser['ID'], $T['Image']);
- $RevisionID = $DB->inserted_id();
-
- // Revision ID
- $DB->prepare_query("
- UPDATE
- `torrents_group`
- SET
- `revision_id` = '$RevisionID'
- WHERE
- `id` = '$GroupID'
- ");
- $DB->exec_prepared_query();
- }
-
- // Tags
- $Tags = explode(',', $T['TagList']);
- if (!$T['GroupID']) {
- foreach ($Tags as $Tag) {
- $Tag = Misc::sanitize_tag($Tag);
- if (!empty($Tag)) {
- $Tag = Misc::get_alias_tag($Tag);
- $DB->query("
- INSERT INTO tags
- (Name, UserID)
- VALUES
- ( ?, ? )
- ON DUPLICATE KEY UPDATE
- Uses = Uses + 1;", $Tag, $LoggedUser['ID']);
- $TagID = $DB->inserted_id();
-
- $DB->query("
- INSERT INTO torrents_tags
- (TagID, GroupID, UserID)
- VALUES
- ( ?, ?, ? )
- ON DUPLICATE KEY UPDATE TagID=TagID", $TagID, $GroupID, $LoggedUser['ID']);
- }
- }
- }
-
- // Use this section to control freeleeches
- $T['FreeTorrent'] = '0';
- $T['FreeLeechType'] = '0';
-
- $DB->query("
- SELECT Name, First, Second
- FROM misc
- WHERE Second = 'freeleech'");
-
- if ($DB->has_results()) {
- $FreeLeechTags = $DB->to_array('Name');
- foreach ($FreeLeechTags as $Tag => $Exp) {
- if ($Tag === 'global' || in_array($Tag, $Tags)) {
- $T['FreeTorrent'] = '1';
- $T['FreeLeechType'] = '3';
- break;
- }
- }
- }
-
- // Torrents over a size in bytes are neutral leech
- // Download doesn't count, upload does
- if (($TotalSize > 10737418240)) { # 10 GiB
- $T['FreeTorrent'] = '2';
- $T['FreeLeechType'] = '2';
- }
-
- // Torrent
- $DB->query(
- "
- INSERT INTO torrents
- (GroupID, UserID, Media, Container, Codec, Resolution,
- Version, Censored,
- Anonymous, Archive, info_hash, FileCount, FileList, FilePath, Size, Time,
- Description, FreeTorrent, FreeLeechType)
- VALUES
- ( ?, ?, ?, ?, ?, ?,
- ?, ?,
- ?, ?, ?, ?, ?, ?, ?, NOW(),
- ?, ?, ? )",
- $GroupID,
- $LoggedUser['ID'],
- $T['Media'],
- $T['Container'],
- $T['Codec'],
- $T['Resolution'],
- $T['Version'],
- $T['Censored'],
- $T['Anonymous'],
- $T['Archive'],
- $InfoHash,
- $NumFiles,
- $FileString,
- $FilePath,
- $TotalSize,
- $T['TorrentDescription'],
- $T['FreeTorrent'],
- $T['FreeLeechType']
- );
-
- $TorrentID = $DB->inserted_id();
- $Cache->increment('stats_torrent_count');
- $Tor->Dec['comment'] = 'https://'.SITE_DOMAIN.'/torrents.php?torrentid='.$TorrentID;
-
-
- /**
- * Mirrors
- *
- * Add optional web seeds and IPFS/Dat mirrors.
- * Support an arbitrary and limited number of sources.
- * THESE ARE ASSOCIATED WITH INDIVIDUAL TORRENTS.
- */
-
- if (!empty($T['Mirrors'])) {
- $Mirrors = $Validate->textarea2array($T['Mirrors'], $ENV->URL_REGEX);
- $Screenshots = array_slice($Screenshots, 0, 5);
-
- foreach ($Mirrors as $Mirror) {
- $DB->query(
- "
- INSERT INTO torrents_mirrors
- (`torrent_id`, `user_id`, `timestamp`, `uri`)
- VALUES (?, ?, NOW(), ?)",
- $TorrentID,
- $LoggedUser['ID'],
- $Mirror
- );
- }
- }
-
-
- /**
- * Seqhash
- *
- * Elementary Seqhash support
- */
- if ($ENV->FEATURE_BIOPHP && !empty($T['Seqhash'])) {
- $BioIO = new \BioPHP\IO();
- $BioSeqhash = new \BioPHP\Seqhash();
-
- $Parsed = $BioIO->readFasta($T['Seqhash']);
- foreach ($Parsed as $Parsed) {
- try {
- # todo: Trim sequences in \BioPHP\Transform->normalize()
- $Trimmed = preg_replace('/\s+/', '', $Parsed['sequence']);
- $Seqhash = $BioSeqhash->hash(
- $Trimmed,
- $_POST['seqhash_meta1'],
- $_POST['seqhash_meta2'],
- $_POST['seqhash_meta3']
- );
-
- $DB->query(
- "
- INSERT INTO `bioinformatics`
- (`torrent_id`, `user_id`, `timestamp`,
- `name`, `seqhash`)
- VALUES (?, ?, NOW(), ?, ?)",
- $TorrentID,
- $LoggedUser['ID'],
- $Parsed['name'],
- $Seqhash
- );
- } catch (Exception $Err) {
- $UploadForm = $Type;
- require_once SERVER_ROOT.'/sections/upload/upload.php' ;
- error($Err->getMessage(), $NoHTML = true);
- }
- }
- }
-
-
- /**
- * Update tracker
- */
- Tracker::update_tracker('add_torrent', [
- 'id' => $TorrentID,
- 'info_hash' => rawurlencode($InfoHash),
- 'freetorrent' => $T['FreeTorrent']
- ]);
- $Debug->set_flag('upload: ocelot updated');
-
- // Prevent deletion of this torrent until the rest of the upload process is done
- // (expire the key after 10 minutes to prevent locking it for too long in case there's a fatal error below)
- $Cache->cache_value("torrent_{$TorrentID}_lock", true, 600);
-
- // Give BP if necessary
- // todo: Repurpose this
- if (($Type === "Movies" || $Type === "Anime") && ($T['Container'] === 'ISO' || $T['Container'] === 'M2TS' || $T['Container'] === 'VOB IFO')) {
- $BPAmt = (int) 2*($TotalSize / (1024*1024*1024))*1000;
-
- $DB->query("
- UPDATE users_main
- SET BonusPoints = BonusPoints + ?
- WHERE ID = ?", $BPAmt, $LoggedUser['ID']);
-
- $DB->query("
- UPDATE users_info
- SET AdminComment = CONCAT(NOW(), ' - Received $BPAmt ".BONUS_POINTS." for uploading a torrent $TorrentID\n\n', AdminComment)
- WHERE UserID = ?", $LoggedUser['ID']);
-
- $Cache->delete_value('user_info_heavy_'.$LoggedUser['ID']);
- $Cache->delete_value('user_stats_'.$LoggedUser['ID']);
- }
-
- // Add to shop freeleeches if necessary
- if ($T['FreeLeechType'] === 3) {
- // Figure out which duration to use
- $Expiry = 0;
-
- foreach ($FreeLeechTags as $Tag => $Exp) {
- if ($Tag === 'global' || in_array($Tag, $Tags)) {
- if (((int) $FreeLeechTags[$Tag]['First']) > $Expiry) {
- $Expiry = (int) $FreeLeechTags[$Tag]['First'];
- }
- }
- }
-
- if ($Expiry > 0) {
- $DB->query("
- INSERT INTO shop_freeleeches
- (TorrentID, ExpiryTime)
- VALUES
- (" . $TorrentID . ", FROM_UNIXTIME(" . $Expiry . "))
- ON DUPLICATE KEY UPDATE
- ExpiryTime = FROM_UNIXTIME(UNIX_TIMESTAMP(ExpiryTime) + ($Expiry - FROM_UNIXTIME(NOW())))");
- } else {
- Torrents::freeleech_torrents($TorrentID, 0, 0);
- }
- }
-
- //******************************************************************************//
- //--------------- Write torrent file -------------------------------------------//
-
- $FileName = "$ENV->TORRENT_STORE/$TorrentID.torrent";
- file_put_contents($FileName, $Tor->encode());
- chmod($FileName, 0400);
-
- Misc::write_log("Torrent $TorrentID ($LogName) (".number_format($TotalSize / (1024 * 1024), 2).' MB) was uploaded by ' . $LoggedUser['Username']);
- Torrents::write_group_log($GroupID, $TorrentID, $LoggedUser['ID'], 'uploaded ('.number_format($TotalSize / (1024 * 1024), 2).' MB)', 0);
-
- Torrents::update_hash($GroupID);
- $Debug->set_flag('upload: sphinx updated');
-
- //******************************************************************************//
- //---------------------- Recent Uploads ----------------------------------------//
-
- if (trim($T['Image']) !== '') {
- $RecentUploads = $Cache->get_value("recent_uploads_$UserID");
- if (is_array($RecentUploads)) {
- do {
- foreach ($RecentUploads as $Item) {
- if ($Item['ID'] === $GroupID) {
- break 2;
- }
- }
-
- // Only reached if no matching GroupIDs in the cache already.
- if (count($RecentUploads) === 5) {
- array_pop($RecentUploads);
- }
- array_unshift($RecentUploads, array(
- 'ID' => $GroupID,
- 'Name' => trim($T['Title']),
- 'Artist' => Artists::display_artists($ArtistForm, false, true),
- 'WikiImage' => trim($T['Image'])));
- $Cache->cache_value("recent_uploads_$UserID", $RecentUploads, 0);
- } while (0);
- }
- }
-
-
- /**
- * Post-processing
- *
- * Because tracker updates and notifications can be slow, we're redirecting the user to the destination page
- * and flushing the buffers to make it seem like the PHP process is working in the background.
- */
-
- if ($PublicTorrent) {
- View::show_header('Warning'); ?>
- <h1>Warning</h1>
- <p>
- <strong>Your torrent has been uploaded but you must re-download your torrent file from
- <a
- href="torrents.php?id=<?=$GroupID?>&torrentid=<?=$TorrentID?>">here</a>
- because the site modified it to make it private.</strong>
- </p>
- <?php
- View::show_footer();
- } elseif ($UnsourcedTorrent) {
- View::show_header('Warning'); ?>
- <h1>Warning</h1>
- <p>
- <strong>Your torrent has been uploaded but you must re-download your torrent file from
- <a
- href="torrents.php?id=<?=$GroupID?>&torrentid=<?=$TorrentID?>">here</a>
- because the site modified it to add a source flag.</strong>
- </p>
- <?php
- View::show_footer();
- } elseif ($RequestID) {
- header("Location: requests.php?action=takefill&requestid=$RequestID&torrentid=$TorrentID&auth=".$LoggedUser['AuthKey']);
- } else {
- header("Location: torrents.php?id=$GroupID&torrentid=$TorrentID");
- }
-
- if (function_exists('fastcgi_finish_request')) {
- fastcgi_finish_request();
- } else {
- ignore_user_abort(true);
- ob_flush();
- flush();
- ob_start(); // So we don't keep sending data to the client
- }
-
-
- /**
- * IRC announce and feeds
- */
-
- $Announce = '';
-
- # Category and title
- $Announce .= '['.$T['CategoryName'].'] ';
- $Announce .= substr(trim(empty($T['Title']) ? (empty($T['Title2']) ? $T['TitleJP'] : $T['Title2']) : $T['Title']), 0, 100);
- $Announce .= ' ';
-
- # Exploded for sanity
- $Announce .= '[ '
- . Torrents::torrent_info(
- $Data = $T,
- $ShowMedia = true,
- $ShowEdition = false,
- $HTMLy = false
- )
- . ' ]';
-
- # Twitter stuff
- # Grab $Announce here
- /*
- $Tweet = $Announce;
- $TweetTags =
- implode(
- ' ',
- # Add hashtags
- preg_replace(
- '/^\s* /', # remove space in "* /"
- '#',
- # Trim raw explosion
- array_filter(
- explode(
- ',',
- # todo: Get validated output
- $T['TagList']
- ),
- 'trim'
- )
- )
- );
- $Tweet .= $TweetTags;
- */
-
- # Tags and link
- $Announce .= ' - '.trim($T['TagList']);
- $Announce .= ' - '.site_url()."torrents.php?id=$GroupID&torrentid=$TorrentID";
- $Announce .= ' - '.site_url()."torrents.php?action=download&id=$TorrentID";
-
- # Unused
- #$Title = '['.$T['CategoryName'].'] '.$Announce;
- #$Announce .= Artists::display_artists($ArtistForm, false);
-
- // ENT_QUOTES is needed to decode single quotes/apostrophes
- send_irc(ANNOUNCE_CHAN, html_entity_decode($Announce, ENT_QUOTES));
- $Debug->set_flag('upload: announced on irc');
-
- /**
- * Manage motifications
- */
- // For RSS
- $Item = $Feed->item(
- $Announce,
- Text::strip_bbcode($Body),
- 'torrents.php?action=download&authkey=[[AUTHKEY]]&torrent_pass=[[PASSKEY]]&id='.$TorrentID,
- $Properties['Anonymous'] ? 'Anonymous' : $LoggedUser['Username'],
- 'torrents.php?id='.$GroupID,
- trim($T['TagList'])
- );
-
- // Notifications
- $SQL = "
- SELECT
- unf.`ID`,
- unf.`UserID`,
- `torrent_pass`
- FROM
- `users_notify_filters` AS unf
- JOIN `users_main` AS um
- ON
- um.`ID` = unf.`UserID`
- WHERE
- um.`Enabled` = '1'
- ";
-
- # Creators
- if (empty($ArtistsUnescaped)) {
- $ArtistsUnescaped = $ArtistForm;
- }
-
- if (!empty($ArtistsUnescaped)) {
- $ArtistNameList = [];
- $GuestArtistNameList = [];
-
- foreach ($ArtistsUnescaped as $Importance => $Artist) {
- $ArtistNameList[] = "Artists LIKE '%|".db_string(str_replace('\\', '\\\\', $Artist['name']), true)."|%'";
- }
-
- $SQL .= " AND (";
-
- if (count($ArtistNameList) > 0) {
- $SQL .= implode(' OR ', $ArtistNameList);
- $SQL .= " OR ";
- }
- $SQL .= "Artists = '') AND (";
- } else {
- $SQL .= "AND (Artists = '') AND (";
- }
-
- # Tags
- reset($Tags);
- $TagSQL = [];
- $NotTagSQL = [];
-
- foreach ($Tags as $Tag) {
- $TagSQL[] = " Tags LIKE '%|".db_string(trim($Tag))."|%' ";
- $NotTagSQL[] = " NotTags LIKE '%|".db_string(trim($Tag))."|%' ";
- }
-
- $TagSQL[] = "Tags = ''";
- $SQL .= implode(' OR ', $TagSQL);
- $SQL .= ") AND !(".implode(' OR ', $NotTagSQL).')';
- $SQL .= " AND (Categories LIKE '%|".db_string(trim($Type))."|%' OR Categories = '') ";
-
-
- /*
- Notify based on the following:
- 1. The torrent must match the formatbitrate filter on the notification
- 2. If they set NewGroupsOnly to 1, it must also be the first torrent in the group to match the formatbitrate filter on the notification
- */
-
- if ($T['Format']) {
- $SQL .= " AND (Formats LIKE '%|".db_string(trim($T['Format']))."|%' OR Formats = '') ";
- } else {
- $SQL .= " AND (Formats = '') ";
- }
-
- if ($T['Media']) {
- $SQL .= " AND (Media LIKE '%|".db_string(trim($T['Media']))."|%' OR Media = '') ";
- } else {
- $SQL .= " AND (Media = '') ";
- }
-
- // Either they aren't using NewGroupsOnly
- $SQL .= "AND ((NewGroupsOnly = '0' ";
- // Or this is the first torrent in the group to match the formatbitrate filter
- $SQL .= ") OR ( NewGroupsOnly = '1' ";
- $SQL .= '))';
-
- if ($T['Year']) {
- $SQL .= " AND (('".db_string(trim($T['Year']))."' BETWEEN FromYear AND ToYear)
- OR (FromYear = 0 AND ToYear = 0)) ";
- } else {
- $SQL .= " AND (FromYear = 0 AND ToYear = 0) ";
- }
-
- $SQL .= " AND UserID != '".$LoggedUser['ID']."' ";
-
- $DB->query("
- SELECT
- `Paranoia`
- FROM
- `users_main`
- WHERE
- `ID` = $LoggedUser[ID]
- ");
-
- list($Paranoia) = $DB->next_record();
- $Paranoia = unserialize($Paranoia);
-
- if (!is_array($Paranoia)) {
- $Paranoia = [];
- }
-
- if (!in_array('notifications', $Paranoia)) {
- $SQL .= " AND (Users LIKE '%|".$LoggedUser['ID']."|%' OR Users = '') ";
- }
-
- $SQL .= " AND UserID != '".$LoggedUser['ID']."' ";
- $DB->query($SQL);
- $Debug->set_flag('upload: notification query finished');
-
- if ($DB->has_results()) {
- $UserArray = $DB->to_array('UserID');
- $FilterArray = $DB->to_array('ID');
-
- $InsertSQL = '
- INSERT IGNORE INTO `users_notify_torrents` (`UserID`, `GroupID`, `TorrentID`, `FilterID`)
- VALUES ';
-
- $Rows = [];
- foreach ($UserArray as $User) {
- list($FilterID, $UserID, $Passkey) = $User;
- $Rows[] = "('$UserID', '$GroupID', '$TorrentID', '$FilterID')";
- $Feed->populate("torrents_notify_$Passkey", $Item);
- $Cache->delete_value("notifications_new_$UserID");
- }
-
- $InsertSQL .= implode(',', $Rows);
- $DB->query($InsertSQL);
- $Debug->set_flag('upload: notification inserts finished');
-
- foreach ($FilterArray as $Filter) {
- list($FilterID, $UserID, $Passkey) = $Filter;
- $Feed->populate("torrents_notify_{$FilterID}_$Passkey", $Item);
- }
- }
-
- // RSS for bookmarks
- $DB->query("
- SELECT
- u.`ID`,
- u.`torrent_pass`
- FROM
- `users_main` AS u
- JOIN `bookmarks_torrents` AS b
- ON
- b.`UserID` = u.`ID`
- WHERE
- b.`GroupID` = '$GroupID'
- ");
-
- while (list($UserID, $Passkey) = $DB->next_record()) {
- $Feed->populate("torrents_bookmarks_t_$Passkey", $Item);
- }
-
- $Feed->populate('torrents_all', $Item);
- $Feed->populate('torrents_'.strtolower($Type), $Item);
- $Debug->set_flag('upload: notifications handled');
-
- # Clear cache
- $Cache->delete_value("torrents_details_$GroupID");
- $Cache->delete_value("contest_scores");
-
- # Allow deletion of this torrent now
- $Cache->delete_value("torrent_{$TorrentID}_lock");
|