Browse Source

Retab project

spaghetti 5 years ago
parent
commit
52b2b2e219
100 changed files with 19551 additions and 19551 deletions
  1. 3
    3
      classes/NMA_API.php
  2. 203
    203
      classes/artists.class.php
  3. 374
    374
      classes/artists_similar.class.php
  4. 136
    136
      classes/badges.class.php
  5. 76
    76
      classes/bencode.class.php
  6. 167
    167
      classes/bencodedecode.class.php
  7. 130
    130
      classes/bencodetorrent.class.php
  8. 26
    26
      classes/bitcoinrpc.class.php
  9. 91
    91
      classes/bookmarks.class.php
  10. 363
    363
      classes/cache.class.php
  11. 125
    125
      classes/calendar.class.php
  12. 90
    90
      classes/calendarview.class.php
  13. 177
    177
      classes/charts.class.php
  14. 27
    27
      classes/classloader.php
  15. 42
    42
      classes/collages.class.php
  16. 438
    438
      classes/comments.class.php
  17. 83
    83
      classes/commentsview.class.php
  18. 29
    29
      classes/cookie.class.php
  19. 20
    20
      classes/dbcrypt.class.php
  20. 617
    617
      classes/debug.class.php
  21. 773
    773
      classes/donations.class.php
  22. 176
    176
      classes/donationsbitcoin.class.php
  23. 192
    192
      classes/donationsview.class.php
  24. 18
    18
      classes/encrypt.class.php
  25. 63
    63
      classes/feed.class.php
  26. 52
    52
      classes/file_checker.class.php
  27. 577
    577
      classes/format.class.php
  28. 309
    309
      classes/forums.class.php
  29. 9
    9
      classes/g.class.php
  30. 49
    49
      classes/image.class.php
  31. 233
    233
      classes/imagetools.class.php
  32. 24
    24
      classes/inbox.class.php
  33. 213
    213
      classes/invite_tree.class.php
  34. 176
    176
      classes/irc.class.php
  35. 1
    1
      classes/lockedaccounts.class.php
  36. 64
    64
      classes/mass_user_bookmarks_editor.class.php
  37. 38
    38
      classes/mass_user_torrents_editor.class.php
  38. 234
    234
      classes/mass_user_torrents_table_view.class.php
  39. 1
    1
      classes/mediainfo.class.php
  40. 530
    530
      classes/misc.class.php
  41. 322
    322
      classes/mysql.class.php
  42. 792
    792
      classes/notificationsmanager.class.php
  43. 140
    140
      classes/notificationsmanagerview.class.php
  44. 54
    54
      classes/paranoia.class.php
  45. 80
    80
      classes/permissions.class.php
  46. 254
    254
      classes/permissions_form.php
  47. 33
    33
      classes/proxies.class.php
  48. 173
    173
      classes/pushserver.class.php
  49. 24
    24
      classes/reports.class.php
  50. 231
    231
      classes/requests.class.php
  51. 26
    26
      classes/revisionhistory.class.php
  52. 32
    32
      classes/revisionhistoryview.class.php
  53. 150
    150
      classes/rules.class.php
  54. 235
    235
      classes/script_start.php
  55. 250
    250
      classes/sitehistory.class.php
  56. 194
    194
      classes/sitehistoryview.class.php
  57. 133
    133
      classes/sphinxql.class.php
  58. 352
    352
      classes/sphinxqlquery.class.php
  59. 132
    132
      classes/sphinxqlresult.class.php
  60. 381
    381
      classes/subscriptions.class.php
  61. 194
    194
      classes/tags.class.php
  62. 62
    62
      classes/templates.class.php
  63. 145
    145
      classes/testing.class.php
  64. 159
    159
      classes/testingview.class.php
  65. 999
    999
      classes/text.class.php
  66. 179
    179
      classes/textarea_preview.class.php
  67. 269
    269
      classes/tools.class.php
  68. 65
    65
      classes/top10view.class.php
  69. 272
    272
      classes/torrent.class.php
  70. 253
    253
      classes/torrent_32bit.class.php
  71. 967
    967
      classes/torrent_form.class.php
  72. 1234
    1234
      classes/torrents.class.php
  73. 225
    225
      classes/torrentsdl.class.php
  74. 642
    642
      classes/torrentsearch.class.php
  75. 162
    162
      classes/tracker.class.php
  76. 152
    152
      classes/useragent.class.php
  77. 156
    156
      classes/userrank.class.php
  78. 692
    692
      classes/users.class.php
  79. 103
    103
      classes/util.php
  80. 289
    289
      classes/validate.class.php
  81. 120
    120
      classes/view.class.php
  82. 310
    310
      classes/votes.class.php
  83. 92
    92
      classes/wiki.class.php
  84. 109
    109
      classes/zip.class.php
  85. 38
    38
      design/privatefooter.php
  86. 1
    1
      design/publicfooter.php
  87. 10
    10
      design/publicheader.php
  88. 117
    117
      design/views/generic/reply/quickreply.php
  89. 1
    1
      design/views/generic/textarea/buttons.phtml
  90. 1
    1
      design/views/generic/textarea/preview.phtml
  91. 1
    1
      design/views/generic/textarea/script_factory.phtml
  92. 1
    1
      design/views/generic/textarea/textarea.phtml
  93. 64
    64
      feeds.php
  94. 73
    73
      image.php
  95. 29
    29
      sections/ajax/anidb.php
  96. 61
    61
      sections/ajax/announcements.php
  97. 297
    297
      sections/ajax/artist.php
  98. 30
    30
      sections/ajax/better/index.php
  99. 40
    40
      sections/ajax/better/single.php
  100. 0
    0
      sections/ajax/better/transcode.php

+ 3
- 3
classes/NMA_API.php View File

@@ -119,9 +119,9 @@ class NMA_API
119 119
                       'description' => substr($description, 0, 10000),
120 120
                       'priority'    => $priority
121 121
         );
122
-		if (!empty($url)) {
123
-			$post['url'] = substr($url, 0, 2000);
124
-		}
122
+    if (!empty($url)) {
123
+      $post['url'] = substr($url, 0, 2000);
124
+    }
125 125
         if ($this->devKey) {
126 126
             $post['developerkey'] = $this->devKey;
127 127
         }

+ 203
- 203
classes/artists.class.php View File

@@ -1,209 +1,209 @@
1 1
 <?
