Browse Source

Big broken commit: redo torrents_group schema, remove "capture user" and "donor forum honorific" features, add ability to call API from Gazelle, duplicate API for new version, style updates, etc.

biotorrents 4 years ago
parent
commit
375989bb73
100 changed files with 6965 additions and 1382 deletions
  1. 0
    1
      api.php
  2. 111
    58
      classes/donations.class.php
  3. 52
    2
      classes/json.class.php
  4. 83
    64
      classes/permissions_form.php
  5. 8
    5
      classes/security.class.php
  6. 0
    17
      classes/slaves.class.php
  7. 1
    1
      classes/torrent_form.class.php
  8. 202
    70
      classes/torrents.class.php
  9. 176
    89
      classes/userrank.class.php
  10. 1
    7
      classes/users.class.php
  11. 0
    1
      classes/vendor/Parsedown.php
  12. 1
    2
      classes/vendor/ParsedownExtra.php
  13. 0
    1
      classes/vendor/TwitterAPIExchange.php
  14. 1
    0
      design/privateheader.php
  15. 1
    1
      design/publicheader.php
  16. 168
    26
      gazelle.sql
  17. 17
    15
      sections/ajax/artist.php
  18. 41
    42
      sections/ajax/index.php
  19. 1
    1
      sections/ajax/loadavg.php
  20. 46
    23
      sections/ajax/send_recommendation.php
  21. 5
    3
      sections/ajax/stats.php
  22. 23
    17
      sections/ajax/top10/torrents.php
  23. 37
    23
      sections/ajax/user_recents.php
  24. 83
    0
      sections/api/announcements.php
  25. 362
    0
      sections/api/artist.php
  26. 14
    0
      sections/api/autofill/doi.php
  27. 38
    0
      sections/api/better/index.php
  28. 55
    0
      sections/api/better/single.php
  29. 131
    0
      sections/api/better/transcode.php
  30. 63
    0
      sections/api/bookmarks/artists.php
  31. 47
    0
      sections/api/bookmarks/index.php
  32. 124
    0
      sections/api/bookmarks/torrents.php
  33. 132
    0
      sections/api/browse.php
  34. 49
    0
      sections/api/clear_user_notification.php
  35. 174
    0
      sections/api/collage.php
  36. 70
    0
      sections/api/community_stats.php
  37. 180
    0
      sections/api/forum/forum.php
  38. 34
    0
      sections/api/forum/index.php
  39. 117
    0
      sections/api/forum/main.php
  40. 291
    0
      sections/api/forum/thread.php
  41. 21
    0
      sections/api/get_friends.php
  42. 8
    0
      sections/api/get_user_notifications.php
  43. 118
    0
      sections/api/inbox/inbox.php
  44. 13
    0
      sections/api/inbox/index.php
  45. 106
    0
      sections/api/inbox/viewconv.php
  46. 287
    0
      sections/api/index.php
  47. 117
    0
      sections/api/info.php
  48. 14
    0
      sections/api/loadavg.php
  49. 42
    0
      sections/api/news_ajax.php
  50. 110
    0
      sections/api/notifications.php
  51. 12
    0
      sections/api/ontology.php
  52. 12
    0
      sections/api/preview.php
  53. 32
    0
      sections/api/raw_bbcode.php
  54. 119
    0
      sections/api/request.php
  55. 369
    0
      sections/api/requests.php
  56. 90
    0
      sections/api/send_recommendation.php
  57. 165
    0
      sections/api/stats.php
  58. 92
    0
      sections/api/subscriptions.php
  59. 42
    0
      sections/api/tcomments.php
  60. 32
    0
      sections/api/top10/index.php
  61. 83
    0
      sections/api/top10/tags.php
  62. 185
    0
      sections/api/top10/torrents.php
  63. 130
    0
      sections/api/top10/users.php
  64. 166
    0
      sections/api/torrents/group.php
  65. 105
    0
      sections/api/torrents/torrent.php
  66. 22
    0
      sections/api/torrents/torrentgroupalbumart.php
  67. 485
    0
      sections/api/user.php
  68. 96
    0
      sections/api/user_recents.php
  69. 20
    0
      sections/api/userhistory/index.php
  70. 186
    0
      sections/api/userhistory/post_history.php
  71. 58
    0
      sections/api/usersearch.php
  72. 41
    0
      sections/api/wiki.php
  73. 39
    38
      sections/artist/add_alias.php
  74. 1
    1
      sections/artist/artist.php
  75. 97
    93
      sections/artist/change_artistid.php
  76. 38
    29
      sections/artist/delete.php
  77. 2
    2
      sections/forums/thread.php
  78. 39
    19
      sections/index/private.php
  79. 2
    2
      sections/locked/index.php
  80. 0
    24
      sections/rules/chat.php
  81. 27
    19
      sections/schedule/daily/top10_daily.php
  82. 27
    19
      sections/schedule/weekly/top10_weekly.php
  83. 0
    16
      sections/slaves/index.php
  84. 0
    60
      sections/slaves/slaves.php
  85. 3
    3
      sections/stats/torrents.php
  86. 0
    110
      sections/store/capture_user.php
  87. 41
    51
      sections/top10/torrents.php
  88. 2
    3
      sections/torrents/browse.php
  89. 10
    10
      sections/torrents/edit.php
  90. 13
    13
      sections/torrents/editgroup.php
  91. 23
    23
      sections/torrents/functions.php
  92. 1
    1
      sections/torrents/nonwikiedit.php
  93. 0
    74
      sections/torrents/takechangecategory.php
  94. 52
    41
      sections/torrents/takenewgroup.php
  95. 64
    47
      sections/upload/upload.php
  96. 0
    42
      sections/user/edit.php
  97. 22
    58
      sections/user/user.php
  98. 145
    111
      sections/userhistory/token_history.php
  99. 0
    4
      signup.php
  100. 0
    0
      sphinx.conf

slaves.php → api.php View File

@@ -1,5 +1,4 @@
1 1
 <?php
2 2
 declare(strict_types=1);
3 3
 
4
-define('ERROR_EXCEPTION', true);
5 4
 require_once 'classes/script_start.php';

+ 111
- 58
classes/donations.class.php View File

@@ -1,13 +1,14 @@
1 1
 <?php
2 2
 declare(strict_types=1);
3 3
 
4
-define('BTC_API_URL', 'https://api.bitcoinaverage.com/ticker/global/EUR/');
5
-define('USD_API_URL', 'http://www.google.com/ig/calculator?hl=en&q=1USD=?EUR');
6
-
7 4
 class Donations
8 5
 {
9 6
     private static $IsSchedule = false;
10 7
 
8
+
9
+    /**
10
+     * regular_donate
11
+     */
11 12
     public static function regular_donate($UserID, $DonationAmount, $Source, $Reason, $Currency = 'USD')
12 13
     {
13 14
         self::donate(
@@ -23,6 +24,10 @@ class Donations
23 24
         );
24 25
     }
25 26
 
27
+
28
+    /**
29
+     * donate
30
+     */
26 31
     public static function donate($UserID, $Args)
27 32
     {
28 33
         $UserID = (int) $UserID;
@@ -220,6 +225,10 @@ class Donations
220 225
         G::$DB->set_query_id($QueryID);
221 226
     }
222 227
 
228
+
229
+    /**
230
+     * calculate_special_rank
231
+     */
223 232
     private static function calculate_special_rank($UserID)
224 233
     {
225 234
         $UserID = (int) $UserID;
@@ -272,6 +281,10 @@ class Donations
272 281
         G::$DB->set_query_id($QueryID);
273 282
     }
274 283
 
284
+
285
+    /**
286
+     * expire_ranks
287
+     */
275 288
     public static function expire_ranks()
276 289
     {
277 290
         $QueryID = G::$DB->get_query_id();
@@ -309,11 +322,19 @@ class Donations
309 322
         G::$DB->set_query_id($QueryID);
310 323
     }
311 324
 
325
+
326
+    /**
327
+     * calculate_rank
328
+     */
312 329
     private static function calculate_rank($Amount)
313 330
     {
314 331
         return floor($Amount / 5);
315 332
     }
316 333
 
334
+
335
+    /**
336
+     * update_rank
337
+     */
317 338
     public static function update_rank($UserID, $Rank, $TotalRank, $Reason)
318 339
     {
319 340
         $Rank = (int) $Rank;
@@ -332,6 +353,10 @@ class Donations
332 353
         );
333 354
     }
334 355
 
356
+
357
+    /**
358
+     * hide_stats
359
+     */
335 360
     public static function hide_stats($UserID)
336 361
     {
337 362
         $QueryID = G::$DB->get_query_id();
@@ -345,6 +370,10 @@ class Donations
345 370
         G::$DB->set_query_id($QueryID);
346 371
     }
347 372
 
373
+
374
+    /**
375
+     * show_stats
376
+     */
348 377
     public static function show_stats($UserID)
349 378
     {
350 379
         $QueryID = G::$DB->get_query_id();
@@ -358,6 +387,10 @@ class Donations
358 387
         G::$DB->set_query_id($QueryID);
359 388
     }
360 389
 
390
+
391
+    /**
392
+     * is_visible
393
+     */
361 394
     public static function is_visible($UserID)
362 395
     {
363 396
         $QueryID = G::$DB->get_query_id();
@@ -375,12 +408,17 @@ class Donations
375 408
         return $HasResults;
376 409
     }
377 410
 
411
+
412
+    /**
413
+     * has_donor_forum
414
+     */
378 415
     public static function has_donor_forum($UserID)
379 416
     {
380 417
         $ENV = ENV::go();
381 418
         return self::get_rank($UserID) >= $ENV->DONOR_FORUM_RANK || self::get_special_rank($UserID) >= MAX_SPECIAL_RANK;
382 419
     }
383 420
 
421
+
384 422
     /**
385 423
      * Put all the common donor info in the same cache key to save some cache calls
386 424
      */
@@ -452,26 +490,46 @@ class Donations
452 490
         return $DonorInfo;
453 491
     }
454 492
 
493
+
494
+    /**
495
+     * get_rank
496
+     */
455 497
     public static function get_rank($UserID)
456 498
     {
457 499
         return self::get_donor_info($UserID)['Rank'];
458 500
     }
459 501
 
502
+
503
+    /**
504
+     * get_special_rank
505
+     */
460 506
     public static function get_special_rank($UserID)
461 507
     {
462 508
         return self::get_donor_info($UserID)['SRank'];
463 509
     }
464 510
 
511
+
512
+    /**
513
+     * get_total_rank
514
+     */
465 515
     public static function get_total_rank($UserID)
466 516
     {
467 517
         return self::get_donor_info($UserID)['TotRank'];
468 518
     }
469 519
 
520
+
521
+    /**
522
+     * get_donation_time
523
+     */
470 524
     public static function get_donation_time($UserID)
471 525
     {
472 526
         return self::get_donor_info($UserID)['Time'];
473 527
     }
474 528
 
529
+
530
+    /**
531
+     * get_personal_collages
532
+     */
475 533
     public static function get_personal_collages($UserID)
476 534
     {
477 535
         $DonorInfo = self::get_donor_info($UserID);
@@ -483,30 +541,10 @@ class Donations
483 541
         return $Collages;
484 542
     }
485 543
 
486
-    public static function get_titles($UserID)
487
-    {
488
-        $Results = G::$Cache->get_value("donor_title_$UserID");
489
-        if ($Results === false) {
490
-            $QueryID = G::$DB->get_query_id();
491
-
492
-            G::$DB->query("
493
-            SELECT
494
-              `Prefix`,
495
-              `Suffix`,
496
-              `UseComma`
497
-            FROM
498
-              `donor_forum_usernames`
499
-            WHERE
500
-              `UserID` = '$UserID'
501
-            ");
502
-
503
-            $Results = G::$DB->next_record();
504
-            G::$DB->set_query_id($QueryID);
505
-            G::$Cache->cache_value("donor_title_$UserID", $Results, 0);
506
-        }
507
-        return $Results;
508
-    }
509 544
 
545
+    /**
546
+     * get_enabled_rewards
547
+     */
510 548
     public static function get_enabled_rewards($UserID)
511 549
     {
512 550
         $Rewards = [];
@@ -553,11 +591,19 @@ class Donations
553 591
         return $Rewards;
554 592
     }
555 593
 
594
+
595
+    /**
596
+     * get_rewards
597
+     */
556 598
     public static function get_rewards($UserID)
557 599
     {
558 600
         return self::get_donor_info($UserID)['Rewards'];
559 601
     }
560 602
 
603
+
604
+    /**
605
+     * get_profile_rewards
606
+     */
561 607
     public static function get_profile_rewards($UserID)
562 608
     {
563 609
         $Results = G::$Cache->get_value("donor_profile_rewards_$UserID");
@@ -587,6 +633,10 @@ class Donations
587 633
         return $Results;
588 634
     }
589 635
 
636
+
637
+    /**
638
+     * add_profile_info_reward
639
+     */
590 640
     private static function add_profile_info_reward($Counter, &$Insert, &$Values, &$Update)
591 641
     {
592 642
         if (isset($_POST["profile_title_" . $Counter]) && isset($_POST["profile_info_" . $Counter])) {
@@ -603,6 +653,10 @@ class Donations
603 653
         }
604 654
     }
605 655
 
656
+
657
+    /**
658
+     * update_rewards
659
+     */
606 660
     public static function update_rewards($UserID)
607 661
     {
608 662
         $Rank = self::get_rank($UserID);
@@ -663,7 +717,6 @@ class Donations
663 717
                 $Values[] = "'$CustomIcon'";
664 718
                 $Update[] = "CustomIcon = '$CustomIcon'";
665 719
             }
666
-            self::update_titles($UserID, $_POST['donor_title_prefix'], $_POST['donor_title_suffix'], $_POST['donor_title_comma']);
667 720
             $Counter++;
668 721
         }
669 722
 
@@ -705,37 +758,10 @@ class Donations
705 758
         G::$Cache->delete_value("donor_info_$UserID");
706 759
     }
707 760
 
708
-    public static function update_titles($UserID, $Prefix, $Suffix, $UseComma)
709
-    {
710
-        $QueryID = G::$DB->get_query_id();
711
-        $Prefix = trim(db_string($Prefix));
712
-        $Suffix = trim(db_string($Suffix));
713
-        $UseComma = empty($UseComma);
714
-
715
-        G::$DB->query("
716
-        INSERT INTO `donor_forum_usernames`(
717
-          `UserID`,
718
-          `Prefix`,
719
-          `Suffix`,
720
-          `UseComma`
721
-        )
722
-        VALUES(
723
-          '$UserID',
724
-          '$Prefix',
725
-          '$Suffix',
726
-          '$UseComma'
727
-        )
728
-        ON DUPLICATE KEY
729
-        UPDATE
730
-          `Prefix` = '$Prefix',
731
-          `Suffix` = '$Suffix',
732
-          `UseComma` = '$UseComma'
733
-        ");
734
-
735
-        G::$Cache->delete_value("donor_title_$UserID");
736
-        G::$DB->set_query_id($QueryID);
737
-    }
738 761
 
762
+    /**
763
+     * get_donation_history
764
+     */
739 765
     public static function get_donation_history($UserID)
740 766
     {
741 767
         $UserID = (int) $UserID;
@@ -743,7 +769,6 @@ class Donations
743 769
             error(404);
744 770
         }
745 771
 
746
-        # todo: Investigate Rank in donations table
747 772
         $QueryID = G::$DB->get_query_id();
748 773
         G::$DB->query("
749 774
         SELECT
@@ -770,6 +795,10 @@ class Donations
770 795
         return $DonationHistory;
771 796
     }
772 797
 
798
+
799
+    /**
800
+     * get_rank_expiration
801
+     */
773 802
     public static function get_rank_expiration($UserID)
774 803
     {
775 804
         $DonorInfo = self::get_donor_info($UserID);
@@ -789,6 +818,10 @@ class Donations
789 818
         return $Return;
790 819
     }
791 820
 
821
+
822
+    /**
823
+     * get_leaderboard_position
824
+     */
792 825
     public static function get_leaderboard_position($UserID)
793 826
     {
794 827
         $UserID = (int) $UserID;
@@ -823,11 +856,19 @@ class Donations
823 856
         return $Position;
824 857
     }
825 858
 
859
+
860
+    /**
861
+     * is_donor
862
+     */
826 863
     public static function is_donor($UserID)
827 864
     {
828 865
         return self::get_rank($UserID) > 0;
829 866
     }
830 867
 
868
+
869
+    /**
870
+     * currency_exchange
871
+     */
831 872
     public static function currency_exchange($Amount, $Currency)
832 873
     {
833 874
         if (!self::is_valid_currency($Currency)) {
@@ -849,11 +890,19 @@ class Donations
849 890
         return round($Amount, 2);
850 891
     }
851 892
 
893
+
894
+    /**
895
+     * is_valid_currency
896
+     */
852 897
     public static function is_valid_currency($Currency)
853 898
     {
854 899
         return $Currency === 'EUR' || $Currency === 'BTC' || $Currency === 'USD';
855 900
     }
856 901
 
902
+
903
+    /**
904
+     * btc_to_euro
905
+     */
857 906
     public static function btc_to_euro($Amount)
858 907
     {
859 908
         $Rate = G::$Cache->get_value('btc_rate');
@@ -863,6 +912,10 @@ class Donations
863 912
         return $Rate * $Amount;
864 913
     }
865 914
 
915
+
916
+    /**
917
+     * usd_to_euro
918
+     */
866 919
     public static function usd_to_euro($Amount)
867 920
     {
868 921
         $Rate = G::$Cache->get_value('usd_rate');

+ 52
- 2
classes/json.class.php View File

@@ -4,8 +4,6 @@ declare(strict_types = 1);
4 4
 /**
5 5
  * Adapted from
6 6
  * https://github.com/OPSnet/Gazelle/blob/master/app/Json.php
7
- *
8
- * Unused as of 2020-12-12
9 7
  */
10 8
 
11 9
 abstract class Json
@@ -14,6 +12,7 @@ abstract class Json
14 12
     protected $source;
15 13
     protected $mode;
16 14
 
15
+
17 16
     /**
18 17
      * __construct
19 18
      */
@@ -25,6 +24,7 @@ abstract class Json
25 24
         $this->version = 1;
26 25
     }
27 26
 
27
+
28 28
     /**
29 29
      * The payload of a valid JSON response, implemented in the child class.
30 30
      * @return array Payload to be passed to json_encode()
@@ -32,6 +32,7 @@ abstract class Json
32 32
      */
33 33
     abstract public function payload(): ?array;
34 34
 
35
+
35 36
     /**
36 37
      * Configure JSON printing (any of the json_encode  JSON_* constants)
37 38
      *
@@ -43,6 +44,7 @@ abstract class Json
43 44
         return $this;
44 45
     }
45 46
 
47
+
46 48
     /**
47 49
      * set the version of the Json payload. Increment the
48 50
      * value when there is significant change in the payload.
@@ -56,6 +58,7 @@ abstract class Json
56 58
         return $this;
57 59
     }
58 60
 
61
+
59 62
     /**
60 63
      * General failure routine for when bad things happen.
61 64
      *
@@ -77,6 +80,7 @@ abstract class Json
77 80
         );
78 81
     }
79 82
 
83
+
80 84
     /**
81 85
      * emit
82 86
      */
@@ -99,6 +103,7 @@ abstract class Json
99 103
         );
100 104
     }
101 105
 
106
+
102 107
     /**
103 108
      * debug
104 109
      */
@@ -116,6 +121,7 @@ abstract class Json
116 121
         ];
117 122
     }
118 123
 
124
+
119 125
     /**
120 126
      * info
121 127
      */
@@ -128,4 +134,48 @@ abstract class Json
128 134
             ]
129 135
         ];
130 136
     }
137
+
138
+
139
+    /**
140
+     * fetch
141
+     *
142
+     * Get resources over the API to populate Gazelle display.
143
+     * Instead of copy-pasting the same SQL queries in many places.
144
+     *
145
+     * Takes a query string, e.g., "action=torrentgroup&id=1."
146
+     * Requires an API key for the user ID 0 (minor database surgery).
147
+     */
148
+    public function fetch($Action, $Params = [])
149
+    {
150
+        $ENV = ENV::go();
151
+
152
+        $Token = $ENV->getPriv('SELF_API');
153
+        $Params = implode('&', $Params);
154
+
155
+        $ch = curl_init();
156
+
157
+        # todo: Make this use localhost and not HTTPS
158
+        curl_setopt($ch, CURLOPT_URL, "https://$ENV->SITE_DOMAIN/api.php?action=$Action&$Params");
159
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
160
+
161
+        # https://docs.biotorrents.de
162
+        curl_setopt(
163
+            $ch,
164
+            CURLOPT_HTTPHEADER,
165
+            [
166
+                'Accept: application/json',
167
+                "Authorization: Bearer $Token",
168
+            ]
169
+        );
170
+
171
+        $Data = curl_exec($ch);
172
+        curl_close($ch);
173
+
174
+        # Error out on bad query
175
+        if (!$Data) {
176
+            return error();
177
+        } else {
178
+            return json_decode($Data);
179
+        }
180
+    }
131 181
 }

+ 83
- 64
classes/permissions_form.php View File

@@ -1,12 +1,13 @@
1 1
 <?php
2 2
 declare(strict_types=1);
3 3
 
4
-/********************************************************************************
5
- ************ Permissions form ********************** user.php and tools.php ****
6
- ********************************************************************************
7
- ** This function is used to create both the class permissions form, and the   **
8
- ** user custom permissions form.                                              **
9
- ********************************************************************************/
4
+/**
5
+ * Permissions form
6
+ * user.php and tools.php
7
+ *
8
+ * This function is used to create both the class permissions form,
9
+ * and the user custom permissions form.
10
+ */
10 11
 
11 12
 $PermissionsArray = array(
12 13
   'site_leech' => 'Can leech (Does this work?).',
@@ -112,16 +113,17 @@ $PermissionsArray = array(
112 113
 
113 114
 function permissions_form()
114 115
 {
115
-    ?>
116
-<div class="permissions">
117
-  <div class="permission_container">
118
-    <table>
119
-      <tr class="colhead">
120
-        <td>Site</td>
121
-      </tr>
122
-      <tr>
123
-        <td>
124
-          <?php
116
+    echo <<<HTML
117
+    <div class="permission_container">
118
+      <table>
119
+        <tr class="colhead">
120
+          <th>Site</th>
121
+        </tr>
122
+        
123
+        <tr>
124
+          <td>
125
+HTML;
126
+
125 127
     display_perm('site_leech', 'Can leech.');
126 128
     display_perm('site_upload', 'Can upload.');
127 129
     display_perm('site_vote', 'Can vote on requests.');
@@ -161,20 +163,24 @@ function permissions_form()
161 163
     display_perm('site_forums_double_post', 'Can double post in the forums.');
162 164
     display_perm('project_team', 'Part of the project team.');
163 165
     display_perm('site_tag_aliases_read', 'Can view the list of tag aliases.');
164
-    display_perm('site_ratio_watch_immunity', 'Immune from being put on ratio watch.'); ?>
165
-        </td>
166
-      </tr>
167
-    </table>
168
-  </div>
166
+    display_perm('site_ratio_watch_immunity', 'Immune from being put on ratio watch.');
167
+
168
+    echo <<<HTML
169
+          </td>
170
+        </tr>
171
+      </table>
172
+    </div>
173
+    
174
+    <div class="permission_container">
175
+      <table>
176
+        <tr class="colhead">
177
+          <th>Users</th>
178
+        </tr>
179
+        
180
+        <tr>
181
+          <td>
182
+HTML;
169 183
 
170
-  <div class="permission_container">
171
-    <table>
172
-      <tr class="colhead">
173
-        <td>Users</td>
174
-      </tr>
175
-      <tr>
176
-        <td>
177
-          <?php
178 184
     display_perm('users_edit_usernames', 'Can edit usernames.');
179 185
     display_perm('users_edit_ratio', 'Can edit anyone\'s upload/download amounts.');
180 186
     display_perm('users_edit_own_ratio', 'Can edit own upload/download amounts.');
@@ -206,21 +212,27 @@ function permissions_form()
206 212
     display_perm('users_override_paranoia', 'Can override paranoia');
207 213
     display_perm('users_make_invisible', 'Can make users invisible');
208 214
     display_perm('users_logout', 'Can log users out');
209
-    display_perm('users_mod', 'Can access basic moderator tools (Admin comment)'); ?>
210
-          * Everything is only applicable to users with the same or lower class level
211
-        </td>
212
-      </tr>
213
-    </table>
214
-  </div>
215
+    display_perm('users_mod', 'Can access basic moderator tools (Admin comment)');
216
+
217
+    echo <<<HTML
218
+            <strong class="important_text">
219
+              Everything is only applicable to users with the same or lower class level
220
+            </strong>
221
+          </td>
222
+        </tr>
223
+      </table>
224
+    </div>
225
+    
226
+    <div class="permission_container">
227
+      <table>
228
+        <tr class="colhead">
229
+          <th>Torrents</th>
230
+        </tr>
231
+        
232
+        <tr>
233
+          <td>
234
+HTML;
215 235
 
216
-  <div class="permission_container">
217
-    <table>
218
-      <tr class="colhead">
219
-        <td>Torrents</td>
220
-      </tr>
221
-      <tr>
222
-        <td>
223
-          <?php
224 236
     display_perm('torrents_edit', 'Can edit any torrent');
225 237
     display_perm('torrents_delete', 'Can delete torrents');
226 238
     display_perm('torrents_delete_fast', 'Can delete more than 3 torrents at a time.');
@@ -232,20 +244,24 @@ function permissions_form()
232 244
     display_perm('artist_edit_vanityhouse', 'Can mark artists as part of Vanity House.');
233 245
     display_perm('torrents_fix_ghosts', 'Can fix ghost groups on artist pages.');
234 246
     display_perm('screenshots_add', 'Can add screenshots to any torrent and delete their own screenshots.');
235
-    display_perm('screenshots_delete', 'Can delete any screenshot from any torrent.'); ?>
236
-        </td>
237
-      </tr>
238
-    </table>
239
-  </div>
247
+    display_perm('screenshots_delete', 'Can delete any screenshot from any torrent.');
248
+
249
+    echo <<<HTML
250
+          </td>
251
+        </tr>
252
+      </table>
253
+    </div>
254
+    
255
+    <div class="permission_container">
256
+      <table>
257
+        <tr class="colhead">
258
+          <th>Administrative</th>
259
+        </tr>
260
+        
261
+        <tr>
262
+          <td>
263
+HTML;
240 264
 
241
-  <div class="permission_container">
242
-    <table>
243
-      <tr class="colhead">
244
-        <td>Administrative</td>
245
-      </tr>
246
-      <tr>
247
-        <td>
248
-          <?php
249 265
     display_perm('admin_manage_news', 'Can manage site news');
250 266
     display_perm('admin_manage_blog', 'Can manage the site blog');
251 267
     display_perm('admin_manage_polls', 'Can manage polls');
@@ -261,13 +277,16 @@ function permissions_form()
261 277
     display_perm('admin_manage_permissions', 'Can edit permission classes/user permissions.');
262 278
     display_perm('admin_schedule', 'Can run the site schedule.');
263 279
     display_perm('admin_login_watch', 'Can manage login watch.');
264
-    display_perm('admin_manage_wiki', 'Can manage wiki access.'); ?>
265
-        </td>
266
-      </tr>
267
-    </table>
268
-  </div>
280
+    display_perm('admin_manage_wiki', 'Can manage wiki access.');
269 281
 
270
-  <div class="submit_container"><input type="submit" name="submit" value="Save Permission Class" /></div>
271
-</div>
272
-<?php
282
+    echo <<<HTML
283
+          </td>
284
+        </tr>
285
+      </table>
286
+    </div>
287
+    
288
+    <div class="submit_container">
289
+      <input type="submit" name="submit" value="Save Permission Class" />
290
+    </div>
291
+HTML;
273 292
 }

+ 8
- 5
classes/security.class.php View File

@@ -11,20 +11,23 @@ declare(strict_types = 1);
11 11
 class Security
12 12
 {
13 13
     /**
14
-     * Check ID
14
+     * Check integer
15 15
      *
16 16
      * Makes sure a number ID is valid,
17 17
      * e.g., a page ID requested by GET.
18 18
      */
19
-    public function CheckID($ID)
19
+    public function checkInt($IDs)
20 20
     {
21 21
         # Temporary failsafe
22 22
         # (int) 'dingus' = 0
23 23
         # (int) 3.14 = 3
24
-        $ID = (int) $ID;
24
+        $IDs = (is_array($IDs) ?: [(int) $IDs]);
25
+        foreach ($IDs as $ID) {
26
+            $ID = (int) $ID;
25 27
 
26
-        if (!is_int($ID) || $ID < 1) {
27
-            error(400);
28
+            if (!is_int($ID) || $ID < 1) {
29
+                error(400);
30
+            }
28 31
         }
29 32
 
30 33
         return;

+ 0
- 17
classes/slaves.class.php View File

@@ -1,17 +0,0 @@
1
-<?php
2
-#declare(strict_types=1);
3
-
4
-class Slaves
5
-{
6
-    public static function get_level($SlaveID)
7
-    {
8
-        G::$DB->query("
9
-        SELECT u.Uploaded, u.Downloaded, u.BonusPoints, COUNT(t.UserID)
10
-        FROM users_main AS u
11
-          LEFT JOIN torrents AS t ON u.ID=t.UserID
12
-          WHERE u.ID = $SlaveID");
13
-          
14
-        list($Upload, $Download, $Points, $Uploads) = G::$DB->next_record();
15
-        return intval(((($Uploads**0.35)*1.5)+1) * max(($Upload+($Points*1000000)-$Download)/(1024**3), 1));
16
-    }
17
-};

+ 1
- 1
classes/torrent_form.class.php View File

@@ -1285,7 +1285,7 @@ HTML;
1285 1285
         /**
1286 1286
          * Mirrors
1287 1287
          *
1288
-         * This should be in the `torrents` table not `torrents_group`.
1288
+         * This should be in the `torrents` table not `torrents_group.`
1289 1289
          * The intended use is for web seeds, Dat mirrors, etc.
1290 1290
          */
1291 1291
         if (!$this->DisabledFlag && $this->NewTorrent) {

+ 202
- 70
classes/torrents.class.php View File

@@ -60,54 +60,97 @@ class Torrents
60 60
                 unset($GroupIDs[$i], $Found[$GroupID], $NotFound[$GroupID]);
61 61
                 continue;
62 62
             }
63
+
63 64
             $Data = G::$Cache->get_value($Key . $GroupID, true);
64 65
             if (!empty($Data) && is_array($Data) && $Data['ver'] === Cache::GROUP_VERSION) {
65 66
                 unset($NotFound[$GroupID]);
66 67
                 $Found[$GroupID] = $Data['d'];
67 68
             }
68 69
         }
70
+
69 71
         // Make sure there's something in $GroupIDs, otherwise the SQL will break
70 72
         if (count($GroupIDs) === 0) {
71 73
             return [];
72 74
         }
73 75
 
74
-        /*
75
-        Changing any of these attributes returned will cause very large, very dramatic site-wide chaos.
76
-        Do not change what is returned or the order thereof without updating:
77
-          torrents, artists, collages, bookmarks, better, the front page,
78
-        and anywhere else the get_groups function is used.
79
-        Update self::array_group(), too
80
-        */
76
+        /**
77
+         * Changing any of these attributes returned will cause very large, very dramatic site-wide chaos.
78
+         * Do not change what is returned or the order thereof without updating:
79
+         * torrents, artists, collages, bookmarks, better, the front page,
80
+         * and anywhere else the get_groups function is used.
81
+         * Update self::array_group(), too.
82
+         */
81 83
 
82 84
         if (count($NotFound) > 0) {
83 85
             $IDs = implode(',', array_keys($NotFound));
84 86
             $NotFound = [];
85 87
             $QueryID = G::$DB->get_query_id();
88
+
86 89
             G::$DB->query("
87 90
             SELECT
88
-              ID, Name, Title2, NameJP, Year, CatalogueNumber, Studio, Series, TagList, WikiImage, CategoryID
89
-            FROM torrents_group
90
-              WHERE ID IN ($IDs)");
91
+              `id`,
92
+              `title`,
93
+              `subject`,
94
+              `object`,
95
+              `published`,
96
+              `identifier`,
97
+              `workgroup`,
98
+              `location`,
99
+              `tag_list`,
100
+              `picture`,
101
+              `category_id`
102
+            FROM
103
+              `torrents_group`
104
+            WHERE
105
+              `id` IN($IDs)
106
+            ");
91 107
 
92 108
             while ($Group = G::$DB->next_record(MYSQLI_ASSOC, true)) {
93
-                $NotFound[$Group['ID']] = $Group;
94
-                $NotFound[$Group['ID']]['Torrents'] = [];
95
-                $NotFound[$Group['ID']]['Artists'] = [];
109
+                $NotFound[$Group['id']] = $Group;
110
+                $NotFound[$Group['id']]['Torrents'] = [];
111
+                $NotFound[$Group['id']]['Artists'] = [];
96 112
             }
97 113
             G::$DB->set_query_id($QueryID);
98 114
 
99 115
             if ($Torrents) {
100 116
                 $QueryID = G::$DB->get_query_id();
117
+
101 118
                 G::$DB->query("
102
-                  SELECT
103
-                  ID, GroupID, Media, Container, Codec, Resolution, Version,
104
-                    Censored, Archive, FileCount, FreeTorrent,
105
-                    Size, Leechers, Seeders, Snatched, Time, f.ExpiryTime, ID AS HasFile,
106
-                    FreeLeechType, hex(info_hash) as info_hash
107
-                  FROM torrents
108
-                    LEFT JOIN shop_freeleeches AS f ON f.TorrentID=ID
109
-                    WHERE GroupID IN ($IDs)
110
-                  ORDER BY GroupID, Media, Container, Codec, ID");
119
+                SELECT
120
+                  `ID`,
121
+                  `GroupID`,
122
+                  `Media`,
123
+                  `Container`,
124
+                  `Codec`,
125
+                  `Resolution`,
126
+                  `Version`,
127
+                  `Censored`,
128
+                  `Archive`,
129
+                  `FileCount`,
130
+                  `FreeTorrent`,
131
+                  `Size`,
132
+                  `Leechers`,
133
+                  `Seeders`,
134
+                  `Snatched`,
135
+                  `Time`,
136
+                  f.`ExpiryTime`,
137
+                  `ID` AS `HasFile`,
138
+                  `FreeLeechType`,
139
+                  HEX(`info_hash`) AS `info_hash`
140
+                FROM
141
+                  `torrents`
142
+                LEFT JOIN `shop_freeleeches` AS f
143
+                ON
144
+                  f.`TorrentID` = `ID`
145
+                WHERE
146
+                  `GroupID` IN($IDs)
147
+                ORDER BY
148
+                  `GroupID`,
149
+                  `Media`,
150
+                  `Container`,
151
+                  `Codec`,
152
+                  `ID`
153
+                ");
111 154
                   
112 155
                 while ($Torrent = G::$DB->next_record(MYSQLI_ASSOC, true)) {
113 156
                     $NotFound[$Torrent['GroupID']]['Torrents'][$Torrent['ID']] = $Torrent;
@@ -138,6 +181,7 @@ class Torrents
138 181
                 }
139 182
                 $Found[$GroupID]['Artists'] = $Data;
140 183
             }
184
+
141 185
             // Fetch all user specific torrent properties
142 186
             if ($Torrents) {
143 187
                 foreach ($Found as &$Group) {
@@ -166,18 +210,18 @@ class Torrents
166 210
     public static function array_group(array &$Group)
167 211
     {
168 212
         return array(
169
-          'GroupID' => $Group['ID'],
170
-          'GroupName' => $Group['Name'],
171
-          'GroupTitle2' => $Group['Title2'],
172
-          'GroupNameJP' => $Group['NameJP'],
173
-          'GroupYear' => $Group['Year'],
174
-          'GroupCategoryID' => $Group['CategoryID'],
175
-          'GroupCatalogueNumber' => $Group['CatalogueNumber'],
176
-          'GroupStudio' => $Group['Studio'],
177
-          'GroupSeries' => $Group['Series'],
213
+          'id' => $Group['id'],
214
+          'title' => $Group['title'],
215
+          'subject' => $Group['subject'],
216
+          'object' => $Group['object'],
217
+          'published' => $Group['published'],
218
+          'category_id' => $Group['category_id'],
219
+          'identifier' => $Group['identifier'],
220
+          'workgroup' => $Group['workgroup'],
221
+          'location' => $Group['location'],
178 222
           'GroupFlags' => ($Group['Flags'] ?? ''),
179
-          'TagList' => $Group['TagList'],
180
-          'WikiImage' => $Group['WikiImage'],
223
+          'tag_list' => $Group['tag_list'],
224
+          'picture' => $Group['picture'],
181 225
           'Torrents' => $Group['Torrents'],
182 226
           'Artists' => $Group['Artists']
183 227
         );
@@ -231,18 +275,24 @@ class Torrents
231 275
     {
232 276
         global $Time;
233 277
         $QueryID = G::$DB->get_query_id();
234
-        G::$DB->query(
235
-            "
236
-        INSERT INTO group_log
237
-          (GroupID, TorrentID, UserID, Info, Time, Hidden)
238
-        VALUES
239
-          (?, ?, ?, ?, NOW(), ?)",
240
-            $GroupID,
241
-            $TorrentID,
242
-            $UserID,
243
-            $Message,
244
-            $Hidden
245
-        );
278
+        G::$DB->query("
279
+        INSERT INTO `group_log`(
280
+          `GroupID`,
281
+          `TorrentID`,
282
+          `UserID`,
283
+          `Info`,
284
+          `Time`,
285
+          `Hidden`
286
+        )
287
+        VALUES(
288
+          '$GroupID',
289
+          '$TorrentID',
290
+          '$UserID',
291
+          '$Message',
292
+          NOW(),
293
+          '$Hidden'
294
+        )
295
+        ");
246 296
         G::$DB->set_query_id($QueryID);
247 297
     }
248 298
 
@@ -372,10 +422,15 @@ class Torrents
372 422
         Misc::write_log("Group $GroupID automatically deleted (No torrents have this group).");
373 423
 
374 424
         G::$DB->query("
375
-        SELECT CategoryID
376
-        FROM torrents_group
377
-          WHERE ID = ?", $GroupID);
425
+        SELECT
426
+          `category_id`
427
+        FROM
428
+          `torrents_group`
429
+        WHERE
430
+          `id` = '$GroupID'
431
+        ");
378 432
         list($Category) = G::$DB->next_record();
433
+
379 434
         if ($Category == 1) {
380 435
             G::$Cache->decrement('stats_album_count');
381 436
         }
@@ -460,14 +515,21 @@ class Torrents
460 515
         Comments::delete_page('torrents', $GroupID);
461 516
 
462 517
         G::$DB->query("
463
-        DELETE FROM torrents_group
464
-          WHERE ID = ?", $GroupID);
518
+        DELETE
519
+        FROM
520
+          `torrents_group`
521
+        WHERE
522
+          `id` = '$GroupID'
523
+        ");
524
+
465 525
         G::$DB->query("
466 526
         DELETE FROM torrents_tags
467 527
           WHERE GroupID = ?", $GroupID);
528
+
468 529
         G::$DB->query("
469 530
         DELETE FROM bookmarks_torrents
470 531
           WHERE GroupID = ?", $GroupID);
532
+
471 533
         G::$DB->query("
472 534
         DELETE FROM wiki_torrents
473 535
           WHERE PageID = ?", $GroupID);
@@ -488,15 +550,28 @@ class Torrents
488 550
         $QueryID = G::$DB->get_query_id();
489 551
 
490 552
         G::$DB->query("
491
-        UPDATE torrents_group
492
-        SET TagList = (
493
-          SELECT REPLACE(GROUP_CONCAT(tags.Name SEPARATOR ' '), '.', '_')
494
-          FROM torrents_tags AS t
495
-            INNER JOIN tags ON tags.ID = t.TagID
496
-          WHERE t.GroupID = ?
497
-          GROUP BY t.GroupID
553
+        UPDATE
554
+          `torrents_group`
555
+        SET
556
+          `tag_list` =(
557
+          SELECT
558
+          REPLACE
559
+            (
560
+              GROUP_CONCAT(tags.Name SEPARATOR ' '),
561
+              '.',
562
+              '_'
563
+            )
564
+          FROM
565
+            `torrents_tags` AS t
566
+          INNER JOIN `tags` ON tags.`ID` = t.`TagID`
567
+          WHERE
568
+            t.`GroupID` = '$GroupID'
569
+          GROUP BY
570
+            t.`GroupID`
498 571
         )
499
-          WHERE ID = ?", $GroupID, $GroupID);
572
+        WHERE
573
+          `ID` = '$GroupID'
574
+        ");
500 575
 
501 576
         // Fetch album artists
502 577
         G::$DB->query("
@@ -512,19 +587,76 @@ class Torrents
512 587
         }
513 588
 
514 589
         G::$DB->query("
515
-        REPLACE INTO sphinx_delta
516
-          (ID, GroupID, GroupName, GroupTitle2, GroupNameJP, TagList, Year, CatalogueNumber, CategoryID, Time,
517
-          Size, Snatched, Seeders, Leechers, Censored, Studio, Series,
518
-          FreeTorrent, Media, Container, Codec, Resolution, Version, Description,
519
-          FileList, ArtistName)
590
+        REPLACE
591
+        INTO sphinx_delta(
592
+          `ID`,
593
+          `GroupID`,
594
+          `GroupName`,
595
+          `GroupTitle2`,
596
+          `GroupNameJP`,
597
+          `TagList`,
598
+          `Year`,
599
+          `CatalogueNumber`,
600
+          `CategoryID`,
601
+          `Time`,
602
+          `Size`,
603
+          `Snatched`,
604
+          `Seeders`,
605
+          `Leechers`,
606
+          `Censored`,
607
+          `Studio`,
608
+          `Series`,
609
+          `FreeTorrent`,
610
+          `Media`,
611
+          `Container`,
612
+          `Codec`,
613
+          `Resolution`,
614
+          `Version`,
615
+          `Description`,
616
+          `FileList`,
617
+          `ArtistName`
618
+        )
520 619
         SELECT
521
-          t.ID, g.ID, Name, Title2, NameJP, TagList, Year, CatalogueNumber, CategoryID, UNIX_TIMESTAMP(t.Time),
522
-          Size, Snatched, Seeders, Leechers, Censored, Studio, Series,
523
-          CAST(FreeTorrent AS CHAR), Media, Container, Codec, Resolution, Version, Description,
524
-          REPLACE(REPLACE(FileList, '_', ' '), '/', ' ') AS FileList, ?
525
-        FROM torrents AS t
526
-          JOIN torrents_group AS g ON g.ID = t.GroupID
527
-          WHERE g.ID = ?", $ArtistName, $GroupID);
620
+          t.`ID`,
621
+          g.`id`,
622
+          `Name`,
623
+          `Title2`,
624
+          `NameJP`,
625
+          `TagList`,
626
+          `Year`,
627
+          `CatalogueNumber`,
628
+          `CategoryID`,
629
+          UNIX_TIMESTAMP(t.`Time`),
630
+          `Size`,
631
+          `Snatched`,
632
+          `Seeders`,
633
+          `Leechers`,
634
+          `Censored`,
635
+          `Studio`,
636
+          `Series`,
637
+          CAST(`FreeTorrent` AS CHAR),
638
+          `Media`,
639
+          `Container`,
640
+          `Codec`,
641
+          `Resolution`,
642
+          `Version`,
643
+          `Description`,
644
+        REPLACE
645
+          (
646
+        REPLACE
647
+          (`FileList`, '_', ' '),
648
+          '/',
649
+          ' '
650
+        ) AS FileList,
651
+        '$ArtistName'
652
+        FROM
653
+          `torrents` AS t
654
+        JOIN `torrents_group` AS g
655
+        ON
656
+          g.`id` = t.`GroupID`
657
+        WHERE
658
+          g.`id` = '$GroupID'
659
+        ");
528 660
 
529 661
         G::$Cache->delete_value("torrents_details_$GroupID");
530 662
         G::$Cache->delete_value("torrent_group_$GroupID");

+ 176
- 89
classes/userrank.class.php View File

@@ -1,133 +1,211 @@
1 1
 <?php
2
-#declare(strict_types=1);
2
+declare(strict_types=1);
3 3
 
4 4
 class UserRank
5 5
 {
6
-    const PREFIX = 'percentiles_'; // Prefix for memcache keys, to make life easier
6
+    # Prefix for memcache keys, to make life easier
7
+    const PREFIX = 'percentiles_';
7 8
 
8
-    // Returns a 101 row array (101 percentiles - 0 - 100), with the minimum value for that percentile as the value for each row
9
-    // BTW - ingenious
9
+
10
+    /**
11
+     * Returns a 101 row array (101 percentiles: 0-100),
12
+     * with the minimum value for that percentile as the value for each row.
13
+     *
14
+     * BTW - ingenious
15
+     */
10 16
     private static function build_table($MemKey, $Query)
11 17
     {
12 18
         $QueryID = G::$DB->get_query_id();
13 19
 
14 20
         G::$DB->query("
15
-        DROP TEMPORARY TABLE IF EXISTS temp_stats");
21
+        DROP TEMPORARY TABLE IF EXISTS
22
+          `temp_stats`
23
+        ");
16 24
 
17 25
         G::$DB->query("
18
-        CREATE TEMPORARY TABLE temp_stats (
19
-          ID int(10) NOT NULL PRIMARY KEY AUTO_INCREMENT,
20
-          Val bigint(20) NOT NULL
21
-        );");
26
+        CREATE TEMPORARY TABLE `temp_stats`(
27
+          `id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
28
+          `value` BIGINT NOT NULL
29
+        );
30
+        ");
22 31
 
23 32
         G::$DB->query("
24
-        INSERT INTO temp_stats (Val) ".
25
-        $Query);
33
+        INSERT INTO `temp_stats`(`value`) "
34
+        . $Query
35
+        );
26 36
 
27 37
         G::$DB->query("
28
-        SELECT COUNT(ID)
29
-        FROM temp_stats");
38
+        SELECT
39
+          COUNT(`id`)
40
+        FROM
41
+          `temp_stats`
42
+        ");
30 43
         list($UserCount) = G::$DB->next_record();
31 44
 
45
+        $UserCount = (int) $UserCount;
32 46
         G::$DB->query("
33
-        SELECT MIN(Val)
34
-        FROM temp_stats
35
-          GROUP BY CEIL(ID / (".(int)$UserCount." / 100));");
47
+        SELECT
48
+          MIN(`value`)
49
+        FROM
50
+          `temp_stats`
51
+        GROUP BY
52
+          CEIL(`id` /($UserCount / 100));
53
+        ");
36 54
 
37 55
         $Table = G::$DB->to_array();
38 56
         G::$DB->set_query_id($QueryID);
39 57
 
40
-        // Give a little variation to the cache length, so all the tables don't expire at the same time
58
+        # Give a little variation to the cache length, so all the tables don't expire at the same time
41 59
         G::$Cache->cache_value($MemKey, $Table, 3600 * 24 * rand(800, 1000) * 0.001);
42 60
 
43 61
         return $Table;
44 62
     }
45 63
 
64
+
65
+    /**
66
+     * table_query
67
+     */
46 68
     private static function table_query($TableName)
47 69
     {
48 70
         switch ($TableName) {
49
-        case 'uploaded':
50
-          $Query =  "
51
-          SELECT Uploaded
52
-          FROM users_main
53
-          WHERE Enabled = '1'
54
-            AND Uploaded > 0
55
-          ORDER BY Uploaded;";
56
-          break;
57
-
58
-        case 'downloaded':
59
-          $Query =  "
60
-          SELECT Downloaded
61
-          FROM users_main
62
-          WHERE Enabled = '1'
63
-            AND Downloaded > 0
64
-          ORDER BY Downloaded;";
65
-          break;
66
-
67
-        case 'uploads':
68
-          $Query = "
69
-          SELECT COUNT(t.ID) AS Uploads
70
-          FROM users_main AS um
71
-            JOIN torrents AS t ON t.UserID = um.ID
72
-          WHERE um.Enabled = '1'
73
-          GROUP BY um.ID
74
-          ORDER BY Uploads;";
75
-          break;
76
-
77
-        case 'requests':
78
-          $Query = "
79
-          SELECT COUNT(r.ID) AS Requests
80
-          FROM users_main AS um
81
-            JOIN requests AS r ON r.FillerID = um.ID
82
-          WHERE um.Enabled = '1'
83
-          GROUP BY um.ID
84
-          ORDER BY Requests;";
85
-          break;
86
-
87
-        case 'posts':
88
-          $Query = "
89
-          SELECT COUNT(p.ID) AS Posts
90
-          FROM users_main AS um
91
-            JOIN forums_posts AS p ON p.AuthorID = um.ID
92
-          WHERE um.Enabled = '1'
93
-          GROUP BY um.ID
94
-          ORDER BY Posts;";
95
-          break;
96
-
97
-        case 'bounty':
98
-          $Query = "
99
-          SELECT SUM(rv.Bounty) AS Bounty
100
-          FROM users_main AS um
101
-            JOIN requests_votes AS rv ON rv.UserID = um.ID
102
-          WHERE um.Enabled = '1' " .
103
-          "GROUP BY um.ID
104
-          ORDER BY Bounty;";
105
-          break;
106
-
107
-        case 'artists':
108
-          $Query = "
109
-          SELECT COUNT(ta.ArtistID) AS Artists
110
-          FROM torrents_artists AS ta
111
-            JOIN torrents_group AS tg ON tg.ID = ta.GroupID
112
-            JOIN torrents AS t ON t.GroupID = tg.ID
113
-          WHERE t.UserID != ta.UserID
114
-          GROUP BY tg.ID
115
-          ORDER BY Artists ASC";
116
-          break;
71
+            case 'uploaded':
72
+            $Query =  "
73
+            SELECT
74
+              `Uploaded`
75
+            FROM
76
+              `users_main`
77
+            WHERE
78
+              `Enabled` = '1' AND `Uploaded` > 0
79
+            ORDER BY
80
+              `Uploaded`;
81
+            ";
82
+            break;
83
+
84
+            case 'downloaded':
85
+            $Query =  "
86
+            SELECT
87
+              `Downloaded`
88
+            FROM
89
+              `users_main`
90
+            WHERE
91
+              `Enabled` = '1' AND `Downloaded` > 0
92
+            ORDER BY
93
+              `Downloaded`;
94
+            ";
95
+            break;
96
+
97
+            case 'uploads':
98
+            $Query = "
99
+            SELECT
100
+              COUNT(t.`ID`) AS `Uploads`
101
+            FROM
102
+              `users_main` AS um
103
+            JOIN `torrents` AS t
104
+            ON
105
+              t.`UserID` = um.`ID`
106
+            WHERE
107
+              um.`Enabled` = '1'
108
+            GROUP BY
109
+              um.`ID`
110
+            ORDER BY
111
+              `Uploads`;
112
+            ";
113
+            break;
114
+
115
+            case 'requests':
116
+            $Query = "
117
+            SELECT
118
+              COUNT(r.`ID`) AS `Requests`
119
+            FROM
120
+              `users_main` AS um
121
+            JOIN `requests` AS r
122
+            ON
123
+              r.`FillerID` = um.`ID`
124
+            WHERE
125
+              um.`Enabled` = '1'
126
+            GROUP BY
127
+              um.`ID`
128
+            ORDER BY
129
+              `Requests`;
130
+            ";
131
+            break;
132
+
133
+            case 'posts':
134
+            $Query = "
135
+            SELECT
136
+              COUNT(p.`ID`) AS `Posts`
137
+            FROM
138
+              `users_main` AS um
139
+            JOIN `forums_posts` AS p
140
+            ON
141
+              p.`AuthorID` = um.`ID`
142
+            WHERE
143
+              um.`Enabled` = '1'
144
+            GROUP BY
145
+              um.`ID`
146
+            ORDER BY
147
+              `Posts`;
148
+            ";
149
+            break;
150
+
151
+            case 'bounty':
152
+            $Query = "
153
+            SELECT
154
+              SUM(rv.`Bounty`) AS `Bounty`
155
+            FROM
156
+              `users_main` AS um
157
+            JOIN `requests_votes` AS rv
158
+            ON
159
+              rv.`UserID` = um.`ID`
160
+            WHERE
161
+              um.`Enabled` = '1'
162
+            GROUP BY
163
+              um.`ID`
164
+            ORDER BY
165
+              `Bounty`;
166
+            ";
167
+            break;
168
+
169
+            case 'artists':
170
+            $Query = "
171
+            SELECT
172
+              COUNT(ta.`ArtistID`) AS `Artists`
173
+            FROM
174
+              `torrents_artists` AS ta
175
+            JOIN `torrents_group` AS tg
176
+            ON
177
+              tg.`id` = ta.`GroupID`
178
+            JOIN `torrents` AS t
179
+            ON
180
+              t.`GroupID` = tg.`id`
181
+            WHERE
182
+              t.`UserID` != ta.`UserID`
183
+            GROUP BY
184
+              tg.`id`
185
+            ORDER BY
186
+              `Artists` ASC
187
+            ";
188
+            break;
117 189
         }
190
+
118 191
         return $Query;
119 192
     }
120 193
 
194
+
195
+    /**
196
+     * get_rank
197
+     */
121 198
     public static function get_rank($TableName, $Value)
122 199
     {
123
-        if ($Value == 0) {
200
+        if ($Value === 0) {
124 201
             return 0;
125 202
         }
126 203
 
127 204
         $Table = G::$Cache->get_value(self::PREFIX.$TableName);
128 205
         if (!$Table) {
129
-            //Cache lock!
206
+            # Cache lock!
130 207
             $Lock = G::$Cache->get_value(self::PREFIX.$TableName.'_lock');
208
+
131 209
             if ($Lock) {
132 210
                 return false;
133 211
             } else {
@@ -140,17 +218,25 @@ class UserRank
140 218
         $LastPercentile = 0;
141 219
         foreach ($Table as $Row) {
142 220
             list($CurValue) = $Row;
221
+
143 222
             if ($CurValue >= $Value) {
144 223
                 return $LastPercentile;
145 224
             }
225
+
146 226
             $LastPercentile++;
147 227
         }
148
-        return 100; // 100th percentile
228
+
229
+        # 100th percentile
230
+        return 100;
149 231
     }
150 232
 
233
+
234
+    /**
235
+     * overall_score
236
+     */
151 237
     public static function overall_score($Uploaded, $Downloaded, $Uploads, $Requests, $Posts, $Bounty, $Artists, $Ratio)
152 238
     {
153
-        // We can do this all in 1 line, but it's easier to read this way
239
+        # We can do this all in 1 line, but it's easier to read this way
154 240
         if ($Ratio > 1) {
155 241
             $Ratio = 1;
156 242
         }
@@ -169,6 +255,7 @@ class UserRank
169 255
         $TotalScore += $Artists;
170 256
         $TotalScore /= (15 + 8 + 25 + 2 + 1 + 1 + 1);
171 257
         $TotalScore *= $Ratio;
258
+        
172 259
         return $TotalScore;
173 260
     }
174 261
 }

+ 1
- 7
classes/users.class.php View File

@@ -457,10 +457,9 @@ class Users
457 457
      * @param boolean $IsEnabled
458 458
      * @param boolean $Class whether or not to show the class
459 459
      * @param boolean $Title whether or not to show the title
460
-     * @param boolean $IsDonorForum for displaying donor forum honorific prefixes and suffixes
461 460
      * @return HTML formatted username
462 461
      */
463
-    public static function format_username($UserID, $Badges = false, $IsWarned = true, $IsEnabled = true, $Class = false, $Title = false, $IsDonorForum = false)
462
+    public static function format_username($UserID, $Badges = false, $IsWarned = true, $IsEnabled = true, $Class = false, $Title = false)
464 463
     {
465 464
         global $Classes;
466 465
 
@@ -490,11 +489,6 @@ class Users
490 489
         # Show donor icon?
491 490
         $ShowDonorIcon = (!in_array('hide_donor_heart', $Paranoia) || $OverrideParanoia);
492 491
 
493
-        if ($IsDonorForum) {
494
-            list($Prefix, $Suffix, $HasComma) = Donations::get_titles($UserID);
495
-            $Username = "$Prefix $Username" . ($HasComma ? ', ' : ' ') . "$Suffix ";
496
-        }
497
-
498 492
         if ($Title) {
499 493
             $Str .= "<strong><a href='user.php?id=$UserID'>$Username</a></strong>";
500 494
         } else {

+ 0
- 1
classes/vendor/Parsedown.php View File

@@ -1,5 +1,4 @@
1 1
 <?php
2
-#declare(strict_types=1);
3 2
 
4 3
 #
5 4
 #

+ 1
- 2
classes/vendor/ParsedownExtra.php View File

@@ -1,5 +1,4 @@
1 1
 <?php
2
-#declare(strict_types=1);
3 2
 
4 3
 #
5 4
 #
@@ -370,7 +369,7 @@ class ParsedownExtra extends Parsedown
370 369
 
371 370
             if ( ! isset($this->DefinitionData['Footnote'][$name]['number']))
372 371
             {
373
-                $this->DefinitionData['Footnote'][$name]['number'] = ++ $this->footnoteCount; # &raquo; &
372
+                $this->DefinitionData['Footnote'][$name]['number'] = ++ $this->footnoteCount; # » &
374 373
             }
375 374
 
376 375
             $Element = array(

+ 0
- 1
classes/vendor/TwitterAPIExchange.php View File

@@ -1,5 +1,4 @@
1 1
 <?php
2
-#declare(strict_types=1);
3 2
 
4 3
 /**
5 4
  * Twitter-API-PHP : Simple PHP wrapper for the v1.1 API

+ 1
- 0
design/privateheader.php View File

@@ -49,6 +49,7 @@ $Styles = array_filter(
49 49
     array_merge(
50 50
         [
51 51
           'vendor/jquery-ui.min',
52
+          'vendor/normalize',
52 53
           #'assets/fonts/fa/css/all.min',
53 54
           'global'
54 55
         ],

+ 1
- 1
design/publicheader.php View File

@@ -41,7 +41,7 @@ foreach ($Scripts as $Script) {
41 41
 }
42 42
 
43 43
 # Load CSS
44
-$Styles = ['global', 'public'];
44
+$Styles = ['vendor/normalize', 'global', 'public'];
45 45
 foreach ($Styles as $Style) {
46 46
     echo View::pushAsset(
47 47
         "$ENV->STATIC_SERVER/styles/$Style.css",

+ 168
- 26
gazelle.sql
File diff suppressed because it is too large
View File


+ 17
- 15
sections/ajax/artist.php View File

@@ -134,22 +134,24 @@ if (empty($LoggedUser['DisableRequests'])) {
134 134
 $NumRequests = count($Requests);
135 135
 
136 136
 if (($Importances = $Cache->get_value("artist_groups_$ArtistID")) === false) {
137
-    /*
138 137
     $DB->query("
139
-      SELECT
140
-        DISTINCTROW ta.GroupID, ta.Importance, tg.VanityHouse, tg.Year
141
-      FROM torrents_artists AS ta
142
-        JOIN torrents_group AS tg ON tg.ID = ta.GroupID
143
-      WHERE ta.ArtistID = '$ArtistID'
144
-      ORDER BY tg.Year DESC, tg.Name DESC");
145
-    */
146
-    $DB->query("
147
-    SELECT
148
-      DISTINCTROW ta.GroupID, ta.Importance, tg.Year
149
-    FROM torrents_artists AS ta
150
-      JOIN torrents_group AS tg ON tg.ID = ta.GroupID
151
-    WHERE ta.ArtistID = '$ArtistID'
152
-    ORDER BY tg.Year DESC, tg.Name DESC");
138
+    SELECT DISTINCTROW
139
+      ta.`GroupID`,
140
+      ta.`Importance`,
141
+      tg.`published`
142
+    FROM
143
+      `torrents_artists` AS ta
144
+    JOIN `torrents_group` AS tg
145
+    ON
146
+      tg.`id` = ta.`GroupID`
147
+    WHERE
148
+      ta.`ArtistID` = '$ArtistID'
149
+    ORDER BY
150
+      tg.`published`,
151
+      tg.`Name`
152
+    DESC
153
+    ");
154
+    
153 155
     $GroupIDs = $DB->collect('GroupID');
154 156
     $Importances = $DB->to_array(false, MYSQLI_BOTH, false);
155 157
     $Cache->cache_value("artist_groups_$ArtistID", $Importances, 0);

+ 41
- 42
sections/ajax/index.php View File

@@ -86,181 +86,180 @@ switch ($_GET['action']) {
86 86
    * Torrents
87 87
    */
88 88
   case 'torrent':
89
-    require 'torrent.php';
89
+    require_once 'torrent.php';
90 90
     break;
91 91
 
92 92
   case 'torrentgroup':
93
-    require 'torrentgroup.php';
93
+    require_once 'torrentgroup.php';
94 94
     break;
95 95
 
96 96
   // So the album art script can function without breaking the rate limit
97 97
   case 'torrentgroupalbumart':
98
-    require SERVER_ROOT.'/sections/ajax/torrentgroupalbumart.php';
98
+    require_once SERVER_ROOT.'/sections/ajax/torrentgroupalbumart.php';
99 99
     break;
100 100
 
101 101
   case 'browse':
102
-    require SERVER_ROOT.'/sections/ajax/browse.php';
102
+    require_once SERVER_ROOT.'/sections/ajax/browse.php';
103 103
     break;
104 104
   
105 105
    case 'tcomments':
106
-    require SERVER_ROOT.'/sections/ajax/tcomments.php';
106
+    require_once SERVER_ROOT.'/sections/ajax/tcomments.php';
107 107
     break;
108 108
 
109 109
   /**
110 110
    * Features
111 111
    */
112 112
   case 'collage':
113
-    require SERVER_ROOT.'/sections/ajax/collage.php';
113
+    require_once SERVER_ROOT.'/sections/ajax/collage.php';
114 114
     break;
115 115
   
116 116
   case 'artist':
117
-    require SERVER_ROOT.'/sections/ajax/artist.php';
117
+    require_once SERVER_ROOT.'/sections/ajax/artist.php';
118 118
     break;
119 119
 
120 120
   case 'request':
121
-    require SERVER_ROOT.'/sections/ajax/request.php';
121
+    require_once SERVER_ROOT.'/sections/ajax/request.php';
122 122
     break;
123 123
 
124 124
   case 'requests':
125
-    require SERVER_ROOT.'/sections/ajax/requests.php';
125
+    require_once SERVER_ROOT.'/sections/ajax/requests.php';
126 126
     break;
127 127
 
128 128
   case 'top10':
129
-    require SERVER_ROOT.'/sections/ajax/top10/index.php';
129
+    require_once SERVER_ROOT.'/sections/ajax/top10/index.php';
130 130
     break;
131 131
 
132 132
   /**
133 133
    * Users
134 134
    */
135 135
   case 'user':
136
-    require SERVER_ROOT.'/sections/ajax/user.php';
136
+    require_once SERVER_ROOT.'/sections/ajax/user.php';
137 137
     break;
138 138
 
139 139
   case 'usersearch':
140
-    require SERVER_ROOT.'/sections/ajax/usersearch.php';
140
+    require_once SERVER_ROOT.'/sections/ajax/usersearch.php';
141 141
     break;
142 142
   
143 143
   case 'community_stats':
144
-    require SERVER_ROOT.'/sections/ajax/community_stats.php';
144
+    require_once SERVER_ROOT.'/sections/ajax/community_stats.php';
145 145
     break;
146 146
 
147 147
   case 'user_recents':
148
-    require SERVER_ROOT.'/sections/ajax/user_recents.php';
148
+    require_once SERVER_ROOT.'/sections/ajax/user_recents.php';
149 149
     break;
150 150
 
151 151
   case 'userhistory':
152
-    require SERVER_ROOT.'/sections/ajax/userhistory/index.php';
152
+    require_once SERVER_ROOT.'/sections/ajax/userhistory/index.php';
153 153
     break;
154 154
 
155 155
   /**
156 156
    * Account
157 157
    */
158 158
   case 'inbox':
159
-    require SERVER_ROOT.'/sections/ajax/inbox/index.php';
159
+    require_once SERVER_ROOT.'/sections/ajax/inbox/index.php';
160 160
     break;
161 161
 
162 162
   case 'bookmarks':
163
-    require SERVER_ROOT.'/sections/ajax/bookmarks/index.php';
163
+    require_once SERVER_ROOT.'/sections/ajax/bookmarks/index.php';
164 164
     break;
165 165
 
166 166
   case 'notifications':
167
-    require SERVER_ROOT.'/sections/ajax/notifications.php';
167
+    require_once SERVER_ROOT.'/sections/ajax/notifications.php';
168 168
     break;
169 169
 
170 170
   case 'get_user_notifications':
171
-    require SERVER_ROOT.'/sections/ajax/get_user_notifications.php';
171
+    require_once SERVER_ROOT.'/sections/ajax/get_user_notifications.php';
172 172
     break;
173 173
 
174 174
   case 'clear_user_notification':
175
-    require SERVER_ROOT.'/sections/ajax/clear_user_notification.php';
175
+    require_once SERVER_ROOT.'/sections/ajax/clear_user_notification.php';
176 176
     break;
177 177
 
178 178
   /**
179 179
    * Forums
180 180
    */
181 181
   case 'forum':
182
-    require SERVER_ROOT.'/sections/ajax/forum/index.php';
182
+    require_once SERVER_ROOT.'/sections/ajax/forum/index.php';
183 183
     break;
184 184
 
185
-
186 185
   case 'subscriptions':
187
-    require SERVER_ROOT.'/sections/ajax/subscriptions.php';
186
+    require_once SERVER_ROOT.'/sections/ajax/subscriptions.php';
188 187
     break;
189 188
 
190 189
   case 'raw_bbcode':
191
-    require SERVER_ROOT.'/sections/ajax/raw_bbcode.php';
190
+    require_once SERVER_ROOT.'/sections/ajax/raw_bbcode.php';
192 191
     break;
193 192
 
194 193
   /**
195 194
    * Meta
196 195
    */
197 196
   case 'index':
198
-    require SERVER_ROOT.'/sections/ajax/info.php';
197
+    require_once SERVER_ROOT.'/sections/ajax/info.php';
199 198
     break;
200 199
 
201 200
   case 'manifest':
202
-    require SERVER_ROOT.'/manifest.php';
201
+    require_once SERVER_ROOT.'/manifest.php';
203 202
     json_die('success', manifest());
204 203
     break;
205 204
 
206 205
   case 'stats':
207
-    require SERVER_ROOT.'/sections/ajax/stats.php';
206
+    require_once SERVER_ROOT.'/sections/ajax/stats.php';
208 207
     break;
209 208
 
210 209
   case 'loadavg':
211
-    require SERVER_ROOT.'/sections/ajax/loadavg.php';
210
+    require_once SERVER_ROOT.'/sections/ajax/loadavg.php';
212 211
     break;
213 212
 
214 213
   case 'announcements':
215
-    require SERVER_ROOT.'/sections/ajax/announcements.php';
214
+    require_once SERVER_ROOT.'/sections/ajax/announcements.php';
216 215
     break;
217 216
 
218 217
   case 'wiki':
219
-    require SERVER_ROOT.'/sections/ajax/wiki.php';
218
+    require_once SERVER_ROOT.'/sections/ajax/wiki.php';
220 219
     break;
221 220
   
222 221
   case 'ontology':
223
-    require SERVER_ROOT.'/sections/ajax/ontology.php';
222
+    require_once SERVER_ROOT.'/sections/ajax/ontology.php';
224 223
     break;
225 224
   
226 225
   /**
227 226
    * Under construction
228 227
    */
229 228
   case 'preview':
230
-    require 'preview.php';
229
+    require_once 'preview.php';
231 230
     break;
232 231
 
233 232
   case 'better':
234
-    require SERVER_ROOT.'/sections/ajax/better/index.php';
233
+    require_once SERVER_ROOT.'/sections/ajax/better/index.php';
235 234
     break;
236 235
 
237 236
   case 'get_friends':
238
-    require SERVER_ROOT.'/sections/ajax/get_friends.php';
237
+    require_once SERVER_ROOT.'/sections/ajax/get_friends.php';
239 238
     break;
240 239
 
241 240
   case 'news_ajax':
242
-    require SERVER_ROOT.'/sections/ajax/news_ajax.php';
241
+    require_once SERVER_ROOT.'/sections/ajax/news_ajax.php';
243 242
     break;
244 243
 
245 244
   case 'send_recommendation':
246
-    require SERVER_ROOT.'/sections/ajax/send_recommendation.php';
245
+    require_once SERVER_ROOT.'/sections/ajax/send_recommendation.php';
247 246
     break;
248 247
 
249 248
   /*
250 249
   case 'similar_artists':
251
-    require SERVER_ROOT.'/sections/ajax/similar_artists.php';
250
+    require_once SERVER_ROOT.'/sections/ajax/similar_artists.php';
252 251
     break;
253 252
   */
254 253
 
255 254
   /*
256 255
   case 'votefavorite':
257
-    require SERVER_ROOT.'/sections/ajax/takevote.php';
256
+    require_once SERVER_ROOT.'/sections/ajax/takevote.php';
258 257
     break;
259 258
   */
260 259
 
261 260
   /*
262 261
   case 'torrent_info':
263
-    require 'torrent_info.php';
262
+    require_once 'torrent_info.php';
264 263
     break;
265 264
   */
266 265
 
@@ -273,15 +272,15 @@ switch ($_GET['action']) {
273 272
   case 'autofill':
274 273
     /*
275 274
     if ($_GET['cat'] === 'anime') {
276
-        require SERVER_ROOT.'/sections/ajax/autofill/anime.php';
275
+        require_once SERVER_ROOT.'/sections/ajax/autofill/anime.php';
277 276
     }
278 277
 
279 278
     if ($_GET['cat'] === 'jav') {
280
-        require SERVER_ROOT.'/sections/ajax/autofill/jav.php';
279
+        require_once SERVER_ROOT.'/sections/ajax/autofill/jav.php';
281 280
     }
282 281
 
283 282
     if ($_GET['cat'] === 'manga') {
284
-        require SERVER_ROOT.'/sections/ajax/autofill/manga.php';
283
+        require_once SERVER_ROOT.'/sections/ajax/autofill/manga.php';
285 284
     }
286 285
     */
287 286
     break;

+ 1
- 1
sections/ajax/loadavg.php View File

@@ -1,5 +1,5 @@
1 1
 <?php
2
-#declare(strict_types=1);
2
+declare(strict_types=1);
3 3
 
4 4
 #authorize();
5 5
 

+ 46
- 23
sections/ajax/send_recommendation.php View File

@@ -1,25 +1,32 @@
1 1
 <?php
2 2
 #declare(strict_types=1);
3 3
 
4
-$FriendID = (int)$_POST['friend'];
4
+$FriendID = (int) $_POST['friend'];
5 5
 $Type = $_POST['type'];
6
-$ID = (int)$_POST['id'];
6
+$ID = (int) $_POST['id'];
7 7
 $Note = $_POST['note'];
8 8
 
9 9
 if (empty($FriendID) || empty($Type) || empty($ID)) {
10 10
     echo json_encode(array('status' => 'error', 'response' => 'Error.'));
11 11
     error();
12 12
 }
13
+
13 14
 // Make sure the recipient is on your friends list and not some random dude.
14 15
 $DB->query("
15
-  SELECT f.FriendID, u.Username
16
-  FROM friends AS f
17
-    RIGHT JOIN users_enable_recommendations AS r
18
-      ON r.ID = f.FriendID AND r.Enable = 1
19
-    RIGHT JOIN users_main AS u
20
-      ON u.ID = f.FriendID
21
-  WHERE f.UserID = '$LoggedUser[ID]'
22
-    AND f.FriendID = '$FriendID'");
16
+SELECT
17
+  f.`FriendID`,
18
+  u.`Username`
19
+FROM
20
+  `friends` AS f
21
+RIGHT JOIN `users_enable_recommendations` AS r
22
+ON
23
+  r.`ID` = f.`FriendID` AND r.`Enable` = 1
24
+RIGHT JOIN `users_main` AS u
25
+ON
26
+  u.`ID` = f.`FriendID`
27
+WHERE
28
+  f.`UserID` = '$LoggedUser[ID]' AND f.`FriendID` = '$FriendID'
29
+");
23 30
 
24 31
 if (!$DB->has_results()) {
25 32
     echo json_encode(array('status' => 'error', 'response' => 'Not on friend list.'));
@@ -32,32 +39,48 @@ $Link = '';
32 39
 // https://en.wikipedia.org/wiki/English_articles#Distinction_between_a_and_an
33 40
 $Article = 'a';
34 41
 switch ($Type) {
35
-  case 'torrent':
42
+    case 'torrent':
36 43
     $Link = "torrents.php?id=$ID";
37 44
     $DB->query("
38
-      SELECT Name
39
-      FROM torrents_group
40
-      WHERE ID = '$ID'");
41
-    break;
42
-  case 'artist':
45
+    SELECT
46
+      `title`
47
+    FROM
48
+      `torrents_group`
49
+    WHERE
50
+      `id` = '$ID'
51
+    ");
52
+      break;
53
+
54
+    case 'artist':
43 55
     $Article = 'an';
44 56
     $Link = "artist.php?id=$ID";
45 57
     $DB->query("
46
-      SELECT Name
47
-      FROM artists_group
48
-      WHERE ArtistID = '$ID'");
58
+    SELECT
59
+      `Name`
60
+    FROM
61
+      `artists_group`
62
+    WHERE
63
+      `ArtistID` = '$ID'
64
+    ");
49 65
     break;
50
-  case 'collage':
66
+
67
+    case 'collage':
51 68
     $Link = "collages.php?id=$ID";
52 69
     $DB->query("
53
-      SELECT Name
54
-      FROM collages
55
-      WHERE ID = '$ID'");
70
+    SELECT
71
+      `Name`
72
+    FROM
73
+      `collages`
74
+    WHERE
75
+      `ID` = '$ID'
76
+    ");
56 77
     break;
57 78
 }
79
+
58 80
 list($Name) = $DB->next_record();
59 81
 $Subject = $LoggedUser['Username'] . " recommended you $Article $Type!";
60 82
 $Body = $LoggedUser['Username'] . " recommended you the $Type [url=".site_url()."$Link]$Name".'[/url].';
83
+
61 84
 if (!empty($Note)) {
62 85
     $Body = "$Body\n\n$Note";
63 86
 }

+ 5
- 3
sections/ajax/stats.php View File

@@ -1,5 +1,5 @@
1 1
 <?php
2
-#declare(strict_types=1);
2
+declare(strict_types=1);
3 3
 
4 4
 // Begin user stats
5 5
 if (($UserCount = $Cache->get_value('stats_user_count')) === false) {
@@ -67,12 +67,13 @@ if (($TorrentCount = $Cache->get_value('stats_torrent_count')) === false) {
67 67
 if (($AlbumCount = $Cache->get_value('stats_album_count')) === false) {
68 68
     $DB->query("
69 69
     SELECT
70
-      COUNT(`ID`)
70
+      COUNT(`id`)
71 71
     FROM
72 72
       `torrents_group`
73 73
     WHERE
74
-      `CategoryID` = '1'
74
+      `category_id` = '1'
75 75
     ");
76
+
76 77
     list($AlbumCount) = $DB->next_record();
77 78
     $Cache->cache_value('stats_album_count', $AlbumCount, 604830); // staggered 1 week cache
78 79
 }
@@ -84,6 +85,7 @@ if (($ArtistCount = $Cache->get_value('stats_artist_count')) === false) {
84 85
     FROM
85 86
       `artists_group`
86 87
     ");
88
+    
87 89
     list($ArtistCount) = $DB->next_record();
88 90
     $Cache->cache_value('stats_artist_count', $ArtistCount, 604860); // staggered 1 week cache
89 91
 }

+ 23
- 17
sections/ajax/top10/torrents.php View File

@@ -18,23 +18,29 @@ $Limit = isset($_GET['limit']) ? intval($_GET['limit']) : 10;
18 18
 $Limit = in_array($Limit, array(10, 100, 250)) ? $Limit : 10;
19 19
 
20 20
 $WhereSum = (empty($Where)) ? '' : md5($Where);
21
-$BaseQuery = '
22
-  SELECT
23
-    t.ID,
24
-    g.ID,
25
-    g.Name,
26
-    g.CategoryID,
27
-    g.WikiImage,
28
-    g.TagList,
29
-    t.Media,
30
-    g.Year,
31
-    t.Snatched,
32
-    t.Seeders,
33
-    t.Leechers,
34
-    ((t.Size * t.Snatched) + (t.Size * 0.5 * t.Leechers)) AS Data,
35
-    t.Size
36
-  FROM torrents AS t
37
-    LEFT JOIN torrents_group AS g ON g.ID = t.GroupID';
21
+$BaseQuery = "
22
+SELECT
23
+  t.`ID`,
24
+  g.`id`,
25
+  g.`title`,
26
+  g.`category_id`,
27
+  g.`picture`,
28
+  g.`tag_list`,
29
+  t.`Media`,
30
+  g.`published`,
31
+  t.`Snatched`,
32
+  t.`Seeders`,
33
+  t.`Leechers`,
34
+  (
35
+    (t.`Size` * t.`Snatched`) +(t.`Size` * 0.5 * t.`Leechers`)
36
+  ) AS `Data`,
37
+  t.`Size`
38
+FROM
39
+  `torrents` AS t
40
+LEFT JOIN `torrents_group` AS g
41
+ON
42
+  g.`id` = t.`GroupID`
43
+";
38 44
 
39 45
 $OuterResults = [];
40 46
 

+ 37
- 23
sections/ajax/user_recents.php View File

@@ -17,18 +17,26 @@ $Results = [];
17 17
 if (check_paranoia_here('snatched')) {
18 18
     $DB->query("
19 19
     SELECT
20
-      g.ID,
21
-      g.Name,
22
-      g.WikiImage
23
-    FROM xbt_snatched AS s
24
-      INNER JOIN torrents AS t ON t.ID = s.fid
25
-      INNER JOIN torrents_group AS g ON t.GroupID = g.ID
26
-    WHERE s.uid = '$UserID'
27
-      AND g.CategoryID = '1'
28
-      AND g.WikiImage != ''
29
-    GROUP BY g.ID
30
-    ORDER BY s.tstamp DESC
31
-    LIMIT $Limit");
20
+      g.`id`,
21
+      g.`title`,
22
+      g.`picture`
23
+    FROM
24
+      `xbt_snatched` AS s
25
+    INNER JOIN `torrents` AS t
26
+    ON
27
+      t.`ID` = s.`fid`
28
+    INNER JOIN `torrents_group` AS g
29
+    ON
30
+      t.`GroupID` = g.`id`
31
+    WHERE
32
+      s.`uid` = '$UserID' AND g.`category_id` = '1' AND g.`picture` != ''
33
+    GROUP BY
34
+      g.`id`
35
+    ORDER BY
36
+      s.`tstamp`
37
+    DESC
38
+    LIMIT $Limit
39
+    ");
32 40
 
33 41
     $RecentSnatches = $DB->to_array(false, MYSQLI_ASSOC);
34 42
     $Artists = Artists::get_artists($DB->collect('ID'));
@@ -45,17 +53,23 @@ if (check_paranoia_here('snatched')) {
45 53
 if (check_paranoia_here('uploads')) {
46 54
     $DB->query("
47 55
     SELECT
48
-      g.ID,
49
-      g.Name,
50
-      g.WikiImage
51
-    FROM torrents_group AS g
52
-      INNER JOIN torrents AS t ON t.GroupID = g.ID
53
-    WHERE t.UserID = '$UserID'
54
-      AND g.CategoryID = '1'
55
-      AND g.WikiImage != ''
56
-    GROUP BY g.ID
57
-    ORDER BY t.Time DESC
58
-    LIMIT $Limit");
56
+      g.`id`,
57
+      g.`title`,
58
+      g.`picture`
59
+    FROM
60
+      `torrents_group` AS g
61
+    INNER JOIN `torrents` AS t
62
+    ON
63
+      t.`GroupID` = g.`id`
64
+    WHERE
65
+      t.`UserID` = '$UserID' AND g.`category_id` = '1' AND g.`picture` != ''
66
+    GROUP BY
67
+      g.`id`
68
+    ORDER BY
69
+      t.`Time`
70
+    DESC
71
+    LIMIT $Limit
72
+    ");
59 73
 
60 74
     $RecentUploads = $DB->to_array(false, MYSQLI_ASSOC);
61 75
     $Artists = Artists::get_artists($DB->collect('ID'));

+ 83
- 0
sections/api/announcements.php View File

@@ -0,0 +1,83 @@
1
+<?
2
+if (!$News = $Cache->get_value('news')) {
3
+  $DB->query("
4
+    SELECT
5
+      ID,
6
+      Title,
7
+      Body,
8
+      Time
9
+    FROM news
10
+    ORDER BY Time DESC
11
+    LIMIT 5");
12
+  $News = $DB->to_array(false, MYSQLI_NUM, false);
13
+  $Cache->cache_value('news', $News, 3600 * 24 * 30);
14
+  $Cache->cache_value('news_latest_id', $News[0][0], 0);
15
+}
16
+
17
+if ($LoggedUser['LastReadNews'] != $News[0][0]) {
18
+  $Cache->begin_transaction("user_info_heavy_$UserID");
19
+  $Cache->update_row(false, array('LastReadNews' => $News[0][0]));
20
+  $Cache->commit_transaction(0);
21
+  $DB->query("
22
+    UPDATE users_info
23
+    SET LastReadNews = '".$News[0][0]."'
24
+    WHERE UserID = $UserID");
25
+  $LoggedUser['LastReadNews'] = $News[0][0];
26
+}
27
+
28
+if (($Blog = $Cache->get_value('blog')) === false) {
29
+  $DB->query("
30
+    SELECT
31
+      b.ID,
32
+      um.Username,
33
+      b.UserID,
34
+      b.Title,
35
+      b.Body,
36
+      b.Time,
37
+      b.ThreadID
38
+    FROM blog AS b
39
+      LEFT JOIN users_main AS um ON b.UserID = um.ID
40
+    ORDER BY Time DESC
41
+    LIMIT 20");
42
+  $Blog = $DB->to_array();
43
+  $Cache->cache_value('blog', $Blog, 1209600);
44
+}
45
+$JsonBlog = [];
46
+for ($i = 0; $i < 5; $i++) {
47
+  list($BlogID, $Author, $AuthorID, $Title, $Body, $BlogTime, $ThreadID) = $Blog[$i];
48
+  $JsonBlog[] = array(
49
+    'blogId' => (int)$BlogID,
50
+    'author' => $Author,
51
+    'title' => $Title,
52
+    'bbBody' => $Body,
53
+    'body' => Text::full_format($Body),
54
+    'blogTime' => $BlogTime,
55
+    'threadId' => (int)$ThreadID
56
+  );
57
+}
58
+
59
+$JsonAnnouncements = [];
60
+$Count = 0;
61
+foreach ($News as $NewsItem) {
62
+  list($NewsID, $Title, $Body, $NewsTime) = $NewsItem;
63
+  if (strtotime($NewsTime) > time()) {
64
+    continue;
65
+  }
66
+
67
+  $JsonAnnouncements[] = array(
68
+    'newsId' => (int)$NewsID,
69
+    'title' => $Title,
70
+    'bbBody' => $Body,
71
+    'body' => Text::full_format($Body),
72
+    'newsTime' => $NewsTime
73
+  );
74
+
75
+  if (++$Count > 4) {
76
+    break;
77
+  }
78
+}
79
+
80
+json_die("success", array(
81
+  'announcements' => $JsonAnnouncements,
82
+  'blogPosts' => $JsonBlog
83
+));

+ 362
- 0
sections/api/artist.php View File

@@ -0,0 +1,362 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+# todo: Go through line by line
5
+
6
+// For sorting tags
7
+function compare($X, $Y)
8
+{
9
+    return($Y['count'] - $X['count']);
10
+}
11
+
12
+if (!empty($_GET['artistreleases'])) {
13
+    $OnlyArtistReleases = true;
14
+}
15
+
16
+if ($_GET['id'] && $_GET['artistname']) {
17
+    json_die('failure', 'bad parameters');
18
+}
19
+
20
+$ArtistID = $_GET['id'];
21
+if ($ArtistID && !is_number($ArtistID)) {
22
+    json_die('failure');
23
+}
24
+
25
+if (empty($ArtistID)) {
26
+    if (!empty($_GET['artistname'])) {
27
+        $Name = db_string(trim($_GET['artistname']));
28
+        $DB->query("
29
+      SELECT ArtistID
30
+      FROM artists_alias
31
+      WHERE Name LIKE '$Name'");
32
+        if (!(list($ArtistID) = $DB->next_record(MYSQLI_NUM, false))) {
33
+            json_die('failure');
34
+        }
35
+        // If we get here, we got the ID!
36
+    }
37
+}
38
+
39
+if (!empty($_GET['revisionid'])) { // if they're viewing an old revision
40
+    $RevisionID = $_GET['revisionid'];
41
+    if (!is_number($RevisionID)) {
42
+        error(0);
43
+    }
44
+    $Data = $Cache->get_value("artist_$ArtistID"."_revision_$RevisionID");
45
+} else { // viewing the live version
46
+    $Data = $Cache->get_value("artist_$ArtistID");
47
+    $RevisionID = false;
48
+}
49
+if ($Data) {
50
+    list($Name, $Image, $Body) = current($Data);
51
+} else {
52
+    if ($RevisionID) {
53
+        /*
54
+          $sql = "
55
+            SELECT
56
+              a.Name,
57
+              wiki.Image,
58
+              wiki.body,
59
+              a.VanityHouse
60
+            FROM wiki_artists AS wiki
61
+              LEFT JOIN artists_group AS a ON wiki.RevisionID = a.RevisionID
62
+            WHERE wiki.RevisionID = '$RevisionID' ";
63
+        */
64
+        $sql = "
65
+      SELECT
66
+        a.Name,
67
+        wiki.Image,
68
+        wiki.body
69
+      FROM wiki_artists AS wiki
70
+        LEFT JOIN artists_group AS a ON wiki.RevisionID = a.RevisionID
71
+      WHERE wiki.RevisionID = '$RevisionID' ";
72
+    } else {
73
+        /*
74
+          $sql = "
75
+            SELECT
76
+              a.Name,
77
+              wiki.Image,
78
+              wiki.body,
79
+              a.VanityHouse
80
+            FROM artists_group AS a
81
+              LEFT JOIN wiki_artists AS wiki ON wiki.RevisionID = a.RevisionID
82
+            WHERE a.ArtistID = '$ArtistID' ";
83
+        */
84
+        $sql = "
85
+      SELECT
86
+        a.Name,
87
+        wiki.Image,
88
+        wiki.body
89
+      FROM artists_group AS a
90
+        LEFT JOIN wiki_artists AS wiki ON wiki.RevisionID = a.RevisionID
91
+      WHERE a.ArtistID = '$ArtistID' ";
92
+    }
93
+    $sql .= " GROUP BY a.ArtistID";
94
+    $DB->query($sql);
95
+
96
+    if (!$DB->has_results()) {
97
+        json_die('failure');
98
+    }
99
+
100
+    //  list($Name, $Image, $Body, $VanityHouseArtist) = $DB->next_record(MYSQLI_NUM, array(0));
101
+    list($Name, $Image, $Body) = $DB->next_record(MYSQLI_NUM, array(0));
102
+}
103
+
104
+// Requests
105
+$Requests = [];
106
+if (empty($LoggedUser['DisableRequests'])) {
107
+    $Requests = $Cache->get_value("artists_requests_$ArtistID");
108
+    if (!is_array($Requests)) {
109
+        $DB->query("
110
+      SELECT
111
+        r.ID,
112
+        r.CategoryID,
113
+        r.Title,
114
+        r.Year,
115
+        r.TimeAdded,
116
+        COUNT(rv.UserID) AS Votes,
117
+        SUM(rv.Bounty) AS Bounty
118
+      FROM requests AS r
119
+        LEFT JOIN requests_votes AS rv ON rv.RequestID = r.ID
120
+        LEFT JOIN requests_artists AS ra ON r.ID = ra.RequestID
121
+      WHERE ra.ArtistID = $ArtistID
122
+        AND r.TorrentID = 0
123
+      GROUP BY r.ID
124
+      ORDER BY Votes DESC");
125
+
126
+        if ($DB->has_results()) {
127
+            $Requests = $DB->to_array('ID', MYSQLI_ASSOC, false);
128
+        } else {
129
+            $Requests = [];
130
+        }
131
+        $Cache->cache_value("artists_requests_$ArtistID", $Requests);
132
+    }
133
+}
134
+$NumRequests = count($Requests);
135
+
136
+if (($Importances = $Cache->get_value("artist_groups_$ArtistID")) === false) {
137
+    $DB->query("
138
+    SELECT DISTINCTROW
139
+      ta.`GroupID`,
140
+      ta.`Importance`,
141
+      tg.`published`
142
+    FROM
143
+      `torrents_artists` AS ta
144
+    JOIN `torrents_group` AS tg
145
+    ON
146
+      tg.`id` = ta.`GroupID`
147
+    WHERE
148
+      ta.`ArtistID` = '$ArtistID'
149
+    ORDER BY
150
+      tg.`published`,
151
+      tg.`Name`
152
+    DESC
153
+    ");
154
+    
155
+    $GroupIDs = $DB->collect('GroupID');
156
+    $Importances = $DB->to_array(false, MYSQLI_BOTH, false);
157
+    $Cache->cache_value("artist_groups_$ArtistID", $Importances, 0);
158
+} else {
159
+    $GroupIDs = [];
160
+    foreach ($Importances as $Group) {
161
+        $GroupIDs[] = $Group['GroupID'];
162
+    }
163
+}
164
+if (count($GroupIDs) > 0) {
165
+    $TorrentList = Torrents::get_groups($GroupIDs, true, true);
166
+} else {
167
+    $TorrentList = [];
168
+}
169
+$NumGroups = count($TorrentList);
170
+
171
+//Get list of used release types
172
+$UsedReleases = [];
173
+foreach ($TorrentList as $GroupID=>$Group) {
174
+    if ($Importances[$GroupID]['Importance'] == '2') {
175
+        $TorrentList[$GroupID]['ReleaseType'] = 1024;
176
+        $GuestAlbums = true;
177
+    }
178
+    if ($Importances[$GroupID]['Importance'] == '3') {
179
+        $TorrentList[$GroupID]['ReleaseType'] = 1023;
180
+        $RemixerAlbums = true;
181
+    }
182
+    if ($Importances[$GroupID]['Importance'] == '4') {
183
+        $TorrentList[$GroupID]['ReleaseType'] = 1022;
184
+        $ComposerAlbums = true;
185
+    }
186
+    if ($Importances[$GroupID]['Importance'] == '7') {
187
+        $TorrentList[$GroupID]['ReleaseType'] = 1021;
188
+        $ProducerAlbums = true;
189
+    }
190
+    if (!in_array($TorrentList[$GroupID]['ReleaseType'], $UsedReleases)) {
191
+        $UsedReleases[] = $TorrentList[$GroupID]['ReleaseType'];
192
+    }
193
+}
194
+
195
+if (!empty($GuestAlbums)) {
196
+    $ReleaseTypes[1024] = 'Guest Appearance';
197
+}
198
+if (!empty($RemixerAlbums)) {
199
+    $ReleaseTypes[1023] = 'Remixed By';
200
+}
201
+if (!empty($ComposerAlbums)) {
202
+    $ReleaseTypes[1022] = 'Composition';
203
+}
204
+if (!empty($ProducerAlbums)) {
205
+    $ReleaseTypes[1021] = 'Produced By';
206
+}
207
+
208
+reset($TorrentList);
209
+
210
+$JsonTorrents = [];
211
+$Tags = [];
212
+$NumTorrents = $NumSeeders = $NumLeechers = $NumSnatches = 0;
213
+foreach ($GroupIDs as $GroupID) {
214
+    if (!isset($TorrentList[$GroupID])) {
215
+        continue;
216
+    }
217
+    $Group = $TorrentList[$GroupID];
218
+    extract(Torrents::array_group($Group));
219
+
220
+    foreach ($Artists as &$Artist) {
221
+        $Artist['id'] = (int)$Artist['id'];
222
+        $Artist['aliasid'] = (int)$Artist['aliasid'];
223
+    }
224
+
225
+    foreach ($ExtendedArtists as &$ArtistGroup) {
226
+        foreach ($ArtistGroup as &$Artist) {
227
+            $Artist['id'] = (int)$Artist['id'];
228
+            $Artist['aliasid'] = (int)$Artist['aliasid'];
229
+        }
230
+    }
231
+
232
+    $Found = Misc::search_array($Artists, 'id', $ArtistID);
233
+    if (isset($OnlyArtistReleases) && empty($Found)) {
234
+        continue;
235
+    }
236
+
237
+    $GroupVanityHouse = $Importances[$GroupID]['VanityHouse'];
238
+
239
+    $TagList = explode(' ', str_replace('_', '.', $TagList));
240
+
241
+    // $Tags array is for the sidebar on the right
242
+    foreach ($TagList as $Tag) {
243
+        if (!isset($Tags[$Tag])) {
244
+            $Tags[$Tag] = array('name' => $Tag, 'count' => 1);
245
+        } else {
246
+            $Tags[$Tag]['count']++;
247
+        }
248
+    }
249
+    $InnerTorrents = [];
250
+    foreach ($Torrents as $Torrent) {
251
+        $NumTorrents++;
252
+        $NumSeeders += $Torrent['Seeders'];
253
+        $NumLeechers += $Torrent['Leechers'];
254
+        $NumSnatches += $Torrent['Snatched'];
255
+
256
+        $InnerTorrents[] = array(
257
+      'id' => (int)$Torrent['ID'],
258
+      'groupId' => (int)$Torrent['GroupID'],
259
+      'media' => $Torrent['Media'],
260
+      'format' => $Torrent['Format'],
261
+      'encoding' => $Torrent['Encoding'],
262
+      'remasterYear' => (int)$Torrent['RemasterYear'],
263
+      'remastered' => $Torrent['Remastered'] == 1,
264
+      'remasterTitle' => $Torrent['RemasterTitle'],
265
+      'remasterRecordLabel' => $Torrent['RemasterRecordLabel'],
266
+      'scene' => $Torrent['Scene'] == 1,
267
+      'hasLog' => $Torrent['HasLog'] == 1,
268
+      'hasCue' => $Torrent['HasCue'] == 1,
269
+      'logScore' => (int)$Torrent['LogScore'],
270
+      'fileCount' => (int)$Torrent['FileCount'],
271
+      'freeTorrent' => $Torrent['FreeTorrent'] == 1,
272
+      'size' => (int)$Torrent['Size'],
273
+      'leechers' => (int)$Torrent['Leechers'],
274
+      'seeders' => (int)$Torrent['Seeders'],
275
+      'snatched' => (int)$Torrent['Snatched'],
276
+      'time' => $Torrent['Time'],
277
+      'hasFile' => (int)$Torrent['HasFile']
278
+    );
279
+    }
280
+    $JsonTorrents[] = array(
281
+    'groupId' => (int)$GroupID,
282
+    'groupName' => $GroupName,
283
+    'groupYear' => (int)$GroupYear,
284
+    'groupRecordLabel' => $GroupRecordLabel,
285
+    'groupCatalogueNumber' => $GroupCatalogueNumber,
286
+    'groupCategoryID' => $GroupCategoryID,
287
+    'tags' => $TagList,
288
+    'releaseType' => (int)$ReleaseType,
289
+    'wikiImage' => $WikiImage,
290
+    'groupVanityHouse' => $GroupVanityHouse == 1,
291
+    'hasBookmarked' => Bookmarks::has_bookmarked('torrent', $GroupID),
292
+    'artists' => $Artists,
293
+    'extendedArtists' => $ExtendedArtists,
294
+    'torrent' => $InnerTorrents,
295
+
296
+  );
297
+}
298
+
299
+$JsonRequests = [];
300
+foreach ($Requests as $RequestID => $Request) {
301
+    $JsonRequests[] = array(
302
+    'requestId' => (int)$RequestID,
303
+    'categoryId' => (int)$Request['CategoryID'],
304
+    'title' => $Request['Title'],
305
+    'year' => (int)$Request['Year'],
306
+    'timeAdded' => $Request['TimeAdded'],
307
+    'votes' => (int)$Request['Votes'],
308
+    'bounty' => (int)$Request['Bounty']
309
+  );
310
+}
311
+
312
+//notifications disabled by default
313
+$notificationsEnabled = false;
314
+if (check_perms('site_torrents_notify')) {
315
+    if (($Notify = $Cache->get_value('notify_artists_'.$LoggedUser['ID'])) === false) {
316
+        $DB->query("
317
+      SELECT ID, Artists
318
+      FROM users_notify_filters
319
+      WHERE UserID = '$LoggedUser[ID]'
320
+        AND Label = 'Artist notifications'
321
+      LIMIT 1");
322
+        $Notify = $DB->next_record(MYSQLI_ASSOC, false);
323
+        $Cache->cache_value('notify_artists_'.$LoggedUser['ID'], $Notify, 0);
324
+    }
325
+    if (stripos($Notify['Artists'], "|$Name|") === false) {
326
+        $notificationsEnabled = false;
327
+    } else {
328
+        $notificationsEnabled = true;
329
+    }
330
+}
331
+
332
+// Cache page for later use
333
+
334
+if ($RevisionID) {
335
+    $Key = "artist_$ArtistID"."_revision_$RevisionID";
336
+} else {
337
+    $Key = "artist_$ArtistID";
338
+}
339
+
340
+$Data = array(array($Name, $Image, $Body));
341
+
342
+$Cache->cache_value($Key, $Data, 3600);
343
+
344
+json_die('success', array(
345
+  'id' => (int)$ArtistID,
346
+  'name' => $Name,
347
+  'notificationsEnabled' => $notificationsEnabled,
348
+  'hasBookmarked' => Bookmarks::has_bookmarked('artist', $ArtistID),
349
+  'image' => $Image,
350
+  'body' => Text::full_format($Body),
351
+  'vanityHouse' => $VanityHouseArtist == 1,
352
+  'tags' => array_values($Tags),
353
+  'statistics' => array(
354
+    'numGroups' => $NumGroups,
355
+    'numTorrents' => $NumTorrents,
356
+    'numSeeders' => $NumSeeders,
357
+    'numLeechers' => $NumLeechers,
358
+    'numSnatches' => $NumSnatches
359
+  ),
360
+  'torrentgroup' => $JsonTorrents,
361
+  'requests' => $JsonRequests
362
+));

+ 14
- 0
sections/api/autofill/doi.php View File

@@ -0,0 +1,14 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+if (!$_GET['doi']) {
5
+    json_die();
6
+}
7
+
8
+print
9
+    json_encode(
10
+        [
11
+            'status' => 'success',
12
+            'response' => ['loadAverage' => sys_getloadavg()]
13
+        ]
14
+    );

+ 38
- 0
sections/api/better/index.php View File

@@ -0,0 +1,38 @@
1
+<?
2
+//Include all the basic stuff...
3
+
4
+enforce_login();
5
+if (isset($_GET['method'])) {
6
+  switch ($_GET['method']) {
7
+    case 'transcode':
8
+      include(SERVER_ROOT.'/sections/ajax/better/transcode.php');
9
+      break;
10
+    case 'single':
11
+      include(SERVER_ROOT.'/sections/ajax/better/single.php');
12
+      break;
13
+    case 'snatch':
14
+      include(SERVER_ROOT.'/sections/ajax/better/snatch.php');
15
+      break;
16
+    case 'artistless':
17
+      include(SERVER_ROOT.'/sections/ajax/better/artistless.php');
18
+      break;
19
+    case 'tags':
20
+      include(SERVER_ROOT.'/sections/ajax/better/tags.php');
21
+      break;
22
+    case 'folders':
23
+      include(SERVER_ROOT.'/sections/ajax/better/folders.php');
24
+      break;
25
+    case 'files':
26
+      include(SERVER_ROOT.'/sections/ajax/better/files.php');
27
+      break;
28
+    case 'upload':
29
+      include(SERVER_ROOT.'/sections/ajax/better/upload.php');
30
+      break;
31
+    default:
32
+      echo json_encode(array('status' => 'failure'));
33
+      break;
34
+  }
35
+} else {
36
+  echo json_encode(array('status' => 'failure'));
37
+}
38
+?>

+ 55
- 0
sections/api/better/single.php View File

@@ -0,0 +1,55 @@
1
+<?
2
+if (($Results = $Cache->get_value('better_single_groupids')) === false) {
3
+  $DB->query("
4
+    SELECT
5
+      t.ID AS TorrentID,
6
+      t.GroupID AS GroupID
7
+    FROM xbt_files_users AS x
8
+      JOIN torrents AS t ON t.ID=x.fid
9
+    WHERE t.Format='FLAC'
10
+    GROUP BY x.fid
11
+    HAVING COUNT(x.uid) = 1
12
+    ORDER BY t.LogScore DESC, t.Time ASC
13
+    LIMIT 30");
14
+
15
+  $Results = $DB->to_pair('GroupID', 'TorrentID', false);
16
+  $Cache->cache_value('better_single_groupids', $Results, 30 * 60);
17
+}
18
+
19
+$Groups = Torrents::get_groups(array_keys($Results));
20
+
21
+$JsonResults = [];
22
+foreach ($Results as $GroupID => $FlacID) {
23
+  if (!isset($Groups[$GroupID])) {
24
+    continue;
25
+  }
26
+  $Group = $Groups[$GroupID];
27
+  extract(Torrents::array_group($Group));
28
+
29
+  $JsonArtists = [];
30
+  if (count($Artists) > 0) {
31
+    foreach ($Artists as $Artist) {
32
+      $JsonArtists[] = array(
33
+        'id' => (int)$Artist['id'],
34
+        'name' => $Artist['name'],
35
+        'aliasId' => (int)$Artist['aliasid']
36
+      );
37
+    }
38
+  }
39
+
40
+  $JsonResults[] = array(
41
+    'torrentId' => (int)$FlacID,
42
+    'groupId' => (int)$GroupID,
43
+    'artist' => $JsonArtists,
44
+    'groupName' => $GroupName,
45
+    'groupYear' => (int)$GroupYear,
46
+    'downloadUrl' => "torrents.php?action=download&id=$FlacID&authkey=".$LoggedUser['AuthKey'].'&torrent_pass='.$LoggedUser['torrent_pass']
47
+  );
48
+}
49
+
50
+echo json_encode(
51
+  array(
52
+    'status' => 'success',
53
+    'response' => $JsonResults
54
+  )
55
+);

+ 131
- 0
sections/api/better/transcode.php View File

@@ -0,0 +1,131 @@
1
+<?
2
+if (!isset($_GET['type']) || !is_number($_GET['type']) || $_GET['type'] > 3) {
3
+  error(0);
4
+}
5
+
6
+$Options = array('v0', 'v2', '320');
7
+$Encodings = array('V0 (VBR)', 'V2 (VBR)', '320');
8
+$EncodingKeys = array_fill_keys($Encodings, true);
9
+
10
+if ($_GET['type'] === '3') {
11
+  $List = "!(v0 | v2 | 320)";
12
+} else {
13
+  $List = '!'.$Options[$_GET['type']];
14
+  if ($_GET['type'] !== '0') {
15
+    $_GET['type'] = display_str($_GET['type']);
16
+  }
17
+}
18
+$SphQL = new SphinxqlQuery();
19
+$SphQL->select('id, groupid')
20
+  ->from('better_transcode')
21
+  ->where('logscore', 100)
22
+  ->where_match('FLAC', 'format')
23
+  ->where_match($List, 'encoding', false)
24
+  ->order_by('RAND()')
25
+  ->limit(0, TORRENTS_PER_PAGE, TORRENTS_PER_PAGE);
26
+if (!empty($_GET['search'])) {
27
+  $SphQL->where_match($_GET['search'], '(groupname,artistname,year,taglist)');
28
+}
29
+
30
+$SphQLResult = $SphQL->query();
31
+$TorrentCount = $SphQLResult->get_meta('total');
32
+
33
+if ($TorrentCount == 0) {
34
+  error('No results found!');
35
+}
36
+
37
+$Results = $SphQLResult->to_array('groupid');
38
+$Groups = Torrents::get_groups(array_keys($Results));
39
+
40
+$TorrentGroups = [];
41
+foreach ($Groups as $GroupID => $Group) {
42
+  if (empty($Group['Torrents'])) {
43
+    unset($Groups[$GroupID]);
44
+    continue;
45
+  }
46
+  foreach ($Group['Torrents'] as $Torrent) {
47
+    $TorRemIdent = "$Torrent[Media] $Torrent[RemasterYear] $Torrent[RemasterTitle] $Torrent[RemasterRecordLabel] $Torrent[RemasterCatalogueNumber]";
48
+    if (!isset($TorrentGroups[$Group['ID']])) {
49
+      $TorrentGroups[$Group['ID']] = array(
50
+        $TorRemIdent => array(
51
+          'FlacID' => 0,
52
+          'Formats' => [],
53
+          'RemasterTitle' => $Torrent['RemasterTitle'],
54
+          'RemasterYear' => $Torrent['RemasterYear'],
55
+          'RemasterRecordLabel' => $Torrent['RemasterRecordLabel'],
56
+          'RemasterCatalogueNumber' => $Torrent['RemasterCatalogueNumber'],
57
+          'IsSnatched' => false
58
+        )
59
+      );
60
+    } elseif (!isset($TorrentGroups[$Group['ID']][$TorRemIdent])) {
61
+      $TorrentGroups[$Group['ID']][$TorRemIdent] = array(
62
+        'FlacID' => 0,
63
+        'Formats' => [],
64
+        'RemasterTitle' => $Torrent['RemasterTitle'],
65
+        'RemasterYear' => $Torrent['RemasterYear'],
66
+        'RemasterRecordLabel' => $Torrent['RemasterRecordLabel'],
67
+        'RemasterCatalogueNumber' => $Torrent['RemasterCatalogueNumber'],
68
+        'IsSnatched' => false
69
+      );
70
+    }
71
+    if (isset($EncodingKeys[$Torrent['Encoding']])) {
72
+      $TorrentGroups[$Group['ID']][$TorRemIdent]['Formats'][$Torrent['Encoding']] = true;
73
+    } elseif ($TorrentGroups[$Group['ID']][$TorRemIdent]['FlacID'] == 0 && $Torrent['Format'] == 'FLAC' && $Torrent['LogScore'] == 100) {
74
+      $TorrentGroups[$Group['ID']][$TorRemIdent]['FlacID'] = $Torrent['ID'];
75
+      $TorrentGroups[$Group['ID']][$TorRemIdent]['IsSnatched'] = $Torrent['IsSnatched'];
76
+    }
77
+  }
78
+}
79
+
80
+$JsonResults = [];
81
+foreach ($TorrentGroups as $GroupID => $Editions) {
82
+  $GroupInfo = $Groups[$GroupID];
83
+  $GroupYear = $GroupInfo['Year'];
84
+  $ExtendedArtists = $GroupInfo['ExtendedArtists'];
85
+  $GroupCatalogueNumber = $GroupInfo['CatalogueNumber'];
86
+  $GroupName = $GroupInfo['Name'];
87
+  $GroupRecordLabel = $GroupInfo['RecordLabel'];
88
+  $ReleaseType = $GroupInfo['ReleaseType'];
89
+
90
+  if (!empty($ExtendedArtists[1]) || !empty($ExtendedArtists[4]) || !empty($ExtendedArtists[5]) || !empty($ExtendedArtists[6])) {
91
+    unset($ExtendedArtists[2]);
92
+    unset($ExtendedArtists[3]);
93
+    $ArtistNames = Artists::display_artists($ExtendedArtists, false, false, false);
94
+  } else {
95
+    $ArtistNames = '';
96
+  }
97
+
98
+  $TagList = [];
99
+  $TagList = explode(' ', str_replace('_', '.', $GroupInfo['TagList']));
100
+  $TorrentTags = [];
101
+  foreach ($TagList as $Tag) {
102
+    $TorrentTags[] = "<a href=\"torrents.php?taglist=$Tag\">$Tag</a>";
103
+  }
104
+  $TorrentTags = implode(', ', $TorrentTags);
105
+  foreach ($Editions as $RemIdent => $Edition) {
106
+    if (!$Edition['FlacID']
107
+        || !empty($Edition['Formats']) && $_GET['type'] === '3'
108
+        || $Edition['Formats'][$Encodings[$_GET['type']]] == true) {
109
+      continue;
110
+    }
111
+
112
+    $JsonResults[] = array(
113
+      'torrentId' => (int)$Edition['FlacID'],
114
+      'groupId' => (int)$GroupID,
115
+      'artist' => $ArtistNames,
116
+      'groupName' => $GroupName,
117
+      'groupYear' => (int)$GroupYear,
118
+      'missingV2' => !isset($Edition['Formats']['V2 (VBR)']),
119
+      'missingV0' => !isset($Edition['Formats']['V0 (VBR)']),
120
+      'missing320' => !isset($Encodings['Formats']['320']),
121
+      'downloadUrl' => 'torrents.php?action=download&id='.$Edition['FlacID'].'&authkey='.$LoggedUser['AuthKey'].'&torrent_pass='.$LoggedUser['torrent_pass']
122
+    );
123
+  }
124
+}
125
+
126
+echo json_encode(
127
+  array(
128
+    'status' => 'success',
129
+    'response' => $JsonResults
130
+  )
131
+);

+ 63
- 0
sections/api/bookmarks/artists.php View File

@@ -0,0 +1,63 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+if (!empty($_GET['userid'])) {
5
+    if (!check_perms('users_override_paranoia')) {
6
+        json_die('failure');
7
+    }
8
+   
9
+    $UserID = $_GET['userid'];
10
+    $Sneaky = ($UserID !== $LoggedUser['ID']);
11
+
12
+    if (!is_number($UserID)) {
13
+        json_die('failure');
14
+    }
15
+
16
+    $DB->query("
17
+    SELECT
18
+      `Username`
19
+    FROM
20
+      `users_main`
21
+    WHERE
22
+      `ID` = '$UserID'
23
+    ");
24
+    list($Username) = $DB->next_record();
25
+} else {
26
+    $UserID = $LoggedUser['ID'];
27
+}
28
+
29
+//$ArtistList = Bookmarks::all_bookmarks('artist', $UserID);
30
+
31
+$DB->query("
32
+SELECT
33
+  ag.`ArtistID`,
34
+  ag.`Name`
35
+FROM
36
+  `bookmarks_artists` AS ba
37
+INNER JOIN `artists_group` AS ag
38
+ON
39
+  ba.`ArtistID` = ag.`ArtistID`
40
+WHERE
41
+  ba.`UserID` = $UserID
42
+");
43
+
44
+$ArtistList = $DB->to_array();
45
+$JsonArtists = [];
46
+
47
+foreach ($ArtistList as $Artist) {
48
+    list($ArtistID, $Name) = $Artist;
49
+    $JsonArtists[] = array(
50
+      'artistId'   => (int) $ArtistID,
51
+      'artistName' => $Name
52
+  );
53
+}
54
+
55
+print
56
+  json_encode(
57
+      array(
58
+      'status' => 'success',
59
+      'response' => array(
60
+        'artists' => $JsonArtists
61
+      )
62
+    )
63
+  );

+ 47
- 0
sections/api/bookmarks/index.php View File

@@ -0,0 +1,47 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+// Number of users per page
5
+define('BOOKMARKS_PER_PAGE', '20');
6
+
7
+if (empty($_REQUEST['type'])) {
8
+    $_REQUEST['type'] = 'torrents';
9
+}
10
+
11
+switch ($_REQUEST['type']) {
12
+  case 'torrents':
13
+    require SERVER_ROOT.'/sections/ajax/bookmarks/torrents.php';
14
+    break;
15
+
16
+  case 'artists':
17
+    require SERVER_ROOT.'/sections/ajax/bookmarks/artists.php';
18
+    break;
19
+
20
+  /*
21
+  case 'collages':
22
+    $_GET['bookmarks'] = 1;
23
+    require SERVER_ROOT.'/sections/ajax/collages/browse.php';
24
+    break;
25
+  */
26
+
27
+  /*
28
+  case 'requests':
29
+    $_GET['type'] = 'bookmarks';
30
+    require SERVER_ROOT.'/sections/ajax/requests/requests.php';
31
+    break;
32
+  */
33
+
34
+  default:
35
+    json_die('failure');
36
+    break;
37
+
38
+    /*
39
+    print
40
+      json_encode(
41
+          array(
42
+          'status' => 'failure'
43
+        )
44
+      );
45
+    error();
46
+    */
47
+}

+ 124
- 0
sections/api/bookmarks/torrents.php View File

@@ -0,0 +1,124 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+ini_set('memory_limit', -1);
5
+
6
+function compare($X, $Y)
7
+{
8
+    return($Y['count'] - $X['count']);
9
+}
10
+
11
+if (!empty($_GET['userid'])) {
12
+    if (!check_perms('users_override_paranoia')) {
13
+        error(403);
14
+    }
15
+
16
+    $UserID = $_GET['userid'];
17
+    if (!is_number($UserID)) {
18
+        error(404);
19
+    }
20
+
21
+    $DB->query("
22
+    SELECT
23
+      `Username`
24
+    FROM
25
+      `users_main`
26
+    WHERE
27
+      `ID` = '$UserID'
28
+    ");
29
+    list($Username) = $DB->next_record();
30
+} else {
31
+    $UserID = $LoggedUser['ID'];
32
+}
33
+
34
+$Sneaky = ($UserID !== $LoggedUser['ID']);
35
+$JsonBookmarks = [];
36
+
37
+list($GroupIDs, $CollageDataList, $GroupList) = Users::get_bookmarks($UserID);
38
+foreach ($GroupIDs as $GroupID) {
39
+    if (!isset($GroupList[$GroupID])) {
40
+        continue;
41
+    }
42
+
43
+    $Group = $GroupList[$GroupID];
44
+    $JsonTorrents = [];
45
+
46
+    foreach ($Group['Torrents'] as $Torrent) {
47
+        $JsonTorrents[] = array(
48
+          'id'          => (int) $Torrent['ID'],
49
+          'groupId'     => (int) $Torrent['GroupID'],
50
+          'platform'    => $Torrent['Media'],
51
+          'fileCount'   => (int) $Torrent['FileCount'],
52
+          'freeTorrent' => $Torrent['FreeTorrent'] === 1,
53
+          'size'        => (float) $Torrent['Size'],
54
+          'leechers'    => (int) $Torrent['Leechers'],
55
+          'seeders'     => (int) $Torrent['Seeders'],
56
+          'snatched'    => (int) $Torrent['Snatched'],
57
+          'time'        => $Torrent['Time'],
58
+          'hasFile'     => (int) $Torrent['HasFile']
59
+        );
60
+
61
+        /*
62
+        $JsonTorrents[] = array(
63
+          'id'                      => (int) $Torrent['ID'],
64
+          'groupId'                 => (int) $Torrent['GroupID'],
65
+          'media'                   => $Torrent['Media'],
66
+          'format'                  => $Torrent['Format'],
67
+          'encoding'                => $Torrent['Encoding'],
68
+          'remasterYear'            => (int) $Torrent['RemasterYear'],
69
+          'remastered'              => $Torrent['Remastered'] == 1,
70
+          'remasterTitle'           => $Torrent['RemasterTitle'],
71
+          'remasterRecordLabel'     => $Torrent['RemasterRecordLabel'],
72
+          'remasterCatalogueNumber' => $Torrent['RemasterCatalogueNumber'],
73
+          'scene'                   => $Torrent['Scene'] === 1,
74
+          'hasLog'                  => $Torrent['HasLog'] === 1,
75
+          'hasCue'                  => $Torrent['HasCue'] === 1,
76
+          'logScore'                => (float) $Torrent['LogScore'],
77
+          'fileCount'               => (int) $Torrent['FileCount'],
78
+          'freeTorrent'             => $Torrent['FreeTorrent'] === 1,
79
+          'size'                    => (float) $Torrent['Size'],
80
+          'leechers'                => (int) $Torrent['Leechers'],
81
+          'seeders'                 => (int) $Torrent['Seeders'],
82
+          'snatched'                => (int) $Torrent['Snatched'],
83
+          'time'                    => $Torrent['Time'],
84
+          'hasFile'                 => (int) $Torrent['HasFile']
85
+        );
86
+        */
87
+    }
88
+
89
+    $JsonBookmarks[] = array(
90
+    'id'          => (int) $Group['ID'],
91
+    'name'        => $Group['Name'],
92
+    'year'        => (int) $Group['Year'],
93
+    'accession'   => $Group['CatalogueNumber'],
94
+    'tagList'     => $Group['TagList'],
95
+    'vanityHouse' => $Group['VanityHouse'] === 1,
96
+    'picture'     => $Group['WikiImage'],
97
+    'torrents'    => $JsonTorrents
98
+  );
99
+
100
+    /*
101
+    $JsonBookmarks[] = array(
102
+      'id'              => (int) $Group['ID'],
103
+      'name'            => $Group['Name'],
104
+      'year'            => (int) $Group['Year'],
105
+      'recordLabel'     => $Group['RecordLabel'],
106
+      'catalogueNumber' => $Group['CatalogueNumber'],
107
+      'tagList'         => $Group['TagList'],
108
+      'releaseType'     => $Group['ReleaseType'],
109
+      'vanityHouse'     => $Group['VanityHouse'] === 1,
110
+      'image'           => $Group['WikiImage'],
111
+      'torrents'        => $JsonTorrents
112
+    );
113
+    */
114
+}
115
+
116
+print
117
+  json_encode(
118
+      array(
119
+      'status' => 'success',
120
+      'response' => array(
121
+        'bookmarks' => $JsonBookmarks
122
+      )
123
+    )
124
+  );

+ 132
- 0
sections/api/browse.php View File

@@ -0,0 +1,132 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+include SERVER_ROOT.'/sections/torrents/functions.php';
5
+
6
+if (!empty($_GET['order_way']) && $_GET['order_way'] === 'asc') {
7
+    $OrderWay = 'asc';
8
+} else {
9
+    $OrderWay = 'desc';
10
+}
11
+
12
+if (empty($_GET['order_by']) || !isset(TorrentSearch::$SortOrders[$_GET['order_by']])) {
13
+    $OrderBy = 'time';
14
+} else {
15
+    $OrderBy = $_GET['order_by'];
16
+}
17
+
18
+$GroupResults = !isset($_GET['group_results']) || (int) $_GET['group_results'] !== 0;
19
+$Page = !empty($_GET['page']) ? (int) $_GET['page'] : 1;
20
+
21
+$Search = new TorrentSearch($GroupResults, $OrderBy, $OrderWay, $Page, TORRENTS_PER_PAGE);
22
+$Results = $Search->query($_GET);
23
+
24
+$Groups = $Search->get_groups();
25
+$NumResults = $Search->record_count();
26
+
27
+if ($Results === false) {
28
+    json_die('error', 'Search returned an error. Make sure all parameters are valid and of the expected types.');
29
+}
30
+
31
+if ($NumResults === 0) {
32
+    json_die('success', [
33
+    'results' => []
34
+  ]);
35
+}
36
+
37
+$Bookmarks = Bookmarks::all_bookmarks('torrent');
38
+
39
+$JsonGroups = [];
40
+foreach ($Results as $Key => $GroupID) {
41
+    $GroupInfo = $Groups[$GroupID];
42
+    if (empty($GroupInfo['Torrents'])) {
43
+        continue;
44
+    }
45
+
46
+    $CategoryID = $GroupInfo['CategoryID'];
47
+    $Artists = $GroupInfo['Artists'];
48
+    $GroupCatalogueNumber = $GroupInfo['CatalogueNumber'];
49
+    $GroupName = $GroupInfo['Name'];
50
+
51
+    if ($GroupResults) {
52
+        $Torrents = $GroupInfo['Torrents'];
53
+        $GroupTime = $MaxSize = $TotalLeechers = $TotalSeeders = $TotalSnatched = 0;
54
+
55
+        foreach ($Torrents as $T) {
56
+            $GroupTime = max($GroupTime, strtotime($T['Time']));
57
+            $MaxSize = max($MaxSize, $T['Size']);
58
+            $TotalLeechers += $T['Leechers'];
59
+            $TotalSeeders += $T['Seeders'];
60
+            $TotalSnatched += $T['Snatched'];
61
+        }
62
+    } else {
63
+        $TorrentID = $Key;
64
+        $Torrents = [$TorrentID => $GroupInfo['Torrents'][$TorrentID]];
65
+    }
66
+
67
+    $TagList = explode(' ', str_replace('_', '.', $GroupInfo['TagList']));
68
+    $JsonArtists = [];
69
+    $DisplayName = '';
70
+
71
+    if (!empty($Artists)) {
72
+        $DisplayName = Artists::display_artists($Artists, false, false, false);
73
+        foreach ($Artists as $Artist) {
74
+            $JsonArtists[] = [
75
+              'id' => (int) $Artist['id'],
76
+              'name' => $Artist['name']
77
+            ];
78
+        }
79
+    }
80
+
81
+    $JsonTorrents = [];
82
+    foreach ($Torrents as $TorrentID => $Data) {
83
+        // All of the individual torrents in the group
84
+
85
+        $JsonTorrents[] = [
86
+          'torrentId'           => (int) $TorrentID,
87
+          'authors'             => $JsonArtists,
88
+          'platform'            => $Data['Media'],
89
+          'format'              => $Data['Container'],
90
+          'license'             => $Data['Codec'],
91
+          'scope'               => $Data['Resolution'],
92
+          'annotated'           => $Data['Censored'],
93
+          'archive'             => $Data['Archive'],
94
+          'fileCount'           => (int) $Data['FileCount'],
95
+          'time'                => $Data['Time'],
96
+          'size'                => (int) $Data['Size'],
97
+          'snatches'            => (int) $Data['Snatched'],
98
+          'seeders'             => (int) $Data['Seeders'],
99
+          'leechers'            => (int) $Data['Leechers'],
100
+          'isFreeleech'         => (int) $Data['FreeTorrent'] === 1,
101
+          'isNeutralLeech'      => (int) $Data['FreeTorrent'] === 2,
102
+          'isPersonalFreeleech' => $Data['PersonalFL'],
103
+          'canUseToken'         => Torrents::can_use_token($Data),
104
+          'hasSnatched'         => $Data['IsSnatched']
105
+        ];
106
+    }
107
+
108
+    $JsonGroups[] = [
109
+      'groupId'       => (int) $GroupID,
110
+      'groupName'     => $GroupName,
111
+      'author'        => $DisplayName,
112
+      'picture'       => $GroupInfo['WikiImage'],
113
+      'tags'          => $TagList,
114
+      'bookmarked'    => (in_array($GroupID, $Bookmarks)),
115
+      'groupYear'     => (int) $GroupInfo['Year'],
116
+      'groupTime'     => (int) $GroupTime,
117
+      'accession'     => $GroupInfo['CatalogueNumber'],
118
+      'lab'           => $GroupInfo['Studio'],
119
+      'location'      => $GroupInfo['Series'],
120
+      'maxSize'       => (int) $MaxSize,
121
+      'totalSnatched' => (int) $TotalSnatched,
122
+      'totalSeeders'  => (int) $TotalSeeders,
123
+      'totalLeechers' => (int) $TotalLeechers,
124
+      'torrents'      => $JsonTorrents
125
+    ];
126
+}
127
+
128
+json_print('success', [
129
+  'currentPage' => intval($Page),
130
+  'pages' => ceil($NumResults / TORRENTS_PER_PAGE),
131
+  'results' => $JsonGroups
132
+]);

+ 49
- 0
sections/api/clear_user_notification.php View File

@@ -0,0 +1,49 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+$Type = $_POST['type'];
5
+
6
+switch ($Type) {
7
+  case NotificationsManager::INBOX:
8
+    NotificationsManager::clear_inbox();
9
+    break;
10
+
11
+  case NotificationsManager::NEWS:
12
+    NotificationsManager::clear_news(false);
13
+    break;
14
+
15
+  case NotificationsManager::BLOG:
16
+    NotificationsManager::clear_blog(false);
17
+    break;
18
+
19
+  case NotificationsManager::STAFFPM:
20
+    NotificationsManager::clear_staff_pms();
21
+    break;
22
+
23
+  case NotificationsManager::TORRENTS:
24
+    NotificationsManager::clear_torrents();
25
+    break;
26
+
27
+  case NotificationsManager::QUOTES:
28
+    NotificationsManager::clear_quotes();
29
+    break;
30
+
31
+  case NotificationsManager::SUBSCRIPTIONS:
32
+    NotificationsManager::clear_subscriptions();
33
+    break;
34
+
35
+  case NotificationsManager::COLLAGES:
36
+    NotificationsManager::clear_collages();
37
+    break;
38
+
39
+  case NotificationsManager::GLOBALNOTICE:
40
+    NotificationsManager::clear_global_notification();
41
+    break;
42
+    
43
+  default:
44
+    break;
45
+}
46
+
47
+if (strpos($Type, "oneread_") === 0) {
48
+    NotificationsManager::clear_one_read($Type);
49
+}

+ 174
- 0
sections/api/collage.php View File

@@ -0,0 +1,174 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+define('ARTIST_COLLAGE', 'Artists');
5
+
6
+if (empty($_GET['id']) || !is_number($_GET['id'])) {
7
+    json_die('failure', 'bad parameters');
8
+}
9
+
10
+$CollageID = $_GET['id'];
11
+$CacheKey = "collage_$CollageID";
12
+$CollageData = $Cache->get_value($CacheKey);
13
+
14
+if ($CollageData) {
15
+    list($Name, $Description, $CommentList, $Deleted, $CollageCategoryID, $CreatorID, $Locked, $MaxGroups, $MaxGroupsPerUser, $Updated, $Subscribers) = $CollageData;
16
+} else {
17
+    $DB->query("
18
+    SELECT
19
+      `Name`,
20
+      `Description`,
21
+      `UserID`,
22
+      `Deleted`,
23
+      `CategoryID`,
24
+      `Locked`,
25
+      `MaxGroups`,
26
+      `MaxGroupsPerUser`,
27
+      `Updated`,
28
+      `Subscribers`
29
+    FROM
30
+      `collages`
31
+    WHERE
32
+      `ID` = '$CollageID'
33
+    ");
34
+
35
+    if (!$DB->has_results()) {
36
+        json_die("failure");
37
+    }
38
+
39
+    list($Name, $Description, $CreatorID, $Deleted, $CollageCategoryID, $Locked, $MaxGroups, $MaxGroupsPerUser, $Updated, $Subscribers) = $DB->next_record(MYSQLI_NUM);
40
+    $CommentList = null;
41
+    $SetCache = true;
42
+}
43
+
44
+// todo: Cache this
45
+$DB->query("
46
+SELECT
47
+  `GroupID`
48
+FROM
49
+  `collages_torrents`
50
+WHERE
51
+  `CollageID` = $CollageID
52
+");
53
+$TorrentGroups = $DB->collect('GroupID');
54
+
55
+$JSON = array(
56
+  'id'                  => (int) $CollageID,
57
+  'name'                => $Name,
58
+  'description'         => Text::full_format($Description),
59
+  'creatorID'           => (int) $CreatorID,
60
+  'deleted'             => (bool) $Deleted,
61
+  'collageCategoryID'   => (int) $CollageCategoryID,
62
+  'collageCategoryName' => $CollageCats[(int) $CollageCategoryID],
63
+  'locked'              => (bool) $Locked,
64
+  'maxGroups'           => (int) $MaxGroups,
65
+  'maxGroupsPerUser'    => (int) $MaxGroupsPerUser,
66
+  'hasBookmarked'       => Bookmarks::has_bookmarked('collage', $CollageID),
67
+  'subscriberCount'     => (int) $Subscribers,
68
+  'torrentGroupIDList'  => $TorrentGroups
69
+);
70
+
71
+if ($CollageCategoryID !== array_search(ARTIST_COLLAGE, $CollageCats)) {
72
+    // Torrent collage
73
+    $TorrentGroups = [];
74
+    $DB->query("
75
+    SELECT
76
+      ct.`GroupID`
77
+    FROM
78
+      `collages_torrents` AS ct
79
+    JOIN `torrents_group` AS tg
80
+    ON
81
+      tg.`ID` = ct.`GroupID`
82
+    WHERE
83
+      ct.`CollageID` = '$CollageID'
84
+    ORDER BY
85
+      ct.`Sort`
86
+    ");
87
+
88
+    $GroupIDs = $DB->collect('GroupID');
89
+    $GroupList = Torrents::get_groups($GroupIDs);
90
+
91
+    foreach ($GroupIDs as $GroupID) {
92
+        if (!empty($GroupList[$GroupID])) {
93
+            $GroupDetails = Torrents::array_group($GroupList[$GroupID]);
94
+            $TorrentList = [];
95
+
96
+            foreach ($GroupDetails['Torrents'] as $Torrent) {
97
+                $TorrentList[] = array(
98
+                  'torrentid'   => (int)$Torrent['ID'],
99
+                  'platform'    => $Torrent['Media'],
100
+                  'fileCount'   => (int)$Torrent['FileCount'],
101
+                  'size'        => (int)$Torrent['Size'],
102
+                  'seeders'     => (int)$Torrent['Seeders'],
103
+                  'leechers'    => (int)$Torrent['Leechers'],
104
+                  'snatched'    => (int)$Torrent['Snatched'],
105
+                  'freeTorrent' => ($Torrent['FreeTorrent'] === 1),
106
+                  'reported'    => (count(Torrents::get_reports((int)$Torrent['ID'])) > 0),
107
+                  'time'        => $Torrent['Time']
108
+                );
109
+            }
110
+
111
+            $TorrentGroups[] = array(
112
+              'id'          => $GroupDetails['GroupID'],
113
+              'name'        => $GroupDetails['GroupName'],
114
+              'year'        => $GroupDetails['GroupYear'],
115
+              'categoryId'  => $GroupDetails['GroupCategoryID'],
116
+              'accession'   => $GroupDetails['GroupCatalogueNumber'],
117
+              'vanityHouse' => $GroupDetails['GroupVanityHouse'],
118
+              'tagList'     => $GroupDetails['TagList'],
119
+              'picture'     => $GroupDetails['WikiImage'],
120
+              'torrents'    => $TorrentList
121
+            );
122
+        }
123
+    }
124
+    $JSON['torrentgroups'] = $TorrentGroups;
125
+} else {
126
+    // Artist collage
127
+    $DB->query("
128
+    SELECT
129
+      ca.`ArtistID`,
130
+      ag.`Name`,
131
+      aw.`Image`
132
+    FROM
133
+      `collages_artists` AS ca
134
+    JOIN `artists_group` AS ag
135
+    ON
136
+      ag.`ArtistID` = ca.`ArtistID`
137
+    LEFT JOIN `wiki_artists` AS aw
138
+    ON
139
+      aw.`RevisionID` = ag.`RevisionID`
140
+    WHERE
141
+      ca.`CollageID` = '$CollageID'
142
+    ORDER BY
143
+      ca.`Sort`
144
+    ");
145
+
146
+    $Artists = [];
147
+    while (list($ArtistID, $ArtistName, $ArtistImage) = $DB->next_record()) {
148
+        $Artists[] = array(
149
+          'id'      => (int) $ArtistID,
150
+          'name'    => $ArtistName,
151
+          'picture' => $ArtistImage
152
+        );
153
+    }
154
+    $JSON['artists'] = $Artists;
155
+}
156
+
157
+if (isset($SetCache)) {
158
+    $CollageData = array(
159
+      $Name,
160
+      $Description,
161
+      $CommentList,
162
+      (bool) $Deleted,
163
+      (int) $CollageCategoryID,
164
+      (int) $CreatorID,
165
+      (bool) $Locked,
166
+      (int) $MaxGroups,
167
+      (int) $MaxGroupsPerUser,
168
+      $Updated,
169
+      (int) $Subscribers
170
+    );
171
+    $Cache->cache_value($CacheKey, $CollageData, 3600);
172
+}
173
+
174
+json_print('success', $JSON);

+ 70
- 0
sections/api/community_stats.php View File

@@ -0,0 +1,70 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+if (!isset($_GET['userid']) || !is_number($_GET['userid'])) {
5
+    json_die('failure');
6
+}
7
+
8
+$UserID = $_GET['userid'];
9
+$CommStats = array(
10
+  'leeching' => false,
11
+  'seeding' => false,
12
+  'snatched' => false,
13
+  'usnatched' => false,
14
+  'downloaded' => false,
15
+  'udownloaded' => false,
16
+  'seedingperc' => false,
17
+);
18
+
19
+$User = Users::user_info($UserID);
20
+
21
+function check_paranoia_here($Setting)
22
+{
23
+    global $User;
24
+    return check_paranoia($Setting, $User['Paranoia'], $User['Class'], $User['ID']);
25
+}
26
+
27
+if (check_paranoia_here('seeding+') || check_paranoia_here('leeching+')) {
28
+    $DB->query("
29
+    SELECT IF(remaining = 0, 'Seeding', 'Leeching') AS Type, COUNT(x.uid)
30
+    FROM xbt_files_users AS x
31
+      INNER JOIN torrents AS t ON t.ID = x.fid
32
+    WHERE x.uid = '$UserID'
33
+      AND x.active = 1
34
+    GROUP BY Type");
35
+    $PeerCount = $DB->to_array(0, MYSQLI_NUM, false);
36
+    if (check_paranoia('seeding+')) {
37
+        $Seeding = isset($PeerCount['Seeding']) ? $PeerCount['Seeding'][1] : 0;
38
+        $CommStats['seeding'] = number_format($Seeding);
39
+    }
40
+    if (check_paranoia('leeching+')) {
41
+        $CommStats['leeching'] = isset($PeerCount['Leeching']) ? number_format($PeerCount['Leeching'][1]) : 0;
42
+    }
43
+}
44
+if (check_paranoia_here('snatched+')) {
45
+    $DB->query("
46
+    SELECT COUNT(x.uid), COUNT(DISTINCT x.fid)
47
+    FROM xbt_snatched AS x
48
+      INNER JOIN torrents AS t ON t.ID = x.fid
49
+    WHERE x.uid = '$UserID'");
50
+    list($Snatched, $UniqueSnatched) = $DB->next_record(MYSQLI_NUM, false);
51
+    $CommStats['snatched'] = number_format($Snatched);
52
+    if (check_perms('site_view_torrent_snatchlist', $User['Class'])) {
53
+        $CommStats['usnatched'] = number_format($UniqueSnatched);
54
+    }
55
+    if (check_paranoia_here('seeding+') && check_paranoia_here('snatched+') && $UniqueSnatched > 0) {
56
+        $CommStats['seedingperc'] = 100 * min(1, round($Seeding / $UniqueSnatched, 2));
57
+    }
58
+}
59
+if (check_perms('site_view_torrent_snatchlist', $Class)) {
60
+    $DB->query("
61
+    SELECT COUNT(ud.UserID), COUNT(DISTINCT ud.TorrentID)
62
+    FROM users_downloads AS ud
63
+      JOIN torrents AS t ON t.ID = ud.TorrentID
64
+    WHERE ud.UserID = '$UserID'");
65
+    list($NumDownloads, $UniqueDownloads) = $DB->next_record(MYSQLI_NUM, false);
66
+    $CommStats['downloaded'] = number_format($NumDownloads);
67
+    $CommStats['udownloaded'] = number_format($UniqueDownloads);
68
+}
69
+
70
+json_die('success', $CommStats);

+ 180
- 0
sections/api/forum/forum.php View File

@@ -0,0 +1,180 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+# todo: Go through line by line
5
+
6
+/**********|| Page to show individual forums || ********************************\
7
+
8
+Things to expect in $_GET:
9
+  ForumID: ID of the forum curently being browsed
10
+  page: The page the user's on.
11
+  page = 1 is the same as no page
12
+
13
+********************************************************************************/
14
+
15
+//---------- Things to sort out before it can start printing/generating content
16
+
17
+// Check for lame SQL injection attempts
18
+$ForumID = $_GET['forumid'];
19
+if (!is_number($ForumID)) {
20
+    echo json_encode(array('status' => 'failure'));
21
+    error();
22
+}
23
+
24
+if (isset($_GET['pp'])) {
25
+    $PerPage = intval($_GET['pp']);
26
+} elseif (isset($LoggedUser['PostsPerPage'])) {
27
+    $PerPage = $LoggedUser['PostsPerPage'];
28
+} else {
29
+    $PerPage = POSTS_PER_PAGE;
30
+}
31
+
32
+list($Page, $Limit) = Format::page_limit(TOPICS_PER_PAGE);
33
+
34
+//---------- Get some data to start processing
35
+
36
+// Caching anything beyond the first page of any given forum is just wasting ram
37
+// users are more likely to search then to browse to page 2
38
+if ($Page === 1) {
39
+    list($Forum, , , $Stickies) = $Cache->get_value("forums_$ForumID");
40
+}
41
+if (!isset($Forum) || !is_array($Forum)) {
42
+    $DB->query("
43
+    SELECT
44
+      ID,
45
+      Title,
46
+      AuthorID,
47
+      IsLocked,
48
+      IsSticky,
49
+      NumPosts,
50
+      LastPostID,
51
+      LastPostTime,
52
+      LastPostAuthorID
53
+    FROM forums_topics
54
+    WHERE ForumID = '$ForumID'
55
+    ORDER BY IsSticky DESC, LastPostTime DESC
56
+    LIMIT $Limit"); // Can be cached until someone makes a new post
57
+    $Forum = $DB->to_array('ID', MYSQLI_ASSOC, false);
58
+    if ($Page === 1) {
59
+        $DB->query("
60
+      SELECT COUNT(ID)
61
+      FROM forums_topics
62
+      WHERE ForumID = '$ForumID'
63
+        AND IsSticky = '1'");
64
+        list($Stickies) = $DB->next_record();
65
+        $Cache->cache_value("forums_$ForumID", array($Forum, '', 0, $Stickies), 0);
66
+    }
67
+}
68
+
69
+if (!isset($Forums[$ForumID])) {
70
+    json_die("failure");
71
+}
72
+// Make sure they're allowed to look at the page
73
+if (!check_perms('site_moderate_forums')) {
74
+    if (isset($LoggedUser['CustomForums'][$ForumID]) && $LoggedUser['CustomForums'][$ForumID] === 0) {
75
+        json_die("failure", "insufficient permissions to view page");
76
+    }
77
+}
78
+if ($LoggedUser['CustomForums'][$ForumID] != 1 && $Forums[$ForumID]['MinClassRead'] > $LoggedUser['Class']) {
79
+    json_die("failure", "insufficient permissions to view page");
80
+}
81
+
82
+$ForumName = display_str($Forums[$ForumID]['Name']);
83
+$JsonSpecificRules = [];
84
+foreach ($Forums[$ForumID]['SpecificRules'] as $ThreadIDs) {
85
+    $Thread = Forums::get_thread_info($ThreadIDs);
86
+    $JsonSpecificRules[] = array(
87
+    'threadId' => (int)$ThreadIDs,
88
+    'thread' => display_str($Thread['Title'])
89
+  );
90
+}
91
+
92
+$Pages = Format::get_pages($Page, $Forums[$ForumID]['NumTopics'], TOPICS_PER_PAGE, 9);
93
+
94
+if (count($Forum) === 0) {
95
+    print
96
+    json_encode(
97
+        array(
98
+        'status' => 'success',
99
+        'forumName' => $ForumName,
100
+        'threads' => []
101
+      )
102
+    );
103
+} else {
104
+    // forums_last_read_topics is a record of the last post a user read in a topic, and what page that was on
105
+    $DB->query("
106
+    SELECT
107
+      l.TopicID,
108
+      l.PostID,
109
+      CEIL(
110
+        (
111
+          SELECT COUNT(p.ID)
112
+          FROM forums_posts AS p
113
+          WHERE p.TopicID = l.TopicID
114
+            AND p.ID <= l.PostID
115
+        ) / $PerPage
116
+      ) AS Page
117
+    FROM forums_last_read_topics AS l
118
+    WHERE l.TopicID IN(".implode(', ', array_keys($Forum)).')
119
+      AND l.UserID = \''.$LoggedUser['ID'].'\'');
120
+
121
+    // Turns the result set into a multi-dimensional array, with
122
+    // forums_last_read_topics.TopicID as the key.
123
+    // This is done here so we get the benefit of the caching, and we
124
+    // don't have to make a database query for each topic on the page
125
+    $LastRead = $DB->to_array('TopicID');
126
+
127
+    $JsonTopics = [];
128
+    foreach ($Forum as $Topic) {
129
+        list($TopicID, $Title, $AuthorID, $Locked, $Sticky, $PostCount, $LastID, $LastTime, $LastAuthorID) = array_values($Topic);
130
+
131
+        // Handle read/unread posts - the reason we can't cache the whole page
132
+        if ((!$Locked || $Sticky)
133
+        && ((empty($LastRead[$TopicID]) || $LastRead[$TopicID]['PostID'] < $LastID)
134
+          && strtotime($LastTime) > $LoggedUser['CatchupTime'])
135
+    ) {
136
+            $Read = 'unread';
137
+        } else {
138
+            $Read = 'read';
139
+        }
140
+        $UserInfo = Users::user_info($AuthorID);
141
+        $AuthorName = $UserInfo['Username'];
142
+        $UserInfo = Users::user_info($LastAuthorID);
143
+        $LastAuthorName = $UserInfo['Username'];
144
+        // Bug fix for no last time available
145
+        if (!$LastTime) {
146
+            $LastTime = '';
147
+        }
148
+
149
+        $JsonTopics[] = array(
150
+      'topicId' => (int)$TopicID,
151
+      'title' => display_str($Title),
152
+      'authorId' => (int)$AuthorID,
153
+      'authorName' => $AuthorName,
154
+      'locked' => $Locked === 1,
155
+      'sticky' => $Sticky === 1,
156
+      'postCount' => (int)$PostCount,
157
+      'lastID' => ($LastID === null) ? 0 : (int)$LastID,
158
+      'lastTime' => $LastTime,
159
+      'lastAuthorId' => ($LastAuthorID === null) ? 0 : (int)$LastAuthorID,
160
+      'lastAuthorName' => ($LastAuthorName === null) ? '' : $LastAuthorName,
161
+      'lastReadPage' => ($LastRead[$TopicID]['Page'] === null) ? 0 : (int)$LastRead[$TopicID]['Page'],
162
+      'lastReadPostId' => ($LastRead[$TopicID]['PostID'] === null) ? 0 : (int)$LastRead[$TopicID]['PostID'],
163
+      'read' => $Read === 'read'
164
+    );
165
+    }
166
+
167
+    print
168
+    json_encode(
169
+        array(
170
+        'status' => 'success',
171
+        'response' => array(
172
+          'forumName' => $ForumName,
173
+          'specificRules' => $JsonSpecificRules,
174
+          'currentPage' => (int)$Page,
175
+          'pages' => ceil($Forums[$ForumID]['NumTopics'] / TOPICS_PER_PAGE),
176
+          'threads' => $JsonTopics
177
+        )
178
+      )
179
+    );
180
+}

+ 34
- 0
sections/api/forum/index.php View File

@@ -0,0 +1,34 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+// Already done in /sections/ajax/index.php
5
+//enforce_login();
6
+
7
+if (!empty($LoggedUser['DisableForums'])) {
8
+    echo json_encode(array('status' => 'failure'));
9
+    error();
10
+} else {
11
+    // Replace the old hard-coded forum categories
12
+    $ForumCats = Forums::get_forum_categories();
13
+
14
+    // This variable contains all our lovely forum data
15
+    $Forums = Forums::get_forums();
16
+
17
+    if (empty($_GET['type']) || $_GET['type'] === 'main') {
18
+        include SERVER_ROOT.'/sections/ajax/forum/main.php';
19
+    } else {
20
+        switch ($_GET['type']) {
21
+        case 'viewforum':
22
+          include SERVER_ROOT.'/sections/ajax/forum/forum.php';
23
+          break;
24
+
25
+        case 'viewthread':
26
+          include SERVER_ROOT.'/sections/ajax/forum/thread.php';
27
+          break;
28
+
29
+        default:
30
+          echo json_encode(array('status' => 'failure'));
31
+          break;
32
+        }
33
+    }
34
+}

+ 117
- 0
sections/api/forum/main.php View File

@@ -0,0 +1,117 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+# todo: Go through line by line
5
+if (isset($LoggedUser['PostsPerPage'])) {
6
+    $PerPage = $LoggedUser['PostsPerPage'];
7
+} else {
8
+    $PerPage = POSTS_PER_PAGE;
9
+}
10
+
11
+// We have to iterate here because if one is empty it breaks the query
12
+$TopicIDs = [];
13
+foreach ($Forums as $Forum) {
14
+    if (!empty($Forum['LastPostTopicID'])) {
15
+        $TopicIDs[] = $Forum['LastPostTopicID'];
16
+    }
17
+}
18
+
19
+// Now if we have IDs' we run the query
20
+if (!empty($TopicIDs)) {
21
+    $DB->query("
22
+    SELECT
23
+      l.TopicID,
24
+      l.PostID,
25
+      CEIL(
26
+        (
27
+          SELECT COUNT(p.ID)
28
+          FROM forums_posts AS p
29
+          WHERE p.TopicID = l.TopicID
30
+            AND p.ID <= l.PostID
31
+        ) / $PerPage
32
+      ) AS Page
33
+    FROM forums_last_read_topics AS l
34
+    WHERE l.TopicID IN(".implode(',', $TopicIDs).")
35
+      AND l.UserID = '$LoggedUser[ID]'");
36
+    $LastRead = $DB->to_array('TopicID', MYSQLI_ASSOC);
37
+} else {
38
+    $LastRead = [];
39
+}
40
+
41
+$DB->query("
42
+  SELECT RestrictedForums
43
+  FROM users_info
44
+  WHERE UserID = ".$LoggedUser['ID']);
45
+list($RestrictedForums) = $DB->next_record();
46
+$RestrictedForums = explode(',', $RestrictedForums);
47
+$PermittedForums = array_keys($LoggedUser['PermittedForums']);
48
+
49
+$JsonCategories = [];
50
+$JsonCategory = [];
51
+$JsonForums = [];
52
+foreach ($Forums as $Forum) {
53
+    list($ForumID, $CategoryID, $ForumName, $ForumDescription, $MinRead, $MinWrite, $MinCreate, $NumTopics, $NumPosts, $LastPostID, $LastAuthorID, $LastTopicID, $LastTime, $SpecificRules, $LastTopic, $Locked, $Sticky) = array_values($Forum);
54
+    if ($LoggedUser['CustomForums'][$ForumID] != 1
55
+      && ($MinRead > $LoggedUser['Class']
56
+      || array_search($ForumID, $RestrictedForums) !== false)
57
+  ) {
58
+        continue;
59
+    }
60
+    $ForumDescription = display_str($ForumDescription);
61
+
62
+    if ($CategoryID != $LastCategoryID) {
63
+        if (!empty($JsonForums) && !empty($JsonCategory)) {
64
+            $JsonCategory['forums'] = $JsonForums;
65
+            $JsonCategories[] = $JsonCategory;
66
+        }
67
+        $LastCategoryID = $CategoryID;
68
+        $JsonCategory = array(
69
+      'categoryID' => (int)$CategoryID,
70
+      'categoryName' => $ForumCats[$CategoryID]
71
+    );
72
+        $JsonForums = [];
73
+    }
74
+
75
+    if ((!$Locked || $Sticky)
76
+      && $LastPostID != 0
77
+      && ((empty($LastRead[$LastTopicID]) || $LastRead[$LastTopicID]['PostID'] < $LastPostID)
78
+        && strtotime($LastTime) > $LoggedUser['CatchupTime'])
79
+  ) {
80
+        $Read = 'unread';
81
+    } else {
82
+        $Read = 'read';
83
+    }
84
+    $UserInfo = Users::user_info($LastAuthorID);
85
+
86
+    $JsonForums[] = array(
87
+    'forumId' => (int)$ForumID,
88
+    'forumName' => $ForumName,
89
+    'forumDescription' => $ForumDescription,
90
+    'numTopics' => (float)$NumTopics,
91
+    'numPosts' => (float)$NumPosts,
92
+    'lastPostId' => (float)$LastPostID,
93
+    'lastAuthorId' => (float)$LastAuthorID,
94
+    'lastPostAuthorName' => $UserInfo['Username'],
95
+    'lastTopicId' => (float)$LastTopicID,
96
+    'lastTime' => $LastTime,
97
+    'specificRules' => $SpecificRules,
98
+    'lastTopic' => display_str($LastTopic),
99
+    'read' => $Read === 1,
100
+    'locked' => $Locked === 1,
101
+    'sticky' => $Sticky === 1
102
+  );
103
+}
104
+// ...And an extra one to catch the last category.
105
+if (!empty($JsonForums) && !empty($JsonCategory)) {
106
+    $JsonCategory['forums'] = $JsonForums;
107
+    $JsonCategories[] = $JsonCategory;
108
+}
109
+
110
+echo json_encode(
111
+    array(
112
+    'status' => 'success',
113
+    'response' => array(
114
+      'categories' => $JsonCategories
115
+    )
116
+  )
117
+);

+ 291
- 0
sections/api/forum/thread.php View File

@@ -0,0 +1,291 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+# todo: Go through line by line
5
+// todo: Normalize thread_*_info don't need to waste all that ram on things that are already in other caches
6
+
7
+/**********|| Page to show individual threads || ********************************\
8
+
9
+Things to expect in $_GET:
10
+  ThreadID: ID of the forum curently being browsed
11
+  page: The page the user's on.
12
+  page = 1 is the same as no page
13
+
14
+********************************************************************************/
15
+
16
+//---------- Things to sort out before it can start printing/generating content
17
+
18
+// Check for lame SQL injection attempts
19
+if (!isset($_GET['threadid']) || !is_number($_GET['threadid'])) {
20
+    if (isset($_GET['topicid']) && is_number($_GET['topicid'])) {
21
+        $ThreadID = $_GET['topicid'];
22
+    } elseif (isset($_GET['postid']) && is_number($_GET['postid'])) {
23
+        $DB->query("
24
+        SELECT TopicID
25
+        FROM forums_posts
26
+          WHERE ID = $_GET[postid]");
27
+        list($ThreadID) = $DB->next_record();
28
+
29
+        if ($ThreadID) {
30
+            // Redirect postid to threadid when necessary
31
+            header("Location: ajax.php?action=forum&type=viewthread&threadid=$ThreadID&postid=$_GET[postid]");
32
+            error();
33
+        } else {
34
+            echo json_encode(array('status' => 'failure'));
35
+            error();
36
+        }
37
+    } else {
38
+        echo json_encode(array('status' => 'failure'));
39
+        error();
40
+    }
41
+} else {
42
+    $ThreadID = $_GET['threadid'];
43
+}
44
+
45
+if (isset($_GET['pp'])) {
46
+    $PerPage = $_GET['pp'];
47
+} elseif (isset($LoggedUser['PostsPerPage'])) {
48
+    $PerPage = $LoggedUser['PostsPerPage'];
49
+} else {
50
+    $PerPage = POSTS_PER_PAGE;
51
+}
52
+
53
+//---------- Get some data to start processing
54
+
55
+// Thread information, constant across all pages
56
+$ThreadInfo = Forums::get_thread_info($ThreadID, true, true);
57
+if ($ThreadInfo === null) {
58
+    json_die('failure', 'no such thread exists');
59
+}
60
+$ForumID = $ThreadInfo['ForumID'];
61
+
62
+// Make sure they're allowed to look at the page
63
+if (!Forums::check_forumperm($ForumID)) {
64
+    echo json_encode(array('status' => 'failure'));
65
+    error();
66
+}
67
+
68
+// Post links utilize the catalogue & key params to prevent issues with custom posts per page
69
+if ($ThreadInfo['Posts'] > $PerPage) {
70
+    if (isset($_GET['post']) && is_number($_GET['post'])) {
71
+        $PostNum = $_GET['post'];
72
+    } elseif (isset($_GET['postid']) && is_number($_GET['postid'])) {
73
+        $DB->query("
74
+        SELECT COUNT(ID)
75
+        FROM forums_posts
76
+          WHERE TopicID = $ThreadID
77
+          AND ID <= $_GET[postid]");
78
+        list($PostNum) = $DB->next_record();
79
+    } else {
80
+        $PostNum = 1;
81
+    }
82
+} else {
83
+    $PostNum = 1;
84
+}
85
+list($Page, $Limit) = Format::page_limit($PerPage, min($ThreadInfo['Posts'], $PostNum));
86
+if (($Page - 1) * $PerPage > $ThreadInfo['Posts']) {
87
+    $Page = ceil($ThreadInfo['Posts'] / $PerPage);
88
+}
89
+list($CatalogueID, $CatalogueLimit) = Format::catalogue_limit($Page, $PerPage, THREAD_CATALOGUE);
90
+
91
+// Cache catalogue from which the page is selected, allows block caches and future ability to specify posts per page
92
+if (!$Catalogue = $Cache->get_value("thread_$ThreadID"."_catalogue_$CatalogueID")) {
93
+    $DB->query("
94
+    SELECT
95
+      p.ID,
96
+      p.AuthorID,
97
+      p.AddedTime,
98
+      p.Body,
99
+      p.EditedUserID,
100
+      p.EditedTime
101
+    FROM forums_posts AS p
102
+    WHERE p.TopicID = '$ThreadID'
103
+      AND p.ID != '".$ThreadInfo['StickyPostID']."'
104
+    LIMIT $CatalogueLimit");
105
+    $Catalogue = $DB->to_array(false, MYSQLI_ASSOC);
106
+    if (!$ThreadInfo['IsLocked'] || $ThreadInfo['IsSticky']) {
107
+        $Cache->cache_value("thread_$ThreadID"."_catalogue_$CatalogueID", $Catalogue, 0);
108
+    }
109
+}
110
+$Thread = Format::catalogue_select($Catalogue, $Page, $PerPage, THREAD_CATALOGUE);
111
+
112
+if ($_GET['updatelastread'] !== '0') {
113
+    $LastPost = end($Thread);
114
+    $LastPost = $LastPost['ID'];
115
+    reset($Thread);
116
+    if ($ThreadInfo['Posts'] <= $PerPage * $Page && $ThreadInfo['StickyPostID'] > $LastPost) {
117
+        $LastPost = $ThreadInfo['StickyPostID'];
118
+    }
119
+    // Handle last read
120
+    if (!$ThreadInfo['IsLocked'] || $ThreadInfo['IsSticky']) {
121
+        $DB->query("
122
+        SELECT PostID
123
+        FROM forums_last_read_topics
124
+          WHERE UserID = '$LoggedUser[ID]'
125
+          AND TopicID = '$ThreadID'");
126
+        list($LastRead) = $DB->next_record();
127
+
128
+        if ($LastRead < $LastPost) {
129
+            $DB->query("
130
+            INSERT INTO forums_last_read_topics
131
+              (UserID, TopicID, PostID)
132
+            VALUES
133
+              ('$LoggedUser[ID]', '$ThreadID', '".db_string($LastPost)."')
134
+            ON DUPLICATE KEY UPDATE
135
+              PostID = '$LastPost'");
136
+        }
137
+    }
138
+}
139
+
140
+// Handle subscriptions
141
+$UserSubscriptions = Subscriptions::get_subscriptions();
142
+
143
+if (empty($UserSubscriptions)) {
144
+    $UserSubscriptions = [];
145
+}
146
+
147
+if (in_array($ThreadID, $UserSubscriptions)) {
148
+    $Cache->delete_value('subscriptions_user_new_'.$LoggedUser['ID']);
149
+}
150
+
151
+$JsonPoll = [];
152
+if ($ThreadInfo['NoPoll'] === 0) {
153
+    if (!list($Question, $Answers, $Votes, $Featured, $Closed) = $Cache->get_value("polls_$ThreadID")) {
154
+        $DB->query("
155
+        SELECT Question, Answers, Featured, Closed
156
+        FROM forums_polls
157
+          WHERE TopicID = '$ThreadID'");
158
+        list($Question, $Answers, $Featured, $Closed) = $DB->next_record(MYSQLI_NUM, array(1));
159
+        $Answers = unserialize($Answers);
160
+        $DB->query("
161
+        SELECT Vote, COUNT(UserID)
162
+        FROM forums_polls_votes
163
+          WHERE TopicID = '$ThreadID'
164
+        GROUP BY Vote");
165
+        $VoteArray = $DB->to_array(false, MYSQLI_NUM);
166
+
167
+        $Votes = [];
168
+        foreach ($VoteArray as $VoteSet) {
169
+            list($Key, $Value) = $VoteSet;
170
+            $Votes[$Key] = $Value;
171
+        }
172
+
173
+        foreach (array_keys($Answers) as $i) {
174
+            if (!isset($Votes[$i])) {
175
+                $Votes[$i] = 0;
176
+            }
177
+        }
178
+        $Cache->cache_value("polls_$ThreadID", array($Question, $Answers, $Votes, $Featured, $Closed), 0);
179
+    }
180
+
181
+    if (!empty($Votes)) {
182
+        $TotalVotes = array_sum($Votes);
183
+        $MaxVotes = max($Votes);
184
+    } else {
185
+        $TotalVotes = 0;
186
+        $MaxVotes = 0;
187
+    }
188
+
189
+    #$RevealVoters = in_array($ForumID, FORUMS_TO_REVEAL_VOTERS);
190
+
191
+    // Polls lose the you voted arrow thingy
192
+    $DB->query("
193
+    SELECT Vote
194
+    FROM forums_polls_votes
195
+      WHERE UserID = '".$LoggedUser['ID']."'
196
+      AND TopicID = '$ThreadID'");
197
+    list($UserResponse) = $DB->next_record();
198
+    if (!empty($UserResponse) && $UserResponse !== 0) {
199
+        $Answers[$UserResponse] = '&rsaquo; '.$Answers[$UserResponse];
200
+    } /* else {
201
+        if (!empty($UserResponse) && $RevealVoters) {
202
+            $Answers[$UserResponse] = '&rsaquo; '.$Answers[$UserResponse];
203
+        }
204
+    }
205
+    */
206
+
207
+    $JsonPoll['closed'] = ($Closed === 1);
208
+    $JsonPoll['featured'] = $Featured;
209
+    $JsonPoll['question'] = $Question;
210
+    $JsonPoll['maxVotes'] = (int)$MaxVotes;
211
+    $JsonPoll['totalVotes'] = $TotalVotes;
212
+    $JsonPollAnswers = [];
213
+
214
+    foreach ($Answers as $i => $Answer) {
215
+        if (!empty($Votes[$i]) && $TotalVotes > 0) {
216
+            $Ratio = $Votes[$i] / $MaxVotes;
217
+            $Percent = $Votes[$i] / $TotalVotes;
218
+        } else {
219
+            $Ratio = 0;
220
+            $Percent = 0;
221
+        }
222
+        $JsonPollAnswers[] = array(
223
+            'answer' => $Answer,
224
+            'ratio' => $Ratio,
225
+            'percent' => $Percent
226
+    );
227
+    }
228
+
229
+    if ($UserResponse !== null || $Closed || $ThreadInfo['IsLocked'] || $LoggedUser['Class'] < $Forums[$ForumID]['MinClassWrite']) {
230
+        $JsonPoll['voted'] = true;
231
+    } else {
232
+        $JsonPoll['voted'] = false;
233
+    }
234
+
235
+    $JsonPoll['answers'] = $JsonPollAnswers;
236
+}
237
+
238
+// Sqeeze in stickypost
239
+if ($ThreadInfo['StickyPostID']) {
240
+    if ($ThreadInfo['StickyPostID'] !== $Thread[0]['ID']) {
241
+        array_unshift($Thread, $ThreadInfo['StickyPost']);
242
+    }
243
+    if ($ThreadInfo['StickyPostID'] !== $Thread[count($Thread) - 1]['ID']) {
244
+        $Thread[] = $ThreadInfo['StickyPost'];
245
+    }
246
+}
247
+
248
+$JsonPosts = [];
249
+foreach ($Thread as $Key => $Post) {
250
+    list($PostID, $AuthorID, $AddedTime, $Body, $EditedUserID, $EditedTime) = array_values($Post);
251
+    list($AuthorID, $Username, $PermissionID, $Paranoia, $Artist, $Donor, $Warned, $Avatar, $Enabled, $UserTitle) = array_values(Users::user_info($AuthorID));
252
+
253
+    $UserInfo = Users::user_info($EditedUserID);
254
+    $JsonPosts[] = [
255
+    'postId' => (int)$PostID,
256
+    'addedTime' => $AddedTime,
257
+    'bbBody' => $Body,
258
+    'body' => Text::full_format($Body),
259
+    'editedUserId' => (int)$EditedUserID,
260
+    'editedTime' => $EditedTime,
261
+    'editedUsername' => $UserInfo['Username'],
262
+    'author' => [
263
+      'authorId' => (int)$AuthorID,
264
+      'authorName' => $Username,
265
+      'paranoia' => $Paranoia,
266
+      'artist' => $Artist === '1',
267
+      'donor' => $Donor === '1',
268
+      'warned' => (bool)$Warned,
269
+      'avatar' => $Avatar,
270
+      'enabled' => $Enabled === '2' ? false : true,
271
+      'userTitle' => $UserTitle
272
+    ]
273
+  ];
274
+}
275
+
276
+echo json_encode([
277
+  'status' => 'success',
278
+  'response' => [
279
+    'forumId' => (int)$ForumID,
280
+    'forumName' => $Forums[$ForumID]['Name'],
281
+    'threadId' => (int)$ThreadID,
282
+    'threadTitle' => display_str($ThreadInfo['Title']),
283
+    'subscribed' => in_array($ThreadID, $UserSubscriptions),
284
+    'locked' => $ThreadInfo['IsLocked'] === 1,
285
+    'sticky' => $ThreadInfo['IsSticky'] === 1,
286
+    'currentPage' => (int)$Page,
287
+    'pages' => ceil($ThreadInfo['Posts'] / $PerPage),
288
+    'poll' => empty($JsonPoll) ? null : $JsonPoll,
289
+    'posts' => $JsonPosts
290
+  ]
291
+]);

+ 21
- 0
sections/api/get_friends.php View File

@@ -0,0 +1,21 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+$DB->query("
5
+SELECT
6
+  f.FriendID,
7
+  u.Username
8
+FROM friends AS f
9
+  RIGHT JOIN users_enable_recommendations AS r
10
+  ON r.ID = f.FriendID
11
+    AND r.Enable = 1
12
+  RIGHT JOIN users_main AS u
13
+  ON u.ID = f.FriendID
14
+WHERE f.UserID = '$LoggedUser[ID]'
15
+ORDER BY u.Username ASC
16
+");
17
+
18
+json_die('success', json_encode($DB->to_array(false, MYSQLI_ASSOC)));
19
+
20
+#echo json_encode($DB->to_array(false, MYSQLI_ASSOC));
21
+#die();

+ 8
- 0
sections/api/get_user_notifications.php View File

@@ -0,0 +1,8 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+$Skip = [];
5
+$Skip[] = db_string($_GET['skip']);
6
+
7
+$NotificationsManager = new NotificationsManager($LoggedUser['ID'], $Skip);
8
+json_die('success', $NotificationsManager->get_notifications());

+ 118
- 0
sections/api/inbox/inbox.php View File

@@ -0,0 +1,118 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+$UserID = $LoggedUser['ID'];
5
+
6
+
7
+if (empty($_GET['type'])) {
8
+  $Section = 'inbox';
9
+} else {
10
+  $Section = $_GET['type']; // either 'inbox' or 'sentbox'
11
+}
12
+if (!in_array($Section, array('inbox', 'sentbox'))) {
13
+  print
14
+    json_encode(
15
+      array(
16
+        'status' => 'failure'
17
+      )
18
+    );
19
+  error();
20
+}
21
+
22
+list($Page, $Limit) = Format::page_limit(MESSAGES_PER_PAGE);
23
+
24
+$Sort = empty($_GET['sort']) || $_GET['sort'] != "unread" ? "Date DESC" : "cu.Unread = '1' DESC, DATE DESC";
25
+
26
+$sql = "
27
+  SELECT
28
+    SQL_CALC_FOUND_ROWS
29
+    c.ID,
30
+    c.Subject,
31
+    cu.Unread,
32
+    cu.Sticky,
33
+    cu.ForwardedTo,
34
+    um2.Username AS ForwardedName,
35
+    cu2.UserID,
36
+    um.Username,
37
+    ui.Donor,
38
+    ui.Warned,
39
+    um.Enabled,
40
+    ui.Avatar,";
41
+$sql .= $Section === 'sentbox' ? ' cu.SentDate ' : ' cu.ReceivedDate ';
42
+$sql .= "AS Date
43
+  FROM pm_conversations AS c
44
+    LEFT JOIN pm_conversations_users AS cu ON cu.ConvID = c.ID AND cu.UserID = '$UserID'
45
+    LEFT JOIN pm_conversations_users AS cu2 ON cu2.ConvID = c.ID AND cu2.UserID != '$UserID' AND cu2.ForwardedTo = 0
46
+    LEFT JOIN users_main AS um ON um.ID = cu2.UserID
47
+    LEFT JOIN users_info AS ui ON ui.UserID = um.ID
48
+    LEFT JOIN users_main AS um2 ON um2.ID = cu.ForwardedTo";
49
+
50
+if (!empty($_GET['search']) && $_GET['searchtype'] === 'message') {
51
+  $sql .= ' JOIN pm_messages AS m ON c.ID = m.ConvID';
52
+}
53
+$sql .= " WHERE ";
54
+if (!empty($_GET['search'])) {
55
+  $Search = db_string($_GET['search']);
56
+  if ($_GET['searchtype'] === 'user') {
57
+    $sql .= "um.Username LIKE '$Search' AND ";
58
+  } elseif ($_GET['searchtype'] === 'subject') {
59
+    $Words = explode(' ', $Search);
60
+    $sql .= "c.Subject LIKE '%".implode("%' AND c.Subject LIKE '%", $Words)."%' AND ";
61
+  } elseif ($_GET['searchtype'] === 'message') {
62
+    $Words = explode(' ', $Search);
63
+    $sql .= "m.Body LIKE '%".implode("%' AND m.Body LIKE '%", $Words)."%' AND ";
64
+  }
65
+}
66
+$sql .= $Section === 'sentbox' ? ' cu.InSentbox' : ' cu.InInbox';
67
+$sql .= " = '1'";
68
+
69
+$sql .= "
70
+  GROUP BY c.ID
71
+  ORDER BY cu.Sticky, $Sort
72
+  LIMIT $Limit";
73
+$Results = $DB->query($sql);
74
+$DB->query('SELECT FOUND_ROWS()');
75
+list($NumResults) = $DB->next_record();
76
+$DB->set_query_id($Results);
77
+
78
+$CurURL = Format::get_url(array('sort'));
79
+if (empty($CurURL)) {
80
+  $CurURL = "inbox.php?";
81
+} else {
82
+  $CurURL = "inbox.php?".$CurURL."&";
83
+}
84
+
85
+$Pages = Format::get_pages($Page, $NumResults, MESSAGES_PER_PAGE, 9);
86
+
87
+$JsonMessages = [];
88
+while (list($ConvID, $Subject, $Unread, $Sticky, $ForwardedID, $ForwardedName, $SenderID, $Username, $Donor, $Warned, $Enabled, $Avatar, $Date) = $DB->next_record()) {
89
+  $JsonMessage = array(
90
+    'convId' => (int)$ConvID,
91
+    'subject' => $Subject,
92
+    'unread' => $Unread == 1,
93
+    'sticky' => $Sticky == 1,
94
+    'forwardedId' => (int)$ForwardedID,
95
+    'forwardedName' => $ForwardedName,
96
+    'senderId' => (int)$SenderID,
97
+    'username' => $Username,
98
+    'avatar' => $Avatar,
99
+    'donor' => $Donor == 1,
100
+    'warned' => $Warned == 1,
101
+    'enabled' => $Enabled == 2 ? false : true,
102
+    'date' => $Date
103
+  );
104
+  $JsonMessages[] = $JsonMessage;
105
+}
106
+
107
+print
108
+  json_encode(
109
+    array(
110
+      'status' => 'success',
111
+      'response' => array(
112
+        'currentPage' => (int)$Page,
113
+        'pages' => ceil($NumResults / MESSAGES_PER_PAGE),
114
+        'messages' => $JsonMessages
115
+      )
116
+    )
117
+  );
118
+?>

+ 13
- 0
sections/api/inbox/index.php View File

@@ -0,0 +1,13 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+if (empty($_GET['type']) || $_GET['type'] == 'inbox' || $_GET['type'] == 'sentbox') {
5
+  require(SERVER_ROOT.'/sections/ajax/inbox/inbox.php');
6
+} elseif ($_GET['type'] == 'viewconv') {
7
+  require(SERVER_ROOT.'/sections/ajax/inbox/viewconv.php');
8
+} else {
9
+  echo json_encode(array('status' => 'failure'));
10
+  error();
11
+}
12
+
13
+?>

+ 106
- 0
sections/api/inbox/viewconv.php View File

@@ -0,0 +1,106 @@
1
+<?
2
+$ConvID = $_GET['id'];
3
+if (!$ConvID || !is_number($ConvID)) {
4
+  echo json_encode(array('status' => 'failure'));
5
+  error();
6
+}
7
+
8
+
9
+
10
+$UserID = $LoggedUser['ID'];
11
+$DB->query("
12
+  SELECT InInbox, InSentbox
13
+  FROM pm_conversations_users
14
+  WHERE UserID = '$UserID'
15
+    AND ConvID = '$ConvID'");
16
+if (!$DB->has_results()) {
17
+  echo json_encode(array('status' => 'failure'));
18
+  error();
19
+}
20
+list($InInbox, $InSentbox) = $DB->next_record();
21
+
22
+
23
+
24
+
25
+if (!$InInbox && !$InSentbox) {
26
+  echo json_encode(array('status' => 'failure'));
27
+  error();
28
+}
29
+
30
+// Get information on the conversation
31
+$DB->query("
32
+  SELECT
33
+    c.Subject,
34
+    cu.Sticky,
35
+    cu.UnRead,
36
+    cu.ForwardedTo,
37
+    um.Username
38
+  FROM pm_conversations AS c
39
+    JOIN pm_conversations_users AS cu ON c.ID = cu.ConvID
40
+    LEFT JOIN users_main AS um ON um.ID = cu.ForwardedTo
41
+  WHERE c.ID = '$ConvID'
42
+    AND UserID = '$UserID'");
43
+list($Subject, $Sticky, $UnRead, $ForwardedID, $ForwardedName) = $DB->next_record();
44
+
45
+$DB->query("
46
+  SELECT um.ID, Username
47
+  FROM pm_messages AS pm
48
+    JOIN users_main AS um ON um.ID = pm.SenderID
49
+  WHERE pm.ConvID = '$ConvID'");
50
+
51
+while (list($PMUserID, $Username) = $DB->next_record()) {
52
+  $PMUserID = (int)$PMUserID;
53
+  $Users[$PMUserID]['UserStr'] = Users::format_username($PMUserID, true, true, true, true);
54
+  $Users[$PMUserID]['Username'] = $Username;
55
+  $UserInfo = Users::user_info($PMUserID);
56
+  $Users[$PMUserID]['Avatar'] = $UserInfo['Avatar'];
57
+}
58
+$Users[0]['UserStr'] = 'System'; // in case it's a message from the system
59
+$Users[0]['Username'] = 'System';
60
+$Users[0]['Avatar'] = '';
61
+
62
+if ($UnRead == '1') {
63
+  $DB->query("
64
+    UPDATE pm_conversations_users
65
+    SET UnRead = '0'
66
+    WHERE ConvID = '$ConvID'
67
+      AND UserID = '$UserID'");
68
+  // Clear the caches of the inbox and sentbox
69
+  $Cache->decrement("inbox_new_$UserID");
70
+}
71
+
72
+// Get messages
73
+$DB->query("
74
+  SELECT SentDate, SenderID, Body, ID
75
+  FROM pm_messages
76
+  WHERE ConvID = '$ConvID'
77
+  ORDER BY ID");
78
+
79
+$JsonMessages = [];
80
+while (list($SentDate, $SenderID, $Body, $MessageID) = $DB->next_record()) {
81
+  $Body = apcu_exists('DBKEY') ? Crypto::decrypt($Body) : '[Encrypted]';
82
+  $JsonMessage = array(
83
+    'messageId' => (int)$MessageID,
84
+    'senderId' => (int)$SenderID,
85
+    'senderName' => $Users[(int)$SenderID]['Username'],
86
+    'sentDate' => $SentDate,
87
+    'avatar' => $Users[(int)$SenderID]['Avatar'],
88
+    'bbBody' => $Body,
89
+    'body' => Text::full_format($Body)
90
+  );
91
+  $JsonMessages[] = $JsonMessage;
92
+}
93
+
94
+print
95
+  json_encode(
96
+    array(
97
+      'status' => 'success',
98
+      'response' => array(
99
+        'convId' => (int)$ConvID,
100
+        'subject' => $Subject.($ForwardedID > 0 ? " (Forwarded to $ForwardedName)" : ''),
101
+        'sticky' => $Sticky == 1,
102
+        'messages' => $JsonMessages
103
+      )
104
+    )
105
+  );
106
+?>

+ 287
- 0
sections/api/index.php View File

@@ -0,0 +1,287 @@
1
+<?php
2
+declare(strict_types = 1);
3
+
4
+/**
5
+ * AJAX switch center
6
+ *
7
+ * This page acts as an AJAX "switch" - it's called by scripts, and it includes the required pages.
8
+ * The required page is determined by $_GET['action'].
9
+ */
10
+
11
+$ENV = ENV::go();
12
+
13
+# $_POST login cookie
14
+if (!isset($FullToken)) {
15
+    enforce_login();
16
+}
17
+
18
+
19
+/**
20
+ * These users aren't rate limited.
21
+ * This array should contain user IDs.
22
+ */
23
+
24
+# Get people with Donor permissions
25
+$Donors = $DB->query("
26
+SELECT
27
+  `ID`
28
+FROM
29
+  `users_main`
30
+WHERE
31
+  `PermissionID` = 20
32
+");
33
+
34
+# Add Donors to $UserExceptions or define manually
35
+if ($DB->record_count()) {
36
+    $UserExceptions = array_unique($DB->collect('ID'));
37
+} else {
38
+    $UserExceptions = array(
39
+      # 1, 2, 3, etc.
40
+    );
41
+}
42
+
43
+# System and admin fix
44
+array_push($UserExceptions, 0, 1);
45
+
46
+
47
+/**
48
+ * $AjaxLimit = array($x, $y) = $x requests every $y seconds,
49
+ * e.g., array(5, 10) = 5 requests every 10 seconds.
50
+ */
51
+$AjaxLimit = array(1, 6);
52
+$UserID = $LoggedUser['ID'];
53
+
54
+# Set proper headers for JSON output
55
+# https://github.com/OPSnet/Gazelle/blob/master/sections/api/index.php
56
+if (!empty($_SERVER['CONTENT_TYPE']) && substr($_SERVER['CONTENT_TYPE'], 0, 16) === 'application/json') {
57
+    $_POST = json_decode(file_get_contents('php://input'), true);
58
+}
59
+header('Content-Type: application/json; charset=utf-8');
60
+
61
+# Enforce rate limiting everywhere
62
+if (!in_array($UserID, $UserExceptions) && isset($_GET['action'])) {
63
+    if (!$UserRequests = $Cache->get_value("ajax_requests_$UserID")) {
64
+        $UserRequests = 0;
65
+        $Cache->cache_value("ajax_requests_$UserID", '0', $AjaxLimit[1]);
66
+    }
67
+
68
+    if ($UserRequests > $AjaxLimit[0]) {
69
+        json_die('failure', 'rate limit exceeded');
70
+    } else {
71
+        $Cache->increment_value("ajax_requests_$UserID");
72
+    }
73
+}
74
+
75
+
76
+/**
77
+ * Actions
78
+ */
79
+
80
+switch ($_GET['action']) {
81
+    /**
82
+     * Torrents
83
+     */
84
+    case 'torrent':
85
+      require_once "$ENV->SERVER_ROOT/sections/api/torrents/torrent.php";
86
+      break;
87
+
88
+    case 'group':
89
+      require_once "$ENV->SERVER_ROOT/sections/api/torrents/group.php";
90
+      break;
91
+
92
+  // So the album art script can function without breaking the rate limit
93
+  case 'torrentgroupalbumart':
94
+    require_once "$ENV->SERVER_ROOT/sections/api/torrentgroupalbumart.php";
95
+    break;
96
+
97
+  case 'browse':
98
+    require_once "$ENV->SERVER_ROOT/sections/api/browse.php";
99
+    break;
100
+  
101
+   case 'tcomments':
102
+    require_once "$ENV->SERVER_ROOT/sections/api/tcomments.php";
103
+    break;
104
+
105
+  /**
106
+   * Features
107
+   */
108
+  case 'collage':
109
+    require_once "$ENV->SERVER_ROOT/sections/api/collage.php";
110
+    break;
111
+  
112
+  case 'artist':
113
+    require_once "$ENV->SERVER_ROOT/sections/api/artist.php";
114
+    break;
115
+
116
+  case 'request':
117
+    require_once "$ENV->SERVER_ROOT/sections/api/request.php";
118
+    break;
119
+
120
+  case 'requests':
121
+    require_once "$ENV->SERVER_ROOT/sections/api/requests.php";
122
+    break;
123
+
124
+  case 'top10':
125
+    require_once "$ENV->SERVER_ROOT/sections/api/top10/index.php";
126
+    break;
127
+
128
+  /**
129
+   * Users
130
+   */
131
+  case 'user':
132
+    require_once "$ENV->SERVER_ROOT/sections/api/user.php";
133
+    break;
134
+
135
+  case 'usersearch':
136
+    require_once "$ENV->SERVER_ROOT/sections/api/usersearch.php";
137
+    break;
138
+  
139
+  case 'community_stats':
140
+    require_once "$ENV->SERVER_ROOT/sections/api/community_stats.php";
141
+    break;
142
+
143
+  case 'user_recents':
144
+    require_once "$ENV->SERVER_ROOT/sections/api/user_recents.php";
145
+    break;
146
+
147
+  case 'userhistory':
148
+    require_once "$ENV->SERVER_ROOT/sections/api/userhistory/index.php";
149
+    break;
150
+
151
+  /**
152
+   * Account
153
+   */
154
+  case 'inbox':
155
+    require_once "$ENV->SERVER_ROOT/sections/api/inbox/index.php";
156
+    break;
157
+
158
+  case 'bookmarks':
159
+    require_once "$ENV->SERVER_ROOT/sections/api/bookmarks/index.php";
160
+    break;
161
+
162
+  case 'notifications':
163
+    require_once "$ENV->SERVER_ROOT/sections/api/notifications.php";
164
+    break;
165
+
166
+  case 'get_user_notifications':
167
+    require_once "$ENV->SERVER_ROOT/sections/api/get_user_notifications.php";
168
+    break;
169
+
170
+  case 'clear_user_notification':
171
+    require_once "$ENV->SERVER_ROOT/sections/api/clear_user_notification.php";
172
+    break;
173
+
174
+  /**
175
+   * Forums
176
+   */
177
+  case 'forum':
178
+    require_once "$ENV->SERVER_ROOT/sections/api/forum/index.php";
179
+    break;
180
+
181
+  case 'subscriptions':
182
+    require_once "$ENV->SERVER_ROOT/sections/api/subscriptions.php";
183
+    break;
184
+
185
+  case 'raw_bbcode':
186
+    require_once "$ENV->SERVER_ROOT/sections/api/raw_bbcode.php";
187
+    break;
188
+
189
+  /**
190
+   * Meta
191
+   */
192
+  case 'index':
193
+    require_once "$ENV->SERVER_ROOT/sections/api/info.php";
194
+    break;
195
+
196
+  case 'manifest':
197
+    require_once "$ENV->SERVER_ROOT/manifest.php";
198
+    json_die('success', manifest());
199
+    break;
200
+
201
+  case 'stats':
202
+    require_once "$ENV->SERVER_ROOT/sections/api/stats.php";
203
+    break;
204
+
205
+  case 'loadavg':
206
+    require_once "$ENV->SERVER_ROOT/sections/api/loadavg.php";
207
+    break;
208
+
209
+  case 'announcements':
210
+    require_once "$ENV->SERVER_ROOT/sections/api/announcements.php";
211
+    break;
212
+
213
+  case 'wiki':
214
+    require_once "$ENV->SERVER_ROOT/sections/api/wiki.php";
215
+    break;
216
+  
217
+  case 'ontology':
218
+    require_once "$ENV->SERVER_ROOT/sections/api/ontology.php";
219
+    break;
220
+  
221
+  /**
222
+   * Under construction
223
+   */
224
+  case 'preview':
225
+    require_once "$ENV->SERVER_ROOT/sections/api/preview.php";
226
+    break;
227
+
228
+  case 'better':
229
+    require_once "$ENV->SERVER_ROOT/sections/api/better/index.php";
230
+    break;
231
+
232
+  case 'get_friends':
233
+    require_once "$ENV->SERVER_ROOT/sections/api/get_friends.php";
234
+    break;
235
+
236
+  case 'news_ajax':
237
+    require_once "$ENV->SERVER_ROOT/sections/api/news_ajax.php";
238
+    break;
239
+
240
+  case 'send_recommendation':
241
+    require_once "$ENV->SERVER_ROOT/sections/api/send_recommendation.php";
242
+    break;
243
+
244
+  /*
245
+  case 'similar_artists':
246
+    require_once "$ENV->SERVER_ROOT/sections/api/similar_artists.php";
247
+    break;
248
+  */
249
+
250
+  /*
251
+  case 'votefavorite':
252
+    require_once "$ENV->SERVER_ROOT/sections/api/takevote.php";
253
+    break;
254
+  */
255
+
256
+  /*
257
+  case 'torrent_info':
258
+    require_once "$ENV->SERVER_ROOT/sections/api/torrent_info.php";
259
+    break;
260
+  */
261
+
262
+  /*
263
+  case 'checkprivate':
264
+    include "$ENV->SERVER_ROOT/sections/api/checkprivate.php";
265
+    break;
266
+  */
267
+
268
+  case 'autofill':
269
+    /*
270
+    if ($_GET['cat'] === 'anime') {
271
+        require_once "$ENV->SERVER_ROOT/sections/api/autofill/anime.php";
272
+    }
273
+
274
+    if ($_GET['cat'] === 'jav') {
275
+        require_once "$ENV->SERVER_ROOT/sections/api/autofill/jav.php";
276
+    }
277
+
278
+    if ($_GET['cat'] === 'manga') {
279
+        require_once "$ENV->SERVER_ROOT/sections/api/autofill/manga.php";
280
+    }
281
+    */
282
+    break;
283
+
284
+  default:
285
+    // If they're screwing around with the query string
286
+    json_die('failure');
287
+}

+ 117
- 0
sections/api/info.php View File

@@ -0,0 +1,117 @@
1
+<?
2
+//calculate ratio
3
+//returns 0 for DNE and -1 for infinity, because we don't want strings being returned for a numeric value in our java
4
+$Ratio = 0;
5
+if ($LoggedUser['BytesUploaded'] == 0 && $LoggedUser['BytesDownloaded'] == 0) {
6
+  $Ratio = 0;
7
+} elseif ($LoggedUser['BytesDownloaded'] == 0) {
8
+  $Ratio = -1;
9
+} else {
10
+  $Ratio = number_format(max($LoggedUser['BytesUploaded'] / $LoggedUser['BytesDownloaded'] - 0.005, 0), 2); //Subtract .005 to floor to 2 decimals
11
+}
12
+
13
+$MyNews = $LoggedUser['LastReadNews'];
14
+$CurrentNews = $Cache->get_value('news_latest_id');
15
+if ($CurrentNews === false) {
16
+  $DB->query("
17
+    SELECT ID
18
+    FROM news
19
+    ORDER BY Time DESC
20
+    LIMIT 1");
21
+  if ($DB->record_count() === 1) {
22
+    list($CurrentNews) = $DB->next_record();
23
+  } else {
24
+    $CurrentNews = -1;
25
+  }
26
+  $Cache->cache_value('news_latest_id', $CurrentNews, 0);
27
+}
28
+
29
+$NewMessages = $Cache->get_value('inbox_new_' . $LoggedUser['ID']);
30
+if ($NewMessages === false) {
31
+  $DB->query("
32
+    SELECT COUNT(UnRead)
33
+    FROM pm_conversations_users
34
+    WHERE UserID = '" . $LoggedUser['ID'] . "'
35
+      AND UnRead = '1'
36
+      AND InInbox = '1'");
37
+  list($NewMessages) = $DB->next_record();
38
+  $Cache->cache_value('inbox_new_' . $LoggedUser['ID'], $NewMessages, 0);
39
+}
40
+
41
+if (check_perms('site_torrents_notify')) {
42
+  $NewNotifications = $Cache->get_value('notifications_new_' . $LoggedUser['ID']);
43
+  if ($NewNotifications === false) {
44
+    $DB->query("
45
+      SELECT COUNT(UserID)
46
+      FROM users_notify_torrents
47
+      WHERE UserID = '$LoggedUser[ID]'
48
+        AND UnRead = '1'");
49
+    list($NewNotifications) = $DB->next_record();
50
+    /* if ($NewNotifications && !check_perms('site_torrents_notify')) {
51
+        $DB->query("DELETE FROM users_notify_torrents WHERE UserID='$LoggedUser[ID]'");
52
+        $DB->query("DELETE FROM users_notify_filters WHERE UserID='$LoggedUser[ID]'");
53
+    } */
54
+    $Cache->cache_value('notifications_new_' . $LoggedUser['ID'], $NewNotifications, 0);
55
+  }
56
+}
57
+
58
+// News
59
+$MyNews = $LoggedUser['LastReadNews'];
60
+$CurrentNews = $Cache->get_value('news_latest_id');
61
+if ($CurrentNews === false) {
62
+  $DB->query("
63
+    SELECT ID
64
+    FROM news
65
+    ORDER BY Time DESC
66
+    LIMIT 1");
67
+  if ($DB->record_count() === 1) {
68
+    list($CurrentNews) = $DB->next_record();
69
+  } else {
70
+    $CurrentNews = -1;
71
+  }
72
+  $Cache->cache_value('news_latest_id', $CurrentNews, 0);
73
+}
74
+
75
+// Blog
76
+$MyBlog = $LoggedUser['LastReadBlog'];
77
+$CurrentBlog = $Cache->get_value('blog_latest_id');
78
+if ($CurrentBlog === false) {
79
+  $DB->query("
80
+    SELECT ID
81
+    FROM blog
82
+    WHERE Important = 1
83
+    ORDER BY Time DESC
84
+    LIMIT 1");
85
+  if ($DB->record_count() === 1) {
86
+    list($CurrentBlog) = $DB->next_record();
87
+  } else {
88
+    $CurrentBlog = -1;
89
+  }
90
+  $Cache->cache_value('blog_latest_id', $CurrentBlog, 0);
91
+}
92
+
93
+// Subscriptions
94
+$NewSubscriptions = Subscriptions::has_new_subscriptions();
95
+
96
+json_die("success", array(
97
+  'username' => $LoggedUser['Username'],
98
+  'id' => (int)$LoggedUser['ID'],
99
+  'authkey' => $LoggedUser['AuthKey'],
100
+  'passkey' => $LoggedUser['torrent_pass'],
101
+  'notifications' => array(
102
+    'messages' => (int)$NewMessages,
103
+    'notifications' => (int)$NewNotifications,
104
+    'newAnnouncement' => $MyNews < $CurrentNews,
105
+    'newBlog' => $MyBlog < $CurrentBlog,
106
+    'newSubscriptions' => $NewSubscriptions == 1
107
+  ),
108
+  'userstats' => array(
109
+    'uploaded' => (int)$LoggedUser['BytesUploaded'],
110
+    'downloaded' => (int)$LoggedUser['BytesDownloaded'],
111
+    'ratio' => (float)$Ratio,
112
+    'requiredratio' => (float)$LoggedUser['RequiredRatio'],
113
+    'class' => $ClassLevels[$LoggedUser['Class']]['Name']
114
+  )
115
+));
116
+
117
+?>

+ 14
- 0
sections/api/loadavg.php View File

@@ -0,0 +1,14 @@
1
+<?php
2
+declare(strict_types=1);
3
+
4
+#authorize();
5
+
6
+print
7
+  json_encode(
8
+      array(
9
+        'status' => 'success',
10
+        'response' => array(
11
+          'loadAverage' => sys_getloadavg()
12
+        )
13
+      )
14
+  );

+ 42
- 0
sections/api/news_ajax.php View File

@@ -0,0 +1,42 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+// Don't allow bigger queries than specified below regardless of called function
5
+$SizeLimit = 10;
6
+
7
+$Count = (int)$_GET['count'];
8
+$Offset = (int)$_GET['offset'];
9
+
10
+if (!isset($_GET['count']) || !isset($_GET['offset']) || $Count <= 0 || $Offset < 0 || $Count > $SizeLimit) {
11
+    json_die('failure');
12
+}
13
+
14
+Text::$TOC = true;
15
+
16
+global $DB;
17
+$DB->query("
18
+    SELECT
19
+      ID,
20
+      Title,
21
+      Body,
22
+      Time
23
+    FROM news
24
+    ORDER BY Time DESC
25
+    LIMIT $Offset, $Count");
26
+$News = $DB->to_array(false, MYSQLI_NUM, false);
27
+
28
+$NewsResponse = [];
29
+foreach ($News as $NewsItem) {
30
+    list($NewsID, $Title, $Body, $NewsTime) = $NewsItem;
31
+    array_push(
32
+        $NewsResponse,
33
+        array(
34
+      $NewsID,
35
+      Text::full_format($Title),
36
+      time_diff($NewsTime),
37
+      Text::full_format($Body)
38
+    )
39
+    );
40
+}
41
+
42
+json_die('success', json_encode($NewsResponse));

+ 110
- 0
sections/api/notifications.php View File

@@ -0,0 +1,110 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+# todo: Go through line by line
5
+if (!check_perms('site_torrents_notify')) {
6
+    json_die('failure');
7
+}
8
+
9
+define('NOTIFICATIONS_PER_PAGE', 50);
10
+list($Page, $Limit) = Format::page_limit(NOTIFICATIONS_PER_PAGE);
11
+
12
+$Results = $DB->query("
13
+    SELECT
14
+      SQL_CALC_FOUND_ROWS
15
+      unt.TorrentID,
16
+      unt.UnRead,
17
+      unt.FilterID,
18
+      unf.Label,
19
+      t.GroupID
20
+    FROM users_notify_torrents AS unt
21
+      JOIN torrents AS t ON t.ID = unt.TorrentID
22
+      LEFT JOIN users_notify_filters AS unf ON unf.ID = unt.FilterID
23
+    WHERE unt.UserID = $LoggedUser[ID]".
24
+    ((!empty($_GET['filterid']) && is_number($_GET['filterid']))
25
+      ? " AND unf.ID = '$_GET[filterid]'"
26
+      : '')."
27
+    ORDER BY TorrentID DESC
28
+    LIMIT $Limit");
29
+$GroupIDs = array_unique($DB->collect('GroupID'));
30
+
31
+$DB->query('SELECT FOUND_ROWS()');
32
+list($TorrentCount) = $DB->next_record();
33
+
34
+if (count($GroupIDs)) {
35
+    $TorrentGroups = Torrents::get_groups($GroupIDs);
36
+    $DB->query("
37
+    UPDATE users_notify_torrents
38
+    SET UnRead = '0'
39
+    WHERE UserID = $LoggedUser[ID]");
40
+    $Cache->delete_value("notifications_new_$LoggedUser[ID]");
41
+}
42
+
43
+$DB->set_query_id($Results);
44
+
45
+$JsonNotifications = [];
46
+$NumNew = 0;
47
+
48
+$FilterGroups = [];
49
+while ($Result = $DB->next_record(MYSQLI_ASSOC)) {
50
+    if (!$Result['FilterID']) {
51
+        $Result['FilterID'] = 0;
52
+    }
53
+    if (!isset($FilterGroups[$Result['FilterID']])) {
54
+        $FilterGroups[$Result['FilterID']] = [];
55
+        $FilterGroups[$Result['FilterID']]['FilterLabel'] = ($Result['Label'] ? $Result['Label'] : false);
56
+    }
57
+    array_push($FilterGroups[$Result['FilterID']], $Result);
58
+}
59
+unset($Result);
60
+
61
+foreach ($FilterGroups as $FilterID => $FilterResults) {
62
+    unset($FilterResults['FilterLabel']);
63
+    foreach ($FilterResults as $Result) {
64
+        $TorrentID = $Result['TorrentID'];
65
+//    $GroupID = $Result['GroupID'];
66
+
67
+        $GroupInfo = $TorrentGroups[$Result['GroupID']];
68
+        extract(Torrents::array_group($GroupInfo)); // all group data
69
+        $TorrentInfo = $GroupInfo['Torrents'][$TorrentID];
70
+
71
+        if ($Result['UnRead'] == 1) {
72
+            $NumNew++;
73
+        }
74
+
75
+        $JsonNotifications[] = array(
76
+      'torrentId' => (int)$TorrentID,
77
+      'groupId' => (int)$GroupID,
78
+      'groupName' => $GroupName,
79
+      'groupCategoryId' => (int)$GroupCategoryID,
80
+      'wikiImage' => $WikiImage,
81
+      'torrentTags' => $TagList,
82
+      'size' => (float)$TorrentInfo['Size'],
83
+      'fileCount' => (int)$TorrentInfo['FileCount'],
84
+      'format' => $TorrentInfo['Format'],
85
+      'encoding' => $TorrentInfo['Encoding'],
86
+      'media' => $TorrentInfo['Media'],
87
+      'scene' => $TorrentInfo['Scene'] == 1,
88
+      'groupYear' => (int)$GroupYear,
89
+      'remasterYear' => (int)$TorrentInfo['RemasterYear'],
90
+      'remasterTitle' => $TorrentInfo['RemasterTitle'],
91
+      'snatched' => (int)$TorrentInfo['Snatched'],
92
+      'seeders' => (int)$TorrentInfo['Seeders'],
93
+      'leechers' => (int)$TorrentInfo['Leechers'],
94
+      'notificationTime' => $TorrentInfo['Time'],
95
+      'hasLog' => $TorrentInfo['HasLog'] == 1,
96
+      'hasCue' => $TorrentInfo['HasCue'] == 1,
97
+      'logScore' => (float)$TorrentInfo['LogScore'],
98
+      'freeTorrent' => $TorrentInfo['FreeTorrent'] == 1,
99
+      'logInDb' => $TorrentInfo['HasLog'] == 1,
100
+      'unread' => $Result['UnRead'] == 1
101
+    );
102
+    }
103
+}
104
+
105
+json_die('success', array(
106
+  'currentPages' => intval($Page),
107
+  'pages' => ceil($TorrentCount / NOTIFICATIONS_PER_PAGE),
108
+  'numNew' => $NumNew,
109
+  'results' => $JsonNotifications
110
+));

+ 12
- 0
sections/api/ontology.php View File

@@ -0,0 +1,12 @@
1
+<?php
2
+declare(strict_types = 1);
3
+
4
+# Quick proof-of-concept
5
+$ENV = ENV::go();
6
+print
7
+  json_encode(
8
+      array(
9
+        'status' => 'success',
10
+        'response' => $ENV->CATS
11
+      )
12
+  );

+ 12
- 0
sections/api/preview.php View File

@@ -0,0 +1,12 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+/* AJAX previews, simple stuff */
5
+Text::$TOC = true;
6
+
7
+if (!empty($_POST['AdminComment'])) {
8
+    echo Text::full_format($_POST['AdminComment']);
9
+} else {
10
+    $Content = $_REQUEST['body']; // Don't use URL decode
11
+    echo Text::full_format($Content);
12
+}

+ 32
- 0
sections/api/raw_bbcode.php View File

@@ -0,0 +1,32 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+$PostID = (int) $_GET['postid'];
5
+
6
+if (empty($PostID)) {
7
+    json_die('error', 'empty postid');
8
+}
9
+
10
+$DB->query("
11
+SELECT
12
+  t.`ForumID`,
13
+  p.`Body`
14
+FROM
15
+  `forums_posts` AS p
16
+JOIN `forums_topics` AS t
17
+ON
18
+  p.`TopicID` = t.`ID`
19
+WHERE
20
+  p.`ID` = '$PostID'
21
+");
22
+
23
+if (!$DB->has_results()) {
24
+    json_die('error', 'no results');
25
+}
26
+
27
+list($ForumID, $Body) = $DB->next_record();
28
+if (!Forums::check_forumperm($ForumID)) {
29
+    json_die('error', 'assholes');
30
+}
31
+
32
+json_die('success', array('body' => nl2br($Body)));

+ 119
- 0
sections/api/request.php View File

@@ -0,0 +1,119 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+$RequestTax = 0.1;
5
+
6
+// Minimum and default amount of upload to remove from the user when they vote.
7
+// Also change in static/functions/requests.js
8
+$MinimumVote = 20 * 1024 * 1024;
9
+
10
+/*
11
+ * This is the page that displays the request to the end user after being created.
12
+ */
13
+
14
+if (empty($_GET['id']) || !is_number($_GET['id'])) {
15
+    json_die("failure");
16
+}
17
+
18
+$RequestID = (int)$_GET['id'];
19
+
20
+//First things first, lets get the data for the request.
21
+
22
+$Request = Requests::get_request($RequestID);
23
+if ($Request === false) {
24
+    json_die("failure");
25
+}
26
+
27
+$CategoryID = $Request['CategoryID'];
28
+$Requestor = Users::user_info($Request['UserID']);
29
+$Filler = $Request['FillerID'] ? Users::user_info($Request['FillerID']) : null;
30
+//Convenience variables
31
+$IsFilled = !empty($Request['TorrentID']);
32
+$CanVote = !$IsFilled && check_perms('site_vote');
33
+
34
+if ($CategoryID == 0) {
35
+    $CategoryName = 'Unknown';
36
+} else {
37
+    $CategoryName = $Categories[$CategoryID - 1];
38
+}
39
+
40
+$JsonArtists = Requests::get_artists($RequestID);
41
+
42
+//Votes time
43
+$RequestVotes = Requests::get_votes_array($RequestID);
44
+$VoteCount = count($RequestVotes['Voters']);
45
+$ProjectCanEdit = (check_perms('project_team') && !$IsFilled && (($CategoryID == 0) || ($CategoryName == 'Music' && $Request['Year'] == 0)));
46
+$UserCanEdit = (!$IsFilled && $LoggedUser['ID'] == $Request['UserID'] && $VoteCount < 2);
47
+$CanEdit = ($UserCanEdit || $ProjectCanEdit || check_perms('site_moderate_requests'));
48
+
49
+$JsonTopContributors = [];
50
+$VoteMax = ($VoteCount < 5 ? $VoteCount : 5);
51
+for ($i = 0; $i < $VoteMax; $i++) {
52
+    $User = array_shift($RequestVotes['Voters']);
53
+    $JsonTopContributors[] = array(
54
+    'userId'   => (int)$User['UserID'],
55
+    'userName' => $User['Username'],
56
+    'bounty'   => (int)$User['Bounty']
57
+  );
58
+}
59
+reset($RequestVotes['Voters']);
60
+
61
+list($NumComments, $Page, $Thread) = Comments::load('requests', $RequestID, false);
62
+
63
+$JsonRequestComments = [];
64
+foreach ($Thread as $Key => $Post) {
65
+    list($PostID, $AuthorID, $AddedTime, $Body, $EditedUserID, $EditedTime, $EditedUsername) = array_values($Post);
66
+    list($AuthorID, $Username, $PermissionID, $Paranoia, $Artist, $Donor, $Warned, $Avatar, $Enabled, $UserTitle) = array_values(Users::user_info($AuthorID));
67
+    $JsonRequestComments[] = array(
68
+    'postId'          => (int)$PostID,
69
+    'authorId'        => (int)$AuthorID,
70
+    'name'            => $Username,
71
+    'donor'           => ($Donor == 1),
72
+    'warned'          => (bool)$Warned,
73
+    'enabled'         => ($Enabled == 2 ? false : true),
74
+    'class'           => Users::make_class_string($PermissionID),
75
+    'addedTime'       => $AddedTime,
76
+    'avatar'          => $Avatar,
77
+    'comment'         => Text::full_format($Body),
78
+    'editedUserId'    => (int)$EditedUserID,
79
+    'editedUsername'  => $EditedUsername,
80
+    'editedTime'      => $EditedTime
81
+  );
82
+}
83
+
84
+$JsonTags = [];
85
+foreach ($Request['Tags'] as $Tag) {
86
+    $JsonTags[] = $Tag;
87
+}
88
+json_die('success', array(
89
+  'requestId'       => (int)$RequestID,
90
+  'requestorId'     => (int)$Request['UserID'],
91
+  'requestorName'   => $Requestor['Username'],
92
+  'isBookmarked'    => Bookmarks::has_bookmarked('request', $RequestID),
93
+  'requestTax'      => (float)$RequestTax,
94
+  'timeAdded'       => $Request['TimeAdded'],
95
+  'canEdit'         => (bool)$CanEdit,
96
+  'canVote'         => (bool)$CanVote,
97
+  'minimumVote'     => (int)$MinimumVote,
98
+  'voteCount'       => (int)$VoteCount,
99
+  'lastVote'        => $Request['LastVote'],
100
+  'topContributors' => $JsonTopContributors,
101
+  'totalBounty'     => (int)$RequestVotes['TotalBounty'],
102
+  'categoryId'      => (int)$CategoryID,
103
+  'categoryName'    => $CategoryName,
104
+  'title'           => $Request['Title'],
105
+  'year'            => (int)$Request['Year'],
106
+  'image'           => $Request['Image'],
107
+  'bbDescription'   => $Request['Description'],
108
+  'description'     => Text::full_format($Request['Description']),
109
+  'artists'         => $JsonArtists,
110
+  'isFilled'        => (bool)$IsFilled,
111
+  'fillerId'        => (int)$Request['FillerID'],
112
+  'fillerName'      => $Filler ? $Filler['Username'] : '',
113
+  'torrentId'       => (int)$Request['TorrentID'],
114
+  'timeFilled'      => $Request['TimeFilled'],
115
+  'tags'            => $JsonTags,
116
+  'comments'        => $JsonRequestComments,
117
+  'commentPage'     => (int)$Page,
118
+  'commentPages'    => (int)ceil($NumComments / TORRENT_COMMENTS_PER_PAGE)
119
+));

+ 369
- 0
sections/api/requests.php View File

@@ -0,0 +1,369 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+# todo: Go through line by line
5
+$SphQL = new SphinxqlQuery();
6
+$SphQL->select('id, votes, bounty')->from('requests, requests_delta');
7
+
8
+$SortOrders = array(
9
+  'votes' => 'votes',
10
+  'bounty' => 'bounty',
11
+  'lastvote' => 'lastvote',
12
+  'filled' => 'timefilled',
13
+  'year' => 'year',
14
+  'created' => 'timeadded',
15
+  'random' => false);
16
+
17
+if (empty($_GET['order']) || !isset($SortOrders[$_GET['order']])) {
18
+    $_GET['order'] = 'created';
19
+}
20
+$OrderBy = $_GET['order'];
21
+
22
+if (!empty($_GET['sort']) && $_GET['sort'] === 'asc') {
23
+    $OrderWay = 'asc';
24
+} else {
25
+    $_GET['sort'] = 'desc';
26
+    $OrderWay = 'desc';
27
+}
28
+$NewSort = $_GET['sort'] === 'asc' ? 'desc' : 'asc';
29
+
30
+if ($OrderBy === 'random') {
31
+    $SphQL->order_by('RAND()', '');
32
+    unset($_GET['page']);
33
+} else {
34
+    $SphQL->order_by($SortOrders[$OrderBy], $OrderWay);
35
+}
36
+
37
+$Submitted = !empty($_GET['submit']);
38
+
39
+//Paranoia
40
+if (!empty($_GET['userid'])) {
41
+    if (!is_number($_GET['userid'])) {
42
+        json_die("failure");
43
+    }
44
+    $UserInfo = Users::user_info($_GET['userid']);
45
+    if (empty($UserInfo)) {
46
+        json_die("failure");
47
+    }
48
+    $Perms = Permissions::get_permissions($UserInfo['PermissionID']);
49
+    $UserClass = $Perms['Class'];
50
+}
51
+$BookmarkView = false;
52
+
53
+if (empty($_GET['type'])) {
54
+    $Title = 'Requests';
55
+    if (empty($_GET['showall'])) {
56
+        $SphQL->where('visible', 1);
57
+    }
58
+} else {
59
+    switch ($_GET['type']) {
60
+    case 'created':
61
+      if (!empty($UserInfo)) {
62
+          if (!check_paranoia('requestsvoted_list', $UserInfo['Paranoia'], $Perms['Class'], $UserInfo['ID'])) {
63
+              json_die("failure");
64
+          }
65
+          $Title = "Requests created by $UserInfo[Username]";
66
+          $SphQL->where('userid', $UserInfo['ID']);
67
+      } else {
68
+          $Title = 'My requests';
69
+          $SphQL->where('userid', $LoggedUser['ID']);
70
+      }
71
+      break;
72
+    case 'voted':
73
+      if (!empty($UserInfo)) {
74
+          if (!check_paranoia('requestsvoted_list', $UserInfo['Paranoia'], $Perms['Class'], $UserInfo['ID'])) {
75
+              json_die("failure");
76
+          }
77
+          $Title = "Requests voted for by $UserInfo[Username]";
78
+          $SphQL->where('voter', $UserInfo['ID']);
79
+      } else {
80
+          $Title = 'Requests I have voted on';
81
+          $SphQL->where('voter', $LoggedUser['ID']);
82
+      }
83
+      break;
84
+    case 'filled':
85
+      if (!empty($UserInfo)) {
86
+          if (!check_paranoia('requestsfilled_list', $UserInfo['Paranoia'], $Perms['Class'], $UserInfo['ID'])) {
87
+              json_die("failure");
88
+          }
89
+          $Title = "Requests filled by $UserInfo[Username]";
90
+          $SphQL->where('fillerid', $UserInfo['ID']);
91
+      } else {
92
+          $Title = 'Requests I have filled';
93
+          $SphQL->where('fillerid', $LoggedUser['ID']);
94
+      }
95
+      break;
96
+    case 'bookmarks':
97
+      $Title = 'Your bookmarked requests';
98
+      $BookmarkView = true;
99
+      $SphQL->where('bookmarker', $LoggedUser['ID']);
100
+      break;
101
+    default:
102
+      json_die("failure");
103
+  }
104
+}
105
+
106
+if ($Submitted && empty($_GET['show_filled'])) {
107
+    $SphQL->where('torrentid', 0);
108
+}
109
+
110
+if (!empty($_GET['formats'])) {
111
+    $FormatArray = $_GET['formats'];
112
+    if (count($FormatArray) !== count($Formats)) {
113
+        $FormatNameArray = [];
114
+        foreach ($FormatArray as $Index => $MasterIndex) {
115
+            if (isset($Formats[$MasterIndex])) {
116
+                $FormatNameArray[$Index] = '"' . strtr(Sphinxql::sph_escape_string($Formats[$MasterIndex]), '-.', '  ') . '"';
117
+            }
118
+        }
119
+        if (count($FormatNameArray) >= 1) {
120
+            if (!empty($_GET['formats_strict'])) {
121
+                $SearchString = '(' . implode(' | ', $FormatNameArray) . ')';
122
+            } else {
123
+                $SearchString = '(any | ' . implode(' | ', $FormatNameArray) . ')';
124
+            }
125
+            $SphQL->where_match($SearchString, 'formatlist', false);
126
+        }
127
+    }
128
+}
129
+
130
+if (!empty($_GET['media'])) {
131
+    $MediaArray = $_GET['media'];
132
+    if (count($MediaArray) !== count($Media)) {
133
+        $MediaNameArray = [];
134
+        foreach ($MediaArray as $Index => $MasterIndex) {
135
+            if (isset($Media[$MasterIndex])) {
136
+                $MediaNameArray[$Index] = '"' . strtr(Sphinxql::sph_escape_string($Media[$MasterIndex]), '-.', '  ') . '"';
137
+            }
138
+        }
139
+
140
+        if (count($MediaNameArray) >= 1) {
141
+            if (!empty($_GET['media_strict'])) {
142
+                $SearchString = '(' . implode(' | ', $MediaNameArray) . ')';
143
+            } else {
144
+                $SearchString = '(any | ' . implode(' | ', $MediaNameArray) . ')';
145
+            }
146
+            $SphQL->where_match($SearchString, 'medialist', false);
147
+        }
148
+    }
149
+}
150
+
151
+if (!empty($_GET['bitrates'])) {
152
+    $BitrateArray = $_GET['bitrates'];
153
+    if (count($BitrateArray) !== count($Bitrates)) {
154
+        $BitrateNameArray = [];
155
+        foreach ($BitrateArray as $Index => $MasterIndex) {
156
+            if (isset($Bitrates[$MasterIndex])) {
157
+                $BitrateNameArray[$Index] = '"' . strtr(Sphinxql::sph_escape_string($Bitrates[$MasterIndex]), '-.', '  ') . '"';
158
+            }
159
+        }
160
+
161
+        if (count($BitrateNameArray) >= 1) {
162
+            if (!empty($_GET['bitrate_strict'])) {
163
+                $SearchString = '(' . implode(' | ', $BitrateNameArray) . ')';
164
+            } else {
165
+                $SearchString = '(any | ' . implode(' | ', $BitrateNameArray) . ')';
166
+            }
167
+            $SphQL->where_match($SearchString, 'bitratelist', false);
168
+        }
169
+    }
170
+}
171
+
172
+if (!empty($_GET['search'])) {
173
+    $SearchString = trim($_GET['search']);
174
+    if ($SearchString !== '') {
175
+        $SearchWords = array('include' => [], 'exclude' => []);
176
+        $Words = explode(' ', $SearchString);
177
+        foreach ($Words as $Word) {
178
+            $Word = trim($Word);
179
+            // Skip isolated hyphens to enable "Artist - Title" searches
180
+            if ($Word === '-') {
181
+                continue;
182
+            }
183
+            if ($Word[0] === '!' && strlen($Word) >= 2) {
184
+                if (strpos($Word, '!', 1) === false) {
185
+                    $SearchWords['exclude'][] = $Word;
186
+                } else {
187
+                    $SearchWords['include'][] = $Word;
188
+                }
189
+            } elseif ($Word !== '') {
190
+                $SearchWords['include'][] = $Word;
191
+            }
192
+        }
193
+    }
194
+}
195
+
196
+if (!isset($_GET['tags_type']) || $_GET['tags_type'] === '1') {
197
+    $TagType = 1;
198
+    $_GET['tags_type'] = '1';
199
+} else {
200
+    $TagType = 0;
201
+    $_GET['tags_type'] = '0';
202
+}
203
+if (!empty($_GET['tags'])) {
204
+    $SearchTags = array('include' => [], 'exclude' => []);
205
+    $Tags = explode(',', $_GET['tags']);
206
+    foreach ($Tags as $Tag) {
207
+        $Tag = trim($Tag);
208
+        if ($Tag[0] === '!' && strlen($Tag) >= 2) {
209
+            if (strpos($Tag, '!', 1) === false) {
210
+                $SearchTags['exclude'][] = $Tag;
211
+            } else {
212
+                $SearchTags['include'][] = $Tag;
213
+            }
214
+        } elseif ($Tag !== '') {
215
+            $SearchTags['include'][] = $Tag;
216
+        }
217
+    }
218
+
219
+    $TagFilter = Tags::tag_filter_sph($SearchTags, $TagType);
220
+
221
+    if (!empty($TagFilter['predicate'])) {
222
+        $SphQL->where_match($TagFilter['predicate'], 'taglist', false);
223
+    }
224
+} elseif (!isset($_GET['tags_type']) || $_GET['tags_type'] !== '0') {
225
+    $_GET['tags_type'] = 1;
226
+} else {
227
+    $_GET['tags_type'] = 0;
228
+}
229
+
230
+if (isset($SearchWords)) {
231
+    $QueryParts = [];
232
+    foreach ($SearchWords['include'] as $Word) {
233
+        $QueryParts[] = Sphinxql::sph_escape_string($Word);
234
+    }
235
+    if (!empty($SearchWords['exclude'])) {
236
+        foreach ($SearchWords['exclude'] as $Word) {
237
+            $QueryParts[] = '!' . Sphinxql::sph_escape_string(substr($Word, 1));
238
+        }
239
+    }
240
+    if (!empty($QueryParts)) {
241
+        $SearchString = implode(' ', $QueryParts);
242
+        $SphQL->where_match($SearchString, '*', false);
243
+    }
244
+}
245
+
246
+if (!empty($_GET['filter_cat'])) {
247
+    $CategoryArray = array_keys($_GET['filter_cat']);
248
+    if (count($CategoryArray) !== count($Categories)) {
249
+        foreach ($CategoryArray as $Key => $Index) {
250
+            if (!isset($Categories[$Index - 1])) {
251
+                unset($CategoryArray[$Key]);
252
+            }
253
+        }
254
+        if (count($CategoryArray) >= 1) {
255
+            $SphQL->where('categoryid', $CategoryArray);
256
+        }
257
+    }
258
+}
259
+
260
+if (!empty($_GET['releases'])) {
261
+    $ReleaseArray = $_GET['releases'];
262
+    if (count($ReleaseArray) !== count($ReleaseTypes)) {
263
+        foreach ($ReleaseArray as $Index => $Value) {
264
+            if (!isset($ReleaseTypes[$Value])) {
265
+                unset($ReleaseArray[$Index]);
266
+            }
267
+        }
268
+        if (count($ReleaseArray) >= 1) {
269
+            $SphQL->where('releasetype', $ReleaseArray);
270
+        }
271
+    }
272
+}
273
+
274
+if (!empty($_GET['requestor'])) {
275
+    if (is_number($_GET['requestor'])) {
276
+        $SphQL->where('userid', $_GET['requestor']);
277
+    } else {
278
+        error(404);
279
+    }
280
+}
281
+
282
+if (isset($_GET['year'])) {
283
+    if (is_number($_GET['year']) || $_GET['year'] === '0') {
284
+        $SphQL->where('year', $_GET['year']);
285
+    } else {
286
+        error(404);
287
+    }
288
+}
289
+
290
+if (!empty($_GET['page']) && is_number($_GET['page']) && $_GET['page'] > 0) {
291
+    $Page = $_GET['page'];
292
+    $Offset = ($Page - 1) * REQUESTS_PER_PAGE;
293
+    $SphQL->limit($Offset, REQUESTS_PER_PAGE, $Offset + REQUESTS_PER_PAGE);
294
+} else {
295
+    $Page = 1;
296
+    $SphQL->limit(0, REQUESTS_PER_PAGE, REQUESTS_PER_PAGE);
297
+}
298
+
299
+$SphQLResult = $SphQL->query();
300
+$NumResults = (int)$SphQLResult->get_meta('total_found');
301
+if ($NumResults > 0) {
302
+    $SphRequests = $SphQLResult->to_array('id');
303
+    if ($OrderBy === 'random') {
304
+        $NumResults = count($RequestIDs);
305
+    }
306
+    if ($NumResults > REQUESTS_PER_PAGE) {
307
+        if (($Page - 1) * REQUESTS_PER_PAGE > $NumResults) {
308
+            $Page = 0;
309
+        }
310
+    }
311
+}
312
+
313
+if ($NumResults == 0) {
314
+    json_die("success", array(
315
+    'currentPage' => 1,
316
+    'pages'       => 1,
317
+    'results'     => []
318
+  ));
319
+} else {
320
+    $JsonResults = [];
321
+    $Requests = Requests::get_requests(array_keys($SphRequests));
322
+    foreach ($SphRequests as $RequestID => $SphRequest) {
323
+        $Request = $Requests[$RequestID];
324
+        $VoteCount = $SphRequest['votes'];
325
+        $Bounty = $SphRequest['bounty'] * 1024; // Sphinx stores bounty in kB
326
+        $Requestor = Users::user_info($Request['UserID']);
327
+        $Filler = $Request['FillerID'] ? Users::user_info($Request['FillerID']) : null;
328
+
329
+        if ($Request['CategoryID'] == 0) {
330
+            $CategoryName = 'Unknown';
331
+        } else {
332
+            $CategoryName = $Categories[$Request['CategoryID'] - 1];
333
+        }
334
+
335
+        $JsonArtists = Requests::get_artists($RequestID);
336
+
337
+        $Tags = $Request['Tags'];
338
+
339
+        $JsonResults[] = array(
340
+      'requestId'     => (int)$RequestID,
341
+      'requestorId'   => (int)$Requestor['ID'],
342
+      'requestorName' => $Requestor['Username'],
343
+      'timeAdded'     => $Request['TimeAdded'],
344
+      'lastVote'      => $Request['LastVote'],
345
+      'voteCount'     => (int)$VoteCount,
346
+      'bounty'        => (int)$Bounty,
347
+      'categoryId'    => (int)$Request['CategoryID'],
348
+      'categoryName'  => $CategoryName,
349
+      'authors'       => $JsonArtists,
350
+      #'artists'       => $JsonArtists,
351
+      'title'         => $Request['Title'],
352
+      'year'          => (int)$Request['Year'],
353
+      'picture'         => $Request['Image'],
354
+      #'image'         => $Request['Image'],
355
+      'description'   => $Request['Description'],
356
+      'isFilled'      => ($Request['TorrentID'] > 0),
357
+      'fillerId'      => (int)$Request['FillerID'],
358
+      'fillerName'    => $Filler ? $Filler['Username'] : '',
359
+      'torrentId'     => (int)$Request['TorrentID'],
360
+      'timeFilled'    => $Request['TimeFilled'] == 0 ? '' : $Request['TimeFilled']
361
+    );
362
+    }
363
+
364
+    json_die("success", array(
365
+    'currentPage' => intval($Page),
366
+    'pages'       => ceil($NumResults / REQUESTS_PER_PAGE),
367
+    'results'     => $JsonResults
368
+  ));
369
+}

+ 90
- 0
sections/api/send_recommendation.php View File

@@ -0,0 +1,90 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+$FriendID = (int) $_POST['friend'];
5
+$Type = $_POST['type'];
6
+$ID = (int) $_POST['id'];
7
+$Note = $_POST['note'];
8
+
9
+if (empty($FriendID) || empty($Type) || empty($ID)) {
10
+    echo json_encode(array('status' => 'error', 'response' => 'Error.'));
11
+    error();
12
+}
13
+
14
+// Make sure the recipient is on your friends list and not some random dude.
15
+$DB->query("
16
+SELECT
17
+  f.`FriendID`,
18
+  u.`Username`
19
+FROM
20
+  `friends` AS f
21
+RIGHT JOIN `users_enable_recommendations` AS r
22
+ON
23
+  r.`ID` = f.`FriendID` AND r.`Enable` = 1
24
+RIGHT JOIN `users_main` AS u
25
+ON
26
+  u.`ID` = f.`FriendID`
27
+WHERE
28
+  f.`UserID` = '$LoggedUser[ID]' AND f.`FriendID` = '$FriendID'
29
+");
30
+
31
+if (!$DB->has_results()) {
32
+    echo json_encode(array('status' => 'error', 'response' => 'Not on friend list.'));
33
+    error();
34
+}
35
+
36
+$Type = strtolower($Type);
37
+$Link = '';
38
+// "a" vs "an", english language is so confusing.
39
+// https://en.wikipedia.org/wiki/English_articles#Distinction_between_a_and_an
40
+$Article = 'a';
41
+switch ($Type) {
42
+    case 'torrent':
43
+    $Link = "torrents.php?id=$ID";
44
+    $DB->query("
45
+    SELECT
46
+      `title`
47
+    FROM
48
+      `torrents_group`
49
+    WHERE
50
+      `id` = '$ID'
51
+    ");
52
+      break;
53
+
54
+    case 'artist':
55
+    $Article = 'an';
56
+    $Link = "artist.php?id=$ID";
57
+    $DB->query("
58
+    SELECT
59
+      `Name`
60
+    FROM
61
+      `artists_group`
62
+    WHERE
63
+      `ArtistID` = '$ID'
64
+    ");
65
+    break;
66
+
67
+    case 'collage':
68
+    $Link = "collages.php?id=$ID";
69
+    $DB->query("
70
+    SELECT
71
+      `Name`
72
+    FROM
73
+      `collages`
74
+    WHERE
75
+      `ID` = '$ID'
76
+    ");
77
+    break;
78
+}
79
+
80
+list($Name) = $DB->next_record();
81
+$Subject = $LoggedUser['Username'] . " recommended you $Article $Type!";
82
+$Body = $LoggedUser['Username'] . " recommended you the $Type [url=".site_url()."$Link]$Name".'[/url].';
83
+
84
+if (!empty($Note)) {
85
+    $Body = "$Body\n\n$Note";
86
+}
87
+
88
+Misc::send_pm($FriendID, $LoggedUser['ID'], $Subject, $Body);
89
+echo json_encode(array('status' => 'success', 'response' => 'Sent!'));
90
+die();

+ 165
- 0
sections/api/stats.php View File

@@ -0,0 +1,165 @@
1
+<?php
2
+declare(strict_types=1);
3
+
4
+// Begin user stats
5
+if (($UserCount = $Cache->get_value('stats_user_count')) === false) {
6
+    $DB->query("
7
+    SELECT
8
+      COUNT(`ID`)
9
+    FROM
10
+      `users_main`
11
+    WHERE
12
+      `Enabled` = '1'
13
+    ");
14
+    list($UserCount) = $DB->next_record();
15
+    $Cache->cache_value('stats_user_count', $UserCount, 0); // inf cache
16
+}
17
+
18
+if (($UserStats = $Cache->get_value('stats_users')) === false) {
19
+    $DB->query("
20
+    SELECT
21
+      COUNT(`ID`)
22
+    FROM
23
+      `users_main`
24
+    WHERE
25
+      `Enabled` = '1'
26
+    AND `LastAccess` > '".time_minus(3600 * 24)."'
27
+    ");
28
+    list($UserStats['Day']) = $DB->next_record();
29
+
30
+    $DB->query("
31
+    SELECT
32
+      COUNT(`ID`)
33
+    FROM
34
+      `users_main`
35
+    WHERE
36
+      `Enabled` = '1'
37
+    AND `LastAccess` > '".time_minus(3600 * 24 * 7)."'
38
+    ");
39
+    list($UserStats['Week']) = $DB->next_record();
40
+
41
+    $DB->query("
42
+    SELECT
43
+      COUNT(`ID`)
44
+    FROM
45
+      `users_main`
46
+    WHERE
47
+      `Enabled` = '1'
48
+    AND LastAccess > '".time_minus(3600 * 24 * 30)."'
49
+    ");
50
+    list($UserStats['Month']) = $DB->next_record();
51
+
52
+    $Cache->cache_value('stats_users', $UserStats, 0);
53
+}
54
+
55
+// Begin torrent stats
56
+if (($TorrentCount = $Cache->get_value('stats_torrent_count')) === false) {
57
+    $DB->query("
58
+    SELECT
59
+      COUNT(`ID`)
60
+    FROM
61
+      `torrents`
62
+    ");
63
+    list($TorrentCount) = $DB->next_record();
64
+    $Cache->cache_value('stats_torrent_count', $TorrentCount, 604800); // staggered 1 week cache
65
+}
66
+
67
+if (($AlbumCount = $Cache->get_value('stats_album_count')) === false) {
68
+    $DB->query("
69
+    SELECT
70
+      COUNT(`id`)
71
+    FROM
72
+      `torrents_group`
73
+    WHERE
74
+      `category_id` = '1'
75
+    ");
76
+
77
+    list($AlbumCount) = $DB->next_record();
78
+    $Cache->cache_value('stats_album_count', $AlbumCount, 604830); // staggered 1 week cache
79
+}
80
+
81
+if (($ArtistCount = $Cache->get_value('stats_artist_count')) === false) {
82
+    $DB->query("
83
+    SELECT
84
+      COUNT(`ArtistID`)
85
+    FROM
86
+      `artists_group`
87
+    ");
88
+    
89
+    list($ArtistCount) = $DB->next_record();
90
+    $Cache->cache_value('stats_artist_count', $ArtistCount, 604860); // staggered 1 week cache
91
+}
92
+
93
+// Begin request stats
94
+if (($RequestStats = $Cache->get_value('stats_requests')) === false) {
95
+    $DB->query("
96
+    SELECT
97
+      COUNT(`ID`)
98
+    FROM
99
+      `requests`
100
+    ");
101
+    list($RequestCount) = $DB->next_record();
102
+
103
+    $DB->query("
104
+    SELECT
105
+      COUNT(`ID`)
106
+    FROM
107
+      `requests`
108
+    WHERE
109
+      `FillerID` > 0
110
+    ");
111
+    list($FilledCount) = $DB->next_record();
112
+    $Cache->cache_value('stats_requests', array($RequestCount, $FilledCount), 11280);
113
+} else {
114
+    list($RequestCount, $FilledCount) = $RequestStats;
115
+}
116
+
117
+// Begin swarm stats
118
+if (($PeerStats = $Cache->get_value('stats_peers')) === false) {
119
+    // Cache lock!
120
+    if ($Cache->get_query_lock('peer_stats')) {
121
+        $DB->query("
122
+        SELECT
123
+        IF(
124
+          `remaining` = 0,
125
+          'Seeding',
126
+          'Leeching'
127
+        ) AS `Type`,
128
+        COUNT(`uid`)
129
+        FROM
130
+          `xbt_files_users`
131
+        WHERE
132
+          `active` = 1
133
+        GROUP BY
134
+          `Type`
135
+        ");
136
+
137
+        $PeerCount = $DB->to_array(0, MYSQLI_NUM, false);
138
+        $LeecherCount = isset($PeerCount['Leeching']) ? $PeerCount['Leeching'][1] : 0;
139
+        $SeederCount = isset($PeerCount['Seeding']) ? $PeerCount['Seeding'][1] : 0;
140
+        $Cache->cache_value('stats_peers', array($LeecherCount, $SeederCount), 1209600); // 2 week cache
141
+        $Cache->clear_query_lock('peer_stats');
142
+    } else {
143
+        $LeecherCount = $SeederCount = 0;
144
+    }
145
+} else {
146
+    list($LeecherCount, $SeederCount) = $PeerStats;
147
+}
148
+
149
+json_print('success', array(
150
+  'maxUsers' => USER_LIMIT,
151
+  'enabledUsers' => (int) $UserCount,
152
+  'usersActiveThisDay' => (int) $UserStats['Day'],
153
+  'usersActiveThisWeek' => (int) $UserStats['Week'],
154
+  'usersActiveThisMonth' => (int) $UserStats['Month'],
155
+
156
+  'torrentCount' => (int) $TorrentCount,
157
+  'groupCount' => (int) $AlbumCount,
158
+  'artistCount' => (int) $ArtistCount,
159
+
160
+  'requestCount' => (int) $RequestCount,
161
+  'filledRequestCount' => (int) $FilledCount,
162
+
163
+  'seederCount' => (int) $SeederCount,
164
+  'leecherCount' => (int) $LeecherCount
165
+));

+ 92
- 0
sections/api/subscriptions.php View File

@@ -0,0 +1,92 @@
1
+<?php
2
+/*
3
+User topic subscription page
4
+*/
5
+
6
+if (!empty($LoggedUser['DisableForums'])) {
7
+  json_die('failure');
8
+}
9
+
10
+if (isset($LoggedUser['PostsPerPage'])) {
11
+  $PerPage = $LoggedUser['PostsPerPage'];
12
+} else {
13
+  $PerPage = POSTS_PER_PAGE;
14
+}
15
+list($Page, $Limit) = Format::page_limit($PerPage);
16
+
17
+$ShowUnread = (!isset($_GET['showunread']) && !isset($HeavyInfo['SubscriptionsUnread']) || isset($HeavyInfo['SubscriptionsUnread']) && !!$HeavyInfo['SubscriptionsUnread'] || isset($_GET['showunread']) && !!$_GET['showunread']);
18
+$ShowCollapsed = (!isset($_GET['collapse']) && !isset($HeavyInfo['SubscriptionsCollapse']) || isset($HeavyInfo['SubscriptionsCollapse']) && !!$HeavyInfo['SubscriptionsCollapse'] || isset($_GET['collapse']) && !!$_GET['collapse']);
19
+$sql = '
20
+  SELECT
21
+    SQL_CALC_FOUND_ROWS
22
+    MAX(p.ID) AS ID
23
+  FROM forums_posts AS p
24
+    LEFT JOIN forums_topics AS t ON t.ID = p.TopicID
25
+    JOIN users_subscriptions AS s ON s.TopicID = t.ID
26
+    LEFT JOIN forums AS f ON f.ID = t.ForumID
27
+    LEFT JOIN forums_last_read_topics AS l ON p.TopicID = l.TopicID AND l.UserID = s.UserID
28
+  WHERE s.UserID = '.$LoggedUser['ID'].'
29
+    AND p.ID <= IFNULL(l.PostID, t.LastPostID)
30
+    AND ' . Forums::user_forums_sql();
31
+if ($ShowUnread) {
32
+  $sql .= '
33
+    AND IF(l.PostID IS NULL OR (t.IsLocked = \'1\' && t.IsSticky = \'0\'), t.LastPostID, l.PostID) < t.LastPostID';
34
+}
35
+$sql .= "
36
+  GROUP BY t.ID
37
+  ORDER BY t.LastPostID DESC
38
+  LIMIT $Limit";
39
+$PostIDs = $DB->query($sql);
40
+$DB->query('SELECT FOUND_ROWS()');
41
+list($NumResults) = $DB->next_record();
42
+
43
+if ($NumResults > $PerPage * ($Page - 1)) {
44
+  $DB->set_query_id($PostIDs);
45
+  $PostIDs = $DB->collect('ID');
46
+  $sql = '
47
+    SELECT
48
+      f.ID AS ForumID,
49
+      f.Name AS ForumName,
50
+      p.TopicID,
51
+      t.Title,
52
+      p.Body,
53
+      t.LastPostID,
54
+      t.IsLocked,
55
+      t.IsSticky,
56
+      p.ID,
57
+      um.ID,
58
+      um.Username,
59
+      ui.Avatar,
60
+      p.EditedUserID,
61
+      p.EditedTime,
62
+      ed.Username AS EditedUsername
63
+    FROM forums_posts AS p
64
+      LEFT JOIN forums_topics AS t ON t.ID = p.TopicID
65
+      LEFT JOIN forums AS f ON f.ID = t.ForumID
66
+      LEFT JOIN users_main AS um ON um.ID = p.AuthorID
67
+      LEFT JOIN users_info AS ui ON ui.UserID = um.ID
68
+      LEFT JOIN users_main AS ed ON ed.ID = um.ID
69
+    WHERE p.ID IN ('.implode(',', $PostIDs).')
70
+    ORDER BY f.Name ASC, t.LastPostID DESC';
71
+  $DB->query($sql);
72
+}
73
+
74
+$JsonPosts = [];
75
+while (list($ForumID, $ForumName, $TopicID, $ThreadTitle, $Body, $LastPostID, $Locked, $Sticky, $PostID, $AuthorID, $AuthorName, $AuthorAvatar, $EditedUserID, $EditedTime, $EditedUsername) = $DB->next_record()) {
76
+  $JsonPost = array(
77
+    'forumId' => (int)$ForumID,
78
+    'forumName' => $ForumName,
79
+    'threadId' => (int)$TopicID,
80
+    'threadTitle' => $ThreadTitle,
81
+    'postId' => (int)$PostID,
82
+    'lastPostId' => (int)$LastPostID,
83
+    'locked' => $Locked == 1,
84
+    'new' => ($PostID < $LastPostID && !$Locked)
85
+  );
86
+  $JsonPosts[] = $JsonPost;
87
+}
88
+
89
+json_die('success', array(
90
+  'threads' => $JsonPosts
91
+));
92
+?>

+ 42
- 0
sections/api/tcomments.php View File

@@ -0,0 +1,42 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+if (empty($_GET['id']) || !is_number($_GET['id'])) {
5
+    json_die('failure');
6
+}
7
+
8
+list($NumComments, $Page, $Thread) = Comments::load('torrents', (int)$_GET['id'], false);
9
+
10
+# Begin printing
11
+$JsonComments = [];
12
+foreach ($Thread as $Key => $Post) {
13
+    list($PostID, $AuthorID, $AddedTime, $Body, $EditedUserID, $EditedTime, $EditedUsername) = array_values($Post);
14
+    list($AuthorID, $Username, $PermissionID, $Paranoia, $Artist, $Donor, $Warned, $Avatar, $Enabled, $UserTitle) = array_values(Users::user_info($AuthorID));
15
+
16
+    $JsonComments[] = [
17
+      'postId' => (int) $PostID,
18
+      'addedTime' => $AddedTime,
19
+      'bbBody' => $Body,
20
+      'body' => Text::full_format($Body),
21
+      'editedUserId' => (int) $EditedUserID,
22
+      'editedTime' => $EditedTime,
23
+      'editedUsername' => $EditedUsername,
24
+
25
+      'userinfo' => [
26
+        'authorId' => (int) $AuthorID,
27
+        'authorName' => $Username,
28
+        'artist' => $Artist === 1,
29
+        'donor' => $Donor === 1,
30
+        'warned' => (bool) $Warned,
31
+        'avatar' => $Avatar,
32
+        'enabled' => ($Enabled === 2 ? false : true),
33
+        'userTitle' => $UserTitle
34
+      ]
35
+    ];
36
+}
37
+
38
+json_die('success', [
39
+  'page' => (int) $Page,
40
+  'pages' => ceil($NumComments / TORRENT_COMMENTS_PER_PAGE),
41
+  'comments' => $JsonComments
42
+]);

+ 32
- 0
sections/api/top10/index.php View File

@@ -0,0 +1,32 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+// Already done in /sections/ajax/index.php
5
+//enforce_login();
6
+
7
+if (!check_perms('site_top10')) {
8
+    echo json_encode(array('status' => 'failure'));
9
+    error();
10
+}
11
+
12
+if (empty($_GET['type']) || $_GET['type'] === 'torrents') {
13
+    include SERVER_ROOT.'/sections/ajax/top10/torrents.php';
14
+} else {
15
+    switch ($_GET['type']) {
16
+    case 'users':
17
+      include SERVER_ROOT.'/sections/ajax/top10/users.php';
18
+      break;
19
+
20
+    case 'tags':
21
+      include SERVER_ROOT.'/sections/ajax/top10/tags.php';
22
+      break;
23
+
24
+    case 'history':
25
+      include SERVER_ROOT.'/sections/ajax/top10/history.php';
26
+      break;
27
+
28
+    default:
29
+      echo json_encode(array('status' => 'failure'));
30
+      break;
31
+  }
32
+}

+ 83
- 0
sections/api/top10/tags.php View File

@@ -0,0 +1,83 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+# todo: Go through line by line
5
+
6
+// Error out on invalid requests (before caching)
7
+if (isset($_GET['details'])) {
8
+    if (in_array($_GET['details'], ['ut','ur'])) {
9
+        $Details = $_GET['details'];
10
+    } else {
11
+        echo json_encode(['status' => 'failure']);
12
+        error();
13
+    }
14
+} else {
15
+    $Details = 'all';
16
+}
17
+
18
+// Defaults to 10 (duh)
19
+$Limit = isset($_GET['limit']) ? intval($_GET['limit']) : 10;
20
+$Limit = in_array($Limit, [10, 100, 250]) ? $Limit : 10;
21
+$OuterResults = [];
22
+
23
+if ($Details == 'all' || $Details == 'ut') {
24
+    if (!$TopUsedTags = $Cache->get_value("topusedtag_$Limit")) {
25
+        $DB->query("
26
+      SELECT
27
+        t.ID,
28
+        t.Name,
29
+        COUNT(tt.GroupID) AS Uses
30
+      FROM tags AS t
31
+        JOIN torrents_tags AS tt ON tt.TagID = t.ID
32
+      GROUP BY tt.TagID
33
+      ORDER BY Uses DESC
34
+      LIMIT $Limit");
35
+        $TopUsedTags = $DB->to_array();
36
+        $Cache->cache_value("topusedtag_$Limit", $TopUsedTags, 3600 * 12);
37
+    }
38
+
39
+    $OuterResults[] = generate_tag_json('Most Used Torrent Tags', 'ut', $TopUsedTags, $Limit);
40
+}
41
+
42
+if ($Details == 'all' || $Details == 'ur') {
43
+    if (!$TopRequestTags = $Cache->get_value("toprequesttag_$Limit")) {
44
+        $DB->query("
45
+      SELECT
46
+        t.ID,
47
+        t.Name,
48
+        COUNT(r.RequestID) AS Uses,
49
+        '',''
50
+      FROM tags AS t
51
+        JOIN requests_tags AS r ON r.TagID = t.ID
52
+      GROUP BY r.TagID
53
+      ORDER BY Uses DESC
54
+      LIMIT $Limit");
55
+        $TopRequestTags = $DB->to_array();
56
+        $Cache->cache_value("toprequesttag_$Limit", $TopRequestTags, 3600 * 12);
57
+    }
58
+
59
+    $OuterResults[] = generate_tag_json('Most Used Request Tags', 'ur', $TopRequestTags, $Limit);
60
+}
61
+
62
+echo json_encode([
63
+  'status' => 'success',
64
+  'response' => $OuterResults
65
+]);
66
+
67
+function generate_tag_json($Caption, $Tag, $Details, $Limit)
68
+{
69
+    $results = [];
70
+    foreach ($Details as $Detail) {
71
+        $results[] = [
72
+      'name' => $Detail['Name'],
73
+      'uses' => (int)$Detail['Uses']
74
+    ];
75
+    }
76
+
77
+    return [
78
+    'caption' => $Caption,
79
+    'tag' => $Tag,
80
+    'limit' => (int)$Limit,
81
+    'results' => $results
82
+  ];
83
+}

+ 185
- 0
sections/api/top10/torrents.php View File

@@ -0,0 +1,185 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+# todo: Go through line by line
5
+if (isset($_GET['details'])) {
6
+    if (in_array($_GET['details'], array('day','week','overall','snatched','data','seeded'))) {
7
+        $Details = $_GET['details'];
8
+    } else {
9
+        echo json_encode(array('status' => 'failure'));
10
+        error();
11
+    }
12
+} else {
13
+    $Details = 'all';
14
+}
15
+
16
+// Defaults to 10 (duh)
17
+$Limit = isset($_GET['limit']) ? intval($_GET['limit']) : 10;
18
+$Limit = in_array($Limit, array(10, 100, 250)) ? $Limit : 10;
19
+
20
+$WhereSum = (empty($Where)) ? '' : md5($Where);
21
+$BaseQuery = "
22
+SELECT
23
+  t.`ID`,
24
+  g.`id`,
25
+  g.`title`,
26
+  g.`category_id`,
27
+  g.`picture`,
28
+  g.`tag_list`,
29
+  t.`Media`,
30
+  g.`published`,
31
+  t.`Snatched`,
32
+  t.`Seeders`,
33
+  t.`Leechers`,
34
+  (
35
+    (t.`Size` * t.`Snatched`) +(t.`Size` * 0.5 * t.`Leechers`)
36
+  ) AS `Data`,
37
+  t.`Size`
38
+FROM
39
+  `torrents` AS t
40
+LEFT JOIN `torrents_group` AS g
41
+ON
42
+  g.`id` = t.`GroupID`
43
+";
44
+
45
+$OuterResults = [];
46
+
47
+if ($Details == 'all' || $Details == 'day') {
48
+    if (!$TopTorrentsActiveLastDay = $Cache->get_value('top10tor_day_'.$Limit.$WhereSum)) {
49
+        $DayAgo = time_minus(86400);
50
+        $Query = $BaseQuery.' WHERE t.Seeders>0 AND ';
51
+        if (!empty($Where)) {
52
+            $Query .= $Where.' AND ';
53
+        }
54
+        $Query .= "
55
+      t.Time>'$DayAgo'
56
+      ORDER BY (t.Seeders + t.Leechers) DESC
57
+      LIMIT $Limit;";
58
+        $DB->query($Query);
59
+        $TopTorrentsActiveLastDay = $DB->to_array(false, MYSQLI_NUM);
60
+        $Cache->cache_value('top10tor_day_'.$Limit.$WhereSum, $TopTorrentsActiveLastDay, 3600 * 2);
61
+    }
62
+    $OuterResults[] = generate_torrent_json('Most Active Torrents Uploaded in the Past Day', 'day', $TopTorrentsActiveLastDay, $Limit);
63
+}
64
+if ($Details == 'all' || $Details == 'week') {
65
+    if (!$TopTorrentsActiveLastWeek = $Cache->get_value('top10tor_week_'.$Limit.$WhereSum)) {
66
+        $WeekAgo = time_minus(604800);
67
+        $Query = $BaseQuery.' WHERE ';
68
+        if (!empty($Where)) {
69
+            $Query .= $Where.' AND ';
70
+        }
71
+        $Query .= "
72
+      t.Time>'$WeekAgo'
73
+      ORDER BY (t.Seeders + t.Leechers) DESC
74
+      LIMIT $Limit;";
75
+        $DB->query($Query);
76
+        $TopTorrentsActiveLastWeek = $DB->to_array(false, MYSQLI_NUM);
77
+        $Cache->cache_value('top10tor_week_'.$Limit.$WhereSum, $TopTorrentsActiveLastWeek, 3600*6);
78
+    }
79
+    $OuterResults[] = generate_torrent_json('Most Active Torrents Uploaded in the Past Week', 'week', $TopTorrentsActiveLastWeek, $Limit);
80
+}
81
+
82
+if ($Details == 'all' || $Details == 'overall') {
83
+    if (!$TopTorrentsActiveAllTime = $Cache->get_value("top10tor_overall_$Limit$WhereSum")) {
84
+        $Query = $BaseQuery;
85
+        if (!empty($Where)) {
86
+            $Query .= " WHERE $Where";
87
+        }
88
+        $Query .= "
89
+      ORDER BY (t.Seeders + t.Leechers) DESC
90
+      LIMIT $Limit;";
91
+        $DB->query($Query);
92
+        $TopTorrentsActiveAllTime = $DB->to_array(false, MYSQLI_NUM);
93
+        $Cache->cache_value("top10tor_overall_$Limit$WhereSum", $TopTorrentsActiveAllTime, 3600 * 6);
94
+    }
95
+    $OuterResults[] = generate_torrent_json('Most Active Torrents of All Time', 'overall', $TopTorrentsActiveAllTime, $Limit);
96
+}
97
+
98
+if (($Details == 'all' || $Details == 'snatched') && empty($Where)) {
99
+    if (!$TopTorrentsSnatched = $Cache->get_value("top10tor_snatched_$Limit$WhereSum")) {
100
+        $Query = $BaseQuery;
101
+        $Query .= "
102
+      ORDER BY t.Snatched DESC
103
+      LIMIT $Limit;";
104
+        $DB->query($Query);
105
+        $TopTorrentsSnatched = $DB->to_array(false, MYSQLI_NUM);
106
+        $Cache->cache_value("top10tor_snatched_$Limit$WhereSum", $TopTorrentsSnatched, 3600 * 6);
107
+    }
108
+    $OuterResults[] = generate_torrent_json('Most Snatched Torrents', 'snatched', $TopTorrentsSnatched, $Limit);
109
+}
110
+
111
+if (($Details == 'all' || $Details == 'data') && empty($Where)) {
112
+    if (!$TopTorrentsTransferred = $Cache->get_value("top10tor_data_$Limit$WhereSum")) {
113
+        $Query = $BaseQuery;
114
+        $Query .= "
115
+      ORDER BY Data DESC
116
+      LIMIT $Limit;";
117
+        $DB->query($Query);
118
+        $TopTorrentsTransferred = $DB->to_array(false, MYSQLI_NUM);
119
+        $Cache->cache_value("top10tor_data_$Limit$WhereSum", $TopTorrentsTransferred, 3600 * 6);
120
+    }
121
+    $OuterResults[] = generate_torrent_json('Most Data Transferred Torrents', 'data', $TopTorrentsTransferred, $Limit);
122
+}
123
+
124
+if (($Details == 'all' || $Details == 'seeded') && empty($Where)) {
125
+    if (!$TopTorrentsSeeded = $Cache->get_value("top10tor_seeded_$Limit$WhereSum")) {
126
+        $Query = $BaseQuery."
127
+      ORDER BY t.Seeders DESC
128
+      LIMIT $Limit;";
129
+        $DB->query($Query);
130
+        $TopTorrentsSeeded = $DB->to_array(false, MYSQLI_NUM);
131
+        $Cache->cache_value("top10tor_seeded_$Limit$WhereSum", $TopTorrentsSeeded, 3600 * 6);
132
+    }
133
+    $OuterResults[] = generate_torrent_json('Best Seeded Torrents', 'seeded', $TopTorrentsSeeded, $Limit);
134
+}
135
+
136
+json_print("success", $OuterResults);
137
+
138
+function generate_torrent_json($Caption, $Tag, $Details, $Limit)
139
+{
140
+    global $LoggedUser, $Categories;
141
+    $results = [];
142
+    foreach ($Details as $Detail) {
143
+        list($TorrentID, $GroupID, $GroupName, $GroupCategoryID, $WikiImage, $TorrentTags,
144
+      $Media, $GroupYear,
145
+      $Snatched, $Seeders, $Leechers, $Data, $Size) = $Detail;
146
+
147
+        # todo: Make JSON object if multiple artists
148
+        $Artist = Artists::display_artists(Artists::get_artist($GroupID), false, false);
149
+
150
+        $TagList = [];
151
+
152
+        if ($TorrentTags != '') {
153
+            $TorrentTags = explode(' ', $TorrentTags);
154
+            foreach ($TorrentTags as $TagKey => $TagName) {
155
+                $TagName = str_replace('_', '.', $TagName);
156
+                $TagList[] = $TagName;
157
+            }
158
+        }
159
+
160
+        // Append to the existing array
161
+        $results[] = array(
162
+          'torrentId'     => (int) $TorrentID,
163
+          'groupId'       => (int) $GroupID,
164
+          'author'        => $Artist, # todo
165
+          'groupName'     => $GroupName,
166
+          'groupCategory' => (int) $GroupCategoryID,
167
+          'groupYear'     => (int) $GroupYear,
168
+          'platform'      => $Media,
169
+          'tags'          => $TagList,
170
+          'snatched'      => (int) $Snatched,
171
+          'seeders'       => (int) $Seeders,
172
+          'leechers'      => (int) $Leechers,
173
+          'data'          => (int) $Data,
174
+          'size'          => (int) $Size,
175
+          'picture'       => $WikiImage,
176
+        );
177
+    }
178
+
179
+    return array(
180
+      'caption' => $Caption,
181
+      'tag'     => $Tag,
182
+      'limit'   => (int)$Limit,
183
+      'results' => $results
184
+    );
185
+}

+ 130
- 0
sections/api/top10/users.php View File

@@ -0,0 +1,130 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+# todo: Go through line by line
5
+if (isset($_GET['details'])) {
6
+    if (in_array($_GET['details'], array('ul','dl','numul','uls','dls'))) {
7
+        $Details = $_GET['details'];
8
+    } else {
9
+        echo json_encode(array('status' => 'failure'));
10
+        error();
11
+    }
12
+} else {
13
+    $Details = 'all';
14
+}
15
+
16
+// Defaults to 10 (duh)
17
+$Limit = isset($_GET['limit']) ? intval($_GET['limit']) : 10;
18
+$Limit = in_array($Limit, array(10,100,250)) ? $Limit : 10;
19
+
20
+$BaseQuery = "
21
+  SELECT
22
+    u.ID,
23
+    u.Username,
24
+    ui.JoinDate,
25
+    u.Uploaded,
26
+    u.Downloaded,
27
+    ABS(u.Uploaded-524288000) / (".time()." - UNIX_TIMESTAMP(ui.JoinDate)) AS UpSpeed,
28
+    u.Downloaded / (".time()." - UNIX_TIMESTAMP(ui.JoinDate)) AS DownSpeed,
29
+    COUNT(t.ID) AS NumUploads
30
+  FROM users_main AS u
31
+    JOIN users_info AS ui ON ui.UserID = u.ID
32
+    LEFT JOIN torrents AS t ON t.UserID = u.ID
33
+  WHERE u.Enabled = '1'
34
+    AND Uploaded > '". 5 * 1024 * 1024 * 1024 ."'
35
+    AND Downloaded > '". 5 * 1024 * 1024 * 1024 ."'
36
+    AND (Paranoia IS NULL OR (Paranoia NOT LIKE '%\"uploaded\"%' AND Paranoia NOT LIKE '%\"downloaded\"%'))
37
+  GROUP BY u.ID";
38
+
39
+$OuterResults = [];
40
+
41
+if ($Details == 'all' || $Details == 'ul') {
42
+    if (!$TopUserUploads = $Cache->get_value("topuser_ul_$Limit")) {
43
+        $DB->query("
44
+      $BaseQuery
45
+      ORDER BY u.Uploaded DESC
46
+      LIMIT $Limit;");
47
+        $TopUserUploads = $DB->to_array();
48
+        $Cache->cache_value("topuser_ul_$Limit", $TopUserUploads, 3600 * 12);
49
+    }
50
+    $OuterResults[] = generate_user_json('Uploaders', 'ul', $TopUserUploads, $Limit);
51
+}
52
+
53
+if ($Details == 'all' || $Details == 'dl') {
54
+    if (!$TopUserDownloads = $Cache->get_value("topuser_dl_$Limit")) {
55
+        $DB->query("
56
+      $BaseQuery
57
+      ORDER BY u.Downloaded DESC
58
+      LIMIT $Limit;");
59
+        $TopUserDownloads = $DB->to_array();
60
+        $Cache->cache_value("topuser_dl_$Limit", $TopUserDownloads, 3600 * 12);
61
+    }
62
+    $OuterResults[] = generate_user_json('Downloaders', 'dl', $TopUserDownloads, $Limit);
63
+}
64
+
65
+if ($Details == 'all' || $Details == 'numul') {
66
+    if (!$TopUserNumUploads = $Cache->get_value("topuser_numul_$Limit")) {
67
+        $DB->query("
68
+      $BaseQuery
69
+      ORDER BY NumUploads DESC
70
+      LIMIT $Limit;");
71
+        $TopUserNumUploads = $DB->to_array();
72
+        $Cache->cache_value("topuser_numul_$Limit", $TopUserNumUploads, 3600 * 12);
73
+    }
74
+    $OuterResults[] = generate_user_json('Torrents Uploaded', 'numul', $TopUserNumUploads, $Limit);
75
+}
76
+
77
+if ($Details == 'all' || $Details == 'uls') {
78
+    if (!$TopUserUploadSpeed = $Cache->get_value("topuser_ulspeed_$Limit")) {
79
+        $DB->query("
80
+      $BaseQuery
81
+      ORDER BY UpSpeed DESC
82
+      LIMIT $Limit;");
83
+        $TopUserUploadSpeed = $DB->to_array();
84
+        $Cache->cache_value("topuser_ulspeed_$Limit", $TopUserUploadSpeed, 3600 * 12);
85
+    }
86
+    $OuterResults[] = generate_user_json('Fastest Uploaders', 'uls', $TopUserUploadSpeed, $Limit);
87
+}
88
+
89
+if ($Details == 'all' || $Details == 'dls') {
90
+    if (!$TopUserDownloadSpeed = $Cache->get_value("topuser_dlspeed_$Limit")) {
91
+        $DB->query("
92
+      $BaseQuery
93
+      ORDER BY DownSpeed DESC
94
+      LIMIT $Limit;");
95
+        $TopUserDownloadSpeed = $DB->to_array();
96
+        $Cache->cache_value("topuser_dlspeed_$Limit", $TopUserDownloadSpeed, 3600 * 12);
97
+    }
98
+    $OuterResults[] = generate_user_json('Fastest Downloaders', 'dls', $TopUserDownloadSpeed, $Limit);
99
+}
100
+
101
+print
102
+  json_encode(
103
+      array(
104
+      'status' => 'success',
105
+      'response' => $OuterResults
106
+    )
107
+  );
108
+
109
+function generate_user_json($Caption, $Tag, $Details, $Limit)
110
+{
111
+    $results = [];
112
+    foreach ($Details as $Detail) {
113
+        $results[] = array(
114
+      'id' => (int)$Detail['ID'],
115
+      'username' => $Detail['Username'],
116
+      'uploaded' => (float)$Detail['Uploaded'],
117
+      'upSpeed' => (float)$Detail['UpSpeed'],
118
+      'downloaded' => (float)$Detail['Downloaded'],
119
+      'downSpeed' => (float)$Detail['DownSpeed'],
120
+      'numUploads' => (int)$Detail['NumUploads'],
121
+      'joinDate' => $Detail['JoinDate']
122
+    );
123
+    }
124
+    return array(
125
+    'caption' => $Caption,
126
+    'tag' => $Tag,
127
+    'limit' => (int)$Limit,
128
+    'results' => $results
129
+    );
130
+}

+ 166
- 0
sections/api/torrents/group.php View File

@@ -0,0 +1,166 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+$ENV = ENV::go();
5
+require_once "$ENV->SERVER_ROOT/sections/torrents/functions.php";
6
+
7
+# Either id or hash
8
+$GroupID = (int) $_GET['id'];
9
+$TorrentHash = (string) $_GET['hash'];
10
+
11
+# Error if both supplied
12
+if ($GroupID && $TorrentHash) {
13
+    json_die('failure', 'bad parameters');
14
+}
15
+
16
+# Get id from hash
17
+if ($TorrentHash) {
18
+    if (!is_valid_torrenthash($TorrentHash)) {
19
+        json_die('failure', 'bad hash parameter');
20
+    } else {
21
+        $GroupID = (int) torrenthash_to_groupid($TorrentHash);
22
+        if (!$GroupID) {
23
+            json_die('failure', 'bad hash parameter');
24
+        }
25
+    }
26
+}
27
+
28
+# Error if bad id
29
+if ($GroupID <= 0) {
30
+    json_die('failure', 'bad id parameter');
31
+}
32
+
33
+$TorrentCache = get_group_info($GroupID, true, 0, true, true);
34
+if (!$TorrentCache) {
35
+    json_die('failure', 'bad id parameter');
36
+}
37
+
38
+# Get torrent details (group, torrents, artists)
39
+list($TorrentDetails, $TorrentList) = $TorrentCache;
40
+$Artists = Artists::get_artist($GroupID);
41
+
42
+# Get category name if possible
43
+if ($TorrentDetails['category_id'] === 0) {
44
+    $CategoryName = 'Unknown';
45
+} else {
46
+    $CategoryName = $Categories[$TorrentDetails['category_id'] - 1];
47
+}
48
+
49
+# Get tag list (name and id)
50
+$TagIDs = explode('|', $TorrentDetails["GROUP_CONCAT(DISTINCT tags.`ID` SEPARATOR '|')"]);
51
+$TagNames= explode('|', $TorrentDetails["GROUP_CONCAT(DISTINCT tags.`Name` SEPARATOR '|')"]);
52
+
53
+$TagList = [];
54
+foreach ($TagIDs as $Key => $ID) {
55
+    array_push(
56
+        $TagList,
57
+        [
58
+            'id'   => $ID,
59
+            'name' => $TagNames[$Key],
60
+        ]
61
+    );
62
+}
63
+
64
+# Get citation list (doi and id)
65
+# todo: Update DB schema
66
+$Citations = [];
67
+foreach ($TorrentDetails['Screenshots'] as $Citation) {
68
+    array_push(
69
+        $Citations,
70
+        [
71
+            'id'        => $Citation['ID'],
72
+            'doi'       => $Citation['URI'],
73
+           #'timestamp' => $Citation['Time'],
74
+        ]
75
+    );
76
+}
77
+
78
+# Torrent group response
79
+# todo: Add seeding, leeching, snatched
80
+$JsonTorrentDetails = [
81
+    'id'            => (int) $TorrentDetails['id'],
82
+    'identifier'    => $TorrentDetails['identifier'],
83
+
84
+    'category_id'   => (int) $TorrentDetails['category_id'],
85
+    'category_name' => $CategoryName,
86
+
87
+    'title'         => $TorrentDetails['title'],
88
+    'subject'       => $TorrentDetails['subject'],
89
+    'object'        => $TorrentDetails['object'],
90
+
91
+    'authors'       => $Artists,
92
+    'published'     => (int) $TorrentDetails['published'],
93
+    'workgroup'     => $TorrentDetails['workgroup'],
94
+    'location'      => $TorrentDetails['location'],
95
+
96
+    'citations'     => $Citations,
97
+    'mirrors'       => ($TorrentDetails['Mirrors']) ?: false,
98
+  
99
+    'description'   => $TorrentDetails['description'],
100
+   #'description'   => Text::full_format($TorrentDetails['description']),
101
+    'picture'       => $TorrentDetails['picture'],
102
+    'tag_list'      => $TagList,
103
+
104
+    'bookmarked'    => Bookmarks::has_bookmarked('torrent', $GroupID),
105
+    'timestamp'     => $TorrentDetails['timestamp'],
106
+];
107
+
108
+# Torrents in group
109
+$JsonTorrentList = [];
110
+foreach ($TorrentList as $Torrent) {
111
+    # Convert file list back to the old format
112
+    $FileList = explode("\n", $Torrent['FileList']);
113
+
114
+    foreach ($FileList as &$File) {
115
+        $File = Torrents::filelist_old_format($File);
116
+    }
117
+
118
+    # todo: Make a nested object
119
+    # todo: Limit to 100 files
120
+    unset($File);
121
+    $FileList = implode('|||', $FileList);
122
+    $Userinfo = Users::user_info($Torrent['UserID']);
123
+
124
+    $Reports = Torrents::get_reports($Torrent['ID']);
125
+    $Torrent['Reported'] = count($Reports) > 0;
126
+
127
+    # Torrent details response
128
+    # todo: Update DB schema
129
+    $JsonTorrentList[] = [
130
+        'id'           => (int) $Torrent['ID'],
131
+        'info_hash'    => $Torrent['InfoHash'],
132
+        'description'  => $Torrent['Description'],
133
+
134
+        'platform'     => $Torrent['Media'],
135
+        'format'       => $Torrent['Container'],
136
+        'scope'        => $Torrent['Resolution'],
137
+        'annotated'    => (bool) $Torrent['Censored'],
138
+        'license'      => $Torrent['Codec'],
139
+
140
+        'size'         => (int) $Torrent['Size'],
141
+        'archive'      => $Torrent['Archive'],
142
+        'file_count'   => (int) $Torrent['FileCount'],
143
+        'file_path'    => $Torrent['FilePath'],
144
+        'file_list'    => $FileList,
145
+
146
+        'seeders'      => (int) $Torrent['Seeders'],
147
+        'leechers'     => (int) $Torrent['Leechers'],
148
+        'snatched'     => (int) $Torrent['Snatched'],
149
+        'free_torrent' => ($Torrent['FreeTorrent'] === 1),
150
+
151
+        'reported'     => (bool) $Torrent['Reported'],
152
+        'time'         => $Torrent['Time'],
153
+
154
+        'user_id'      => (int) ($Torrent['Anonymous'] ? 0 : $Torrent['UserID']),
155
+        'username'     => ($Torrent['Anonymous'] ? 'Anonymous' : $Userinfo['Username']),
156
+    ];
157
+}
158
+
159
+# Print response
160
+json_die(
161
+    'success',
162
+    [
163
+        'group' => $JsonTorrentDetails,
164
+        'torrents' => $JsonTorrentList,
165
+    ]
166
+);

+ 105
- 0
sections/api/torrents/torrent.php View File

@@ -0,0 +1,105 @@
1
+<?php
2
+declare(strict_types=1);
3
+
4
+require_once SERVER_ROOT.'/sections/torrents/functions.php';
5
+
6
+$TorrentID = (int) $_GET['id'];
7
+$TorrentHash = (string) $_GET['hash'];
8
+
9
+if ($TorrentID && $TorrentHash) {
10
+    json_die('failure', 'bad parameters');
11
+}
12
+
13
+if ($TorrentHash) {
14
+    if (!is_valid_torrenthash($TorrentHash)) {
15
+        json_die('failure', 'bad hash parameter');
16
+    } else {
17
+        $TorrentID = (int) torrenthash_to_torrentid($TorrentHash);
18
+        if (!$TorrentID) {
19
+            json_die('failure', 'bad hash parameter');
20
+        }
21
+    }
22
+}
23
+
24
+if ($TorrentID <= 0) {
25
+    json_die('failure', 'bad id parameter');
26
+}
27
+
28
+$TorrentCache = get_torrent_info($TorrentID, true, 0, true, true);
29
+if (!$TorrentCache) {
30
+    json_die('failure', 'bad id parameter');
31
+}
32
+
33
+list($TorrentDetails, $TorrentList) = $TorrentCache;
34
+if (!isset($TorrentList[$TorrentID])) {
35
+    json_die('failure', 'bad id parameter');
36
+}
37
+
38
+$GroupID = $TorrentDetails['ID'];
39
+$Artists = Artists::get_artist($GroupID);
40
+
41
+if ($TorrentDetails['category_id'] === 0) {
42
+    $CategoryName = 'Unknown';
43
+} else {
44
+    $CategoryName = $Categories[$TorrentDetails['category_id'] - 1];
45
+}
46
+
47
+$TagList = explode('|', $TorrentDetails['GROUP_CONCAT(DISTINCT tags.Name SEPARATOR \'|\')']);
48
+
49
+$JsonTorrentDetails = [
50
+  'description'  => Text::full_format($TorrentDetails['description']),
51
+  'picture'      => $TorrentDetails['picture'],
52
+  'id'           => (int) $TorrentDetails['id'],
53
+  'title'         => $TorrentDetails['title'],
54
+  'subject'     => $TorrentDetails['subject'],
55
+  'object'       => $TorrentDetails['object'],
56
+  'authors'      => $Artists,
57
+  'published'         => (int) $TorrentDetails['published'],
58
+  'identifier'    => $TorrentDetails['identifier'],
59
+  'category_id'   => (int) $TorrentDetails['category_id'],
60
+  'icategory_name' => $CategoryName,
61
+  'timestamp'         => $TorrentDetails['timestamp'],
62
+  'bookmarked' => Bookmarks::has_bookmarked('torrent', $GroupID),
63
+  'tag_list'         => $TagList
64
+];
65
+
66
+$Torrent = $TorrentList[$TorrentID];
67
+
68
+$Reports = Torrents::get_reports($TorrentID);
69
+$Torrent['Reported'] = (count($Reports) > 0);
70
+
71
+// Convert file list back to the old format
72
+$FileList = explode("\n", $Torrent['FileList']);
73
+foreach ($FileList as &$File) {
74
+    $File = Torrents::filelist_old_format($File);
75
+}
76
+
77
+unset($File);
78
+$FileList = implode('|||', $FileList);
79
+$Userinfo = Users::user_info($Torrent['UserID']);
80
+
81
+$JsonTorrentList[] = [
82
+  'id'          => (int) $Torrent['ID'],
83
+  'infoHash'    => $Torrent['InfoHash'],
84
+  'platform'    => $Torrent['Media'],
85
+  'format'      => $Torrent['Container'],
86
+  'license'     => $Torrent['Codec'],
87
+  'scope'       => $Torrent['Resolution'],
88
+  'annotated'   => (bool) $Torrent['Censored'],
89
+  'archive'     => $Torrent['Archive'],
90
+  'fileCount'   => (int) $Torrent['FileCount'],
91
+  'size'        => (int) $Torrent['Size'],
92
+  'seeders'     => (int) $Torrent['Seeders'],
93
+  'leechers'    => (int) $Torrent['Leechers'],
94
+  'snatched'    => (int) $Torrent['Snatched'],
95
+  'freeTorrent' => ($Torrent['FreeTorrent'] == 1),
96
+  'reported'    => (bool) $Torrent['Reported'],
97
+  'time'        => $Torrent['Time'],
98
+  'description' => $Torrent['Description'],
99
+  'fileList'    => $FileList,
100
+  'filePath'    => $Torrent['FilePath'],
101
+  'userId'      => (int) ($Torrent['Anonymous'] ? 0 : $Torrent['UserID']),
102
+  'username'    => ($Torrent['Anonymous'] ? 'Anonymous' : $Userinfo['Username'])
103
+];
104
+
105
+json_die('success', ['group' => $JsonTorrentDetails, 'torrent' => array_pop($JsonTorrentList)]);

+ 22
- 0
sections/api/torrents/torrentgroupalbumart.php View File

@@ -0,0 +1,22 @@
1
+<?php
2
+declare(strict_types=1);
3
+
4
+require SERVER_ROOT.'/sections/torrents/functions.php';
5
+
6
+$GroupID = (int) $_GET['id'];
7
+if ($GroupID === 0) {
8
+    error('Bad ID parameter', true);
9
+}
10
+
11
+$TorrentDetails = get_group_info($GroupID, true, 0, false);
12
+$TorrentDetails = $TorrentDetails[0];
13
+$Image = $TorrentDetails['WikiImage'];
14
+
15
+// Handle no artwork
16
+if (!$Image) {
17
+    $Image = STATIC_SERVER.'common/noartwork/music.png';
18
+}
19
+
20
+json_die('success', array(
21
+  'picture' => $Image
22
+));

+ 485
- 0
sections/api/user.php View File

@@ -0,0 +1,485 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+if (empty($_GET['id']) || !is_numeric($_GET['id'])) {
5
+    json_die('failure', 'bad id parameter');
6
+}
7
+
8
+$UserID = $_GET['id'];
9
+if ($UserID === $LoggedUser['ID']) {
10
+    $OwnProfile = true;
11
+} else {
12
+    $OwnProfile = false;
13
+}
14
+
15
+// Always view as a normal user
16
+$DB->query("
17
+SELECT
18
+  m.`Username`,
19
+  m.`Email`,
20
+  m.`LastAccess`,
21
+  m.`IP`,
22
+  p.`Level` AS Class,
23
+  m.`Uploaded`,
24
+  m.`Downloaded`,
25
+  m.`RequiredRatio`,
26
+  m.`Enabled`,
27
+  m.`Paranoia`,
28
+  m.`Invites`,
29
+  m.`Title`,
30
+  m.`torrent_pass`,
31
+  m.`can_leech`,
32
+  i.`JoinDate`,
33
+  i.`Info`,
34
+  i.`Avatar`,
35
+  i.`Donor`,
36
+  i.`Warned`,
37
+COUNT(posts.`id`) AS ForumPosts,
38
+  i.`Inviter`,
39
+  i.`DisableInvites`,
40
+  inviter.`username`
41
+FROM
42
+  `users_main` AS m
43
+JOIN `users_info` AS i
44
+ON
45
+  i.`UserID` = m.`ID`
46
+LEFT JOIN `permissions` AS p
47
+ON
48
+  p.`ID` = m.`PermissionID`
49
+LEFT JOIN `users_main` AS inviter
50
+ON
51
+  i.`Inviter` = inviter.`ID`
52
+LEFT JOIN `forums_posts` AS posts
53
+ON
54
+  posts.`AuthorID` = m.`ID`
55
+WHERE
56
+  m.`ID` = $UserID
57
+GROUP BY
58
+  `AuthorID`
59
+");
60
+
61
+// If user doesn't exist
62
+if (!$DB->has_results()) {
63
+    json_die('failure', 'no such user');
64
+}
65
+
66
+list($Username, $Email, $LastAccess, $IP, $Class, $Uploaded, $Downloaded, $RequiredRatio, $Enabled, $Paranoia, $Invites, $CustomTitle, $torrent_pass, $DisableLeech, $JoinDate, $Info, $Avatar, $Donor, $Warned, $ForumPosts, $InviterID, $DisableInvites, $InviterName) = $DB->next_record(MYSQLI_NUM, array(9, 11));
67
+
68
+$Paranoia = unserialize($Paranoia);
69
+if (!is_array($Paranoia)) {
70
+    $Paranoia = [];
71
+}
72
+
73
+$ParanoiaLevel = 0;
74
+foreach ($Paranoia as $P) {
75
+    $ParanoiaLevel++;
76
+    if (strpos($P, '+') !== false) {
77
+        $ParanoiaLevel++;
78
+    }
79
+}
80
+
81
+// Raw time is better for JSON
82
+//$JoinedDate = time_diff($JoinDate);
83
+//$LastAccess = time_diff($LastAccess);
84
+
85
+function check_paranoia_here($Setting)
86
+{
87
+    global $Paranoia, $Class, $UserID;
88
+    return check_paranoia($Setting, $Paranoia, $Class, $UserID);
89
+}
90
+
91
+$Friend = false;
92
+$DB->query("
93
+SELECT
94
+  `FriendID`
95
+FROM
96
+  `friends`
97
+WHERE
98
+  `UserID` = '$LoggedUser[ID]'
99
+  AND `FriendID` = '$UserID'
100
+");
101
+
102
+if ($DB->has_results()) {
103
+    $Friend = true;
104
+}
105
+
106
+if (check_paranoia_here('requestsfilled_count') || check_paranoia_here('requestsfilled_bounty')) {
107
+    $DB->query("
108
+    SELECT
109
+      COUNT(DISTINCT r.`ID`),
110
+      SUM(rv.`Bounty`)
111
+    FROM
112
+      `requests` AS r
113
+    LEFT JOIN `requests_votes` AS rv
114
+    ON
115
+      r.`ID` = rv.`RequestID`
116
+    WHERE
117
+      r.`FillerID` = $UserID
118
+    ");
119
+    list($RequestsFilled, $TotalBounty) = $DB->next_record();
120
+
121
+    $DB->query("
122
+    SELECT
123
+      COUNT(`RequestID`),
124
+      SUM(`Bounty`)
125
+    FROM
126
+      `requests_votes`
127
+    WHERE
128
+      `UserID` = $UserID
129
+    ");
130
+    list($RequestsVoted, $TotalSpent) = $DB->next_record();
131
+
132
+    $DB->query("
133
+    SELECT
134
+      COUNT(`ID`)
135
+    FROM
136
+      `torrents`
137
+    WHERE
138
+      `UserID` = '$UserID'
139
+    ");
140
+    list($Uploads) = $DB->next_record();
141
+} else {
142
+    $RequestsFilled = null;
143
+    $TotalBounty = null;
144
+    $RequestsVoted = 0;
145
+    $TotalSpent = 0;
146
+}
147
+
148
+if (check_paranoia_here('uploads+')) {
149
+    $DB->query("
150
+    SELECT
151
+      COUNT(`ID`)
152
+    FROM
153
+      `torrents`
154
+    WHERE
155
+      `UserID` = '$UserID'
156
+    ");
157
+    list($Uploads) = $DB->next_record();
158
+} else {
159
+    $Uploads = null;
160
+}
161
+
162
+if (check_paranoia_here('artistsadded')) {
163
+    $DB->query("
164
+    SELECT
165
+      COUNT(`ArtistID`)
166
+    FROM
167
+      `torrents_artists`
168
+    WHERE
169
+      `UserID` = $UserID
170
+    ");
171
+    list($ArtistsAdded) = $DB->next_record();
172
+} else {
173
+    $ArtistsAdded = null;
174
+}
175
+
176
+// Do the ranks
177
+if (check_paranoia_here('uploaded')) {
178
+    $UploadedRank = UserRank::get_rank('uploaded', $Uploaded);
179
+} else {
180
+    $UploadedRank = null;
181
+}
182
+
183
+if (check_paranoia_here('downloaded')) {
184
+    $DownloadedRank = UserRank::get_rank('downloaded', $Downloaded);
185
+} else {
186
+    $DownloadedRank = null;
187
+}
188
+
189
+if (check_paranoia_here('uploads+')) {
190
+    $UploadsRank = UserRank::get_rank('uploads', $Uploads);
191
+} else {
192
+    $UploadsRank = null;
193
+}
194
+
195
+if (check_paranoia_here('requestsfilled_count')) {
196
+    $RequestRank = UserRank::get_rank('requests', $RequestsFilled);
197
+} else {
198
+    $RequestRank = null;
199
+}
200
+
201
+$PostRank = UserRank::get_rank('posts', $ForumPosts);
202
+
203
+if (check_paranoia_here('requestsvoted_bounty')) {
204
+    $BountyRank = UserRank::get_rank('bounty', $TotalSpent);
205
+} else {
206
+    $BountyRank = null;
207
+}
208
+
209
+if (check_paranoia_here('artistsadded')) {
210
+    $ArtistsRank = UserRank::get_rank('artists', $ArtistsAdded);
211
+} else {
212
+    $ArtistsRank = null;
213
+}
214
+
215
+if ($Downloaded === 0) {
216
+    $Ratio = 1;
217
+} elseif ($Uploaded === 0) {
218
+    $Ratio = 0.5;
219
+} else {
220
+    $Ratio = round($Uploaded / $Downloaded, 2);
221
+}
222
+
223
+if (check_paranoia_here(array('uploaded', 'downloaded', 'uploads+', 'requestsfilled_count', 'requestsvoted_bounty', 'artistsadded'))) {
224
+    $OverallRank = floor(UserRank::overall_score($UploadedRank, $DownloadedRank, $UploadsRank, $RequestRank, $PostRank, $BountyRank, $ArtistsRank, $Ratio));
225
+} else {
226
+    $OverallRank = null;
227
+}
228
+
229
+// Community section
230
+if (check_paranoia_here('snatched+')) {
231
+    $DB->query("
232
+    SELECT
233
+      COUNT(x.`uid`),
234
+      COUNT(DISTINCT x.`fid`)
235
+    FROM
236
+      `xbt_snatched` AS x
237
+    INNER JOIN `torrents` AS t
238
+    ON
239
+      t.`ID` = x.`fid`
240
+    WHERE
241
+      x.`uid` = '$UserID'
242
+    ");
243
+    list($Snatched, $UniqueSnatched) = $DB->next_record();
244
+}
245
+
246
+if (check_paranoia_here('torrentcomments+')) {
247
+    $DB->query("
248
+    SELECT
249
+      COUNT(`ID`)
250
+    FROM
251
+      `comments`
252
+    WHERE
253
+      `Page` = 'torrents'
254
+      AND `AuthorID` = '$UserID'
255
+    ");
256
+    list($NumComments) = $DB->next_record();
257
+}
258
+
259
+if (check_paranoia_here('torrentcomments+')) {
260
+    $DB->query("
261
+    SELECT
262
+      COUNT(`ID`)
263
+    FROM
264
+      `comments`
265
+    WHERE
266
+      `Page` = 'artist'
267
+      AND `AuthorID` = '$UserID'
268
+    ");
269
+    list($NumArtistComments) = $DB->next_record();
270
+}
271
+
272
+if (check_paranoia_here('torrentcomments+')) {
273
+    $DB->query("
274
+    SELECT
275
+      COUNT(`ID`)
276
+    FROM
277
+      `comments`
278
+    WHERE
279
+      `Page` = 'collages'
280
+      AND `AuthorID` = '$UserID'
281
+    ");
282
+    list($NumCollageComments) = $DB->next_record();
283
+}
284
+
285
+if (check_paranoia_here('torrentcomments+')) {
286
+    $DB->query("
287
+    SELECT
288
+      COUNT(`ID`)
289
+    FROM
290
+      `comments`
291
+    WHERE
292
+      `Page` = 'requests'
293
+      AND `AuthorID` = '$UserID'
294
+    ");
295
+    list($NumRequestComments) = $DB->next_record();
296
+}
297
+
298
+if (check_paranoia_here('collages+')) {
299
+    $DB->query("
300
+    SELECT
301
+      COUNT(`ID`)
302
+    FROM
303
+      `collages`
304
+    WHERE
305
+      `Deleted` = '0'
306
+      AND `UserID` = '$UserID'
307
+    ");
308
+    list($NumCollages) = $DB->next_record();
309
+}
310
+
311
+if (check_paranoia_here('collagecontribs+')) {
312
+    $DB->query("
313
+    SELECT
314
+      COUNT(DISTINCT ct.`CollageID`)
315
+    FROM
316
+      `collages_torrents` AS ct
317
+    JOIN `collages` AS c
318
+    ON
319
+      ct.`CollageID` = c.`ID`
320
+    WHERE
321
+      c.`Deleted` = '0'
322
+      AND ct.`UserID` = '$UserID'
323
+    ");
324
+    list($NumCollageContribs) = $DB->next_record();
325
+}
326
+
327
+if (check_paranoia_here('uniquegroups+')) {
328
+    $DB->query("
329
+    SELECT
330
+      COUNT(DISTINCT `GroupID`)
331
+    FROM
332
+      `torrents`
333
+    WHERE
334
+      `UserID` = '$UserID'
335
+    ");
336
+    list($UniqueGroups) = $DB->next_record();
337
+}
338
+
339
+if (check_paranoia_here('seeding+')) {
340
+    $DB->query("
341
+    SELECT
342
+      COUNT(x.`uid`)
343
+    FROM
344
+      `xbt_files_users` AS x
345
+    INNER JOIN `torrents` AS t
346
+    ON
347
+      t.`ID` = x.`fid`
348
+    WHERE
349
+      x.`uid` = '$UserID'
350
+      AND x.`remaining` = 0
351
+    ");
352
+    list($Seeding) = $DB->next_record();
353
+}
354
+
355
+if (check_paranoia_here('leeching+')) {
356
+    $DB->query("
357
+    SELECT
358
+      COUNT(x.`uid`)
359
+    FROM
360
+      `xbt_files_users` AS x
361
+    INNER JOIN `torrents` AS t
362
+    ON
363
+      t.`ID` = x.`fid`
364
+    WHERE
365
+      x.`uid` = '$UserID'
366
+      AND x.`remaining` > 0
367
+    ");
368
+    list($Leeching) = $DB->next_record();
369
+}
370
+
371
+if (check_paranoia_here('invitedcount')) {
372
+    $DB->query("
373
+    SELECT
374
+      COUNT(`UserID`)
375
+    FROM
376
+      `users_info`
377
+    WHERE
378
+      `Inviter` = '$UserID'
379
+    ");
380
+    list($Invited) = $DB->next_record();
381
+}
382
+
383
+if (!$OwnProfile) {
384
+    $torrent_pass = '';
385
+}
386
+
387
+// Run through some paranoia stuff to decide what we can send out
388
+if (!check_paranoia_here('lastseen')) {
389
+    $LastAccess = '';
390
+}
391
+
392
+if (check_paranoia_here('ratio')) {
393
+    $Ratio = Format::get_ratio($Uploaded, $Downloaded, 5);
394
+} else {
395
+    $Ratio = null;
396
+}
397
+
398
+if (!check_paranoia_here('uploaded')) {
399
+    $Uploaded = null;
400
+}
401
+
402
+if (!check_paranoia_here('downloaded')) {
403
+    $Downloaded = null;
404
+}
405
+
406
+if (isset($RequiredRatio) && !check_paranoia_here('requiredratio')) {
407
+    $RequiredRatio = null;
408
+}
409
+
410
+if ($ParanoiaLevel === 0) {
411
+    $ParanoiaLevelText = 'Off';
412
+} elseif ($ParanoiaLevel === 1) {
413
+    $ParanoiaLevelText = 'Very Low';
414
+} elseif ($ParanoiaLevel <= 5) {
415
+    $ParanoiaLevelText = 'Low';
416
+} elseif ($ParanoiaLevel <= 20) {
417
+    $ParanoiaLevelText = 'High';
418
+} else {
419
+    $ParanoiaLevelText = 'Very high';
420
+}
421
+
422
+// Bugfix for no access time available
423
+if (!$LastAccess) {
424
+    $LastAccess = '';
425
+}
426
+
427
+header('Content-Type: text/plain; charset=utf-8');
428
+
429
+json_print('success', [
430
+  'username'    => $Username,
431
+  'avatar'      => $Avatar,
432
+  'isFriend'    => (bool) $Friend,
433
+  'profileText' => Text::full_format($Info),
434
+
435
+  'stats' => [
436
+    'joinedDate'    => $JoinDate,
437
+    'lastAccess'    => $LastAccess,
438
+    'uploaded'      => (int) $Uploaded,
439
+    'downloaded'    => (int) $Downloaded,
440
+    'ratio'         => (float) $Ratio,
441
+    'requiredRatio' => (float) $RequiredRatio
442
+  ],
443
+
444
+  'ranks' => [
445
+    'uploaded'   => (int) $UploadedRank,
446
+    'downloaded' => (int) $DownloadedRank,
447
+    'uploads'    => (int) $UploadsRank,
448
+    'requests'   => (int) $RequestRank,
449
+    'bounty'     => (int) $BountyRank,
450
+    'posts'      => (int) $PostRank,
451
+    'artists'    => (int) $ArtistsRank,
452
+    'overall'    => (int) $OverallRank
453
+  ],
454
+
455
+  'personal' => [
456
+    'class'        => $ClassLevels[$Class]['Name'],
457
+    'paranoia'     => (int) $ParanoiaLevel,
458
+    'paranoiaText' => $ParanoiaLevelText,
459
+    'donor'        => ($Donor === 1),
460
+    'warned'       => (bool) $Warned,
461
+    'enabled'      => ((int) $Enabled === 1 || (int) $Enabled === 0 || !$Enabled),
462
+    'passkey'      => $torrent_pass
463
+  ],
464
+
465
+  'community' => [
466
+    'posts'           => (int) $ForumPosts,
467
+    'torrentComments' => (int) $NumComments,
468
+    'artistComments'  => (int) $NumArtistComments,
469
+    'collageComments' => (int) $NumCollageComments,
470
+    'requestComments' => (int) $NumRequestComments,
471
+    'collagesStarted' => (int) $NumCollages,
472
+    'collagesContrib' => (int) $NumCollageContribs,
473
+    'requestsFilled'  => (int) $RequestsFilled,
474
+    'bountyEarned'    => (int) $TotalBounty,
475
+    'requestsVoted'   => (int) $RequestsVoted,
476
+    'bountySpent'     => (int) $TotalSpent,
477
+    'uploaded'        => (int) $Uploads,
478
+    'groups'          => (int) $UniqueGroups,
479
+    'seeding'         => (int) $Seeding,
480
+    'leeching'        => (int) $Leeching,
481
+    'snatched'        => (int) $Snatched,
482
+    'invited'         => (int) $Invited,
483
+    'artistsAdded'    => (int) $ArtistsAdded
484
+  ]
485
+]);

+ 96
- 0
sections/api/user_recents.php View File

@@ -0,0 +1,96 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+# todo: Go through line by line
5
+$UserID = (int) $_GET['userid'];
6
+$Limit = (int) $_GET['limit'];
7
+
8
+if (empty($UserID) || $Limit > 50) {
9
+    json_die('failure', 'bad parameters');
10
+}
11
+
12
+if (empty($Limit)) {
13
+    $Limit = 15;
14
+}
15
+
16
+$Results = [];
17
+if (check_paranoia_here('snatched')) {
18
+    $DB->query("
19
+    SELECT
20
+      g.`id`,
21
+      g.`title`,
22
+      g.`picture`
23
+    FROM
24
+      `xbt_snatched` AS s
25
+    INNER JOIN `torrents` AS t
26
+    ON
27
+      t.`ID` = s.`fid`
28
+    INNER JOIN `torrents_group` AS g
29
+    ON
30
+      t.`GroupID` = g.`id`
31
+    WHERE
32
+      s.`uid` = '$UserID' AND g.`category_id` = '1' AND g.`picture` != ''
33
+    GROUP BY
34
+      g.`id`
35
+    ORDER BY
36
+      s.`tstamp`
37
+    DESC
38
+    LIMIT $Limit
39
+    ");
40
+
41
+    $RecentSnatches = $DB->to_array(false, MYSQLI_ASSOC);
42
+    $Artists = Artists::get_artists($DB->collect('ID'));
43
+
44
+    foreach ($RecentSnatches as $Key => $SnatchInfo) {
45
+        $RecentSnatches[$Key]['artists'][] = $Artists[$SnatchInfo['ID']];
46
+        $RecentSnatches[$Key]['ID'] = (int)$RecentSnatches[$Key]['ID'];
47
+    }
48
+    $Results['snatches'] = $RecentSnatches;
49
+} else {
50
+    $Results['snatches'] = 'hidden';
51
+}
52
+
53
+if (check_paranoia_here('uploads')) {
54
+    $DB->query("
55
+    SELECT
56
+      g.`id`,
57
+      g.`title`,
58
+      g.`picture`
59
+    FROM
60
+      `torrents_group` AS g
61
+    INNER JOIN `torrents` AS t
62
+    ON
63
+      t.`GroupID` = g.`id`
64
+    WHERE
65
+      t.`UserID` = '$UserID' AND g.`category_id` = '1' AND g.`picture` != ''
66
+    GROUP BY
67
+      g.`id`
68
+    ORDER BY
69
+      t.`Time`
70
+    DESC
71
+    LIMIT $Limit
72
+    ");
73
+
74
+    $RecentUploads = $DB->to_array(false, MYSQLI_ASSOC);
75
+    $Artists = Artists::get_artists($DB->collect('ID'));
76
+
77
+    foreach ($RecentUploads as $Key => $UploadInfo) {
78
+        $RecentUploads[$Key]['artists'][] = $Artists[$UploadInfo['ID']];
79
+        $RecentUploads[$Key]['ID'] = (int)$RecentUploads[$Key]['ID'];
80
+    }
81
+    $Results['uploads'] = $RecentUploads;
82
+} else {
83
+    $Results['uploads'] = 'hidden';
84
+}
85
+
86
+json_die('success', $Results);
87
+
88
+function check_paranoia_here($Setting)
89
+{
90
+    global $Paranoia, $Class, $UserID, $Preview;
91
+    if ($Preview == 1) {
92
+        return check_paranoia($Setting, $Paranoia, $Class);
93
+    } else {
94
+        return check_paranoia($Setting, $Paranoia, $Class, $UserID);
95
+    }
96
+}

+ 20
- 0
sections/api/userhistory/index.php View File

@@ -0,0 +1,20 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+if ($_GET['type']) {
5
+    switch ($_GET['type']) {
6
+    case 'posts':
7
+      // Load post history page
8
+      include('post_history.php');
9
+      break;
10
+
11
+    default:
12
+      echo json_encode(
13
+          array('status' => 'failure')
14
+      );
15
+  }
16
+} else {
17
+    echo json_encode(
18
+        array('status' => 'failure')
19
+    );
20
+}

+ 186
- 0
sections/api/userhistory/post_history.php View File

@@ -0,0 +1,186 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+# todo: Go through line by line
5
+function error_out($reason = '')
6
+{
7
+    $error = array('status' => 'failure');
8
+    if ($reason !== '') {
9
+        $error['reason'] = $reason;
10
+    }
11
+    echo $error;
12
+    error();
13
+}
14
+
15
+if (!empty($LoggedUser['DisableForums'])) {
16
+    error_out('You do not have access to the forums!');
17
+}
18
+
19
+$UserID = empty($_GET['userid']) ? $LoggedUser['ID'] : $_GET['userid'];
20
+if (!is_number($UserID)) {
21
+    error_out('User does not exist!');
22
+}
23
+
24
+if (isset($LoggedUser['PostsPerPage'])) {
25
+    $PerPage = $LoggedUser['PostsPerPage'];
26
+} else {
27
+    $PerPage = POSTS_PER_PAGE;
28
+}
29
+
30
+list($Page, $Limit) = Format::page_limit($PerPage);
31
+
32
+$UserInfo = Users::user_info($UserID);
33
+extract(array_intersect_key($UserInfo, array_flip(array('Username', 'Enabled', 'Title', 'Avatar', 'Donor', 'Warned'))));
34
+
35
+$ViewingOwn = ($UserID === $LoggedUser['ID']);
36
+$ShowUnread = ($ViewingOwn && (!isset($_GET['showunread']) || !!$_GET['showunread']));
37
+$ShowGrouped = ($ViewingOwn && (!isset($_GET['group']) || !!$_GET['group']));
38
+if ($ShowGrouped) {
39
+    $SQL = '
40
+    SELECT
41
+      SQL_CALC_FOUND_ROWS
42
+      MAX(p.ID) AS ID
43
+    FROM forums_posts AS p
44
+      LEFT JOIN forums_topics AS t ON t.ID = p.TopicID';
45
+    if ($ShowUnread) {
46
+        $SQL .= '
47
+      LEFT JOIN forums_last_read_topics AS l ON l.TopicID = t.ID AND l.UserID = '.$LoggedUser['ID'];
48
+    }
49
+    $SQL .= '
50
+      LEFT JOIN forums AS f ON f.ID = t.ForumID
51
+    WHERE p.AuthorID = '.$UserID.'
52
+      AND ' . Forums::user_forums_sql();
53
+    if ($ShowUnread) {
54
+        $SQL .= '
55
+      AND ((t.IsLocked = \'0\' OR t.IsSticky = \'1\')
56
+      AND (l.PostID < t.LastPostID OR l.PostID IS NULL))';
57
+    }
58
+    $SQL .= "
59
+    GROUP BY t.ID
60
+    ORDER BY p.ID DESC
61
+    LIMIT $Limit";
62
+    $PostIDs = $DB->query($SQL);
63
+    $DB->query('SELECT FOUND_ROWS()');
64
+    list($Results) = $DB->next_record();
65
+
66
+    if ($Results > $PerPage * ($Page - 1)) {
67
+        $DB->set_query_id($PostIDs);
68
+        $PostIDs = $DB->collect('ID');
69
+        $SQL = "
70
+      SELECT
71
+        p.ID,
72
+        p.AddedTime,
73
+        p.Body,
74
+        p.EditedUserID,
75
+        p.EditedTime,
76
+        ed.Username,
77
+        p.TopicID,
78
+        t.Title,
79
+        t.LastPostID,
80
+        l.PostID AS LastRead,
81
+        t.IsLocked,
82
+        t.IsSticky
83
+      FROM forums_posts AS p
84
+        LEFT JOIN users_main AS um ON um.ID = p.AuthorID
85
+        LEFT JOIN users_info AS ui ON ui.UserID = p.AuthorID
86
+        LEFT JOIN users_main AS ed ON ed.ID = p.EditedUserID
87
+        JOIN forums_topics AS t ON t.ID = p.TopicID
88
+        JOIN forums AS f ON f.ID = t.ForumID
89
+        LEFT JOIN forums_last_read_topics AS l ON l.UserID = $UserID AND l.TopicID = t.ID
90
+      WHERE p.ID IN (".implode(',', $PostIDs).')
91
+      ORDER BY p.ID DESC';
92
+        $Posts = $DB->query($SQL);
93
+    }
94
+} else {
95
+    $SQL = '
96
+    SELECT
97
+      SQL_CALC_FOUND_ROWS';
98
+    if ($ShowGrouped) {
99
+        $SQL .= '
100
+      *
101
+    FROM (
102
+      SELECT';
103
+    }
104
+    $SQL .= '
105
+        p.ID,
106
+        p.AddedTime,
107
+        p.Body,
108
+        p.EditedUserID,
109
+        p.EditedTime,
110
+        ed.Username,
111
+        p.TopicID,
112
+        t.Title,
113
+        t.LastPostID,';
114
+    if ($UserID === $LoggedUser['ID']) {
115
+        $SQL .= '
116
+        l.PostID AS LastRead,';
117
+    }
118
+    $SQL .= "
119
+        t.IsLocked,
120
+        t.IsSticky
121
+      FROM forums_posts AS p
122
+        LEFT JOIN users_main AS um ON um.ID = p.AuthorID
123
+        LEFT JOIN users_info AS ui ON ui.UserID = p.AuthorID
124
+        LEFT JOIN users_main AS ed ON ed.ID = p.EditedUserID
125
+        JOIN forums_topics AS t ON t.ID = p.TopicID
126
+        JOIN forums AS f ON f.ID = t.ForumID
127
+        LEFT JOIN forums_last_read_topics AS l ON l.UserID = $UserID AND l.TopicID = t.ID
128
+      WHERE p.AuthorID = $UserID
129
+        AND " . Forums::user_forums_sql();
130
+
131
+    if ($ShowUnread) {
132
+        $SQL .= '
133
+        AND ((t.IsLocked = \'0\' OR t.IsSticky = \'1\')
134
+          AND (l.PostID < t.LastPostID OR l.PostID IS NULL)
135
+        ) ';
136
+    }
137
+
138
+    $SQL .= '
139
+      ORDER BY p.ID DESC';
140
+
141
+    if ($ShowGrouped) {
142
+        $SQL .= '
143
+    ) AS sub
144
+    GROUP BY TopicID
145
+    ORDER BY ID DESC';
146
+    }
147
+
148
+    $SQL .= "
149
+    LIMIT $Limit";
150
+    $Posts = $DB->query($SQL);
151
+
152
+    $DB->query('SELECT FOUND_ROWS()');
153
+    list($Results) = $DB->next_record();
154
+
155
+    $DB->set_query_id($Posts);
156
+}
157
+
158
+$JsonResults = [];
159
+while (list($PostID, $AddedTime, $Body, $EditedUserID, $EditedTime, $EditedUsername, $TopicID, $ThreadTitle, $LastPostID, $LastRead, $Locked, $Sticky) = $DB->next_record()) {
160
+    $JsonResults[] = array(
161
+    'postId' => (int)$PostID,
162
+    'topicId' => (int)$TopicID,
163
+    'threadTitle' => $ThreadTitle,
164
+    'lastPostId' => (int)$LastPostID,
165
+    'lastRead' => (int)$LastRead,
166
+    'locked' => $Locked === '1',
167
+    'sticky' => $Sticky === '1',
168
+    'addedTime' => $AddedTime,
169
+    'body' => Text::full_format($Body),
170
+    'bbbody' => $Body,
171
+    'editedUserId' => (int)$EditedUserID,
172
+    'editedTime' => $EditedTime,
173
+    'editedUsername' => $EditedUsername
174
+    );
175
+}
176
+
177
+echo json_encode(
178
+    array(
179
+    'status' => 'success',
180
+    'response' => array(
181
+      'currentPage' => (int)$Page,
182
+      'pages' => ceil($Results / $PerPage),
183
+      'threads' => $JsonResults
184
+      )
185
+    )
186
+);

+ 58
- 0
sections/api/usersearch.php View File

@@ -0,0 +1,58 @@
1
+<?php
2
+/**********************************************************************
3
+ *>>>>>>>>>>>>>>>>>>>>>>>>>>> User search <<<<<<<<<<<<<<<<<<<<<<<<<<<<*
4
+ **********************************************************************/
5
+
6
+if (empty($_GET['search'])) {
7
+  json_die("failure", "no search terms");
8
+} else {
9
+  $_GET['username'] = $_GET['search'];
10
+}
11
+
12
+define('USERS_PER_PAGE', 30);
13
+
14
+if (isset($_GET['username'])) {
15
+  $_GET['username'] = trim($_GET['username']);
16
+
17
+  list($Page, $Limit) = Format::page_limit(USERS_PER_PAGE);
18
+  $DB->query("
19
+    SELECT
20
+      SQL_CALC_FOUND_ROWS
21
+      ID,
22
+      Username,
23
+      Enabled,
24
+      PermissionID,
25
+      Donor,
26
+      Warned,
27
+      Avatar
28
+    FROM users_main AS um
29
+      JOIN users_info AS ui ON ui.UserID = um.ID
30
+    WHERE Username LIKE '%".db_string($_GET['username'])."%'
31
+    ORDER BY Username
32
+    LIMIT $Limit");
33
+  $Results = $DB->to_array();
34
+  $DB->query('SELECT FOUND_ROWS();');
35
+  list($NumResults) = $DB->next_record();
36
+
37
+}
38
+
39
+$JsonUsers = [];
40
+foreach ($Results as $Result) {
41
+  list($UserID, $Username, $Enabled, $PermissionID, $Donor, $Warned, $Avatar) = $Result;
42
+
43
+  $JsonUsers[] = [
44
+    'userId' => (int)$UserID,
45
+    'username' => $Username,
46
+    'donor' => $Donor == 1,
47
+    'warned' => (bool)$Warned,
48
+    'enabled' => ($Enabled == 2 ? false : true),
49
+    'class' => Users::make_class_string($PermissionID),
50
+    'avatar' => $Avatar
51
+  ];
52
+}
53
+
54
+json_die("success", [
55
+  'currentPage' => (int)$Page,
56
+  'pages' => ceil($NumResults / USERS_PER_PAGE),
57
+  'results' => $JsonUsers
58
+]);

+ 41
- 0
sections/api/wiki.php View File

@@ -0,0 +1,41 @@
1
+<?php
2
+#declare(strict_types=1);
3
+
4
+if (!empty($_GET['id']) && is_number($_GET['id'])) {
5
+    // Visiting article via ID
6
+    $ArticleID = $_GET['id'];
7
+} elseif ($_GET['name'] !== '') {
8
+    // Retrieve article ID via alias
9
+    $ArticleID = Wiki::alias_to_id($_GET['name']);
10
+} else {
11
+    json_die('failure');
12
+}
13
+
14
+// No article found
15
+if (!$ArticleID) {
16
+    json_die('failure', 'article not found');
17
+}
18
+
19
+$Article = Wiki::get_article($ArticleID, false);
20
+if (!$Article) {
21
+    json_die('failure', 'article not found');
22
+}
23
+
24
+list($Revision, $Title, $Body, $Read, $Edit, $Date, $AuthorID, $AuthorName, $Aliases, $UserIDs) = array_shift($Article);
25
+if ($Read > $LoggedUser['EffectiveClass']) {
26
+    json_die('failure', 'higher user class required to view article');
27
+}
28
+
29
+Text::$TOC = true;
30
+$TextBody = Text::full_format($Body, false);
31
+
32
+json_die('success', array(
33
+  'title'      => $Title,
34
+  'bbBody'     => $Body,
35
+  'body'       => $TextBody,
36
+  'aliases'    => $Aliases,
37
+  'authorID'   => (int) $AuthorID,
38
+  'authorName' => $AuthorName,
39
+  'date'       => $Date,
40
+  'revision'   => (int) $Revision
41
+));

+ 39
- 38
sections/artist/add_alias.php View File

@@ -1,23 +1,25 @@
1
-<?
1
+<?php
2
+#declare(strict_types=1);
3
+
2 4
 authorize();
3 5
 
4 6
 if (!check_perms('torrents_edit')) {
5
-  error(403);
7
+    error(403);
6 8
 }
7 9
 $ArtistID = $_POST['artistid'];
8 10
 $Redirect = $_POST['redirect'];
9 11
 $AliasName = Artists::normalise_artist_name($_POST['name']);
10 12
 $DBAliasName = db_string($AliasName);
11 13
 if (!$Redirect) {
12
-  $Redirect = 0;
14
+    $Redirect = 0;
13 15
 }
14 16
 
15 17
 if (!is_number($ArtistID) || !($Redirect === 0 || is_number($Redirect)) || !$ArtistID) {
16
-  error(0);
18
+    error(0);
17 19
 }
18 20
 
19 21
 if ($AliasName == '') {
20
-  error('Blank artist name.');
22
+    error('Blank artist name.');
21 23
 }
22 24
 
23 25
 /*
@@ -33,58 +35,57 @@ $DB->query("
33 35
   FROM artists_alias
34 36
   WHERE Name = '$DBAliasName'");
35 37
 if ($DB->has_results()) {
36
-  while (list($CloneAliasID, $CloneArtistID, $CloneAliasName, $CloneRedirect) = $DB->next_record(MYSQLI_NUM, false)) {
37
-    if (!strcasecmp($CloneAliasName, $AliasName)) {
38
-      break;
38
+    while (list($CloneAliasID, $CloneArtistID, $CloneAliasName, $CloneRedirect) = $DB->next_record(MYSQLI_NUM, false)) {
39
+        if (!strcasecmp($CloneAliasName, $AliasName)) {
40
+            break;
41
+        }
39 42
     }
40
-  }
41
-  if ($CloneAliasID) {
42
-    if ($ArtistID == $CloneArtistID && $Redirect == 0) {
43
-      if ($CloneRedirect != 0) {
44
-        $DB->query("
43
+    if ($CloneAliasID) {
44
+        if ($ArtistID == $CloneArtistID && $Redirect == 0) {
45
+            if ($CloneRedirect != 0) {
46
+                $DB->query("
45 47
           UPDATE artists_alias
46 48
           SET ArtistID = '$ArtistID', Redirect = 0
47 49
           WHERE AliasID = '$CloneAliasID'");
48
-        Misc::write_log("Redirection for the alias $CloneAliasID ($DBAliasName) for the artist $ArtistID was removed by user $LoggedUser[ID] ($LoggedUser[Username])");
49
-      } else {
50
-        error('No changes were made as the target alias did not redirect anywhere.');
51
-      }
52
-    } else {
53
-      error('An alias by that name already exists <a href="artist.php?id='.$CloneArtistID.'">here</a>. You can try renaming that artist to this one.');
50
+                Misc::write_log("Redirection for the alias $CloneAliasID ($DBAliasName) for the artist $ArtistID was removed by user $LoggedUser[ID] ($LoggedUser[Username])");
51
+            } else {
52
+                error('No changes were made as the target alias did not redirect anywhere.');
53
+            }
54
+        } else {
55
+            error('An alias by that name already exists <a href="artist.php?id='.$CloneArtistID.'">here</a>. You can try renaming that artist to this one.');
56
+        }
54 57
     }
55
-  }
56 58
 }
57 59
 if (!$CloneAliasID) {
58
-  if ($Redirect) {
59
-    $DB->query("
60
+    if ($Redirect) {
61
+        $DB->query("
60 62
       SELECT ArtistID, Redirect
61 63
       FROM artists_alias
62 64
       WHERE AliasID = $Redirect");
63
-    if (!$DB->has_results()) {
64
-      error('Cannot redirect to a nonexistent artist alias.');
65
+        if (!$DB->has_results()) {
66
+            error('Cannot redirect to a nonexistent artist alias.');
67
+        }
68
+        list($FoundArtistID, $FoundRedirect) = $DB->next_record();
69
+        if ($ArtistID != $FoundArtistID) {
70
+            error('Redirection must target an alias for the current artist.');
71
+        }
72
+        if ($FoundRedirect != 0) {
73
+            $Redirect = $FoundRedirect;
74
+        }
65 75
     }
66
-    list($FoundArtistID, $FoundRedirect) = $DB->next_record();
67
-    if ($ArtistID != $FoundArtistID) {
68
-      error('Redirection must target an alias for the current artist.');
69
-    }
70
-    if ($FoundRedirect != 0) {
71
-      $Redirect = $FoundRedirect;
72
-    }
73
-  }
74
-  $DB->query("
76
+    $DB->query("
75 77
     INSERT INTO artists_alias
76 78
       (ArtistID, Name, Redirect, UserID)
77 79
     VALUES
78 80
       ($ArtistID, '$DBAliasName', $Redirect, ".$LoggedUser['ID'].')');
79
-  $AliasID = $DB->inserted_id();
81
+    $AliasID = $DB->inserted_id();
80 82
 
81
-  $DB->query("
83
+    $DB->query("
82 84
     SELECT Name
83 85
     FROM artists_group
84 86
     WHERE ArtistID = $ArtistID");
85
-  list($ArtistName) = $DB->next_record(MYSQLI_NUM, false);
87
+    list($ArtistName) = $DB->next_record(MYSQLI_NUM, false);
86 88
 
87
-  Misc::write_log("The alias $AliasID ($DBAliasName) was added to the artist $ArtistID (".db_string($ArtistName).') by user '.$LoggedUser['ID'].' ('.$LoggedUser['Username'].')');
89
+    Misc::write_log("The alias $AliasID ($DBAliasName) was added to the artist $ArtistID (".db_string($ArtistName).') by user '.$LoggedUser['ID'].' ('.$LoggedUser['Username'].')');
88 90
 }
89 91
 header('Location: '.$_SERVER['HTTP_REFERER']);
90
-?>

+ 1
- 1
sections/artist/artist.php View File

@@ -191,7 +191,7 @@ $OldGroupID = 0;
191 191
     <?php
192 192
 
193 193
 foreach ($TorrentList as $Group) {
194
-    extract(Torrents::array_group($TorrentList[$Group['ID']]), EXTR_OVERWRITE);
194
+    extract(Torrents::array_group($TorrentList[$Group['id']]), EXTR_OVERWRITE);
195 195
 
196 196
     if ($GroupID === $OldGroupID) {
197 197
         continue;

+ 97
- 93
sections/artist/change_artistid.php View File

@@ -1,11 +1,13 @@
1
-<?
1
+<?php
2
+#declare(strict_types=1);
3
+
2 4
 authorize();
3 5
 
4 6
 if (!check_perms('torrents_edit')) {
5
-  error(403);
7
+    error(403);
6 8
 }
7 9
 if (!empty($_POST['newartistid']) && !empty($_POST['newartistname'])) {
8
-  error('Please enter a valid artist ID number or a valid artist name.');
10
+    error('Please enter a valid artist ID number or a valid artist name.');
9 11
 }
10 12
 $ArtistID = (int)$_POST['artistid'];
11 13
 $NewArtistID = (int)$_POST['newartistid'];
@@ -13,10 +15,10 @@ $NewArtistName = $_POST['newartistname'];
13 15
 
14 16
 
15 17
 if (!is_number($ArtistID) || !$ArtistID) {
16
-  error('Please select a valid artist to change.');
18
+    error('Please select a valid artist to change.');
17 19
 }
18 20
 if (empty($NewArtistName) && (!$NewArtistID || !is_number($NewArtistID))) {
19
-  error('Please enter a valid artist ID number or a valid artist name.');
21
+    error('Please enter a valid artist ID number or a valid artist name.');
20 22
 }
21 23
 
22 24
 $DB->query("
@@ -25,171 +27,173 @@ $DB->query("
25 27
   WHERE ArtistID = $ArtistID
26 28
   LIMIT 1");
27 29
 if (!(list($ArtistName) = $DB->next_record(MYSQLI_NUM, false))) {
28
-  error('An error has occurred.');
30
+    error('An error has occurred.');
29 31
 }
30 32
 
31 33
 if ($NewArtistID > 0) {
32
-  // Make sure that's a real artist ID number, and grab the name
33
-  $DB->query("
34
+    // Make sure that's a real artist ID number, and grab the name
35
+    $DB->query("
34 36
     SELECT Name
35 37
     FROM artists_group
36 38
     WHERE ArtistID = $NewArtistID
37 39
     LIMIT 1");
38
-  if (!(list($NewArtistName) = $DB->next_record())) {
39
-    error('Please enter a valid artist ID number.');
40
-  }
40
+    if (!(list($NewArtistName) = $DB->next_record())) {
41
+        error('Please enter a valid artist ID number.');
42
+    }
41 43
 } else {
42
-  // Didn't give an ID, so try to grab based on the name
43
-  $DB->query("
44
+    // Didn't give an ID, so try to grab based on the name
45
+    $DB->query("
44 46
     SELECT ArtistID
45 47
     FROM artists_alias
46 48
     WHERE Name = '".db_string($NewArtistName)."'
47 49
     LIMIT 1");
48
-  if (!(list($NewArtistID) = $DB->next_record())) {
49
-    error('No artist by that name was found.');
50
-  }
50
+    if (!(list($NewArtistID) = $DB->next_record())) {
51
+        error('No artist by that name was found.');
52
+    }
51 53
 }
52 54
 
53 55
 if ($ArtistID == $NewArtistID) {
54
-  error('You cannot merge an artist with itself.');
56
+    error('You cannot merge an artist with itself.');
55 57
 }
56 58
 if (isset($_POST['confirm'])) {
57
-  // Get the information for the cache update
58
-  $DB->query("
59
+    // Get the information for the cache update
60
+    $DB->query("
59 61
     SELECT DISTINCT GroupID
60 62
     FROM torrents_artists
61 63
     WHERE ArtistID = $ArtistID");
62
-  $Groups = $DB->collect('GroupID');
63
-  $DB->query("
64
+    $Groups = $DB->collect('GroupID');
65
+    $DB->query("
64 66
     SELECT DISTINCT RequestID
65 67
     FROM requests_artists
66 68
     WHERE ArtistID = $ArtistID");
67
-  $Requests = $DB->collect('RequestID');
68
-  $DB->query("
69
+    $Requests = $DB->collect('RequestID');
70
+    $DB->query("
69 71
     SELECT DISTINCT UserID
70 72
     FROM bookmarks_artists
71 73
     WHERE ArtistID = $ArtistID");
72
-  $BookmarkUsers = $DB->collect('UserID');
73
-  $DB->query("
74
+    $BookmarkUsers = $DB->collect('UserID');
75
+    $DB->query("
74 76
     SELECT DISTINCT ct.CollageID
75 77
     FROM collages_torrents AS ct
76 78
       JOIN torrents_artists AS ta ON ta.GroupID = ct.GroupID
77 79
     WHERE ta.ArtistID = $ArtistID");
78
-  $Collages = $DB->collect('CollageID');
80
+    $Collages = $DB->collect('CollageID');
79 81
 
80
-  // And the info to avoid double-listing an artist if it and the target are on the same group
81
-  $DB->query("
82
+    // And the info to avoid double-listing an artist if it and the target are on the same group
83
+    $DB->query("
82 84
     SELECT DISTINCT GroupID
83 85
     FROM torrents_artists
84 86
     WHERE ArtistID = $NewArtistID");
85
-  $NewArtistGroups = $DB->collect('GroupID');
86
-  $NewArtistGroups[] = '0';
87
-  $NewArtistGroups = implode(',', $NewArtistGroups);
87
+    $NewArtistGroups = $DB->collect('GroupID');
88
+    $NewArtistGroups[] = '0';
89
+    $NewArtistGroups = implode(',', $NewArtistGroups);
88 90
 
89
-  $DB->query("
91
+    $DB->query("
90 92
     SELECT DISTINCT RequestID
91 93
     FROM requests_artists
92 94
     WHERE ArtistID = $NewArtistID");
93
-  $NewArtistRequests = $DB->collect('RequestID');
94
-  $NewArtistRequests[] = '0';
95
-  $NewArtistRequests = implode(',', $NewArtistRequests);
95
+    $NewArtistRequests = $DB->collect('RequestID');
96
+    $NewArtistRequests[] = '0';
97
+    $NewArtistRequests = implode(',', $NewArtistRequests);
96 98
 
97
-  $DB->query("
99
+    $DB->query("
98 100
     SELECT DISTINCT UserID
99 101
     FROM bookmarks_artists
100 102
     WHERE ArtistID = $NewArtistID");
101
-  $NewArtistBookmarks = $DB->collect('UserID');
102
-  $NewArtistBookmarks[] = '0';
103
-  $NewArtistBookmarks = implode(',', $NewArtistBookmarks);
103
+    $NewArtistBookmarks = $DB->collect('UserID');
104
+    $NewArtistBookmarks[] = '0';
105
+    $NewArtistBookmarks = implode(',', $NewArtistBookmarks);
104 106
 
105
-  // Merge all of this artist's aliases onto the new artist
106
-  $DB->query("
107
+    // Merge all of this artist's aliases onto the new artist
108
+    $DB->query("
107 109
     UPDATE artists_alias
108 110
     SET ArtistID = $NewArtistID
109 111
     WHERE ArtistID = $ArtistID");
110 112
 
111
-  // Update the torrent groups, requests, and bookmarks
112
-  $DB->query("
113
+    // Update the torrent groups, requests, and bookmarks
114
+    $DB->query("
113 115
     UPDATE IGNORE torrents_artists
114 116
     SET ArtistID = $NewArtistID
115 117
     WHERE ArtistID = $ArtistID
116 118
       AND GroupID NOT IN ($NewArtistGroups)");
117
-  $DB->query("
119
+    $DB->query("
118 120
     DELETE FROM torrents_artists
119 121
     WHERE ArtistID = $ArtistID");
120
-  $DB->query("
122
+    $DB->query("
121 123
     UPDATE IGNORE requests_artists
122 124
     SET ArtistID = $NewArtistID
123 125
     WHERE ArtistID = $ArtistID
124 126
       AND RequestID NOT IN ($NewArtistRequests)");
125
-  $DB->query("
127
+    $DB->query("
126 128
     DELETE FROM requests_artists
127 129
     WHERE ArtistID = $ArtistID");
128
-  $DB->query("
130
+    $DB->query("
129 131
     UPDATE IGNORE bookmarks_artists
130 132
     SET ArtistID = $NewArtistID
131 133
     WHERE ArtistID = $ArtistID
132 134
       AND UserID NOT IN ($NewArtistBookmarks)");
133
-  $DB->query("
135
+    $DB->query("
134 136
     DELETE FROM bookmarks_artists
135 137
     WHERE ArtistID = $ArtistID");
136 138
 
137
-  // Cache clearing
138
-  if (!empty($Groups)) {
139
-    foreach ($Groups as $GroupID) {
140
-      $Cache->delete_value("groups_artists_$GroupID");
141
-      Torrents::update_hash($GroupID);
139
+    // Cache clearing
140
+    if (!empty($Groups)) {
141
+        foreach ($Groups as $GroupID) {
142
+            $Cache->delete_value("groups_artists_$GroupID");
143
+            Torrents::update_hash($GroupID);
144
+        }
142 145
     }
143
-  }
144
-  if (!empty($Requests)) {
145
-    foreach ($Requests as $RequestID) {
146
-      $Cache->delete_value("request_artists_$RequestID");
147
-      Requests::update_sphinx_requests($RequestID);
146
+    if (!empty($Requests)) {
147
+        foreach ($Requests as $RequestID) {
148
+            $Cache->delete_value("request_artists_$RequestID");
149
+            Requests::update_sphinx_requests($RequestID);
150
+        }
148 151
     }
149
-  }
150
-  if (!empty($BookmarkUsers)) {
151
-    foreach ($BookmarkUsers as $UserID) {
152
-      $Cache->delete_value("notify_artists_$UserID");
152
+    if (!empty($BookmarkUsers)) {
153
+        foreach ($BookmarkUsers as $UserID) {
154
+            $Cache->delete_value("notify_artists_$UserID");
155
+        }
153 156
     }
154
-  }
155
-  if (!empty($Collages)) {
156
-    foreach ($Collages as $CollageID) {
157
-      $Cache->delete_value("collage_$CollageID");
157
+    if (!empty($Collages)) {
158
+        foreach ($Collages as $CollageID) {
159
+            $Cache->delete_value("collage_$CollageID");
160
+        }
158 161
     }
159
-  }
160 162
 
161
-  $Cache->delete_value("artist_$ArtistID");
162
-  $Cache->delete_value("artist_$NewArtistID");
163
-  $Cache->delete_value("artist_groups_$ArtistID");
164
-  $Cache->delete_value("artist_groups_$NewArtistID");
163
+    $Cache->delete_value("artist_$ArtistID");
164
+    $Cache->delete_value("artist_$NewArtistID");
165
+    $Cache->delete_value("artist_groups_$ArtistID");
166
+    $Cache->delete_value("artist_groups_$NewArtistID");
165 167
 
166
-  // Delete the old artist
167
-  $DB->query("
168
+    // Delete the old artist
169
+    $DB->query("
168 170
     DELETE FROM artists_group
169 171
     WHERE ArtistID = $ArtistID");
170 172
 
171
-  Misc::write_log("The artist $ArtistID ($ArtistName) was made into a non-redirecting alias of artist $NewArtistID ($NewArtistName) by user ".$LoggedUser['ID']." (".$LoggedUser['Username'].')');
173
+    Misc::write_log("The artist $ArtistID ($ArtistName) was made into a non-redirecting alias of artist $NewArtistID ($NewArtistName) by user ".$LoggedUser['ID']." (".$LoggedUser['Username'].')');
172 174
 
173
-  header("Location: artist.php?action=edit&artistid=$NewArtistID");
175
+    header("Location: artist.php?action=edit&artistid=$NewArtistID");
174 176
 } else {
175
-  View::show_header('Merging Artists');
176
-?>
177
-  <div class="header">
178
-    <h2>Confirm merge</h2>
177
+    View::show_header('Merging Artists'); ?>
178
+<div class="header">
179
+  <h2>Confirm merge</h2>
180
+</div>
181
+<form class="merge_form" name="artist" action="artist.php" method="post">
182
+  <input type="hidden" name="action" value="change_artistid" />
183
+  <input type="hidden" name="auth"
184
+    value="<?=$LoggedUser['AuthKey']?>" />
185
+  <input type="hidden" name="artistid" value="<?=$ArtistID?>" />
186
+  <input type="hidden" name="newartistid"
187
+    value="<?=$NewArtistID?>" />
188
+  <input type="hidden" name="confirm" value="1" />
189
+  <div style="text-align: center;">
190
+    <p>Please confirm that you wish to make <a
191
+        href="artist.php?id=<?=$ArtistID?>"><?=display_str($ArtistName)?> (<?=$ArtistID?>)</a> into a non-redirecting alias of <a
192
+        href="artist.php?id=<?=$NewArtistID?>"><?=display_str($NewArtistName)?> (<?=$NewArtistID?>)</a>.</p>
193
+    <br />
194
+    <input type="submit" value="Confirm" />
179 195
   </div>
180
-  <form class="merge_form" name="artist" action="artist.php" method="post">
181
-    <input type="hidden" name="action" value="change_artistid" />
182
-    <input type="hidden" name="auth" value="<?=$LoggedUser['AuthKey']?>" />
183
-    <input type="hidden" name="artistid" value="<?=$ArtistID?>" />
184
-    <input type="hidden" name="newartistid" value="<?=$NewArtistID?>" />
185
-    <input type="hidden" name="confirm" value="1" />
186
-    <div style="text-align: center;">
187
-      <p>Please confirm that you wish to make <a href="artist.php?id=<?=$ArtistID?>"><?=display_str($ArtistName)?> (<?=$ArtistID?>)</a> into a non-redirecting alias of <a href="artist.php?id=<?=$NewArtistID?>"><?=display_str($NewArtistName)?> (<?=$NewArtistID?>)</a>.</p>
188
-      <br />
189
-      <input type="submit" value="Confirm" />
190
-    </div>
191
-  </form>
192
-<?
196
+</form>
197
+<?php
193 198
   View::show_footer();
194 199
 }
195
-?>

+ 38
- 29
sections/artist/delete.php View File

@@ -1,11 +1,13 @@
1
-<?
1
+<?php
2
+
3
+/*
2 4
 /************************************************************************
3 5
 ||------------|| Delete artist ||--------------------------------------||
4 6
 
5 7
 This is a very powerful page - it deletes an artist, and all associated
6 8
 requests and torrents. It is called when $_GET['action'] == 'delete'.
7 9
 
8
-************************************************************************/
10
+************************************************************************
9 11
 
10 12
 authorize();
11 13
 
@@ -34,23 +36,26 @@ $DB->query("
34 36
 $Count = $DB->record_count();
35 37
 if ($DB->has_results()) {
36 38
 ?>
37
-  <div>
38
-    There are still torrents that have <a href="artist.php?id=<?=$ArtistID?>" class="tooltip" title="View artist" dir="ltr"><?=$Name?></a> as an artist.<br />
39
-    Please remove the artist from these torrents manually before attempting to delete.<br />
40
-    <div class="box pad">
41
-      <ul>
42
-<?
39
+<div>
40
+  There are still torrents that have <a
41
+    href="artist.php?id=<?=$ArtistID?>" class="tooltip"
42
+    title="View artist" dir="ltr"><?=$Name?></a> as an artist.<br />
43
+  Please remove the artist from these torrents manually before attempting to delete.<br />
44
+  <div class="box pad">
45
+    <ul>
46
+      <?
43 47
   while (list($GroupName, $GroupID) = $DB->next_record(MYSQLI_NUM, true)) {
44 48
 ?>
45
-        <li>
46
-          <a href="torrents.php?id=<?=$GroupID?>" class="tooltip" title="View torrent group" dir="ltr"><?=$GroupName?></a>
47
-        </li>
48
-<?
49
+      <li>
50
+        <a href="torrents.php?id=<?=$GroupID?>" class="tooltip"
51
+          title="View torrent group" dir="ltr"><?=$GroupName?></a>
52
+      </li>
53
+      <?
49 54
   }
50 55
 ?>
51
-      </ul>
52
-    </div>
56
+    </ul>
53 57
   </div>
58
+</div>
54 59
 <?
55 60
 }
56 61
 
@@ -62,32 +67,36 @@ $DB->query("
62 67
 $Count += $DB->record_count();
63 68
 if ($DB->has_results()) {
64 69
 ?>
65
-  <div>
66
-    There are still requests that have <a href="artist.php?id=<?=$ArtistID?>" class="tooltip" title="View artist" dir="ltr"><?=$Name?></a> as an artist.<br />
67
-    Please remove the artist from these requests manually before attempting to delete.<br />
68
-    <div class="box pad">
69
-      <ul>
70
-<?
70
+<div>
71
+  There are still requests that have <a
72
+    href="artist.php?id=<?=$ArtistID?>" class="tooltip"
73
+    title="View artist" dir="ltr"><?=$Name?></a> as an artist.<br />
74
+  Please remove the artist from these requests manually before attempting to delete.<br />
75
+  <div class="box pad">
76
+    <ul>
77
+      <?
71 78
   while (list($RequestName, $RequestID) = $DB->next_record(MYSQLI_NUM, true)) {
72 79
 ?>
73
-        <li>
74
-          <a href="requests.php?action=view&amp;id=<?=$RequestID?>" class="tooltip" title="View request" dir="ltr"><?=$RequestName?></a>
75
-        </li>
76
-<?
80
+      <li>
81
+        <a href="requests.php?action=view&amp;id=<?=$RequestID?>"
82
+          class="tooltip" title="View request" dir="ltr"><?=$RequestName?></a>
83
+      </li>
84
+      <?
77 85
   }
78 86
 ?>
79
-      </ul>
80
-    </div>
87
+    </ul>
81 88
   </div>
89
+</div>
82 90
 <?
83 91
 }
84 92
 
85 93
 if ($Count == 0) {
86 94
   Artists::delete_artist($ArtistID);
87 95
 ?>
88
-  <div class="box pad">
89
-    Artist "<?=$Name?>" deleted!
90
-  </div>
96
+<div class="box pad">
97
+  Artist "<?=$Name?>" deleted!
98
+</div>
91 99
 <?
92 100
 }
93 101
 View::show_footer();?>
102
+*/

+ 2
- 2
sections/forums/thread.php View File

@@ -516,7 +516,7 @@ foreach ($Thread as $Key => $Post) {
516 516
     <td colspan="<?=Users::has_avatars_enabled() ? 2 : 1?>">
517 517
       <div class="float_left"><a class="post_id"
518 518
           href="forums.php?action=viewthread&amp;threadid=<?=$ThreadID?>&amp;postid=<?=$PostID?>#post<?=$PostID?>">#<?=$PostID?></a>
519
-        <?=Users::format_username($AuthorID, true, true, true, true, true, $IsDonorForum);
519
+        <?=Users::format_username($AuthorID, true, true, true, true, true);
520 520
     echo "\n"; ?>
521 521
         <?=time_diff($AddedTime, 2);
522 522
     echo "\n"; ?>
@@ -598,7 +598,7 @@ foreach ($Thread as $Key => $Post) {
598 598
             onclick="LoadEdit('forums', <?=$PostID?>, 1); return false;">&laquo;</a>
599 599
           <?php } ?>
600 600
           Last edited by
601
-          <?=Users::format_username($EditedUserID, false, false, false, false, false, $IsDonorForum) ?>
601
+          <?=Users::format_username($EditedUserID, false, false, false, false, false) ?>
602 602
           <?=time_diff($EditedTime, 2, true, true)?>
603 603
         </div>
604 604
         <?php } ?>

+ 39
- 19
sections/index/private.php View File

@@ -93,15 +93,26 @@ for ($i = 0; $i < $Limit; $i++) {
93 93
 if (($Freeleeches = $Cache->get_value('shop_freeleech_list')) === false) {
94 94
     $DB->query("
95 95
     SELECT
96
-      TorrentID,
97
-      UNIX_TIMESTAMP(ExpiryTime),
98
-      COALESCE(NULLIF(Name,''), NULLIF(Title2,''), NameJP) AS Name,
99
-      WikiImage
100
-    FROM shop_freeleeches AS sf
101
-    LEFT JOIN torrents AS t on sf.TorrentID=t.ID
102
-    LEFT JOIN torrents_group AS tg ON tg.ID=t.GroupID
103
-    ORDER BY ExpiryTime ASC
104
-    LIMIT 10");
96
+      `TorrentID`,
97
+      UNIX_TIMESTAMP(`ExpiryTime`),
98
+      COALESCE(
99
+        NULLIF(`title`, ''),
100
+        NULLIF(`subject`, ''),
101
+        `object`
102
+      ) AS `Name`,
103
+      `picture`
104
+    FROM
105
+      `shop_freeleeches` AS sf
106
+    LEFT JOIN `torrents` AS t
107
+    ON
108
+      sf.`TorrentID` = t.`ID`
109
+    LEFT JOIN `torrents_group` AS tg
110
+    ON
111
+      tg.`id` = t.`GroupID`
112
+    ORDER BY
113
+      `ExpiryTime` ASC
114
+    LIMIT 10
115
+    ");
105 116
     $Freeleeches = $DB->to_array();
106 117
     $Cache->cache_value('shop_freeleech_list', $Freeleeches, 1209600);
107 118
 }
@@ -447,16 +458,25 @@ $Recommend_artists = $Cache->get_value('recommend_artists');
447 458
 if (!is_array($Recommend) || !is_array($Recommend_artists)) {
448 459
     $DB->query("
449 460
     SELECT
450
-      tr.GroupID,
451
-      tr.UserID,
452
-      u.Username,
453
-      tg.Name,
454
-      tg.TagList
455
-    FROM torrents_recommended AS tr
456
-      JOIN torrents_group AS tg ON tg.ID = tr.GroupID
457
-      LEFT JOIN users_main AS u ON u.ID = tr.UserID
458
-    ORDER BY tr.Time DESC
459
-    LIMIT 10");
461
+      tr.`GroupID`,
462
+      tr.`UserID`,
463
+      u.`Username`,
464
+      tg.`title`,
465
+      tg.`tag_list`
466
+    FROM
467
+      `torrents_recommended` AS tr
468
+    JOIN `torrents_group` AS tg
469
+    ON
470
+      tg.`id` = tr.`GroupID`
471
+    LEFT JOIN `users_main` AS u
472
+    ON
473
+      u.`ID` = tr.`UserID`
474
+    ORDER BY
475
+      tr.`Time`
476
+    DESC
477
+    LIMIT 10
478
+    ");
479
+    
460 480
     $Recommend = $DB->to_array();
461 481
     $Cache->cache_value('recommend', $Recommend, 1209600);
462 482
 

+ 2
- 2
sections/locked/index.php View File

@@ -1,5 +1,5 @@
1 1
 <?php
2
-#declare(strict_types=1);
2
+declare(strict_types=1);
3 3
 
4 4
 enforce_login();
5 5
 
@@ -7,4 +7,4 @@ if (!check_perms('users_mod') && !isset(G::$LoggedUser['LockedAccount'])) {
7 7
     error(404);
8 8
 }
9 9
 
10
-include 'default.php';
10
+require_once 'default.php';

+ 0
- 24
sections/rules/chat.php View File

@@ -13,30 +13,6 @@ View::show_header('Chat Rules');
13 13
 
14 14
 /*
15 15
 echo '<pre>';
16
-/*
17
-# https://github.com/J7mbo/twitter-api-php
18
-require_once('TwitterAPIExchange.php');
19
-
20
-$settings = array(
21
-  'oauth_access_token' => "YOUR_OAUTH_ACCESS_TOKEN",
22
-  'oauth_access_token_secret' => "YOUR_OAUTH_ACCESS_TOKEN_SECRET",
23
-  'consumer_key' => "YOUR_CONSUMER_KEY",
24
-  'consumer_secret' => "YOUR_CONSUMER_SECRET"
25
-);
26
-
27
-$url = 'https://api.twitter.com/1.1/blocks/create.json';
28
-$requestMethod = 'POST';
29
-
30
-$postfields = array(
31
-  'screen_name' => 'usernameToBlock',
32
-  'skip_status' => '1'
33
-);
34
-
35
-$twitter = new TwitterAPIExchange($settings);
36
-echo $twitter->buildOauth($url, $requestMethod)
37
-    ->setPostfields($postfields)
38
-    ->performRequest();
39
-* /
40 16
 
41 17
 #var_dump();
42 18
 #var_dump();

+ 27
- 19
sections/schedule/daily/top10_daily.php View File

@@ -9,25 +9,33 @@ $HistoryID = $DB->inserted_id();
9 9
 $Top10 = $Cache->get_value('top10tor_day_10');
10 10
 if ($Top10 === false) {
11 11
     $DB->query("
12
-      SELECT
13
-        t.ID,
14
-        g.ID,
15
-        g.Name,
16
-        g.CategoryID,
17
-        g.WikiImage,
18
-        g.TagList,
19
-        t.Media,
20
-        g.Year,
21
-        t.Snatched,
22
-        t.Seeders,
23
-        t.Leechers,
24
-        ((t.Size * t.Snatched) + (t.Size * 0.5 * t.Leechers)) AS Data
25
-      FROM torrents AS t
26
-        LEFT JOIN torrents_group AS g ON g.ID = t.GroupID
27
-      WHERE t.Seeders > 0
28
-        AND t.Time > ('$sqltime' - INTERVAL 1 DAY)
29
-      ORDER BY (t.Seeders + t.Leechers) DESC
30
-      LIMIT 10;");
12
+    SELECT
13
+      t.`ID`,
14
+      g.`id`,
15
+      g.`title`,
16
+      g.`category_id`,
17
+      g.`picture`,
18
+      g.`tag_list`,
19
+      t.`Media`,
20
+      g.`published`,
21
+      t.`Snatched`,
22
+      t.`Seeders`,
23
+      t.`Leechers`,
24
+      (
25
+        (t.`Size` * t.`Snatched`) +(t.`Size` * 0.5 * t.`Leechers`)
26
+      ) AS `Data`
27
+    FROM
28
+      `torrents` AS t
29
+    LEFT JOIN `torrents_group` AS g
30
+    ON
31
+      g.`id` = t.`GroupID`
32
+    WHERE
33
+      t.`Seeders` > 0 AND t.`Time` >('$sqltime' - INTERVAL 1 DAY)
34
+    ORDER BY
35
+      (t.`Seeders` + t.`Leechers`)
36
+    DESC
37
+    LIMIT 10;
38
+    ");
31 39
     $Top10 = $DB->to_array();
32 40
 }
33 41
 

+ 27
- 19
sections/schedule/weekly/top10_weekly.php View File

@@ -9,25 +9,33 @@ $HistoryID = $DB->inserted_id();
9 9
 $Top10 = $Cache->get_value('top10tor_week_10');
10 10
 if ($Top10 === false) {
11 11
     $DB->query("
12
-      SELECT
13
-        t.ID,
14
-        g.ID,
15
-        g.Name,
16
-        g.CategoryID,
17
-        g.WikiImage,
18
-        g.TagList,
19
-        t.Media,
20
-        g.Year,
21
-        t.Snatched,
22
-        t.Seeders,
23
-        t.Leechers,
24
-        ((t.Size * t.Snatched) + (t.Size * 0.5 * t.Leechers)) AS Data
25
-      FROM torrents AS t
26
-        LEFT JOIN torrents_group AS g ON g.ID = t.GroupID
27
-      WHERE t.Seeders > 0
28
-        AND t.Time > ('$sqltime' - INTERVAL 1 WEEK)
29
-      ORDER BY (t.Seeders + t.Leechers) DESC
30
-      LIMIT 10;");
12
+    SELECT
13
+      t.`ID`,
14
+      g.`id`,
15
+      g.`title`,
16
+      g.`category_id`,
17
+      g.`picture`,
18
+      g.`tag_list`,
19
+      t.`Media`,
20
+      g.`published`,
21
+      t.`Snatched`,
22
+      t.`Seeders`,
23
+      t.`Leechers`,
24
+      (
25
+        (t.`Size` * t.`Snatched`) +(t.`Size` * 0.5 * t.`Leechers`)
26
+      ) AS `Data`
27
+    FROM
28
+      `torrents` AS t
29
+    LEFT JOIN `torrents_group` AS g
30
+    ON
31
+      g.`id` = t.`GroupID`
32
+    WHERE
33
+      t.`Seeders` > 0 AND t.`Time` >('$sqltime' - INTERVAL 1 WEEK)
34
+    ORDER BY
35
+      (t.`Seeders` + t.`Leechers`)
36
+    DESC
37
+    LIMIT 10;
38
+    ");
31 39
 
32 40
     $Top10 = $DB->to_array();
33 41
 }

+ 0
- 16
sections/slaves/index.php View File

@@ -1,16 +0,0 @@
1
-<?
2
-enforce_login();
3
-
4
-if (isset($_REQUEST['action'])) {
5
-  switch ($_REQUEST['action']) {
6
-    case '':
7
-      include('upload_1GB.php');
8
-      break;
9
-    default:
10
-      error(404);
11
-      break;
12
-  }
13
-} else {
14
-  require(SERVER_ROOT.'/sections/slaves/slaves.php');
15
-}
16
-?>

+ 0
- 60
sections/slaves/slaves.php View File

@@ -1,60 +0,0 @@
1
-<?
2
-$DB->query("SELECT OwnerID FROM slaves WHERE UserID = $UserID");
3
-if ($DB->has_results()) {
4
-  list($Owner) = $DB->next_record();
5
-}
6
-
7
-$UserLevel = Slaves::get_level($UserID);
8
-
9
-$DB->query("SELECT UserID FROM slaves WHERE OwnerID = $UserID");
10
-$Slaves = $DB->collect('UserID');
11
-
12
-if (isset($_POST['release'])) {
13
-  if (in_array($_POST['release'], $Slaves)) {
14
-    $DB->query("
15
-      DELETE FROM slaves
16
-      WHERE UserID = ".db_string($_POST['release'])."
17
-      AND OwnerID = '$UserID'");
18
-  }
19
-  $Slaves = array_diff($Slaves, [$_POST['release']]);
20
-}
21
-
22
-foreach ($Slaves as $i => $Slave) {
23
-  $Level = slaves::get_level($Slave);
24
-  $Slaves[$i] = ['ID' => $Slave, 'Level' => $Level];
25
-}
26
-
27
-View::show_header('Slaves');
28
-?>
29
-<div>
30
-  <h2>Slavery</h2>
31
-  <div class="box pad">
32
-<?php if (isset($Owner)) { ?>
33
-    <h3>You are owned by <?=Users::format_username($Owner, false, true, true)?></h3>
34
-<?php } else { ?>
35
-    <h3>You are free</h3>
36
-<?php } ?>
37
-  </div>
38
-<?php if (sizeof($Slaves) == 0) { ?>
39
-  <h3>You have no slaves</h3>
40
-<?php } else { ?>
41
-  <h2>Your slaves</h2>
42
-  <div class="box">
43
-    <table>
44
-      <tr class="colhead">
45
-        <td>Slave</td>
46
-        <td>Level</td>
47
-        <td>Release</td>
48
-      </tr>
49
-<?php foreach ($Slaves as $Slave) { ?>
50
-      <tr>
51
-        <td><?=Users::format_username($Slave['ID'], false, true, true)?></td>
52
-        <td><?=number_format($Slave['Level'])?></td>
53
-        <td><form method="post"><button type="submit" name="release" value=<?=$Slave['ID']?>>Release</button></form></td>
54
-      </tr>
55
-<?php } ?>
56
-    </table>
57
-  </div>
58
-<?php } ?>
59
-</div>
60
-<? View::show_footer(); ?>

+ 3
- 3
sections/stats/torrents.php View File

@@ -53,15 +53,15 @@ if (!list($Labels, $InFlow, $OutFlow, $Max) = $Cache->get_value('torrents_timeli
53 53
 if (!$CategoryDistribution = $Cache->get_value('category_distribution')) {
54 54
     $DB->query("
55 55
     SELECT
56
-      tg.`CategoryID`,
56
+      tg.`category_id`,
57 57
       COUNT(t.`ID`) AS Torrents
58 58
     FROM
59 59
       `torrents` AS t
60 60
     JOIN `torrents_group` AS tg
61 61
     ON
62
-      tg.`ID` = t.`GroupID`
62
+      tg.`id` = t.`GroupID`
63 63
     GROUP BY
64
-      tg.`CategoryID`
64
+      tg.`category_id`
65 65
     ORDER BY
66 66
       `Torrents`
67 67
     DESC

+ 0
- 110
sections/store/capture_user.php View File

@@ -1,110 +0,0 @@
1
-<?php
2
-#declare(strict_types=1);
3
-
4
-if (isset($_POST['target']) && isset($_POST['amount'])) {
5
-    $TargetID = abs(intval($_POST['target']));
6
-    $Amount = abs(intval($_POST['amount']));
7
-    $UserID = $LoggedUser['ID'];
8
-
9
-    $DB->query("
10
-      SELECT u.BonusPoints, p.Level
11
-      FROM users_main AS u
12
-      LEFT JOIN permissions AS p ON u.PermissionID=p.ID
13
-      WHERE u.ID = $UserID");
14
-
15
-    if ($DB->has_results()) {
16
-        list($Points, $PLevel) = $DB->next_record();
17
-
18
-        if ($Points < $Amount) {
19
-            error('Not enough points!');
20
-        }
21
-
22
-        if ($UserID == $TargetID) {
23
-            error("You can't capture yourself!");
24
-        }
25
-
26
-        if ($PLevel < 200) {
27
-            error('Insufficient class');
28
-        }
29
-
30
-        $DB->query("SELECT COUNT(*) FROM slaves WHERE OwnerID = $UserID");
31
-        if ($DB->next_record()[0] >= 6) {
32
-            error('You own too many users already');
33
-        }
34
-
35
-        // Logic for capture success
36
-        $DB->query("
37
-          SELECT u.Uploaded,
38
-            u.Downloaded,
39
-            u.BonusPoints,
40
-            COUNT(t.UserID)
41
-          FROM users_main AS u
42
-          LEFT JOIN torrents AS t ON u.ID=t.UserID
43
-          WHERE u.ID = $TargetID");
44
-
45
-        if (!$DB->has_results()) {
46
-            error('User does not exist');
47
-        }
48
-
49
-        list($Upload, $Download, $Points, $Uploads) = $DB->next_record();
50
-        $AdjLevel = intval(((($Uploads**0.35)*1.5)+1) * max(($Upload+($Points*1000000)-$Download)/(1024**3), 1) * 1000);
51
-
52
-        if ($Amount <= $AdjLevel) {
53
-            error('You need to spend more points to have any chance of catching this user!');
54
-        }
55
-
56
-        $Captured = (rand(0, $Amount) >= $AdjLevel);
57
-        $DB->query("
58
-          UPDATE users_main
59
-          SET BonusPoints = BonusPoints - $Amount
60
-          WHERE ID = $UserID");
61
-        $Cache->delete_value('user_info_heavy_'.$UserID);
62
-
63
-        if ($Captured) {
64
-            $DB->query("
65
-              INSERT INTO slaves
66
-                (UserID, OwnerID)
67
-              Values($TargetID, $UserID)");
68
-        }
69
-    }
70
-
71
-    View::show_header('Store'); ?>
72
-<div>
73
-  <h2>Capture <?=($Captured?'Successful':'Failed')?>
74
-  </h2>
75
-  <div class="box">
76
-    <p>
77
-      <?=($Captured?'You successfully captured your target':'Your target eluded capture')?>
78
-    </p>
79
-    <p>
80
-      <a href="/store.php">Back to Store</a>
81
-      | <a href="/user.php?id=<?=$TargetID?>">Back to Profile</a>
82
-    </p>
83
-  </div>
84
-</div>
85
-<?php View::show_footer();
86
-} else {
87
-    View::show_header('Store'); ?>
88
-<div>
89
-  <div class="box text-align: center;">
90
-
91
-    <form action="store.php" method="POST">
92
-      <input type="hidden" name="item" value="capture_user">
93
-      <strong>
94
-        Enter the name of the user you want to capture and the <?=BONUS_POINTS?> you want to spend
95
-      </strong>
96
-      <br />
97
-      <input type="text" name="target_name" placeholder="Username">
98
-      <input type="text" name="amount"
99
-        placeholder="<?=BONUS_POINTS?>">
100
-      <input type="submit">
101
-    </form>
102
-
103
-    <p>
104
-      <a href="/store.php">Back to Store</a>
105
-    </p>
106
-  </div>
107
-</div>
108
-<?php
109
-View::show_footer();
110
-}

+ 41
- 51
sections/top10/torrents.php View File

@@ -164,48 +164,32 @@ if (!empty($Where)) {
164 164
     $WhereSum = '';
165 165
 }
166 166
 
167
-$BaseQuery = '
168
-  SELECT
169
-    t.ID,
170
-    g.ID,
171
-    g.Name,
172
-    g.Title2,
173
-    g.NameJP,
174
-    g.CategoryID,
175
-    g.WikiImage,
176
-    g.TagList,
177
-    t.Media,
178
-    g.Year,
179
-    g.Studio,
180
-    t.Snatched,
181
-    t.Seeders,
182
-    t.Leechers,
183
-    ((t.Size * t.Snatched) + (t.Size * 0.5 * t.Leechers)) AS Data,
184
-    t.Size
185
-  FROM torrents AS t
186
-    LEFT JOIN torrents_group AS g ON g.ID = t.GroupID';
187
-
188
-/*
189
-$BaseQuery = '
190
-  SELECT
191
-    t.ID,
192
-    g.ID,
193
-    g.Name,
194
-    g.Title2,
195
-    g.NameJP,
196
-    g.CategoryID,
197
-    g.WikiImage,
198
-    g.TagList,
199
-    t.Media,
200
-    g.Year,
201
-    t.Snatched,
202
-    t.Seeders,
203
-    t.Leechers,
204
-    ((t.Size * t.Snatched) + (t.Size * 0.5 * t.Leechers)) AS Data,
205
-    t.Size
206
-  FROM torrents AS t
207
-    LEFT JOIN torrents_group AS g ON g.ID = t.GroupID';
208
-*/
167
+$BaseQuery = "
168
+SELECT
169
+  t.`ID`,
170
+  g.`id`,
171
+  g.`title`,
172
+  g.`subject`,
173
+  g.`object`,
174
+  g.`category_id`,
175
+  g.`picture`,
176
+  g.`tag_list`,
177
+  t.`Media`,
178
+  g.`published`,
179
+  g.`workgroup`,
180
+  t.`Snatched`,
181
+  t.`Seeders`,
182
+  t.`Leechers`,
183
+  (
184
+    (t.`Size` * t.`Snatched`) +(t.`Size` * 0.5 * t.`Leechers`)
185
+  ) AS `Data`,
186
+  t.`Size`
187
+FROM
188
+  `torrents` AS t
189
+LEFT JOIN `torrents_group` AS g
190
+ON
191
+  g.`id` = t.`GroupID`
192
+";
209 193
 
210 194
 if ($Details === 'all' || $Details === 'day') {
211 195
     $TopTorrentsActiveLastDay = $Cache->get_value('top10tor_day_'.$Limit.$WhereSum.$GroupBySum);
@@ -447,26 +431,32 @@ function generate_torrent_table($Caption, $Tag, $Details, $Limit)
447 431
         <?php
448 432
     switch ($Limit) {
449 433
       case 100: ?>
450
-        &ndash; <a href="top10.php?details=<?=$Tag?>" class="brackets">Top
434
+        &ndash; <a href="top10.php?details=<?=$Tag?>"
435
+            class="brackets">Top
451 436
             10</a>
452 437
         &ndash; <span class="brackets">Top 100</span>
453
-        &ndash; <a href="top10.php?type=torrents&amp;limit=250&amp;details=<?=$Tag?>"
438
+        &ndash; <a
439
+            href="top10.php?type=torrents&amp;limit=250&amp;details=<?=$Tag?>"
454 440
             class="brackets">Top 250</a>
455 441
         <?php break;
456 442
 
457 443
       case 250: ?>
458
-        &ndash; <a href="top10.php?details=<?=$Tag?>" class="brackets">Top
444
+        &ndash; <a href="top10.php?details=<?=$Tag?>"
445
+            class="brackets">Top
459 446
             10</a>
460
-        &ndash; <a href="top10.php?type=torrents&amp;limit=100&amp;details=<?=$Tag?>"
447
+        &ndash; <a
448
+            href="top10.php?type=torrents&amp;limit=100&amp;details=<?=$Tag?>"
461 449
             class="brackets">Top 100</a>
462 450
         &ndash; <span class="brackets">Top 250</span>
463 451
         <?php break;
464 452
 
465 453
       default: ?>
466 454
         &ndash; <span class="brackets">Top 10</span>
467
-        &ndash; <a href="top10.php?type=torrents&amp;limit=100&amp;details=<?=$Tag?>"
455
+        &ndash; <a
456
+            href="top10.php?type=torrents&amp;limit=100&amp;details=<?=$Tag?>"
468 457
             class="brackets">Top 100</a>
469
-        &ndash; <a href="top10.php?type=torrents&amp;limit=250&amp;details=<?=$Tag?>"
458
+        &ndash; <a
459
+            href="top10.php?type=torrents&amp;limit=250&amp;details=<?=$Tag?>"
470 460
             class="brackets">Top 250</a>
471 461
         <?php } ?>
472 462
     </small>
@@ -481,13 +471,13 @@ function generate_torrent_table($Caption, $Tag, $Details, $Limit)
481 471
         <td style="text-align: right;">Size</td>
482 472
         <td style="text-align: right;">Data</td>
483 473
         <td style="text-align: right;" class="sign snatches">
484
-        ↻
474
+            
485 475
         </td>
486 476
         <td style="text-align: right;" class="sign seeders">
487
-        &uarr;
477
+            &uarr;
488 478
         </td>
489 479
         <td style="text-align: right;" class="sign leechers">
490
-        &darr;
480
+            &darr;
491 481
         </td>
492 482
         <td style="text-align: right;">Peers</td>
493 483
     </tr>

+ 2
- 3
sections/torrents/browse.php View File

@@ -1,7 +1,7 @@
1 1
 <?php
2 2
 #declare(strict_types = 1);
3 3
 
4
-include SERVER_ROOT.'/sections/torrents/functions.php';
4
+require_once SERVER_ROOT.'/sections/torrents/functions.php';
5 5
 
6 6
 // The "order by x" links on columns headers
7 7
 function header_link($SortKey, $DefaultWay = 'desc')
@@ -805,8 +805,7 @@ die();
805 805
               # Emoji in classes/astists.class.php
806 806
               $Label = '&ensp;';
807 807
               $DisplayName .= $Label.'<div class="torrent_artists">'.Artists::display_artists($Artists).'</div>';
808
-          }
809
-         ?>
808
+          } ?>
810 809
   <tr class="group<?=$SnatchedGroupClass?>">
811 810
     <?php
812 811
       $ShowGroups = !(!empty($LoggedUser['TorrentGrouping']) && $LoggedUser['TorrentGrouping'] === 1); ?>

+ 10
- 10
sections/torrents/edit.php View File

@@ -32,14 +32,14 @@ SELECT
32 32
   t.`FreeLeechType`,
33 33
   t.`Description` AS TorrentDescription,
34 34
   t.`FileList`,
35
-  tg.`CategoryID`,
36
-  tg.`Name` AS Title,
37
-  tg.`Title2` AS Title2,
38
-  tg.`NameJP` AS TitleJP,
39
-  tg.`Year`,
40
-  tg.`Studio`,
41
-  tg.`Series`,
42
-  tg.`CatalogueNumber`,
35
+  tg.`category_id`,
36
+  tg.`title` AS title,
37
+  tg.`subject` AS subject,
38
+  tg.`object` AS object,
39
+  tg.`published`,
40
+  tg.`workgroup`,
41
+  tg.`location`,
42
+  tg.`identifier`,
43 43
   ag.`Name` AS ArtistName,
44 44
   t.`GroupID`,
45 45
   t.`UserID`,
@@ -50,10 +50,10 @@ FROM
50 50
   `torrents` AS t
51 51
 LEFT JOIN `torrents_group` AS tg
52 52
 ON
53
-  tg.`ID` = t.`GroupID`
53
+  tg.`id` = t.`GroupID`
54 54
 LEFT JOIN `torrents_artists` AS ta
55 55
 ON
56
-  tg.`ID` = ta.`GroupID`
56
+  tg.`id` = ta.`GroupID`
57 57
 LEFT JOIN `artists_group` AS ag
58 58
 ON
59 59
   ag.`ArtistID` = ta.`ArtistID`

+ 13
- 13
sections/torrents/editgroup.php View File

@@ -9,30 +9,30 @@ declare(strict_types = 1);
9 9
  */
10 10
 
11 11
 $GroupID = $_GET['groupid'];
12
-Security::CheckID($GroupID);
12
+Security::checkInt($GroupID);
13 13
 
14 14
 // Get the torrent group name and the body of the last revision
15 15
 $DB->prepare_query("
16 16
 SELECT
17
-  tg.`Name`,
18
-  tg.`Title2`,
19
-  tg.`NameJP`,
17
+  tg.`title`,
18
+  tg.`subject`,
19
+  tg.`object`,
20 20
   wt.`Image`,
21 21
   wt.`Body`,
22
-  tg.`WikiImage`,
23
-  tg.`WikiBody`,
24
-  tg.`Year`,
25
-  tg.`Studio`,
26
-  tg.`Series`,
27
-  tg.`CatalogueNumber`,
28
-  tg.`CategoryID`
22
+  tg.`picture`,
23
+  tg.`description`,
24
+  tg.`year`,
25
+  tg.`labratory`,
26
+  tg.`location`,
27
+  tg.`identifier`,
28
+  tg.`category_id`
29 29
 FROM
30 30
   `torrents_group` AS tg
31 31
 LEFT JOIN `wiki_torrents` AS wt
32 32
 ON
33
-  wt.`RevisionID` = tg.`RevisionID`
33
+  wt.`RevisionID` = tg.`revision_id`
34 34
 WHERE
35
-  tg.`ID` = '$GroupID'
35
+  tg.`id` = '$GroupID'
36 36
 ");
37 37
 $DB->exec_prepared_query();
38 38
 

+ 23
- 23
sections/torrents/functions.php View File

@@ -14,40 +14,40 @@ function get_group_info($GroupID, $Return = true, $RevisionID = 0, $PersonalProp
14 14
 
15 15
         if (!$RevisionID) {
16 16
             $SQL .= '
17
-              g.WikiBody,
18
-              g.WikiImage, ';
17
+            g.`description`,
18
+            g.`picture`, ';
19 19
         } else {
20 20
             $SQL .= '
21
-              w.Body,
22
-              w.Image, ';
21
+            w.`Body`,
22
+            w.`Image`, ';
23 23
         }
24 24
 
25 25
         $SQL .= "
26
-          g.ID,
27
-          g.Name,
28
-          g.Title2,
29
-          g.NameJP,
30
-          g.Year,
31
-          g.Studio,
32
-          g.Series,
33
-          g.CatalogueNumber,
34
-          g.CategoryID,
35
-          g.Time,
36
-            GROUP_CONCAT(DISTINCT tags.Name SEPARATOR '|'),
37
-            GROUP_CONCAT(DISTINCT tags.ID SEPARATOR '|'),
38
-            GROUP_CONCAT(tt.UserID SEPARATOR '|')
39
-          FROM torrents_group AS g
40
-            LEFT JOIN torrents_tags AS tt ON tt.GroupID = g.ID
41
-            LEFT JOIN tags ON tags.ID = tt.TagID";
26
+          g.`id`,
27
+          g.`title`,
28
+          g.`subject`,
29
+          g.`object`,
30
+          g.`published`,
31
+          g.`workgroup`,
32
+          g.`location`,
33
+          g.`identifier`,
34
+          g.`category_id`,
35
+          g.`timestamp`,
36
+            GROUP_CONCAT(DISTINCT tags.`Name` SEPARATOR '|'),
37
+            GROUP_CONCAT(DISTINCT tags.`ID` SEPARATOR '|'),
38
+            GROUP_CONCAT(tt.`UserID` SEPARATOR '|')
39
+          FROM `torrents_group` AS g
40
+            LEFT JOIN `torrents_tags` AS tt ON tt.`GroupID` = g.`id`
41
+            LEFT JOIN `tags` ON tags.`ID` = tt.`TagID`";
42 42
 
43 43
         if ($RevisionID) {
44 44
             $SQL .= "
45
-              LEFT JOIN wiki_torrents AS w ON w.PageID = '".db_string($GroupID)."'
46
-                AND w.RevisionID = '".db_string($RevisionID)."' ";
45
+              LEFT JOIN `wiki_torrents` AS w ON w.`PageID` = '".db_string($GroupID)."'
46
+                AND w.`RevisionID` = '".db_string($RevisionID)."' ";
47 47
         }
48 48
 
49 49
         $SQL .= "
50
-          WHERE g.ID = '".db_string($GroupID)."'
50
+          WHERE g.`id` = '".db_string($GroupID)."'
51 51
             GROUP BY NULL";
52 52
 
53 53
         $DB->query($SQL);

+ 1
- 1
sections/torrents/nonwikiedit.php View File

@@ -1,7 +1,7 @@
1 1
 <?php
2 2
 declare(strict_types=1);
3 3
 
4
-Security::CheckID($_POST['groupid']);
4
+Security::checkInt($_POST['groupid']);
5 5
 authorize();
6 6
 
7 7
 // Usual perm checks

+ 0
- 74
sections/torrents/takechangecategory.php View File

@@ -20,80 +20,6 @@ if (!is_number($OldGroupID) || !is_number($TorrentID) || !$OldGroupID || !$Torre
20 20
     error(0);
21 21
 }
22 22
 
23
-/*
24
-switch ($Categories[$NewCategoryID-1]) {
25
-  case 'Music':
26
-    $ArtistName = db_string(trim($_POST['artist']));
27
-    $Year = trim($_POST['year']);
28
-    $ReleaseType = trim($_POST['releasetype']);
29
-
30
-    if (empty($Year) || empty($ArtistName) || !is_number($Year) || empty($ReleaseType) || !is_number($ReleaseType)) {
31
-        error(0);
32
-    }
33
-
34
-    $DB->query("
35
-      SELECT ArtistID, AliasID, Redirect, Name
36
-      FROM artists_alias
37
-      WHERE Name LIKE '$ArtistName'");
38
-
39
-    if (!$DB->has_results()) {
40
-        $Redirect = 0;
41
-        $DB->query("
42
-        INSERT INTO artists_group (Name)
43
-        VALUES ('$ArtistName')");
44
-        $ArtistID = $DB->inserted_id();
45
-        $DB->query("
46
-        INSERT INTO artists_alias (ArtistID, Name)
47
-        VALUES ('$ArtistID', '$ArtistName')");
48
-        $AliasID = $DB->inserted_id();
49
-    } else {
50
-        list($ArtistID, $AliasID, $Redirect, $ArtistName) = $DB->next_record();
51
-        if ($Redirect) {
52
-            $AliasID = $ArtistID;
53
-        }
54
-    }
55
-
56
-    $DB->query("
57
-      INSERT INTO torrents_group
58
-        (ArtistID, CategoryID, Name, Year, ReleaseType, Time, WikiBody, WikiImage)
59
-      VALUES
60
-        ($ArtistID, '1', '$Title', '$Year', '$ReleaseType', NOW(), '', '')");
61
-    $GroupID = $DB->inserted_id();
62
-
63
-    $DB->query("
64
-      INSERT INTO torrents_artists
65
-        (GroupID, ArtistID, AliasID, Importance, UserID)
66
-      VALUES
67
-        ('$GroupID', '$ArtistID', '$AliasID', '1', '$LoggedUser[ID]')");
68
-    break;
69
-
70
-  case 'Audiobooks':
71
-  case 'Comedy':
72
-    $Year = trim($_POST['year']);
73
-    if (empty($Year) || !is_number($Year)) {
74
-        error(0);
75
-    }
76
-    $DB->query("
77
-      INSERT INTO torrents_group
78
-        (CategoryID, Name, Year, Time, WikiBody, WikiImage)
79
-      VALUES
80
-        ($NewCategoryID, '$Title', '$Year', NOW(), '', '')");
81
-    $GroupID = $DB->inserted_id();
82
-    break;
83
-  case 'Applications':
84
-  case 'Comics':
85
-  case 'E-Books':
86
-  case 'E-Learning Videos':
87
-    $DB->query("
88
-      INSERT INTO torrents_group
89
-        (CategoryID, Name, Time, WikiBody, WikiImage)
90
-      VALUES
91
-        ($NewCategoryID, '$Title', NOW(), '', '')");
92
-    $GroupID = $DB->inserted_id();
93
-    break;
94
-}
95
-*/
96
-
97 23
 $DB->query("
98 24
   UPDATE torrents
99 25
   SET GroupID = '$GroupID'

+ 52
- 41
sections/torrents/takenewgroup.php View File

@@ -1,4 +1,4 @@
1
-<?
1
+<?php
2 2
 #declare(strict_types = 1);
3 3
 
4 4
 /***************************************************************
@@ -9,7 +9,7 @@
9 9
 authorize();
10 10
 
11 11
 if (!check_perms('torrents_edit')) {
12
-  error(403);
12
+    error(403);
13 13
 }
14 14
 
15 15
 $OldGroupID = $_POST['oldgroupid'];
@@ -19,91 +19,102 @@ $Title = db_string(trim($_POST['title']));
19 19
 $Year = db_string(trim($_POST['year']));
20 20
 
21 21
 if (!is_number($OldGroupID) || !is_number($TorrentID) || !is_number($Year) || !$OldGroupID || !$TorrentID || !$Year || empty($Title) || empty($ArtistName)) {
22
-  error(0);
22
+    error(0);
23 23
 }
24 24
 
25
-//Everything is legit, let's just confim they're not retarded
25
+// Everything is legit, let's just confim they're not retarded
26 26
 if (empty($_POST['confirm'])) {
27
-  View::show_header();
28
-?>
29
-  <div class="center">
27
+    View::show_header(); ?>
28
+
29
+<div class="center">
30 30
   <div class="header">
31 31
     <h2>Split Confirm!</h2>
32 32
   </div>
33
+
33 34
   <div class="box pad">
34 35
     <form class="confirm_form" name="torrent_group" action="torrents.php" method="post">
35 36
       <input type="hidden" name="action" value="newgroup" />
36
-      <input type="hidden" name="auth" value="<?=$LoggedUser['AuthKey']?>" />
37
+      <input type="hidden" name="auth"
38
+        value="<?=$LoggedUser['AuthKey']?>" />
37 39
       <input type="hidden" name="confirm" value="true" />
38
-      <input type="hidden" name="torrentid" value="<?=$TorrentID?>" />
39
-      <input type="hidden" name="oldgroupid" value="<?=$OldGroupID?>" />
40
-      <input type="hidden" name="artist" value="<?=display_str($_POST['artist'])?>" />
41
-      <input type="hidden" name="title" value="<?=display_str($_POST['title'])?>" />
40
+      <input type="hidden" name="torrentid"
41
+        value="<?=$TorrentID?>" />
42
+      <input type="hidden" name="oldgroupid"
43
+        value="<?=$OldGroupID?>" />
44
+      <input type="hidden" name="artist"
45
+        value="<?=display_str($_POST['artist'])?>" />
46
+      <input type="hidden" name="title"
47
+        value="<?=display_str($_POST['title'])?>" />
42 48
       <input type="hidden" name="year" value="<?=$Year?>" />
43
-      <h3>You are attempting to split the torrent <a href="torrents.php?torrentid=<?=$TorrentID?>"><?=$TorrentID?></a> off into a new group:</h3>
44
-      <ul><li><?=display_str($_POST['artist'])?> - <?=display_str($_POST['title'])?> [<?=$Year?>]</li></ul>
49
+      <h3>You are attempting to split the torrent <a
50
+          href="torrents.php?torrentid=<?=$TorrentID?>"><?=$TorrentID?></a> off into a new group:</h3>
51
+      <ul>
52
+        <li><?=display_str($_POST['artist'])?> -
53
+          <?=display_str($_POST['title'])?>
54
+          [<?=$Year?>]
55
+        </li>
56
+      </ul>
45 57
       <input type="submit" value="Confirm" />
46 58
     </form>
47 59
   </div>
48
-  </div>
49
-<?
60
+</div>
61
+<?php
50 62
   View::show_footer();
51 63
 } else {
52
-  $DB->query("
64
+    $DB->query("
53 65
     SELECT ArtistID,  Name
54 66
     FROM artists_group
55 67
     WHERE Name = '$ArtistName'");
56
-  if (!$DB->has_results()) {
57
-    $DB->query("
68
+    if (!$DB->has_results()) {
69
+        $DB->query("
58 70
       INSERT INTO artists_group (Name)
59 71
       VALUES ('$ArtistName')");
60
-    $ArtistID = $DB->inserted_id();
61
-  } else {
62
-    list($ArtistID, $ArtistName) = $DB->next_record();
63
-  }
72
+        $ArtistID = $DB->inserted_id();
73
+    } else {
74
+        list($ArtistID, $ArtistName) = $DB->next_record();
75
+    }
64 76
 
65
-  $DB->query("
77
+    $DB->query("
66 78
     SELECT CategoryID
67 79
     FROM torrents_group
68 80
     WHERE ID = $OldGroupID");
69 81
 
70
-  list($CategoryID) = $DB->next_record();
82
+    list($CategoryID) = $DB->next_record();
71 83
 
72
-  $DB->query("
84
+    $DB->query("
73 85
     INSERT INTO torrents_group
74 86
       (CategoryID, Name, Year, Time, WikiBody, WikiImage)
75 87
     VALUES
76 88
       ('$CategoryID', '$Title', '$Year', NOW(), '', '')");
77
-  $GroupID = $DB->inserted_id();
89
+    $GroupID = $DB->inserted_id();
78 90
 
79
-  $DB->query("
91
+    $DB->query("
80 92
     INSERT INTO torrents_artists
81 93
       (GroupID, ArtistID, UserID)
82 94
     VALUES
83 95
       ('$GroupID', '$ArtistID', '$LoggedUser[ID]')");
84 96
 
85
-  $DB->query("
97
+    $DB->query("
86 98
     UPDATE torrents
87 99
     SET GroupID = '$GroupID'
88 100
     WHERE ID = '$TorrentID'");
89 101
 
90
-  // Delete old group if needed
91
-  $DB->query("
102
+    // Delete old group if needed
103
+    $DB->query("
92 104
     SELECT ID
93 105
     FROM torrents
94 106
     WHERE GroupID = '$OldGroupID'");
95
-  if (!$DB->has_results()) {
96
-    Torrents::delete_group($OldGroupID);
97
-  } else {
98
-    Torrents::update_hash($OldGroupID);
99
-  }
107
+    if (!$DB->has_results()) {
108
+        Torrents::delete_group($OldGroupID);
109
+    } else {
110
+        Torrents::update_hash($OldGroupID);
111
+    }
100 112
 
101
-  Torrents::update_hash($GroupID);
113
+    Torrents::update_hash($GroupID);
102 114
 
103
-  $Cache->delete_value("torrent_download_$TorrentID");
115
+    $Cache->delete_value("torrent_download_$TorrentID");
104 116
 
105
-  Misc::write_log("Torrent $TorrentID was edited by " . $LoggedUser['Username']);
117
+    Misc::write_log("Torrent $TorrentID was edited by " . $LoggedUser['Username']);
106 118
 
107
-  header("Location: torrents.php?id=$GroupID");
119
+    header("Location: torrents.php?id=$GroupID");
108 120
 }
109
-?>

+ 64
- 47
sections/upload/upload.php View File

@@ -1,17 +1,19 @@
1 1
 <?php
2
-#declare(strict_types=1);
2
+declare(strict_types=1);
3 3
 
4
-//**********************************************************************//
5
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Upload form ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
6
-// This page relies on the TorrentForm class. All it does is call      //
7
-// the necessary functions.                                             //
8
-//----------------------------------------------------------------------//
9
-// $Properties, $Err and $UploadForm are set in takeupload.php, and     //
10
-// are only used when the form doesn't validate and this page must be   //
11
-// called again.                                                        //
12
-//**********************************************************************//
4
+/**
5
+ * Upload form
6
+ *
7
+ * This page relies on the TorrentForm class.
8
+ * All it does is call the necessary functions.
9
+ *
10
+ * $Properties, $Err and $UploadForm are set in takeupload.php,
11
+ * and are only used when the form doesn't validate
12
+ * and this page must be called again.
13
+ */
13 14
 
14 15
 ini_set('max_file_uploads', '100');
16
+
15 17
 View::show_header(
16 18
     'Upload',
17 19
     'upload,bbcode,vendor/easymde.min',
@@ -19,23 +21,25 @@ View::show_header(
19 21
 );
20 22
 
21 23
 if (empty($Properties) && !empty($_GET['groupid']) && is_number($_GET['groupid'])) {
22
-    $DB->query('
24
+    $GroupID = $_GET['groupid'];
25
+    $DB->query("
23 26
       SELECT
24
-        tg.ID as GroupID,
25
-        tg.CategoryID,
26
-        tg.Name AS Title,
27
-        tg.Title2,
28
-        tg.NameJP AS TitleJP,
29
-        tg.Year,
30
-        tg.Studio,
31
-        tg.Series,
32
-        tg.CatalogueNumber,
33
-        tg.WikiImage AS Image,
34
-        tg.WikiBody AS GroupDescription
35
-      FROM torrents_group AS tg
36
-        LEFT JOIN torrents AS t ON t.GroupID = tg.ID
37
-      WHERE tg.ID = '.$_GET['groupid'].'
38
-      GROUP BY tg.ID');
27
+        tg.`id` as GroupID,
28
+        tg.`category_id`,
29
+        tg.`title` AS Title,
30
+        tg.`subject`,
31
+        tg.`object` AS TitleJP,
32
+        tg.`published`,
33
+        tg.`workgroup`,
34
+        tg.`location`,
35
+        tg.`identifier`,
36
+        tg.`picture` AS Image,
37
+        tg.`description` AS GroupDescription
38
+      FROM `torrents_group` AS tg
39
+        LEFT JOIN `torrents` AS t ON t.`GroupID` = tg.`id`
40
+      WHERE tg.`id` = '$GroupID'
41
+      GROUP BY tg.`id`
42
+      ");
39 43
 
40 44
     if ($DB->has_results()) {
41 45
         list($Properties) = $DB->to_array(false, MYSQLI_BOTH);
@@ -44,11 +48,14 @@ if (empty($Properties) && !empty($_GET['groupid']) && is_number($_GET['groupid']
44 48
         $Properties['Artists'] = Artists::get_artist($_GET['groupid']);
45 49
 
46 50
         $DB->query("
47
-          SELECT
48
-            GROUP_CONCAT(tags.Name SEPARATOR ', ') AS TagList
49
-          FROM torrents_tags AS tt
50
-            JOIN tags ON tags.ID = tt.TagID
51
-          WHERE tt.GroupID = '$_GET[groupid]'");
51
+        SELECT
52
+          GROUP_CONCAT(tags.`Name` SEPARATOR ', ') AS TagList
53
+        FROM
54
+          `torrents_tags` AS tt
55
+        JOIN `tags` ON tags.`ID` = tt.`TagID`
56
+        WHERE
57
+          tt.`GroupID` = '$_GET[groupid]'
58
+        ");
52 59
         list($Properties['TagList']) = $DB->next_record();
53 60
     } else {
54 61
         unset($_GET['groupid']);
@@ -58,19 +65,23 @@ if (empty($Properties) && !empty($_GET['groupid']) && is_number($_GET['groupid']
58 65
         $Properties['RequestID'] = $_GET['requestid'];
59 66
     }
60 67
 } elseif (empty($Properties) && isset($_GET['requestid']) && is_number($_GET['requestid'])) {
61
-    $DB->query('
62
-      SELECT
63
-        ID AS RequestID,
64
-        CategoryID,
65
-        Title AS Title,
66
-        Title2,
67
-        TitleJP AS TitleJP,
68
-        CatalogueNumber,
69
-        Image
70
-      FROM requests
71
-      WHERE ID = '.$_GET['requestid']);
72
-
68
+    $RequestID = $_GET['requestid'];
69
+    $DB->query("
70
+    SELECT
71
+      `ID` AS RequestID,
72
+      `CategoryID`,
73
+      `Title` AS Title,
74
+      `Title2`,
75
+      `TitleJP` AS TitleJP,
76
+      `CatalogueNumber`,
77
+      `Image`
78
+    FROM
79
+      `requests`
80
+    WHERE
81
+      `ID` = '$RequestID'
82
+    ");
73 83
     list($Properties) = $DB->to_array(false, MYSQLI_BOTH);
84
+
74 85
     $UploadForm = $Categories[$Properties['CategoryID'] - 1];
75 86
     $Properties['CategoryName'] = $Categories[$Properties['CategoryID'] - 1];
76 87
     $Properties['Artists'] = Requests::get_artists($_GET['requestid']);
@@ -93,10 +104,15 @@ $TorrentForm = new TorrentForm($Properties ?? false, $Err ?? false);
93 104
 $GenreTags = $Cache->get_value('genre_tags');
94 105
 if (!$GenreTags) {
95 106
     $DB->query("
96
-      SELECT Name
97
-      FROM tags
98
-      WHERE TagType = 'genre'
99
-        ORDER BY Name");
107
+    SELECT
108
+      `Name`
109
+    FROM
110
+      `tags`
111
+    WHERE
112
+      `TagType` = 'genre'
113
+    ORDER BY
114
+      `Name`
115
+    ");
100 116
     
101 117
     $GenreTags = $DB->collect('Name');
102 118
     $Cache->cache_value('genre_tags', $GenreTags, 3600 * 6);
@@ -111,4 +127,5 @@ echo $TorrentForm->error();
111 127
 echo $TorrentForm->head();
112 128
 echo $TorrentForm->basicInfo();
113 129
 echo $TorrentForm->upload_form();
130
+
114 131
 View::show_footer();

+ 0
- 42
sections/user/edit.php View File

@@ -86,7 +86,6 @@ if ($DonorIsVisible === null) {
86 86
 extract(Donations::get_enabled_rewards($UserID));
87 87
 $Rewards = Donations::get_rewards($UserID);
88 88
 $ProfileRewards = Donations::get_profile_rewards($UserID);
89
-$DonorTitles = Donations::get_titles($UserID);
90 89
 ?>
91 90
 
92 91
 <div>
@@ -748,47 +747,6 @@ HTML;
748 747
               value="<?=$Rewards['CustomIcon']?>" />
749 748
           </td>
750 749
         </tr>
751
-        <?php }
752
-
753
-# Donor forum honorific
754
-  if ($HasDonorForum) { ?>
755
-        <tr id="pers_donorforum_tr">
756
-          <td class="label">
757
-            <strong>Donor forum honorific</strong>
758
-          </td>
759
-
760
-          <td>
761
-            <div>
762
-              <label>
763
-                <strong>Prefix</strong>
764
-                <input type="text" size="30" maxlength="30" name="donor_title_prefix" id="donor_title_prefix"
765
-                  value="<?=$DonorTitles['Prefix']?>" />
766
-              </label>
767
-            </div>
768
-
769
-            <div>
770
-              <label>
771
-                <strong>Suffix</strong>
772
-                <input type="text" size="30" maxlength="30" name="donor_title_suffix" id="donor_title_suffix"
773
-                  value="<?=$DonorTitles['Suffix']?>" />
774
-              </label>
775
-            </div>
776
-
777
-            <div>
778
-              <label>
779
-                <strong>Hide comma</strong>
780
-                <input type="checkbox" id="donor_title_comma" name="donor_title_comma" <?=!$DonorTitles['UseComma'] ? ' checked="checked"' : '' ?>
781
-                />
782
-              </label>
783
-            </div>
784
-
785
-            <strong>Preview</strong>
786
-            <span id="donor_title_prefix_preview"></span>
787
-            <?=$Username?>
788
-            <span id="donor_title_comma_preview">,</span>
789
-            <span id="donor_title_suffix_preview"></span>
790
-          </td>
791
-        </tr>
792 750
         <?php } ?>
793 751
 
794 752
         <!-- Profile title 1 -->

+ 22
- 58
sections/user/user.php View File

@@ -365,46 +365,9 @@ if (!$OwnProfile && !$LoggedUser['DisablePoints']) { ?>
365 365
         <p>Note: 10% of your gift is taken as tax.</p>
366 366
       </div>
367 367
     </div>
368
-    <?php
369
-}
370
-$DB->query("
371
-  SELECT u.Username
372
-  FROM slaves AS s
373
-  LEFT JOIN users_main AS u ON u.ID = s.OwnerID
374
-  WHERE s.UserID = $UserID");
375
-if ($LoggedUser['Class'] >= 200 || $DB->has_results()) { ?>
376
-    <div class='box ownership_box'>
377
-      <div class='head colhead_dark'>Ownership</div>
378
-      <div class="pad">
379
-        <?php if ($DB->has_results()) { ?>
380
-        <p>This user is owned by <?=($DB->next_record()['Username'])?>
381
-        </p>
382
-        <?php } else {
383
-    $DB->query("
384
-      SELECT u.Uploaded, u.Downloaded, u.BonusPoints, COUNT(t.UserID)
385
-      FROM users_main AS u
386
-      LEFT JOIN torrents AS t ON u.ID=t.UserID
387
-      WHERE u.ID = $UserID");
388
-    list($Upload, $Download, $Points, $Uploads) = $DB->next_record();
389
-    $Level = intval(((($Uploads**0.35)*1.5)+1) * max(($Upload+($Points*1000000)-$Download)/(1024**3), 1)); ?>
390
-        <p>This user is wild and level <?=$Level?>
391
-        </p>
392
-        <?php if (!$OwnProfile) { ?>
393
-        <p>Try to capture them with <?=BONUS_POINTS?>? The more you
394
-          spend, the higher the chance of capture</p>
395
-        <form action='store.php' method='post'>
396
-          <input type='hidden' name='item' value='capture_user' />
397
-          <input type='hidden' name='target' value='<?=$UserID?>' />
398
-          <input type='text' name='amount'
399
-            placeholder='<?=BONUS_POINTS?>' /><input type='submit'
400
-            value='Capture' />
401
-        </form>
402
-        <?php }
403
-} ?>
404
-      </div>
405
-    </div>
406 368
     <?php } ?>
407
-    <div class="box box_info box_userinfo_stats">
369
+
370
+<div class="box box_info box_userinfo_stats">
408 371
       <div class="head colhead_dark">Statistics</div>
409 372
       <ul class="stats nobullet">
410 373
         <li>Joined: <?=$JoinedDate?>
@@ -837,17 +800,17 @@ if (check_paranoia_here('snatched')) {
837 800
     if ($RecentSnatches === false) {
838 801
         $DB->query("
839 802
       SELECT
840
-        g.ID,
841
-        g.Name,
842
-        g.Title2,
843
-        g.NameJP,
844
-        g.WikiImage
803
+        g.`id`,
804
+        g.`title`,
805
+        g.`subject`,
806
+        g.`object`,
807
+        g.`picture`
845 808
       FROM xbt_snatched AS s
846 809
         INNER JOIN torrents AS t ON t.ID = s.fid
847
-        INNER JOIN torrents_group AS g ON t.GroupID = g.ID
810
+        INNER JOIN torrents_group AS g ON t.GroupID = g.`id`
848 811
       WHERE s.uid = '$UserID'
849
-        AND g.WikiImage != ''
850
-      GROUP BY g.ID,s.tstamp
812
+        AND g.`picture` != ''
813
+      GROUP BY g.`id`,s.tstamp
851 814
       ORDER BY s.tstamp DESC
852 815
       LIMIT 5");
853 816
         $RecentSnatches = $DB->to_array();
@@ -893,16 +856,16 @@ if (check_paranoia_here('uploads')) {
893 856
     if ($RecentUploads === false) {
894 857
         $DB->query("
895 858
       SELECT
896
-        g.ID,
897
-        g.Name,
898
-        g.Title2,
899
-        g.NameJP,
900
-        g.WikiImage
859
+        g.`id`,
860
+        g.`title`,
861
+        g.`subject`,
862
+        g.`object`,
863
+        g.`picture`
901 864
       FROM torrents_group AS g
902
-        INNER JOIN torrents AS t ON t.GroupID = g.ID
865
+        INNER JOIN torrents AS t ON t.GroupID = g.`id`
903 866
       WHERE t.UserID = '$UserID'
904
-        AND g.WikiImage != ''
905
-      GROUP BY g.ID,t.Time
867
+        AND g.`picture` != ''
868
+      GROUP BY g.`id`,t.Time
906 869
       ORDER BY t.Time DESC
907 870
       LIMIT 5");
908 871
         $RecentUploads = $DB->to_array();
@@ -955,10 +918,10 @@ foreach ($Collages as $CollageInfo) {
955 918
     list($CollageID, $CName) = $CollageInfo;
956 919
     $DB->query("
957 920
     SELECT ct.GroupID,
958
-      tg.WikiImage,
959
-      tg.CategoryID
921
+      tg.`picture`,
922
+      tg.`category_id`
960 923
     FROM collages_torrents AS ct
961
-      JOIN torrents_group AS tg ON tg.ID = ct.GroupID
924
+      JOIN torrents_group AS tg ON tg.`id` = ct.GroupID
962 925
     WHERE ct.CollageID = '$CollageID'
963 926
     ORDER BY ct.Sort
964 927
     LIMIT 5");
@@ -1020,6 +983,7 @@ if ((check_perms('users_view_invites')) && $Invited > 0) {
1020 983
         <?php $Tree->make_tree(); ?>
1021 984
       </div>
1022 985
     </div>
986
+</div>
1023 987
     <?php
1024 988
 }
1025 989
 

+ 145
- 111
sections/userhistory/token_history.php View File

@@ -1,152 +1,186 @@
1 1
 <?php
2
-/************************************************************************
3
-||------------------|| User token history page ||-----------------------||
4
-This page lists the torrents a user has spent his tokens on. It
5
-gets called if $_GET['action'] == 'token_history'.
2
+declare(strict_types=1);
6 3
 
7
-Using $_GET['userid'] allows a mod to see any user's token history.
8
-Nonmods and empty userid show $LoggedUser['ID']'s history
9
-************************************************************************/
4
+/**
5
+ * User token history page
6
+ * This page lists the torrents a user has spent his tokens on.
7
+ * It gets called if $_GET['action'] === 'token_history.'
8
+ *
9
+ * Using $_GET['userid'] allows a mod to see any user's token history.
10
+ * Non-mods and empty userid show $LoggedUser['ID']'s history.
11
+ */
10 12
 
13
+# Validate user ID
11 14
 if (isset($_GET['userid'])) {
12
-  $UserID = $_GET['userid'];
15
+    $UserID = $_GET['userid'];
13 16
 } else {
14
-  $UserID = $LoggedUser['ID'];
15
-}
16
-if (!is_number($UserID)) {
17
-  error(404);
17
+    $UserID = $LoggedUser['ID'];
18 18
 }
19 19
 
20
+Security::checkInt($UserID);
21
+
22
+# Get user info
20 23
 $UserInfo = Users::user_info($UserID);
21 24
 $Perms = Permissions::get_permissions($UserInfo['PermissionID']);
22 25
 $UserClass = $Perms['Class'];
23 26
 
27
+# Validate mod permissions
24 28
 if (!check_perms('users_mod')) {
25
-  if ($LoggedUser['ID'] != $UserID && !check_paranoia(false, $User['Paranoia'], $UserClass, $UserID)) {
26
-    error(403);
27
-  }
29
+    if ($LoggedUser['ID'] !== $UserID && !check_paranoia(false, $User['Paranoia'], $UserClass, $UserID)) {
30
+        error(403);
31
+    }
28 32
 }
29 33
 
30 34
 if (isset($_GET['expire'])) {
31
-  if (!check_perms('users_mod')) {
32
-    error(403);
33
-  }
34
-  $UserID = $_GET['userid'];
35
-  $TorrentID = $_GET['torrentid'];
36
-
37
-  if (!is_number($UserID) || !is_number($TorrentID)) {
38
-    error(403);
39
-  }
40
-  $DB->query("
41
-    SELECT HEX(info_hash)
42
-    FROM torrents
43
-    WHERE ID = $TorrentID");
44
-  if (list($InfoHash) = $DB->next_record(MYSQLI_NUM, FALSE)) {
35
+    if (!check_perms('users_mod')) {
36
+        error(403);
37
+    }
38
+
39
+    $UserID = $_GET['userid'];
40
+    $TorrentID = $_GET['torrentid'];
41
+
42
+    if (!is_number($UserID) || !is_number($TorrentID)) {
43
+        error(403);
44
+    }
45
+
45 46
     $DB->query("
46
-      UPDATE users_freeleeches
47
-      SET Expired = TRUE
48
-      WHERE UserID = $UserID
49
-        AND TorrentID = $TorrentID");
50
-    $Cache->delete_value("users_tokens_$UserID");
51
-    Tracker::update_tracker('remove_token', ['info_hash' => substr('%'.chunk_split($InfoHash,2,'%'),0,-1), 'userid' => $UserID]);
52
-  }
53
-  header("Location: userhistory.php?action=token_history&userid=$UserID");
47
+    SELECT
48
+      HEX(`info_hash`)
49
+    FROM
50
+      `torrents`
51
+    WHERE
52
+      `ID` = '$TorrentID'
53
+    ");
54
+
55
+    if (list($InfoHash) = $DB->next_record(MYSQLI_NUM, false)) {
56
+        $DB->query("
57
+        UPDATE
58
+          `users_freeleeches`
59
+        SET
60
+          `Expired` = TRUE
61
+        WHERE
62
+          `UserID` = '$UserID' AND `TorrentID` = '$TorrentID'
63
+        ");
64
+
65
+        $Cache->delete_value("users_tokens_$UserID");
66
+        Tracker::update_tracker(
67
+            'remove_token',
68
+            ['info_hash' => substr('%'.chunk_split($InfoHash, 2, '%'), 0, -1), 'userid' => $UserID]
69
+        );
70
+    }
71
+    header("Location: userhistory.php?action=token_history&userid=$UserID");
54 72
 }
55 73
 
74
+# Render HTML
56 75
 View::show_header('Freeleech token history');
57
-
58 76
 list($Page, $Limit) = Format::page_limit(25);
59 77
 
60
-/*
61
-$DB->query("
62
-  SELECT
63
-    SQL_CALC_FOUND_ROWS
64
-    f.TorrentID,
65
-    t.GroupID,
66
-    f.Time,
67
-    f.Expired,
68
-    f.Downloaded,
69
-    f.Uses,
70
-    g.Name,
71
-    t.Format,
72
-    t.Encoding
73
-  FROM users_freeleeches AS f
74
-    JOIN torrents AS t ON t.ID = f.TorrentID
75
-    JOIN torrents_group AS g ON g.ID = t.GroupID
76
-  WHERE f.UserID = $UserID
77
-  ORDER BY f.Time DESC
78
-  LIMIT $Limit");
79
-*/
80 78
 $DB->query("
81
-  SELECT
82
-    SQL_CALC_FOUND_ROWS
83
-    f.TorrentID,
84
-    t.GroupID,
85
-    f.Time,
86
-    f.Expired,
87
-    f.Downloaded,
88
-    f.Uses,
89
-    g.Name
90
-  FROM users_freeleeches AS f
91
-    JOIN torrents AS t ON t.ID = f.TorrentID
92
-    JOIN torrents_group AS g ON g.ID = t.GroupID
93
-  WHERE f.UserID = $UserID
94
-  ORDER BY f.Time DESC
95
-  LIMIT $Limit");
96
-$Tokens = $DB->to_array();
79
+SELECT SQL_CALC_FOUND_ROWS
80
+  f.`TorrentID`,
81
+  t.`GroupID`,
82
+  f.`Time`,
83
+  f.`Expired`,
84
+  f.`Downloaded`,
85
+  f.`Uses`,
86
+  g.`title`
87
+FROM
88
+  `users_freeleeches` AS f
89
+JOIN `torrents` AS t
90
+ON
91
+  t.`ID` = f.`TorrentID`
92
+JOIN `torrents_group` AS g
93
+ON
94
+  g.`id` = t.`GroupID`
95
+WHERE
96
+  f.`UserID` = '$UserID'
97
+ORDER BY
98
+  f.`Time`
99
+DESC
100
+LIMIT $Limit
101
+");
97 102
 
103
+$Tokens = $DB->to_array();
98 104
 $DB->query('SELECT FOUND_ROWS()');
99 105
 list($NumResults) = $DB->next_record();
100 106
 $Pages = Format::get_pages($Page, $NumResults, 25);
101
-
102 107
 ?>
108
+
103 109
 <div class="header">
104
-  <h2>Freeleech token history for <?=Users::format_username($UserID, false, false, false)?></h2>
110
+  <h2>
111
+    Freeleech token history for
112
+    <?= Users::format_username($UserID, false, false, false) ?>
113
+  </h2>
105 114
 </div>
106
-<div class="linkbox"><?=$Pages?></div>
115
+
116
+<div class="linkbox">
117
+  <?= $Pages ?>
118
+</div>
119
+
107 120
 <table>
108 121
   <tr class="colhead_dark">
109
-    <td>Torrent</td>
110
-    <td>Time</td>
111
-    <td>Expired</td>
112
-<? if (check_perms('users_mod')) { ?>
113
-    <td>Downloaded</td>
114
-    <td>Tokens used</td>
115
-<? } ?>
122
+    <th>Torrent</th>
123
+    <th>Time</th>
124
+    <th>Expired</th>
125
+
126
+    <?php if (check_perms('users_mod')) { ?>
127
+    <th>Downloaded</th>
128
+    <th>Tokens used</th>
129
+    <?php } ?>
116 130
   </tr>
117
-<?
131
+
132
+  <?php
118 133
 foreach ($Tokens as $Token) {
119
-  $GroupIDs[] = $Token['GroupID'];
134
+    $GroupIDs[] = $Token['GroupID'];
120 135
 }
121 136
 $Artists = Artists::get_artists($GroupIDs);
122 137
 
123 138
 foreach ($Tokens as $Token) {
124
-  list($TorrentID, $GroupID, $Time, $Expired, $Downloaded, $Uses, $Name) = $Token;
125
-  if ($Name != '') {
126
-    $Name = "<a href=\"torrents.php?torrentid=$TorrentID\">$Name</a>";
127
-  } else {
128
-    $Name = "(<i>Deleted torrent <a href=\"log.php?search=Torrent+$TorrentID\">$TorrentID</a></i>)";
129
-  }
130
-  $ArtistName = Artists::display_artists($Artists[$GroupID]);
131
-  if ($ArtistName) {
132
-    $Name = $ArtistName.$Name;
133
-  }
134
-?>
139
+    list($TorrentID, $GroupID, $Time, $Expired, $Downloaded, $Uses, $Name) = $Token;
140
+
141
+    if ($Name !== '') {
142
+        $Name = "<a href='torrents.php?torrentid=$TorrentID'>$Name</a>";
143
+    } else {
144
+        $Name = "(<i>Deleted torrent <a href='log.php?search=Torrent+$TorrentID'>$TorrentID</a></i>)";
145
+    }
146
+
147
+    $ArtistName = Artists::display_artists($Artists[$GroupID]);
148
+    if ($ArtistName) {
149
+        $Name = $ArtistName.$Name;
150
+    } ?>
151
+
135 152
   <tr class="row">
136
-    <td><?=$Name?></td>
137
-    <td><?=time_diff($Time)?></td>
138
-    <td><?=($Expired ? 'Yes' : 'No')?><?=(check_perms('users_mod') && !$Expired) ? " <a href=\"userhistory.php?action=token_history&amp;expire=1&amp;userid=$UserID&amp;torrentid=$TorrentID\">(expire)</a>" : ''; ?>
153
+    <td>
154
+      <?= $Name ?>
155
+    </td>
156
+
157
+    <td>
158
+      <?= time_diff($Time) ?>
159
+    </td>
160
+
161
+    <td>
162
+      <?= ($Expired ? 'Yes' : 'No') ?>
163
+      <?= (check_perms('users_mod') && !$Expired)
164
+        ? " <a href='userhistory.php?action=token_history&amp;expire=1&amp;userid=$UserID&amp;torrentid=$TorrentID'>(expire)</a>"
165
+        : ''; ?>
166
+    </td>
167
+
168
+    <?php if (check_perms('users_mod')) { ?>
169
+    <td>
170
+      <?= Format::get_size($Downloaded) ?>
171
+    </td>
172
+
173
+    <td>
174
+      <?= $Uses ?>
139 175
     </td>
140
-<?php if (check_perms('users_mod')) { ?>
141
-    <td><?=Format::get_size($Downloaded)?></td>
142
-    <td><?=$Uses?></td>
143
-<?php } ?>
176
+    <?php } ?>
144 177
   </tr>
145
-<?
146
-}
147
-?>
178
+  <?php
179
+} ?>
148 180
 </table>
149
-<div class="linkbox"><?=$Pages?></div>
150
-<?
151
-View::show_footer();
152
-?>
181
+
182
+<div class="linkbox">
183
+  <?= $Pages ?>
184
+</div>
185
+
186
+<?php View::show_footer();

+ 0
- 4
signup.php View File

@@ -1,4 +0,0 @@
1
-<?php
2
-declare(strict_types=1);
3
-
4
-header('Location: register.php');

+ 0
- 0
sphinx.conf View File


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

Loading…
Cancel
Save