Oppaitime's version of Gazelle
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

upload_handle.php 34KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952
  1. <?
  2. //****************************************************************************//
  3. //--------------- Take upload ------------------------------------------------//
  4. // This pages handles the backend of the torrent upload function. It checks //
  5. // the data, and if it all validates, it builds the torrent file, then writes //
  6. // the data to the database and the torrent to the disk. //
  7. //****************************************************************************//
  8. // Maximum allowed size for uploaded files.
  9. // http://php.net/upload-max-filesize
  10. ini_set('upload_max_filesize', 2097152); // 2 Mibibytes
  11. ini_set('max_file_uploads', 100);
  12. define('MAX_FILENAME_LENGTH', 180);
  13. include(SERVER_ROOT.'/classes/validate.class.php');
  14. include(SERVER_ROOT.'/classes/feed.class.php');
  15. include(SERVER_ROOT.'/sections/torrents/functions.php');
  16. include(SERVER_ROOT.'/classes/file_checker.class.php');
  17. enforce_login();
  18. authorize();
  19. $Validate = new VALIDATE;
  20. $Feed = new FEED;
  21. define('QUERY_EXCEPTION', true); // Shut up debugging
  22. //******************************************************************************//
  23. //--------------- Set $Properties array ----------------------------------------//
  24. // This is used if the form doesn't validate, and when the time comes to enter //
  25. // it into the database. //
  26. // Haha wow god i'm trying to restrict the database to only have fields for //
  27. // movies and not add anything for other categories but this is fucking dumb //
  28. $Properties = array();
  29. $Type = $Categories[(int)$_POST['type']];
  30. $TypeID = $_POST['type'] + 1;
  31. $Properties['CategoryName'] = $Type;
  32. $Properties['Title'] = $_POST['title'];
  33. $Properties['TitleJP'] = $_POST['title_jp'];
  34. $Properties['Year'] = $_POST['year'];
  35. $Properties['Studio'] = isset($_POST['studio']) ? $_POST['studio'] : '';
  36. $Properties['Series'] = isset($_POST['series']) ? $_POST['series'] : '';
  37. $Properties['CatalogueNumber'] = isset($_POST['catalogue']) ? $_POST['catalogue'] : '';
  38. $Properties['Pages'] = isset($_POST['pages']) ? $_POST['pages'] : 0;
  39. $Properties['Container'] = isset($_POST['container']) ? $_POST['container'] : '';
  40. $Properties['Media'] = $_POST['media'];
  41. $Properties['Codec'] = isset($_POST['codec']) ? $_POST['codec'] : '';
  42. $Properties['Resolution'] = isset($_POST['resolution']) ? $_POST['resolution'] : '';
  43. $Properties['AudioFormat'] = isset($_POST['audioformat']) ? $_POST['audioformat'] : '';
  44. $Properties['Subbing'] = isset($_POST['sub']) ? $_POST['sub'] : '';
  45. $Properties['Language'] = isset($_POST['lang']) ? $_POST['lang'] : '';
  46. $Properties['Subber'] = isset($_POST['subber']) ? $_POST['subber'] : '';
  47. $Properties['DLsiteID'] = (isset($_POST['dlsiteid'])) ? $_POST['dlsiteid'] : '';
  48. $Properties['Censored'] = (isset($_POST['censored'])) ? 1 : 0;
  49. $Properties['Archive'] = (isset($_POST['archive']) && $_POST['archive'] != '---') ? $_POST['archive'] : '';
  50. if (isset($_POST['library_image'])) $Properties['LibraryImage'] = $_POST['library_image'];
  51. if (isset($_POST['tags'])) $Properties['TagList'] = implode(',',array_unique(explode(',', str_replace(' ','',$_POST['tags']))));
  52. if (isset($_POST['image'])) $Properties['Image'] = $_POST['image'];
  53. if (isset($_POST['release'])) {
  54. $Properties['ReleaseGroup'] = $_POST['release'];
  55. }
  56. $Properties['GroupDescription'] = trim($_POST['album_desc']);
  57. $Properties['TorrentDescription'] = $_POST['release_desc'];
  58. $Properties['MediaInfo'] = $_POST['mediainfo'];
  59. $Properties['Screenshots'] = isset($_POST['screenshots']) ? $_POST['screenshots'] : "";
  60. if ($_POST['album_desc']) {
  61. $Properties['GroupDescription'] = trim($_POST['album_desc']);
  62. } elseif ($_POST['desc']) {
  63. $Properties['GroupDescription'] = trim($_POST['desc']);
  64. $Properties['MediaInfo'] = $_POST['mediainfo'];
  65. }
  66. if (isset($_POST['groupid'])) $Properties['GroupID'] = $_POST['groupid'];
  67. if (isset($Properties['GroupID'])) {
  68. $Properties['Artists'] = Artists::get_artist($Properties['GroupID']);
  69. }
  70. if ($Type == 'Movies' || $Type == 'Manga' || $Type == 'Anime' || $Type == 'Games' ) {
  71. if (empty($_POST['idols'])) {
  72. $Err = "You didn't enter any goils";
  73. } else {
  74. $Artists = $_POST['idols'];
  75. }
  76. }
  77. if (!empty($_POST['requestid'])) {
  78. $RequestID = $_POST['requestid'];
  79. $Properties['RequestID'] = $RequestID;
  80. }
  81. //******************************************************************************//
  82. //--------------- Validate data in upload form ---------------------------------//
  83. $Validate->SetFields('type', '1', 'inarray', 'Please select a valid type.', array('inarray' => array_keys($Categories)));
  84. switch ($Type) {
  85. case 'Movies':
  86. case 'Anime':
  87. $Validate->SetFields('codec',
  88. '1','inarray','Please select a valid codec.', array('inarray'=>$Codecs));
  89. $Validate->SetFields('resolution',
  90. '1','regex','Please set a valid resolution.', array('regex'=>'/^(SD)|([0-9]+(p|i))|([0-9]K)|([0-9]+x[0-9]+)$/'));
  91. $Validate->SetFields('audioformat',
  92. '1','inarray','Please select a valid audio format.', array('inarray'=>$AudioFormats));
  93. $Validate->SetFields('sub',
  94. '1','inarray','Please select a valid sub format.', array('inarray'=>$Subbing));
  95. $Validate->SetFields('censored', '1', 'inarray', 'Set valid censoring', array('inarray'=>array(0, 1)));
  96. case 'Games':
  97. $Validate->SetFields('container',
  98. '1','inarray','Please select a valid container.', array('inarray'=>array_merge($Containers, $ContainersGames)));
  99. case 'Manga':
  100. if (!isset($_POST['groupid']) || !$_POST['groupid']) {
  101. $Validate->SetFields('year',
  102. '1','number','The year of the original release must be entered.', array('maxlength'=>3000, 'minlength'=>1800));
  103. if ($Type == 'Manga') {
  104. $Validate->SetFields('pages',
  105. '1', 'number', 'That is not a valid page count', array('minlength'=>1));
  106. }
  107. }
  108. $Validate->SetFields('media',
  109. '1','inarray','Please select a valid media/platform.', array('inarray'=>array_merge($Media, $MediaManga, $Platform)));
  110. $Validate->SetFields('lang',
  111. '1','inarray','Please select a valid language.', array('inarray'=>$Languages));
  112. $Validate->SetFields('release_desc',
  113. '0','string','The release description has a minimum length of 10 characters.', array('maxlength'=>1000000, 'minlength'=>10));
  114. default:
  115. if (!isset($_POST['groupid']) || !$_POST['groupid']) {
  116. $Validate->SetFields('title',
  117. '1','string','Title must be between 1 and 200 characters.', array('maxlength'=>200, 'minlength'=>1));
  118. if (isset($_POST['title_jp'])) {
  119. $Validate->SetFields('title_jp',
  120. '1','string','Japanese Title must be between 1 and 512 bytes.', array('maxlength'=>512, 'minlength'=>1));
  121. }
  122. $Validate->SetFields('tags',
  123. '1','string','You must enter at least one tag. Maximum length is 300 characters.', array('maxlength'=>300, 'minlength'=>2));
  124. $Validate->SetFields('image',
  125. '0','link','The image URL you entered was invalid.', array('maxlength'=>255, 'minlength'=>12));
  126. }
  127. $Validate->SetFields('album_desc',
  128. '1','string','The description has a minimum length of 10 characters.', array('maxlength'=>1000000, 'minlength'=>10));
  129. $Validate->SetFields('groupid', '0', 'number', 'Group ID was not numeric');
  130. }
  131. $Validate->SetFields('rules',
  132. '1','require','Your torrent must abide by the rules.');
  133. $Err = $Validate->ValidateForm($_POST); // Validate the form
  134. if (count(explode(',', $Properties['TagList'])) < 5) {
  135. $Err = 'You must enter at least 5 tags.';
  136. }
  137. $File = $_FILES['file_input']; // This is our torrent file
  138. $TorrentName = $File['tmp_name'];
  139. if (!is_uploaded_file($TorrentName) || !filesize($TorrentName)) {
  140. $Err = 'No torrent file uploaded, or file is empty.';
  141. } elseif (substr(strtolower($File['name']), strlen($File['name']) - strlen('.torrent')) !== '.torrent') {
  142. $Err = "You seem to have put something other than a torrent file into the upload field. (".$File['name'].").";
  143. }
  144. /*if ($Type == 'Music') {
  145. include(SERVER_ROOT.'/sections/upload/get_extra_torrents.php');
  146. }*/
  147. //Multiple artists!
  148. $LogName = '';
  149. if (empty($Properties['GroupID']) && empty($ArtistForm) && ($Type == 'Movies' || $Type == 'Anime' || $Type == 'Manga' || $Type == 'Games')) {
  150. $ArtistNames = array();
  151. $ArtistForm = array();
  152. for ($i = 0; $i < count($Artists); $i++) {
  153. if (trim($Artists[$i]) != '') {
  154. if (!in_array($Artists[$i], $ArtistNames)) {
  155. $ArtistForm[$i] = array('name' => Artists::normalise_artist_name($Artists[$i]));
  156. array_push($ArtistNames, $ArtistForm[$i]['name']);
  157. }
  158. }
  159. }
  160. $LogName .= Artists::display_artists($ArtistForm, false, true, false);
  161. } elseif (($Type == 'Movies' || $Type == 'Anime' || $Type == 'Manga' || $Type == 'Games') && empty($ArtistForm)) {
  162. $DB->query("
  163. SELECT ta.ArtistID, ag.Name
  164. FROM torrents_artists AS ta
  165. JOIN artists_group AS ag ON ta.ArtistID = ag.ArtistID
  166. WHERE ta.GroupID = ".$Properties['GroupID']."
  167. ORDER BY ag.Name ASC;");
  168. $ArtistForm = array();
  169. while (list($ArtistID, $ArtistName) = $DB->next_record(MYSQLI_BOTH, false)) {
  170. array_push($ArtistForm, array('id' => $ArtistID, 'name' => display_str($ArtistName)));
  171. array_push($ArtistsUnescaped, array('name' => $ArtistName));
  172. }
  173. $LogName .= Artists::display_artists($ArtistsUnescaped, false, true, false);
  174. }
  175. if ($Err) { // Show the upload form, with the data the user entered
  176. $UploadForm = $Type;
  177. include(SERVER_ROOT.'/sections/upload/upload.php');
  178. die();
  179. }
  180. // Strip out Amazon's padding
  181. $AmazonReg = '/(http:\/\/ecx.images-amazon.com\/images\/.+)(\._.*_\.jpg)/i';
  182. $Matches = array();
  183. //What the fuck is $RegX what.cd devs?
  184. //if (preg_match($RegX, $Properties['Image'], $Matches)) {
  185. if (preg_match($AmazonReg, $Properties['Image'], $Matches)) {
  186. $Properties['Image'] = $Matches[1].'.jpg';
  187. }
  188. ImageTools::blacklisted($Properties['Image']);
  189. //******************************************************************************//
  190. //--------------- Make variables ready for database input ----------------------//
  191. // Shorten and escape $Properties for database input
  192. $T = array();
  193. foreach ($Properties as $Key => $Value) {
  194. $T[$Key] = "'".db_string(trim($Value))."'";
  195. if (!$T[$Key]) {
  196. $T[$Key] = null;
  197. }
  198. }
  199. $T['Censored'] = $Properties['Censored'];
  200. //******************************************************************************//
  201. //--------------- Generate torrent file ----------------------------------------//
  202. $Tor = new BencodeTorrent($TorrentName, true);
  203. $PublicTorrent = $Tor->make_private(); // The torrent is now private.
  204. $TorEnc = db_string($Tor->encode());
  205. $InfoHash = pack('H*', $Tor->info_hash());
  206. $DB->query("
  207. SELECT ID
  208. FROM torrents
  209. WHERE info_hash = '".db_string($InfoHash)."'");
  210. if ($DB->has_results()) {
  211. list($ID) = $DB->next_record();
  212. $DB->query("
  213. SELECT TorrentID
  214. FROM torrents_files
  215. WHERE TorrentID = $ID");
  216. if ($DB->has_results()) {
  217. $Err = '<a href="torrents.php?torrentid='.$ID.'">The exact same torrent file already exists on the site!</a>';
  218. } else {
  219. // A lost torrent
  220. $DB->query("
  221. INSERT INTO torrents_files (TorrentID, File)
  222. VALUES ($ID, '$TorEnc')");
  223. $Err = '<a href="torrents.php?torrentid='.$ID.'">Thank you for fixing this torrent</a>';
  224. }
  225. }
  226. if (isset($Tor->Dec['encrypted_files'])) {
  227. $Err = 'This torrent contains an encrypted file list which is not supported here.';
  228. }
  229. // File list and size
  230. list($TotalSize, $FileList) = $Tor->file_list();
  231. $NumFiles = count($FileList);
  232. $TmpFileList = array();
  233. $TooLongPaths = array();
  234. $DirName = (isset($Tor->Dec['info']['files']) ? Format::make_utf8($Tor->get_name()) : '');
  235. $IgnoredLogFileNames = array('audiochecker.log', 'sox.log');
  236. check_name($DirName); // check the folder name against the blacklist
  237. foreach ($FileList as $File) {
  238. list($Size, $Name) = $File;
  239. // Check file name and extension against blacklist/whitelist
  240. check_file($Type, $Name);
  241. // Make sure the filename is not too long
  242. if (mb_strlen($Name, 'UTF-8') + mb_strlen($DirName, 'UTF-8') + 1 > MAX_FILENAME_LENGTH) {
  243. $TooLongPaths[] = "$DirName/$Name";
  244. }
  245. // Add file info to array
  246. $TmpFileList[] = Torrents::filelist_format_file($File);
  247. }
  248. if (count($TooLongPaths) > 0) {
  249. $Names = implode(' <br />', $TooLongPaths);
  250. $Err = "The torrent contained one or more files with too long a name:<br /> $Names";
  251. }
  252. $FilePath = db_string($DirName);
  253. $FileString = db_string(implode("\n", $TmpFileList));
  254. $Debug->set_flag('upload: torrent decoded');
  255. /*if ($Type == 'Music') {
  256. include(SERVER_ROOT.'/sections/upload/generate_extra_torrents.php');
  257. }*/
  258. if (!empty($Err)) { // Show the upload form, with the data the user entered
  259. $UploadForm = $Type;
  260. include(SERVER_ROOT.'/sections/upload/upload.php');
  261. die();
  262. }
  263. //******************************************************************************//
  264. //--------------- Start database stuff -----------------------------------------//
  265. $Body = $Properties['GroupDescription'];
  266. // Trickery
  267. if (!preg_match('/^'.IMAGE_REGEX.'$/i', $Properties['Image'])) {
  268. $Properties['Image'] = '';
  269. $T['Image'] = "''";
  270. }
  271. if ($Type == 'Movies' || $Type == 'Anime' || $Type == 'Manga' || $Type == 'Games') {
  272. // Does it belong in a group?
  273. if ($Properties['GroupID']) {
  274. $DB->query("
  275. SELECT
  276. ID,
  277. WikiImage,
  278. WikiBody,
  279. RevisionID,
  280. Name,
  281. Year,
  282. TagList
  283. FROM torrents_group
  284. WHERE id = ".$Properties['GroupID']);
  285. if ($DB->has_results()) {
  286. // Don't escape tg.Name. It's written directly to the log table
  287. list($GroupID, $WikiImage, $WikiBody, $RevisionID, $Properties['Title'], $Properties['Year'], $Properties['TagList']) = $DB->next_record(MYSQLI_NUM, array(4));
  288. $Properties['TagList'] = str_replace(array(' ', '.', '_'), array(', ', '.', '.'), $Properties['TagList']);
  289. if (!$Properties['Image'] && $WikiImage) {
  290. $Properties['Image'] = $WikiImage;
  291. $T['Image'] = "'".db_string($WikiImage)."'";
  292. }
  293. if (strlen($WikiBody) > strlen($Body)) {
  294. $Body = $WikiBody;
  295. if (!$Properties['Image'] || $Properties['Image'] == $WikiImage) {
  296. $NoRevision = true;
  297. }
  298. }
  299. $Properties['Artist'] = Artists::display_artists(Artists::get_artist($GroupID), false, false);
  300. }
  301. }
  302. if (!isset($GroupID) || !$GroupID) {
  303. foreach ($ArtistForm as $Num => $Artist) {
  304. $DB->query("
  305. SELECT
  306. tg.id,
  307. tg.WikiImage,
  308. tg.WikiBody,
  309. tg.RevisionID
  310. FROM torrents_group AS tg
  311. LEFT JOIN torrents_artists AS ta ON ta.GroupID = tg.ID
  312. LEFT JOIN artists_group AS ag ON ta.ArtistID = ag.ArtistID
  313. WHERE ag.Name = '".db_string($Artist['name'])."'
  314. AND tg.Name = ".$T['Title']."
  315. AND tg.Year = ".$T['Year']);
  316. if ($DB->has_results()) {
  317. list($GroupID, $WikiImage, $WikiBody, $RevisionID) = $DB->next_record();
  318. if (!$Properties['Image'] && $WikiImage) {
  319. $Properties['Image'] = $WikiImage;
  320. $T['Image'] = "'".db_string($WikiImage)."'";
  321. }
  322. if (strlen($WikiBody) > strlen($Body)) {
  323. $Body = $WikiBody;
  324. if (!$Properties['Image'] || $Properties['Image'] == $WikiImage) {
  325. $NoRevision = true;
  326. }
  327. }
  328. $ArtistForm = Artists::get_artist($GroupID);
  329. //This torrent belongs in a group
  330. break;
  331. } else {
  332. // The album hasn't been uploaded. Try to get the artist IDs
  333. $DB->query("
  334. SELECT
  335. ArtistID,
  336. Name
  337. FROM artists_group
  338. WHERE Name = '".db_string($Artist['name'])."'");
  339. if ($DB->has_results()) {
  340. while (list($ArtistID, $Name) = $DB->next_record(MYSQLI_NUM, false)) {
  341. if (!strcasecmp($Artist['name'], $Name)) {
  342. $ArtistForm[$Num] = array('id' => $ArtistID, 'name' => $Name);
  343. break;
  344. }
  345. }
  346. }
  347. }
  348. }
  349. }
  350. }
  351. //Needs to be here as it isn't set for add format until now
  352. $LogName .= $Properties['Title'];
  353. //For notifications--take note now whether it's a new group
  354. $IsNewGroup = !isset($GroupID) || !$GroupID;
  355. //----- Start inserts
  356. if ((!isset($GroupID) || !$GroupID) && ($Type != 'Other')) {
  357. //array to store which artists we have added already, to prevent adding an artist twice
  358. $ArtistsAdded = array();
  359. foreach ($ArtistForm as $Num => $Artist) {
  360. if (!isset($Artist['id']) || !$Artist['id']) {
  361. if (isset($ArtistsAdded[strtolower($Artist['name'])])) {
  362. $ArtistForm[$Num] = $ArtistsAdded[strtolower($Artist['name'])];
  363. } else {
  364. // Create artist
  365. $DB->query("
  366. INSERT INTO artists_group (Name)
  367. VALUES ('".db_string($Artist['name'])."')");
  368. $ArtistID = $DB->inserted_id();
  369. $Cache->increment('stats_artist_count');
  370. /*$DB->query("
  371. INSERT INTO artists_alias (ArtistID, Name)
  372. VALUES ($ArtistID, '".db_string($Artist['name'])."')");
  373. $AliasID = $DB->inserted_id();*/
  374. $ArtistForm[$Num] = array('id' => $ArtistID, 'name' => $Artist['name']);
  375. $ArtistsAdded[strtolower($Artist['name'])] = $ArtistForm[$Num];
  376. }
  377. }
  378. }
  379. unset($ArtistsAdded);
  380. }
  381. if (!isset($GroupID) || !$GroupID) {
  382. // Create torrent group
  383. $DB->query("
  384. INSERT INTO torrents_group
  385. (CategoryID, Name, NameJP, Year, Series, Studio, CatalogueNumber, Pages, Time, WikiBody, WikiImage, DLsiteID)
  386. VALUES
  387. ($TypeID, ".$T['Title'].", ".$T['TitleJP'].", ".$T['Year'].", ".$T['Series'].", ".$T['Studio'].", ".$T['CatalogueNumber'].", " . $T['Pages'] . ", '".sqltime()."', '".db_string($Body)."', ".$T['Image'].", ".$T['DLsiteID'].")");
  388. $GroupID = $DB->inserted_id();
  389. if ($Type == 'Movies' || $Type == 'Anime' || $Type == 'Manga' || $Type == 'Games') {
  390. foreach ($ArtistForm as $Num => $Artist) {
  391. $DB->query("
  392. INSERT IGNORE INTO torrents_artists (GroupID, ArtistID, UserID)
  393. VALUES ($GroupID, ".$Artist['id'].', '.$LoggedUser['ID'].")");
  394. $Cache->increment('stats_album_count');
  395. $Cache->delete_value('artist_groups_'.$Artist['id']);
  396. }
  397. }
  398. $Cache->increment('stats_group_count');
  399. // Add screenshots
  400. $Screenshots = array_slice(array_filter(array_map("db_string", array_map("trim", array_unique(explode("\n", $Properties['Screenshots'])))), function ($s) { return preg_match('/^'.IMAGE_REGEX.'$/i', $s); }), 0, 10);
  401. $values = array();
  402. foreach ($Screenshots as $s) {
  403. $values[] = "(" . $GroupID . ", " . $LoggedUser['ID'] . ", NOW(), '" . $s . "')";
  404. }
  405. if (!empty($values)) {
  406. $DB->query("
  407. INSERT INTO torrents_screenshots
  408. (GroupID, UserID, Time, Image)
  409. VALUES " . implode(", ", $values));
  410. }
  411. } else {
  412. $DB->query("
  413. UPDATE torrents_group
  414. SET Time = '".sqltime()."'
  415. WHERE ID = $GroupID");
  416. $Cache->delete_value("torrent_group_$GroupID");
  417. $Cache->delete_value("torrents_details_$GroupID");
  418. $Cache->delete_value("detail_files_$GroupID");
  419. }
  420. // Description
  421. if (!isset($NoRevision) || !$NoRevision) {
  422. $DB->query("
  423. INSERT INTO wiki_torrents
  424. (PageID, Body, UserID, Summary, Time, Image)
  425. VALUES
  426. ($GroupID, $T[GroupDescription], $LoggedUser[ID], 'Uploaded new torrent', '".sqltime()."', $T[Image])");
  427. $RevisionID = $DB->inserted_id();
  428. // Revision ID
  429. $DB->query("
  430. UPDATE torrents_group
  431. SET RevisionID = '$RevisionID'
  432. WHERE ID = $GroupID");
  433. }
  434. // Tags
  435. $Tags = explode(',', $Properties['TagList']);
  436. if (!$Properties['GroupID']) {
  437. foreach ($Tags as $Tag) {
  438. $Tag = Misc::sanitize_tag($Tag);
  439. if (!empty($Tag)) {
  440. $Tag = Misc::get_alias_tag($Tag);
  441. $DB->query("
  442. INSERT INTO tags
  443. (Name, UserID)
  444. VALUES
  445. ('$Tag', $LoggedUser[ID])
  446. ON DUPLICATE KEY UPDATE
  447. Uses = Uses + 1;
  448. ");
  449. $TagID = $DB->inserted_id();
  450. $DB->query("
  451. INSERT INTO torrents_tags
  452. (TagID, GroupID, UserID, PositiveVotes)
  453. VALUES
  454. ($TagID, $GroupID, $LoggedUser[ID], 10)
  455. ON DUPLICATE KEY UPDATE
  456. PositiveVotes = PositiveVotes + 1;
  457. ");
  458. }
  459. }
  460. }
  461. // Use this section to control freeleeches
  462. $DB->query("
  463. SELECT Name, Value
  464. FROM site_options
  465. WHERE Comment = 'freeleech'");
  466. if ($DB->has_results()) {
  467. $FreeLeechTags = $DB->to_array('Name');
  468. foreach ($FreeLeechTags as $Tag => $Exp) {
  469. if ($Tag == 'global' || in_array($Tag, $Tags)) {
  470. $T['FreeTorrent'] = 1;
  471. $T['FreeLeechType'] = 3;
  472. break;
  473. }
  474. }
  475. } else {
  476. $T['FreeTorrent'] = 0;
  477. $T['FreeLeechType'] = 0;
  478. }
  479. // Torrent
  480. $DB->query("
  481. INSERT INTO torrents
  482. (GroupID, UserID, Media, Container, Codec, Resolution, AudioFormat,
  483. Subbing, Language, Subber, Censored, Archive, info_hash, FileCount, FileList,
  484. FilePath, Size, Time, Description, MediaInfo, FreeTorrent, FreeLeechType)
  485. VALUES
  486. ($GroupID, $LoggedUser[ID], $T[Media], $T[Container], $T[Codec], $T[Resolution], $T[AudioFormat],
  487. $T[Subbing], $T[Language], $T[Subber], $T[Censored], $T[Archive],'".db_string($InfoHash)."', $NumFiles, '$FileString',
  488. '$FilePath', $TotalSize, '".sqltime()."', $T[TorrentDescription], $T[MediaInfo], '$T[FreeTorrent]', '$T[FreeLeechType]')");
  489. $Cache->increment('stats_torrent_count');
  490. $TorrentID = $DB->inserted_id();
  491. Tracker::update_tracker('add_torrent', array('id' => $TorrentID, 'info_hash' => rawurlencode($InfoHash), 'freetorrent' => $T['FreeTorrent']));
  492. $Debug->set_flag('upload: ocelot updated');
  493. // Prevent deletion of this torrent until the rest of the upload process is done
  494. // (expire the key after 10 minutes to prevent locking it for too long in case there's a fatal error below)
  495. $Cache->cache_value("torrent_{$TorrentID}_lock", true, 600);
  496. // Add to shop freeleeches if necessary
  497. if ($T['FreeLeechType'] == 3) {
  498. // Figure out which duration to use
  499. $Expiry = 0;
  500. foreach ($FreeLeechTags as $Tag => $Exp) {
  501. if ($Tag == 'global' || in_array($Tag, $Tags)) {
  502. if (((int) $FreeLeechTags[$Tag]['Value']) > $Expiry)
  503. $Expiry = (int) $FreeLeechTags[$Tag]['Value'];
  504. }
  505. }
  506. if ($Expiry > 0) {
  507. $DB->query("
  508. INSERT INTO shop_freeleeches
  509. (TorrentID, ExpiryTime)
  510. VALUES
  511. (" . $TorrentID . ", FROM_UNIXTIME(" . $Expiry . "))
  512. ON DUPLICATE KEY UPDATE
  513. ExpiryTime = FROM_UNIXTIME(UNIX_TIMESTAMP(ExpiryTime) + ($Expiry - FROM_UNIXTIME(NOW())))");
  514. } else {
  515. Torrents::freeleech_torrents($TorrentID, 0, 0);
  516. }
  517. }
  518. //******************************************************************************//
  519. //--------------- Write torrent file -------------------------------------------//
  520. $DB->query("
  521. INSERT INTO torrents_files (TorrentID, File)
  522. VALUES ($TorrentID, '$TorEnc')");
  523. Misc::write_log("Torrent $TorrentID ($LogName) (".number_format($TotalSize / (1024 * 1024), 2).' MB) was uploaded by ' . $LoggedUser['Username']);
  524. Torrents::write_group_log($GroupID, $TorrentID, $LoggedUser['ID'], 'uploaded ('.number_format($TotalSize / (1024 * 1024), 2).' MB)', 0);
  525. Torrents::update_hash($GroupID);
  526. $Debug->set_flag('upload: sphinx updated');
  527. /*if ($Type == 'Music') {
  528. include(SERVER_ROOT.'/sections/upload/insert_extra_torrents.php');
  529. }*/
  530. //******************************************************************************//
  531. //---------------------- Recent Uploads ----------------------------------------//
  532. if (trim($Properties['Image']) != '') {
  533. $RecentUploads = $Cache->get_value("recent_uploads_$UserID");
  534. if (is_array($RecentUploads)) {
  535. do {
  536. foreach ($RecentUploads as $Item) {
  537. if ($Item['ID'] == $GroupID) {
  538. break 2;
  539. }
  540. }
  541. // Only reached if no matching GroupIDs in the cache already.
  542. if (count($RecentUploads) === 5) {
  543. array_pop($RecentUploads);
  544. }
  545. array_unshift($RecentUploads, array(
  546. 'ID' => $GroupID,
  547. 'Name' => trim($Properties['Title']),
  548. 'Artist' => Artists::display_artists($ArtistForm, false, true),
  549. 'WikiImage' => trim($Properties['Image'])));
  550. $Cache->cache_value("recent_uploads_$UserID", $RecentUploads, 0);
  551. } while (0);
  552. }
  553. }
  554. //******************************************************************************//
  555. //---------------------------------- Contest -----------------------------------//
  556. if ($Properties['LibraryImage'] != '') {
  557. $DB->query("
  558. INSERT INTO reportsv2
  559. (ReporterID, TorrentID, Type, UserComment, Status, ReportedTime, Track, Image, ExtraID, Link)
  560. VALUES
  561. (0, $TorrentID, 'library', '".db_string(($Properties['MultiDisc'] ? 'Multi-disc' : ''))."', 'New', '".sqltime()."', '', '".db_string($Properties['LibraryImage'])."', '', '')");
  562. }
  563. //******************************************************************************//
  564. //------------------------------- Post-processing ------------------------------//
  565. /* Because tracker updates and notifications can be slow, we're
  566. * redirecting the user to the destination page and flushing the buffers
  567. * to make it seem like the PHP process is working in the background.
  568. */
  569. if ($PublicTorrent) {
  570. View::show_header('Warning');
  571. ?>
  572. <h1>Warning</h1>
  573. <p><strong>Your torrent has been uploaded; however, you must download your torrent from <a href="torrents.php?id=<?=$GroupID?>">here</a> because you didn't make your torrent using the "private" option.</strong></p>
  574. <?
  575. View::show_footer();
  576. } elseif ($RequestID) {
  577. header("Location: requests.php?action=takefill&requestid=$RequestID&torrentid=$TorrentID&auth=".$LoggedUser['AuthKey']);
  578. } else {
  579. header("Location: torrents.php?id=$GroupID");
  580. }
  581. if (function_exists('fastcgi_finish_request')) {
  582. fastcgi_finish_request();
  583. } else {
  584. ignore_user_abort(true);
  585. ob_flush();
  586. flush();
  587. ob_start(); // So we don't keep sending data to the client
  588. }
  589. //******************************************************************************//
  590. //--------------------------- IRC announce and feeds ---------------------------//
  591. $Announce = '';
  592. if ($Type != 'Other') {
  593. $Announce .= Artists::display_artists($ArtistForm, false);
  594. }
  595. $Announce .= trim($Properties['Title']).' ';
  596. if ($Type != 'Other') {
  597. $Announce .= '['.Torrents::torrent_info($Properties, false, false, false).']';
  598. }
  599. $Title = '['.$Properties['CategoryName'].'] '.$Announce;
  600. $Announce = "$Title - ".site_url()."torrents.php?id=$GroupID / ".site_url()."torrents.php?action=download&id=$TorrentID";
  601. $Announce .= ' - '.trim($Properties['TagList']);
  602. // ENT_QUOTES is needed to decode single quotes/apostrophes
  603. send_irc('PRIVMSG '.BOT_ANNOUNCE_CHAN.' '.html_entity_decode($Announce, ENT_QUOTES));
  604. $Debug->set_flag('upload: announced on irc');
  605. // Manage notifications
  606. /*
  607. $UsedFormatBitrates = array();
  608. if (!$IsNewGroup) {
  609. // maybe there are torrents in the same release as the new torrent. Let's find out (for notifications)
  610. $GroupInfo = get_group_info($GroupID, true, 0, false);
  611. $ThisMedia = display_str($Properties['Media']);
  612. $ThisRemastered = display_str($Properties['Remastered']);
  613. $ThisRemasterYear = display_str($Properties['RemasterYear']);
  614. $ThisRemasterTitle = display_str($Properties['RemasterTitle']);
  615. $ThisRemasterRecordLabel = display_str($Properties['RemasterRecordLabel']);
  616. $ThisRemasterCatalogueNumber = display_str($Properties['RemasterCatalogueNumber']);
  617. foreach ($GroupInfo[1] as $TorrentInfo) {
  618. if (($TorrentInfo['Media'] == $ThisMedia)
  619. && ($TorrentInfo['Remastered'] == $ThisRemastered)
  620. && ($TorrentInfo['RemasterYear'] == (int)$ThisRemasterYear)
  621. && ($TorrentInfo['RemasterTitle'] == $ThisRemasterTitle)
  622. && ($TorrentInfo['RemasterRecordLabel'] == $ThisRemasterRecordLabel)
  623. && ($TorrentInfo['RemasterCatalogueNumber'] == $ThisRemasterCatalogueNumber)
  624. && ($TorrentInfo['ID'] != $TorrentID)) {
  625. $UsedFormatBitrates[] = array('format' => $TorrentInfo['Format'], 'bitrate' => $TorrentInfo['Encoding']);
  626. }
  627. }
  628. }
  629. */
  630. // For RSS
  631. $Item = $Feed->item($Title, Text::strip_bbcode($Body), 'torrents.php?action=download&amp;authkey=[[AUTHKEY]]&amp;torrent_pass=[[PASSKEY]]&amp;id='.$TorrentID, $LoggedUser['Username'], 'torrents.php?id='.$GroupID, trim($Properties['TagList']));
  632. //Notifications
  633. $SQL = "
  634. SELECT unf.ID, unf.UserID, torrent_pass
  635. FROM users_notify_filters AS unf
  636. JOIN users_main AS um ON um.ID = unf.UserID
  637. WHERE um.Enabled = '1'";
  638. if (empty($ArtistsUnescaped)) {
  639. $ArtistsUnescaped = $ArtistForm;
  640. }
  641. if (!empty($ArtistsUnescaped)) {
  642. $ArtistNameList = array();
  643. $GuestArtistNameList = array();
  644. foreach ($ArtistsUnescaped as $Importance => $Artists) {
  645. foreach ($Artists as $Artist) {
  646. if ($Importance == 1 || $Importance == 4 || $Importance == 5 || $Importance == 6) {
  647. $ArtistNameList[] = "Artists LIKE '%|".db_string(str_replace('\\', '\\\\', $Artist['name']), true)."|%'";
  648. } else {
  649. $GuestArtistNameList[] = "Artists LIKE '%|".db_string(str_replace('\\', '\\\\', $Artist['name']), true)."|%'";
  650. }
  651. }
  652. }
  653. // Don't add notification if >2 main artists or if tracked artist isn't a main artist
  654. if (count($ArtistNameList) > 2 || $Artist['name'] == 'Various Artists') {
  655. $SQL .= " AND (ExcludeVA = '0' AND (";
  656. $SQL .= implode(' OR ', array_merge($ArtistNameList, $GuestArtistNameList));
  657. $SQL .= " OR Artists = '')) AND (";
  658. } else {
  659. $SQL .= " AND (";
  660. if (!empty($GuestArtistNameList)) {
  661. $SQL .= "(ExcludeVA = '0' AND (";
  662. $SQL .= implode(' OR ', $GuestArtistNameList);
  663. $SQL .= ')) OR ';
  664. }
  665. if (count($ArtistNameList) > 0) {
  666. $SQL .= implode(' OR ', $ArtistNameList);
  667. $SQL .= " OR ";
  668. }
  669. $SQL .= "Artists = '') AND (";
  670. }
  671. } else {
  672. $SQL .= "AND (Artists = '') AND (";
  673. }
  674. reset($Tags);
  675. $TagSQL = array();
  676. $NotTagSQL = array();
  677. foreach ($Tags as $Tag) {
  678. $TagSQL[] = " Tags LIKE '%|".db_string(trim($Tag))."|%' ";
  679. $NotTagSQL[] = " NotTags LIKE '%|".db_string(trim($Tag))."|%' ";
  680. }
  681. $TagSQL[] = "Tags = ''";
  682. $SQL .= implode(' OR ', $TagSQL);
  683. $SQL .= ") AND !(".implode(' OR ', $NotTagSQL).')';
  684. $SQL .= " AND (Categories LIKE '%|".db_string(trim($Type))."|%' OR Categories = '') ";
  685. if ($Properties['ReleaseType']) {
  686. $SQL .= " AND (ReleaseTypes LIKE '%|".db_string(trim($ReleaseTypes[$Properties['ReleaseType']]))."|%' OR ReleaseTypes = '') ";
  687. } else {
  688. $SQL .= " AND (ReleaseTypes = '') ";
  689. }
  690. /*
  691. Notify based on the following:
  692. 1. The torrent must match the formatbitrate filter on the notification
  693. 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
  694. */
  695. if ($Properties['Format']) {
  696. $SQL .= " AND (Formats LIKE '%|".db_string(trim($Properties['Format']))."|%' OR Formats = '') ";
  697. } else {
  698. $SQL .= " AND (Formats = '') ";
  699. }
  700. if ($_POST['bitrate']) {
  701. $SQL .= " AND (Encodings LIKE '%|".db_string(trim($_POST['bitrate']))."|%' OR Encodings = '') ";
  702. } else {
  703. $SQL .= " AND (Encodings = '') ";
  704. }
  705. if ($Properties['Media']) {
  706. $SQL .= " AND (Media LIKE '%|".db_string(trim($Properties['Media']))."|%' OR Media = '') ";
  707. } else {
  708. $SQL .= " AND (Media = '') ";
  709. }
  710. // Either they aren't using NewGroupsOnly
  711. $SQL .= "AND ((NewGroupsOnly = '0' ";
  712. // Or this is the first torrent in the group to match the formatbitrate filter
  713. $SQL .= ") OR ( NewGroupsOnly = '1' ";
  714. // Test the filter doesn't match any previous formatbitrate in the group
  715. /*
  716. foreach ($UsedFormatBitrates as $UsedFormatBitrate) {
  717. $FormatReq = "(Formats LIKE '%|".db_string($UsedFormatBitrate['format'])."|%' OR Formats = '') ";
  718. $BitrateReq = "(Encodings LIKE '%|".db_string($UsedFormatBitrate['bitrate'])."|%' OR Encodings = '') ";
  719. $SQL .= "AND (NOT($FormatReq AND $BitrateReq)) ";
  720. }
  721. */
  722. $SQL .= '))';
  723. /*if ($Properties['Year'] && $Properties['RemasterYear']) {
  724. $SQL .= " AND (('".db_string(trim($Properties['Year']))."' BETWEEN FromYear AND ToYear)
  725. OR ('".db_string(trim($Properties['RemasterYear']))."' BETWEEN FromYear AND ToYear)
  726. OR (FromYear = 0 AND ToYear = 0)) ";
  727. } else*/
  728. if ($Properties['Year'] || $Properties['RemasterYear']) {
  729. //$SQL .= " AND (('".db_string(trim(Max($Properties['Year'],$Properties['RemasterYear'])))."' BETWEEN FromYear AND ToYear)
  730. $SQL .= " AND (('".db_string(trim($Properties['Year']))."' BETWEEN FromYear AND ToYear)
  731. OR (FromYear = 0 AND ToYear = 0)) ";
  732. } else {
  733. $SQL .= " AND (FromYear = 0 AND ToYear = 0) ";
  734. }
  735. $SQL .= " AND UserID != '".$LoggedUser['ID']."' ";
  736. $DB->query("
  737. SELECT Paranoia
  738. FROM users_main
  739. WHERE ID = $LoggedUser[ID]");
  740. list($Paranoia) = $DB->next_record();
  741. $Paranoia = unserialize($Paranoia);
  742. if (!is_array($Paranoia)) {
  743. $Paranoia = array();
  744. }
  745. if (!in_array('notifications', $Paranoia)) {
  746. $SQL .= " AND (Users LIKE '%|".$LoggedUser['ID']."|%' OR Users = '') ";
  747. }
  748. $SQL .= " AND UserID != '".$LoggedUser['ID']."' ";
  749. $DB->query($SQL);
  750. $Debug->set_flag('upload: notification query finished');
  751. if ($DB->has_results()) {
  752. $UserArray = $DB->to_array('UserID');
  753. $FilterArray = $DB->to_array('ID');
  754. $InsertSQL = '
  755. INSERT IGNORE INTO users_notify_torrents (UserID, GroupID, TorrentID, FilterID)
  756. VALUES ';
  757. $Rows = array();
  758. foreach ($UserArray as $User) {
  759. list($FilterID, $UserID, $Passkey) = $User;
  760. $Rows[] = "('$UserID', '$GroupID', '$TorrentID', '$FilterID')";
  761. $Feed->populate("torrents_notify_$Passkey", $Item);
  762. $Cache->delete_value("notifications_new_$UserID");
  763. }
  764. $InsertSQL .= implode(',', $Rows);
  765. $DB->query($InsertSQL);
  766. $Debug->set_flag('upload: notification inserts finished');
  767. foreach ($FilterArray as $Filter) {
  768. list($FilterID, $UserID, $Passkey) = $Filter;
  769. $Feed->populate("torrents_notify_{$FilterID}_$Passkey", $Item);
  770. }
  771. }
  772. // RSS for bookmarks
  773. $DB->query("
  774. SELECT u.ID, u.torrent_pass
  775. FROM users_main AS u
  776. JOIN bookmarks_torrents AS b ON b.UserID = u.ID
  777. WHERE b.GroupID = $GroupID");
  778. while (list($UserID, $Passkey) = $DB->next_record()) {
  779. $Feed->populate("torrents_bookmarks_t_$Passkey", $Item);
  780. }
  781. $Feed->populate('torrents_all', $Item);
  782. $Debug->set_flag('upload: notifications handled');
  783. if ($Type == 'Music') {
  784. $Feed->populate('torrents_music', $Item);
  785. if ($Properties['Media'] == 'Vinyl') {
  786. $Feed->populate('torrents_vinyl', $Item);
  787. }
  788. if ($Properties['Bitrate'] == 'Lossless') {
  789. $Feed->populate('torrents_lossless', $Item);
  790. }
  791. if ($Properties['Bitrate'] == '24bit Lossless') {
  792. $Feed->populate('torrents_lossless24', $Item);
  793. }
  794. if ($Properties['Format'] == 'MP3') {
  795. $Feed->populate('torrents_mp3', $Item);
  796. }
  797. if ($Properties['Format'] == 'FLAC') {
  798. $Feed->populate('torrents_flac', $Item);
  799. }
  800. }
  801. if ($Type == 'Applications') {
  802. $Feed->populate('torrents_apps', $Item);
  803. }
  804. if ($Type == 'E-Books') {
  805. $Feed->populate('torrents_ebooks', $Item);
  806. }
  807. if ($Type == 'Audiobooks') {
  808. $Feed->populate('torrents_abooks', $Item);
  809. }
  810. if ($Type == 'E-Learning Videos') {
  811. $Feed->populate('torrents_evids', $Item);
  812. }
  813. if ($Type == 'Comedy') {
  814. $Feed->populate('torrents_comedy', $Item);
  815. }
  816. if ($Type == 'Comics') {
  817. $Feed->populate('torrents_comics', $Item);
  818. }
  819. // Clear cache
  820. $Cache->delete_value("torrents_details_$GroupID");
  821. $Cache->delete_value("contest_scores");
  822. // Allow deletion of this torrent now
  823. $Cache->delete_value("torrent_{$TorrentID}_lock");