2 2
 class Artists {
3
-	/**
4
-	 * Given an array of GroupIDs, return their associated artists.
5
-	 *
6
-	 * @param array $GroupIDs
7
-	 * @return an array of the following form:
8
-	 * 	GroupID => {
9
-	 *		[ArtistType] => {
10
-	 *			id, name, aliasid
11
-	 *		}
12
-	 *	}
13
-	 * ArtistType is an int. It can be:
14
-	 * 1 => Main artist
15
-	 * 2 => Guest artist
16
-	 * 4 => Composer
17
-	 * 5 => Conductor
18
-	 * 6 => DJ
19
-	 */
20
-	public static function get_artists($GroupIDs) {
21
-		$Results = array();
22
-		$DBs = array();
23
-		foreach ($GroupIDs as $GroupID) {
24
-			if (!is_number($GroupID)) {
25
-				continue;
26
-			}
27
-			$Artists = G::$Cache->get_value('groups_artists_'.$GroupID);
28
-			if (is_array($Artists)) {
29
-				$Results[$GroupID] = $Artists;
30
-			} else {
31
-				$DBs[] = $GroupID;
32
-			}
33
-		}
34
-		if (count($DBs) > 0) {
35
-			$IDs = implode(',', $DBs);
36
-			if (empty($IDs)) {
37
-				$IDs = "null";
38
-			}
39
-			$QueryID = G::$DB->get_query_id();
40
-			G::$DB->query("
41
-				SELECT ta.GroupID,
42
-					ta.ArtistID,
43
-					ag.Name
44
-				FROM torrents_artists AS ta
45
-					JOIN artists_group AS ag ON ta.ArtistID = ag.ArtistID
46
-				WHERE ta.GroupID IN ($IDs)
47
-				ORDER BY ta.GroupID ASC,
48
-					ag.Name ASC;");
49
-			while (list($GroupID, $ArtistID, $ArtistName) = G::$DB->next_record(MYSQLI_BOTH, false)) {
50
-				$Results[$GroupID][] = array('id' => $ArtistID, 'name' => $ArtistName);
51
-				$New[$GroupID][] = array('id' => $ArtistID, 'name' => $ArtistName);
52
-			}
53
-			G::$DB->set_query_id($QueryID);
54
-			foreach ($DBs as $GroupID) {
55
-				if (isset($New[$GroupID])) {
56
-					G::$Cache->cache_value('groups_artists_'.$GroupID, $New[$GroupID]);
57
-				}
58
-				else {
59
-					G::$Cache->cache_value('groups_artists_'.$GroupID, array());
60
-				}
61
-			}
62
-			$Missing = array_diff($GroupIDs, array_keys($Results));
63
-			if (!empty($Missing)) {
64
-				$Results += array_fill_keys($Missing, array());
65
-			}
66
-		}
67
-		return $Results;
68
-	}
69
-
70
-
71
-	/**
72
-	 * Convenience function for get_artists, when you just need one group.
73
-	 *
74
-	 * @param int $GroupID
75
-	 * @return array - see get_artists
76
-	 */
77
-	public static function get_artist($GroupID) {
78
-		$Results = Artists::get_artists(array($GroupID));
79
-		return $Results[$GroupID];
80
-	}
81
-
82
-
83
-	/**
84
-	 * Format an array of artists for display.
85
-	 * TODO: Revisit the logic of this, see if we can helper-function the copypasta.
86
-	 *
87
-	 * @param array Artists an array of the form output by get_artists
88
-	 * @param boolean $MakeLink if true, the artists will be links, if false, they will be text.
89
-	 * @param boolean $IncludeHyphen if true, appends " - " to the end.
90
-	 * @param $Escape if true, output will be escaped. Think carefully before setting it false.
91
-	 */
92
-	public static function display_artists($Artists, $MakeLink = true, $IncludeHyphen = true, $Escape = true) {
93
-		if (!empty($Artists)) {
94
-			$ampersand = ($Escape) ? ' &amp; ' : ' & ';
95
-			$link = '';
96
-			
97
-			switch(count($Artists)) {
98
-				case 0:
99
-					break;
100
-				case 3:
101
-					$link .= Artists::display_artist($Artists[2], $MakeLink, $Escape). ", ";
102
-				case 2:
103
-					$link .= Artists::display_artist($Artists[1], $MakeLink, $Escape). ", ";
104
-				case 1:
105
-					$link .= Artists::display_artist($Artists[0], $MakeLink, $Escape).($IncludeHyphen?' – ':'');
106
-					break;
107
-				default:
108
-					$link = "Various".($IncludeHyphen?' – ':'');		
3
+  /**
4
+   * Given an array of GroupIDs, return their associated artists.
5
+   *
6
+   * @param array $GroupIDs
7
+   * @return an array of the following form:
8
+   *   GroupID => {
9
+   *    [ArtistType] => {
10
+   *      id, name, aliasid
11
+   *    }
12
+   *  }
13
+   * ArtistType is an int. It can be:
14
+   * 1 => Main artist
15
+   * 2 => Guest artist
16
+   * 4 => Composer
17
+   * 5 => Conductor
18
+   * 6 => DJ
19
+   */
20
+  public static function get_artists($GroupIDs) {
21
+    $Results = array();
22
+    $DBs = array();
23
+    foreach ($GroupIDs as $GroupID) {
24
+      if (!is_number($GroupID)) {
25
+        continue;
26
+      }
27
+      $Artists = G::$Cache->get_value('groups_artists_'.$GroupID);
28
+      if (is_array($Artists)) {
29
+        $Results[$GroupID] = $Artists;
30
+      } else {
31
+        $DBs[] = $GroupID;
32
+      }
33
+    }
34
+    if (count($DBs) > 0) {
35
+      $IDs = implode(',', $DBs);
36
+      if (empty($IDs)) {
37
+        $IDs = "null";
38
+      }
39
+      $QueryID = G::$DB->get_query_id();
40
+      G::$DB->query("
41
+        SELECT ta.GroupID,
42
+          ta.ArtistID,
43
+          ag.Name
44
+        FROM torrents_artists AS ta
45
+          JOIN artists_group AS ag ON ta.ArtistID = ag.ArtistID
46
+        WHERE ta.GroupID IN ($IDs)
47
+        ORDER BY ta.GroupID ASC,
48
+          ag.Name ASC;");
49
+      while (list($GroupID, $ArtistID, $ArtistName) = G::$DB->next_record(MYSQLI_BOTH, false)) {
50
+        $Results[$GroupID][] = array('id' => $ArtistID, 'name' => $ArtistName);
51
+        $New[$GroupID][] = array('id' => $ArtistID, 'name' => $ArtistName);
52
+      }
53
+      G::$DB->set_query_id($QueryID);
54
+      foreach ($DBs as $GroupID) {
55
+        if (isset($New[$GroupID])) {
56
+          G::$Cache->cache_value('groups_artists_'.$GroupID, $New[$GroupID]);
57
+        }
58
+        else {
59
+          G::$Cache->cache_value('groups_artists_'.$GroupID, array());
60
+        }
61
+      }
62
+      $Missing = array_diff($GroupIDs, array_keys($Results));
63
+      if (!empty($Missing)) {
64
+        $Results += array_fill_keys($Missing, array());
65
+      }
66
+    }
67
+    return $Results;
68
+  }
69
+
70
+
71
+  /**
72
+   * Convenience function for get_artists, when you just need one group.
73
+   *
74
+   * @param int $GroupID
75
+   * @return array - see get_artists
76
+   */
77
+  public static function get_artist($GroupID) {
78
+    $Results = Artists::get_artists(array($GroupID));
79
+    return $Results[$GroupID];
80
+  }
81
+
82
+
83
+  /**
84
+   * Format an array of artists for display.
85
+   * TODO: Revisit the logic of this, see if we can helper-function the copypasta.
86
+   *
87
+   * @param array Artists an array of the form output by get_artists
88
+   * @param boolean $MakeLink if true, the artists will be links, if false, they will be text.
89
+   * @param boolean $IncludeHyphen if true, appends " - " to the end.
90
+   * @param $Escape if true, output will be escaped. Think carefully before setting it false.
91
+   */
92
+  public static function display_artists($Artists, $MakeLink = true, $IncludeHyphen = true, $Escape = true) {
93
+    if (!empty($Artists)) {
94
+      $ampersand = ($Escape) ? ' &amp; ' : ' & ';
95
+      $link = '';
96
+
97
+      switch(count($Artists)) {
98
+        case 0:
99
+          break;
100
+        case 3:
101
+          $link .= Artists::display_artist($Artists[2], $MakeLink, $Escape). ", ";
102
+        case 2:
103
+          $link .= Artists::display_artist($Artists[1], $MakeLink, $Escape). ", ";
104
+        case 1:
105
+          $link .= Artists::display_artist($Artists[0], $MakeLink, $Escape).($IncludeHyphen?' – ':'');
106
+          break;
107
+        default:
108
+          $link = "Various".($IncludeHyphen?' – ':'');
109 109
       }
110 110
 
111
-			return $link;
112
-		} else {
113
-			return '';
114
-		}
115
-	}
116
-
117
-
118
-	/**
119
-	 * Formats a single artist name.
120
-	 *
121
-	 * @param array $Artist an array of the form ('id'=>ID, 'name'=>Name)
122
-	 * @param boolean $MakeLink If true, links to the artist page.
123
-	 * @param boolean $Escape If false and $MakeLink is false, returns the unescaped, unadorned artist name.
124
-	 * @return string Formatted artist name.
125
-	 */
126
-	public static function display_artist($Artist, $MakeLink = true, $Escape = true) {
127
-		if ($MakeLink && !$Escape) {
128
-			error('Invalid parameters to Artists::display_artist()');
129
-		} elseif ($MakeLink) {
130
-			return '<a href="artist.php?id='.$Artist['id'].'" dir="ltr">'.display_str($Artist['name']).'</a>';
131
-		} elseif ($Escape) {
132
-			return display_str($Artist['name']);
133
-		} else {
134
-			return $Artist['name'];
135
-		}
136
-	}
137
-
138
-	/**
139
-	 * Deletes an artist and their requests, wiki, and tags.
140
-	 * Does NOT delete their torrents.
141
-	 *
142
-	 * @param int $ArtistID
143
-	 */
144
-	public static function delete_artist($ArtistID) {
145
-		$QueryID = G::$DB->get_query_id();
146
-		G::$DB->query("
147
-			SELECT Name
148
-			FROM artists_group
149
-			WHERE ArtistID = ".$ArtistID);
150
-		list($Name) = G::$DB->next_record(MYSQLI_NUM, false);
151
-
152
-		// Delete requests
153
-		G::$DB->query("
154
-			SELECT RequestID
155
-			FROM requests_artists
156
-			WHERE ArtistID = $ArtistID
157
-				AND ArtistID != 0");
158
-		$Requests = G::$DB->to_array();
159
-		foreach ($Requests AS $Request) {
160
-			list($RequestID) = $Request;
161
-			G::$DB->query('DELETE FROM requests WHERE ID='.$RequestID);
162
-			G::$DB->query('DELETE FROM requests_votes WHERE RequestID='.$RequestID);
163
-			G::$DB->query('DELETE FROM requests_tags WHERE RequestID='.$RequestID);
164
-			G::$DB->query('DELETE FROM requests_artists WHERE RequestID='.$RequestID);
165
-		}
166
-
167
-		// Delete artist
168
-		G::$DB->query('DELETE FROM artists_group WHERE ArtistID='.$ArtistID);
169
-		G::$Cache->decrement('stats_artist_count');
170
-
171
-		// Delete wiki revisions
172
-		G::$DB->query('DELETE FROM wiki_artists WHERE PageID='.$ArtistID);
173
-
174
-		// Delete tags
175
-		G::$DB->query('DELETE FROM artists_tags WHERE ArtistID='.$ArtistID);
176
-
177
-		// Delete artist comments, subscriptions and quote notifications
178
-		Comments::delete_page('artist', $ArtistID);
179
-
180
-		G::$Cache->delete_value('artist_'.$ArtistID);
181
-		G::$Cache->delete_value('artist_groups_'.$ArtistID);
182
-		// Record in log
183
-
184
-		if (!empty(G::$LoggedUser['Username'])) {
185
-			$Username = G::$LoggedUser['Username'];
186
-		} else {
187
-			$Username = 'System';
188
-		}
189
-		Misc::write_log("Artist $ArtistID ($Name) was deleted by $Username");
190
-		G::$DB->set_query_id($QueryID);
191
-	}
192
-
193
-
194
-	/**
195
-	 * Remove LRM (left-right-marker) and trims, because people copypaste carelessly.
196
-	 * If we don't do this, we get seemingly duplicate artist names.
197
-	 * TODO: make stricter, e.g. on all whitespace characters or Unicode normalisation
198
-	 *
199
-	 * @param string $ArtistName
200
-	 */
201
-	public static function normalise_artist_name($ArtistName) {
202
-		// \u200e is &lrm;
203
-		$ArtistName = trim($ArtistName);
204
-		$ArtistName = preg_replace('/^(\xE2\x80\x8E)+/', '', $ArtistName);
205
-		$ArtistName = preg_replace('/(\xE2\x80\x8E)+$/', '', $ArtistName);
206
-		return trim(preg_replace('/ +/', ' ', $ArtistName));
207
-	}
111
+      return $link;
112
+    } else {
113
+      return '';
114
+    }
115
+  }
116
+
117
+
118
+  /**
119
+   * Formats a single artist name.
120
+   *
121
+   * @param array $Artist an array of the form ('id'=>ID, 'name'=>Name)
122
+   * @param boolean $MakeLink If true, links to the artist page.
123
+   * @param boolean $Escape If false and $MakeLink is false, returns the unescaped, unadorned artist name.
124
+   * @return string Formatted artist name.
125
+   */
126
+  public static function display_artist($Artist, $MakeLink = true, $Escape = true) {
127
+    if ($MakeLink && !$Escape) {
128
+      error('Invalid parameters to Artists::display_artist()');
129
+    } elseif ($MakeLink) {
130
+      return '<a href="artist.php?id='.$Artist['id'].'" dir="ltr">'.display_str($Artist['name']).'</a>';
131
+    } elseif ($Escape) {
132
+      return display_str($Artist['name']);
133
+    } else {
134
+      return $Artist['name'];
135
+    }
136
+  }
137
+
138
+  /**
139
+   * Deletes an artist and their requests, wiki, and tags.
140
+   * Does NOT delete their torrents.
141
+   *
142
+   * @param int $ArtistID
143
+   */
144
+  public static function delete_artist($ArtistID) {
145
+    $QueryID = G::$DB->get_query_id();
146
+    G::$DB->query("
147
+      SELECT Name
148
+      FROM artists_group
149
+      WHERE ArtistID = ".$ArtistID);
150
+    list($Name) = G::$DB->next_record(MYSQLI_NUM, false);
151
+
152
+    // Delete requests
153
+    G::$DB->query("
154
+      SELECT RequestID
155
+      FROM requests_artists
156
+      WHERE ArtistID = $ArtistID
157
+        AND ArtistID != 0");
158
+    $Requests = G::$DB->to_array();
159
+    foreach ($Requests AS $Request) {
160
+      list($RequestID) = $Request;
161
+      G::$DB->query('DELETE FROM requests WHERE ID='.$RequestID);
162
+      G::$DB->query('DELETE FROM requests_votes WHERE RequestID='.$RequestID);
163
+      G::$DB->query('DELETE FROM requests_tags WHERE RequestID='.$RequestID);
164
+      G::$DB->query('DELETE FROM requests_artists WHERE RequestID='.$RequestID);
165
+    }
166
+
167
+    // Delete artist
168
+    G::$DB->query('DELETE FROM artists_group WHERE ArtistID='.$ArtistID);
169
+    G::$Cache->decrement('stats_artist_count');
170
+
171
+    // Delete wiki revisions
172
+    G::$DB->query('DELETE FROM wiki_artists WHERE PageID='.$ArtistID);
173
+
174
+    // Delete tags
175
+    G::$DB->query('DELETE FROM artists_tags WHERE ArtistID='.$ArtistID);
176
+
177
+    // Delete artist comments, subscriptions and quote notifications
178
+    Comments::delete_page('artist', $ArtistID);
179
+
180
+    G::$Cache->delete_value('artist_'.$ArtistID);
181
+    G::$Cache->delete_value('artist_groups_'.$ArtistID);
182
+    // Record in log
183
+
184
+    if (!empty(G::$LoggedUser['Username'])) {
185
+      $Username = G::$LoggedUser['Username'];
186
+    } else {
187
+      $Username = 'System';
188
+    }
189
+    Misc::write_log("Artist $ArtistID ($Name) was deleted by $Username");
190
+    G::$DB->set_query_id($QueryID);
191
+  }
192
+
193
+
194
+  /**
195
+   * Remove LRM (left-right-marker) and trims, because people copypaste carelessly.
196
+   * If we don't do this, we get seemingly duplicate artist names.
197
+   * TODO: make stricter, e.g. on all whitespace characters or Unicode normalisation
198
+   *
199
+   * @param string $ArtistName
200
+   */
201
+  public static function normalise_artist_name($ArtistName) {
202
+    // \u200e is &lrm;
203
+    $ArtistName = trim($ArtistName);
204
+    $ArtistName = preg_replace('/^(\xE2\x80\x8E)+/', '', $ArtistName);
205
+    $ArtistName = preg_replace('/(\xE2\x80\x8E)+$/', '', $ArtistName);
206
+    return trim(preg_replace('/ +/', ' ', $ArtistName));
207
+  }
208 208
 }
209 209
 ?>

+ 374
- 374
classes/artists_similar.class.php View File

@@ -1,385 +1,385 @@
1 1
 <?
2 2
 class ARTIST {
3
-	var $ID = 0;
4
-	var $Name = 0;
5
-	var $NameLength = 0;
6
-	var $SimilarID = 0;
7
-	var $Displayed = false;
8
-	var $x = 0;
9
-	var $y = 0;
10
-	var $Similar = array();
11
-
12
-	function ARTIST($ID = '', $Name = '') {
13
-		$this->ID = $ID;
14
-		$this->NameLength = mb_strlen($Name, 'utf8');
15
-		$this->Name = display_str($Name);
16
-	}
3
+  var $ID = 0;
4
+  var $Name = 0;
5
+  var $NameLength = 0;
6
+  var $SimilarID = 0;
7
+  var $Displayed = false;
8
+  var $x = 0;
9
+  var $y = 0;
10
+  var $Similar = array();
11
+
12
+  function ARTIST($ID = '', $Name = '') {
13
+    $this->ID = $ID;
14
+    $this->NameLength = mb_strlen($Name, 'utf8');
15
+    $this->Name = display_str($Name);
16
+  }
17 17
 }
18 18
 
19 19
 class ARTISTS_SIMILAR extends ARTIST{
20
-	var $Artists = array();
21
-	var $TotalScore = 0;
22
-
23
-	var $xValues = array(WIDTH=>1);
24
-	var $yValues = array(HEIGHT=>1);
25
-
26
-	var $LargestDecimal = 0;
27
-	var $LowestDecimal = 1;
28
-
29
-
30
-
31
-	function dump_data() {
32
-		return serialize(array(time(), $this->Name, $this->x, $this->y, serialize($this->Artists), serialize($this->Similar)));
33
-	}
34
-
35
-	function load_data($Data) {
36
-		list($LastUpdated, $this->Name, $this->x, $this->y, $this->Artists, $this->Similar) = unserialize($Data);
37
-		$this->Artists = unserialize($this->Artists);
38
-		$this->Similar = unserialize($this->Similar);
39
-	}
40
-
41
-	function set_up() {
42
-		$QueryID = G::$DB->get_query_id();
43
-
44
-		$this->x = ceil(WIDTH / 2);
45
-		$this->y = ceil(HEIGHT / 2);
46
-
47
-		$this->xValues[$this->x] = $this->ID;
48
-		$this->yValues[$this->y] = $this->ID;
49
-
50
-
51
-		// Get artists that are directly similar to the artist
52
-		$ArtistIDs = array();
53
-		G::$DB->query("
54
-			SELECT
55
-				s2.ArtistID,
56
-				ag.Name,
57
-				ass.Score
58
-			FROM artists_similar AS s1
59
-				JOIN artists_similar AS s2 ON s1.SimilarID=s2.SimilarID AND s1.ArtistID!=s2.ArtistID
60
-				JOIN artists_similar_scores AS ass ON ass.SimilarID=s1.SimilarID
61
-				JOIN artists_group AS ag ON ag.ArtistID=s2.ArtistID
62
-			WHERE s1.ArtistID=".$this->ID."
63
-			ORDER BY ass.Score DESC
64
-			LIMIT 14");
65
-
66
-		if (!G::$DB->has_results()) {
67
-			return;
68
-		}
69
-
70
-		// Build into array. Each artist is its own object in $this->Artists
71
-		while (list($ArtistID, $Name, $Score) = G::$DB->next_record(MYSQLI_NUM, false)) {
72
-			if ($Score < 0) {
73
-				continue;
74
-			}
75
-			$this->Artists[$ArtistID] = new ARTIST($ArtistID, $Name);
76
-			$this->Similar[$ArtistID] = array('ID' => $ArtistID, 'Score' => $Score);
77
-			$this->TotalScore += $Score;
78
-			$ArtistIDs[] = $ArtistID;
79
-		}
80
-
81
-		// Get similarities between artists on the map
82
-		G::$DB->query("
83
-			SELECT
84
-				s1.ArtistID,
85
-				s2.ArtistID
86
-			FROM artists_similar AS s1
87
-				JOIN artists_similar AS s2 ON s1.SimilarID=s2.SimilarID AND s1.ArtistID!=s2.ArtistID
88
-				JOIN artists_similar_scores AS ass ON ass.SimilarID=s1.SimilarID
89
-				JOIN artists_group AS a ON a.ArtistID=s2.ArtistID
90
-			WHERE s1.ArtistID IN(".implode(',', $ArtistIDs).')
91
-				AND s2.ArtistID IN('.implode(',', $ArtistIDs).')');
92
-
93
-		// Build into array
94
-		while (list($Artist1ID, $Artist2ID) = G::$DB->next_record()) {
95
-			$this->Artists[$Artist1ID]->Similar[$Artist2ID] = array('ID'=>$Artist2ID);
96
-		}
97
-
98
-		// Calculate decimal point scores between artists
99
-		foreach ($this->Similar as $SimilarArtist) {
100
-			list($ArtistID, $Similar) = array_values($SimilarArtist);
101
-			$this->Similar[$ArtistID]['Decimal'] =  $this->similarity($Similar['Score'], $this->TotalScore);
102
-
103
-			if ($this->Similar[$ArtistID]['Decimal'] < $this->LowestDecimal) {
104
-				$this->LowestDecimal = $this->Similar[$ArtistID]['Decimal'];
105
-			}
106
-			if ($this->Similar[$ArtistID]['Decimal'] > $this->LargestDecimal) {
107
-				$this->LargestDecimal = $this->Similar[$ArtistID]['Decimal'];
108
-			}
109
-		}
110
-		reset($this->Artists);
111
-
112
-		G::$DB->set_query_id($QueryID);
113
-	}
114
-
115
-	function set_positions() {
116
-		$xValues = array(); // Possible x values
117
-		$Root = ceil(WIDTH / 4); // Half-way into half of the image
118
-		$Offset = 4; // Distance from the root (a quarter of the way into the image) to the x value
119
-
120
-		// The number of artists placed in the top or the bottom
121
-		$NumTop = 0;
122
-		$NumBottom = 0;
123
-
124
-		// The number of artists placed in the left or the right
125
-		$NumLeft = 0;
126
-		$NumRight = 0;
127
-
128
-		$Multiplier = 0;
129
-
130
-		// Build up an impressive list of possible x values
131
-		// We later iterate through these, and pick out the ones we want
132
-
133
-		// These x values are all below WIDTH/2 (all on the left)
134
-		// The script later chooses which side to put them on
135
-
136
-		// We create more very low x values because they're more likely to be skipped
137
-		for ($i = 0; $i <= count($this->Artists) * 4; $i++) {
138
-			if ($Offset >= ((WIDTH / 4))) {
139
-				$Offset = $Offset % (WIDTH / 4);
140
-			}
141
-			$Plus = $Root + $Offset; // Point on the right of the root
142
-			$Minus = abs($Root - $Offset); // Point on the left of the root
143
-
144
-			$xValues[$Plus] = $Plus;
145
-
146
-			$xValues[$Minus] = $Minus;
147
-
148
-			// Throw in an extra x value closer to the edge, because they're more likely to be skipped
149
-
150
-			if ($Minus > 30) {
151
-			//	$xValues[$Minus - 30] = $Minus - 30;
152
-			}
153
-
154
-			$Offset = $Offset + rand(5, 20); // Increase offset, and go again
155
-		}
156
-
157
-		foreach ($this->Artists as $Artist) {
158
-			$ArtistID = $Artist->ID;
159
-			if ($Artist->Displayed == true) {
160
-				continue;
161
-			}
162
-			$this->Similar[$ArtistID]['Decimal'] = $this->Similar[$ArtistID]['Decimal'] * (1 / ($this->LargestDecimal)) - 0.1;
163
-			// Calculate the distance away from the center, based on similarity
164
-			$IdealDistance =  $this->calculate_distance($this->Similar[$ArtistID]['Decimal'], $this->x, $this->y);
165
-
166
-			$this->Similar[$ArtistID]['Distance'] = $IdealDistance;
167
-
168
-			// 1 = left, 2 = right
169
-			$Horizontal = 0;
170
-			$Vertical = 0;
171
-
172
-			// See if any similar artists have been placed yet. If so, place artist in that half
173
-			// (provided that there are enough in the other half to visually balance out)
174
-			reset($Artist->Similar);
175
-			foreach ($Artist->Similar as $SimilarArtist) {
176
-				list($Artist2ID) = array_values($SimilarArtist);
177
-				if ($this->Artists[$Artist2ID]) {
178
-					if ($this->Artists[$Artist2ID]->x > (WIDTH / 2) && ($NumRight-$NumLeft) < 1) {
179
-						$Horizontal = 2;
180
-					} elseif ($NumLeft - $NumRight < 1) {
181
-						$Horizontal = 1;
182
-					}
183
-					break;
184
-				}
185
-			}
186
-
187
-			shuffle($xValues);
188
-
189
-			while ($xValue = array_shift($xValues)) {
190
-				if (abs($this->x - $xValue) <= $IdealDistance) {
191
-					if (hypot(abs($this->x - $xValue), ($this->y - 50)) > $IdealDistance
192
-						|| ceil(sqrt(pow($IdealDistance, 2) - pow($this->x - $xValue, 2))) > (HEIGHT / 2)) {
193
-						$xValue = $this->x - ceil(sqrt(pow($IdealDistance, 2) - pow($IdealDistance * 0.1 * rand(5,9), 2)));
194
-						//echo "Had to change x value for ".$Artist->Name." to ".$xValue."\n";
195
-					}
196
-					// Found a match (Is close enough to the center to satisfy $IdealDistance),
197
-					// Now it's time to choose which half to put it on
198
-					if (!$Horizontal) {
199
-						// No similar artists displayed
200
-						$Horizontal = ($NumLeft < $NumRight) ? 1 : 2;
201
-					}
202
-					if ($Horizontal == 2) {
203
-						$xValue = WIDTH - $xValue;
204
-						$NumRight++;
205
-					} else {
206
-						$NumLeft++;
207
-					}
208
-
209
-					$Artist->x = $xValue;
210
-					$this->xValues[$xValue] = $ArtistID;
211
-					unset($xValues[$xValue]);
212
-
213
-					break;
214
-				}
215
-			}
216
-			if (!$xValue) { // Uh-oh, we were unable to choose an x value.
217
-				$xValue = ceil(sqrt(pow($IdealDistance, 2) / 2));
218
-				$xValue = (WIDTH / 2) - $xValue;
219
-				$Artist->x = $xValue;
220
-				$this->xValues[$xValue] = $ArtistID;
221
-				unset($xValues[$xValue]);
222
-			}
223
-
224
-
225
-			// Pythagoras. $yValue is the vertical distance from the center to the y value
226
-			$yValue = sqrt(pow($IdealDistance, 2) - pow(abs($this->x - $Artist->x), 2));
227
-
228
-
229
-			// Now we pick if it should go on the top or bottom
230
-
231
-			if ($NumTop > $NumBottom) { // Send it to the bottom half
232
-				$yValue = (HEIGHT / 2) + $yValue;
233
-				$NumBottom++;
234
-			} else {
235
-				$yValue=(HEIGHT / 2) - $yValue;
236
-				$NumTop++;
237
-			}
238
-
239
-			$yValue = ceil($yValue);
240
-
241
-			// $yValue is now a proper y coordinate
242
-			// Now time to do some spacing out
243
-
244
-			if ($yValue < 10) {
245
-				$yValue += (10 + abs($yValue)) + rand(10,20);
246
-			}
247
-
248
-			if ($yValue > (HEIGHT - 10)) {
249
-				$yValue -= ((HEIGHT / 2) - rand(10,20));
250
-			}
251
-
252
-			$i = 1;
253
-			while ($Conflict = $this->scan_array_range($this->yValues, abs($yValue - 13), $yValue + 13)) {
254
-				if ($i > 10) {
255
-					break;
256
-				}
257
-				if (!$this->scan_array_range($this->yValues, abs($yValue - 5), $yValue - 20)) {
258
-					$yValue -= 20;
259
-				}
260
-
261
-				$yValue = $Conflict + rand(10, 20);
262
-				if ($yValue > HEIGHT - 10) {
263
-					$yValue -= ceil(HEIGHT / 2.5);
264
-				} elseif ($yValue < 10) {
265
-					$yValue += ceil(HEIGHT / 2.5);
266
-				}
267
-				$i++;
268
-			}
269
-
270
-			$Artist->y = $yValue;
271
-			$this->yValues[$yValue] = $ArtistID;
272
-		}
273
-		reset($this->Artists);
274
-		reset($this->xValues);
275
-		reset($this->yValues);
276
-
277
-	}
278
-
279
-	// Calculate the ideal distance from the center point ($Rootx, $Rooty) to the artist's point on the board
280
-	// Pythagoras as fun!
281
-	function calculate_distance($SimilarityCoefficient, $Rootx, $Rooty) {
282
-		$MaxWidth = WIDTH - $Rootx;
283
-		$MaxHeight = HEIGHT - $Rooty;
284
-		$x = $MaxWidth - ($SimilarityCoefficient * $MaxWidth * 0.01); // Possible x value
285
-		$y = $MaxHeight - ($SimilarityCoefficient * $MaxHeight); // Possible y value
286
-		$Hypot = hypot($Rootx - $x, $Rooty - $y);
287
-		return $MaxWidth - $Hypot;
288
-
289
-	}
290
-
291
-	function similarity($Score, $TotalArtistScore) {
292
-		return (pow(($Score / ($TotalArtistScore + 1)), (1 / 1)));
293
-	}
294
-
295
-	function scan_array_range($Array, $Start, $Finish) {
296
-		if ($Start < 0) {
297
-			die($Start);
298
-		}
299
-		for ($i = $Start; $i <= $Finish; $i++) {
300
-			if (isset($Array[$i])) {
301
-				return $i;
302
-			}
303
-		}
304
-		return false;
305
-	}
306
-
307
-	function write_artists() {
20
+  var $Artists = array();
21
+  var $TotalScore = 0;
22
+
23
+  var $xValues = array(WIDTH=>1);
24
+  var $yValues = array(HEIGHT=>1);
25
+
26
+  var $LargestDecimal = 0;
27
+  var $LowestDecimal = 1;
28
+
29
+
30
+
31
+  function dump_data() {
32
+    return serialize(array(time(), $this->Name, $this->x, $this->y, serialize($this->Artists), serialize($this->Similar)));
33
+  }
34
+
35
+  function load_data($Data) {
36
+    list($LastUpdated, $this->Name, $this->x, $this->y, $this->Artists, $this->Similar) = unserialize($Data);
37
+    $this->Artists = unserialize($this->Artists);
38
+    $this->Similar = unserialize($this->Similar);
39
+  }
40
+
41
+  function set_up() {
42
+    $QueryID = G::$DB->get_query_id();
43
+
44
+    $this->x = ceil(WIDTH / 2);
45
+    $this->y = ceil(HEIGHT / 2);
46
+
47
+    $this->xValues[$this->x] = $this->ID;
48
+    $this->yValues[$this->y] = $this->ID;
49
+
50
+
51
+    // Get artists that are directly similar to the artist
52
+    $ArtistIDs = array();
53
+    G::$DB->query("
54
+      SELECT
55
+        s2.ArtistID,
56
+        ag.Name,
57
+        ass.Score
58
+      FROM artists_similar AS s1
59
+        JOIN artists_similar AS s2 ON s1.SimilarID=s2.SimilarID AND s1.ArtistID!=s2.ArtistID
60
+        JOIN artists_similar_scores AS ass ON ass.SimilarID=s1.SimilarID
61
+        JOIN artists_group AS ag ON ag.ArtistID=s2.ArtistID
62
+      WHERE s1.ArtistID=".$this->ID."
63
+      ORDER BY ass.Score DESC
64
+      LIMIT 14");
65
+
66
+    if (!G::$DB->has_results()) {
67
+      return;
68
+    }
69
+
70
+    // Build into array. Each artist is its own object in $this->Artists
71
+    while (list($ArtistID, $Name, $Score) = G::$DB->next_record(MYSQLI_NUM, false)) {
72
+      if ($Score < 0) {
73
+        continue;
74
+      }
75
+      $this->Artists[$ArtistID] = new ARTIST($ArtistID, $Name);
76
+      $this->Similar[$ArtistID] = array('ID' => $ArtistID, 'Score' => $Score);
77
+      $this->TotalScore += $Score;
78
+      $ArtistIDs[] = $ArtistID;
79
+    }
80
+
81
+    // Get similarities between artists on the map
82
+    G::$DB->query("
83
+      SELECT
84
+        s1.ArtistID,
85
+        s2.ArtistID
86
+      FROM artists_similar AS s1
87
+        JOIN artists_similar AS s2 ON s1.SimilarID=s2.SimilarID AND s1.ArtistID!=s2.ArtistID
88
+        JOIN artists_similar_scores AS ass ON ass.SimilarID=s1.SimilarID
89
+        JOIN artists_group AS a ON a.ArtistID=s2.ArtistID
90
+      WHERE s1.ArtistID IN(".implode(',', $ArtistIDs).')
91
+        AND s2.ArtistID IN('.implode(',', $ArtistIDs).')');
92
+
93
+    // Build into array
94
+    while (list($Artist1ID, $Artist2ID) = G::$DB->next_record()) {
95
+      $this->Artists[$Artist1ID]->Similar[$Artist2ID] = array('ID'=>$Artist2ID);
96
+    }
97
+
98
+    // Calculate decimal point scores between artists
99
+    foreach ($this->Similar as $SimilarArtist) {
100
+      list($ArtistID, $Similar) = array_values($SimilarArtist);
101
+      $this->Similar[$ArtistID]['Decimal'] =  $this->similarity($Similar['Score'], $this->TotalScore);
102
+
103
+      if ($this->Similar[$ArtistID]['Decimal'] < $this->LowestDecimal) {
104
+        $this->LowestDecimal = $this->Similar[$ArtistID]['Decimal'];
105
+      }
106
+      if ($this->Similar[$ArtistID]['Decimal'] > $this->LargestDecimal) {
107
+        $this->LargestDecimal = $this->Similar[$ArtistID]['Decimal'];
108
+      }
109
+    }
110
+    reset($this->Artists);
111
+
112
+    G::$DB->set_query_id($QueryID);
113
+  }
114
+
115
+  function set_positions() {
116
+    $xValues = array(); // Possible x values
117
+    $Root = ceil(WIDTH / 4); // Half-way into half of the image
118
+    $Offset = 4; // Distance from the root (a quarter of the way into the image) to the x value
119
+
120
+    // The number of artists placed in the top or the bottom
121
+    $NumTop = 0;
122
+    $NumBottom = 0;
123
+
124
+    // The number of artists placed in the left or the right
125
+    $NumLeft = 0;
126
+    $NumRight = 0;
127
+
128
+    $Multiplier = 0;
129
+
130
+    // Build up an impressive list of possible x values
131
+    // We later iterate through these, and pick out the ones we want
132
+
133
+    // These x values are all below WIDTH/2 (all on the left)
134
+    // The script later chooses which side to put them on
135
+
136
+    // We create more very low x values because they're more likely to be skipped
137
+    for ($i = 0; $i <= count($this->Artists) * 4; $i++) {
138
+      if ($Offset >= ((WIDTH / 4))) {
139
+        $Offset = $Offset % (WIDTH / 4);
140
+      }
141
+      $Plus = $Root + $Offset; // Point on the right of the root
142
+      $Minus = abs($Root - $Offset); // Point on the left of the root
143
+
144
+      $xValues[$Plus] = $Plus;
145
+
146
+      $xValues[$Minus] = $Minus;
147
+
148
+      // Throw in an extra x value closer to the edge, because they're more likely to be skipped
149
+
150
+      if ($Minus > 30) {
151
+      //  $xValues[$Minus - 30] = $Minus - 30;
152
+      }
153
+
154
+      $Offset = $Offset + rand(5, 20); // Increase offset, and go again
155
+    }
156
+
157
+    foreach ($this->Artists as $Artist) {
158
+      $ArtistID = $Artist->ID;
159
+      if ($Artist->Displayed == true) {
160
+        continue;
161
+      }
162
+      $this->Similar[$ArtistID]['Decimal'] = $this->Similar[$ArtistID]['Decimal'] * (1 / ($this->LargestDecimal)) - 0.1;
163
+      // Calculate the distance away from the center, based on similarity
164
+      $IdealDistance =  $this->calculate_distance($this->Similar[$ArtistID]['Decimal'], $this->x, $this->y);
165
+
166
+      $this->Similar[$ArtistID]['Distance'] = $IdealDistance;
167
+
168
+      // 1 = left, 2 = right
169
+      $Horizontal = 0;
170
+      $Vertical = 0;
171
+
172
+      // See if any similar artists have been placed yet. If so, place artist in that half
173
+      // (provided that there are enough in the other half to visually balance out)
174
+      reset($Artist->Similar);
175
+      foreach ($Artist->Similar as $SimilarArtist) {
176
+        list($Artist2ID) = array_values($SimilarArtist);
177
+        if ($this->Artists[$Artist2ID]) {
178
+          if ($this->Artists[$Artist2ID]->x > (WIDTH / 2) && ($NumRight-$NumLeft) < 1) {
179
+            $Horizontal = 2;
180
+          } elseif ($NumLeft - $NumRight < 1) {
181
+            $Horizontal = 1;
182
+          }
183
+          break;
184
+        }
185
+      }
186
+
187
+      shuffle($xValues);
188
+
189
+      while ($xValue = array_shift($xValues)) {
190
+        if (abs($this->x - $xValue) <= $IdealDistance) {
191
+          if (hypot(abs($this->x - $xValue), ($this->y - 50)) > $IdealDistance
192
+            || ceil(sqrt(pow($IdealDistance, 2) - pow($this->x - $xValue, 2))) > (HEIGHT / 2)) {
193
+            $xValue = $this->x - ceil(sqrt(pow($IdealDistance, 2) - pow($IdealDistance * 0.1 * rand(5,9), 2)));
194
+            //echo "Had to change x value for ".$Artist->Name." to ".$xValue."\n";
195
+          }
196
+          // Found a match (Is close enough to the center to satisfy $IdealDistance),
197
+          // Now it's time to choose which half to put it on
198
+          if (!$Horizontal) {
199
+            // No similar artists displayed
200
+            $Horizontal = ($NumLeft < $NumRight) ? 1 : 2;
201
+          }
202
+          if ($Horizontal == 2) {
203
+            $xValue = WIDTH - $xValue;
204
+            $NumRight++;
205
+          } else {
206
+            $NumLeft++;
207
+          }
208
+
209
+          $Artist->x = $xValue;
210
+          $this->xValues[$xValue] = $ArtistID;
211
+          unset($xValues[$xValue]);
212
+
213
+          break;
214
+        }
215
+      }
216
+      if (!$xValue) { // Uh-oh, we were unable to choose an x value.
217
+        $xValue = ceil(sqrt(pow($IdealDistance, 2) / 2));
218
+        $xValue = (WIDTH / 2) - $xValue;
219
+        $Artist->x = $xValue;
220
+        $this->xValues[$xValue] = $ArtistID;
221
+        unset($xValues[$xValue]);
222
+      }
223
+
224
+
225
+      // Pythagoras. $yValue is the vertical distance from the center to the y value
226
+      $yValue = sqrt(pow($IdealDistance, 2) - pow(abs($this->x - $Artist->x), 2));
227
+
228
+
229
+      // Now we pick if it should go on the top or bottom
230
+
231
+      if ($NumTop > $NumBottom) { // Send it to the bottom half
232
+        $yValue = (HEIGHT / 2) + $yValue;
233
+        $NumBottom++;
234
+      } else {
235
+        $yValue=(HEIGHT / 2) - $yValue;
236
+        $NumTop++;
237
+      }
238
+
239
+      $yValue = ceil($yValue);
240
+
241
+      // $yValue is now a proper y coordinate
242
+      // Now time to do some spacing out
243
+
244
+      if ($yValue < 10) {
245
+        $yValue += (10 + abs($yValue)) + rand(10,20);
246
+      }
247
+
248
+      if ($yValue > (HEIGHT - 10)) {
249
+        $yValue -= ((HEIGHT / 2) - rand(10,20));
250
+      }
251
+
252
+      $i = 1;
253
+      while ($Conflict = $this->scan_array_range($this->yValues, abs($yValue - 13), $yValue + 13)) {
254
+        if ($i > 10) {
255
+          break;
256
+        }
257
+        if (!$this->scan_array_range($this->yValues, abs($yValue - 5), $yValue - 20)) {
258
+          $yValue -= 20;
259
+        }
260
+
261
+        $yValue = $Conflict + rand(10, 20);
262
+        if ($yValue > HEIGHT - 10) {
263
+          $yValue -= ceil(HEIGHT / 2.5);
264
+        } elseif ($yValue < 10) {
265
+          $yValue += ceil(HEIGHT / 2.5);
266
+        }
267
+        $i++;
268
+      }
269
+
270
+      $Artist->y = $yValue;
271
+      $this->yValues[$yValue] = $ArtistID;
272
+    }
273
+    reset($this->Artists);
274
+    reset($this->xValues);
275
+    reset($this->yValues);
276
+
277
+  }
278
+
279
+  // Calculate the ideal distance from the center point ($Rootx, $Rooty) to the artist's point on the board
280
+  // Pythagoras as fun!
281
+  function calculate_distance($SimilarityCoefficient, $Rootx, $Rooty) {
282
+    $MaxWidth = WIDTH - $Rootx;
283
+    $MaxHeight = HEIGHT - $Rooty;
284
+    $x = $MaxWidth - ($SimilarityCoefficient * $MaxWidth * 0.01); // Possible x value
285
+    $y = $MaxHeight - ($SimilarityCoefficient * $MaxHeight); // Possible y value
286
+    $Hypot = hypot($Rootx - $x, $Rooty - $y);
287
+    return $MaxWidth - $Hypot;
288
+
289
+  }
290
+
291
+  function similarity($Score, $TotalArtistScore) {
292
+    return (pow(($Score / ($TotalArtistScore + 1)), (1 / 1)));
293
+  }
294
+
295
+  function scan_array_range($Array, $Start, $Finish) {
296
+    if ($Start < 0) {
297
+      die($Start);
298
+    }
299
+    for ($i = $Start; $i <= $Finish; $i++) {
300
+      if (isset($Array[$i])) {
301
+        return $i;
302
+      }
303
+    }
304
+    return false;
305
+  }
306
+
307
+  function write_artists() {
308 308
 ?>
309
-		<div style="position: absolute; bottom: <?=($this->y - 10)?>px; left: <?=($this->x - $this->NameLength * 4)?>px; font-size: 13pt; white-space: nowrap;" class="similar_artist_header">
310
-			<?=($this->Name)?>
311
-		</div>
309
+    <div style="position: absolute; bottom: <?=($this->y - 10)?>px; left: <?=($this->x - $this->NameLength * 4)?>px; font-size: 13pt; white-space: nowrap;" class="similar_artist_header">
310
+      <?=($this->Name)?>
311
+    </div>
312 312
 <?
313
-		foreach ($this->Artists as $Artist) {
314
-			if ($Artist->ID == $this->ID) {
315
-				continue;
316
-			}
317
-			$xPosition = $Artist->x - $Artist->NameLength * 4;
318
-			if ($xPosition < 0) {
319
-				$xPosition = 3;
320
-				$Artist->x = $xPosition;
321
-
322
-			}
323
-			$Decimal = $this->Similar[$Artist->ID]['Decimal'];
324
-
325
-			if ($Decimal < 0.2) {
326
-				$FontSize = 8;
327
-			} elseif ($Decimal < 0.3) {
328
-				$FontSize = 9;
329
-			} elseif ($Decimal < 0.4) {
330
-				$FontSize = 10;
331
-			} else {
332
-				$FontSize = 12;
333
-			}
313
+    foreach ($this->Artists as $Artist) {
314
+      if ($Artist->ID == $this->ID) {
315
+        continue;
316
+      }
317
+      $xPosition = $Artist->x - $Artist->NameLength * 4;
318
+      if ($xPosition < 0) {
319
+        $xPosition = 3;
320
+        $Artist->x = $xPosition;
321
+
322
+      }
323
+      $Decimal = $this->Similar[$Artist->ID]['Decimal'];
324
+
325
+      if ($Decimal < 0.2) {
326
+        $FontSize = 8;
327
+      } elseif ($Decimal < 0.3) {
328
+        $FontSize = 9;
329
+      } elseif ($Decimal < 0.4) {
330
+        $FontSize = 10;
331
+      } else {
332
+        $FontSize = 12;
333
+      }
334 334
 ?>
335
-		<div style="position: absolute; top: <?=($Artist->y - 5)?>px; left: <?=$xPosition?>px; font-size: <?=$FontSize?>pt; white-space: nowrap;">
336
-			<a href="artist.php?id=<?=($Artist->ID)?>" class="similar_artist"><?=($Artist->Name)?></a>
337
-		</div>
335
+    <div style="position: absolute; top: <?=($Artist->y - 5)?>px; left: <?=$xPosition?>px; font-size: <?=$FontSize?>pt; white-space: nowrap;">
336
+      <a href="artist.php?id=<?=($Artist->ID)?>" class="similar_artist"><?=($Artist->Name)?></a>
337
+    </div>
338 338
 <?
339
-		}
340
-		reset($this->Artists);
341
-	}
342
-
343
-	function background_image() {
344
-		global $Img;
345
-		reset($this->Similar);
346
-		foreach ($this->Similar as $SimilarArtist) {
347
-			list($ArtistID, $Val) = array_values($SimilarArtist);
348
-			$Artist = $this->Artists[$ArtistID];
349
-			$Decimal = $this->Similar[$ArtistID]['Decimal'];
350
-			$Width = ceil($Decimal * 4) + 1;
351
-
352
-			$Img->line($this->x, $this->y, $Artist->x, $Artist->y, $Img->color(199, 218, 255), $Width);
353
-
354
-			unset($Artist->Similar[$this->ID]);
355
-			reset($Artist->Similar);
356
-			foreach ($Artist->Similar as $SimilarArtist2) {
357
-				list($Artist2ID) = array_values($SimilarArtist2);
358
-				if ($this->Artists[$Artist2ID]) {
359
-					$Artist2 = $this->Artists[$Artist2ID];
360
-					$Img->line($Artist->x, $Artist->y, $Artist2->x, $Artist2->y, $Img->color(173, 201, 255));
361
-					unset($Artist2->Similar[$ArtistID]);
362
-				}
363
-			}
364
-			reset($this->xValues);
365
-		}
366
-		$Img->make_png(SERVER_ROOT.'/static/similar/'.$this->ID.'.png');
367
-	}
368
-
369
-	function dump() {
370
-		echo "Similarities:\n";
371
-		foreach ($this->Artists as $Artist) {
372
-			echo $Artist->ID;
373
-			echo ' - ';
374
-			echo $Artist->Name;
375
-			echo "\n";
376
-			echo 'x - ' . $Artist->x . "\n";
377
-			echo 'y - ' . $Artist->y . "\n";
378
-			print_r($this->Similar[$Artist->ID]);
379
-			//print_r($Artist->Similar);
380
-			echo "\n\n---\n\n";
381
-		}
382
-
383
-	}
339
+    }
340
+    reset($this->Artists);
341
+  }
342
+
343
+  function background_image() {
344
+    global $Img;
345
+    reset($this->Similar);
346
+    foreach ($this->Similar as $SimilarArtist) {
347
+      list($ArtistID, $Val) = array_values($SimilarArtist);
348
+      $Artist = $this->Artists[$ArtistID];
349
+      $Decimal = $this->Similar[$ArtistID]['Decimal'];
350
+      $Width = ceil($Decimal * 4) + 1;
351
+
352
+      $Img->line($this->x, $this->y, $Artist->x, $Artist->y, $Img->color(199, 218, 255), $Width);
353
+
354
+      unset($Artist->Similar[$this->ID]);
355
+      reset($Artist->Similar);
356
+      foreach ($Artist->Similar as $SimilarArtist2) {
357
+        list($Artist2ID) = array_values($SimilarArtist2);
358
+        if ($this->Artists[$Artist2ID]) {
359
+          $Artist2 = $this->Artists[$Artist2ID];
360
+          $Img->line($Artist->x, $Artist->y, $Artist2->x, $Artist2->y, $Img->color(173, 201, 255));
361
+          unset($Artist2->Similar[$ArtistID]);
362
+        }
363
+      }
364
+      reset($this->xValues);
365
+    }
366
+    $Img->make_png(SERVER_ROOT.'/static/similar/'.$this->ID.'.png');
367
+  }
368
+
369
+  function dump() {
370
+    echo "Similarities:\n";
371
+    foreach ($this->Artists as $Artist) {
372
+      echo $Artist->ID;
373
+      echo ' - ';
374
+      echo $Artist->Name;
375
+      echo "\n";
376
+      echo 'x - ' . $Artist->x . "\n";
377
+      echo 'y - ' . $Artist->y . "\n";
378
+      print_r($this->Similar[$Artist->ID]);
379
+      //print_r($Artist->Similar);
380
+      echo "\n\n---\n\n";
381
+    }
382
+
383
+  }
384 384
 }
385 385
 ?>

+ 136
- 136
classes/badges.class.php View File

@@ -1,145 +1,145 @@
1 1
 <?
2 2
 class Badges {
3
-	/**
4
-	 * Given a UserID, returns that user's badges
5
-	 *
6
-	 * @param int $UserID
7
-	 * @return array of BadgeIDs
8
-	 */
9
-	public static function get_badges($UserID) {
10
-		$Result = array();
11
-		
12
-		if (G::$Cache->get_value('user_badges_'.$UserID) !== false) {
13
-			return G::$Cache->get_value('user_badges_'.$UserID);
14
-		}
15
-
16
-		$QueryID = G::$DB->get_query_id();
17
-		G::$DB->query("
18
-			SELECT BadgeID, Displayed
19
-			FROM users_badges
20
-			WHERE UserID = ".$UserID);
21
-
22
-		if (G::$DB->has_results()) {
23
-			while (list($BadgeID, $Displayed) = G::$DB->next_record()) {
24
-				$Result[] = array('BadgeID' => $BadgeID, 'Displayed' => $Displayed);
25
-			}
26
-		}
27
-
28
-		G::$DB->set_query_id($QueryID);
29
-
30
-		G::$Cache->cache_value('user_badges_'.$UserID, $Result);
31
-
32
-		return $Result;
33
-	}
34
-
35
-	/**
36
-	 * Awards UserID the given BadgeID
37
-	 *
38
-	 * @param int $UserID
39
-	 * @param int $BadgeID
40
-	 * @return bool success?
41
-	 */
42
-	public static function award_badge($UserID, $BadgeID) {
43
-		if (self::has_badge($UserID, array('BadgeID' => $BadgeID))) {
44
-			return false;
45
-		} else {
46
-			$QueryID = G::$DB->get_query_id();
47
-			G::$DB->query("
48
-				INSERT INTO users_badges
49
-					(UserID, BadgeID)
50
-				VALUES
51
-					($UserID, $BadgeID)");
52
-			G::$DB->set_query_id($QueryID);
53
-
54
-			G::$Cache->delete_value('user_badges_'.$UserID);
55
-
56
-			return true;
57
-		}
58
-	}
59
-
60
-	/**
61
-	 * Given a UserID, return that user's displayed badges
62
-	 *
63
-	 * @param int $UserID
64
-	 * @return array of BadgeIDs
65
-	 */
66
-	public static function get_displayed_badges($UserID) {
67
-		$Result = array();
3
+  /**
4
+   * Given a UserID, returns that user's badges
5
+   *
6
+   * @param int $UserID
7
+   * @return array of BadgeIDs
8
+   */
9
+  public static function get_badges($UserID) {
10
+    $Result = array();
11
+
12
+    if (G::$Cache->get_value('user_badges_'.$UserID) !== false) {
13
+      return G::$Cache->get_value('user_badges_'.$UserID);
14
+    }
15
+
16
+    $QueryID = G::$DB->get_query_id();
17
+    G::$DB->query("
18
+      SELECT BadgeID, Displayed
19
+      FROM users_badges
20
+      WHERE UserID = ".$UserID);
21
+
22
+    if (G::$DB->has_results()) {
23
+      while (list($BadgeID, $Displayed) = G::$DB->next_record()) {
24
+        $Result[] = array('BadgeID' => $BadgeID, 'Displayed' => $Displayed);
25
+      }
26
+    }
27
+
28
+    G::$DB->set_query_id($QueryID);
29
+
30
+    G::$Cache->cache_value('user_badges_'.$UserID, $Result);
31
+
32
+    return $Result;
33
+  }
34
+
35
+  /**
36
+   * Awards UserID the given BadgeID
37
+   *
38
+   * @param int $UserID
39
+   * @param int $BadgeID
40
+   * @return bool success?
41
+   */
42
+  public static function award_badge($UserID, $BadgeID) {
43
+    if (self::has_badge($UserID, array('BadgeID' => $BadgeID))) {
44
+      return false;
45
+    } else {
46
+      $QueryID = G::$DB->get_query_id();
47
+      G::$DB->query("
48
+        INSERT INTO users_badges
49
+          (UserID, BadgeID)
50
+        VALUES
51
+          ($UserID, $BadgeID)");
52
+      G::$DB->set_query_id($QueryID);
53
+
54
+      G::$Cache->delete_value('user_badges_'.$UserID);
55
+
56
+      return true;
57
+    }
58
+  }
59
+
60
+  /**
61
+   * Given a UserID, return that user's displayed badges
62
+   *
63
+   * @param int $UserID
64
+   * @return array of BadgeIDs
65
+   */
66
+  public static function get_displayed_badges($UserID) {
67
+    $Result = array();
68 68
 
69 69
     $Badges = self::get_badges($UserID);
70 70
 
71
-		foreach ($Badges as $Badge) {
72
-			if ($Badge['Displayed'])
73
-				$Result[] = $Badge;
74
-		}
75
-		return $Result;
76
-	}
77
-
78
-	/**
79
-	 * Returns true if the given user owns the given badge
80
-	 *
81
-	 * @param int $UserID
82
-	 * @param $Badge
83
-	 * @return bool
84
-	 */
85
-	public static function has_badge($UserID, $Badge) {
71
+    foreach ($Badges as $Badge) {
72
+      if ($Badge['Displayed'])
73
+        $Result[] = $Badge;
74
+    }
75
+    return $Result;
76
+  }
77
+
78
+  /**
79
+   * Returns true if the given user owns the given badge
80
+   *
81
+   * @param int $UserID
82
+   * @param $Badge
83
+   * @return bool
84
+   */
85
+  public static function has_badge($UserID, $Badge) {
86 86
     $Badges = self::get_badges($UserID);
87 87
 
88
-		foreach ($Badges as $B) {
89
-			if ($B['BadgeID'] == $Badge['BadgeID'])
90
-				return true;
91
-		}
92
-
93
-		return false;
94
-	}
95
-
96
-	/**
97
-	 * Creates HTML for displaying a badge.
98
-	 *
99
-	 * @param $Badge
100
-	 * @param bool $Tooltip Should HTML contain a tooltip?
101
-	 * @return string HTML
102
-	 */
103
-	public static function display_badge($Badge, $Tooltip = false) {
104
-		$html = "";
105
-		
106
-		if (G::$Cache->get_value('badge_'.$Badge['BadgeID'])) {
107
-			extract(G::$Cache->get_value('badge_'.$Badge['BadgeID']));
108
-		}
109
-		if (!isset($Icon)) {
110
-			$QueryID = G::$DB->get_query_id();
111
-			G::$DB->query("
112
-				SELECT
113
-				Icon, Name, Description
114
-				FROM badges
115
-				WHERE ID = ".$Badge['BadgeID']);
116
-
117
-			if (G::$DB->has_results()) {
118
-				list($Icon, $Name, $Description) = G::$DB->next_record();
119
-				G::$Cache->cache_value('badge_'.$Badge['BadgeID'], array('Icon' => $Icon, 'Name' => $Name, 'Description' => $Description));
120
-			}
121
-
122
-			G::$DB->set_query_id($QueryID);
123
-
124
-		}
125
-
126
-		if (isset($Icon)) {
127
-			if ($Tooltip) {
128
-				$html .= "<a class='badge_icon'><img class='tooltip' title='$Name</br>$Description' src='$Icon' /></a>";
129
-			} else { 
130
-				$html .= "<a class='badge_icon'><img title='$Name' src='$Icon' /></a>";
131
-			}
132
-		}
133
-		
134
-		return $html;
135
-	}
136
-
137
-	public static function display_badges($Badges, $Tooltip = false) {
138
-		$html = "";
139
-		foreach ($Badges as $Badge) {
140
-			$html .= self::display_badge($Badge, $Tooltip);
141
-		}
142
-		return $html;
143
-	}
88
+    foreach ($Badges as $B) {
89
+      if ($B['BadgeID'] == $Badge['BadgeID'])
90
+        return true;
91
+    }
92
+
93
+    return false;
94
+  }
95
+
96
+  /**
97
+   * Creates HTML for displaying a badge.
98
+   *
99
+   * @param $Badge
100
+   * @param bool $Tooltip Should HTML contain a tooltip?
101
+   * @return string HTML
102
+   */
103
+  public static function display_badge($Badge, $Tooltip = false) {
104
+    $html = "";
105
+
106
+    if (G::$Cache->get_value('badge_'.$Badge['BadgeID'])) {
107
+      extract(G::$Cache->get_value('badge_'.$Badge['BadgeID']));
108
+    }
109
+    if (!isset($Icon)) {
110
+      $QueryID = G::$DB->get_query_id();
111
+      G::$DB->query("
112
+        SELECT
113
+        Icon, Name, Description
114
+        FROM badges
115
+        WHERE ID = ".$Badge['BadgeID']);
116
+
117
+      if (G::$DB->has_results()) {
118
+        list($Icon, $Name, $Description) = G::$DB->next_record();
119
+        G::$Cache->cache_value('badge_'.$Badge['BadgeID'], array('Icon' => $Icon, 'Name' => $Name, 'Description' => $Description));
120
+      }
121
+
122
+      G::$DB->set_query_id($QueryID);
123
+
124
+    }
125
+
126
+    if (isset($Icon)) {
127
+      if ($Tooltip) {
128
+        $html .= "<a class='badge_icon'><img class='tooltip' title='$Name</br>$Description' src='$Icon' /></a>";
129
+      } else {
130
+        $html .= "<a class='badge_icon'><img title='$Name' src='$Icon' /></a>";
131
+      }
132
+    }
133
+
134
+    return $html;
135
+  }
136
+
137
+  public static function display_badges($Badges, $Tooltip = false) {
138
+    $html = "";
139
+    foreach ($Badges as $Badge) {
140
+      $html .= self::display_badge($Badge, $Tooltip);
141
+    }
142
+    return $html;
143
+  }
144 144
 }
145 145
 ?>

+ 76
- 76
classes/bencode.class.php View File

@@ -4,23 +4,23 @@
4 4
  * Overhead from the function calls is small enough to not worry about
5 5
  */
6 6
 class Int64 {
7
-	private $Num;
7
+  private $Num;
8 8
 
9
-	public function __construct($Val) {
10
-		$this->Num = $Val;
11
-	}
9
+  public function __construct($Val) {
10
+    $this->Num = $Val;
11
+  }
12 12
 
13
-	public static function make($Val) {
14
-		return PHP_INT_SIZE === 4 ? new Int64($Val) : (int)$Val;
15
-	}
13
+  public static function make($Val) {
14
+    return PHP_INT_SIZE === 4 ? new Int64($Val) : (int)$Val;
15
+  }
16 16
 
17
-	public static function get($Val) {
18
-		return PHP_INT_SIZE === 4 ? $Val->Num : $Val;
19
-	}
17
+  public static function get($Val) {
18
+    return PHP_INT_SIZE === 4 ? $Val->Num : $Val;
19
+  }
20 20
 
21
-	public static function is_int($Val) {
22
-		return is_int($Val) || (is_object($Val) && get_class($Val) === 'Int64');
23
-	}
21
+  public static function is_int($Val) {
22
+    return is_int($Val) || (is_object($Val) && get_class($Val) === 'Int64');
23
+  }
24 24
 }
25 25
 
26 26
 /**
@@ -28,69 +28,69 @@ class Int64 {
28 28
  * note is that empty dictionaries are represented by boolean trues
29 29
  */
30 30
 class Bencode {
31
-	private $DefaultKeys = array( // Get rid of everything except these keys to save some space
32
-			'created by', 'creation date', 'encoding', 'info');
33
-	private $Data;
34
-	public $Enc;
31
+  private $DefaultKeys = array( // Get rid of everything except these keys to save some space
32
+      'created by', 'creation date', 'encoding', 'info');
33
+  private $Data;
34
+  public $Enc;
35 35
 
36
-	/**
37
-	 * Encode an arbitrary array (usually one that's just been decoded)
38
-	 *
39
-	 * @param array $Arg the thing to encode
40
-	 * @param mixed $Keys string or array with keys in the input array to encode or true to encode everything
41
-	 * @return bencoded string representing the content of the input array
42
-	 */
43
-	public function encode($Arg = false, $Keys = false) {
44
-		if ($Arg === false) {
45
-			$Data =& $this->Dec;
46
-		} else {
47
-			$Data =& $Arg;
48
-		}
49
-		if ($Keys === true) {
50
-			$this->Data = $Data;
51
-		} elseif ($Keys === false) {
52
-			$this->Data = array_intersect_key($Data, array_flip($this->DefaultKeys));
53
-		} elseif (is_array($Keys)) {
54
-			$this->Data = array_intersect_key($Data, array_flip($Keys));
55
-		} else {
56
-			$this->Data = isset($Data[$Keys]) ? $Data[$Keys] : false;
57
-		}
58
-		if (!$this->Data) {
59
-			return false;
60
-		}
61
-		$this->Enc = $this->_benc();
62
-		return $this->Enc;
63
-	}
36
+  /**
37
+   * Encode an arbitrary array (usually one that's just been decoded)
38
+   *
39
+   * @param array $Arg the thing to encode
40
+   * @param mixed $Keys string or array with keys in the input array to encode or true to encode everything
41
+   * @return bencoded string representing the content of the input array
42
+   */
43
+  public function encode($Arg = false, $Keys = false) {
44
+    if ($Arg === false) {
45
+      $Data =& $this->Dec;
46
+    } else {
47
+      $Data =& $Arg;
48
+    }
49
+    if ($Keys === true) {
50
+      $this->Data = $Data;
51
+    } elseif ($Keys === false) {
52
+      $this->Data = array_intersect_key($Data, array_flip($this->DefaultKeys));
53
+    } elseif (is_array($Keys)) {
54
+      $this->Data = array_intersect_key($Data, array_flip($Keys));
55
+    } else {
56
+      $this->Data = isset($Data[$Keys]) ? $Data[$Keys] : false;
57
+    }
58
+    if (!$this->Data) {
59
+      return false;
60
+    }
61
+    $this->Enc = $this->_benc();
62
+    return $this->Enc;
63
+  }
64 64
 
65
-	/**
66
-	 * Internal encoding function that does the actual job
67
-	 *
68
-	 * @return bencoded string
69
-	 */
70
-	private function _benc() {
71
-		if (!is_array($this->Data)) {
72
-			if (Int64::is_int($this->Data)) { // Integer
73
-				return 'i'.Int64::get($this->Data).'e';
74
-			}
75
-			if ($this->Data === true) { // Empty dictionary
76
-				return 'de';
77
-			}
78
-			return strlen($this->Data).':'.$this->Data; // String
79
-		}
80
-		if (empty($this->Data) || Int64::is_int(key($this->Data))) {
81
-			$IsDict = false;
82
-		} else {
83
-			$IsDict = true;
84
-			ksort($this->Data); // Dictionaries must be sorted
85
-		}
86
-		$Ret = $IsDict ? 'd' : 'l';
87
-		foreach ($this->Data as $Key => $Value) {
88
-			if ($IsDict) {
89
-				$Ret .= strlen($Key).':'.$Key;
90
-			}
91
-			$this->Data = $Value;
92
-			$Ret .= $this->_benc();
93
-		}
94
-		return $Ret.'e';
95
-	}
65
+  /**
66
+   * Internal encoding function that does the actual job
67
+   *
68
+   * @return bencoded string
69
+   */
70
+  private function _benc() {
71
+    if (!is_array($this->Data)) {
72
+      if (Int64::is_int($this->Data)) { // Integer
73
+        return 'i'.Int64::get($this->Data).'e';
74
+      }
75
+      if ($this->Data === true) { // Empty dictionary
76
+        return 'de';
77
+      }
78
+      return strlen($this->Data).':'.$this->Data; // String
79
+    }
80
+    if (empty($this->Data) || Int64::is_int(key($this->Data))) {
81
+      $IsDict = false;
82
+    } else {
83
+      $IsDict = true;
84
+      ksort($this->Data); // Dictionaries must be sorted
85
+    }
86
+    $Ret = $IsDict ? 'd' : 'l';
87
+    foreach ($this->Data as $Key => $Value) {
88
+      if ($IsDict) {
89
+        $Ret .= strlen($Key).':'.$Key;
90
+      }
91
+      $this->Data = $Value;
92
+      $Ret .= $this->_benc();
93
+    }
94
+    return $Ret.'e';
95
+  }
96 96
 }

+ 167
- 167
classes/bencodedecode.class.php View File

@@ -4,181 +4,181 @@
4 4
  * note is that empty dictionaries are represented by boolean trues
5 5
  */
6 6
 class BencodeDecode extends Bencode {
7
-	private $Data;
8
-	private $Length;
9
-	private $Pos = 0;
10
-	public $Dec = array();
11
-	public $ExitOnError = true;
12
-	const SnipLength = 40;
7
+  private $Data;
8
+  private $Length;
9
+  private $Pos = 0;
10
+  public $Dec = array();
11
+  public $ExitOnError = true;
12
+  const SnipLength = 40;
13 13
 
14
-	/**
15
-	 * Decode prepararations
16
-	 *
17
-	 * @param string $Arg bencoded string or path to bencoded file to decode
18
-	 * @param bool $IsPath needs to be true if $Arg is a path
19
-	 * @return decoded data with a suitable structure
20
-	 */
21
-	function __construct($Arg = false, $IsPath = false) {
22
-		if ($Arg === false) {
23
-			if (empty($this->Enc)) {
24
-				return false;
25
-			}
26
-		} else {
27
-			if ($IsPath === true) {
28
-				return $this->bdec_file($Arg);
29
-			}
30
-			$this->Data = $Arg;
31
-		}
32
-		return $this->decode();
33
-	}
14
+  /**
15
+   * Decode prepararations
16
+   *
17
+   * @param string $Arg bencoded string or path to bencoded file to decode
18
+   * @param bool $IsPath needs to be true if $Arg is a path
19
+   * @return decoded data with a suitable structure
20
+   */
21
+  function __construct($Arg = false, $IsPath = false) {
22
+    if ($Arg === false) {
23
+      if (empty($this->Enc)) {
24
+        return false;
25
+      }
26
+    } else {
27
+      if ($IsPath === true) {
28
+        return $this->bdec_file($Arg);
29
+      }
30
+      $this->Data = $Arg;
31
+    }
32
+    return $this->decode();
33
+  }
34 34
 
35
-	/**
36
-	 * Decodes a bencoded file
37
-	 *
38
-	 * @param $Path path to bencoded file to decode
39
-	 * @return decoded data with a suitable structure
40
-	 */
41
-	public function bdec_file($Path = false) {
42
-		if (empty($Path)) {
43
-			return false;
44
-		}
45
-		if (!$this->Data = @file_get_contents($Path, FILE_BINARY)) {
46
-			return $this->error("Error: file '$Path' could not be opened.\n");
47
-		}
48
-		return $this->decode();
49
-	}
35
+  /**
36
+   * Decodes a bencoded file
37
+   *
38
+   * @param $Path path to bencoded file to decode
39
+   * @return decoded data with a suitable structure
40
+   */
41
+  public function bdec_file($Path = false) {
42
+    if (empty($Path)) {
43
+      return false;
44
+    }
45
+    if (!$this->Data = @file_get_contents($Path, FILE_BINARY)) {
46
+      return $this->error("Error: file '$Path' could not be opened.\n");
47
+    }
48
+    return $this->decode();
49
+  }
50 50
 
51
-	/**
52
-	 * Decodes a string with bencoded data
53
-	 *
54
-	 * @param mixed $Arg bencoded data or false to decode the content of $this->Data
55
-	 * @return decoded data with a suitable structure
56
-	 */
57
-	public function decode($Arg = false) {
58
-		if ($Arg !== false) {
59
-			$this->Data = $Arg;
60
-		} elseif (!$this->Data) {
61
-			$this->Data = $this->Enc;
62
-		}
63
-		if (!$this->Data) {
64
-			return false;
65
-		}
66
-		$this->Length = strlen($this->Data);
67
-		$this->Pos = 0;
68
-		$this->Dec = $this->_bdec();
69
-		if ($this->Pos < $this->Length) {
70
-			// Not really necessary, but if the torrent is invalid, it's better to warn than to silently truncate it
71
-			return $this->error();
72
-		}
73
-		return $this->Dec;
74
-	}
51
+  /**
52
+   * Decodes a string with bencoded data
53
+   *
54
+   * @param mixed $Arg bencoded data or false to decode the content of $this->Data
55
+   * @return decoded data with a suitable structure
56
+   */
57
+  public function decode($Arg = false) {
58
+    if ($Arg !== false) {
59
+      $this->Data = $Arg;
60
+    } elseif (!$this->Data) {
61
+      $this->Data = $this->Enc;
62
+    }
63
+    if (!$this->Data) {
64
+      return false;
65
+    }
66
+    $this->Length = strlen($this->Data);
67
+    $this->Pos = 0;
68
+    $this->Dec = $this->_bdec();
69
+    if ($this->Pos < $this->Length) {
70
+      // Not really necessary, but if the torrent is invalid, it's better to warn than to silently truncate it
71
+      return $this->error();
72
+    }
73
+    return $this->Dec;
74
+  }
75 75
 
76
-	/**
77
-	 * Internal decoding function that does the actual job
78
-	 *
79
-	 * @return decoded data with a suitable structure
80
-	 */
81
-	private function _bdec() {
82
-		switch ($this->Data[$this->Pos]) {
76
+  /**
77
+   * Internal decoding function that does the actual job
78
+   *
79
+   * @return decoded data with a suitable structure
80
+   */
81
+  private function _bdec() {
82
+    switch ($this->Data[$this->Pos]) {
83 83
 
84
-			case 'i':
85
-				$this->Pos++;
86
-				$Value = substr($this->Data, $this->Pos, strpos($this->Data, 'e', $this->Pos) - $this->Pos);
87
-				if (!ctype_digit($Value) && !($Value[0] == '-' && ctype_digit(substr($Value, 1)))) {
88
-					return $this->error();
89
-				}
90
-				$this->Pos += strlen($Value) + 1;
91
-				return Int64::make($Value);
84
+      case 'i':
85
+        $this->Pos++;
86
+        $Value = substr($this->Data, $this->Pos, strpos($this->Data, 'e', $this->Pos) - $this->Pos);
87
+        if (!ctype_digit($Value) && !($Value[0] == '-' && ctype_digit(substr($Value, 1)))) {
88
+          return $this->error();
89
+        }
90
+        $this->Pos += strlen($Value) + 1;
91
+        return Int64::make($Value);
92 92
 
93
-			case 'l':
94
-				$Value = array();
95
-				$this->Pos++;
96
-				while ($this->Data[$this->Pos] != 'e') {
97
-					if ($this->Pos >= $this->Length) {
98
-						return $this->error();
99
-					}
100
-					$Value[] = $this->_bdec();
101
-				}
102
-				$this->Pos++;
103
-				return $Value;
93
+      case 'l':
94
+        $Value = array();
95
+        $this->Pos++;
96
+        while ($this->Data[$this->Pos] != 'e') {
97
+          if ($this->Pos >= $this->Length) {
98
+            return $this->error();
99
+          }
100
+          $Value[] = $this->_bdec();
101
+        }
102
+        $this->Pos++;
103
+        return $Value;
104 104
 
105
-			case 'd':
106
-				$Value = array();
107
-				$this->Pos++;
108
-				while ($this->Data[$this->Pos] != 'e') {
109
-					$Length = substr($this->Data, $this->Pos, strpos($this->Data, ':', $this->Pos) - $this->Pos);
110
-					if (!ctype_digit($Length)) {
111
-						return $this->error();
112
-					}
113
-					$this->Pos += strlen($Length) + $Length + 1;
114
-					$Key = substr($this->Data, $this->Pos - $Length, $Length);
115
-					if ($this->Pos >= $this->Length) {
116
-						return $this->error();
117
-					}
118
-					$Value[$Key] = $this->_bdec();
119
-				}
120
-				$this->Pos++;
121
-				// Use boolean true to keep track of empty dictionaries
122
-				return empty($Value) ? true : $Value;
105
+      case 'd':
106
+        $Value = array();
107
+        $this->Pos++;
108
+        while ($this->Data[$this->Pos] != 'e') {
109
+          $Length = substr($this->Data, $this->Pos, strpos($this->Data, ':', $this->Pos) - $this->Pos);
110
+          if (!ctype_digit($Length)) {
111
+            return $this->error();
112
+          }
113
+          $this->Pos += strlen($Length) + $Length + 1;
114
+          $Key = substr($this->Data, $this->Pos - $Length, $Length);
115
+          if ($this->Pos >= $this->Length) {
116
+            return $this->error();
117
+          }
118
+          $Value[$Key] = $this->_bdec();
119
+        }
120
+        $this->Pos++;
121
+        // Use boolean true to keep track of empty dictionaries
122
+        return empty($Value) ? true : $Value;
123 123
 
124
-			default:
125
-				$Length = substr($this->Data, $this->Pos, strpos($this->Data, ':', $this->Pos) - $this->Pos);
126
-				if (!ctype_digit($Length)) {
127
-					return $this->error(); // Even if the string is likely to be decoded correctly without this check, it's malformed
128
-				}
129
-				$this->Pos += strlen($Length) + $Length + 1;
130
-				return substr($this->Data, $this->Pos - $Length, $Length);
131
-		}
132
-	}
124
+      default:
125
+        $Length = substr($this->Data, $this->Pos, strpos($this->Data, ':', $this->Pos) - $this->Pos);
126
+        if (!ctype_digit($Length)) {
127
+          return $this->error(); // Even if the string is likely to be decoded correctly without this check, it's malformed
128
+        }
129
+        $this->Pos += strlen($Length) + $Length + 1;
130
+        return substr($this->Data, $this->Pos - $Length, $Length);
131
+    }
132
+  }
133 133
 
134
-	/**
135
-	 * Convert everything to the correct data types and optionally escape strings
136
-	 *
137
-	 * @param bool $Escape whether to escape the textual data
138
-	 * @param mixed $Data decoded data or false to use the $Dec property
139
-	 * @return decoded data with more useful data types
140
-	 */
141
-	public function dump($Escape = true, $Data = false) {
142
-		if ($Data === false) {
143
-			$Data = $this->Dec;
144
-		}
145
-		if (Int64::is_int($Data)) {
146
-			return Int64::get($Data);
147
-		}
148
-		if (is_bool($Data)) {
149
-			return array();
150
-		}
151
-		if (is_array($Data)) {
152
-			$Output = array();
153
-			foreach ($Data as $Key => $Val) {
154
-				$Output[$Key] = $this->dump($Escape, $Val);
155
-			}
156
-			return $Output;
157
-		}
158
-		return $Escape ? htmlentities($Data) : $Data;
159
-	}
134
+  /**
135
+   * Convert everything to the correct data types and optionally escape strings
136
+   *
137
+   * @param bool $Escape whether to escape the textual data
138
+   * @param mixed $Data decoded data or false to use the $Dec property
139
+   * @return decoded data with more useful data types
140
+   */
141
+  public function dump($Escape = true, $Data = false) {
142
+    if ($Data === false) {
143
+      $Data = $this->Dec;
144
+    }
145
+    if (Int64::is_int($Data)) {
146
+      return Int64::get($Data);
147
+    }
148
+    if (is_bool($Data)) {
149
+      return array();
150
+    }
151
+    if (is_array($Data)) {
152
+      $Output = array();
153
+      foreach ($Data as $Key => $Val) {
154
+        $Output[$Key] = $this->dump($Escape, $Val);
155
+      }
156
+      return $Output;
157
+    }
158
+    return $Escape ? htmlentities($Data) : $Data;
159
+  }
160 160
 
161
-	/**
162
-	 * Display an error and halt the operation unless the $ExitOnError property is false
163
-	 *
164
-	 * @param string $ErrMsg the error message to display
165
-	 */
166
-	private function error($ErrMsg = false) {
167
-		static $ErrorPos;
168
-		if ($this->Pos === $ErrorPos) {
169
-			// The recursive nature of the class requires this to avoid duplicate error messages
170
-			return false;
171
-		}
172
-		if ($ErrMsg === false) {
173
-			printf("Malformed string. Invalid character at pos 0x%X: %s\n",
174
-					$this->Pos, str_replace(array("\r","\n"), array('',' '), htmlentities(substr($this->Data, $this->Pos, self::SnipLength))));
175
-		} else {
176
-			echo $ErrMsg;
177
-		}
178
-		if ($this->ExitOnError) {
179
-			exit();
180
-		}
181
-		$ErrorPos = $this->Pos;
182
-		return false;
183
-	}
161
+  /**
162
+   * Display an error and halt the operation unless the $ExitOnError property is false
163
+   *
164
+   * @param string $ErrMsg the error message to display
165
+   */
166
+  private function error($ErrMsg = false) {
167
+    static $ErrorPos;
168
+    if ($this->Pos === $ErrorPos) {
169
+      // The recursive nature of the class requires this to avoid duplicate error messages
170
+      return false;
171
+    }
172
+    if ($ErrMsg === false) {
173
+      printf("Malformed string. Invalid character at pos 0x%X: %s\n",
174
+          $this->Pos, str_replace(array("\r","\n"), array('',' '), htmlentities(substr($this->Data, $this->Pos, self::SnipLength))));
175
+    } else {
176
+      echo $ErrMsg;
177
+    }
178
+    if ($this->ExitOnError) {
179
+      exit();
180
+    }
181
+    $ErrorPos = $this->Pos;
182
+    return false;
183
+  }
184 184
 }

+ 130
- 130
classes/bencodetorrent.class.php View File

@@ -3,141 +3,141 @@
3 3
  * Torrent class that contains some convenient functions related to torrent meta data
4 4
  */
5 5
 class BencodeTorrent extends BencodeDecode {
6
-	private $PathKey = 'path';
7
-	public $Files = array();
8
-	public $Size = 0;
6
+  private $PathKey = 'path';
7
+  public $Files = array();
8
+  public $Size = 0;
9 9
 
10
-	/**
11
-	 * Create a list of the files in the torrent and their sizes as well as the total torrent size
12
-	 *
13
-	 * @return array with a list of files and file sizes
14
-	 */
15
-	public function file_list() {
16
-		if (empty($this->Dec)) {
17
-			return false;
18
-		}
19
-		$InfoDict =& $this->Dec['info'];
20
-		if (!isset($InfoDict['files'])) {
21
-			// Single-file torrent
22
-			$this->Size = (Int64::is_int($InfoDict['length'])
23
-				? Int64::get($InfoDict['length'])
24
-				: $InfoDict['length']);
25
-			$Name = (isset($InfoDict['name.utf-8'])
26
-				? $InfoDict['name.utf-8']
27
-				: $InfoDict['name']);
28
-			$this->Files[] = array($this->Size, $Name);
29
-		} else {
30
-			if (isset($InfoDict['path.utf-8']['files'][0])) {
31
-				$this->PathKey = 'path.utf-8';
32
-			}
33
-			foreach ($InfoDict['files'] as $File) {
34
-				$TmpPath = array();
35
-				foreach ($File[$this->PathKey] as $SubPath) {
36
-					$TmpPath[] = $SubPath;
37
-				}
38
-				$CurSize = (Int64::is_int($File['length'])
39
-					? Int64::get($File['length'])
40
-					: $File['length']);
41
-				$this->Files[] = array($CurSize, implode('/', $TmpPath));
42
-				$this->Size += $CurSize;
43
-			}
44
-			uasort($this->Files, function($a, $b) {
45
-					return strnatcasecmp($a[1], $b[1]);
46
-				});
47
-		}
48
-		return array($this->Size, $this->Files);
49
-	}
10
+  /**
11
+   * Create a list of the files in the torrent and their sizes as well as the total torrent size
12
+   *
13
+   * @return array with a list of files and file sizes
14
+   */
15
+  public function file_list() {
16
+    if (empty($this->Dec)) {
17
+      return false;
18
+    }
19
+    $InfoDict =& $this->Dec['info'];
20
+    if (!isset($InfoDict['files'])) {
21
+      // Single-file torrent
22
+      $this->Size = (Int64::is_int($InfoDict['length'])
23
+        ? Int64::get($InfoDict['length'])
24
+        : $InfoDict['length']);
25
+      $Name = (isset($InfoDict['name.utf-8'])
26
+        ? $InfoDict['name.utf-8']
27
+        : $InfoDict['name']);
28
+      $this->Files[] = array($this->Size, $Name);
29
+    } else {
30
+      if (isset($InfoDict['path.utf-8']['files'][0])) {
31
+        $this->PathKey = 'path.utf-8';
32
+      }
33
+      foreach ($InfoDict['files'] as $File) {
34
+        $TmpPath = array();
35
+        foreach ($File[$this->PathKey] as $SubPath) {
36
+          $TmpPath[] = $SubPath;
37
+        }
38
+        $CurSize = (Int64::is_int($File['length'])
39
+          ? Int64::get($File['length'])
40
+          : $File['length']);
41
+        $this->Files[] = array($CurSize, implode('/', $TmpPath));
42
+        $this->Size += $CurSize;
43
+      }
44
+      uasort($this->Files, function($a, $b) {
45
+          return strnatcasecmp($a[1], $b[1]);
46
+        });
47
+    }
48
+    return array($this->Size, $this->Files);
49
+  }
50 50
 
51
-	/**
52
-	 * Find out the name of the torrent
53
-	 *
54
-	 * @return string torrent name
55
-	 */
56
-	public function get_name() {
57
-		if (empty($this->Dec)) {
58
-			return false;
59
-		}
60
-		if (isset($this->Dec['info']['name.utf-8'])) {
61
-			return $this->Dec['info']['name.utf-8'];
62
-		}
63
-		return $this->Dec['info']['name'];
64
-	}
51
+  /**
52
+   * Find out the name of the torrent
53
+   *
54
+   * @return string torrent name
55
+   */
56
+  public function get_name() {
57
+    if (empty($this->Dec)) {
58
+      return false;
59
+    }
60
+    if (isset($this->Dec['info']['name.utf-8'])) {
61
+      return $this->Dec['info']['name.utf-8'];
62
+    }
63
+    return $this->Dec['info']['name'];
64
+  }
65 65
 
66
-	/**
67
-	 * Find out the total size of the torrent
68
-	 *
69
-	 * @return string torrent size
70
-	 */
71
-	public function get_size() {
72
-		if (empty($this->Files)) {
73
-			if (empty($this->Dec)) {
74
-				return false;
75
-			}
76
-			$FileList = $this->file_list();
77
-		}
78
-		return $FileList[0];
79
-	}
66
+  /**
67
+   * Find out the total size of the torrent
68
+   *
69
+   * @return string torrent size
70
+   */
71
+  public function get_size() {
72
+    if (empty($this->Files)) {
73
+      if (empty($this->Dec)) {
74
+        return false;
75
+      }
76
+      $FileList = $this->file_list();
77
+    }
78
+    return $FileList[0];
79
+  }
80 80
 
81
-	/**
82
-	 * Checks if the "private" flag is present in the torrent
83
-	 *
84
-	 * @return true if the "private" flag is set
85
-	 */
86
-	public function is_private() {
87
-		if (empty($this->Dec)) {
88
-			return false;
89
-		}
90
-		return isset($this->Dec['info']['private']) && Int64::get($this->Dec['info']['private']) == 1;
91
-	}
92
-	/**
93
-	 * Add the "private" flag to the torrent
94
-	 *
95
-	 * @return true if a change was required
96
-	 */
97
-	public function make_private() {
98
-		if (empty($this->Dec)) {
99
-			return false;
100
-		}
101
-		if ($this->is_private()) {
102
-			return false;
103
-		}
104
-		$this->Dec['info']['private'] = Int64::make(1);
105
-		ksort($this->Dec['info']);
106
-		return true;
107
-	}
81
+  /**
82
+   * Checks if the "private" flag is present in the torrent
83
+   *
84
+   * @return true if the "private" flag is set
85
+   */
86
+  public function is_private() {
87
+    if (empty($this->Dec)) {
88
+      return false;
89
+    }
90
+    return isset($this->Dec['info']['private']) && Int64::get($this->Dec['info']['private']) == 1;
91
+  }
92
+  /**
93
+   * Add the "private" flag to the torrent
94
+   *
95
+   * @return true if a change was required
96
+   */
97
+  public function make_private() {
98
+    if (empty($this->Dec)) {
99
+      return false;
100
+    }
101
+    if ($this->is_private()) {
102
+      return false;
103
+    }
104
+    $this->Dec['info']['private'] = Int64::make(1);
105
+    ksort($this->Dec['info']);
106
+    return true;
107
+  }
108 108
 
109
-	/**
110
-	 * Calculate the torrent's info hash
111
-	 *
112
-	 * @return info hash in hexadecimal form
113
-	 */
114
-	public function info_hash() {
115
-		if (empty($this->Dec) || !isset($this->Dec['info'])) {
116
-			return false;
117
-		}
118
-		return sha1($this->encode(false, 'info'));
119
-	}
109
+  /**
110
+   * Calculate the torrent's info hash
111
+   *
112
+   * @return info hash in hexadecimal form
113
+   */
114
+  public function info_hash() {
115
+    if (empty($this->Dec) || !isset($this->Dec['info'])) {
116
+      return false;
117
+    }
118
+    return sha1($this->encode(false, 'info'));
119
+  }
120 120
 
121
-	/**
122
-	 * Add the announce URL to a torrent
123
-	 */
124
-	public static function add_announce_url($Data, $Url) {
125
-		return 'd8:announce'.strlen($Url).':'.$Url . substr($Data, 1);
126
-	}
121
+  /**
122
+   * Add the announce URL to a torrent
123
+   */
124
+  public static function add_announce_url($Data, $Url) {
125
+    return 'd8:announce'.strlen($Url).':'.$Url . substr($Data, 1);
126
+  }
127 127
 
128
-	/**
129
-	 * Let's support announce lists
130
-	 */
131
-	public static function add_announce_list($Data, $Urls) {
132
-		$r = 'd13:announce-listl';
133
-		for ($i = 0; $i < count($Urls); $i++) {
134
-			$r .= 'l';
135
-			for ($j = 0; $j < count($Urls[$i]); $j++) {
136
-				$r .= strlen($Urls[$i][$j]).':'.$Urls[$i][$j];
137
-			}
138
-			$r .= 'e';
139
-		}
140
-		$r .= 'e' .substr($Data, 1);
141
-		return $r;
142
-	}
128
+  /**
129
+   * Let's support announce lists
130
+   */
131
+  public static function add_announce_list($Data, $Urls) {
132
+    $r = 'd13:announce-listl';
133
+    for ($i = 0; $i < count($Urls); $i++) {
134
+      $r .= 'l';
135
+      for ($j = 0; $j < count($Urls[$i]); $j++) {
136
+        $r .= strlen($Urls[$i][$j]).':'.$Urls[$i][$j];
137
+      }
138
+      $r .= 'e';
139
+    }
140
+    $r .= 'e' .substr($Data, 1);
141
+    return $r;
142
+  }
143 143
 }

+ 26
- 26
classes/bitcoinrpc.class.php View File

@@ -1,32 +1,32 @@
1 1
 <?php
2 2
 class BitcoinRpc {
3 3
 
4
-	public static function __callStatic($Method, $Args) {
5
-		if (!defined('BITCOIN_RPC_URL')) {
6
-			return false;
7
-		}
8
-		$MessageID = mt_rand();
9
-		$Params = json_encode(array(
10
-			'method' => $Method,
11
-			'params' => $Args,
12
-			'id' => $MessageID)
13
-		);
4
+  public static function __callStatic($Method, $Args) {
5
+    if (!defined('BITCOIN_RPC_URL')) {
6
+      return false;
7
+    }
8
+    $MessageID = mt_rand();
9
+    $Params = json_encode(array(
10
+      'method' => $Method,
11
+      'params' => $Args,
12
+      'id' => $MessageID)
13
+    );
14 14
 
15
-		$Request = array(
16
-			'http' => array(
17
-				'method' => 'POST',
18
-				'header' => 'Content-type: application/json',
19
-				'content' => $Params
20
-				)
21
-			);
15
+    $Request = array(
16
+      'http' => array(
17
+        'method' => 'POST',
18
+        'header' => 'Content-type: application/json',
19
+        'content' => $Params
20
+        )
21
+      );
22 22
 
23
-		if (!$Response = file_get_contents(BITCOIN_RPC_URL, false, stream_context_create($Request))) {
24
-			return false;
25
-		}
26
-		$Response = json_decode($Response);
27
-		if ($Response->id != $MessageID || !empty($Response->error) || empty($Response->result)) {
28
-			return false;
29
-		}
30
-		return $Response->result;
31
-	}
23
+    if (!$Response = file_get_contents(BITCOIN_RPC_URL, false, stream_context_create($Request))) {
24
+      return false;
25
+    }
26
+    $Response = json_decode($Response);
27
+    if ($Response->id != $MessageID || !empty($Response->error) || empty($Response->result)) {