Browse Source

[WiP] Embed HTTP/FTP mirrors in torrent files

pjc 5 years ago
parent
commit
2ae278eccc

+ 43
- 16
_packages/extension-parser/classes/config.php View File

@@ -1,6 +1,8 @@
1 1
 <?php
2 2
 
3
+# Line 224
3 4
 # Sequencing Formats
5
+#
4 6
 # https://www.ncbi.nlm.nih.gov/sra/docs/submitformats/
5 7
 $Containers = [
6 8
   'BAM'        => ['bam'],
@@ -26,13 +28,14 @@ $Containers = [
26 28
 ];
27 29
 
28 30
 # Imaging Formats
31
+#
29 32
 # https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3948928/
30 33
 $ContainersGames = [
31 34
   'Analyze'   => ['hdr', 'img'],
32 35
   'Interfile' => ['h33'],
33
-  'Dicom'     => ['dcm', 'dicom'],
34
-  'Nifti'     => ['nii', 'nifti'],
35
-  'Minc'      => ['minc', 'mnc'],
36
+  'DICOM'     => ['dcm', 'dicom'],
37
+  'NIfTI'     => ['nii', 'nifti'],
38
+  'MINC'      => ['minc', 'mnc'],
36 39
   'JPEG'      => ['jfif', 'jpeg', 'jpg'],
37 40
   'JPEG 2000' => ['j2k', 'jp2', 'jpf', 'jpm', 'jpx', 'mj2'],
38 41
   'PNG'       => ['png'],
@@ -42,8 +45,9 @@ $ContainersGames = [
42 45
 ];
43 46
 
44 47
 # Protein Formats
48
+# DON'T PARSE RAW FILES. TOO MANY COMPETING VENDORS
49
+#
45 50
 # https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3518119/
46
-# DO NOT PARSE RAW FILES. TOO MANY COMPETING VENDORS
47 51
 $ContainersProt = [
48 52
   'ABI/Sciex'      => ['t2d', 'wiff'],
49 53
   'APML'           => ['apml'],
@@ -57,28 +61,51 @@ $ContainersProt = [
57 61
   'MGF'            => ['mgf'],
58 62
   'MS2'            => ['ms2'],
59 63
   'MSF'            => ['msf'],
64
+  'mzData'         => ['mzdata'],
65
+  'mzML'           => ['mzml'],
66
+  'mzXML'          => ['mzxml'],
60 67
   'OMSSA'          => ['omssa', 'omx'],
61 68
   'PEFF'           => ['peff'],
69
+  'pepXML'         => ['pepxml'],
70
+  'protXML'        => ['protxml'],
62 71
   'Shimadzu'       => ['lcd', 'qgd', 'spc'],
63 72
   'Skyline'        => ['sky', 'skyd'],
64 73
   'TPP/SPC'        => ['dta'],
65 74
   'Tandem'         => ['tandem'],
66 75
   'TraML'          => ['traml'],
67 76
   'ULVAC-PHI'      => ['tdc'],
68
-  'mzML'           => ['mzml'],
69
-  'mzXML'          => ['mzxml'],
70
-  'mzData'         => ['mzdata'],
71
-  'pepXML'         => ['pepxml'],
72
-  'protXML'        => ['protxml'],
73 77
   'Plain'          => ['csv', 'txt'],
74 78
 ];
75 79
 
80
+# Extra Formats
81
+# DON'T PARSE IMG OR ISO FILES
82
+#
83
+# https://en.wikipedia.org/wiki/Disk_image#File_formats
84
+# https://en.wikipedia.org/wiki/OpenDocument
85
+# https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions
86
+# http://dcjtech.info/topic/python-file-extensions/
87
+$ContainersExtra = [
88
+  'Docker'           => ['dockerfile'],
89
+  'Hard Disk'        => ['fvd', 'dmg', 'esd', 'qcow', 'qcow2', 'qcow3', 'smi', 'swm', 'vdi', 'vhd', 'vhdx', 'vmdk', 'wim'],
90
+  'Optical Disc'     => ['bin', 'ccd', 'cso', 'cue', 'daa', 'isz', 'mdf', 'mds', 'mdx', 'nrg', 'uif'],
91
+  'Python'           => ['pxd', 'py', 'py3', 'pyc', 'pyd', 'pyde', 'pyi', 'pyo', 'pyp', 'pyt', 'pyw', 'pywz', 'pyx', 'pyz', 'rpy', 'xpy'],
92
+  'Jupyter Notebook' => ['ipynb'],
93
+  'Ontology'         => ['cgif', 'cl', 'clif', 'csv', 'htm', 'html', 'kif', 'obo', 'owl', 'rdf', 'rdfa', 'rdfs', 'rif', 'tsv', 'xcl', 'xht', 'xhtml', 'xml'],
94
+  'OpenDocument'     => ['odt', 'fodt', 'ods', 'fods', 'odp', 'fodp', 'odg', 'fodg', 'odf'],
95
+  'Word'             => ['doc', 'dot', 'wbk', 'docx', 'docm', 'dotx', 'dotm', 'docb'],
96
+  'Excel'            => ['xls', 'xlt', 'xlm', 'xlsx', 'xlsm', 'xltx', 'xltm', 'xlsb', 'xla', 'xlam', 'xll', 'xlw'],
97
+  'PowerPoint'       => ['ppt', 'pot', 'pps', 'pptx', 'pptm', 'potx', 'potm', 'ppam', 'ppsx', 'ppsm', 'sldx', 'sldm'],
98
+  'PDF'              => ['pdf', 'fdf', 'xfdf'],
99
+  'Other'            => [''],
100
+];
101
+
76 102
 $Archives = [
77
-  '7z'     => ['7z'],
78
-  'bzip2'  => ['bz2', 'bzip2'],
79
-  'gzip'   => ['gz', 'gzip', 'tgz', 'tpz'],
80
-  'Pickle' => ['pickle', 'pkl'],
81
-  'RAR'    => ['rar', 'rev'],
82
-  'ZIP'    => ['zip', 'zipx'],
83
-  'None'   => [''],
103
+  '7z'       => ['7z'],
104
+  'bzip2'    => ['bz2', 'bzip2'],
105
+  'gzip'     => ['gz', 'gzip', 'tgz', 'tpz'],
106
+  'Pickle'   => ['pickle', 'pkl'],
107
+  'RAR'      => ['rar', 'rev'],
108
+  'ZIP'      => ['zip', 'zipx'],
109
+  'None'     => [''],
84 110
 ];
111
+# Line 330

+ 83
- 0
_packages/extension-parser/static/functions/upload.js View File

@@ -0,0 +1,83 @@
1
+// Line 11
2
+function Categories() {
3
+    let def = [
4
+        'javdb', // Accession Number
5
+        'audio', // Version
6
+        'title', // Torrent Title
7
+        'title_rj', // Organism
8
+        'title_jp', // Strain/Variety
9
+        'idols', // Authors(s)
10
+        'studio', // Department/Lab
11
+        'series', // Location
12
+        'year', // Year
13
+        'codec', // License
14
+        // Platform changes below
15
+        'resolution', // Assembly Level
16
+        // Format changes below
17
+        'archive', // Archive
18
+        'tags', // Tags
19
+        'cover', // Picture
20
+        'mirrors', // Mirrors
21
+        'screenshots', // Publications
22
+        'group_desc', // Torrent Group Description
23
+        'release_desc', // Torrent Description
24
+        'censored', // Aligned/Annotated
25
+        'anon', // Upload Anonymously
26
+    ]
27
+  
28
+    let cats = [
29
+        { // DNA
30
+            'media': {}, // Platform
31
+            'container': {}, // Format
32
+        },
33
+        { // RNA
34
+            'media': {}, // Platform
35
+            'container': {}, // Format
36
+        },
37
+        { // Proteins
38
+            'media': {}, // Platform
39
+            'container_prot': {}, // Format
40
+        },
41
+        { // Imaging
42
+            'media_manga': {}, // Platform
43
+            'container_games': {}, // Format
44
+        },
45
+        { // Extras
46
+            'media': {}, // Platform
47
+            'container_extra': {}, // Format
48
+        }
49
+    ]
50
+  
51
+    let active = {}
52
+    for (let field of def) active[field] = {}
53
+    let category = 0
54
+    if ($('input[name="type"]').raw()) category = $('input[name="type"]').raw().value
55
+    if ($('#categories').raw()) category = $('#categories').raw().value
56
+    active = Object.assign(active, cats[category])
57
+  
58
+    let hide = el => {
59
+        Array.from($(`#${el.id} input, #${el.id} select, #${el.id} textarea`)).forEach(inp => inp.disabled = true)
60
+        $(el).ghide()
61
+    }
62
+  
63
+    let show = el => {
64
+        Array.from($(`#${el.id} input, #${el.id} select, #${el.id} textarea`)).forEach(inp => inp.disabled = false)
65
+        $(el).gshow()
66
+    }
67
+  
68
+    let trs = $('#dynamic_form tr')
69
+    for (let tr of trs) {
70
+        let field = tr.id.slice(0, -3)
71
+        if (active[field]) {
72
+            if (active[field].name) {
73
+                tr.children[0].innerHTML = active[field].name
74
+            }
75
+            let notes = $(`#${tr.id} p.notes`).raw()
76
+            if (notes) notes.innerHTML = active[field].notes || ''
77
+            show(tr)
78
+        } else {
79
+            hide(tr)
80
+        }
81
+    }
82
+}
83
+// Line 91

+ 2
- 3
_packages/web-seeds/classes/bencodetorrent.class.php View File

@@ -2,8 +2,8 @@
2 2
 
3 3
 class BencodeTorrent extends BencodeDecode
4 4
 {
5
-    # ...
6
-
5
+    
6
+    # Line 172
7 7
     /**
8 8
      * Add list of web seeds to a torrent
9 9
      */
@@ -20,5 +20,4 @@ class BencodeTorrent extends BencodeDecode
20 20
         return $r.'e'.substr($Data, 1);
21 21
     }
22 22
 }
23
-
24 23
 # EOF

+ 13
- 0
_packages/web-seeds/classes/torrent_form.class.php View File

@@ -0,0 +1,13 @@
1
+<!-- Line 674 -->
2
+<!-- FTP/HTTP mirrors -->
3
+<?php if (!$this->DisabledFlag && $this->NewTorrent) { ?>
4
+  <tr id="mirrors_tr">
5
+    <td class="label">Mirrors</td>
6
+    <td>
7
+      <textarea rows="1" cols="60" name="mirrors"
8
+        id="mirrors"><?= display_str($Torrent['Mirrors'])?></textarea>
9
+      <strong class="important_text">Experimental.</strong>
10
+      Up to two FTP/HTTP addresses that either point directly to a file, or for multi-file torrents, to the enclosing folder
11
+  </tr>
12
+<?php } ?>
13
+<!-- Line 684 -->

+ 24
- 0
_packages/web-seeds/classes/torrentsdl.class.php View File

@@ -0,0 +1,24 @@
1
+<?php
2
+
3
+class TorrentsDL
4
+{
5
+    # Line 21
6
+    private $AnnounceList;
7
+    private $WebSeeds;
8
+    # Line 22
9
+
10
+    # Line 31
11
+    public function __construct(&$QueryResult, $Title)
12
+    {
13
+        G::$Cache->InternalCache = false; // The internal cache is almost completely useless for this
14
+        Zip::unlimit(); // Need more memory and longer timeout
15
+        $this->QueryResult = $QueryResult;
16
+        $this->Title = $Title;
17
+        $this->User = G::$LoggedUser;
18
+        $this->AnnounceURL = ANNOUNCE_URLS[0][0].'/'.G::$LoggedUser['torrent_pass'].'/announce';
19
+        $this->WebSeeds = $WebSeeds;
20
+        # Line 39
21
+    }
22
+}
23
+
24
+# cont.

+ 10
- 0
_packages/web-seeds/gazelle.sql View File

@@ -0,0 +1,10 @@
1
+-- Line 1239
2
+CREATE TABLE `torrents_mirrors` (
3
+  `ID` int(10) NOT NULL AUTO_INCREMENT,
4
+  `GroupID` int(10) NOT NULL,
5
+  `UserID` int(10) NOT NULL,
6
+  `Time` datetime,
7
+  `Resource` varchar(255) NOT NULL,
8
+  PRIMARY KEY (`ID`,`GroupID`,`Resource`)
9
+) ENGINE=InnoDB CHARSET=utf8mb4;
10
+-- Line 1246

+ 58
- 0
_packages/web-seeds/sections/torrents/details.php View File

@@ -0,0 +1,58 @@
1
+<?php
2
+
3
+# Line 22
4
+// Group details
5
+list($WikiBody, $WikiImage, $GroupID, $GroupName, $GroupNameRJ, $GroupNameJP, $GroupYear,
6
+  $GroupStudio, $GroupSeries, $GroupCatalogueNumber, $GroupPages, $GroupCategoryID,
7
+  $GroupDLsiteID, $GroupTime, $TorrentTags, $TorrentTagIDs, $TorrentTagUserIDs,
8
+  $Screenshots, $Mirrors, $GroupFlags) = array_values($TorrentDetails);
9
+# Line 26
10
+?>
11
+
12
+<!-- Line 967 -->
13
+<!-- Mirrors -->
14
+<div class="box torrent_mirrors_box <?php if (!count($Mirrors)) {
15
+    echo 'dead';
16
+} ?>">
17
+
18
+<div class="head"><a href="#">&uarr;</a>&nbsp;<strong>
19
+Mirrors (<?= count($Mirrors) ?>)</strong>
20
+<?php
21
+if (count($Mirrors) > 0) {
22
+    ?>
23
+<a class="float_right brackets" data-toggle-target=".torrent_mirrors" data-toggle-replace="Show">Hide</a>
24
+<?php
25
+}
26
+
27
+$DB->query("
28
+SELECT UserID
29
+FROM torrents
30
+WHERE GroupID = $GroupID");
31
+
32
+if (in_array($LoggedUser['ID'], $DB->collect('UserID'))
33
+ || check_perms('torrents_edit')
34
+ || check_perms('screenshots_add')
35
+ || check_perms('screenshots_delete')) {
36
+?>
37
+<a class="brackets"
38
+  href="torrents.php?action=editgroup&groupid=<?=$GroupID?>#mirrors_section">Add/Remove</a>
39
+<?php
40
+}
41
+?>
42
+  </div>
43
+
44
+  <div class="body torrent_mirrors">
45
+  <?php if (!empty($Mirrors)) {
46
+    echo '<p>Mirror links open in a new tab.</p>';
47
+  } ?>
48
+    <ul>
49
+      <?php
50
+        foreach ($Mirrors as $Mirror) {
51
+          echo '<li><a href="'.$Mirror['Resource'].'" target="_blank">'.$Mirror['Resource'].'</a></li>';
52
+        }
53
+      ?>
54
+    </ul>
55
+  </div>
56
+</div>
57
+<?php
58
+# Line 1005

+ 167
- 0
_packages/web-seeds/sections/torrents/functions.php View File

@@ -0,0 +1,167 @@
1
+<?php
2
+
3
+# Line 3
4
+function get_group_info($GroupID, $Return = true, $RevisionID = 0, $PersonalProperties = true, $ApiCall = false)
5
+{
6
+    global $Cache, $DB;
7
+    if (!$RevisionID) {
8
+        $TorrentCache = $Cache->get_value("torrents_details_$GroupID");
9
+    }
10
+    if ($RevisionID || !is_array($TorrentCache)) {
11
+        // Fetch the group details
12
+
13
+        $SQL = 'SELECT ';
14
+
15
+        if (!$RevisionID) {
16
+            $SQL .= '
17
+        g.WikiBody,
18
+        g.WikiImage, ';
19
+        } else {
20
+            $SQL .= '
21
+        w.Body,
22
+        w.Image, ';
23
+        }
24
+
25
+        $SQL .= "
26
+        g.ID,
27
+        g.Name,
28
+        g.NameRJ,
29
+        g.NameJP,
30
+        g.Year,
31
+        g.Studio,
32
+        g.Series,
33
+        g.CatalogueNumber,
34
+        g.Pages,
35
+        g.CategoryID,
36
+        g.DLsiteID,
37
+        g.Time,
38
+        GROUP_CONCAT(DISTINCT tags.Name SEPARATOR '|'),
39
+        GROUP_CONCAT(DISTINCT tags.ID SEPARATOR '|'),
40
+        GROUP_CONCAT(tt.UserID SEPARATOR '|')
41
+      FROM torrents_group AS g
42
+        LEFT JOIN torrents_tags AS tt ON tt.GroupID = g.ID
43
+        LEFT JOIN tags ON tags.ID = tt.TagID";
44
+
45
+        if ($RevisionID) {
46
+            $SQL .= "
47
+        LEFT JOIN wiki_torrents AS w ON w.PageID = '".db_string($GroupID)."'
48
+            AND w.RevisionID = '".db_string($RevisionID)."' ";
49
+        }
50
+
51
+        $SQL .= "
52
+      WHERE g.ID = '".db_string($GroupID)."'
53
+      GROUP BY NULL";
54
+
55
+        $DB->query($SQL);
56
+
57
+        $TorrentDetails = $DB->next_record(MYSQLI_ASSOC);
58
+        $TorrentDetails['Screenshots'] = [];
59
+        $TorrentDetails['Mirrors'] = [];
60
+
61
+        # Screenshots (Publications)
62
+        $DB->query("
63
+      SELECT
64
+        ID, UserID, Time, Image
65
+      FROM torrents_screenshots
66
+      WHERE GroupID = ".db_string($GroupID));
67
+
68
+        if ($DB->has_results()) {
69
+            while ($Screenshot = $DB->next_record(MYSQLI_ASSOC, true)) {
70
+                $TorrentDetails['Screenshots'][] = $Screenshot;
71
+            }
72
+        }
73
+
74
+        # Mirrors
75
+        $DB->query("
76
+        SELECT
77
+          ID, UserID, Time, Resource
78
+        FROM torrents_mirrors
79
+        WHERE GroupID = ".db_string($GroupID));
80
+  
81
+        if ($DB->has_results()) {
82
+            while ($Mirror = $DB->next_record(MYSQLI_ASSOC, true)) {
83
+                $TorrentDetails['Mirrors'][] = $Mirror;
84
+            }
85
+        }
86
+  
87
+        // Fetch the individual torrents
88
+        $DB->query("
89
+      SELECT
90
+        t.ID,
91
+        t.Media,
92
+        t.Container,
93
+        t.Codec,
94
+        t.Resolution,
95
+        t.AudioFormat,
96
+        t.Subbing,
97
+        t.Subber,
98
+        t.Language,
99
+        t.Censored,
100
+        t.Anonymous,
101
+        t.Archive,
102
+        t.FileCount,
103
+        t.Size,
104
+        t.Seeders,
105
+        t.Leechers,
106
+        t.Snatched,
107
+        t.FreeTorrent,
108
+        t.FreeLeechType,
109
+        t.Time,
110
+        t.Description,
111
+        t.MediaInfo,
112
+        t.FileList,
113
+        t.FilePath,
114
+        t.UserID,
115
+        t.last_action,
116
+        HEX(t.info_hash) AS InfoHash,
117
+        tbt.TorrentID AS BadTags,
118
+        tbf.TorrentID AS BadFolders,
119
+        tfi.TorrentID AS BadFiles,
120
+        t.LastReseedRequest,
121
+        tln.TorrentID AS LogInDB,
122
+        t.ID AS HasFile
123
+      FROM torrents AS t
124
+        LEFT JOIN torrents_bad_tags AS tbt ON tbt.TorrentID = t.ID
125
+        LEFT JOIN torrents_bad_folders AS tbf ON tbf.TorrentID = t.ID
126
+        LEFT JOIN torrents_bad_files AS tfi ON tfi.TorrentID = t.ID
127
+        LEFT JOIN torrents_logs_new AS tln ON tln.TorrentID = t.ID
128
+      WHERE t.GroupID = '".db_string($GroupID)."'
129
+      GROUP BY t.ID
130
+      ORDER BY
131
+        t.Media ASC,
132
+        t.ID");
133
+
134
+        $TorrentList = $DB->to_array('ID', MYSQLI_ASSOC);
135
+        if (count($TorrentList) === 0 && $ApiCall == false) {
136
+            header('Location: log.php?search='.(empty($_GET['torrentid']) ? "Group+$GroupID" : "Torrent+$_GET[torrentid]"));
137
+            die();
138
+        } elseif (count($TorrentList) === 0 && $ApiCall == true) {
139
+            return null;
140
+        }
141
+        if (in_array(0, $DB->collect('Seeders'))) {
142
+            $CacheTime = 600;
143
+        } else {
144
+            $CacheTime = 3600;
145
+        }
146
+        // Store it all in cache
147
+        if (!$RevisionID) {
148
+            $Cache->cache_value("torrents_details_$GroupID", array($TorrentDetails, $TorrentList), $CacheTime);
149
+        }
150
+    } else { // If we're reading from cache
151
+        $TorrentDetails = $TorrentCache[0];
152
+        $TorrentList = $TorrentCache[1];
153
+    }
154
+
155
+    if ($PersonalProperties) {
156
+        // Fetch all user specific torrent and group properties
157
+        $TorrentDetails['Flags'] = array('IsSnatched' => false, 'IsLeeching' => false, 'IsSeeding' => false);
158
+        foreach ($TorrentList as &$Torrent) {
159
+            Torrents::torrent_properties($Torrent, $TorrentDetails['Flags']);
160
+        }
161
+    }
162
+
163
+    if ($Return) {
164
+        return array($TorrentDetails, $TorrentList);
165
+    }
166
+}
167
+# Line 165

+ 107
- 0
_packages/web-seeds/sections/upload/upload_handle.php View File

@@ -0,0 +1,107 @@
1
+<?php
2
+
3
+# Line 88
4
+$Properties['Screenshots'] = isset($_POST['screenshots']) ? $_POST['screenshots'] : '';
5
+$Properties['Mirrors'] = isset($_POST['mirrors']) ? $_POST['mirrors'] : '';
6
+# Line 89
7
+
8
+# Line 512
9
+if (!isset($GroupID) || !$GroupID) {
10
+    // Create torrent group
11
+    $DB->query(
12
+        "
13
+    INSERT INTO torrents_group
14
+      (CategoryID, Name, NameRJ, NameJP, Year,
15
+      Series, Studio, CatalogueNumber, Pages, Time,
16
+      WikiBody, WikiImage, DLsiteID)
17
+    VALUES
18
+      ( ?, ?, ?, ?, ?,
19
+        ?, ?, ?, ?, NOW(),
20
+        ?, ?, ? )",
21
+        $TypeID,
22
+        $T['Title'],
23
+        $T['TitleRJ'],
24
+        $T['TitleJP'],
25
+        $T['Year'],
26
+        $T['Series'],
27
+        $T['Studio'],
28
+        $T['CatalogueNumber'],
29
+        $T['Pages'],
30
+        $Body,
31
+        $T['Image'],
32
+        $T['DLsiteID']
33
+    );
34
+    $GroupID = $DB->inserted_id();
35
+    foreach ($ArtistForm as $Num => $Artist) {
36
+        $DB->query("
37
+      INSERT IGNORE INTO torrents_artists (GroupID, ArtistID, UserID)
38
+      VALUES ( ?, ?, ? )", $GroupID, $Artist['id'], $LoggedUser['ID']);
39
+        $Cache->increment('stats_album_count');
40
+        $Cache->delete_value('artist_groups_'.$Artist['id']);
41
+    }
42
+    $Cache->increment('stats_group_count');
43
+
44
+    // Add screenshots
45
+    // todo: Clear DB_MYSQL::exec_prepared_query() errors
46
+    $Screenshots = explode("\n", $T['Screenshots']);
47
+    $Screenshots = array_map('trim', $Screenshots);
48
+
49
+    $Screenshots = array_filter($Screenshots, function ($s) {
50
+        return preg_match('/^'.DOI_REGEX.'$/i', $s);
51
+    });
52
+
53
+    $Screenshots = array_unique($Screenshots);
54
+    $Screenshots = array_slice($Screenshots, 0, 10);
55
+
56
+    # Add optional web seeds similar to screenshots
57
+    # Support an arbitrary and limited number of sources
58
+    $Mirrors = explode("\n", $T['Mirrors']);
59
+    $Mirrors = array_map('trim', $Mirrors);
60
+
61
+    $Mirrors = array_filter($Mirrors, function ($s) {
62
+        return preg_match('/^'.URL_REGEX.'$/i', $s);
63
+    });
64
+
65
+    $Mirrors = array_unique($Mirrors);
66
+    $Mirrors = array_slice($Mirrors, 0, 2);
67
+
68
+    # Downgrade TLS on resource URIs
69
+    # Required for BEP 19 compatibility
70
+    $Mirrors = str_ireplace('tps://', 'tp://', $Mirrors);
71
+
72
+    # Perform the DB inserts here
73
+    # Screenshots (publications)
74
+    if (!empty($Screenshots)) {
75
+        $Screenshot = '';
76
+        $DB->prepare_query("
77
+      INSERT INTO torrents_screenshots
78
+        (GroupID, UserID, Time, Image)
79
+      VALUES (?, ?, NOW(), ?)", $GroupID, $LoggedUser['ID'], $Screenshot);
80
+        foreach ($Screenshots as $Screenshot) {
81
+            $DB->exec_prepared_query();
82
+        }
83
+    }
84
+
85
+    # Mirrors
86
+    if (!empty($Mirrors)) {
87
+        $Mirror = '';
88
+        $DB->prepare_query("
89
+  INSERT INTO torrents_mirrors
90
+    (GroupID, UserID, Time, Resource)
91
+  VALUES (?, ?, NOW(), ?)", $GroupID, $LoggedUser['ID'], $Mirror);
92
+        foreach ($Mirrors as $Mirror) {
93
+            $DB->exec_prepared_query();
94
+        }
95
+    }
96
+
97
+# Main if/else
98
+} else {
99
+    $DB->query("
100
+    UPDATE torrents_group
101
+    SET Time = NOW()
102
+    WHERE ID = ?", $GroupID);
103
+    $Cache->delete_value("torrent_group_$GroupID");
104
+    $Cache->delete_value("torrents_details_$GroupID");
105
+    $Cache->delete_value("detail_files_$GroupID");
106
+}
107
+# Line 609

+ 99
- 50
classes/torrent_form.class.php View File

@@ -2,24 +2,24 @@
2 2
 
3 3
 // This class is used in upload.php to display the upload form, and the edit
4 4
 // section of torrents.php to display a shortened version of the same form
5
-
6 5
 class TorrentForm
7 6
 {
8 7
     public $UploadForm = '';
9 8
     public $Categories = [];
10
-    #var $Formats = [];
11
-    #var $Bitrates = [];
9
+    #public $Formats = [];
10
+    #public $Bitrates = [];
12 11
     public $Media = [];
13 12
     public $MediaManga = [];
14 13
     public $Containers = [];
15 14
     public $ContainersGames = [];
16 15
     public $ContainersProt = [];
16
+    public $ContainersExtra = [];
17 17
     public $Codecs = [];
18 18
     public $Resolutions = [];
19
-    public $AudioFormats = [];
20
-    #var $Subbing = [];
21
-    #var $Languages = [];
22
-    #var $Platform = [];
19
+    #public $AudioFormats = [];
20
+    #public $Subbing = [];
21
+    #public $Languages = [];
22
+    #public $Platform = [];
23 23
     public $NewTorrent = false;
24 24
     public $Torrent = [];
25 25
     public $Error = false;
@@ -33,7 +33,7 @@ class TorrentForm
33 33
         $this->Torrent = $Torrent;
34 34
         $this->Error = $Error;
35 35
 
36
-        global $UploadForm, $Categories, $Media,  $MediaManga, $TorrentID, $Containers, $ContainersGames, $ContainersProt, $Codecs, $Resolutions, $Archives;
36
+        global $UploadForm, $Categories, $Media,  $MediaManga, $TorrentID, $Containers, $ContainersGames, $ContainersProt, $ContainersExtra, $Codecs, $Resolutions, $Archives;
37 37
         #global $UploadForm, $Categories, $Formats, $Bitrates, $Media, $MediaManga, $TorrentID, $Containers, $ContainersGames, $Codecs, $Resolutions, $AudioFormats, $Subbing, $Languages, $Platform, $Archives, $ArchivesManga;
38 38
 
39 39
         $this->UploadForm = $UploadForm;
@@ -45,9 +45,10 @@ class TorrentForm
45 45
         $this->Containers = $Containers;
46 46
         $this->ContainersGames = $ContainersGames;
47 47
         $this->ContainersProt = $ContainersProt;
48
+        $this->ContainersExtra = $ContainersExtra;
48 49
         $this->Codecs = $Codecs;
49 50
         $this->Resolutions = $Resolutions;
50
-        $this->AudioFormats = $AudioFormats;
51
+        #$this->AudioFormats = $AudioFormats;
51 52
         #$this->Subbing = $Subbing;
52 53
         #$this->Languages = $Languages;
53 54
         $this->TorrentID = $TorrentID;
@@ -69,7 +70,10 @@ class TorrentForm
69 70
           WHERE UserID = ?", G::$LoggedUser['ID']);
70 71
         list($Uploads) = G::$DB->next_record(); ?>
71 72
 
72
-<!-- Everything until the catalogue number field-->
73
+<!--
74
+  Everything until the catalogue number field
75
+  Server-side torrent scrubbing admonishment
76
+-->
73 77
 <div class="thin">
74 78
   <?php if ($this->NewTorrent) { ?>
75 79
   <p style="text-align: center;">
@@ -80,6 +84,11 @@ class TorrentForm
80 84
       <a href="wiki.php?action=article&name=uploadingpitfalls">uploading pitfalls</a></strong>.
81 85
   </p>
82 86
 
87
+  <!--
88
+    Announce URLs displayed on the form
89
+    They're added to torrents in classes/torrentsdl.class.php
90
+    BioTorrents.de Gazelle supports tiered swarms, T1 private and T2 public
91
+  -->
83 92
   <p style="text-align: center;">
84 93
     <?php
85 94
       $Announces = ANNOUNCE_URLS[0];
@@ -95,6 +104,7 @@ class TorrentForm
95 104
       }
96 105
     ?>
97 106
 
107
+    <!-- Source -->
98 108
     <strong>Source</strong>
99 109
     <input type="text" value="<?= Users::get_upload_sources()[0] ?>"
100 110
       size="20" onclick="this.select();" readonly="readonly" />
@@ -185,6 +195,7 @@ class TorrentForm
185 195
       <?php
186 196
     }
187 197
 
198
+    # Make the endmatter
188 199
     public function foot()
189 200
     {
190 201
         $Torrent = $this->Torrent; ?>
@@ -258,17 +269,17 @@ class TorrentForm
258 269
   </form>
259 270
 </div>
260 271
 
261
-<!-- Okay, finally the real form -->
262 272
 <?php
263 273
     } # End
264 274
 
275
+    # Okay, finally the real form
265 276
     public function upload_form()
266 277
     {
267 278
         $QueryID = G::$DB->get_query_id();
268 279
         $this->head();
269 280
         $Torrent = $this->Torrent; ?>
270 281
 
271
-<!-- Catalogue number field -->
282
+<!-- Catalogue number autofill -->
272 283
 <table cellpadding="3" cellspacing="1" border="0" class="layout slice" width="100%">
273 284
   <?php if ($this->NewTorrent) { ?>
274 285
 
@@ -288,7 +299,7 @@ class TorrentForm
288 299
     </td>
289 300
   </tr>
290 301
 
291
-  <!-- Other autofill options -->
302
+  <!-- Autofill 2 -->
292 303
   <tr id="anidb_tr" class="hidden">
293 304
     <td class="label">AniDB Autofill (optional)</td>
294 305
     <td>
@@ -299,6 +310,7 @@ class TorrentForm
299 310
     </td>
300 311
   </tr>
301 312
 
313
+  <!-- Autofill 3 -->
302 314
   <tr id="ehentai_tr" class="hidden">
303 315
     <td class="label">e-hentai URL (optional)</td>
304 316
     <td>
@@ -334,6 +346,7 @@ class TorrentForm
334 346
     </td>
335 347
   </tr>
336 348
 
349
+  <!-- 2 -->
337 350
   <tr id="title_rj_tr">
338 351
     <td class="label" title="">Organism</td>
339 352
     <td>
@@ -344,6 +357,7 @@ class TorrentForm
344 357
     </td>
345 358
   </tr>
346 359
 
360
+  <!-- 3 -->
347 361
   <tr id="title_jp_tr">
348 362
     <td class="label">Strain/Variety</td>
349 363
     <td>
@@ -493,53 +507,37 @@ class TorrentForm
493 507
     </td>
494 508
   </tr>
495 509
 
496
-  <!-- Resolution -->
497
-  <tr id="resolution_tr">
510
+  <!-- Multiple container fields -->
511
+  <tr id="container_tr">
498 512
     <td class="label">
499
-      Assembly Level
513
+      Format
500 514
       <strong class="important_text">*</strong>
501 515
     </td>
502 516
     <td>
503
-      <select id="ressel" name="ressel" onchange="SetResolution()">
517
+      <select name="container">
504 518
         <option value="">---</option>
519
+        <option value="Autofill">Autofill</option>
505 520
         <?php
506
-          foreach ($this->Resolutions as $Res) {
507
-              echo "\t\t\t\t\t\t<option value=\"$Res\"";
508
-              if ($Res === ($Torrent['Resolution'] ?? false)
509
-              || (!isset($FoundRes) && ($Torrent['Resolution'] ?? false)
510
-              && $Res === 'Other')) {
511
-                  echo " selected";
512
-                  $FoundRes = true;
513
-              }
514
-              echo ">$Res</option>\n";
521
+          foreach ($this->Containers as $Name => $Container) {
522
+              echo "<option value='$Name'>$Name</option>\n";
515 523
           } ?>
516
-      </select>
517
-
518
-      <input type="text" id="resolution" name="resolution" size="10" class="hidden"
519
-        value="<?= ($Torrent['Resolution']??'') ?>"
520
-        readonly>
521
-      </input>
522
-      <script>
523
-        if ($('#ressel').raw().value == "Other") {
524
-          $('#resolution').raw().readOnly = false
525
-          $('#resolution').gshow()
526
-        }
527
-      </script><br />
528
-      How complete the data is, specifically or conceptually
524
+      </select><br />
525
+      Data file format, or detect from file list
529 526
     </td>
530 527
   </tr>
531 528
 
532
-  <!-- Three container fields -->
533
-  <tr id="container_tr">
529
+  <!-- 2 -->
530
+  <tr id="container_games_tr">
534 531
     <td class="label">
535 532
       Format
536 533
       <strong class="important_text">*</strong>
537 534
     </td>
538 535
     <td>
539
-      <select name="container">
536
+      <select id="container" name="container">
540 537
         <option value="">---</option>
538
+        <option value="Autofill">Autofill</option>
541 539
         <?php
542
-          foreach ($this->Containers as $Name => $Container) {
540
+          foreach ($this->ContainersGames as $Name => $Container) {
543 541
               echo "<option value='$Name'>$Name</option>\n";
544 542
           } ?>
545 543
       </select><br />
@@ -547,8 +545,8 @@ class TorrentForm
547 545
     </td>
548 546
   </tr>
549 547
 
550
-  <!-- 2 -->
551
-  <tr id="container_games_tr">
548
+  <!-- 3 -->
549
+  <tr id="container_prot_tr">
552 550
     <td class="label">
553 551
       Format
554 552
       <strong class="important_text">*</strong>
@@ -556,8 +554,9 @@ class TorrentForm
556 554
     <td>
557 555
       <select id="container" name="container">
558 556
         <option value="">---</option>
557
+        <option value="Autofill">Autofill</option>
559 558
         <?php
560
-          foreach ($this->ContainersGames as $Name => $Container) {
559
+          foreach ($this->ContainersProt as $Name => $Container) {
561 560
               echo "<option value='$Name'>$Name</option>\n";
562 561
           } ?>
563 562
       </select><br />
@@ -565,8 +564,8 @@ class TorrentForm
565 564
     </td>
566 565
   </tr>
567 566
 
568
-  <!-- 3 -->
569
-  <tr id="container_prot_tr">
567
+    <!-- 4 -->
568
+    <tr id="container_extra_tr">
570 569
     <td class="label">
571 570
       Format
572 571
       <strong class="important_text">*</strong>
@@ -574,8 +573,9 @@ class TorrentForm
574 573
     <td>
575 574
       <select id="container" name="container">
576 575
         <option value="">---</option>
576
+        <option value="Autofill">Autofill</option>
577 577
         <?php
578
-          foreach ($this->ContainersProt as $Name => $Container) {
578
+          foreach ($this->ContainersExtra as $Name => $Container) {
579 579
               echo "<option value='$Name'>$Name</option>\n";
580 580
           } ?>
581 581
       </select><br />
@@ -592,6 +592,7 @@ class TorrentForm
592 592
     <td>
593 593
       <select name='archive'>
594 594
         <option value="">---</option>
595
+        <option value="Autofill">Autofill</option>
595 596
         <?php
596 597
           foreach ($this->Archives as $Name => $Archive) {
597 598
               echo "\t\t\t\t\t\t<option value=\"$Name\"";
@@ -605,6 +606,42 @@ class TorrentForm
605 606
     </td>
606 607
   </tr>
607 608
 
609
+    <!-- Resolution -->
610
+    <tr id="resolution_tr">
611
+    <td class="label">
612
+      Assembly Level
613
+      <strong class="important_text">*</strong>
614
+    </td>
615
+    <td>
616
+      <select id="ressel" name="ressel" onchange="SetResolution()">
617
+        <option value="">---</option>
618
+        <?php
619
+          foreach ($this->Resolutions as $Res) {
620
+              echo "\t\t\t\t\t\t<option value=\"$Res\"";
621
+              if ($Res === ($Torrent['Resolution'] ?? false)
622
+              || (!isset($FoundRes) && ($Torrent['Resolution'] ?? false)
623
+              && $Res === 'Other')) {
624
+                  echo " selected";
625
+                  $FoundRes = true;
626
+              }
627
+              echo ">$Res</option>\n";
628
+          } ?>
629
+      </select>
630
+
631
+      <input type="text" id="resolution" name="resolution" size="10" class="hidden"
632
+        value="<?= ($Torrent['Resolution']??'') ?>"
633
+        readonly>
634
+      </input>
635
+      <script>
636
+        if ($('#ressel').raw().value === 'Other') {
637
+          $('#resolution').raw().readOnly = false
638
+          $('#resolution').gshow()
639
+        }
640
+      </script><br />
641
+      How complete the data is, specifically or conceptually
642
+    </td>
643
+  </tr>
644
+
608 645
   <!-- Tags -->
609 646
   <?php if ($this->NewTorrent) { ?>
610 647
   <tr id="tags_tr">
@@ -651,6 +688,18 @@ class TorrentForm
651 688
     </td>
652 689
   </tr>
653 690
 
691
+  <!-- FTP/HTTP mirrors -->
692
+  <?php if (!$this->DisabledFlag && $this->NewTorrent) { ?>
693
+  <tr id="mirrors_tr">
694
+    <td class="label">Mirrors</td>
695
+    <td>
696
+      <textarea rows="1" cols="60" name="mirrors"
697
+        id="mirrors"><?= display_str($Torrent['Mirrors'])?></textarea>
698
+        <strong class="important_text">Experimental.</strong>
699
+      Up to two FTP/HTTP addresses that either point directly to a file, or for multi-file torrents, to the enclosing folder
700
+  </tr>
701
+  <?php } ?>
702
+  
654 703
   <!-- Sample pictures/links -->
655 704
   <?php if (!$this->DisabledFlag && $this->NewTorrent) { ?>
656 705
   <tr id="screenshots_tr">
@@ -685,7 +734,7 @@ class TorrentForm
685 734
       General info about the torrent subject's function or significance
686 735
     </td>
687 736
   </tr>
688
-  <?php } # Ends if NewTorrent line 499?>
737
+  <?php } # Ends if NewTorrent line 646?>
689 738
 
690 739
   <!-- Torrent description -->
691 740
   <tr id="release_desc_tr">

+ 875
- 846
classes/torrents.class.php
File diff suppressed because it is too large
View File


+ 11
- 3
classes/torrentsdl.class.php View File

@@ -1,4 +1,5 @@
1 1
 <?php
2
+
2 3
 /**
3 4
  * Class for functions related to the features involving torrent downloads
4 5
  */
@@ -18,6 +19,7 @@ class TorrentsDL
18 19
     private $User;
19 20
     private $AnnounceURL;
20 21
     private $AnnounceList;
22
+    private $WebSeeds;
21 23
 
22 24
     /**
23 25
      * Create a Zip object and store the query results
@@ -42,6 +44,7 @@ class TorrentsDL
42 44
 
43 45
         $this->AnnounceList = (sizeof(ANNOUNCE_URLS) === 1 && sizeof(ANNOUNCE_URLS[0]) === 1) ? [] : array(array_map('add_passkey', ANNOUNCE_URLS[0]), ANNOUNCE_URLS[1]);
44 46
         #$this->AnnounceList = (sizeof(ANNOUNCE_URLS) === 1 && sizeof(ANNOUNCE_URLS[0]) === 1) ? [] : array_map('add_passkey', ANNOUNCE_URLS);
47
+        $this->WebSeeds = [];
45 48
         $this->Zip = new Zip(Misc::file_string($Title));
46 49
     }
47 50
 
@@ -242,23 +245,28 @@ class TorrentsDL
242 245
     {
243 246
         if (Misc::is_new_torrent($TorrentData)) {
244 247
             $Bencode = BencodeTorrent::add_announce_url($TorrentData, $AnnounceURL);
248
+
249
+            # Announce list
245 250
             if (!empty($AnnounceList)) {
246 251
                 $Bencode = BencodeTorrent::add_announce_list($Bencode, $AnnounceList);
247 252
             }
248
-            /* todo: Support web seeds
253
+
254
+            # Web seeds
249 255
             if (!empty($WebSeeds)) {
250 256
                 $Bencode = BencodeTorrent::add_web_seeds($Bencode, $WebSeeds);
251 257
             }
252
-            */
253 258
             return $Bencode;
254 259
         }
260
+
255 261
         $Tor = new TORRENT(unserialize(base64_decode($TorrentData)), true);
256 262
         $Tor->set_announce_url($AnnounceURL);
257 263
         unset($Tor->Val['announce-list']);
264
+
258 265
         if (!empty($AnnounceList)) {
259 266
             $Tor->set_announce_list($AnnounceList);
260 267
         }
261
-        unset($Tor->Val['url-list']);
268
+
269
+        #unset($Tor->Val['url-list']);
262 270
         unset($Tor->Val['libtorrent_resume']);
263 271
         return $Tor->enc();
264 272
     }

+ 9
- 0
gazelle.sql View File

@@ -1236,6 +1236,15 @@ CREATE TABLE `torrents_screenshots` (
1236 1236
   PRIMARY KEY (`ID`,`GroupID`,`Image`)
1237 1237
 ) ENGINE=InnoDB CHARSET=utf8mb4;
1238 1238
 
1239
+CREATE TABLE `torrents_mirrors` (
1240
+  `ID` int(10) NOT NULL AUTO_INCREMENT,
1241
+  `GroupID` int(10) NOT NULL,
1242
+  `UserID` int(10) NOT NULL,
1243
+  `Time` datetime,
1244
+  `Resource` varchar(255) NOT NULL,
1245
+  PRIMARY KEY (`ID`,`GroupID`,`Resource`)
1246
+) ENGINE=InnoDB CHARSET=utf8mb4;
1247
+
1239 1248
 CREATE TABLE `torrents_tags` (
1240 1249
   `TagID` int(10) NOT NULL DEFAULT '0',
1241 1250
   `GroupID` int(10) NOT NULL DEFAULT '0',

+ 24
- 24
sections/ajax/torrentgroup.php View File

@@ -6,38 +6,38 @@ $GroupID = (int)$_GET['id'];
6 6
 $TorrentHash = (string)$_GET['hash'];
7 7
 
8 8
 if ($GroupID && $TorrentHash) {
9
-  json_die("failure", "bad parameters");
9
+    json_die("failure", "bad parameters");
10 10
 }
11 11
 
12 12
 if ($TorrentHash) {
13
-  if (!is_valid_torrenthash($TorrentHash)) {
14
-    json_die("failure", "bad hash parameter");
15
-  } else {
16
-    $GroupID = (int)torrenthash_to_groupid($TorrentHash);
17
-    if (!$GroupID) {
18
-      json_die("failure", "bad hash parameter");
13
+    if (!is_valid_torrenthash($TorrentHash)) {
14
+        json_die("failure", "bad hash parameter");
15
+    } else {
16
+        $GroupID = (int)torrenthash_to_groupid($TorrentHash);
17
+        if (!$GroupID) {
18
+            json_die("failure", "bad hash parameter");
19
+        }
19 20
     }
20
-  }
21 21
 }
22 22
 
23 23
 if ($GroupID <= 0) {
24
-  json_die("failure", "bad id parameter");
24
+    json_die("failure", "bad id parameter");
25 25
 }
26 26
 
27 27
 $TorrentCache = get_group_info($GroupID, true, 0, true, true);
28 28
 
29 29
 if (!$TorrentCache) {
30
-  json_die("failure", "bad id parameter");
30
+    json_die("failure", "bad id parameter");
31 31
 }
32 32
 
33 33
 list($TorrentDetails, $TorrentList) = $TorrentCache;
34 34
 
35 35
 $Artists = pullmediainfo(Artists::get_artist($GroupID));
36 36
 
37
-if ($TorrentDetails['CategoryID'] == 0) {
38
-  $CategoryName = 'Unknown';
37
+if ($TorrentDetails['CategoryID'] === 0) {
38
+    $CategoryName = 'Unknown';
39 39
 } else {
40
-  $CategoryName = $Categories[$TorrentDetails['CategoryID'] - 1];
40
+    $CategoryName = $Categories[$TorrentDetails['CategoryID'] - 1];
41 41
 }
42 42
 
43 43
 $TagList = explode('|', $TorrentDetails['GROUP_CONCAT(DISTINCT tags.Name SEPARATOR \'|\')']);
@@ -62,17 +62,17 @@ $JsonTorrentDetails = [
62 62
 
63 63
 $JsonTorrentList = [];
64 64
 foreach ($TorrentList as $Torrent) {
65
-  // Convert file list back to the old format
66
-  $FileList = explode("\n", $Torrent['FileList']);
67
-  foreach ($FileList as &$File) {
68
-    $File = Torrents::filelist_old_format($File);
69
-  }
70
-  unset($File);
71
-  $FileList = implode('|||', $FileList);
72
-  $Userinfo = Users::user_info($Torrent['UserID']);
73
-  $Reports = Torrents::get_reports($Torrent['ID']);
74
-  $Torrent['Reported'] = count($Reports) > 0;
75
-  $JsonTorrentList[] = [
65
+    // Convert file list back to the old format
66
+    $FileList = explode("\n", $Torrent['FileList']);
67
+    foreach ($FileList as &$File) {
68
+        $File = Torrents::filelist_old_format($File);
69
+    }
70
+    unset($File);
71
+    $FileList = implode('|||', $FileList);
72
+    $Userinfo = Users::user_info($Torrent['UserID']);
73
+    $Reports = Torrents::get_reports($Torrent['ID']);
74
+    $Torrent['Reported'] = count($Reports) > 0;
75
+    $JsonTorrentList[] = [
76 76
     'id'          => (int)$Torrent['ID'],
77 77
     'infoHash'    => $Torrent['InfoHash'],
78 78
     'media'       => $Torrent['Media'],

+ 2
- 1
sections/ajax/torrentgroupalbumart.php View File

@@ -1,9 +1,10 @@
1 1
 <?php
2
+
2 3
 require(SERVER_ROOT.'/sections/torrents/functions.php');
3 4
 
4 5
 $GroupID = (int)$_GET['id'];
5 6
 if ($GroupID === 0) {
6
-  error('Bad ID parameter', true);
7
+    error('Bad ID parameter', true);
7 8
 }
8 9
 
9 10
 $TorrentDetails = get_group_info($GroupID, true, 0, false);

+ 18
- 18
sections/artist/notify.php View File

@@ -1,11 +1,12 @@
1
-<?
1
+<?php
2
+
2 3
 authorize();
3 4
 if (!check_perms('site_torrents_notify')) {
4
-  error(403);
5
+    error(403);
5 6
 }
6 7
 $ArtistID = $_GET['artistid'];
7 8
 if (!is_number($ArtistID)) {
8
-  error(0);
9
+    error(0);
9 10
 }
10 11
 /*
11 12
 $DB->query("
@@ -20,11 +21,11 @@ $DB->query("
20 21
   SELECT Name
21 22
   FROM artists_group
22 23
   WHERE ArtistID = '$ArtistID'");
23
-list($ArtistAliases) = $DB->next_record(MYSQLI_NUM, FALSE);
24
+list($ArtistAliases) = $DB->next_record(MYSQLI_NUM, false);
24 25
 
25 26
 $Notify = $Cache->get_value('notify_artists_'.$LoggedUser['ID']);
26 27
 if (empty($Notify)) {
27
-  $DB->query("
28
+    $DB->query("
28 29
     SELECT ID, Artists
29 30
     FROM users_notify_filters
30 31
     WHERE Label = 'Artist notifications'
@@ -32,31 +33,30 @@ if (empty($Notify)) {
32 33
     ORDER BY ID
33 34
     LIMIT 1");
34 35
 } else {
35
-  $DB->query("
36
+    $DB->query("
36 37
     SELECT ID, Artists
37 38
     FROM users_notify_filters
38 39
     WHERE ID = '$Notify[ID]'");
39 40
 }
40 41
 if (empty($Notify) && !$DB->has_results()) {
41
-  $DB->query("
42
+    $DB->query("
42 43
     INSERT INTO users_notify_filters
43 44
       (UserID, Label, Artists)
44 45
     VALUES
45 46
       ('$LoggedUser[ID]', 'Artist notifications', '|".db_string($ArtistAliases)."|')");
46
-  $FilterID = $DB->inserted_id();
47
-  $Cache->delete_value('notify_filters_'.$LoggedUser['ID']);
48
-  $Cache->delete_value('notify_artists_'.$LoggedUser['ID']);
47
+    $FilterID = $DB->inserted_id();
48
+    $Cache->delete_value('notify_filters_'.$LoggedUser['ID']);
49
+    $Cache->delete_value('notify_artists_'.$LoggedUser['ID']);
49 50
 } else {
50
-  list($ID, $ArtistNames) = $DB->next_record(MYSQLI_NUM, FALSE);
51
-  if (stripos($ArtistNames, "|$ArtistAliases|") === false) {
52
-    $ArtistNames .= "$ArtistAliases|";
53
-    $DB->query("
51
+    list($ID, $ArtistNames) = $DB->next_record(MYSQLI_NUM, false);
52
+    if (stripos($ArtistNames, "|$ArtistAliases|") === false) {
53
+        $ArtistNames .= "$ArtistAliases|";
54
+        $DB->query("
54 55
       UPDATE users_notify_filters
55 56
       SET Artists = '".db_string($ArtistNames)."'
56 57
       WHERE ID = '$ID'");
57
-    $Cache->delete_value('notify_filters_'.$LoggedUser['ID']);
58
-    $Cache->delete_value('notify_artists_'.$LoggedUser['ID']);
59
-  }
58
+        $Cache->delete_value('notify_filters_'.$LoggedUser['ID']);
59
+        $Cache->delete_value('notify_artists_'.$LoggedUser['ID']);
60
+    }
60 61
 }
61 62
 header('Location: '.$_SERVER['HTTP_REFERER']);
62
-?>

+ 46
- 1
sections/torrents/details.php View File

@@ -23,7 +23,7 @@ $TorrentList = $TorrentCache[1];
23 23
 list($WikiBody, $WikiImage, $GroupID, $GroupName, $GroupNameRJ, $GroupNameJP, $GroupYear,
24 24
   $GroupStudio, $GroupSeries, $GroupCatalogueNumber, $GroupPages, $GroupCategoryID,
25 25
   $GroupDLsiteID, $GroupTime, $TorrentTags, $TorrentTagIDs, $TorrentTagUserIDs,
26
-  $Screenshots, $GroupFlags) = array_values($TorrentDetails);
26
+  $Screenshots, $Mirrors, $GroupFlags) = array_values($TorrentDetails);
27 27
 
28 28
 if (!$GroupName) {
29 29
     if (!$GroupNameRJ) {
@@ -951,6 +951,8 @@ if (count($PersonalCollages) > 0) {
951 951
     <?php
952 952
 }
953 953
 ?>
954
+
955
+    <!-- Torrent group description -->
954 956
     <div class="box torrent_description">
955 957
       <div class="head"><a href="#">&uarr;</a>&nbsp;<strong><?=(!empty($ReleaseType) ? $ReleaseTypes[$ReleaseType].' info' : 'Info')?></strong>
956 958
       </div>
@@ -961,6 +963,48 @@ if (count($PersonalCollages) > 0) {
961 963
 } ?>
962 964
       </div>
963 965
     </div>
966
+
967
+        <!-- Mirrors -->
968
+        <div class="box torrent_mirrors_box <?php if (!count($Mirrors)) {
969
+    echo 'dead';
970
+} ?>">
971
+      <div class="head"><a href="#">&uarr;</a>&nbsp;<strong>
972
+      Mirrors (<?= count($Mirrors) ?>)</strong>
973
+        <?php
974
+    if (count($Mirrors) > 0) {
975
+        ?>
976
+        <a class="float_right brackets" data-toggle-target=".torrent_mirrors" data-toggle-replace="Show">Hide</a>
977
+        <?php
978
+    }
979
+
980
+    $DB->query("
981
+      SELECT UserID
982
+      FROM torrents
983
+      WHERE GroupID = $GroupID");
984
+
985
+    if (in_array($LoggedUser['ID'], $DB->collect('UserID')) || check_perms('torrents_edit') || check_perms('screenshots_add') || check_perms('screenshots_delete')) {
986
+        ?>
987
+        <a class="brackets"
988
+          href="torrents.php?action=editgroup&groupid=<?=$GroupID?>#mirrors_section">Add/Remove</a>
989
+        <?php
990
+    }
991
+?>
992
+      </div>
993
+      <div class="body torrent_mirrors">
994
+        <?php if (!empty($Mirrors)) {
995
+    echo '<p>Mirror links open in a new tab.</p>';
996
+} ?>
997
+        <ul>
998
+          <?php
999
+    foreach ($Mirrors as $Mirror) {
1000
+        echo '<li><a href="'.$Mirror['Resource'].'" target="_blank">'.$Mirror['Resource'].'</a></li>';
1001
+    }
1002
+?>
1003
+        </ul>
1004
+      </div>
1005
+    </div>
1006
+
1007
+    <!-- Screenshots (Publications) -->
964 1008
     <div class="box torrent_screenshots_box <?php if (!count($Screenshots)) {
965 1009
     echo 'dead';
966 1010
 } ?>">
@@ -1018,6 +1062,7 @@ if (count($PersonalCollages) > 0) {
1018 1062
         } catch (e) {}
1019 1063
       </script>
1020 1064
     </div>
1065
+
1021 1066
     <?php
1022 1067
 // --- Comments ---
1023 1068
 $Pages = Format::get_pages($Page, $NumComments, TORRENT_COMMENTS_PER_PAGE, 9, '#comments');

+ 33
- 24
sections/torrents/download.php View File

@@ -1,4 +1,5 @@
1 1
 <?php
2
+
2 3
 if (!isset($_REQUEST['authkey']) || !isset($_REQUEST['torrent_pass'])) {
3 4
     enforce_login();
4 5
     $TorrentPass = $LoggedUser['torrent_pass'];
@@ -12,40 +13,41 @@ if (!isset($_REQUEST['authkey']) || !isset($_REQUEST['torrent_pass'])) {
12 13
     $UserInfo = $Cache->get_value('user_'.$_REQUEST['torrent_pass']);
13 14
     if (!is_array($UserInfo)) {
14 15
         $DB->query("
15
-      SELECT ID, la.UserID
16
-      FROM users_main AS m
16
+        SELECT ID, la.UserID
17
+          FROM users_main AS m
17 18
         INNER JOIN users_info AS i ON i.UserID = m.ID
18 19
         LEFT JOIN locked_accounts AS la ON la.UserID = m.ID
19
-      WHERE m.torrent_pass = '".db_string($_REQUEST['torrent_pass'])."'
20
-        AND m.Enabled = '1'");
20
+          WHERE m.torrent_pass = '".db_string($_REQUEST['torrent_pass'])."'
21
+          AND m.Enabled = '1'");
21 22
         $UserInfo = $DB->next_record();
22 23
         $Cache->cache_value('user_'.$_REQUEST['torrent_pass'], $UserInfo, 3600);
23 24
     }
25
+
24 26
     $UserInfo = array($UserInfo);
25 27
     list($UserID, $Locked) = array_shift($UserInfo);
26 28
     if (!$UserID) {
27 29
         error(0);
28 30
     }
31
+
29 32
     $TorrentPass = $_REQUEST['torrent_pass'];
30 33
     $AuthKey = $_REQUEST['authkey'];
31 34
 
32
-    if ($Locked == $UserID) {
35
+    if ($Locked === $UserID) {
33 36
         header('HTTP/1.1 403 Forbidden');
34 37
         die();
35 38
     }
36 39
 }
37 40
 
38 41
 $TorrentID = $_REQUEST['id'];
39
-
40
-
41
-
42 42
 if (!is_number($TorrentID)) {
43 43
     error(0);
44 44
 }
45 45
 
46
-/* uTorrent Remote and various scripts redownload .torrent files periodically.
47
-  To prevent this retardation from blowing bandwidth etc., let's block it
48
-  if the .torrent file has been downloaded four times before */
46
+/*
47
+ * uTorrent Remote and various scripts redownload .torrent files periodically.
48
+ * To prevent this retardation from blowing bandwidth etc., let's block it
49
+ * if the .torrent file has been downloaded four times before
50
+*/
49 51
 $ScriptUAs = array('BTWebClient*', 'Python-urllib*', 'python-requests*');
50 52
 if (Misc::in_array_partial($_SERVER['HTTP_USER_AGENT'], $ScriptUAs)) {
51 53
     $DB->query("
@@ -54,6 +56,7 @@ if (Misc::in_array_partial($_SERVER['HTTP_USER_AGENT'], $ScriptUAs)) {
54 56
     WHERE UserID = $UserID
55 57
       AND TorrentID = $TorrentID
56 58
     LIMIT 4");
59
+
57 60
     if ($DB->record_count() === 4) {
58 61
         error('You have already downloaded this torrent file four times. If you need to download it again, please do so from your browser.', true);
59 62
         die();
@@ -72,29 +75,36 @@ if (!is_array($Info) || !array_key_exists('PlainArtists', $Info) || empty($Info[
72 75
       COALESCE(NULLIF(tg.Name,''), NULLIF(tg.NameRJ,''), tg.NameJP) AS Name,
73 76
       tg.WikiImage,
74 77
       tg.CategoryID,
78
+      tm.Resource,
75 79
       t.Size,
76 80
       t.FreeTorrent,
77 81
       HEX(t.info_hash)
78 82
     FROM torrents AS t
79 83
       INNER JOIN torrents_group AS tg ON tg.ID = t.GroupID
84
+      LEFT JOIN torrents_mirrors AS tm ON tm.ID = t.GroupID
80 85
     WHERE t.ID = '".db_string($TorrentID)."'");
86
+
81 87
     if (!$DB->has_results()) {
82 88
         error(404);
83 89
     }
90
+
84 91
     $Info = array($DB->next_record(MYSQLI_NUM, array(4, 5, 6, 10)));
85 92
     $Artists = Artists::get_artist($Info[0][4], false);
86 93
     $Info['Artists'] = Artists::display_artists($Artists, false, true);
87 94
     $Info['PlainArtists'] = Artists::display_artists($Artists, false, true, false);
88 95
     $Cache->cache_value("torrent_download_$TorrentID", $Info, 0);
89 96
 }
97
+
90 98
 if (!is_array($Info[0])) {
91 99
     error(404);
92 100
 }
93
-list($Media, $Format, $Encoding, $Year, $GroupID, $Name, $Image, $CategoryID, $Size, $FreeTorrent, $InfoHash) = array_shift($Info); // used for generating the filename
101
+
102
+list($Media, $Format, $Encoding, $Year, $GroupID, $Name, $Image, $CategoryID, $Resources, $Size, $FreeTorrent, $InfoHash) = array_shift($Info); // Used for generating the filename
94 103
 $Artists = $Info['Artists'];
95 104
 
96 105
 // If he's trying use a token on this, we need to make sure he has one,
97 106
 // deduct it, add this to the FLs table, and update his cache key.
107
+// todo: Make sure strict equality works
98 108
 if ($_REQUEST['usetoken'] && $FreeTorrent == '0') {
99 109
     if (isset($LoggedUser)) {
100 110
         $FLTokens = $LoggedUser['FLTokens'];
@@ -110,7 +120,6 @@ if ($_REQUEST['usetoken'] && $FreeTorrent == '0') {
110 120
     }
111 121
 
112 122
     // First make sure this isn't already FL, and if it is, do nothing
113
-
114 123
     if (!Torrents::has_token($TorrentID)) {
115 124
         if ($FLTokens <= 0) {
116 125
             error('You do not have any freeleech tokens left. Please use the regular DL link.');
@@ -126,16 +135,16 @@ if ($_REQUEST['usetoken'] && $FreeTorrent == '0') {
126 135
 
127 136
         if (!Torrents::has_token($TorrentID)) {
128 137
             $DB->query("
129
-        INSERT INTO users_freeleeches (UserID, TorrentID, Time)
130
-        VALUES ($UserID, $TorrentID, NOW())
131
-        ON DUPLICATE KEY UPDATE
132
-          Time = VALUES(Time),
133
-          Expired = FALSE,
134
-          Uses = Uses + 1");
138
+            INSERT INTO users_freeleeches (UserID, TorrentID, Time)
139
+            VALUES ($UserID, $TorrentID, NOW())
140
+            ON DUPLICATE KEY UPDATE
141
+              Time = VALUES(Time),
142
+              Expired = FALSE,
143
+              Uses = Uses + 1");
135 144
             $DB->query("
136
-        UPDATE users_main
137
-        SET FLTokens = FLTokens - 1
138
-        WHERE ID = $UserID");
145
+            UPDATE users_main
146
+            SET FLTokens = FLTokens - 1
147
+            WHERE ID = $UserID");
139 148
 
140 149
             // Fix for downloadthemall messing with the cached token count
141 150
             $UInfo = Users::user_heavy_info($UserID);
@@ -150,7 +159,7 @@ if ($_REQUEST['usetoken'] && $FreeTorrent == '0') {
150 159
     }
151 160
 }
152 161
 
153
-//Stupid Recent Snatches On User Page
162
+// Stupid Recent Snatches on User Page
154 163
 if ($Image != '') {
155 164
     $RecentSnatches = $Cache->get_value("recent_snatches_$UserID");
156 165
     if (!empty($RecentSnatches)) {
@@ -192,6 +201,6 @@ $UserAnnounceURL = ANNOUNCE_URLS[0][0].'/'.$TorrentPass.'/announce';
192 201
 $UserAnnounceList = (sizeof(ANNOUNCE_URLS) === 1 && sizeof(ANNOUNCE_URLS[0]) === 1) ? [] : array(array_map('add_passkey', ANNOUNCE_URLS[0]), ANNOUNCE_URLS[1]);
193 202
 #$UserAnnounceList = (sizeof(ANNOUNCE_URLS) === 1 && sizeof(ANNOUNCE_URLS[0]) === 1) ? [] : array_map('add_passkey', ANNOUNCE_URLS);
194 203
 
195
-echo TorrentsDL::get_file($Contents, $UserAnnounceURL, $UserAnnounceList);
204
+echo TorrentsDL::get_file($Contents, $UserAnnounceURL, $UserAnnounceList, $Resources);
196 205
 
197 206
 define('SKIP_NO_CACHE_HEADERS', 1);

+ 298
- 274
sections/torrents/functions.php View File

@@ -1,25 +1,26 @@
1
-<?
2
-function get_group_info($GroupID, $Return = true, $RevisionID = 0, $PersonalProperties = true, $ApiCall = false) {
3
-  global $Cache, $DB;
4
-  if (!$RevisionID) {
5
-    $TorrentCache = $Cache->get_value("torrents_details_$GroupID");
6
-  }
7
-  if ($RevisionID || !is_array($TorrentCache)) {
8
-    // Fetch the group details
9
-
10
-    $SQL = 'SELECT ';
1
+<?php
11 2
 
3
+function get_group_info($GroupID, $Return = true, $RevisionID = 0, $PersonalProperties = true, $ApiCall = false)
4
+{
5
+    global $Cache, $DB;
12 6
     if (!$RevisionID) {
13
-      $SQL .= '
7
+        $TorrentCache = $Cache->get_value("torrents_details_$GroupID");
8
+    }
9
+    if ($RevisionID || !is_array($TorrentCache)) {
10
+        // Fetch the group details
11
+        $SQL = 'SELECT ';
12
+
13
+        if (!$RevisionID) {
14
+            $SQL .= '
14 15
         g.WikiBody,
15 16
         g.WikiImage, ';
16
-    } else {
17
-      $SQL .= '
17
+        } else {
18
+            $SQL .= '
18 19
         w.Body,
19 20
         w.Image, ';
20
-    }
21
+        }
21 22
 
22
-    $SQL .= "
23
+        $SQL .= "
23 24
         g.ID,
24 25
         g.Name,
25 26
         g.NameRJ,
@@ -39,35 +40,50 @@ function get_group_info($GroupID, $Return = true, $RevisionID = 0, $PersonalProp
39 40
         LEFT JOIN torrents_tags AS tt ON tt.GroupID = g.ID
40 41
         LEFT JOIN tags ON tags.ID = tt.TagID";
41 42
 
42
-    if ($RevisionID) {
43
-      $SQL .= "
43
+        if ($RevisionID) {
44
+            $SQL .= "
44 45
         LEFT JOIN wiki_torrents AS w ON w.PageID = '".db_string($GroupID)."'
45 46
             AND w.RevisionID = '".db_string($RevisionID)."' ";
46
-    }
47
+        }
47 48
 
48
-    $SQL .= "
49
+        $SQL .= "
49 50
       WHERE g.ID = '".db_string($GroupID)."'
50 51
       GROUP BY NULL";
51 52
 
52
-    $DB->query($SQL);
53
-
54
-    $TorrentDetails = $DB->next_record(MYSQLI_ASSOC);
55
-    $TorrentDetails['Screenshots'] = [];
56
-
57
-    $DB->query("
58
-      SELECT
59
-        ID, UserID, Time, Image
60
-      FROM torrents_screenshots
61
-      WHERE GroupID = ".db_string($GroupID));
62
-
63
-    if ($DB->has_results()) {
64
-      while ($Screenshot = $DB->next_record(MYSQLI_ASSOC, true)) {
65
-        $TorrentDetails['Screenshots'][] = $Screenshot;
66
-      }
67
-    }
68
-
69
-    // Fetch the individual torrents
70
-    $DB->query("
53
+        $DB->query($SQL);
54
+
55
+        $TorrentDetails = $DB->next_record(MYSQLI_ASSOC);
56
+        $TorrentDetails['Screenshots'] = [];
57
+        $TorrentDetails['Mirrors'] = [];
58
+
59
+        # Screenshots (Publications)
60
+        $DB->query("
61
+        SELECT
62
+          ID, UserID, Time, Image
63
+        FROM torrents_screenshots
64
+        WHERE GroupID = ".db_string($GroupID));
65
+
66
+        if ($DB->has_results()) {
67
+            while ($Screenshot = $DB->next_record(MYSQLI_ASSOC, true)) {
68
+                $TorrentDetails['Screenshots'][] = $Screenshot;
69
+            }
70
+        }
71
+
72
+        # Mirrors
73
+        $DB->query("
74
+        SELECT
75
+          ID, UserID, Time, Resource
76
+        FROM torrents_mirrors
77
+        WHERE GroupID = ".db_string($GroupID));
78
+  
79
+        if ($DB->has_results()) {
80
+            while ($Mirror = $DB->next_record(MYSQLI_ASSOC, true)) {
81
+                $TorrentDetails['Mirrors'][] = $Mirror;
82
+            }
83
+        }
84
+  
85
+        // Fetch the individual torrents
86
+        $DB->query("
71 87
       SELECT
72 88
         t.ID,
73 89
         t.Media,
@@ -113,115 +129,121 @@ function get_group_info($GroupID, $Return = true, $RevisionID = 0, $PersonalProp
113 129
         t.Media ASC,
114 130
         t.ID");
115 131
 
116
-    $TorrentList = $DB->to_array('ID', MYSQLI_ASSOC);
117
-    if (count($TorrentList) === 0 && $ApiCall == false) {
118
-      header('Location: log.php?search='.(empty($_GET['torrentid']) ? "Group+$GroupID" : "Torrent+$_GET[torrentid]"));
119
-      die();
120
-    } elseif (count($TorrentList) === 0 && $ApiCall == true) {
121
-      return null;
122
-    }
123
-    if (in_array(0, $DB->collect('Seeders'))) {
124
-      $CacheTime = 600;
125
-    } else {
126
-      $CacheTime = 3600;
132
+        $TorrentList = $DB->to_array('ID', MYSQLI_ASSOC);
133
+        if (count($TorrentList) === 0 && $ApiCall == false) {
134
+            header('Location: log.php?search='.(empty($_GET['torrentid']) ? "Group+$GroupID" : "Torrent+$_GET[torrentid]"));
135
+            die();
136
+        } elseif (count($TorrentList) === 0 && $ApiCall == true) {
137
+            return null;
138
+        }
139
+        if (in_array(0, $DB->collect('Seeders'))) {
140
+            $CacheTime = 600;
141
+        } else {
142
+            $CacheTime = 3600;
143
+        }
144
+        // Store it all in cache
145
+        if (!$RevisionID) {
146
+            $Cache->cache_value("torrents_details_$GroupID", array($TorrentDetails, $TorrentList), $CacheTime);
147
+        }
148
+    } else { // If we're reading from cache
149
+        $TorrentDetails = $TorrentCache[0];
150
+        $TorrentList = $TorrentCache[1];
127 151
     }
128
-    // Store it all in cache
129
-    if (!$RevisionID) {
130
-      $Cache->cache_value("torrents_details_$GroupID", array($TorrentDetails, $TorrentList), $CacheTime);
131
-    }
132
-  } else { // If we're reading from cache
133
-    $TorrentDetails = $TorrentCache[0];
134
-    $TorrentList = $TorrentCache[1];
135
-  }
136 152
 
137
-  if ($PersonalProperties) {
138
-    // Fetch all user specific torrent and group properties
139
-    $TorrentDetails['Flags'] = array('IsSnatched' => false, 'IsLeeching' => false, 'IsSeeding' => false);
140
-    foreach ($TorrentList as &$Torrent) {
141
-      Torrents::torrent_properties($Torrent, $TorrentDetails['Flags']);
153
+    if ($PersonalProperties) {
154
+        // Fetch all user specific torrent and group properties
155
+        $TorrentDetails['Flags'] = array('IsSnatched' => false, 'IsLeeching' => false, 'IsSeeding' => false);
156
+        foreach ($TorrentList as &$Torrent) {
157
+            Torrents::torrent_properties($Torrent, $TorrentDetails['Flags']);
158
+        }
142 159
     }
143
-  }
144
-
145
-  if ($Return) {
146
-    return array($TorrentDetails, $TorrentList);
147
-  }
148
-}
149 160
 
150
-function get_torrent_info($TorrentID, $Return = true, $RevisionID = 0, $PersonalProperties = true, $ApiCall = false) {
151
-  global $Cache, $DB;
152
-  $GroupID = (int)torrentid_to_groupid($TorrentID);
153
-  $GroupInfo = get_group_info($GroupID, $Return, $RevisionID, $PersonalProperties, $ApiCall);
154
-  if ($GroupInfo) {
155
-    foreach ($GroupInfo[1] as &$Torrent) {
156
-      //Remove unneeded entries
157
-      if ($Torrent['ID'] != $TorrentID) {
158
-        unset($GroupInfo[1][$Torrent['ID']]);
159
-      }
160
-      if ($Return) {
161
-        return $GroupInfo;
162
-      }
163
-    }
164
-  } else {
165 161
     if ($Return) {
166
-      return null;
162
+        return array($TorrentDetails, $TorrentList);
167 163
     }
168
-  }
169 164
 }
170 165
 
171
-//Check if a givin string can be validated as a torrenthash
172
-function is_valid_torrenthash($Str) {
173
-  //6C19FF4C 6C1DD265 3B25832C 0F6228B2 52D743D5
174
-  $Str = str_replace(' ', '', $Str);
175
-  if (preg_match('/^[0-9a-fA-F]{40}$/', $Str))
176
-    return $Str;
177
-  return false;
166
+function get_torrent_info($TorrentID, $Return = true, $RevisionID = 0, $PersonalProperties = true, $ApiCall = false)
167
+{
168
+    global $Cache, $DB;
169
+    $GroupID = (int)torrentid_to_groupid($TorrentID);
170
+    $GroupInfo = get_group_info($GroupID, $Return, $RevisionID, $PersonalProperties, $ApiCall);
171
+    if ($GroupInfo) {
172
+        foreach ($GroupInfo[1] as &$Torrent) {
173
+            // Remove unneeded entries
174
+            if ($Torrent['ID'] != $TorrentID) {
175
+                unset($GroupInfo[1][$Torrent['ID']]);
176
+            }
177
+            if ($Return) {
178
+                return $GroupInfo;
179
+            }
180
+        }
181
+    } else {
182
+        if ($Return) {
183
+            return null;
184
+        }
185
+    }
178 186
 }
179 187
 
180
-//Functionality for the API to resolve input into other data.
188
+// Check if a givin string can be validated as a torrenthash
189
+function is_valid_torrenthash($Str)
190
+{
191
+    // 6C19FF4C 6C1DD265 3B25832C 0F6228B2 52D743D5
192
+    $Str = str_replace(' ', '', $Str);
193
+    if (preg_match('/^[0-9a-fA-F]{40}$/', $Str)) {
194
+        return $Str;
195
+    }
196
+    return false;
197
+}
181 198
 
182
-function torrenthash_to_torrentid($Str) {
183
-  global $Cache, $DB;
184
-  $DB->query("
199
+// Functionality for the API to resolve input into other data
200
+function torrenthash_to_torrentid($Str)
201
+{
202
+    global $Cache, $DB;
203
+    $DB->query("
185 204
     SELECT ID
186 205
     FROM torrents
187 206
     WHERE HEX(info_hash) = '".db_string($Str)."'");
188
-  $TorrentID = (int)array_pop($DB->next_record(MYSQLI_ASSOC));
189
-  if ($TorrentID) {
190
-    return $TorrentID;
191
-  }
192
-  return null;
207
+    $TorrentID = (int)array_pop($DB->next_record(MYSQLI_ASSOC));
208
+    if ($TorrentID) {
209
+        return $TorrentID;
210
+    }
211
+    return null;
193 212
 }
194 213
 
195
-function torrenthash_to_groupid($Str) {
196
-  global $Cache, $DB;
197
-  $DB->query("
214
+function torrenthash_to_groupid($Str)
215
+{
216
+    global $Cache, $DB;
217
+    $DB->query("
198 218
     SELECT GroupID
199 219
     FROM torrents
200 220
     WHERE HEX(info_hash) = '".db_string($Str)."'");
201
-  $GroupID = (int)array_pop($DB->next_record(MYSQLI_ASSOC));
202
-  if ($GroupID) {
203
-    return $GroupID;
204
-  }
205
-  return null;
221
+    $GroupID = (int)array_pop($DB->next_record(MYSQLI_ASSOC));
222
+    if ($GroupID) {
223
+        return $GroupID;
224
+    }
225
+    return null;
206 226
 }
207 227
 
208
-function torrentid_to_groupid($TorrentID) {
209
-  global $Cache, $DB;
210
-  $DB->query("
228
+function torrentid_to_groupid($TorrentID)
229
+{
230
+    global $Cache, $DB;
231
+    $DB->query("
211 232
     SELECT GroupID
212 233
     FROM torrents
213 234
     WHERE ID = '".db_string($TorrentID)."'");
214
-  $GroupID = (int)array_pop($DB->next_record(MYSQLI_ASSOC));
215
-  if ($GroupID) {
216
-    return $GroupID;
217
-  }
218
-  return null;
235
+    $GroupID = (int)array_pop($DB->next_record(MYSQLI_ASSOC));
236
+    if ($GroupID) {
237
+        return $GroupID;
238
+    }
239
+    return null;
219 240
 }
220 241
 
221
-//After adjusting / deleting logs, recalculate the score for the torrent.
222
-function set_torrent_logscore($TorrentID) {
223
-  global $DB;
224
-  $DB->query("
242
+// After adjusting / deleting logs, recalculate the score for the torrent
243
+function set_torrent_logscore($TorrentID)
244
+{
245
+    global $DB;
246
+    $DB->query("
225 247
     UPDATE torrents
226 248
     SET LogScore = (
227 249
         SELECT FLOOR(AVG(Score))
@@ -231,84 +253,86 @@ function set_torrent_logscore($TorrentID) {
231 253
     WHERE ID = $TorrentID");
232 254
 }
233 255
 
234
-function get_group_requests($GroupID) {
235
-  if (empty($GroupID) || !is_number($GroupID)) {
236
-    return [];
237
-  }
238
-  global $DB, $Cache;
256
+function get_group_requests($GroupID)
257
+{
258
+    if (empty($GroupID) || !is_number($GroupID)) {
259
+        return [];
260
+    }
261
+    global $DB, $Cache;
239 262
 
240
-  $Requests = $Cache->get_value("requests_group_$GroupID");
241
-  if ($Requests === false) {
242
-    $DB->query("
263
+    $Requests = $Cache->get_value("requests_group_$GroupID");
264
+    if ($Requests === false) {
265
+        $DB->query("
243 266
       SELECT ID
244 267
       FROM requests
245 268
       WHERE GroupID = $GroupID
246 269
         AND TimeFilled IS NULL");
247
-    $Requests = $DB->collect('ID');
248
-    $Cache->cache_value("requests_group_$GroupID", $Requests, 0);
249
-  }
250
-  return Requests::get_requests($Requests);
270
+        $Requests = $DB->collect('ID');
271
+        $Cache->cache_value("requests_group_$GroupID", $Requests, 0);
272
+    }
273
+    return Requests::get_requests($Requests);
251 274
 }
252 275
 
253
-//Used by both sections/torrents/details.php and sections/reportsv2/report.php
254
-function build_torrents_table($Cache, $DB, $LoggedUser, $GroupID, $GroupName, $GroupCategoryID, $TorrentList, $Types, $Username) {
255
-
256
-  function filelist($Str) {
257
-    return "</td>\n<td>" . Format::get_size($Str[1]) . "</td>\n</tr>";
258
-  }
259
-  $EditionID = 0;
260
-  foreach ($TorrentList as $Torrent) {
261
-  list($TorrentID, $Media, $Container, $Codec, $Resolution, $AudioFormat, $Subbing,
276
+// Used by both sections/torrents/details.php and sections/reportsv2/report.php
277
+function build_torrents_table($Cache, $DB, $LoggedUser, $GroupID, $GroupName, $GroupCategoryID, $TorrentList, $Types, $Username)
278
+{
279
+    function filelist($Str)
280
+    {
281
+        return "</td>\n<td>" . Format::get_size($Str[1]) . "</td>\n</tr>";
282
+    }
283
+    $EditionID = 0;
284
+    foreach ($TorrentList as $Torrent) {
285
+        list($TorrentID, $Media, $Container, $Codec, $Resolution, $AudioFormat, $Subbing,
262 286
   $Subber, $Language, $Censored, $Anonymous, $Archive, $FileCount, $Size, $Seeders, $Leechers, $Snatched,
263 287
   $FreeTorrent, $FreeLeechType, $TorrentTime, $Description, $MediaInfo, $FileList, $FilePath, $UserID,
264 288
   $LastActive, $InfoHash, $BadTags, $BadFolders, $BadFiles, $LastReseedRequest,
265 289
   $LogInDB, $HasFile, $PersonalFL, $IsSnatched, $IsSeeding, $IsLeeching) = array_values($Torrent);
266 290
 
267
-  $Reported = false;
268
-  $Reports = Torrents::get_reports($TorrentID);
269
-  $NumReports = count($Reports);
291
+        $Reported = false;
292
+        $Reports = Torrents::get_reports($TorrentID);
293
+        $NumReports = count($Reports);
270 294
 
271
-  if ($NumReports > 0) {
272
-    $Reported = true;
273
-    include(SERVER_ROOT.'/sections/reportsv2/array.php');
274
-    $ReportInfo = '
295
+        if ($NumReports > 0) {
296
+            $Reported = true;
297
+            include(SERVER_ROOT.'/sections/reportsv2/array.php');
298
+            $ReportInfo = '
275 299
     <table class="reportinfo_table">
276 300
       <tr class="colhead_dark" style="font-weight: bold;">
277 301
         <td>This torrent has '.$NumReports.' active '.($NumReports === 1 ? 'report' : 'reports').":</td>
278 302
       </tr>";
279 303
 
280
-    foreach ($Reports as $Report) {
281
-      if (check_perms('admin_reports')) {
282
-        $ReporterID = $Report['ReporterID'];
283
-        $Reporter = Users::user_info($ReporterID);
284
-        $ReporterName = $Reporter['Username'];
285
-        $ReportLinks = "<a href=\"user.php?id=$ReporterID\">$ReporterName</a> <a href=\"reportsv2.php?view=report&amp;id=$Report[ID]\">reported it</a>";
286
-      } else {
287
-        $ReportLinks = 'Someone reported it';
288
-      }
289
-
290
-      if (isset($Types[$GroupCategoryID][$Report['Type']])) {
291
-        $ReportType = $Types[$GroupCategoryID][$Report['Type']];
292
-      } elseif (isset($Types['master'][$Report['Type']])) {
293
-        $ReportType = $Types['master'][$Report['Type']];
294
-      } else {
295
-        //There was a type but it wasn't an option!
296
-        $ReportType = $Types['master']['other'];
297
-      }
298
-      $ReportInfo .= "
304
+            foreach ($Reports as $Report) {
305
+                if (check_perms('admin_reports')) {
306
+                    $ReporterID = $Report['ReporterID'];
307
+                    $Reporter = Users::user_info($ReporterID);
308
+                    $ReporterName = $Reporter['Username'];
309
+                    $ReportLinks = "<a href=\"user.php?id=$ReporterID\">$ReporterName</a> <a href=\"reportsv2.php?view=report&amp;id=$Report[ID]\">reported it</a>";
310
+                } else {
311
+                    $ReportLinks = 'Someone reported it';
312
+                }
313
+
314
+                if (isset($Types[$GroupCategoryID][$Report['Type']])) {
315
+                    $ReportType = $Types[$GroupCategoryID][$Report['Type']];
316
+                } elseif (isset($Types['master'][$Report['Type']])) {
317
+                    $ReportType = $Types['master'][$Report['Type']];
318
+                } else {
319
+                    // There was a type but it wasn't an option!
320
+                    $ReportType = $Types['master']['other'];
321
+                }
322
+                $ReportInfo .= "
299 323
       <tr>
300 324
         <td>$ReportLinks ".time_diff($Report['ReportedTime'], 2, true, true).' for the reason "'.$ReportType['title'].'":
301 325
           <blockquote>'.Text::full_format($Report['UserComment']).'</blockquote>
302 326
         </td>
303 327
       </tr>';
304
-    }
305
-    $ReportInfo .= "\n\t\t</table>";
306
-  }
328
+            }
329
+            $ReportInfo .= "\n\t\t</table>";
330
+        }
307 331
 
308
-  $CanEdit = (check_perms('torrents_edit') || (($UserID == $LoggedUser['ID'] && !$LoggedUser['DisableWiki'])));
332
+        $CanEdit = (check_perms('torrents_edit') || (($UserID == $LoggedUser['ID'] && !$LoggedUser['DisableWiki'])));
309 333
 
310
-  $RegenLink = check_perms('users_mod') ? ' <a href="torrents.php?action=regen_filelist&amp;torrentid=' . $TorrentID . '" class="brackets">Regenerate</a>' : '';
311
-  $FileTable = '
334
+        $RegenLink = check_perms('users_mod') ? ' <a href="torrents.php?action=regen_filelist&amp;torrentid=' . $TorrentID . '" class="brackets">Regenerate</a>' : '';
335
+        $FileTable = '
312 336
   <table class="filelist_table">
313 337
     <tr class="colhead_dark">
314 338
       <td>
@@ -319,88 +343,88 @@ function build_torrents_table($Cache, $DB, $LoggedUser, $GroupID, $GroupName, $G
319 343
         <strong>Size</strong>
320 344
       </td>
321 345
     </tr>';
322
-  if (substr($FileList, -3) == '}}}') { // Old style
323
-    $FileListSplit = explode('|||', $FileList);
324
-    foreach ($FileListSplit as $File) {
325
-    $NameEnd = strrpos($File, '{{{');
326
-    $Name = substr($File, 0, $NameEnd);
327
-    if ($Spaces = strspn($Name, ' ')) {
328
-      $Name = str_replace(' ', '&nbsp;', substr($Name, 0, $Spaces)) . substr($Name, $Spaces);
329
-    }
330
-    $FileSize = substr($File, $NameEnd + 3, -3);
331
-    $FileTable .= sprintf("\n<tr class=\"row\"><td>%s</td><td class=\"number_column\">%s</td></tr>", $Name, Format::get_size($FileSize));
332
-    }
333
-  } else {
334
-    $FileListSplit = explode("\n", $FileList);
335
-    foreach ($FileListSplit as $File) {
336
-    $FileInfo = Torrents::filelist_get_file($File);
337
-    $FileTable .= sprintf("\n<tr class=\"row\"><td>%s</td><td class=\"number_column\">%s</td></tr>", $FileInfo['name'], Format::get_size($FileInfo['size']));
338
-    }
339
-  }
340
-  $FileTable .= '
346
+        if (substr($FileList, -3) == '}}}') { // Old style
347
+            $FileListSplit = explode('|||', $FileList);
348
+            foreach ($FileListSplit as $File) {
349
+                $NameEnd = strrpos($File, '{{{');
350
+                $Name = substr($File, 0, $NameEnd);
351
+                if ($Spaces = strspn($Name, ' ')) {
352
+                    $Name = str_replace(' ', '&nbsp;', substr($Name, 0, $Spaces)) . substr($Name, $Spaces);
353
+                }
354
+                $FileSize = substr($File, $NameEnd + 3, -3);
355
+                $FileTable .= sprintf("\n<tr class=\"row\"><td>%s</td><td class=\"number_column\">%s</td></tr>", $Name, Format::get_size($FileSize));
356
+            }
357
+        } else {
358
+            $FileListSplit = explode("\n", $FileList);
359
+            foreach ($FileListSplit as $File) {
360
+                $FileInfo = Torrents::filelist_get_file($File);
361
+                $FileTable .= sprintf("\n<tr class=\"row\"><td>%s</td><td class=\"number_column\">%s</td></tr>", $FileInfo['name'], Format::get_size($FileInfo['size']));
362
+            }
363
+        }
364
+        $FileTable .= '
341 365
   </table>';
342 366
 
343
-  $ExtraInfo = ''; // String that contains information on the torrent (e.g. format and encoding)
367
+        $ExtraInfo = ''; // String that contains information on the torrent (e.g. format and encoding)
344 368
   $AddExtra = ''; // Separator between torrent properties
345 369
 
346 370
   $TorrentUploader = $Username; // Save this for "Uploaded by:" below
347
-  // similar to Torrents::torrent_info()
348
-  if (!$ExtraInfo) {
349
-    $ExtraInfo = $GroupName;
350
-    $AddExtra = ' / ';
351
-  }
352
-  if ($IsLeeching) {
353
-    $ExtraInfo .= $AddExtra . Format::torrent_label('Leeching');
354
-    $AddExtra = ' / ';
355
-  } else if ($IsSeeding) {
356
-    $ExtraInfo .= $AddExtra . Format::torrent_label('Seeding');
357
-    $AddExtra = ' / ';
358
-  } else if ($IsSnatched) {
359
-    $ExtraInfo .= $AddExtra . Format::torrent_label('Snatched!');
360
-    $AddExtra = ' / ';
361
-  }
362
-  if ($FreeTorrent == '1') {
363
-    $ExtraInfo .= $AddExtra . Format::torrent_label('Freeleech!');
364
-    $AddExtra = ' / ';
365
-  }
366
-  if ($FreeTorrent == '2') {
367
-    $ExtraInfo .= $AddExtra . Format::torrent_label('Neutral Leech!');
368
-    $AddExtra = ' / ';
369
-  }
370
-  if ($PersonalFL) {
371
-    $ExtraInfo .= $AddExtra . Format::torrent_label('Personal Freeleech!');
372
-    $AddExtra = ' / ';
373
-  }
374
-  if ($Reported) {
375
-    $ExtraInfo .= $AddExtra . Format::torrent_label('Reported');
376
-    $AddExtra = ' / ';
377
-  }
378
-  if (!empty($BadTags)) {
379
-    $ExtraInfo .= $AddExtra . Format::torrent_label('Bad Tags');
380
-    $AddExtra = ' / ';
381
-  }
382
-  if (!empty($BadFolders)) {
383
-    $ExtraInfo .= $AddExtra . Format::torrent_label('Bad Folders');
384
-    $AddExtra = ' / ';
385
-  }
386
-  if (!empty($BadFiles)) {
387
-    $ExtraInfo .= $AddExtra . Format::torrent_label('Bad File Names');
388
-    $AddExtra = ' / ';
389
-  }
390
-    ?>
371
+        // Similar to Torrents::torrent_info()
372
+        if (!$ExtraInfo) {
373
+            $ExtraInfo = $GroupName;
374
+            $AddExtra = ' / ';
375
+        }
376
+        if ($IsLeeching) {
377
+            $ExtraInfo .= $AddExtra . Format::torrent_label('Leeching');
378
+            $AddExtra = ' / ';
379
+        } elseif ($IsSeeding) {
380
+            $ExtraInfo .= $AddExtra . Format::torrent_label('Seeding');
381
+            $AddExtra = ' / ';
382
+        } elseif ($IsSnatched) {
383
+            $ExtraInfo .= $AddExtra . Format::torrent_label('Snatched!');
384
+            $AddExtra = ' / ';
385
+        }
386
+        # todo: Check strict equality
387
+        if ($FreeTorrent == '1') {
388
+            $ExtraInfo .= $AddExtra . Format::torrent_label('Freeleech!');
389
+            $AddExtra = ' / ';
390
+        }
391
+        if ($FreeTorrent == '2') {
392
+            $ExtraInfo .= $AddExtra . Format::torrent_label('Neutral Leech!');
393
+            $AddExtra = ' / ';
394
+        }
395
+        if ($PersonalFL) {
396
+            $ExtraInfo .= $AddExtra . Format::torrent_label('Personal Freeleech!');
397
+            $AddExtra = ' / ';
398
+        }
399
+        if ($Reported) {
400
+            $ExtraInfo .= $AddExtra . Format::torrent_label('Reported');
401
+            $AddExtra = ' / ';
402
+        }
403
+        if (!empty($BadTags)) {
404
+            $ExtraInfo .= $AddExtra . Format::torrent_label('Bad Tags');
405
+            $AddExtra = ' / ';
406
+        }
407
+        if (!empty($BadFolders)) {
408
+            $ExtraInfo .= $AddExtra . Format::torrent_label('Bad Folders');
409
+            $AddExtra = ' / ';
410
+        }
411
+        if (!empty($BadFiles)) {
412
+            $ExtraInfo .= $AddExtra . Format::torrent_label('Bad File Names');
413
+            $AddExtra = ' / ';
414
+        } ?>
391 415
         <tr class="torrent_row<?=(isset($ReleaseType)?' releases_'.$ReleaseType:'')?> groupid_<?=($GroupID)?> edition_<?=($EditionID)?> group_torrent<?=($IsSnatched ? ' snatched_torrent' : '')?>" style="font-weight: normal;" id="torrent<?=($TorrentID)?>">
392 416
           <td>
393 417
             <span>[ <a href="torrents.php?action=download&amp;id=<?=($TorrentID)?>&amp;authkey=<?=($LoggedUser['AuthKey'])?>&amp;torrent_pass=<?=($LoggedUser['torrent_pass'])?>" class="tooltip" title="Download"><?=($HasFile ? 'DL' : 'Missing')?></a>
394
-<?  if (Torrents::can_use_token($Torrent)) { ?>
418
+<?php  if (Torrents::can_use_token($Torrent)) { ?>
395 419
               | <a href="torrents.php?action=download&amp;id=<?=($TorrentID)?>&amp;authkey=<?=($LoggedUser['AuthKey'])?>&amp;torrent_pass=<?=($LoggedUser['torrent_pass'])?>&amp;usetoken=1" class="tooltip" title="Use a FL Token" onclick="return confirm('Are you sure you want to use a freeleech token here?');">FL</a>
396
-<?  } ?>
420
+<?php  } ?>
397 421
               | <a href="reportsv2.php?action=report&amp;id=<?=($TorrentID)?>" class="tooltip" title="Report">RP</a>
398
-<?  if ($CanEdit) { ?>
422
+<?php  if ($CanEdit) { ?>
399 423
               | <a href="torrents.php?action=edit&amp;id=<?=($TorrentID)?>" class="tooltip" title="Edit">ED</a>
400
-<?  }
401
-  if (check_perms('torrents_delete') || $UserID == $LoggedUser['ID']) { ?>
424
+<?php  }
425
+        if (check_perms('torrents_delete') || $UserID == $LoggedUser['ID']) { ?>
402 426
               | <a href="torrents.php?action=delete&amp;torrentid=<?=($TorrentID)?>" class="tooltip" title="Remove">RM</a>
403
-<?  } ?>
427
+<?php  } ?>
404 428
               | <a href="torrents.php?torrentid=<?=($TorrentID)?>" class="tooltip" title="Permalink">PL</a>
405 429
             ]</span>
406 430
             &raquo; <a data-toggle-target="#torrent_<?=($TorrentID)?>"><?=($ExtraInfo)?></a>
@@ -410,61 +434,61 @@ function build_torrents_table($Cache, $DB, $LoggedUser, $GroupID, $GroupName, $G
410 434
           <td class="number_column"><?=(number_format($Seeders))?></td>
411 435
           <td class="number_column"><?=(number_format($Leechers))?></td>
412 436
         </tr>
413
-        <tr class="<?=(isset($ReleaseType)?'releases_'.$ReleaseType:'')?> groupid_<?=($GroupID)?> edition_<?=($EditionID)?> torrentdetails pad<? if (!isset($_GET['torrentid']) || $_GET['torrentid'] != $TorrentID) { ?> hidden<? } ?>" id="torrent_<?=($TorrentID)?>">
437
+        <tr class="<?=(isset($ReleaseType)?'releases_'.$ReleaseType:'')?> groupid_<?=($GroupID)?> edition_<?=($EditionID)?> torrentdetails pad<?php if (!isset($_GET['torrentid']) || $_GET['torrentid'] != $TorrentID) { ?> hidden<?php } ?>" id="torrent_<?=($TorrentID)?>">
414 438
           <td colspan="5">
415 439
             <blockquote>
416
-              Uploaded by <?
440
+              Uploaded by <?php
417 441
   if ($Anonymous) {
418
-    if (check_perms('users_mod')) { ?>
442
+      if (check_perms('users_mod')) { ?>
419 443
       <em class="tooltip" title="<?=Users::user_info($UserID)['Username']?>">Anonymous</em>
420
-<?  } else {
421
-      ?><em>Anonymous</em><?
422
-    }
444
+<?php  } else {
445
+          ?><em>Anonymous</em><?php
446
+      }
423 447
   } else {
424
-    print (Users::format_username($UserID, false, false, false));
425
-  }
426
-?> <?=time_diff($TorrentTime);?>
427
-<?  if ($Seeders == 0) {
428
-    if ($LastActive && time() - strtotime($LastActive) >= 1209600) { ?>
448
+      print(Users::format_username($UserID, false, false, false));
449
+  } ?> <?=time_diff($TorrentTime); ?>
450
+<?php  if ($Seeders === 0) {
451
+      if ($LastActive && time() - strtotime($LastActive) >= 1209600) { ?>
429 452
                 <br /><strong>Last active: <?=time_diff($LastActive);?></strong>
430
-<?    } else { ?>
453
+<?php    } else { ?>
431 454
                 <br />Last active: <?=time_diff($LastActive);?>
432
-<?    }
433
-    if ($LastActive && time() - strtotime($LastActive) >= 345678 && time() - strtotime($LastReseedRequest) >= 864000) { ?>
455
+<?php    }
456
+      if ($LastActive && time() - strtotime($LastActive) >= 345678 && time() - strtotime($LastReseedRequest) >= 864000) { ?>
434 457
                 <br /><a href="torrents.php?action=reseed&amp;torrentid=<?=($TorrentID)?>&amp;groupid=<?=($GroupID)?>" class="brackets">Request re-seed</a>
435
-<?    }
458
+<?php    }
436 459
   } ?>
437 460
             </blockquote>
438
-<?  if (check_perms('site_moderate_requests')) { ?>
461
+<?php  if (check_perms('site_moderate_requests')) { ?>
439 462
             <div class="linkbox">
440 463
               <a href="torrents.php?action=masspm&amp;id=<?=($GroupID)?>&amp;torrentid=<?=($TorrentID)?>" class="brackets">Mass PM snatchers</a>
441 464
             </div>
442
-<?  } ?>
465
+<?php  } ?>
443 466
             <div class="linkbox">
444 467
               <a href="#" class="brackets" onclick="show_peers('<?=($TorrentID)?>', 0); return false;">View peer list</a>
445
-<?  if (check_perms('site_view_torrent_snatchlist')) { ?>
468
+<?php  if (check_perms('site_view_torrent_snatchlist')) { ?>
446 469
               <a href="#" class="brackets tooltip" onclick="show_downloads('<?=($TorrentID)?>', 0); return false;" title="View the list of users that have clicked the &quot;DL&quot; button.">View download list</a>
447 470
               <a href="#" class="brackets tooltip" onclick="show_snatches('<?=($TorrentID)?>', 0); return false;" title="View the list of users that have reported a snatch to the tracker.">View snatch list</a>
448
-<?  } ?>
471
+<?php  } ?>
449 472
               <a href="#" class="brackets" onclick="show_files('<?=($TorrentID)?>'); return false;">View file list</a>
450
-<?  if ($Reported) { ?>
473
+<?php  if ($Reported) { ?>
451 474
               <a href="#" class="brackets" onclick="show_reported('<?=($TorrentID)?>'); return false;">View report information</a>
452
-<?  } ?>
475
+<?php  } ?>
453 476
             </div>
454 477
             <div id="peers_<?=($TorrentID)?>" class="hidden"></div>
455 478
             <div id="downloads_<?=($TorrentID)?>" class="hidden"></div>
456 479
             <div id="snatches_<?=($TorrentID)?>" class="hidden"></div>
457 480
             <div id="files_<?=($TorrentID)?>" class="hidden"><?=($FileTable)?></div>
458
-<?  if ($Reported) { ?>
481
+<?php  if ($Reported) { ?>
459 482
             <div id="reported_<?=($TorrentID)?>" class="hidden"><?=($ReportInfo)?></div>
460
-<?  }
461
-  if (!empty($Description)) {
462
-    echo "\n\t\t\t\t\t\t<blockquote>" . Text::full_format($Description) . '</blockquote>';
463
-  } if (!empty($MediaInfo)) {
464
-    echo "\n\t\t\t\t\t\t<blockquote>" . MediaInfo::parse($MediaInfo) . "</blockquote>";
465
-  } ?>
483
+<?php  }
484
+        if (!empty($Description)) {
485
+            echo "\n\t\t\t\t\t\t<blockquote>" . Text::full_format($Description) . '</blockquote>';
486
+        }
487
+        if (!empty($MediaInfo)) {
488
+            echo "\n\t\t\t\t\t\t<blockquote>" . MediaInfo::parse($MediaInfo) . "</blockquote>";
489
+        } ?>
466 490
           </td>
467 491
         </tr>
468
-<?
469
-  }
492
+<?php
493
+    }
470 494
 }

+ 37
- 3
sections/upload/upload_handle.php View File

@@ -86,6 +86,7 @@ $Properties['GroupDescription'] = trim($_POST['album_desc']);
86 86
 $Properties['TorrentDescription'] = $_POST['release_desc'];
87 87
 $Properties['MediaInfo'] = 'nil';
88 88
 $Properties['Screenshots'] = isset($_POST['screenshots']) ? $_POST['screenshots'] : '';
89
+$Properties['Mirrors'] = isset($_POST['mirrors']) ? $_POST['mirrors'] : '';
89 90
 
90 91
 if ($_POST['album_desc']) {
91 92
     $Properties['GroupDescription'] = trim($_POST['album_desc']);
@@ -406,9 +407,9 @@ if (!empty($Err)) { // Show the upload form, with the data the user entered
406 407
 if ($T['Container'] === 'Autofill' || $T['Archive'] === 'Autofill') {
407 408
     # torrents.Container
408 409
     $Validate->ParseExtensions(
409
-    $Tor->file_list(),
410
-    array_merge($Containers, $ContainersGames, $ContainersProt)
411
-);
410
+        $Tor->file_list(),
411
+        array_merge($Containers, $ContainersGames, $ContainersProt)
412
+    );
412 413
     /*
413 414
     # torrents.Archive
414 415
     $Validate->ParseExtensions(
@@ -555,6 +556,25 @@ if (!isset($GroupID) || !$GroupID) {
555 556
     $Screenshots = array_unique($Screenshots);
556 557
     $Screenshots = array_slice($Screenshots, 0, 10);
557 558
 
559
+
560
+    # Add optional web seeds similar to screenshots
561
+    # Support an arbitrary and limited number of sources
562
+    $Mirrors = explode("\n", $T['Mirrors']);
563
+    $Mirrors = array_map('trim', $Mirrors);
564
+
565
+    $Mirrors = array_filter($Mirrors, function ($s) {
566
+        return preg_match('/^'.URL_REGEX.'$/i', $s);
567
+    });
568
+
569
+    $Mirrors = array_unique($Mirrors);
570
+    $Mirrors = array_slice($Mirrors, 0, 2);
571
+
572
+    # Downgrade TLS on resource URIs
573
+    # Required for BEP 19 compatibility
574
+    $Mirrors = str_ireplace('tps://', 'tp://', $Mirrors);
575
+
576
+    # Perform the DB inserts here
577
+    # Screenshots (Publications)
558 578
     if (!empty($Screenshots)) {
559 579
         $Screenshot = '';
560 580
         $DB->prepare_query("
@@ -565,6 +585,20 @@ if (!isset($GroupID) || !$GroupID) {
565 585
             $DB->exec_prepared_query();
566 586
         }
567 587
     }
588
+
589
+    # Mirrors
590
+    if (!empty($Mirrors)) {
591
+        $Mirror = '';
592
+        $DB->prepare_query("
593
+        INSERT INTO torrents_mirrors
594
+          (GroupID, UserID, Time, Resource)
595
+        VALUES (?, ?, NOW(), ?)", $GroupID, $LoggedUser['ID'], $Mirror);
596
+        foreach ($Mirrors as $Mirror) {
597
+            $DB->exec_prepared_query();
598
+        }
599
+    }
600
+
601
+# Main if/else
568 602
 } else {
569 603
     $DB->query("
570 604
     UPDATE torrents_group

+ 60
- 86
static/functions/upload.js View File

@@ -9,79 +9,52 @@ function DisplayTrans() {
9 9
 }
10 10
 
11 11
 function Categories() {
12
-  let def = ['title', 'title_rj', 'title_jp', 'year', 'lang', 'censored', 'tags', 'cover', 'group_desc', 'release_desc', 'anon']
12
+  let def = [
13
+      'javdb', // Accession Number
14
+      'audio', // Version
15
+      'title', // Torrent Title
16
+      'title_rj', // Organism
17
+      'title_jp', // Strain/Variety
18
+      'idols', // Authors(s)
19
+      'studio', // Department/Lab
20
+      'series', // Location
21
+      'year', // Year
22
+      'codec', // License
23
+      // Platform changes below
24
+      'resolution', // Assembly Level
25
+      // Format changes below
26
+      'archive', // Archive
27
+      'tags', // Tags
28
+      'cover', // Picture
29
+      'mirrors', // Mirrors
30
+      'screenshots', // Publications
31
+      'group_desc', // Torrent Group Description
32
+      'release_desc', // Torrent Description
33
+      'censored', // Aligned/Annotated
34
+      'anon', // Upload Anonymously
35
+  ]
36
+
13 37
   let cats = [
14
-    { // DNA
15
-      'javdb': {},
16
-      'audio': {},
17
-      'idols': {},
18
-      'studio': {},
19
-      'series': {},
20
-      'media': {},
21
-      'container': {},
22
-      'resolution': {},
23
-      'archive': {},
24
-      'codec': {},
25
-      'screenshots': {},
26
-      'group_desc': {},
27
-      'release_desc': {}
28
-    }, { // RNA
29
-      'javdb': {},
30
-      'audio': {},
31
-      'idols': {},
32
-      'studio': {},
33
-      'series': {},
34
-      'media': {},
35
-      'container': {},
36
-      'resolution': {},
37
-      'archive': {},
38
-      'codec': {},
39
-      'screenshots': {},
40
-      'group_desc': {},
41
-      'release_desc': {}
42
-    }, { // Protein
43
-      'javdb': {},
44
-      'audio': {},
45
-      'idols': {},
46
-      'studio': {},
47
-      'series': {},
48
-      'media': {},
49
-      'container_prot': {},
50
-      'resolution': {},
51
-      'archive': {},
52
-      'codec': {},
53
-      'screenshots': {},
54
-      'group_desc': {},
55
-      'release_desc': {}
56
-    }, { // Imaging
57
-      'javdb': {},
58
-      'audio': {},
59
-      'idols': {},
60
-      'studio': {},
61
-      'series': {},
62
-      'media_manga': {},
63
-      'container_games': {},
64
-      'resolution': {},
65
-      'archive': {},
66
-      'codec': {},
67
-      'screenshots': {},
68
-      'group_desc': {},
69
-      'release_desc': {}
70
-    }, { // Extras
71
-      'javdb': {},
72
-      'audio': {},
73
-      'idols': {},
74
-      'studio': {},
75
-      'series': {},
76
-      'media': {},
77
-      'container': {},
78
-      'resolution': {},
79
-      'archive': {},
80
-      'codec': {},
81
-      'screenshots': {},
82
-      'group_desc': {},
83
-      'release_desc': {}
84
-    }
38
+      { // DNA
39
+          'media': {}, // Platform
40
+          'container': {}, // Format
41
+      },
42
+      { // RNA
43
+          'media': {}, // Platform
44
+          'container': {}, // Format
45
+      },
46
+      { // Proteins
47
+          'media': {}, // Platform
48
+          'container_prot': {}, // Format
49
+      },
50
+      { // Imaging
51
+          'media_manga': {}, // Platform
52
+          'container_games': {}, // Format
53
+      },
54
+      { // Extras
55
+          'media': {}, // Platform
56
+          'container_extra': {}, // Format
57
+      }
85 58
   ]
86 59
 
87 60
   let active = {}
@@ -92,27 +65,28 @@ function Categories() {
92 65
   active = Object.assign(active, cats[category])
93 66
 
94 67
   let hide = el => {
95
-    Array.from($(`#${el.id} input, #${el.id} select, #${el.id} textarea`)).forEach(inp => inp.disabled = true)
96
-    $(el).ghide()
68
+      Array.from($(`#${el.id} input, #${el.id} select, #${el.id} textarea`)).forEach(inp => inp.disabled = true)
69
+      $(el).ghide()
97 70
   }
71
+
98 72
   let show = el => {
99
-    Array.from($(`#${el.id} input, #${el.id} select, #${el.id} textarea`)).forEach(inp => inp.disabled = false)
100
-    $(el).gshow()
73
+      Array.from($(`#${el.id} input, #${el.id} select, #${el.id} textarea`)).forEach(inp => inp.disabled = false)
74
+      $(el).gshow()
101 75
   }
102 76
 
103 77
   let trs = $('#dynamic_form tr')
104 78
   for (let tr of trs) {
105
-    let field = tr.id.slice(0, -3)
106
-    if (active[field]) {
107
-      if (active[field].name) {
108
-        tr.children[0].innerHTML = active[field].name
79
+      let field = tr.id.slice(0, -3)
80
+      if (active[field]) {
81
+          if (active[field].name) {
82
+              tr.children[0].innerHTML = active[field].name
83
+          }
84
+          let notes = $(`#${tr.id} p.notes`).raw()
85
+          if (notes) notes.innerHTML = active[field].notes || ''
86
+          show(tr)
87
+      } else {
88
+          hide(tr)
109 89
       }
110
-      let notes = $(`#${tr.id} p.notes`).raw()
111
-      if (notes) notes.innerHTML = active[field].notes || ''
112
-      show(tr)
113
-    } else {
114
-      hide(tr)
115
-    }
116 90
   }
117 91
 }
118 92
 

Loading…
Cancel
Save