diff --git a/.gitignore b/.gitignore index 238f7992..bb7db37f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ config.php release/* static/similar +*.swp +*.project +*.php~ diff --git a/classes/class_cache.php b/classes/class_cache.php index aae3b8cb..cd5e8ed1 100644 --- a/classes/class_cache.php +++ b/classes/class_cache.php @@ -38,7 +38,9 @@ class CACHE extends Memcache { 'stats_*', 'percentiles_*', 'top10tor_*', - 'query_lock_*' + 'query_lock_*', + 'top10votes_*', + 'similar_albums_*' ); public $CanClear = false; diff --git a/classes/class_format.php b/classes/class_format.php index 6ce89cd4..db52778c 100644 --- a/classes/class_format.php +++ b/classes/class_format.php @@ -60,24 +60,39 @@ public static function get_ratio_color($Ratio) { * @param int $Dividend AKA numerator * @param int $Divisor * @param boolean $Color if true, ratio will be coloured. - * @return formatted ratio HTML + * @return string formatted ratio HTML */ - public static function get_ratio_html($Dividend, $Divisor, $Color = true) { - if ($Divisor == 0 && $Dividend == 0) { - return '--'; - } elseif ($Divisor == 0) { - return ''; - } - $Ratio = number_format(max($Dividend/$Divisor-0.005,0), 2); //Subtract .005 to floor to 2 decimals - if ($Color) { - $Class = Format::get_ratio_color($Ratio); - if ($Class) { - $Ratio = ''.$Ratio.''; - } - } + public static function get_ratio_html($Dividend, $Divisor, $Color = true) + { + $Ratio = self::get_ratio($Dividend, $Divisor); + + if ($Ratio === false) return '--'; + if ($Ratio === '∞') return ''; + + if ($Color) + $Ratio = sprintf('%s', + self::get_ratio_color($Ratio), + self::get_ratio($Dividend, $Divisor, 5), + $Ratio + ); + return $Ratio; } + /** + * Returns ratio + * @param int $Dividend + * @param int $Divisor + * @return boolean|string|float + */ + public function get_ratio ($Dividend, $Divisor, $Decimal = 2) + { + if ($Divisor == 0 && $Dividend == 0) return false; + if ($Divisor == 0) return '∞'; + +// Subtract .005 to floor to 2 decimals + return number_format(max($Dividend/$Divisor - 0.005, 0), $Decimal); + } /** * Gets the query string of the current page, minus the parameters in $Exclude @@ -192,7 +207,7 @@ public static function get_pages($StartPage,$TotalRecords,$ItemsPerPage,$ShowPag $StartPosition = max($StartPosition, 1); - $QueryString = Format::get_url(array('page','post')); + $QueryString = self::get_url(array('page','post')); if ($QueryString != '') { $QueryString = '&'.$QueryString; } @@ -254,7 +269,7 @@ public static function get_size($Size, $Levels = 2) { if (func_num_args() == 1 && $Steps >= 4) { $Levels++; } - return number_format($Size,$Levels) . $Units[$Steps]; + return number_format($Size, $Levels) . $Units[$Steps]; } @@ -364,7 +379,7 @@ public static function selected($Name, $Value, $Attribute='selected', $Array = a */ public static function make_utf8($Str) { if ($Str!="") { - if (Format::is_utf8($Str)) { $Encoding="UTF-8"; } + if (self::is_utf8($Str)) { $Encoding="UTF-8"; } if (empty($Encoding)) { $Encoding=mb_detect_encoding($Str,'UTF-8, ISO-8859-1'); } if (empty($Encoding)) { $Encoding="ISO-8859-1"; } if ($Encoding=="UTF-8") { return $Str; } @@ -392,5 +407,4 @@ public static function is_utf8($Str) { ); } -} -?> +} \ No newline at end of file diff --git a/classes/class_mass_user_bookmarks_editor.php b/classes/class_mass_user_bookmarks_editor.php new file mode 100644 index 00000000..4bc127af --- /dev/null +++ b/classes/class_mass_user_bookmarks_editor.php @@ -0,0 +1,74 @@ +set_table($Table); + } + + /** + * Runs a SQL query and clears the bookmarks_torrent_{$UserID}_full Cache key + * + * $Cache->delete_value didn't always work, but setting the key to null, did. (?) + * + * @param string $sql + */ + protected function query_and_clear_cache ($sql) + { + if (is_string($sql) && $this->DB->query($sql)) { + $this->Cache->cache_value('bookmarks_torrent_' . $this->UserID, null, 0); + $this->Cache->cache_value('bookmarks_torrent_' . $this->UserID . '_full', null, 0); + } + } + + /** + * Uses (checkboxes) $_POST['remove'] to delete entries. + * + * Uses an IN() to match multiple items in one query. + */ + public function mass_remove () { + $SQL = array(); + foreach ($_POST['remove'] as $GroupID => $K) { + if (is_number($GroupID)) + $SQL[] = sprintf('%d', $GroupID); + } + + if (!empty($SQL)) { + $SQL = sprintf('DELETE FROM %s WHERE UserID = %d AND GroupID IN (%s)', + $this->Table, + $this->UserID, + implode(', ', $SQL) + ); + $this->query_and_clear_cache($SQL); + } + } + + /** + * Uses $_POST['sort'] values to update the DB. + */ + public function mass_update () { + $SQL = array(); + foreach ($_POST['sort'] as $GroupID => $Sort) { + if (is_number($Sort) && is_number($GroupID)) + $SQL[] = sprintf('(%d, %d, %d)', $GroupID, $Sort, $this->UserID); + } + + if (!empty($SQL)) { + $SQL = sprintf('INSERT INTO %s (GroupID, Sort, UserID) VALUES %s + ON DUPLICATE KEY UPDATE Sort = VALUES (Sort)', + $this->Table, + implode(', ', $SQL)); + $this->query_and_clear_cache($SQL); + } + } +} \ No newline at end of file diff --git a/classes/class_mass_user_torrents_editor.php b/classes/class_mass_user_torrents_editor.php new file mode 100644 index 00000000..11da274b --- /dev/null +++ b/classes/class_mass_user_torrents_editor.php @@ -0,0 +1,99 @@ +Cache = $Cache; + $this->DB = $DB; + $this->UserID = (int) $UserID; + if ($this->UserID < 1) error(403); + } + + /** + * Set the Table + * @param string $Table + */ + final public function set_table ($Table) + { + $this->Table = db_string($Table); + } + + /** + * Get the Table + * @param sting $Table + * @return string $Table + */ + final public function get_table () + { + return $this->Table; + } + + /** + * The extending class must provide a method to send a query and clear the cache + */ + abstract protected function query_and_clear_cache ($sql); + + /** + * A method to insert many rows into a single table + * Not required in subsequent classes + */ + public function mass_add () {} + + /** + * A method to remove many rows from a table + * The extending class must have a mass_remove method + */ + abstract public function mass_remove (); + + /** + * A method to update many rows in a table + * The extending class must have a mass_update method + */ + abstract public function mass_update (); +} \ No newline at end of file diff --git a/classes/class_mass_user_torrents_table_view.php b/classes/class_mass_user_torrents_table_view.php new file mode 100644 index 00000000..1f9eaa16 --- /dev/null +++ b/classes/class_mass_user_torrents_table_view.php @@ -0,0 +1,296 @@ +set_heading($Heading); + $this->set_edit_type($EditType); + + $this->UserID = (int) $UserID; + $this->LoggedUser = &$LoggedUser; + + $this->TorrentList = $TorrentList; + $this->CollageDataList = $CollageDataList; + + $this->HasTorrents = !empty($TorrentList); + if(!$this->HasTorrents) $this->no_torrents(); + } + + private function no_torrents () + { +?> +
+
+

No torrents found.

+
+
+

Add some torrents and come back later.

+
+
+header(); + $this->body(); + $this->footer(); + } + + /** + * Renders a comptele page/table header: div#thin, h2, scripts, notes, + * form, table, etc. + */ + public function header () + { + if ($this->HasTorrents) : +?> + +
+
+

Heading)?>

+
+ + + + + + + + + +
Sorting
+
    +
  • Click on the headings to organize columns automatically.
  • +
  • Sort multiple columns simultaneously by holding down the shift key and clicking other column headers.
  • +
  • Click and drag any row to change its order.
  • +
  • Double-click on a row to check it.
  • +
+ +
+ +
+ +buttons(); ?> + + + + + + + + + + + + + + +HasTorrents) : +?> + + +
Order#YearArtistTorrentUserRemove
+ +buttons(); ?> + +
+ + + +
+
+
+ +HasTorrents) + foreach ($this->TorrentList as $GroupID => $Group) { + $Artists = array(); + extract($Group); + extract($this->CollageDataList[$GroupID]); + + $this->NumGroups++; + + $DisplayName = self::display_name($ExtendedArtists, $Artists, $VanityHouse); + $TorrentLink = ''.$Name.''; + $Year = $Year > 0 ? $Year : ''; + + $this->row($Sort, $GroupID, $Year, $DisplayName, $TorrentLink); + } + } + + /** + * Outputs a single row + * + * @param string|int $Sort + * @param string|int $GroupID + * @param string|int $GroupYear + * @param string $DisplayName + * @param string $TorrentLink + */ + public function row ($Sort, $GroupID, $GroupYear, $DisplayName, $TorrentLink) + { + $CSS = $this->NumGroups % 2 === 0 ? 'rowa' : 'rowb'; +?> + + + + + + NumGroups?> + + + + UserID, false, false, false)?> + + + 0) { + $DisplayName = Artists::display_artists(array('1'=>$Artists), true, false); + } + if ($VanityHouse) $DisplayName .= ' [VH]'; + return $DisplayName; + } + + /** + * Renders buttons used at the top and bottom of the table + */ + public function buttons () + { +?> +
+ + +
+EditType = $EditType; + } + + /** + * Set's the current page's heading + * @param string $Heading + */ + public function set_heading ($Heading) + { + $this->Heading = $Heading; + } +} \ No newline at end of file diff --git a/classes/class_misc.php b/classes/class_misc.php index 48877a97..08e23b16 100644 --- a/classes/class_misc.php +++ b/classes/class_misc.php @@ -88,10 +88,19 @@ public static function send_pm($ToID,$FromID,$Subject,$Body,$ConvID='') { list($UnRead) = $DB->next_record(); $Cache->cache_value('inbox_new_'.$ID, $UnRead); } + + $DB->query("SELECT Username FROM users_main WHERE ID = '$FromID'"); + list($SenderName) = $DB->next_record(); + foreach($ToID as $ID) { + $DB->query("SELECT COUNT(ConvID) FROM pm_conversations_users WHERE UnRead = '1' and UserID='$ID' AND InInbox = '1'"); + list($UnRead) = $DB->next_record(); + $Cache->cache_value('inbox_new_'.$ID, $UnRead); + + } return $ConvID; } - + /** * Create thread function, things should already be escaped when sent here. diff --git a/classes/class_text.php b/classes/class_text.php index f3fdcccb..8bab5048 100644 --- a/classes/class_text.php +++ b/classes/class_text.php @@ -12,8 +12,8 @@ class TEXT { ':-|' => 'blank.gif', ':blush:' => 'blush.gif', ':cool:' => 'cool.gif', - ':'(' => 'crying.gif', - ':crying:' => 'crying.gif', + ':'(' => 'crying.gif', + ':crying:' => 'crying.gif', '>.>' => 'eyesright.gif', ':frown:' => 'frown.gif', '<3' => 'heart.gif', @@ -21,7 +21,7 @@ class TEXT { //':\\' => 'hmm.gif', ':whatlove:' => 'ilu.gif', ':lol:' => 'laughing.gif', - ':loveflac:' => 'loveflac.gif', + ':loveflac:' => 'loveflac.gif', ':flaclove:' => 'loveflac.gif', ':ninja:' => 'ninja.gif', ':no:' => 'no.gif', @@ -52,19 +52,62 @@ class TEXT { ':wtf:' => 'wtf.gif', ':wub:' => 'wub.gif', ); - + private $NoImg = 0; // If images should be turned into URLs - private $Levels = 0; // If images should be turned into URLs - function __construct() { + private $Levels = 0; + + /** + * Used to detect and disable parsing (eg TOC) within quotes + * @var int $InQuotes + */ + private $InQuotes = 0; + + /** + * Array of headlines for Table Of Contents (TOC) + * @var array $HeadLines + */ + private $Headlines; + + /** + * Counter for making headline URLs unique + * @var int $HeadLines + */ + private $HeadlineID = 0; + + /** + * Depth + * @var array $HeadlineLevels + */ + private $HeadlineLevels = array('1', '2', '3', '4'); + + /** + * TOC enabler + * @var bool $TOC + */ + private $TOC; + + /** + * @param bool $TOC When used, will enabled TOC + */ + public function __construct ($TOC = false) { + $this->TOC = (bool) $TOC; foreach($this->Smileys as $Key=>$Val) { $this->Smileys[$Key] = ''; } reset($this->Smileys); } - - function full_format($Str) { + + /** + * Output BB Code as xHTML + * @param string $Str BBCode text + * @param bool $OutputTOC Ouput TOC near (above) text + * @param int $Min See {@link parse_toc} + * @return string + */ + public function full_format ($Str, $OutputTOC = true, $Min = 3) { $Str = display_str($Str); + $this->Headlines = array(); //Inline links $URLPrefix = '(\[url\]|\[url\=|\[img\=|\[img\])'; @@ -74,34 +117,45 @@ function full_format($Str) { $callback = create_function('$matches', 'return str_replace("[inlineurl]","",$matches[0]);'); $Str = preg_replace_callback('/(?<=\[inlineurl\]|'.$URLPrefix.')(\S*\[inlineurl\]\S*)/m', $callback, $Str); - $Str = preg_replace('/\=\=\=\=([^=].*)\=\=\=\=/i', '[inlinesize=3]$1[/inlinesize]', $Str); - $Str = preg_replace('/\=\=\=([^=].*)\=\=\=/i', '[inlinesize=5]$1[/inlinesize]', $Str); - $Str = preg_replace('/\=\=([^=].*)\=\=/i', '[inlinesize=7]$1[/inlinesize]', $Str); - + if ($this->TOC) { + $Str = preg_replace('/(\={5})([^=].*)\1/i', '[headline=4]$2[/headline]', $Str); + $Str = preg_replace('/(\={4})([^=].*)\1/i', '[headline=3]$2[/headline]', $Str); + $Str = preg_replace('/(\={3})([^=].*)\1/i', '[headline=2]$2[/headline]', $Str); + $Str = preg_replace('/(\={2})([^=].*)\1/i', '[headline=1]$2[/headline]', $Str); + } else { + $Str = preg_replace('/(\={4})([^=].*)\1/i', '[inlinesize=3]$2[/inlinesize]', $Str); + $Str = preg_replace('/(\={3})([^=].*)\1/i', '[inlinesize=5]$2[/inlinesize]', $Str); + $Str = preg_replace('/(\={2})([^=].*)\1/i', '[inlinesize=7]$2[/inlinesize]', $Str); + } + $Str = $this->parse($Str); - + $HTML = $this->to_html($Str); - + $HTML = nl2br($HTML); + + if ($this->TOC && $OutputTOC) + $HTML = $this->parse_toc($Min) . $HTML; + return $HTML; } - - function strip_bbcode($Str) { + + public function strip_bbcode ($Str) { $Str = display_str($Str); - + //Inline links $Str = preg_replace('/(?parse($Str); - + $Str = $this->raw_text($Str); - + $Str = nl2br($Str); return $Str; } - - - function valid_url($Str, $Extension = '', $Inline = false) { + + + private function valid_url ($Str, $Extension = '', $Inline = false) { $Regex = '/^'; $Regex .= '(https?|ftps?|irc):\/\/'; // protocol $Regex .= '(\w+(:\w+)?@)?'; // user:pass@ @@ -125,11 +179,11 @@ function valid_url($Str, $Extension = '', $Inline = false) { $Regex .= '(#[a-z0-9\-_.,%\/\@[\]~&=:;()+*\^$!]*)?'; // #anchor $Regex .= '$/i'; - + return preg_match($Regex, $Str, $Matches); } - - function local_url($Str) { + + public function local_url ($Str) { $URLInfo = parse_url($Str); if(!$URLInfo) { return false; } $Host = $URLInfo['host']; @@ -147,48 +201,49 @@ function local_url($Str) { } else { return false; } - + } - - -/* How parsing works -Parsing takes $Str, breaks it into blocks, and builds it into $Array. -Blocks start at the beginning of $Str, when the parser encounters a [, and after a tag has been closed. -This is all done in a loop. -EXPLANATION OF PARSER LOGIC + /* + How parsing works -1) Find the next tag (regex) - 1a) If there aren't any tags left, write everything remaining to a block and return (done parsing) - 1b) If the next tag isn't where the pointer is, write everything up to there to a text block. -2) See if it's a [[wiki-link]] or an ordinary tag, and get the tag name -3) If it's not a wiki link: - 3a) check it against the $this->ValidTags array to see if it's actually a tag and not [bullshit] - If it's [not a tag], just leave it as plaintext and move on - 3b) Get the attribute, if it exists [name=attribute] -4) Move the pointer past the end of the tag -5) Find out where the tag closes (beginning of [/tag]) - 5a) Different for different types of tag. Some tags don't close, others are weird like [*] - 5b) If it's a normal tag, it may have versions of itself nested inside - eg: - [quote=bob]* - [quote=joe]I am a redneck!**[/quote] - Me too! - ***[/quote] - If we're at the position *, the first [/quote] tag is denoted by **. - However, our quote tag doesn't actually close there. We must perform - a loop which checks the number of opening [quote] tags, and make sure - they are all closed before we find our final [/quote] tag (***). + Parsing takes $Str, breaks it into blocks, and builds it into $Array. + Blocks start at the beginning of $Str, when the parser encounters a [, and after a tag has been closed. + This is all done in a loop. - 5c) Get the contents between [open] and [/close] and call it the block. - In many cases, this will be parsed itself later on, in a new parse() call. - 5d) Move the pointer past the end of the [/close] tag. -6) Depending on what type of tag we're dealing with, create an array with the attribute and block. - In many cases, the block may be parsed here itself. Stick them in the $Array. -7) Increment array pointer, start again (past the end of the [/close] tag) + EXPLANATION OF PARSER LOGIC -*/ - function parse($Str) { + 1) Find the next tag (regex) + 1a) If there aren't any tags left, write everything remaining to a block and return (done parsing) + 1b) If the next tag isn't where the pointer is, write everything up to there to a text block. + 2) See if it's a [[wiki-link]] or an ordinary tag, and get the tag name + 3) If it's not a wiki link: + 3a) check it against the $this->ValidTags array to see if it's actually a tag and not [bullshit] + If it's [not a tag], just leave it as plaintext and move on + 3b) Get the attribute, if it exists [name=attribute] + 4) Move the pointer past the end of the tag + 5) Find out where the tag closes (beginning of [/tag]) + 5a) Different for different types of tag. Some tags don't close, others are weird like [*] + 5b) If it's a normal tag, it may have versions of itself nested inside - eg: + [quote=bob]* + [quote=joe]I am a redneck!**[/quote] + Me too! + ***[/quote] + If we're at the position *, the first [/quote] tag is denoted by **. + However, our quote tag doesn't actually close there. We must perform + a loop which checks the number of opening [quote] tags, and make sure + they are all closed before we find our final [/quote] tag (***). + + 5c) Get the contents between [open] and [/close] and call it the block. + In many cases, this will be parsed itself later on, in a new parse() call. + 5d) Move the pointer past the end of the [/close] tag. + 6) Depending on what type of tag we're dealing with, create an array with the attribute and block. + In many cases, the block may be parsed here itself. Stick them in the $Array. + 7) Increment array pointer, start again (past the end of the [/close] tag) + + */ + private function parse ($Str) { $i = 0; // Pointer to keep track of where we are in $Str $Len = strlen($Str); $Array = array(); @@ -196,18 +251,18 @@ function parse($Str) { while($i<$Len) { $Block = ''; - + // 1) Find the next tag (regex) // [name(=attribute)?]|[[wiki-link]] $IsTag = preg_match("/((\[[a-zA-Z*#]+)(=(?:[^\n'\"\[\]]|\[\d*\])+)?\])|(\[\[[^\n\"'\[\]]+\]\])/", $Str, $Tag, PREG_OFFSET_CAPTURE, $i); - + // 1a) If there aren't any tags left, write everything remaining to a block if(!$IsTag) { // No more tags $Array[$ArrayPos] = substr($Str, $i); break; } - + // 1b) If the next tag isn't where the pointer is, write everything up to there to a text block. $TagPos = $Tag[0][1]; if($TagPos>$i) { @@ -215,7 +270,7 @@ function parse($Str) { ++$ArrayPos; $i=$TagPos; } - + // 2) See if it's a [[wiki-link]] or an ordinary tag, and get the tag name if(!empty($Tag[4][0])) { // Wiki-link $WikiLink = true; @@ -224,7 +279,7 @@ function parse($Str) { } else { // 3) If it's not a wiki link: $WikiLink = false; $TagName = strtolower(substr($Tag[2][0], 1)); - + //3a) check it against the $this->ValidTags array to see if it's actually a tag and not [bullshit] if(!isset($this->ValidTags[$TagName])) { $Array[$ArrayPos] = substr($Str, $i, ($TagPos-$i)+strlen($Tag[0][0])); @@ -232,9 +287,9 @@ function parse($Str) { ++$ArrayPos; continue; } - + $MaxAttribs = $this->ValidTags[$TagName]; - + // 3b) Get the attribute, if it exists [name=attribute] if(!empty($Tag[3][0])) { $Attrib = substr($Tag[3][0], 1); @@ -242,23 +297,23 @@ function parse($Str) { $Attrib=''; } } - + // 4) Move the pointer past the end of the tag $i=$TagPos+strlen($Tag[0][0]); - + // 5) Find out where the tag closes (beginning of [/tag]) - + // Unfortunately, BBCode doesn't have nice standards like xhtml // [*], [img=...], and http:// follow different formats // Thus, we have to handle these before we handle the majority of tags - - + + //5a) Different for different types of tag. Some tags don't close, others are weird like [*] if($TagName == 'img' && !empty($Tag[3][0])) { //[img=...] $Block = ''; // Nothing inside this tag // Don't need to touch $i } elseif($TagName == 'inlineurl') { // We did a big replace early on to turn http:// into [inlineurl]http:// - + // Let's say the block can stop at a newline or a space $CloseTag = strcspn($Str, " \n\r", $i); if($CloseTag === false) { // block finishes with URL @@ -273,11 +328,11 @@ function parse($Str) { $URL = substr($URL, 0, -1); } $Block = $URL; // Get the URL - + // strcspn returns the number of characters after the offset $i, not after the beginning of the string // Therefore, we use += instead of the = everywhere else - $i += $CloseTag; // 5d) Move the pointer past the end of the [/close] tag. - } elseif($WikiLink == true || $TagName == 'n') { + $i += $CloseTag; // 5d) Move the pointer past the end of the [/close] tag. + } elseif($WikiLink == true || $TagName == 'n') { // Don't need to do anything - empty tag with no closing } elseif($TagName === '*' || $TagName === '#') { // We're in a list. Find where it ends @@ -285,28 +340,28 @@ function parse($Str) { do { // Look for \n[*] $NewLine = strpos($Str, "\n", $NewLine+1); } while($NewLine!== false && substr($Str, $NewLine+1, 3) == '['.$TagName.']'); - + $CloseTag = $NewLine; if($CloseTag === false) { // block finishes with list $CloseTag = $Len; } $Block = substr($Str, $i, $CloseTag-$i); // Get the list - $i = $CloseTag; // 5d) Move the pointer past the end of the [/close] tag. + $i = $CloseTag; // 5d) Move the pointer past the end of the [/close] tag. } else { //5b) If it's a normal tag, it may have versions of itself nested inside $CloseTag = $i-1; $InTagPos = $i-1; $NumInOpens = 0; $NumInCloses = -1; - + $InOpenRegex = '/\[('.$TagName.')'; if($MaxAttribs>0) { $InOpenRegex.="(=[^\n'\"\[\]]+)?"; } $InOpenRegex.='\]/i'; - - - // Every time we find an internal open tag of the same type, search for the next close tag + + + // Every time we find an internal open tag of the same type, search for the next close tag // (as the first close tag won't do - it's been opened again) do { $CloseTag = stripos($Str, '[/'.$TagName.']', $CloseTag+1); @@ -316,7 +371,7 @@ function parse($Str) { } else { $NumInCloses++; // Majority of cases } - + // Is there another open tag inside this one? $OpenTag = preg_match($InOpenRegex, $Str, $InTag, PREG_OFFSET_CAPTURE, $InTagPos+1); if(!$OpenTag || $InTag[0][1]>$CloseTag) { @@ -325,17 +380,17 @@ function parse($Str) { $InTagPos = $InTag[0][1]; $NumInOpens++; } - + } while($NumInOpens>$NumInCloses); - - + + // Find the internal block inside the tag $Block = substr($Str, $i, $CloseTag-$i); // 5c) Get the contents between [open] and [/close] and call it the block. - - $i = $CloseTag+strlen($TagName)+3; // 5d) Move the pointer past the end of the [/close] tag. - + + $i = $CloseTag+strlen($TagName)+3; // 5d) Move the pointer past the end of the [/close] tag. + } - + // 6) Depending on what type of tag we're dealing with, create an array with the attribute and block. switch($TagName) { case 'inlineurl': @@ -386,10 +441,23 @@ function parse($Str) { case 'code': case 'plain': $Block = strtr($Block, array('[inlineurl]'=>'')); + + $Callback = function ($matches) { + $n = $matches[2]; + $text = ''; + if ($n < 5 && $n > 0) { + $e = str_repeat('=', $matches[2]+1); + $text = $e . $matches[3] . $e; + } + return $text; + }; + $Block = preg_replace_callback('/\[(headline)\=(\d)\](.*?)\[\/\1\]/i', $Callback, $Block); + $Block = preg_replace('/\[inlinesize\=3\](.*?)\[\/inlinesize\]/i', '====$1====', $Block); $Block = preg_replace('/\[inlinesize\=5\](.*?)\[\/inlinesize\]/i', '===$1===', $Block); $Block = preg_replace('/\[inlinesize\=7\](.*?)\[\/inlinesize\]/i', '==$1==', $Block); - + + $Array[$ArrayPos] = array('Type'=>$TagName, 'Val'=>$Block); break; case 'hide': @@ -411,28 +479,92 @@ function parse($Str) { default: if($WikiLink == true) { $Array[$ArrayPos] = array('Type'=>'wiki','Val'=>$TagName); - } else { - + } else { + // Basic tags, like [b] or [size=5] - + $Array[$ArrayPos] = array('Type'=>$TagName, 'Val'=>$this->parse($Block)); if(!empty($Attrib) && $MaxAttribs>0) { $Array[$ArrayPos]['Attr'] = strtolower($Attrib); } } } - + $ArrayPos++; // 7) Increment array pointer, start again (past the end of the [/close] tag) } return $Array; } - - function to_html($Array) { + + /** + * Generates a navigation list for TOC + * @param int $Min Minimum number of headlines required for a TOC list + */ + public function parse_toc ($Min = 3) + { + if (count($this->Headlines) > $Min) { + $list = '', $level); + $list .= "\n\n"; + return $list; + } + } + + /** + * Generates the list items and proper depth + * + * First check if the item should be higher than the current level + * - Close the list and previous lists + * + * Then check if the item should go lower than the current level + * - If the list doesn't open on level one, use the Offset + * - Open appropriate sub lists + * + * Otherwise the item is on the same as level as the previous item + * + * @param int $ItemLevel Current item level + * @param int $Level Current list level + * @param str $List reference to an xHTML string + * @param int $i Iterator digit + * @param int $Offset If the list doesn't start at level 1 + */ + private function headline_level (&$ItemLevel, &$Level, &$List, $i, &$Offset) + { + if ($ItemLevel < $Level) { + $diff = $Level - $ItemLevel; + $List .= '' . str_repeat('', $diff); + } elseif ($ItemLevel > $Level) { + $diff = $ItemLevel - $Level; + if ($Offset > 0) $List .= str_repeat('
    1. ', $Offset-2); + + if ($ItemLevel > 1) { + $List .= $i === 0 ? '
    2. ' : ''; + $List .= "\n" . '
        ' . "\n"; + } + } else { + $List .= $i > 0 ? '' : '
      1. '; + } + } + + private function to_html ($Array) { global $SSL; $this->Levels++; if($this->Levels>10) { return $Block['Val']; } // Hax prevention $Str = ''; - + foreach($Array as $Block) { if(is_string($Block)) { $Str.=$this->smileys($Block); @@ -502,7 +634,7 @@ function to_html($Array) { case 'list': $Str .= '<'.$Block['ListType'].'>'; foreach($Block['Val'] as $Line) { - + $Str.='
      2. '.$this->to_html($Line).'
      3. '; } $Str.=''; @@ -518,12 +650,24 @@ function to_html($Array) { case 'color': case 'colour': $ValidAttribs = array('aqua', 'black', 'blue', 'fuchsia', 'green', 'grey', 'lime', 'maroon', 'navy', 'olive', 'purple', 'red', 'silver', 'teal', 'white', 'yellow'); - if(!in_array($Block['Attr'], $ValidAttribs) && !preg_match('/^#[0-9a-f]{6}$/', $Block['Attr'])) { + if(!in_array($Block['Attr'], $ValidAttribs) && !preg_match('/^#[0-9a-f]{6}$/', $Block['Attr'])) { $Str.='[color='.$Block['Attr'].']'.$this->to_html($Block['Val']).'[/color]'; } else { $Str.=''.$this->to_html($Block['Val']).''; } break; + case 'headline': + $text = $this->to_html($Block['Val']); + if(!in_array($Block['Attr'], $this->HeadlineLevels)) { + $Str .= sprintf('%1$s%2$s%1$s', str_repeat('=', $Block['Attr'] + 1), $text); + } else { + $id = '_' . crc32($text . $this->HeadlineID); + if ($this->InQuotes === 0) $this->Headlines[] = array($Block['Attr'], $text, $id); + + $Str .= sprintf('%2$s', ($Block['Attr']+2), $text, $id); + $this->HeadlineID++; + } + break; case 'inlinesize': case 'size': $ValidAttribs = array('1','2','3','4','5','6','7','8','9','10'); @@ -535,6 +679,7 @@ function to_html($Array) { break; case 'quote': $this->NoImg++; // No images inside quote tags + $this->InQuotes++; if(!empty($Block['Attr'])) { $Exploded = explode("|", $this->to_html($Block['Attr'])); if(isset($Exploded[1]) && is_numeric($Exploded[1])) { @@ -547,6 +692,7 @@ function to_html($Array) { } $Str.='
        '.$this->to_html($Block['Val']).'
        '; $this->NoImg--; + $this->InQuotes--; break; case 'hide': $Str.=''.(($Block['Attr']) ? $Block['Attr'] : 'Hidden text').': Show'; @@ -570,7 +716,7 @@ function to_html($Array) { } } break; - + case 'aud': if($this->NoImg>0 && $this->valid_url($Block['Val'])) { $Str.=''.$Block['Val'].' (audio)'; @@ -583,7 +729,7 @@ function to_html($Array) { $Str.=''; } break; - + case 'url': // Make sure the URL has a label if(empty($Block['Val'])) { @@ -593,7 +739,7 @@ function to_html($Array) { $Block['Val'] = $this->to_html($Block['Val']); $NoName = false; } - + if(!$this->valid_url($Block['Attr'])) { $Str.='[url='.$Block['Attr'].']'.$Block['Val'].'[/url]'; } else { @@ -606,23 +752,23 @@ function to_html($Array) { } } break; - + case 'inlineurl': if(!$this->valid_url($Block['Attr'], '', true)) { $Array = $this->parse($Block['Attr']); $Block['Attr'] = $Array; $Str.=$this->to_html($Block['Attr']); } - + else { $LocalURL = $this->local_url($Block['Attr']); if($LocalURL) { $Str.=''.substr($LocalURL,1).''; } else { $Str.=''.$Block['Attr'].''; - } + } } - + break; } @@ -630,8 +776,8 @@ function to_html($Array) { $this->Levels--; return $Str; } - - function raw_text($Array) { + + private function raw_text ($Array) { $Str = ''; foreach($Array as $Block) { if(is_string($Block)) { @@ -639,7 +785,8 @@ function raw_text($Array) { continue; } switch($Block['Type']) { - + case 'headline': + break; case 'b': case 'u': case 'i': @@ -667,7 +814,7 @@ function raw_text($Array) { $Str.=$Block['Tag'].$this->raw_text($Line); } break; - + case 'url': // Make sure the URL has a label if(empty($Block['Val'])) { @@ -675,10 +822,10 @@ function raw_text($Array) { } else { $Block['Val'] = $this->raw_text($Block['Val']); } - + $Str.=$Block['Val']; break; - + case 'inlineurl': if(!$this->valid_url($Block['Attr'], '', true)) { $Array = $this->parse($Block['Attr']); @@ -688,14 +835,14 @@ function raw_text($Array) { else { $Str.=$Block['Attr']; } - + break; } } return $Str; } - - function smileys($Str) { + + private function smileys ($Str) { global $LoggedUser; if(!empty($LoggedUser['DisableSmileys'])) { return $Str; @@ -706,18 +853,17 @@ function smileys($Str) { } /* -//Uncomment this part to test the class via command line: +//Uncomment this part to test the class via command line: function display_str($Str) {return $Str;} function check_perms($Perm) {return true;} -$Str = "hello +$Str = "hello [pre]http://anonym.to/?http://whatshirts.portmerch.com/ ====hi==== ===hi=== ==hi==[/pre] ====hi==== hi"; -$Text = NEW TEXT; +$Text = new TEXT; echo $Text->full_format($Str); echo "\n" */ -?> diff --git a/classes/class_textarea_preview.php b/classes/class_textarea_preview.php new file mode 100644 index 00000000..63865d63 --- /dev/null +++ b/classes/class_textarea_preview.php @@ -0,0 +1,199 @@ + + * @return void + */ + static public function JavaScript ($all = true) + { + if (self::$Textareas === 0) return; + if (self::$Exectuted === false && $all) + View::parse('generic/textarea/script.phtml'); + + self::$Exectuted = true; + self::iterator(); + } + + /** + * This iterator generates JavaScript to initialize each JavaScript + * TextareaPreview object. + * + * It will generate a numeric or custom ID related to the textarea. + * @static + * @return void + */ + static private function iterator () + { + $script = array(); + for($i = 0; $i < self::$Textareas; $i++) { + if (isset(self::$_ID[$i]) && is_string(self::$_ID[$i])) { + $a = sprintf('%d, "%s"', $i, self::$_ID[$i]); + } else { + $a = $i; + } + $script[] = sprintf('[%s]', $a); + } + if (!empty($script)) + View::parse('generic/textarea/script_factory.phtml', + array('script' => join(', ', $script))); + } +} + +/** + * Textarea Preview Class + * + * This class generates a textarea that works with the JS preview script. + * + * Templates found in design/views/generic/textarea + * + * @example
        buttons(); // output buttons
        + *
        + *  $text->preview(); // output preview div
        + *
        + * // Create a textarea with custom preview wrapper around a table
        + * // the table will be (in)visible depending on the toggle
        + * $text = new TEXTAREA_PREVIEW('body', '', '', 30, 10, false, false);
        + * $id = $text->getID();
        + *
        + * // some template
        + * 
        + * + * + * + * + *
        + *
        + *
        + *
        + *
        + */ +class TEXTAREA_PREVIEW extends TEXTAREA_PREVIEW_SUPER +{ + /** + * @var int Unique ID + */ + private $id; + + /** + * Flag for preview output + * @var bool $preview + */ + private $preview = false; + + /** + * This method creates a textarea + * + * @param string $Name name attribute + * @param string $ID id attribute + * @param string $Value default text attribute + * @param string $Cols cols attribute + * @param string $Rows rows attribute + * @param bool $Preview add the preview divs near the textarea + * @param bool $Buttons add the edit/preview buttons near the textarea + * + * If false for either, use the appropriate methods to add the those + * elements elsewhere. Alternatively, use getID to create your own. + * + * @param array $ExtraAttributes array of attribute="value" + */ + public function __construct ($Name, $ID = '', $Value='', $Cols=50, $Rows=10, + $Preview = true, $Buttons = true, array $ExtraAttributes = array() + ) { + $this->id = parent::$Textareas; + parent::$Textareas += 1; + array_push(parent::$_ID, $ID); + + if (empty($ID)) $ID = 'quickpost_' . $this->id; + + if (!empty($ExtraAttributes)) + $Attributes = ' ' . implode(' ', $ExtraAttributes); + else + $Attributes = ''; + + if ($Preview === true) $this->preview(); + + View::parse('generic/textarea/textarea.phtml', array( + 'ID' => $ID, + 'NID' => $this->id, + 'Name' => &$Name, + 'Value' => &$Value, + 'Cols' => &$Cols, + 'Rows' => &$Rows, + 'Attributes' => &$Attributes + )); + + if ($Buttons === true) $this->buttons(); + } + + /** + * Outputs the divs required for previewing the AJAX content + * Will only output once + */ + public function preview () + { + if (!$this->preview) + View::parse('generic/textarea/preview.phtml', array('ID' => $this->id)); + $this->preview = true; + } + + /** + * Outputs the preview and edit buttons + * Can be called many times to place buttons in different areas + */ + public function buttons () + { + View::parse('generic/textarea/buttons.phtml', array('ID' => $this->id)); + } + + /** + * Returns the textarea's numeric ID. + */ + public function getID () + { + return $this->id; + } +} \ No newline at end of file diff --git a/classes/class_torrent_form.php b/classes/class_torrent_form.php index 547a4213..2e5fbf51 100644 --- a/classes/class_torrent_form.php +++ b/classes/class_torrent_form.php @@ -11,7 +11,7 @@ ** When it is called from the edit page, the forms are shortened quite a bit. ** ** ** ********************************************************************************/ - + class TORRENT_FORM { var $Categories = array(); var $Formats = array(); @@ -23,21 +23,21 @@ class TORRENT_FORM { var $TorrentID = false; var $Disabled = ''; var $DisabledFlag = false; - + function TORRENT_FORM($Torrent = false, $Error = false, $NewTorrent = true) { - + $this->NewTorrent = $NewTorrent; $this->Torrent = $Torrent; $this->Error = $Error; - + global $Categories, $Formats, $Bitrates, $Media, $TorrentID; - + $this->Categories = $Categories; $this->Formats = $Formats; $this->Bitrates = $Bitrates; $this->Media = $Media; $this->TorrentID = $TorrentID; - + if($this->Torrent && $this->Torrent['GroupID']) { $this->Disabled = ' disabled="disabled"'; $this->DisabledFlag = true; @@ -71,7 +71,7 @@ function head() { if($this->Torrent && $this->Torrent['GroupID']) { ?> -Torrent && $this->Torrent['RequestID']) { ?> "; echo $Cat; echo "\n"; - } + } ?> @@ -109,12 +109,12 @@ function head() {
        Torrent; ?>
        - + NewTorrent) { if(check_perms('torrents_freeleech')) { @@ -124,14 +124,14 @@ function foot() { @@ -450,7 +477,7 @@ function compare($X, $Y){ //----------------- End building list and getting stats -View::show_header($Name, 'browse,requests,bbcode'); +View::show_header($Name, 'browse,requests,bbcode,comments'); ?>
        @@ -879,6 +906,174 @@ function require(file, callback) {
        Artist info
        full_format($Body)?>
        +get_value('artist_comments_'.$ArtistID); +if($Results === false) { + $DB->query("SELECT + COUNT(c.ID) + FROM artist_comments as c + WHERE c.ArtistID = '$ArtistID'"); + list($Results) = $DB->next_record(); + $Cache->cache_value('artist_comments_'.$ArtistID, $Results, 0); +} + +if(isset($_GET['postid']) && is_number($_GET['postid']) && $Results > TORRENT_COMMENTS_PER_PAGE) { + $DB->query("SELECT COUNT(ID) FROM artist_comments WHERE ArtistID = $ArtistID AND ID <= $_GET[postid]"); + list($PostNum) = $DB->next_record(); + list($Page,$Limit) = Format::page_limit(TORRENT_COMMENTS_PER_PAGE,$PostNum); +} else { + list($Page,$Limit) = Format::page_limit(TORRENT_COMMENTS_PER_PAGE,$Results); +} + +//Get the cache catalogue +$CatalogueID = floor((TORRENT_COMMENTS_PER_PAGE*$Page-TORRENT_COMMENTS_PER_PAGE)/THREAD_CATALOGUE); +$CatalogueLimit=$CatalogueID*THREAD_CATALOGUE . ', ' . THREAD_CATALOGUE; + +//---------- Get some data to start processing + +// Cache catalogue from which the page is selected, allows block caches and future ability to specify posts per page +$Catalogue = $Cache->get_value('artist_comments_'.$ArtistID.'_catalogue_'.$CatalogueID); +if($Catalogue === false) { + $DB->query("SELECT + c.ID, + c.AuthorID, + c.AddedTime, + c.Body, + c.EditedUserID, + c.EditedTime, + u.Username + FROM artist_comments as c + LEFT JOIN users_main AS u ON u.ID=c.EditedUserID + WHERE c.ArtistID = '$ArtistID' + ORDER BY c.ID + LIMIT $CatalogueLimit"); + $Catalogue = $DB->to_array(false,MYSQLI_ASSOC); + $Cache->cache_value('artist_comments_'.$ArtistID.'_catalogue_'.$CatalogueID, $Catalogue, 0); +} + +//This is a hybrid to reduce the catalogue down to the page elements: We use the page limit % catalogue +$Thread = array_slice($Catalogue,((TORRENT_COMMENTS_PER_PAGE*$Page-TORRENT_COMMENTS_PER_PAGE)%THREAD_CATALOGUE),TORRENT_COMMENTS_PER_PAGE,true); +?> + + $Post){ + list($PostID, $AuthorID, $AddedTime, $Body, $EditedUserID, $EditedTime, $EditedUsername) = array_values($Post); + list($AuthorID, $Username, $PermissionID, $Paranoia, $Artist, $Donor, $Warned, $Avatar, $Enabled, $UserTitle) = array_values(Users::user_info($AuthorID)); +?> +
        - because + because @@ -154,34 +154,34 @@ function foot() { Torrent; $IsRemaster = !empty($Torrent['Remastered']); $UnknownRelease = !$this->NewTorrent && $IsRemaster && !$Torrent['RemasterYear']; - + if($Torrent['GroupID']) { global $DB; $DB->query("SELECT ID, RemasterYear, - RemasterTitle, - RemasterRecordLabel, - RemasterCatalogueNumber - FROM torrents - WHERE GroupID = ".$Torrent['GroupID']." - AND Remastered = '1' + RemasterTitle, + RemasterRecordLabel, + RemasterCatalogueNumber + FROM torrents + WHERE GroupID = ".$Torrent['GroupID']." + AND Remastered = '1' AND RemasterYear != 0 - ORDER BY RemasterYear DESC, - RemasterTitle DESC, - RemasterRecordLabel DESC, + ORDER BY RemasterYear DESC, + RemasterTitle DESC, + RemasterRecordLabel DESC, RemasterCatalogueNumber DESC"); - + if($DB->record_count() > 0) { $GroupRemasters = $DB->to_array(false, MYSQLI_BOTH, false); } } - + global $DB; $HasLog = $Torrent['HasLog']; $HasCue = $Torrent['HasCue']; @@ -196,7 +196,7 @@ function music_form($GenreTags) { NewTorrent) { ?> - + @@ -325,7 +325,7 @@ function show() { />
        Title: /> @@ -385,7 +385,7 @@ function show() {

        This is for the catalogue number of the release.

        - + @@ -532,7 +532,7 @@ function show() { @@ -573,7 +573,7 @@ function show() { -NewTorrent) { ?> +NewTorrent) { ?> @@ -611,26 +611,31 @@ function show() { - +
        Artist(s)Artist(s) >DJ / Compiler -DisabledFlag) { ?> [+] [-] Remixer - [+] [-] + [+] [-] +?>
        Scene @@ -405,7 +405,7 @@ function show() { echo $Format; echo "\n"; // - } + } ?> @@ -425,13 +425,13 @@ function show() { } else { $OtherBitrate = false; } - + // See if they're the same bitrate - // We have to do this screwery because '(' is a regex character. + // We have to do this screwery because '(' is a regex character. $SimpleBitrate = explode(' ', $Torrent['Bitrate']); $SimpleBitrate = $SimpleBitrate[0]; - - + + foreach(Misc::display_array($this->Bitrates) as $Bitrate) { echo "\n"; - } + } ?> @@ -502,7 +502,7 @@ function show() { list($LogID) = $DB->next_record(); if ($LogID) { if (!check_perms('users_mod')) { -?> +?>
        Trumpable @@ -517,7 +517,7 @@ function show() { NewTorrent && check_perms('users_mod')) {?>
        Log Adjustment Reason -

        Contains reason for adjusting a score. This field is displayed on the torrent page.

        +

        Contains reason for adjusting a score. This field is displayed on the torrent page.

        Tags @@ -584,20 +584,20 @@ function show() { - + Disabled?>/>
        - Tags should be comma separated, and you should use a period ('.') to separate words inside a tag - eg. 'hip.hop'. + Tags should be comma separated, and you should use a period ('.') to separate words inside a tag - eg. 'hip.hop'.

        There is a list of official tags to the left of the text box. Please use these tags instead of 'unofficial' tags (e.g. use the official 'drum.and.bass' tag, instead of an unofficial 'dnb' tag). Please note that the '2000s' tag refers to music produced between 2000 and 2009.

        - Avoid abbreviations if at all possible. So instead of tagging an album as 'alt', tag it as 'alternative'. Make sure that you use correct spelling. + Avoid abbreviations if at all possible. So instead of tagging an album as 'alt', tag it as 'alternative'. Make sure that you use correct spelling.

        - Avoid using multiple synonymous tags. Using both 'prog.rock' and 'progressive.rock' is redundant and annoying - just use the official 'progressive.rock' tag. + Avoid using multiple synonymous tags. Using both 'prog.rock' and 'progressive.rock' is redundant and annoying - just use the official 'progressive.rock' tag.

        - Don't use 'useless' tags, such as 'seen.live', 'awesome', 'rap' (is encompassed by 'hip.hop'), etc. If an album is live, you can tag it as 'live'. + Don't use 'useless' tags, such as 'seen.live', 'awesome', 'rap' (is encompassed by 'hip.hop'), etc. If an album is live, you can tag it as 'live'.

        - Only tag information on the album itself - NOT THE INDIVIDUAL RELEASE. Tags such as 'v0', 'eac', 'vinyl', 'from.oink' etc. are strictly forbidden. Remember that these tags will be used for other versions of the same album. + Only tag information on the album itself - NOT THE INDIVIDUAL RELEASE. Tags such as 'v0', 'eac', 'vinyl', 'from.oink' etc. are strictly forbidden. Remember that these tags will be used for other versions of the same album.

        You should be able to build up a list of tags using only the official tags to the left of the text box. If you are in any doubt about whether or not a tag is acceptable, do not add it.
        Album Description - -

        Contains background information such as album history and maybe a review.

        +Disabled)); ?> +

        Contains background information such as album history and maybe a review.

        Release Description (optional) - +

        Contains information like encoder settings or details of the ripping process. DO NOT PASTE THE RIPPING LOG HERE.

        Torrent; ?> @@ -690,7 +695,7 @@ function audiobook_form() { echo $Bitrate; echo "\n"; } -?> +?> -NewTorrent) { ?> +NewTorrent) { ?> @@ -722,23 +727,21 @@ function audiobook_form() {
        Tags @@ -714,7 +719,7 @@ function audiobook_form() {
        Description - +

        Contains information like the track listing, a review, a link to Discogs or MusicBrainz, etc.

        Release Description (optional) - +

        Contains information like encoder settings. For analog rips, this frequently contains lineage information.

        Torrent; + $Torrent = $this->Torrent; ?> -NewTorrent) { +NewTorrent) { if ($this->Categories[$CategoryID] == 'E-Books') { ?> @@ -763,7 +766,10 @@ function simple_form($CategoryID) { diff --git a/classes/class_torrents.php b/classes/class_torrents.php index dd14c1b4..7d2ddd32 100644 --- a/classes/class_torrents.php +++ b/classes/class_torrents.php @@ -35,7 +35,13 @@ class Torrents { */ public static function get_groups($GroupIDs, $Return = true, $GetArtists = true, $Torrents = true) { global $DB, $Cache; - + + // Make sure there's something in $GroupIDs, otherwise the SQL + // will break + if (count($GroupIDs) == 0) { + return array('matches'=>array(),'notfound'=>array()); + } + $Found = array_flip($GroupIDs); $NotFound = array_flip($GroupIDs); $Key = $Torrents ? 'torrent_group_' : 'torrent_group_light_'; @@ -435,6 +441,7 @@ public static function torrent_info($Data, $ShowMedia = false, $ShowEdition = fa if (!empty($Data['RemasterTitle'])) { $EditionInfo[]=$Data['RemasterTitle']; } if (count($EditionInfo)) { $Info[]=implode(' ',$EditionInfo); } } + if ($Data['SnatchedTorrent'] == '1') { $Info[]='Snatched!'; } if ($Data['FreeTorrent'] == '1') { $Info[]='Freeleech!'; } if ($Data['FreeTorrent'] == '2') { $Info[]='Neutral Leech!'; } if ($Data['PersonalFL']) { $Info[]='Personal Freeleech!'; } @@ -498,7 +505,6 @@ public static function freeleech_groups($GroupIDs, $FreeNeutral = 1, $FreeLeechT } } - /** * Check if the logged in user has an active freeleech token * @@ -542,5 +548,23 @@ public static function can_use_token($Torrent) { && empty($Torrent['FreeTorrent']) && $LoggedUser['CanLeech'] == '1'); } + + public static function get_snatched_torrents($UserID = false) { + global $DB, $Cache, $LoggedUser; + if($LoggedUser['ShowSnatched']) { + $UserID = $LoggedUser['ID']; + $SnatchedTorrents = $Cache->get_value('users_snatched_'.$UserID); + if (empty($SnatchedTorrents)) { + $DB->query("SELECT DISTINCT fid as TorrentID FROM xbt_snatched WHERE uid='$UserID'"); + $SnatchedTorrents = array_flip($DB->collect('TorrentID')); + $Cache->cache_value('users_snatched_'.$UserID, $SnatchedTorrents, 86400); + } + } + else { + $SnatchedTorrents = array(); + } + return $SnatchedTorrents; + } + } ?> diff --git a/classes/class_users.php b/classes/class_users.php index 24831490..d225c195 100644 --- a/classes/class_users.php +++ b/classes/class_users.php @@ -442,5 +442,70 @@ public static function make_class_string($ClassID) { global $Classes; return $Classes[$ClassID]['Name']; } + + /** + * Returns an array with User Bookmark data: group ids, collage data list, etc + * @global CACHE $Cache + * @global DB_MYSQL $DB + * @param string|int $UserID + * @return array + */ + function bookmark_data ($UserID) + { + global $Cache, $DB; + + $UserID = (int) $UserID; + + $Data = $Cache->get_value('bookmarks_torrent_'.$UserID.'_full'); + + if($Data) { + $Data = unserialize($Data); + list($K, list($TorrentList, $CollageDataList)) = each($Data); + } else { + // Build the data for the collage and the torrent list + $DB->query("SELECT + bt.GroupID, + bt.Sort, + tg.WikiImage, + tg.CategoryID, + bt.Time + FROM bookmarks_torrents AS bt + JOIN torrents_group AS tg ON tg.ID=bt.GroupID + WHERE bt.UserID='$UserID' + ORDER BY bt.Sort ASC"); + + $GroupIDs = $DB->collect('GroupID'); + $CollageDataList = $DB->to_array('GroupID', MYSQLI_ASSOC); + + if(count($GroupIDs) > 0) { + $TorrentList = Torrents::get_groups($GroupIDs); + $TorrentList = $TorrentList['matches']; + } else { + $TorrentList = array(); + } + } + + return array($K, $GroupIDs, $CollageDataList, $TorrentList); + } + + /** + * Returns a list of torrents that a user has spent tokens on + * @global CACHE $Cache + * @global DB_MYSQL $DB + * @param type $UserID + * @return type + */ + function token_torrents ($UserID) + { + global $Cache, $DB; + + $UserID = (int) $UserID; + $TokenTorrents = $Cache->get_value('users_tokens_'.$UserID); + if (empty($TokenTorrents)) { + $DB->query("SELECT TorrentID FROM users_freeleeches WHERE UserID=$UserID AND Expired=FALSE"); + $TokenTorrents = $DB->collect('TorrentID'); + $Cache->cache_value('users_tokens_'.$UserID, $TokenTorrents); + } + return $TokenTorrents; + } } -?> diff --git a/classes/class_view.php b/classes/class_view.php index 73167097..236b2d23 100644 --- a/classes/class_view.php +++ b/classes/class_view.php @@ -1,5 +1,11 @@ + + /** + * This method is similar to render_template, but does not require a + * template class. + * + * Instead, this method simply renders a PHP file (PHTML) with the supplied + * variables. + * + * All files must be placed within {self::IncludePath}. Create and organize + * new paths and files. (eg: /design/views/artist/, design/view/forums/, etc.) + * + * @static + * @param string $TemplateFile A relative path to a PHTML file + * @param array $Variables Assoc. array of variables to extract for the template + * @example
         $some_id));
        +	 * 
        + */ + static public function parse ($TemplateFile, array $Variables = null) + { + $Template = self::IncludePath . $TemplateFile; + if (file_exists($Template)) { + extract($Variables); + include $Template; + } + } +} \ No newline at end of file diff --git a/classes/permissions_form.php b/classes/permissions_form.php index d890c9e4..e8573e9f 100644 --- a/classes/permissions_form.php +++ b/classes/permissions_form.php @@ -16,6 +16,7 @@ 'site_advanced_search' => 'Advanced search access.', 'site_top10' => 'Top 10 access.', 'site_advanced_top10' => 'Advanced Top 10 access.', + 'site_album_votes' => 'Voting for favorite torrents.', 'site_torrents_notify' => 'Notifications access.', 'site_collages_create' => 'Collage create access.', 'site_collages_manage' => 'Collage manage access.', @@ -135,6 +136,7 @@ function permissions_form(){ ?> + diff --git a/classes/script_start.php b/classes/script_start.php index 90ba7b2e..3781196b 100644 --- a/classes/script_start.php +++ b/classes/script_start.php @@ -1,10 +1,9 @@ +
        Author - Title
        Description - +
        + diff --git a/design/views/generic/textarea/buttons.phtml b/design/views/generic/textarea/buttons.phtml new file mode 100644 index 00000000..907e70d3 --- /dev/null +++ b/design/views/generic/textarea/buttons.phtml @@ -0,0 +1,3 @@ + + + diff --git a/design/views/generic/textarea/preview.phtml b/design/views/generic/textarea/preview.phtml new file mode 100644 index 00000000..2af2d71d --- /dev/null +++ b/design/views/generic/textarea/preview.phtml @@ -0,0 +1,4 @@ + + diff --git a/design/views/generic/textarea/script.phtml b/design/views/generic/textarea/script.phtml new file mode 100644 index 00000000..6d63d2dc --- /dev/null +++ b/design/views/generic/textarea/script.phtml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/design/views/generic/textarea/script_factory.phtml b/design/views/generic/textarea/script_factory.phtml new file mode 100644 index 00000000..a1d2f0ee --- /dev/null +++ b/design/views/generic/textarea/script_factory.phtml @@ -0,0 +1,4 @@ + + diff --git a/design/views/generic/textarea/textarea.phtml b/design/views/generic/textarea/textarea.phtml new file mode 100644 index 00000000..a49787ee --- /dev/null +++ b/design/views/generic/textarea/textarea.phtml @@ -0,0 +1,4 @@ + +
        + +
        diff --git a/gazelle.sql b/gazelle.sql index 8f9673a1..fe7feed5 100644 --- a/gazelle.sql +++ b/gazelle.sql @@ -23,6 +23,19 @@ CREATE TABLE `api_users` ( KEY `UserID` (`UserID`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; +CREATE TABLE `artist_comments` ( + `ID` int(10) NOT NULL AUTO_INCREMENT, + `ArtistID` int(10) NOT NULL, + `AuthorID` int(10) NOT NULL, + `AddedTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `Body` mediumtext COLLATE utf8_bin, + `EditedUserID` int(10) DEFAULT NULL, + `EditedTime` datetime DEFAULT NULL, + PRIMARY KEY (`ID`), + KEY `TopicID` (`ArtistID`), + KEY `AuthorID` (`AuthorID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + CREATE TABLE `artists_alias` ( `AliasID` int(10) NOT NULL AUTO_INCREMENT, `ArtistID` int(10) NOT NULL, @@ -39,11 +52,20 @@ CREATE TABLE `artists_group` ( `Name` varchar(200) CHARACTER SET utf8 COLLATE utf8_swedish_ci DEFAULT NULL, `RevisionID` int(12) DEFAULT NULL, `VanityHouse` tinyint(1) DEFAULT '0', + `LastCommentID` int(10) NOT NULL DEFAULT '0', PRIMARY KEY (`ArtistID`), KEY `Name` (`Name`), KEY `RevisionID` (`RevisionID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; +CREATE TABLE `artists_last_read_comments` ( + `UserID` int(10) NOT NULL, + `ArtistID` int(10) NOT NULL, + `CommentID` int(10) NOT NULL, + PRIMARY KEY (`UserID`,`ArtistID`), + KEY `ArtistID` (`ArtistID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + CREATE TABLE `artists_similar` ( `ArtistID` int(10) NOT NULL DEFAULT '0', `SimilarID` int(12) NOT NULL DEFAULT '0', @@ -490,6 +512,12 @@ CREATE TABLE `pm_messages` ( KEY `ConvID` (`ConvID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; +CREATE TABLE `push_notifications_usage` ( + `PushService` varchar(10) NOT NULL, + `TimesUsed` int(10) NOT NULL DEFAULT '0', + PRIMARY KEY (`PushService`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + CREATE TABLE `reports` ( `ID` int(10) unsigned NOT NULL AUTO_INCREMENT, `UserID` int(10) unsigned NOT NULL DEFAULT '0', @@ -1017,6 +1045,7 @@ CREATE TABLE `torrents_group` ( `WikiImage` varchar(255) COLLATE utf8_bin NOT NULL, `SearchText` varchar(500) COLLATE utf8_bin NOT NULL, `VanityHouse` tinyint(1) DEFAULT '0', + `LastCommentID` int(10) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`), KEY `ArtistID` (`ArtistID`), KEY `CategoryID` (`CategoryID`), @@ -1026,6 +1055,14 @@ CREATE TABLE `torrents_group` ( KEY `RevisionID` (`RevisionID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; +CREATE TABLE `torrents_last_read_comments` ( + `UserID` int(10) NOT NULL, + `GroupID` int(10) NOT NULL, + `CommentID` int(10) NOT NULL, + PRIMARY KEY (`UserID`,`GroupID`), + KEY `GroupID` (`GroupID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + CREATE TABLE `torrents_logs_new` ( `LogID` int(10) NOT NULL AUTO_INCREMENT, `TorrentID` int(10) NOT NULL DEFAULT '0', @@ -1117,6 +1154,13 @@ CREATE TABLE `torrents_votes` ( CONSTRAINT `torrents_votes_ibfk_1` FOREIGN KEY (`GroupID`) REFERENCES `torrents_group` (`ID`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `users_artists_comments_subscriptions` ( + `UserID` int(10) NOT NULL, + `ArtistID` int(10) NOT NULL, + PRIMARY KEY (`UserID`,`ArtistID`), + KEY `ArtistID` (`ArtistID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + CREATE TABLE `users_collage_subs` ( `UserID` int(10) NOT NULL, `CollageID` int(10) NOT NULL, @@ -1125,6 +1169,13 @@ CREATE TABLE `users_collage_subs` ( KEY `CollageID` (`CollageID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; +CREATE TABLE `users_comments_subscriptions` ( + `UserID` int(10) NOT NULL, + `GroupID` int(10) NOT NULL, + PRIMARY KEY (`UserID`,`GroupID`), + KEY `GroupID` (`GroupID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + CREATE TABLE `users_downloads` ( `UserID` int(10) NOT NULL, `TorrentID` int(1) NOT NULL, @@ -1214,6 +1265,7 @@ CREATE TABLE `users_info` ( `SupportFor` varchar(255) NOT NULL, `TorrentGrouping` enum('0','1','2') NOT NULL COMMENT '0=Open,1=Closed,2=Off', `ShowTags` enum('0','1') NOT NULL DEFAULT '1', + `NotifyOnQuote` enum('0','1','2') NOT NULL DEFAULT '0', `AuthKey` varchar(32) NOT NULL, `ResetKey` varchar(32) NOT NULL, `ResetExpires` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', @@ -1243,6 +1295,8 @@ CREATE TABLE `users_info` ( `PermittedForums` varchar(150) NOT NULL DEFAULT '', `UnseededAlerts` enum('0','1') NOT NULL DEFAULT '0', `LastReadBlog` int(10) NOT NULL DEFAULT '0', + `TorrentsCommentsCatchupTime` datetime DEFAULT NULL, + `ArtistsCommentsCatchupTime` datetime DEFAULT NULL, UNIQUE KEY `UserID` (`UserID`), KEY `SupportFor` (`SupportFor`), KEY `DisableInvites` (`DisableInvites`), @@ -1344,6 +1398,17 @@ CREATE TABLE `users_notify_filters` ( KEY `ToYear` (`ToYear`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `users_notify_quoted` ( + `UserID` int(10) NOT NULL, + `QuoterID` int(10) NOT NULL, + `ForumID` int(6) unsigned DEFAULT NULL, + `TopicID` int(10) NOT NULL, + `PostID` int(10) NOT NULL, + `UnRead` enum('0','1') NOT NULL DEFAULT '1', + `Date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`UserID`,`PostID`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + CREATE TABLE `users_notify_torrents` ( `UserID` int(10) NOT NULL, `FilterID` int(10) NOT NULL, @@ -1373,6 +1438,13 @@ CREATE TABLE `users_points_requests` ( KEY `RequestID` (`RequestID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; +CREATE TABLE `users_push_notifications` ( + `UserID` int(10) NOT NULL, + `PushService` tinyint(1) NOT NULL DEFAULT '0', + `PushOptions` text NOT NULL, + PRIMARY KEY (`UserID`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + CREATE TABLE `users_sessions` ( `UserID` int(10) NOT NULL, `SessionID` char(32) NOT NULL, @@ -1544,7 +1616,7 @@ CREATE TABLE `xbt_snatched` ( SET FOREIGN_KEY_CHECKS = 1; -INSERT INTO permissions (ID, Level, Name, `Values`, DisplayStaff) VALUES (15, 1000, 'Sysop', 'a:98:{s:10:\"site_leech\";i:1;s:11:\"site_upload\";i:1;s:9:\"site_vote\";i:1;s:20:\"site_submit_requests\";i:1;s:21:\"site_see_old_requests\";i:1;s:20:\"site_advanced_search\";i:1;s:10:\"site_top10\";i:1;s:19:\"site_advanced_top10\";i:1;s:20:\"site_torrents_notify\";i:1;s:20:\"site_collages_create\";i:1;s:20:\"site_collages_manage\";i:1;s:20:\"site_collages_delete\";i:1;s:23:\"site_collages_subscribe\";i:1;s:22:\"site_collages_personal\";i:1;s:28:\"site_collages_renamepersonal\";i:1;s:19:\"site_make_bookmarks\";i:1;s:14:\"site_edit_wiki\";i:1;s:22:\"site_can_invite_always\";i:1;s:27:\"site_send_unlimited_invites\";i:1;s:22:\"site_moderate_requests\";i:1;s:18:\"site_delete_artist\";i:1;s:20:\"site_moderate_forums\";i:1;s:17:\"site_admin_forums\";i:1;s:23:\"site_forums_double_post\";i:1;s:14:\"site_view_flow\";i:1;s:18:\"site_view_full_log\";i:1;s:28:\"site_view_torrent_snatchlist\";i:1;s:18:\"site_recommend_own\";i:1;s:27:\"site_manage_recommendations\";i:1;s:15:\"site_delete_tag\";i:1;s:23:\"site_disable_ip_history\";i:1;s:14:\"zip_downloader\";i:1;s:10:\"site_debug\";i:1;s:17:\"site_proxy_images\";i:1;s:16:\"site_search_many\";i:1;s:20:\"users_edit_usernames\";i:1;s:16:\"users_edit_ratio\";i:1;s:20:\"users_edit_own_ratio\";i:1;s:17:\"users_edit_titles\";i:1;s:18:\"users_edit_avatars\";i:1;s:18:\"users_edit_invites\";i:1;s:22:\"users_edit_watch_hours\";i:1;s:21:\"users_edit_reset_keys\";i:1;s:19:\"users_edit_profiles\";i:1;s:18:\"users_view_friends\";i:1;s:20:\"users_reset_own_keys\";i:1;s:19:\"users_edit_password\";i:1;s:19:\"users_promote_below\";i:1;s:16:\"users_promote_to\";i:1;s:16:\"users_give_donor\";i:1;s:10:\"users_warn\";i:1;s:19:\"users_disable_users\";i:1;s:19:\"users_disable_posts\";i:1;s:17:\"users_disable_any\";i:1;s:18:\"users_delete_users\";i:1;s:18:\"users_view_invites\";i:1;s:20:\"users_view_seedleech\";i:1;s:19:\"users_view_uploaded\";i:1;s:15:\"users_view_keys\";i:1;s:14:\"users_view_ips\";i:1;s:16:\"users_view_email\";i:1;s:23:\"users_override_paranoia\";i:1;s:12:\"users_logout\";i:1;s:20:\"users_make_invisible\";i:1;s:9:\"users_mod\";i:1;s:13:\"torrents_edit\";i:1;s:15:\"torrents_delete\";i:1;s:20:\"torrents_delete_fast\";i:1;s:18:\"torrents_freeleech\";i:1;s:20:\"torrents_search_fast\";i:1;s:17:\"torrents_hide_dnu\";i:1;s:19:\"torrents_fix_ghosts\";i:1;s:17:\"admin_manage_news\";i:1;s:17:\"admin_manage_blog\";i:1;s:18:\"admin_manage_polls\";i:1;s:19:\"admin_manage_forums\";i:1;s:16:\"admin_manage_fls\";i:1;s:13:\"admin_reports\";i:1;s:26:\"admin_advanced_user_search\";i:1;s:18:\"admin_create_users\";i:1;s:15:\"admin_donor_log\";i:1;s:19:\"admin_manage_ipbans\";i:1;s:9:\"admin_dnu\";i:1;s:17:\"admin_clear_cache\";i:1;s:15:\"admin_whitelist\";i:1;s:24:\"admin_manage_permissions\";i:1;s:14:\"admin_schedule\";i:1;s:17:\"admin_login_watch\";i:1;s:17:\"admin_manage_wiki\";i:1;s:18:\"admin_update_geoip\";i:1;s:21:\"site_collages_recover\";i:1;s:19:\"torrents_add_artist\";i:1;s:13:\"edit_unknowns\";i:1;s:19:\"forums_polls_create\";i:1;s:21:\"forums_polls_moderate\";i:1;s:12:\"project_team\";i:1;s:25:\"torrents_edit_vanityhouse\";i:1;s:23:\"artist_edit_vanityhouse\";i:1;}', '1'), (2, 100, 'User', 'a:7:{s:10:\"site_leech\";i:1;s:11:\"site_upload\";i:1;s:9:\"site_vote\";i:1;s:20:\"site_advanced_search\";i:1;s:10:\"site_top10\";i:1;s:14:\"site_edit_wiki\";i:1;s:19:\"torrents_add_artist\";i:1;}', '0'), (3, 150, 'Member', 'a:10:{s:10:\"site_leech\";i:1;s:11:\"site_upload\";i:1;s:9:\"site_vote\";i:1;s:20:\"site_submit_requests\";i:1;s:20:\"site_advanced_search\";i:1;s:10:\"site_top10\";i:1;s:20:\"site_collages_manage\";i:1;s:19:\"site_make_bookmarks\";i:1;s:14:\"site_edit_wiki\";i:1;s:19:\"torrents_add_artist\";i:1;}', '0'), (4, 200, 'Power User', 'a:14:{s:10:\"site_leech\";i:1;s:11:\"site_upload\";i:1;s:9:\"site_vote\";i:1;s:20:\"site_submit_requests\";i:1;s:20:\"site_advanced_search\";i:1;s:10:\"site_top10\";i:1;s:20:\"site_torrents_notify\";i:1;s:20:\"site_collages_create\";i:1;s:20:\"site_collages_manage\";i:1;s:19:\"site_make_bookmarks\";i:1;s:14:\"site_edit_wiki\";i:1;s:14:\"zip_downloader\";i:1;s:19:\"forums_polls_create\";i:1;s:19:\"torrents_add_artist\";i:1;} ', '0'), (5, 250, 'Elite', 'a:18:{s:10:\"site_leech\";i:1;s:11:\"site_upload\";i:1;s:9:\"site_vote\";i:1;s:20:\"site_submit_requests\";i:1;s:20:\"site_advanced_search\";i:1;s:10:\"site_top10\";i:1;s:20:\"site_torrents_notify\";i:1;s:20:\"site_collages_create\";i:1;s:20:\"site_collages_manage\";i:1;s:19:\"site_advanced_top10\";i:1;s:19:\"site_make_bookmarks\";i:1;s:14:\"site_edit_wiki\";i:1;s:15:\"site_delete_tag\";i:1;s:14:\"zip_downloader\";i:1;s:19:\"forums_polls_create\";i:1;s:13:\"torrents_edit\";i:1;s:19:\"torrents_add_artist\";i:1;s:17:\"admin_clear_cache\";i:1;}', '0'), (20, 202, 'Donor', 'a:9:{s:9:\"site_vote\";i:1;s:20:\"site_submit_requests\";i:1;s:20:\"site_advanced_search\";i:1;s:10:\"site_top10\";i:1;s:20:\"site_torrents_notify\";i:1;s:20:\"site_collages_create\";i:1;s:20:\"site_collages_manage\";i:1;s:14:\"zip_downloader\";i:1;s:19:\"forums_polls_create\";i:1;}', '0'), (19, 201, 'Artist', 'a:9:{s:10:\"site_leech\";s:1:\"1\";s:11:\"site_upload\";s:1:\"1\";s:9:\"site_vote\";s:1:\"1\";s:20:\"site_submit_requests\";s:1:\"1\";s:20:\"site_advanced_search\";s:1:\"1\";s:10:\"site_top10\";s:1:\"1\";s:19:\"site_make_bookmarks\";s:1:\"1\";s:14:\"site_edit_wiki\";s:1:\"1\";s:18:\"site_recommend_own\";s:1:\"1\";}', '0'); +INSERT INTO permissions (ID, Level, Name, `Values`, DisplayStaff) VALUES (15, 1000, 'Sysop', 'a:99:{s:10:\"site_leech\";i:1;s:11:\"site_upload\";i:1;s:9:\"site_vote\";i:1;s:20:\"site_submit_requests\";i:1;s:21:\"site_see_old_requests\";i:1;s:20:\"site_advanced_search\";i:1;s:10:\"site_top10\";i:1;s:19:\"site_advanced_top10\";i:1;s:16:\"site_album_votes\";i:1;s:20:\"site_torrents_notify\";i:1;s:20:\"site_collages_create\";i:1;s:20:\"site_collages_manage\";i:1;s:20:\"site_collages_delete\";i:1;s:23:\"site_collages_subscribe\";i:1;s:22:\"site_collages_personal\";i:1;s:28:\"site_collages_renamepersonal\";i:1;s:19:\"site_make_bookmarks\";i:1;s:14:\"site_edit_wiki\";i:1;s:22:\"site_can_invite_always\";i:1;s:27:\"site_send_unlimited_invites\";i:1;s:22:\"site_moderate_requests\";i:1;s:18:\"site_delete_artist\";i:1;s:20:\"site_moderate_forums\";i:1;s:17:\"site_admin_forums\";i:1;s:23:\"site_forums_double_post\";i:1;s:14:\"site_view_flow\";i:1;s:18:\"site_view_full_log\";i:1;s:28:\"site_view_torrent_snatchlist\";i:1;s:18:\"site_recommend_own\";i:1;s:27:\"site_manage_recommendations\";i:1;s:15:\"site_delete_tag\";i:1;s:23:\"site_disable_ip_history\";i:1;s:14:\"zip_downloader\";i:1;s:10:\"site_debug\";i:1;s:17:\"site_proxy_images\";i:1;s:16:\"site_search_many\";i:1;s:20:\"users_edit_usernames\";i:1;s:16:\"users_edit_ratio\";i:1;s:20:\"users_edit_own_ratio\";i:1;s:17:\"users_edit_titles\";i:1;s:18:\"users_edit_avatars\";i:1;s:18:\"users_edit_invites\";i:1;s:22:\"users_edit_watch_hours\";i:1;s:21:\"users_edit_reset_keys\";i:1;s:19:\"users_edit_profiles\";i:1;s:18:\"users_view_friends\";i:1;s:20:\"users_reset_own_keys\";i:1;s:19:\"users_edit_password\";i:1;s:19:\"users_promote_below\";i:1;s:16:\"users_promote_to\";i:1;s:16:\"users_give_donor\";i:1;s:10:\"users_warn\";i:1;s:19:\"users_disable_users\";i:1;s:19:\"users_disable_posts\";i:1;s:17:\"users_disable_any\";i:1;s:18:\"users_delete_users\";i:1;s:18:\"users_view_invites\";i:1;s:20:\"users_view_seedleech\";i:1;s:19:\"users_view_uploaded\";i:1;s:15:\"users_view_keys\";i:1;s:14:\"users_view_ips\";i:1;s:16:\"users_view_email\";i:1;s:23:\"users_override_paranoia\";i:1;s:12:\"users_logout\";i:1;s:20:\"users_make_invisible\";i:1;s:9:\"users_mod\";i:1;s:13:\"torrents_edit\";i:1;s:15:\"torrents_delete\";i:1;s:20:\"torrents_delete_fast\";i:1;s:18:\"torrents_freeleech\";i:1;s:20:\"torrents_search_fast\";i:1;s:17:\"torrents_hide_dnu\";i:1;s:19:\"torrents_fix_ghosts\";i:1;s:17:\"admin_manage_news\";i:1;s:17:\"admin_manage_blog\";i:1;s:18:\"admin_manage_polls\";i:1;s:19:\"admin_manage_forums\";i:1;s:16:\"admin_manage_fls\";i:1;s:13:\"admin_reports\";i:1;s:26:\"admin_advanced_user_search\";i:1;s:18:\"admin_create_users\";i:1;s:15:\"admin_donor_log\";i:1;s:19:\"admin_manage_ipbans\";i:1;s:9:\"admin_dnu\";i:1;s:17:\"admin_clear_cache\";i:1;s:15:\"admin_whitelist\";i:1;s:24:\"admin_manage_permissions\";i:1;s:14:\"admin_schedule\";i:1;s:17:\"admin_login_watch\";i:1;s:17:\"admin_manage_wiki\";i:1;s:18:\"admin_update_geoip\";i:1;s:21:\"site_collages_recover\";i:1;s:19:\"torrents_add_artist\";i:1;s:13:\"edit_unknowns\";i:1;s:19:\"forums_polls_create\";i:1;s:21:\"forums_polls_moderate\";i:1;s:12:\"project_team\";i:1;s:25:\"torrents_edit_vanityhouse\";i:1;s:23:\"artist_edit_vanityhouse\";i:1;}', '1'), (2, 100, 'User', 'a:7:{s:10:\"site_leech\";i:1;s:11:\"site_upload\";i:1;s:9:\"site_vote\";i:1;s:20:\"site_advanced_search\";i:1;s:10:\"site_top10\";i:1;s:14:\"site_edit_wiki\";i:1;s:19:\"torrents_add_artist\";i:1;}', '0'), (3, 150, 'Member', 'a:10:{s:10:\"site_leech\";i:1;s:11:\"site_upload\";i:1;s:9:\"site_vote\";i:1;s:20:\"site_submit_requests\";i:1;s:20:\"site_advanced_search\";i:1;s:10:\"site_top10\";i:1;s:20:\"site_collages_manage\";i:1;s:19:\"site_make_bookmarks\";i:1;s:14:\"site_edit_wiki\";i:1;s:19:\"torrents_add_artist\";i:1;}', '0'), (4, 200, 'Power User', 'a:14:{s:10:\"site_leech\";i:1;s:11:\"site_upload\";i:1;s:9:\"site_vote\";i:1;s:20:\"site_submit_requests\";i:1;s:20:\"site_advanced_search\";i:1;s:10:\"site_top10\";i:1;s:20:\"site_torrents_notify\";i:1;s:20:\"site_collages_create\";i:1;s:20:\"site_collages_manage\";i:1;s:19:\"site_make_bookmarks\";i:1;s:14:\"site_edit_wiki\";i:1;s:14:\"zip_downloader\";i:1;s:19:\"forums_polls_create\";i:1;s:19:\"torrents_add_artist\";i:1;} ', '0'), (5, 250, 'Elite', 'a:18:{s:10:\"site_leech\";i:1;s:11:\"site_upload\";i:1;s:9:\"site_vote\";i:1;s:20:\"site_submit_requests\";i:1;s:20:\"site_advanced_search\";i:1;s:10:\"site_top10\";i:1;s:20:\"site_torrents_notify\";i:1;s:20:\"site_collages_create\";i:1;s:20:\"site_collages_manage\";i:1;s:19:\"site_advanced_top10\";i:1;s:19:\"site_make_bookmarks\";i:1;s:14:\"site_edit_wiki\";i:1;s:15:\"site_delete_tag\";i:1;s:14:\"zip_downloader\";i:1;s:19:\"forums_polls_create\";i:1;s:13:\"torrents_edit\";i:1;s:19:\"torrents_add_artist\";i:1;s:17:\"admin_clear_cache\";i:1;}', '0'), (20, 202, 'Donor', 'a:9:{s:9:\"site_vote\";i:1;s:20:\"site_submit_requests\";i:1;s:20:\"site_advanced_search\";i:1;s:10:\"site_top10\";i:1;s:20:\"site_torrents_notify\";i:1;s:20:\"site_collages_create\";i:1;s:20:\"site_collages_manage\";i:1;s:14:\"zip_downloader\";i:1;s:19:\"forums_polls_create\";i:1;}', '0'), (19, 201, 'Artist', 'a:9:{s:10:\"site_leech\";s:1:\"1\";s:11:\"site_upload\";s:1:\"1\";s:9:\"site_vote\";s:1:\"1\";s:20:\"site_submit_requests\";s:1:\"1\";s:20:\"site_advanced_search\";s:1:\"1\";s:10:\"site_top10\";s:1:\"1\";s:19:\"site_make_bookmarks\";s:1:\"1\";s:14:\"site_edit_wiki\";s:1:\"1\";s:18:\"site_recommend_own\";s:1:\"1\";}', '0'); INSERT INTO stylesheets (ID, Name, Description, `Default`) VALUES (9, 'Proton', 'Proton by Protiek', '0'), (2, 'Layer cake', 'Grey stylesheet by Emm', '0'), (21, 'postmod', 'Upgrade on anorex', '1'); diff --git a/sections/ajax/index.php b/sections/ajax/index.php index dff1ea20..aa382968 100644 --- a/sections/ajax/index.php +++ b/sections/ajax/index.php @@ -101,6 +101,9 @@ case 'userhistory': require(SERVER_ROOT.'/sections/ajax/userhistory/index.php'); break; + case 'votefavorite': + require(SERVER_ROOT.'/sections/ajax/takevote.php'); + break; default: // If they're screwing around with the query string print json_encode(array('status' => 'failure')); diff --git a/sections/ajax/preview.php b/sections/ajax/preview.php index 085a1e98..2ec6b0ab 100644 --- a/sections/ajax/preview.php +++ b/sections/ajax/preview.php @@ -2,7 +2,7 @@ /* AJAX Previews, simple stuff. */ include(SERVER_ROOT.'/classes/class_text.php'); // Text formatting class -$Text = new TEXT; +$Text = new TEXT(true); if(!empty($_POST['AdminComment'])) { echo $Text->full_format($_POST['AdminComment']); @@ -10,4 +10,4 @@ $Content = $_REQUEST['body']; // Don't use URL decode. echo $Text->full_format($Content); } -?> + diff --git a/sections/ajax/takevote.php b/sections/ajax/takevote.php new file mode 100644 index 00000000..3ceff73d --- /dev/null +++ b/sections/ajax/takevote.php @@ -0,0 +1,204 @@ +get_value('voted_albums_'.$LoggedUser['ID']); +if ($UserVotes === FALSE) { + $DB->query('SELECT GroupID, Type FROM users_votes WHERE UserID='.$LoggedUser['ID']); + $UserVotes = $DB->to_array('GroupID', MYSQL_ASSOC, false); + $Cache->cache_value('voted_albums_'.$LoggedUser['ID'], $UserVotes); +} + +// What are the votes for this group? +$GroupVotes = $Cache->get_value('votes_'.$GroupID); +if ($GroupVotes === FALSE) { + $DB->query("SELECT Ups AS Ups, Total AS Total FROM torrents_votes WHERE GroupID=$GroupID"); + if ($DB->record_count() == 0) { + $GroupVotes = array('Ups'=>0, 'Total'=>0); + } else { + $GroupVotes = $DB->next_record(MYSQLI_ASSOC, false); + } + $Cache->cache_value('votes_'.$GroupID, $GroupVotes); +} + +$UserID = $LoggedUser['ID']; +if ($_REQUEST['do'] == 'vote') { + if (isset($UserVotes[$GroupID]) || !check_perms('site_album_votes')) { + echo 'noaction'; + die(); + } + if ($_REQUEST['vote'] != 'up' && $_REQUEST['vote'] != 'down') { + echo 'badvote'; + die(); + } + $Type = ($_REQUEST['vote'] == 'up')?"Up":"Down"; + + // Update the group's cache key + $GroupVotes['Total'] += 1; + if ($Type == "Up") { + $GroupVotes['Ups'] += 1; + } + $Cache->cache_value('votes_'.$GroupID, $GroupVotes); + + // Update the two votes tables + $DB->query("INSERT INTO users_votes (UserID, GroupID, Type) VALUES ($UserID, $GroupID, '$Type') ON DUPLICATE KEY UPDATE Type = '$Type'"); + // If the group has no votes yet, we need an insert, otherwise an update + // so we can cut corners and use the magic of INSERT...ON DUPLICATE KEY UPDATE... + // to accomplish both in one query + $DB->query("INSERT INTO torrents_votes (GroupID, Total, Ups, Score) + VALUES ($GroupID, 1, ".($Type=='Up'?1:0).", 0) + ON DUPLICATE KEY UPDATE Total = Total + 1, + Score = binomial_ci(".$GroupVotes['Ups'].",". $GroupVotes['Total'].")". + ($Type=='Up'?', Ups = Ups+1':'')); + + $UserVotes[$GroupID] = array('GroupID' => $GroupID, 'Type' => $Type); + + // Update this guy's cache key + $Cache->cache_value('voted_albums_'.$LoggedUser['ID'], $UserVotes); + + // Update the paired cache keys for "people who liked" + // First update this album's paired votes. If this keys is magically not set, + // our life just got a bit easier. We're only tracking paired votes on upvotes. + if ($Type == 'Up') { + $VotePairs = $Cache->get_value('vote_pairs_'.$GroupID); + if ($VotePairs !== FALSE) { + foreach ($UserVotes as $Vote) { + if ($Vote['GroupID'] == $GroupID) { + continue; + } + // Go through each of his other votes, incrementing the + // corresponding keys in this groups vote_pairs array + if (isset($VotePairs[$Vote['GroupID']])) { + $VotePairs[$Vote['GroupID']]['Total'] += 1; + if ($Vote['Type'] == 'Up') { + $VotePairs[$Vote['GroupID']]['Ups'] += 1; + } + } else { + $VotePairs[$Vote['GroupID']] = array('GroupID'=>$Vote['GroupID'], + 'Total' => 1, + 'Ups'=>($Type == 'Up')?1:0); + } + } + } + $Cache->cache_value('vote_pairs_'.$GroupID, $VotePairs); + } + + // Now do the paired votes keys for all of this guy's other votes + foreach ($UserVotes as $VGID => $Vote) { + if ($Vote['Type'] != 'Up') { + // We're only track paired votes on upvotes + continue; + } + // Again, if the cache key is not set, move along + $VotePairs = $Cache->get_value('vote_pairs_'.$VGID); + if ($VotePairs !== FALSE) { + // Go through all of the other albums paired to this one, and update + // this group's entry in their vote_pairs keys + if (isset($VotePairs[$GroupID])) { + $VotePairs[$GroupID]['Total']++; + if ($Type == 'Up') { + $VotePairs[$GroupID]['Ups']++; + } + } else { + $VotePairs[$GroupID] = array('GroupID' => $GroupID, + 'Total' => 1, + 'Ups'=>($Type == 'Up')?1:0); + } + $Cache->cache_value('vote_pairs_'.$VGID, $VotePairs); + } + } + + + echo 'success'; +} elseif ($_REQUEST['do'] == 'unvote') { + if (!isset($UserVotes[$GroupID])) { + echo 'noaction'; + die(); + } + $Type = $UserVotes[$GroupID]['Type']; + + $DB->query("DELETE FROM users_votes WHERE UserID=$UserID AND GroupID=$GroupID"); + + // Update personal cache key + unset($UserVotes[$GroupID]); + $Cache->cache_value('voted_albums_'.$LoggedUser['ID'], $UserVotes); + + // Update the group's cache key + $GroupVotes['Total'] -= 1; + if ($Type == "Up") { + $GroupVotes['Ups'] -= 1; + } + $Cache->cache_value('votes_'.$GroupID, $GroupVotes); + + $DB->query("UPDATE torrents_votes SET Total = GREATEST(0, Total - 1), + Score = binomial_ci(".$GroupVotes['Ups'].",".$GroupVotes['Total'].")". + ($Type=='Up'?', Ups = GREATEST(0, Ups - 1)':'')." + WHERE GroupID=$GroupID"); + // Update paired cache keys + // First update this album's paired votes. If this keys is magically not set, + // our life just got a bit easier. We're only tracking paired votes on upvotes. + if ($Type == 'Up') { + $VotePairs = $Cache->get_value('vote_pairs_'.$GroupID); + if ($VotePairs !== FALSE) { + foreach ($UserVotes as $Vote) { + if (isset($VotePairs[$Vote['GroupID']])) { + if ($VotePairs[$Vote['GroupID']]['Total'] == 0) { + // Something is screwy + $Cache->delete_value('vote_pairs_'.$GroupID); + continue; + } + $VotePairs[$Vote['GroupID']]['Total'] -= 1; + if ($Vote['Type'] == 'Up') { + $VotePairs[$Vote['GroupID']]['Ups'] -= 1; + } + } else { + // Something is screwy, kill the key and move on + $Cache->delete_value('vote_pairs_'.$GroupID); + break; + } + } + } + $Cache->cache_value('vote_pairs_'.$GroupID, $VotePairs); + } + + // Now do the paired votes keys for all of this guy's other votes + foreach ($UserVotes as $VGID => $Vote) { + if ($Vote['Type'] != 'Up') { + // We're only track paired votes on upvotes + continue; + } + // Again, if the cache key is not set, move along + $VotePairs = $Cache->get_value('vote_pairs_'.$VGID); + if ($VotePairs !== FALSE) { + if (isset($VotePairs[$GroupID])) { + if ($VotePairs[$GroupID]['Total'] == 0) { + // Something is screwy + $Cache->delete_value('vote_pairs_'.$VGID); + continue; + } + $VotePairs[$GroupID]['Total'] -= 1; + if ($Type == 'Up') { + $VotePairs[$GroupID]['Ups'] -= 1; + } + $Cache->cache_value('vote_pairs_'.$VGID, $VotePairs); + } else { + // Something is screwy, kill the key and move on + $Cache->delete_value('vote_pairs_'.$VGID); + } + } + } + + // Let the script know what happened + if ($Type == 'Up') { + echo 'success-up'; + } else { + echo 'success-down'; + } +} +?> \ No newline at end of file diff --git a/sections/artist/artist.php b/sections/artist/artist.php index 528fdd29..236e61b0 100644 --- a/sections/artist/artist.php +++ b/sections/artist/artist.php @@ -61,6 +61,15 @@ function compare($X, $Y){ list($Name, $Image, $Body, $VanityHouseArtist) = $DB->next_record(MYSQLI_NUM, array(0)); } +$TokenTorrents = $Cache->get_value('users_tokens_'.$UserID); +if (empty($TokenTorrents)) { + $DB->query("SELECT TorrentID FROM users_freeleeches WHERE UserID=$UserID AND Expired=FALSE"); + $TokenTorrents = $DB->collect('TorrentID'); + $Cache->cache_value('users_tokens_'.$UserID, $TokenTorrents); +} + +$SnatchedTorrents = Torrents::get_snatched_torrents(); + //----------------- Build list and get stats ob_start(); @@ -96,16 +105,14 @@ function compare($X, $Y){ $LastReleaseType = 0; if(empty($Importances) || empty($TorrentList)) { $DB->query("SELECT - DISTINCTROW ta.GroupID, ta.Importance, tg.VanityHouse + DISTINCTROW ta.GroupID, ta.Importance, tg.VanityHouse, tg.ReleaseType FROM torrents_artists AS ta JOIN torrents_group AS tg ON tg.ID=ta.GroupID WHERE ta.ArtistID='$ArtistID' ORDER BY IF(ta.Importance IN ('2', '3', '4', '7'),1000 + ta.Importance, tg.ReleaseType) ASC, tg.Year DESC, tg.Name DESC"); - $GroupIDs = $DB->collect('GroupID'); $Importances = $DB->to_array(false, MYSQLI_BOTH, false); - if(count($GroupIDs)>0) { $TorrentList = Torrents::get_groups($GroupIDs, true,true); $TorrentList = $TorrentList['matches']; @@ -170,8 +177,19 @@ function compare($X, $Y){ if(!empty($ProducerAlbums)) { $ReleaseTypes[1021] = "Produced By"; } - - +//Custom sorting for releases +if(!empty($LoggedUser['SortHide'])) { + $SortOrder = array_keys($LoggedUser['SortHide']); + uasort($Importances, function ($a, $b) { + global $SortOrder; + $c = array_search($a['ReleaseType'], $SortOrder); + $d = array_search($b['ReleaseType'], $SortOrder); + if ($c == $d) { + return 0; + } + return $c < $d ? -1 : 1; + }); +} reset($TorrentList); if(!empty($UsedReleases)) { ?>
        @@ -191,8 +209,8 @@ function compare($X, $Y){ $DisplayName = $ReleaseTypes[$ReleaseID]."s"; break; } - - if (!empty($LoggedUser['DiscogView']) || (isset($LoggedUser['HideTypes']) && in_array($ReleaseID, $LoggedUser['HideTypes']))) { + + if (!empty($LoggedUser['DiscogView']) || (isset($LoggedUser['SortHide']) && array_key_exists($ReleaseType, $LoggedUser['SortHide']) && $LoggedUser['SortHide'][$ReleaseType] == 1)) { $ToggleStr = " onclick=\"$('.releases_$ReleaseID').show(); return true;\""; } else { $ToggleStr = ''; @@ -264,7 +282,12 @@ function compare($X, $Y){ $OldReleaseType = $ReleaseType; } - if (!empty($LoggedUser['DiscogView']) || (isset($LoggedUser['HideTypes']) && in_array($ReleaseType, $LoggedUser['HideTypes']))) { +/* if (!empty($LoggedUser['DiscogView']) || (isset($LoggedUser['HideTypes']) && in_array($ReleaseType, $LoggedUser['HideTypes']))) { + $HideDiscog = ' hidden'; + } else { + $HideDiscog = ''; + } */ + if (!empty($LoggedUser['DiscogView']) || (isset($LoggedUser['SortHide']) && array_key_exists($ReleaseType, $LoggedUser['SortHide']) && $LoggedUser['SortHide'][$ReleaseType] == 1)) { $HideDiscog = ' hidden'; } else { $HideDiscog = ''; @@ -430,8 +453,12 @@ function compare($X, $Y){ && !$Torrent['PersonalFL'] && empty($Torrent['FreeTorrent']) && ($LoggedUser['CanLeech'] == '1')) { ?> | FL ] - -   »  + + +   » 
        + + + + + + + + + +
        + # + [Report] + = $AuthorInfo['Class']) { ?> + + + + + + + + - [Warn] + + + - [Quote] + - [Edit] - [Delete] + + + + +
        + + <?=$Username ?>'s avatar + + Default avatar + + +
        +full_format($Body)?> + +
        +
        + + « + + Last edited by + + +
        +
        + + + +
        +

        Post reply

        +
        + + + + + + + + + +
        +
        + + + +
        +
        + + +
        +
        + query("SELECT CEIL((SELECT COUNT(ID)+1 FROM artist_comments AS ac WHERE ac.ArtistID='".db_string($ArtistID)."')/".TORRENT_COMMENTS_PER_PAGE.") AS Pages"); + list($Pages) = $DB->next_record(); + + $DB->query("INSERT INTO artist_comments (ArtistID,AuthorID,AddedTime,Body) VALUES ( + '".db_string($ArtistID)."', '".db_string($LoggedUser['ID'])."','".sqltime()."','".db_string($_POST['body'])."')"); + $PostID=$DB->inserted_id(); + + $CatalogueID = floor((TORRENT_COMMENTS_PER_PAGE*$Pages-TORRENT_COMMENTS_PER_PAGE)/THREAD_CATALOGUE); + $Cache->begin_transaction('artist_comments_'.$ArtistID.'_catalogue_'.$CatalogueID); + $Post = array( + 'ID'=>$PostID, + 'AuthorID'=>$LoggedUser['ID'], + 'AddedTime'=>sqltime(), + 'Body'=>$_POST['body'], + 'EditedUserID'=>0, + 'EditedTime'=>'0000-00-00 00:00:00', + 'Username'=>'' + ); + $Cache->insert('', $Post); + $Cache->commit_transaction(0); + $Cache->increment('artist_comments_'.$ArtistID); + + header('Location: artist.php?id='.$ArtistID.'&page='.$Pages); + break; + case 'warn' : + include(SERVER_ROOT.'/sections/artist/warn.php'); + break; + case 'take_warn' : + include(SERVER_ROOT.'/sections/artist/take_warn.php'); + break; + + case 'takeedit_post': + authorize(); + + include(SERVER_ROOT.'/classes/class_text.php'); // Text formatting class + $Text = new TEXT; + + // Quick SQL injection check + if(!$_POST['post'] || !is_number($_POST['post'])) { error(0); } + + // Mainly + $DB->query("SELECT + ac.Body, + ac.AuthorID, + ac.ArtistID, + ac.AddedTime + FROM artist_comments AS ac + WHERE ac.ID='".db_string($_POST['post'])."'"); + list($OldBody, $AuthorID,$ArtistID,$AddedTime)=$DB->next_record(); + + $DB->query("SELECT ceil(COUNT(ID) / ".TORRENT_COMMENTS_PER_PAGE.") AS Page FROM artist_comments WHERE ArtistID = $ArtistID AND ID <= $_POST[post]"); + list($Page) = $DB->next_record(); + + if ($LoggedUser['ID']!=$AuthorID && !check_perms('site_moderate_forums')) { error(404); } + if ($DB->record_count()==0) { error(404); } + + // Perform the update + $DB->query("UPDATE artist_comments SET + Body = '".db_string($_POST['body'])."', + EditedUserID = '".db_string($LoggedUser['ID'])."', + EditedTime = '".sqltime()."' + WHERE ID='".db_string($_POST['post'])."'"); + + // Update the cache + $CatalogueID = floor((TORRENT_COMMENTS_PER_PAGE*$Page-TORRENT_COMMENTS_PER_PAGE)/THREAD_CATALOGUE); + $Cache->begin_transaction('artist_comments_'.$ArtistID.'_catalogue_'.$CatalogueID); + + $Cache->update_row($_POST['key'], array( + 'ID'=>$_POST['post'], + 'AuthorID'=>$AuthorID, + 'AddedTime'=>$AddedTime, + 'Body'=>$_POST['body'], + 'EditedUserID'=>db_string($LoggedUser['ID']), + 'EditedTime'=>sqltime(), + 'Username'=>$LoggedUser['Username'] + )); + $Cache->commit_transaction(0); + + $DB->query("INSERT INTO comments_edits (Page, PostID, EditUser, EditTime, Body) + VALUES ('artist', ".db_string($_POST['post']).", ".db_string($LoggedUser['ID']).", '".sqltime()."', '".db_string($OldBody)."')"); + + // This gets sent to the browser, which echoes it in place of the old body + echo $Text->full_format($_POST['body']); + break; + + default: error(0); } } elseif(!empty($_GET['action'])) { - switch ($_GET['action']) { + switch ($_GET['action']) { + case 'get_post': + if (!$_GET['post'] || !is_number($_GET['post'])) { error(0); } + $DB->query("SELECT Body FROM artist_comments WHERE ID='".db_string($_GET['post'])."'"); + list($Body) = $DB->next_record(MYSQLI_NUM); + echo trim($Body); + break; + + case 'delete_comment': + authorize(); + + // Quick SQL injection check + if (!$_GET['postid'] || !is_number($_GET['postid'])) { error(0); } + + // Make sure they are moderators + if (!check_perms('site_moderate_forums')) { error(403); } + + // Get topicid, forumid, number of pages + $DB->query("SELECT + ArtistID, + CEIL(COUNT(ac.ID)/".TORRENT_COMMENTS_PER_PAGE.") AS Pages, + CEIL(SUM(IF(ac.ID<=".$_GET['postid'].",1,0))/".TORRENT_COMMENTS_PER_PAGE.") AS Page + FROM artist_comments AS ac + WHERE ac.ArtistID=(SELECT ArtistID FROM artist_comments WHERE ID=".$_GET['postid'].") + GROUP BY ac.ArtistID"); + list($ArtistID,$Pages,$Page)=$DB->next_record(); + + // $Pages = number of pages in the thread + // $Page = which page the post is on + // These are set for cache clearing. + + $DB->query("DELETE FROM artist_comments WHERE ID='".db_string($_GET['postid'])."'"); + + //We need to clear all subsequential catalogues as they've all been bumped with the absence of this post + $ThisCatalogue = floor((TORRENT_COMMENTS_PER_PAGE*$Page-TORRENT_COMMENTS_PER_PAGE)/THREAD_CATALOGUE); + $LastCatalogue = floor((TORRENT_COMMENTS_PER_PAGE*$Pages-TORRENT_COMMENTS_PER_PAGE)/THREAD_CATALOGUE); + for($i=$ThisCatalogue;$i<=$LastCatalogue;$i++) { + $Cache->delete('artist_comments_'.$ArtistID.'_catalogue_'.$i); + } + + // Delete thread info cache (eg. number of pages) + $Cache->delete('artist_comments_'.$ArtistID); + + break; + case 'edit': require(SERVER_ROOT.'/sections/artist/edit.php'); break; diff --git a/sections/artist/take_warn.php b/sections/artist/take_warn.php new file mode 100644 index 00000000..cefc5ecf --- /dev/null +++ b/sections/artist/take_warn.php @@ -0,0 +1,73 @@ + $LoggedUser['Class']) { + error(403); +} +$URL = "https://". SSL_SITE_URL."/artist.php?id=$ArtistID&postid=$PostID#post$PostID"; +if ($Length != 'verbal') { + $Time = ((int)$Length) * (7 * 24 * 60 * 60); + warn_user($UserID, $Time, "$URL - ". $Reason); + $Subject = "You have received a warning"; + $PrivateMessage = "You have received a $Length week warning for [url=$URL]this artist comment.[/url]\n\n" . $PrivateMessage; + $WarnTime = time_plus($Time); + $AdminComment = date("Y-m-d").' - Warned until '.$WarnTime.' by '.$LoggedUser['Username']."\nReason: $URL - $Reason\n\n"; +} else { + $Subject = "You have received a verbal warning"; + $PrivateMessage = "You have received a verbal warning for [url=$URL]this post.[/url]\n\n" . $PrivateMessage; + + $AdminComment = date("Y-m-d") . ' - Verbally warned by ' . $LoggedUser['Username'] . " for $URL \nReason: $Reason\n\n"; + $DB -> query('UPDATE users_info SET + Warned=\'' . db_string($WarnTime) . '\', + WarnedTimes=WarnedTimes+1, + AdminComment=CONCAT(\'' . db_string($AdminComment) . '\',AdminComment) + WHERE UserID=\'' . db_string($UserID) . '\''); + } +$DB -> query("INSERT INTO users_warnings_forums (UserID, Comment) VALUES('$UserID', '" . db_string($AdminComment) . "') + ON DUPLICATE KEY UPDATE Comment = CONCAT('" . db_string($AdminComment) . "', Comment)"); +send_pm($UserID, $LoggedUser['ID'], $Subject, $PrivateMessage); + +// Mainly +$DB -> query("SELECT + ac.Body, + ac.AuthorID, + ac.ArtistID, + ac.AddedTime + FROM artist_comments AS ac + WHERE ac.ID='$PostID'"); +list($OldBody, $AuthorID, $ArtistID, $AddedTime) = $DB -> next_record(); + +$DB -> query("SELECT ceil(COUNT(ID) / " . TORRENT_COMMENTS_PER_PAGE . ") AS Page FROM artist_comments WHERE ArtistID = $ArtistID AND ID <= $PostID"); +list($Page) = $DB -> next_record(); + +// Perform the update +$DB -> query("UPDATE Artist_comments SET + Body = '$Body', + EditedUserID = '" . db_string($LoggedUser['ID']) . "', + EditedTime = '" . sqltime() . "' + WHERE ID='$PostID'"); + +// Update the cache +$CatalogueID = floor((TORRENT_COMMENTS_PER_PAGE * $Page - TORRENT_COMMENTS_PER_PAGE) / THREAD_CATALOGUE); +$Cache -> begin_transaction('artist_comments_' . $ArtistID . '_catalogue_' . $CatalogueID); + +$Cache -> update_row($_POST['key'], array('ID' => $_POST['postid'], 'AuthorID' => $AuthorID, 'AddedTime' => $AddedTime, 'Body' => $_POST['body'], 'EditedUserID' => db_string($LoggedUser['ID']), 'EditedTime' => sqltime(), 'Username' => $LoggedUser['Username'])); +$Cache -> commit_transaction(0); + +$DB -> query("INSERT INTO comments_edits (Page, PostID, EditUser, EditTime, Body) + VALUES ('artist', " . db_string($_POST['postid']) . ", " . db_string($LoggedUser['ID']) . ", '" . sqltime() . "', '" . db_string($OldBody) . "')"); + +header("Location: artist.php?id=$ArtistID&postid=$PostID#post$PostID"); +?>; diff --git a/sections/artist/warn.php b/sections/artist/warn.php new file mode 100644 index 00000000..afcf8277 --- /dev/null +++ b/sections/artist/warn.php @@ -0,0 +1,68 @@ + query("SELECT + tc.Body, + tc.AddedTime + FROM torrents_comments AS tc + WHERE tc.ID='" . db_string($PostID) . "'"); +list($PostBody) = $DB -> next_record(); + +show_header('Warn User'); +?> + +
        +
        +

        Warning

        +
        +
        +
        + + + + + + + + + + + + + + + + + + + + + + +
        Reason: + +
        Length: +
        Private Message: + +
        Edit Post: + +
        + +
        +
        +
        + diff --git a/sections/bookmarks/add.php b/sections/bookmarks/add.php index 8555b291..24711067 100644 --- a/sections/bookmarks/add.php +++ b/sections/bookmarks/add.php @@ -18,19 +18,30 @@ $DB->query("SELECT UserID FROM $Table WHERE UserID='$LoggedUser[ID]' AND $Col='".db_string($_GET['id'])."'"); if($DB->record_count() == 0) { - $DB->query("INSERT IGNORE INTO $Table - (UserID, $Col, Time) - VALUES - ('$LoggedUser[ID]', '".db_string($_GET['id'])."', '".sqltime()."')"); + if ($Type === 'torrent') { + $DB->query('SELECT MAX(Sort) FROM `bookmarks_torrents` WHERE UserID =' . $LoggedUser['ID']); + list($Sort) = $DB->next_record(); + if (!$Sort) $Sort = 0; + $Sort += 1; + $DB->query("INSERT IGNORE INTO $Table + (UserID, $Col, Time, Sort) + VALUES + ('$LoggedUser[ID]', '".db_string($_GET['id'])."', '".sqltime()."', $Sort)"); + } else { + $DB->query("INSERT IGNORE INTO $Table + (UserID, $Col, Time) + VALUES + ('$LoggedUser[ID]', '".db_string($_GET['id'])."', '".sqltime()."')"); + } $Cache->delete_value('bookmarks_'.$Type.'_'.$LoggedUser['ID']); if ($Type == 'torrent') { $Cache->delete_value('bookmarks_torrent_'.$LoggedUser['ID'].'_full'); $GroupID = $_GET['id']; - + $DB->query("SELECT Name, Year, WikiBody, TagList FROM torrents_group WHERE ID = '$GroupID'"); list($GroupTitle, $Year, $Body, $TagList) = $DB->next_record(); $TagList = str_replace('_','.',$TagList); - + $DB->query("SELECT ID, Format, Encoding, HasLog, HasCue, LogScore, Media, Scene, FreeTorrent, UserID FROM torrents WHERE GroupID = '$GroupID'"); // RSS feed stuff while ($Torrent = $DB->next_record()) { @@ -45,9 +56,9 @@ if ($Scene == "1") { $Title .= " / Scene"; } if ($Freeleech == "1") { $Title .= " / Freeleech!"; } if ($Freeleech == "2") { $Title .= " / Neutral leech!"; } - + $UploaderInfo = Users::user_info($UploaderID); - $Item = $Feed->item($Title, + $Item = $Feed->item($Title, $Text->strip_bbcode($Body), 'torrents.php?action=download&authkey=[[AUTHKEY]]&torrent_pass=[[PASSKEY]]&id='.$TorrentID, $UploaderInfo['Username'], @@ -60,5 +71,4 @@ $Bookmarkers = $DB->collect('UserID'); $SS->UpdateAttributes('requests requests_delta', array('bookmarker'), array($_GET['id'] => array($Bookmarkers)), true); } -} -?> +} \ No newline at end of file diff --git a/sections/bookmarks/edit_torrents.php b/sections/bookmarks/edit_torrents.php new file mode 100644 index 00000000..b8c4aa5b --- /dev/null +++ b/sections/bookmarks/edit_torrents.php @@ -0,0 +1,29 @@ +query("SELECT Username FROM users_main WHERE ID='$UserID'"); + list($Username) = $DB->next_record(); +} else { + $UserID = $LoggedUser['ID']; +} + +// Finally we start + +//Require the table class +// require_once SERVER_ROOT . '/classes/class_mass_user_torrents_table_view.php'; + +View::show_header('Organize Bookmarks', 'browse,jquery'); + +$EditType = isset($_GET['type']) ? $_GET['type'] : 'torrents'; + +list($K, $GroupIDs, $CollageDataList, $TorrentList) = Users::bookmark_data($UserID); + +$TT = new MASS_USER_TORRENTS_TABLE_VIEW($TorrentList, $CollageDataList, $EditType, 'Organize Torrent Bookmarks'); +$TT->render_all(); + +View::show_footer(); \ No newline at end of file diff --git a/sections/bookmarks/index.php b/sections/bookmarks/index.php index 92d4c7b5..0334740f 100644 --- a/sections/bookmarks/index.php +++ b/sections/bookmarks/index.php @@ -2,7 +2,7 @@ enforce_login(); include(SERVER_ROOT.'/sections/bookmarks/functions.php'); -// Number of users per page +// Number of users per page define('BOOKMARKS_PER_PAGE', '20'); if (empty($_REQUEST['action'])) { $_REQUEST['action'] = 'view'; } @@ -15,7 +15,11 @@ case 'remove': require(SERVER_ROOT.'/sections/bookmarks/remove.php'); break; - + + case 'mass_edit': + require(SERVER_ROOT.'/sections/bookmarks/mass_edit.php'); + break; + case 'remove_snatched': authorize(); $DB->query("CREATE TEMPORARY TABLE snatched_groups_temp (GroupID int PRIMARY KEY)"); @@ -26,7 +30,18 @@ header('Location: bookmarks.php'); die(); break; - + + case 'edit': + if (empty($_REQUEST['type'])) { $_REQUEST['type'] = false; } + switch ($_REQUEST['type']) { + case 'torrents': + require(SERVER_ROOT.'/sections/bookmarks/edit_torrents.php'); + break; + default : error(404); + } + break; + + case 'view': if (empty($_REQUEST['type'])) { $_REQUEST['type'] = 'torrents'; } switch ($_REQUEST['type']) { @@ -52,4 +67,3 @@ default: error(404); } -?> diff --git a/sections/bookmarks/mass_edit.php b/sections/bookmarks/mass_edit.php new file mode 100644 index 00000000..a9653abc --- /dev/null +++ b/sections/bookmarks/mass_edit.php @@ -0,0 +1,16 @@ +mass_remove(); + else if ($_POST['update']) + $BU->mass_update(); +} + +header('Location: bookmarks.php?type=torrents'); \ No newline at end of file diff --git a/sections/bookmarks/torrents.php b/sections/bookmarks/torrents.php index 1381a07b..c4592ee2 100644 --- a/sections/bookmarks/torrents.php +++ b/sections/bookmarks/torrents.php @@ -1,5 +1,5 @@ get_value('bookmarks_torrent_'.$UserID.'_full'); +list($K, $GroupIDs, $CollageDataList, $TorrentList) = Users::bookmark_data($UserID); -if($Data) { - $Data = unserialize($Data); - list($K, list($TorrentList, $CollageDataList)) = each($Data); -} else { - // Build the data for the collage and the torrent list - $DB->query("SELECT - bt.GroupID, - tg.WikiImage, - tg.CategoryID, - bt.Time - FROM bookmarks_torrents AS bt - JOIN torrents_group AS tg ON tg.ID=bt.GroupID - WHERE bt.UserID='$UserID' - ORDER BY bt.Time"); - - $GroupIDs = $DB->collect('GroupID'); - $CollageDataList=$DB->to_array('GroupID', MYSQLI_ASSOC); - if(count($GroupIDs)>0) { - $TorrentList = Torrents::get_groups($GroupIDs); - $TorrentList = $TorrentList['matches']; - } else { - $TorrentList = array(); - } +$TokenTorrents = Users::token_torrents($UserID); + +$TokenTorrents = $Cache->get_value('users_tokens_'.$UserID); +if (empty($TokenTorrents)) { + $DB->query("SELECT TorrentID FROM users_freeleeches WHERE UserID=$UserID AND Expired=FALSE"); + $TokenTorrents = $DB->collect('TorrentID'); + $Cache->cache_value('users_tokens_'.$UserID, $TokenTorrents); } - +$SnatchedTorrents = Torrents::get_snatched_torrents(); $Title = ($Sneaky)?"$Username's bookmarked torrents":'Your bookmarked torrents'; // Loop through the result set, building up $Collage and $TorrentTable @@ -63,11 +47,11 @@ function compare($X, $Y){ foreach ($TorrentList as $GroupID=>$Group) { list($GroupID, $GroupName, $GroupYear, $GroupRecordLabel, $GroupCatalogueNumber, $TagList, $ReleaseType, $GroupVanityHouse, $Torrents, $GroupArtists, $ExtendedArtists) = array_values($Group); - list($GroupID2, $Image, $GroupCategoryID, $AddedTime) = array_values($CollageDataList[$GroupID]); - + list($GroupID2, $Sort, $Image, $GroupCategoryID, $AddedTime) = array_values($CollageDataList[$GroupID]); + // Handle stats and stuff $NumGroups++; - + if($GroupArtists) { foreach($GroupArtists as $Artist) { if(!isset($Artists[$Artist['id']])) { @@ -77,7 +61,7 @@ function compare($X, $Y){ } } } - + $TagList = explode(' ',str_replace('_','.',$TagList)); $TorrentTags = array(); @@ -105,9 +89,9 @@ function compare($X, $Y){ $DisplayName .= ''.$GroupName.''; if($GroupYear>0) { $DisplayName = $DisplayName. ' ['. $GroupYear .']';} if($GroupVanityHouse) { $DisplayName .= ' [VH]'; } - + // Start an output buffer, so we can store this output in $TorrentTable - ob_start(); + ob_start(); if(count($Torrents)>1 || $GroupCategoryID==1) { // Grouped torrents $ShowGroups = !(!empty($LoggedUser['TorrentGrouping']) && $LoggedUser['TorrentGrouping'] == 1); @@ -139,10 +123,10 @@ function compare($X, $Y){ $LastRemasterRecordLabel = ''; $LastRemasterCatalogueNumber = ''; $LastMedia = ''; - + $EditionID = 0; unset($FirstUnknown); - + foreach ($Torrents as $TorrentID => $Torrent) { if ($Torrent['Remastered'] && !$Torrent['RemasterYear']) { @@ -151,17 +135,17 @@ function compare($X, $Y){ if($Torrent['RemasterTitle'] != $LastRemasterTitle || $Torrent['RemasterYear'] != $LastRemasterYear || $Torrent['RemasterRecordLabel'] != $LastRemasterRecordLabel || $Torrent['RemasterCatalogueNumber'] != $LastRemasterCatalogueNumber || $FirstUnknown || $Torrent['Media'] != $LastMedia) { - + $EditionID++; if($Torrent['Remastered'] && $Torrent['RemasterYear'] != 0) { - + $RemasterName = $Torrent['RemasterYear']; $AddExtra = " - "; if($Torrent['RemasterRecordLabel']) { $RemasterName .= $AddExtra.display_str($Torrent['RemasterRecordLabel']); $AddExtra=' / '; } if($Torrent['RemasterCatalogueNumber']) { $RemasterName .= $AddExtra.display_str($Torrent['RemasterCatalogueNumber']); $AddExtra=' / '; } if($Torrent['RemasterTitle']) { $RemasterName .= $AddExtra.display_str($Torrent['RemasterTitle']); $AddExtra=' / '; } $RemasterName .= $AddExtra.display_str($Torrent['Media']); - + ?> @@ -199,6 +183,10 @@ function compare($X, $Y){ | RP ] +   »  @@ -210,9 +198,9 @@ function compare($X, $Y){ } } else { // Viewing a type that does not require grouping - + list($TorrentID, $Torrent) = each($Torrents); - + $DisplayName = ''.$GroupName.''; if(!empty($Torrent['FreeTorrent'])) { @@ -233,7 +221,7 @@ function compare($X, $Y){ 0) && ($Torrent['Size'] < 1073741824) && !$Torrent['PersonalFL'] && empty($Torrent['FreeTorrent']) && ($LoggedUser['CanLeech'] == '1')) { ?> | FL - + | RP ] @@ -252,11 +240,11 @@ function compare($X, $Y){
      4. - 0) { ?>

        [Remove Snatched] + [Manage Torrents]
      5. @@ -341,7 +330,7 @@ function compare($X, $Y){ $i++; if($i>5) { break; } ?> -
      6. ()
      7. +
      8. ()
      9. @@ -359,7 +348,7 @@ function compare($X, $Y){ $i++; if($i>10) { break; } ?> -
      10. ()
      11. +
      12. ()
      13. @@ -394,7 +383,7 @@ function compare($X, $Y){ -
        @@ -414,4 +403,3 @@ function compare($X, $Y){ cache_value('bookmarks_torrent_'.$UserID.'_full', serialize(array(array($TorrentList, $CollageDataList))), 3600); -?> diff --git a/sections/collages/all_comments.php b/sections/collages/all_comments.php index 9e3a5387..bf533c16 100644 --- a/sections/collages/all_comments.php +++ b/sections/collages/all_comments.php @@ -108,19 +108,21 @@ if($ThreadInfo['MinClassWrite'] <= $LoggedUser['Class'] && !$LoggedUser['DisablePosting']) { ?>
        -

        Post reply

        -
        +
        +

        Post reply

        +
        - - - - -
        -
        -
        - - - + + + + +
        +
        +
        + + + +
        get_value('users_tokens_'.$UserID); +if (empty($TokenTorrents)) { + $DB->query("SELECT TorrentID FROM users_freeleeches WHERE UserID=$UserID AND Expired=FALSE"); + $TokenTorrents = $DB->collect('TorrentID'); + $Cache->cache_value('users_tokens_'.$UserID, $TokenTorrents); +} +$SnatchedTorrents = Torrents::get_snatched_torrents(); + $Data = $Cache->get_value('collage_'.$CollageID); if($Data) { @@ -244,6 +252,10 @@ function compare($X, $Y){ | RP ] +   » 
        diff --git a/sections/collages/manage.php b/sections/collages/manage.php index d6258eeb..4469a6fe 100644 --- a/sections/collages/manage.php +++ b/sections/collages/manage.php @@ -41,7 +41,7 @@

        Manage collage

        - +
        Sorting
        Sorting
          @@ -51,7 +51,7 @@
        • Press Save All Changes when you are finished sorting.
        • Press Edit or Remove to simply modify one entry.
        - +
        @@ -63,14 +63,14 @@ Order - Δ + # Year Artist Torrent User - Tweak + Tweak - + " id="sort_" size="4" /> - - - - + + + + diff --git a/sections/comments/artistcomments.php b/sections/comments/artistcomments.php new file mode 100644 index 00000000..16b04b70 --- /dev/null +++ b/sections/comments/artistcomments.php @@ -0,0 +1,68 @@ +query("SELECT + SQL_CALC_FOUND_ROWS + ac.AuthorID, + a.ArtistID, + a.Name, + ac.ID, + ac.Body, + ac.AddedTime, + ac.EditedTime, + ac.EditedUserID as EditorID + + FROM artists_group as a + JOIN artist_comments as ac ON ac.ArtistID = a.ArtistID + + WHERE ac.AuthorId = $UserID + + GROUP BY ac.ID + + ORDER BY ac.AddedTime DESC + + LIMIT $Limit; +"); + +$DB->query("SELECT FOUND_ROWS()"); +list($Results) = $DB->next_record(); +$Pages=get_pages($Page,$Results,$PerPage, 11); + +$DB->set_query_id($Comments); +$GroupIDs = $DB->collect('GroupID'); + + +show_header($Title,'bbcode'); +$DB->set_query_id($Comments); + +?>
        +
        +

        + + + +
        + +next_record()) { + $permalink = "artist.php?id=$ArtistID&postid=$PostID#post$PostID"; + $postheader = " on " . "$ArtistName"; + + comment_body($UserID, $PostID, $postheader, $permalink, $Body, $EditorID, $EditedTime); + +} /* end while loop*/ ?> + +
        + t.Time"; - $Title = 'Comments left on your torrents'; - $Header = 'Comments left on your uploads'; - if($Self) $OtherLink = 'Display comments you\'ve made'; -} -else { - $Conditions = "WHERE tc.AuthorID = $UserID"; - $Title = 'Comments made by '.($Self?'you':$Username); - $Header = 'Torrent comments left by '.($Self?'you':Users::format_username($UserID, false, false, false)).''; - if($Self) $OtherLink = 'Display comments left on your uploads'; +switch($action) { +case 'artists': + require (SERVER_ROOT.'/sections/comments/artistcomments.php'); + break; +case 'torrents': +case 'my_torrents': +default: + require(SERVER_ROOT.'/sections/comments/torrentcomments.php'); + break; } -$Comments = $DB->query("SELECT - SQL_CALC_FOUND_ROWS - tc.AuthorID, - t.ID, - t.GroupID, - tg.Name, - tc.ID, - tc.Body, - tc.AddedTime, - tc.EditedTime, - tc.EditedUserID as EditorID - - FROM torrents as t - JOIN torrents_comments as tc ON tc.GroupID = t.GroupID - JOIN torrents_group as tg ON t.GroupID = tg.ID - - $Conditions - - GROUP BY tc.ID - - ORDER BY tc.AddedTime DESC - - LIMIT $Limit; -"); - -$DB->query("SELECT FOUND_ROWS()"); -list($Results) = $DB->next_record(); -$Pages=Format::get_pages($Page,$Results,$PerPage, 11); - -$DB->set_query_id($Comments); -$GroupIDs = $DB->collect('GroupID'); - -$Artists = Artists::get_artists($GroupIDs); - -View::show_header($Title,'bbcode'); -$DB->set_query_id($Comments); - -?>
        -
        -

        - - - -
        - -next_record()) { - $UserInfo = Users::user_info($UserID); - ?> - - - - - - - - - - -
        - # - by - on - -
        - - <?=$UserInfo['Username']?>'s avatar - - Default avatar - - - full_format($Body) ?> - -

        - Last edited by - - - -
        - - -
        - diff --git a/sections/comments/post.php b/sections/comments/post.php new file mode 100644 index 00000000..03eafd9f --- /dev/null +++ b/sections/comments/post.php @@ -0,0 +1,50 @@ +" . Users::format_username($UserID, true, true, true, true, false) . " " + . time_diff($AddedTime) . $postheader; + +?> + ' id="post"> + + + + + + + + + +
        + # + + +
        + + ' width='150' alt="'s avatar" /> + + Default avatar + + + full_format($Body) ?> + +

        + Last edited by + + +
        + t.Time"; + $Title = 'Comments left on your torrents'; + $Header = 'Comments left on your uploads'; + if($Self) $OtherLink = 'Display comments you\'ve made'; +} +else { + $Conditions = "WHERE tc.AuthorID = $UserID"; + $Title = 'Comments made by '.($Self?'you':$Username); + $Header = 'Torrent comments left by '.($Self?'you':Users::format_username($UserID, false, false, false)).''; + if($Self) $OtherLink = 'Display comments left on your uploads'; +} + +$Comments = $DB->query("SELECT + SQL_CALC_FOUND_ROWS + tc.AuthorID, + t.ID, + t.GroupID, + tg.Name, + tc.ID, + tc.Body, + tc.AddedTime, + tc.EditedTime, + tc.EditedUserID as EditorID + + FROM torrents as t + JOIN torrents_comments as tc ON tc.GroupID = t.GroupID + JOIN torrents_group as tg ON t.GroupID = tg.ID + + $Conditions + + GROUP BY tc.ID + + ORDER BY tc.AddedTime DESC + + LIMIT $Limit; +"); + +$DB->query("SELECT FOUND_ROWS()"); +list($Results) = $DB->next_record(); +$Pages=Format::get_pages($Page,$Results,$PerPage, 11); + +$DB->set_query_id($Comments); +$GroupIDs = $DB->collect('GroupID'); + +$Artists = Artists::get_artists($GroupIDs); + +View::show_header($Title,'bbcode'); +$DB->set_query_id($Comments); + +?>
        +
        +

        + + + +
        + +next_record()) { + $permalink = "torrents.php?id=$GroupID&postid=$PostID#post$PostID"; + $postheader = " on " . Artists::display_artists($Artists[$GroupID]) . " \">$Title"; + + comment_body($UserID, $PostID, $postheader, $permalink, $Body, $EditorID, $AddedTime, $EditedTime); + +} /* end while loop*/ ?> + +
        +query("SELECT Body FROM ".$Type."_comments diff --git a/sections/forums/functions.php b/sections/forums/functions.php index 39230f88..2cfae87f 100644 --- a/sections/forums/functions.php +++ b/sections/forums/functions.php @@ -10,8 +10,9 @@ function get_thread_info($ThreadID, $Return = true, $SelectiveCache = false) { COUNT(fp.id) AS Posts, t.LastPostAuthorID, ISNULL(p.TopicID) AS NoPoll, - t.StickyPostID - FROM forums_topics AS t + t.StickyPostID, + t.AuthorID as OP + FROM forums_topics AS t JOIN forums_posts AS fp ON fp.TopicID = t.ID LEFT JOIN forums_polls AS p ON p.TopicID=t.ID WHERE t.ID = '$ThreadID' diff --git a/sections/forums/quote_notify.php b/sections/forums/quote_notify.php new file mode 100644 index 00000000..959aab3c --- /dev/null +++ b/sections/forums/quote_notify.php @@ -0,0 +1,54 @@ +query("SELECT m.ID FROM users_main AS m + JOIN users_info AS i ON i.UserID = m.ID WHERE m.Username IN " . "('" . implode("', '", $Usernames) + . "') + AND i.NotifyOnQuote = '1' AND i.UserID != $LoggedUser[ID]"); +while (list($UserID) = $DB->next_record()) { + $QuoterID = db_string($LoggedUser['ID']); + $UserID = db_string($UserID); + $ForumID = db_string($ForumID); + $TopicID = db_string($TopicID); + $PostID = db_string($PostID); + $DB->query("INSERT INTO users_notify_quoted (UserID, QuoterID, ForumID, TopicID, PostID, Date) + VALUES ('$UserID', '$QuoterID', '$ForumID', '$TopicID', '$PostID', '" . sqltime() . "')"); + $Cache->delete_value('forums_quotes_' . $UserID); +} + +/* + * Validate the username and add it into the $Usernames array + */ +function add_username($Str) { + global $Usernames; + $Matches = array(); + if (preg_match('/\[quote=(.*)]/', $Str, $Matches)) { + $Username = $Matches[1]; + $Username = trim($Username); + if (strlen($Username) > 0 && !preg_match('/[^a-zA-Z0-9|]/i', $Username)) { + $Exploded = explode('|', $Username); + $Username = $Exploded[0]; + $Username = preg_replace('/(^[.,]*)|([.,]*$)/', '', $Username); + $Usernames[] = $Username; + } + } +} +?> diff --git a/sections/forums/take_reply.php b/sections/forums/take_reply.php index ec6fc1de..60b3bcf1 100644 --- a/sections/forums/take_reply.php +++ b/sections/forums/take_reply.php @@ -232,6 +232,6 @@ $Cache->delete_value('subscriptions_user_new_'.$Subscriber); } } - +include('quote_notify.php'); header('Location: forums.php?action=viewthread&threadid='.$TopicID.'&page='.ceil($ThreadInfo['Posts']/$PerPage)); die(); diff --git a/sections/forums/thread.php b/sections/forums/thread.php index 10218b59..019c8626 100644 --- a/sections/forums/thread.php +++ b/sections/forums/thread.php @@ -13,7 +13,7 @@ include(SERVER_ROOT.'/classes/class_text.php'); -$Text = new TEXT; +$Text = new TEXT(true); // Check for lame SQL injection attempts if(!isset($_GET['threadid']) || !is_number($_GET['threadid'])) { @@ -137,8 +137,10 @@ $Cache->delete_value('subscriptions_user_new_'.$LoggedUser['ID']); } +$DB->query("UPDATE users_notify_quoted SET Unread = '0' WHERE UserID = '$LoggedUser[ID]' AND TopicID = '$ThreadID'"); + // Start printing -View::show_header('Forums'.' > '.$Forums[$ForumID]['Name'].' > '.$ThreadInfo['Title'],'comments,subscriptions,bbcode'); +View::show_header($ThreadInfo['Title'] . ' < '.$Forums[$ForumID]['Name'].' < '. 'Forums','comments,subscriptions,bbcode,jquery'); ?>

        @@ -188,13 +190,13 @@ $Answers = unserialize($Answers); $DB->query("SELECT Vote, COUNT(UserID) FROM forums_polls_votes WHERE TopicID='$ThreadID' GROUP BY Vote"); $VoteArray = $DB->to_array(false, MYSQLI_NUM); - + $Votes = array(); foreach ($VoteArray as $VoteSet) { - list($Key,$Value) = $VoteSet; + list($Key,$Value) = $VoteSet; $Votes[$Key] = $Value; } - + foreach(array_keys($Answers) as $i) { if (!isset($Votes[$i])) { $Votes[$i] = 0; @@ -202,7 +204,7 @@ } $Cache->cache_value('polls_'.$ThreadID, array($Question,$Answers,$Votes,$Featured,$Closed), 0); } - + if (!empty($Votes)) { $TotalVotes = array_sum($Votes); $MaxVotes = max($Votes); @@ -210,7 +212,7 @@ $TotalVotes = 0; $MaxVotes = 0; } - + $RevealVoters = in_array($ForumID, $ForumsRevealVoters); //Polls lose the you voted arrow thingy $DB->query("SELECT Vote FROM forums_polls_votes WHERE UserID='".$LoggedUser['ID']."' AND TopicID='$ThreadID'"); @@ -230,7 +232,7 @@

          - $Answer) { if (!empty($Votes[$i]) && $TotalVotes > 0) { @@ -273,11 +275,11 @@ $DB->query("SELECT fpv.Vote AS Vote, GROUP_CONCAT(um.Username SEPARATOR ', ') - FROM users_main AS um + FROM users_main AS um LEFT JOIN forums_polls_votes AS fpv ON um.ID = fpv.UserID WHERE TopicID = ".$ThreadID." GROUP BY fpv.Vote"); - + $StaffVotesTmp = $DB->to_array(); $StaffCount = count($StaffNames); @@ -316,7 +318,7 @@
          @@ -366,7 +368,7 @@

        - - +
        id="post"> + + + + ">
        @@ -480,4 +510,4 @@ function generate_torrent_table($Caption, $Tag, $Details, $Limit) {
        # @@ -448,7 +450,7 @@

        - « + « Last edited by @@ -472,56 +474,64 @@ //TODO: Preview, come up with a standard, make it look like post or just a block of formatted BBcode, but decide and write some proper XHTML ?>
        -

        Post reply

        -
        - - - + + + + + +
        onsubmit="quickpostform.submit_button.disabled=true;" method="post"> - - - + + + -
        -
        -
        -
        +
        +
        +
        +
        - tabindex="2" /> - + tabindex="2" /> + - - + +
        + + +
        Move thread
        - + @@ -293,39 +293,39 @@ - + - + - + - + - + - + @@ -358,8 +358,8 @@ $GroupLink = Artists::display_artists($Group['ExtendedArtists']).''.$Group['Name'].'';*/ ?> - - + + @@ -374,7 +374,7 @@ $TimeAdded) { ?> - + @@ -570,43 +570,45 @@
        -

        Post comment

        -
        -
        Record labelRecord Label
        Catalogue numberCatalogue Number
        Release typeRelease Type
        Acceptable bitratesAcceptable Bitrates
        Acceptable formatsAcceptable Formats
        Acceptable mediaAcceptable Media
        Required FLAC-only extrasRequired FLAC only extra(s)
        Torrent grouptorrents.php?id=Torrent Grouptorrents.php?id=
        Last votedLast Voted
        - - - - - - - - +
        +

        Post comment

        +
        + + + + + + + + +
        -
        - - - -
        -
        - - -
        +
        + + + +
        +
        + + + +
        diff --git a/sections/tools/index.php b/sections/tools/index.php index 8c89101a..a81ad6c4 100644 --- a/sections/tools/index.php +++ b/sections/tools/index.php @@ -142,9 +142,12 @@ if(!check_perms('admin_manage_news')){ error(403); } $DB->query("INSERT INTO news (UserID, Title, Body, Time) VALUES ('$LoggedUser[ID]', '".db_string($_POST['title'])."', '".db_string($_POST['body'])."', '".sqltime()."')"); + + + $Cache->cache_value('news_latest_id', $DB->inserted_id(), 0); $Cache->delete_value('news'); - + header('Location: index.php'); break; diff --git a/sections/tools/managers/news.php b/sections/tools/managers/news.php index ac5aa7af..88a72076 100644 --- a/sections/tools/managers/news.php +++ b/sections/tools/managers/news.php @@ -15,7 +15,6 @@ $DB->query("UPDATE news SET Title='".db_string($_POST['title'])."', Body='".db_string($_POST['body'])."' WHERE ID='".db_string($_POST['newsid'])."'"); $Cache->delete_value('news'); $Cache->delete_value('feed_news'); - } header('Location: index.php'); break; @@ -35,9 +34,9 @@
        - + - +

        Title

        /> @@ -53,7 +52,7 @@

        News archive

        - + query("SELECT n.ID,n.Title,n.Body,n.Time FROM news AS n ORDER BY n.Time DESC");// LIMIT 20 while(list($NewsID,$Title,$Body,$NewsTime)=$DB->next_record()) { @@ -61,10 +60,10 @@
        - posted - - [Edit] + - [Edit] [Delete]
        - +
        full_format($Body) ?>
        diff --git a/sections/top10/history.php b/sections/top10/history.php index 8bf99b40..1a9aace3 100644 --- a/sections/top10/history.php +++ b/sections/top10/history.php @@ -11,6 +11,7 @@ [Users] [Tags] [History] + [Favorites]
        diff --git a/sections/top10/index.php b/sections/top10/index.php index 587e3267..a2133d8b 100644 --- a/sections/top10/index.php +++ b/sections/top10/index.php @@ -26,6 +26,9 @@ case 'history' : include(SERVER_ROOT.'/sections/top10/history.php'); break; + /*case 'votes' : + include(SERVER_ROOT.'/sections/top10/votes.php'); + break;*/ default : error(404); break; diff --git a/sections/top10/tags.php b/sections/top10/tags.php index 09935174..d32672bb 100644 --- a/sections/top10/tags.php +++ b/sections/top10/tags.php @@ -19,7 +19,9 @@ [Torrents] [Users] [Tags] -
        + +
        @@ -47,6 +50,8 @@ [Torrents] [Users] [Tags] +
        " />
        + >  + > +
        Format @@ -116,7 +127,11 @@

        Top @@ -421,7 +436,6 @@ function generate_torrent_table($Caption, $Tag, $Details, $Limit) { if($GroupCategoryID==1 && $ReleaseType > 0) { $DisplayName.= ' ['.$ReleaseTypes[$ReleaseType].']'; } - // append extra info to torrent title $ExtraInfo=''; $AddExtra=''; @@ -434,9 +448,12 @@ function generate_torrent_table($Caption, $Tag, $Details, $Limit) { if($Scene) { $ExtraInfo.=$AddExtra.'Scene'; $AddExtra=' / '; } if($Year>0) { $ExtraInfo.=$AddExtra.$Year; $AddExtra=' '; } if($RemasterTitle) { $ExtraInfo.=$AddExtra.$RemasterTitle; } + if(array_key_exists($TorrentID, $SnatchedTorrents)) { $ExtraInfo.=' / Snatched!'; } if($ExtraInfo!='') { $ExtraInfo = "- [$ExtraInfo]"; } + + $TagList=array(); @@ -454,7 +471,7 @@ function generate_torrent_table($Caption, $Tag, $Details, $Limit) { // print row ?> -

        [ DL ] + + + + Remove Bookmark + + Bookmark + + +

        \ No newline at end of file +?> diff --git a/sections/top10/users.php b/sections/top10/users.php index c9f8d074..9f655302 100644 --- a/sections/top10/users.php +++ b/sections/top10/users.php @@ -19,6 +19,8 @@ [Torrents] [Users] [Tags] + :]]'"; + } + } + } + $Year1 = (int)$_GET['year1']; + $Year2 = (int)$_GET['year2']; + if ($Year1 > 0 && $Year2 <= 0) { + $Where[] = "g.Year = $Year1"; + } elseif ($Year1 > 0 && $Year2 > 0) { + $Where[] = "g.Year BETWEEN $Year1 AND $Year2"; + } elseif ($Year2 > 0 && $Year1 <= 0) { + $Where[] = "g.Year <= $Year2"; + } +} else { + $Details = 'all'; + // defaults to 10 (duh) + $Limit = isset($_GET['limit']) ? intval($_GET['limit']) : 10; + $Limit = in_array($Limit, array(10, 100, 250)) ? $Limit : 10; +} +$Filtered = !empty($Where); + + +$Where = implode(' AND ', $Where); +$WhereSum = (empty($Where)) ? '' : md5($Where); + +// Unlike the other top 10s, this query just gets some raw stats +// We'll need to do some fancy-pants stuff to translate it into +// BPCI scores before getting the torrent data +$Query = "SELECT v.GroupID + FROM torrents_votes AS v"; +if (!empty($Where)) { + $Query .= " JOIN torrents_group AS g ON g.ID = v.GroupID + WHERE $Where AND "; +} else { + $Query .= " WHERE "; +} +$Query .= "Score > 0 ORDER BY Score DESC LIMIT $Limit"; + +$TopVotes = $Cache->get_value('top10votes_'.$Limit.$WhereSum); +if ($TopVotes === false) { + if (true || $Cache->get_query_lock('top10votes')) { + $DB->query($Query); + + $Results = $DB->collect('GroupID'); + $Groups = Torrents::get_groups($Results); + if (count($Results) > 0) { + $DB->query('SELECT ID, CategoryID FROM torrents_group + WHERE ID IN ('.implode(',', $Results).')'); + $Cats = $DB->to_array('ID'); + } + // Make sure it's still in order. + $TopVotes = array(); + foreach ($Results as $GroupID) { + $TopVotes[$GroupID] = $Groups['matches'][$GroupID]; + $TopVotes[$GroupID]['CategoryID'] = $Cats[$GroupID]['CategoryID']; + } + + $Cache->cache_value('top10votes_'.$Limit.$WhereSum,$TopVotes,60*30); + $Cache->clear_query_lock('top10votes'); + } else { + $TopVotes = false; + } +} +$SnatchedTorrents = Torrents::get_snatched_torrents(); +View::show_header('Top '.$Limit.' Voted Groups','browse'); +?> +
        +
        +

        Top Voted Groups

        + +
        + +
        + + + + + + + + + + + + + + +
        Tags (comma-separated): + +
        Year: + + to + +
        + +
        +
        + +

        Top + + + + - [Top 10] + - [Top 100] + - [Top 250] + + - [Top 10] + - [Top 100] + - [Top 250] + + - [Top 10] + - [Top 100] + - [Top 250] + + + +

        +$Group) { + list($GroupID, $GroupName, $GroupYear, $GroupRecordLabel, + $GroupCatalogueNumber, $TagList, $ReleaseType, $GroupVanityHouse, + $Torrents, $GroupArtists, $ExtendedArtists, $GroupCategoryID) = array_values($Group); + + // Handle stats and stuff + $Number++; + $NumGroups++; + + $TagList = explode(' ',str_replace('_','.',$TagList)); + $TorrentTags = array(); + foreach($TagList as $Tag) { + $TorrentTags[]=''.$Tag.''; + } + $PrimaryTag = $TagList[0]; + $TorrentTags = implode(', ', $TorrentTags); + $TorrentTags='
        '.$TorrentTags.'
        '; + + $DisplayName = $Number.' - '; + + if (!empty($ExtendedArtists[1]) || !empty($ExtendedArtists[4]) || !empty($ExtendedArtists[5])|| !empty($ExtendedArtists[6])) { + unset($ExtendedArtists[2]); + unset($ExtendedArtists[3]); + $DisplayName .= Artists::display_artists($ExtendedArtists); + } elseif(count($GroupArtists)>0) { + $DisplayName .= Artists::display_artists(array('1'=>$GroupArtists)); + } + + $DisplayName .= ''.$GroupName.''; + if($GroupYear>0) { $DisplayName = $DisplayName. ' ['. $GroupYear .']';} + if($GroupVanityHouse) { $DisplayName .= ' [VH]'; } + // Start an output buffer, so we can store this output in $TorrentTable + ob_start(); + + if(count($Torrents)>1 || $GroupCategoryID==1) { + // Grouped torrents +?> + + +
        + +
        + + +
        + + + + + [ Unbookmark ] + + [ Bookmark ] + + + + + + + + + $Torrent) { + + if ($Torrent['Remastered'] && !$Torrent['RemasterYear']) { + $FirstUnknown = !isset($FirstUnknown); + } + + if (in_array($TorrentID, $TokenTorrents) && empty($Torrent['FreeTorrent'])) { + $Torrent['PersonalFL'] = 1; + } + + if($Torrent['RemasterTitle'] != $LastRemasterTitle || $Torrent['RemasterYear'] != $LastRemasterYear || + $Torrent['RemasterRecordLabel'] != $LastRemasterRecordLabel || $Torrent['RemasterCatalogueNumber'] != $LastRemasterCatalogueNumber || $FirstUnknown || $Torrent['Media'] != $LastMedia) { + $EditionID++; + if($Torrent['Remastered'] && $Torrent['RemasterYear'] != 0) { + $RemasterName = $Torrent['RemasterYear']; + $AddExtra = " - "; + if($Torrent['RemasterRecordLabel']) { $RemasterName .= $AddExtra.display_str($Torrent['RemasterRecordLabel']); $AddExtra=' / '; } + if($Torrent['RemasterCatalogueNumber']) { $RemasterName .= $AddExtra.display_str($Torrent['RemasterCatalogueNumber']); $AddExtra=' / '; } + if($Torrent['RemasterTitle']) { $RemasterName .= $AddExtra.display_str($Torrent['RemasterTitle']); $AddExtra=' / '; } + $RemasterName .= $AddExtra.display_str($Torrent['Media']); + +?> + + + + + + + + + + + + [ DL + 0) && ($Torrent['Size'] < 1073741824) + && !in_array($TorrentID, $TokenTorrents) && empty($Torrent['FreeTorrent']) && ($LoggedUser['CanLeech'] == '1')) { ?> + | FL + + | RP ] + +   »  + + + + > + + +'.$GroupName.''; + + if(array_key_exists($TorrentID, $SnatchedTorrents)) { $DisplayName.=' Snatched!'; } + + if(!empty($Torrent['FreeTorrent'])) { + $DisplayName .=' Freeleech!'; + } elseif(in_array($TorrentID, $TokenTorrents)) { + $DisplayName .= $AddExtra.'Personal Freeleech!'; + } +?> + + + +
        +
        + + + + [ DL + 0) && ($Torrent['Size'] < 1073741824) + && !in_array($TorrentID, $TokenTorrents) && empty($Torrent['FreeTorrent']) && ($LoggedUser['CanLeech'] == '1')) { ?> + | FL + + | RP + + | Unbookmark + + | Bookmark + + ] + + + + + + + > + + + + + + + + + + + + + + + + + + + + + + +
        TorrentsSizeSnatchesSeedersLeechers
        Server is busy processing another top list request. Please try again in a minute.
        No torrents were found that meet your criteria.
        +
        + \ No newline at end of file diff --git a/sections/torrents/details.php b/sections/torrents/details.php index ed879e33..5aeb0804 100644 --- a/sections/torrents/details.php +++ b/sections/torrents/details.php @@ -80,6 +80,13 @@ function compare($X, $Y){ die(); }*/ +$TokenTorrents = $Cache->get_value('users_tokens_'.$UserID); +if (empty($TokenTorrents)) { + $DB->query("SELECT TorrentID FROM users_freeleeches WHERE UserID=$UserID AND Expired=FALSE"); + $TokenTorrents = $DB->collect('TorrentID'); + $Cache->cache_value('users_tokens_'.$UserID, $TokenTorrents); +} +$SnatchedTorrents = Torrents::get_snatched_torrents(); // Start output View::show_header($Title,'browse,comments,torrent,bbcode'); ?> @@ -357,6 +364,9 @@ function compare($X, $Y){ Tagging rules + +
        @@ -463,6 +473,7 @@ function filelist($Str) { if(!$ExtraInfo) { $ExtraInfo = $GroupName ; $AddExtra=' / '; } + if(array_key_exists($TorrentID, $SnatchedTorrents)) {$ExtraInfo.=$AddExtra.'Snatched!'; $AddExtra=' / '; } if($FreeTorrent == '1') { $ExtraInfo.=$AddExtra.'Freeleech!'; $AddExtra=' / '; } if($FreeTorrent == '2') { $ExtraInfo.=$AddExtra.'Neutral Leech!'; $AddExtra=' / '; } if($PersonalFL) { $ExtraInfo.=$AddExtra.'Personal Freeleech!'; $AddExtra=' / '; } @@ -566,18 +577,18 @@ function filelist($Str) { @@ -728,13 +739,17 @@ function filelist($Str) {
        get_value('torrent_comments_'.$GroupID); if($Results === false) { $DB->query("SELECT @@ -798,7 +813,7 @@ function filelist($Str) { + + + + + - +
        -
        # + # [Report] ','');">[Quote] - [Edit] - [Delete] -
        + @@ -860,43 +875,45 @@ function filelist($Str) {
        -

        Post reply

        -
        - - - + + + + + +
        -
        - - - -
        -
        - - -
        +
        + + + +
        +
        + + + +
        diff --git a/sections/torrents/download.php b/sections/torrents/download.php index edb3b73d..31e22b10 100644 --- a/sections/torrents/download.php +++ b/sections/torrents/download.php @@ -144,6 +144,30 @@ $DB->query("INSERT IGNORE INTO users_downloads (UserID, TorrentID, Time) VALUES ('$UserID', '$TorrentID', '".sqltime()."')"); +$SnatchedTorrents = $Cache->get_value('users_snatched_'.$UserID); +if (empty($SnatchedTorrents)) { + $DB->query("SELECT DISTINCT fid as TorrentID FROM xbt_snatched WHERE uid='$UserID' ORDER BY TorrentID ASC"); + $SnatchedTorrents = array_flip($DB->collect('TorrentID')); + $Cache->cache_value('users_snatched_'.$UserID, $SnatchedTorrents, 86400); +} +if(!array_key_exists($TorrentID, $SnatchedTorrents)) { + $SnatchedTorrents[$TorrentID] = 1; + $Cache->cache_value('users_snatched_'.$UserID, $SnatchedTorrents, 86400); +} + + +$SnatchedTorrents = $Cache->get_value('users_snatched_'.$UserID); +if (empty($SnatchedTorrents)) { + $DB->query("SELECT DISTINCT fid as TorrentID FROM xbt_snatched WHERE uid='$UserID' ORDER BY TorrentID ASC"); + $SnatchedTorrents = array_flip($DB->collect('TorrentID')); + $Cache->cache_value('users_snatched_'.$UserID, $SnatchedTorrents, 86400); +} +if(!array_key_exists($TorrentID, $SnatchedTorrents)) { + $SnatchedTorrents[$TorrentID] = 1; + $Cache->cache_value('users_snatched_'.$UserID, $SnatchedTorrents, 86400); +} + + $DB->query("SELECT File FROM torrents_files WHERE TorrentID='$TorrentID'"); diff --git a/sections/torrents/index.php b/sections/torrents/index.php index c5d59bb2..ad4bce4f 100644 --- a/sections/torrents/index.php +++ b/sections/torrents/index.php @@ -153,44 +153,19 @@ function js_pages($Action, $TorrentID, $NumResults, $CurrentPage) { enforce_login(); require(SERVER_ROOT.'/sections/torrents/manage_artists.php'); break; + case 'notify_clear': - enforce_login(); + case 'notify_clear_item': + case 'notify_clearitem': + case 'notify_clear_filter': + case 'notify_cleargroup': + case 'notify_catchup': + case 'notify_catchup_filter': authorize(); - if(!check_perms('site_torrents_notify')) { - $DB->query("DELETE FROM users_notify_filters WHERE UserID='$LoggedUser[ID]'"); - } - $DB->query("DELETE FROM users_notify_torrents WHERE UserID='$LoggedUser[ID]' AND UnRead='0'"); - $Cache->delete_value('notifications_new_'.$LoggedUser['ID']); - header('Location: torrents.php?action=notify'); + enforce_login(); + require(SERVER_ROOT.'/sections/torrents/notify_actions.php'); break; - case 'notify_cleargroup': - enforce_login(); - authorize(); - if(!isset($_GET['filterid']) || !is_number($_GET['filterid'])) { - error(0); - } - if(!check_perms('site_torrents_notify')) { - $DB->query("DELETE FROM users_notify_filters WHERE UserID='$LoggedUser[ID]'"); - } - $DB->query("DELETE FROM users_notify_torrents WHERE UserID='$LoggedUser[ID]' AND FilterID='$_GET[filterid]' AND UnRead='0'"); - $Cache->delete_value('notifications_new_'.$LoggedUser['ID']); - header('Location: torrents.php?action=notify'); - break; - - case 'notify_clearitem': - enforce_login(); - authorize(); - if(!isset($_GET['torrentid']) || !is_number($_GET['torrentid'])) { - error(0); - } - if(!check_perms('site_torrents_notify')) { - $DB->query("DELETE FROM users_notify_filters WHERE UserID='$LoggedUser[ID]'"); - } - $DB->query("DELETE FROM users_notify_torrents WHERE UserID='$LoggedUser[ID]' AND TorrentID='$_GET[torrentid]'"); - $Cache->delete_value('notifications_new_'.$LoggedUser['ID']); - break; - case 'download': require(SERVER_ROOT.'/sections/torrents/download.php'); break; @@ -199,7 +174,7 @@ function js_pages($Action, $TorrentID, $NumResults, $CurrentPage) { enforce_login(); authorize(); - if (!isset($_POST['groupid']) || !is_number($_POST['groupid']) || $_POST['body']==='' || !isset($_POST['body'])) { + if (!isset($_POST['groupid']) || !is_number($_POST['groupid']) || trim($_POST['body'])==='' || !isset($_POST['body'])) { error(0); } if($LoggedUser['DisablePosting']) { diff --git a/sections/torrents/notify.php b/sections/torrents/notify.php index 4f450d84..86530f12 100644 --- a/sections/torrents/notify.php +++ b/sections/torrents/notify.php @@ -1,29 +1,110 @@ array('unt' => 'unt.TorrentID'), + 'size' => array('t' => 't.Size'), + 'snatches' => array('t' => 't.Snatched'), + 'seeders' => array('t' => 't.Seeders'), + 'leechers' => array('t' => 't.Leechers'), + 'year' => array('tg' => 'tnt.Year')); + +if (empty($_GET['order_by']) || !isset($OrderBys[$_GET['order_by']])) { + $_GET['order_by'] = 'time'; +} +list($OrderTbl, $OrderCol) = each($OrderBys[$_GET['order_by']]); + +if (!empty($_GET['order_way']) && $_GET['order_way'] == 'asc') { + $OrderWay = 'ASC'; +} else { + $OrderWay = 'DESC'; +} + +if (!empty($_GET['filterid']) && is_number($_GET['filterid'])) { + $FilterID = $_GET['filterid']; +} else { + $FilterID = false; +} + list($Page,$Limit) = Format::page_limit(NOTIFICATIONS_PER_PAGE); - +// The "order by x" links on columns headers +function header_link($SortKey, $DefaultWay = "desc") { + global $OrderWay; + if ($SortKey == $_GET['order_by']) { + if ($OrderWay == "DESC") { + $NewWay = "asc"; + } else { + $NewWay = "desc"; + } + } else { + $NewWay = $DefaultWay; + } + return "?action=notify&order_way=".$NewWay."&order_by=".$SortKey."&".Format::get_url(array('page','order_way','order_by')); +} $UserID = $LoggedUser['ID']; -$Results = $DB->query("SELECT SQL_CALC_FOUND_ROWS unt.TorrentID, unt.UnRead, unt.FilterID, unf.Label, t.GroupID +// Sorting by release year requires joining torrents_group, which is slow. Using a temporary table +// makes it speedy enough as long as there aren't too many records to create +if ($OrderTbl == 'tg') { + $DB->query("SELECT COUNT(*) FROM users_notify_torrents AS unt + JOIN torrents AS t ON t.ID=unt.TorrentID + WHERE unt.UserID=$UserID". + ($FilterID + ? " AND FilterID=$FilterID" + : "")); + list($TorrentCount) = $DB->next_record(); + if ($TorrentCount > NOTIFICATIONS_MAX_SLOWSORT) { + error("Due to performance issues, torrent lists with more than ".number_format(NOTIFICATIONS_MAX_SLOWSORT)." items cannot be ordered by release year."); + } + + $DB->query("CREATE TEMPORARY TABLE temp_notify_torrents + (TorrentID int, GroupID int, UnRead tinyint, FilterID int, Year smallint, PRIMARY KEY(GroupID, TorrentID), KEY(Year)) ENGINE=MyISAM"); + $DB->query("INSERT INTO temp_notify_torrents (TorrentID, GroupID, UnRead, FilterID) + SELECT t.ID, t.GroupID, unt.UnRead, unt.FilterID + FROM users_notify_torrents AS unt JOIN torrents AS t ON t.ID=unt.TorrentID + WHERE unt.UserID=$UserID". + ($FilterID + ? " AND unt.FilterID=$FilterID" + : "")); + $DB->query("UPDATE temp_notify_torrents AS tnt JOIN torrents_group AS tg ON tnt.GroupID=tg.ID SET tnt.Year=tg.Year"); + + $DB->query("SELECT TorrentID, GroupID, UnRead, FilterID + FROM temp_notify_torrents AS tnt + ORDER BY $OrderCol $OrderWay, GroupID $OrderWay LIMIT $Limit"); + $Results = $DB->to_array(false, MYSQLI_ASSOC, false); +} else { + $DB->query("SELECT SQL_CALC_FOUND_ROWS unt.TorrentID, unt.UnRead, unt.FilterID, t.GroupID FROM users_notify_torrents AS unt JOIN torrents AS t ON t.ID = unt.TorrentID - LEFT JOIN users_notify_filters AS unf ON unf.ID = unt.FilterID WHERE unt.UserID=$UserID". - ((!empty($_GET['filterid']) && is_number($_GET['filterid'])) - ? " AND unf.ID='$_GET[filterid]'" + ($FilterID + ? " AND unt.FilterID=$FilterID" : "")." - ORDER BY TorrentID DESC LIMIT $Limit"); -$GroupIDs = array_unique($DB->collect('GroupID')); + ORDER BY $OrderCol $OrderWay LIMIT $Limit"); + $Results = $DB->to_array(false, MYSQLI_ASSOC, false); + $DB->query("SELECT FOUND_ROWS()"); + list($TorrentCount) = $DB->next_record(); +} -$DB->query('SELECT FOUND_ROWS()'); -list($TorrentCount) = $DB->next_record(); -$Debug->log_var($TorrentCount, 'Torrent count'); +$GroupIDs = $FilterIDs = $UnReadIDs = array(); +foreach ($Results as $Torrent) { + $GroupIDs[$Torrent['GroupID']] = 1; + $FilterIDs[$Torrent['FilterID']] = 1; + if ($Torrent['UnRead']) { + $UnReadIDs[] = $Torrent['TorrentID']; + } +} $Pages = Format::get_pages($Page, $TorrentCount, NOTIFICATIONS_PER_PAGE, 9); -if(count($GroupIDs)) { +if (!empty($GroupIDs)) { + $GroupIDs = array_keys($GroupIDs); + $FilterIDs = array_keys($FilterIDs); $TorrentGroups = Torrents::get_groups($GroupIDs); $TorrentGroups = $TorrentGroups['matches']; @@ -31,21 +112,45 @@ $DB->query("SELECT ID, CategoryID FROM torrents_group WHERE ID IN (".implode(',', $GroupIDs).")"); $GroupCategoryIDs = $DB->to_array('ID', MYSQLI_ASSOC, false); - //Clear before header but after query so as to not have the alert bar on this page load - $DB->query("UPDATE users_notify_torrents SET UnRead='0' WHERE UserID=".$LoggedUser['ID']); - $Cache->delete_value('notifications_new_'.$LoggedUser['ID']); + // Get the relevant filter labels + $DB->query("SELECT ID, Label, Artists FROM users_notify_filters WHERE ID IN (".implode(',', $FilterIDs).")"); + $Filters = $DB->to_array('ID', MYSQLI_ASSOC, array(2)); + foreach ($Filters as &$Filter) { + $Filter['Artists'] = explode('|', trim($Filter['Artists'], '|')); + } + unset($Filter); + + if (!empty($UnReadIDs)) { + //Clear before header but after query so as to not have the alert bar on this page load + $DB->query("UPDATE users_notify_torrents SET UnRead='0' WHERE UserID=".$LoggedUser['ID']." AND TorrentID IN (".implode(',', $UnReadIDs).")"); + $Cache->delete_value('notifications_new_'.$LoggedUser['ID']); + } } View::show_header('My notifications', 'notifications'); -$DB->set_query_id($Results); + ?>
        -

        Latest notifications (clear all) (clear selected) (edit filters)

        +

        Latest notifications

        + + NOTIFICATIONS_PER_PAGE) { ?> -record_count()) { ?> +
        @@ -53,75 +158,92 @@
        -next_record(MYSQLI_ASSOC)) { - if(!$Result['FilterID']) { - $Result['FilterID'] = 0; - } - if(!isset($FilterGroups[$Result['FilterID']])) { + foreach ($Results as $Result) { + if (!isset($FilterGroups[$Result['FilterID']])) { $FilterGroups[$Result['FilterID']] = array(); - $FilterGroups[$Result['FilterID']]['FilterLabel'] = $Result['Label'] ? $Result['Label'] : false; + $FilterGroups[$Result['FilterID']]['FilterLabel'] = isset($Filters[$Result['FilterID']]) + ? $Filters[$Result['FilterID']]['Label'] + : false; } - array_push($FilterGroups[$Result['FilterID']], $Result); + $FilterGroups[$Result['FilterID']][] = $Result; } - unset($Result); - $Debug->log_var($FilterGroups, 'Filter groups'); - foreach($FilterGroups as $FilterID => $FilterResults) { + + foreach ($FilterGroups as $FilterID => $FilterResults) { ?> -

        - Matches for '.$FilterResults['FilterLabel'].'' - : 'unknown filter['.$FilterID.']'?> - (clear) - (clear selected) -

        +
        +

        + Matches for '.$FilterResults['FilterLabel'].'' + : 'unknown filter['.$FilterID.']'?> +

        +
        +
        - - - - - - - + + + + + + + ".$GroupInfo['Name'].""; $GroupCategoryID = $GroupCategoryIDs[$GroupID]['CategoryID']; - if($GroupCategoryID == 1) { - if($GroupInfo['Year'] > 0) { + if ($GroupCategoryID == 1) { + if ($GroupInfo['Year'] > 0) { $DisplayName .= " [$GroupInfo[Year]]"; } - if($GroupInfo['ReleaseType'] > 0) { + if ($GroupInfo['ReleaseType'] > 0) { $DisplayName.= " [".$ReleaseTypes[$GroupInfo['ReleaseType']]."]"; } } // append extra info to torrent title $ExtraInfo = Torrents::torrent_info($TorrentInfo, true, true); - $Debug->log_var($ExtraInfo, "Extra torrent info ($TorrentID)"); $TagLinks = array(); - if($GroupInfo['TagList'] != '') { + if ($GroupInfo['TagList'] != '') { $TorrentTags = explode(' ', $GroupInfo['TagList']); $MainTag = $TorrentTags[0]; foreach ($TorrentTags as $TagKey => $TagName) { @@ -137,20 +259,21 @@ // print row ?> - + > diff --git a/sections/torrents/notify_actions.php b/sections/torrents/notify_actions.php new file mode 100644 index 00000000..eec089af --- /dev/null +++ b/sections/torrents/notify_actions.php @@ -0,0 +1,48 @@ +query("DELETE FROM users_notify_torrents WHERE UserID = '$LoggedUser[ID]' AND UnRead = '0'"); + $Cache->delete_value('notifications_new_'.$LoggedUser['ID']); + header('Location: torrents.php?action=notify'); + break; + + case 'notify_clear_item': + case 'notify_clearitem': + if(!isset($_GET['torrentid']) || !is_number($_GET['torrentid'])) { + error(0); + } + $DB->query("DELETE FROM users_notify_torrents WHERE UserID = '$LoggedUser[ID]' AND TorrentID = '$_GET[torrentid]'"); + $Cache->delete_value('notifications_new_'.$LoggedUser['ID']); + break; + + case 'notify_clear_filter': + case 'notify_cleargroup': + if(!isset($_GET['filterid']) || !is_number($_GET['filterid'])) { + error(0); + } + $DB->query("DELETE FROM users_notify_torrents WHERE UserID = '$LoggedUser[ID]' AND FilterID = '$_GET[filterid]' AND UnRead = '0'"); + $Cache->delete_value('notifications_new_'.$LoggedUser['ID']); + header('Location: torrents.php?action=notify'); + break; + + case 'notify_catchup': + $DB->query("UPDATE users_notify_torrents SET UnRead = '0' WHERE UserID=$LoggedUser[ID]"); + if($DB->affected_rows()) { + $Cache->delete_value('notifications_new_'.$LoggedUser['ID']); + } + header('Location: torrents.php?action=notify'); + break; + + case 'notify_catchup_filter': + if(!isset($_GET['filterid']) || !is_number($_GET['filterid'])) { + error(0); + } + $DB->query("UPDATE users_notify_torrents SET UnRead='0' WHERE UserID = $LoggedUser[ID] AND FilterID = $_GET[filterid]"); + if($DB->affected_rows()) { + $Cache->delete_value('notifications_new_'.$LoggedUser['ID']); + } + header('Location: torrents.php?action=notify'); + break; + default: + error(0); +} \ No newline at end of file diff --git a/sections/torrents/ranking_funcs.php b/sections/torrents/ranking_funcs.php new file mode 100644 index 00000000..8f1e2ee3 --- /dev/null +++ b/sections/torrents/ranking_funcs.php @@ -0,0 +1,93 @@ + -3.969683028665376e+01, 2 => 2.209460984245205e+02, + 3 => -2.759285104469687e+02, 4 => 1.383577518672690e+02, + 5 => -3.066479806614716e+01, 6 => 2.506628277459239e+00); + + $b = array(1 => -5.447609879822406e+01, 2 => 1.615858368580409e+02, + 3 => -1.556989798598866e+02, 4 => 6.680131188771972e+01, + 5 => -1.328068155288572e+01); + + $c = array(1 => -7.784894002430293e-03, 2 => -3.223964580411365e-01, + 3 => -2.400758277161838e+00, 4 => -2.549732539343734e+00, + 5 => 4.374664141464968e+00, 6 => 2.938163982698783e+00); + + $d = array(1 => 7.784695709041462e-03, 2 => 3.224671290700398e-01, + 3 => 2.445134137142996e+00, 4 => 3.754408661907416e+00); + + //Define break-points. + $p_low = 0.02425; //Use lower region approx. below this + $p_high = 1 - $p_low; //Use upper region approx. above this + + //Define/list variables (doesn't really need a definition) + //$p (probability), $sigma (std. deviation), and $mu (mean) are user inputs + $q = NULL; $x = NULL; $y = NULL; $r = NULL; + + //Rational approximation for lower region. + if (0 < $p && $p < $p_low) { + $q = sqrt(-2 * log($p)); + $x = ((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * + $q + $c[6]) / (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * + $q + 1); + } + + //Rational approximation for central region. + elseif ($p_low <= $p && $p <= $p_high) { + $q = $p - 0.5; + $r = $q * $q; + $x = ((((($a[1] * $r + $a[2]) * $r + $a[3]) * $r + $a[4]) * $r + $a[5]) * + $r + $a[6]) * $q / ((((($b[1] * $r + $b[2]) * $r + $b[3]) * $r + + $b[4]) * $r + $b[5]) * $r + 1); + } + + //Rational approximation for upper region. + elseif ($p_high < $p && $p < 1) { + $q = sqrt(-2 * log(1 - $p)); + $x = -((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + + $c[5]) * $q + $c[6]) / (((($d[1] * $q + $d[2]) * $q + $d[3]) * + $q + $d[4]) * $q + 1); + } + + //If 0 < p < 1, return a null value + else { + $x = NULL; + } + + return $x; + //END inverse ncdf implementation. +} + +// Confidence level for binomial scoring. Just compute this once. +define(Z_VAL, inverse_ncdf(1-(1-.95)/2)); + +// Implementation of the algorithm described at http://www.evanmiller.org/how-not-to-sort-by-average-rating.html +function binomial_score($Ups, $Total) { + if (($Total <= 0) || ($Ups < 0)) { + return 0; + } + $phat = $Ups/$Total; + return ($phat + Z_VAL*Z_VAL/(2*$Total) - Z_VAL*sqrt(($phat*(1-$phat)+Z_VAL*Z_VAL/(4*$Total))/$Total))/(1+Z_VAL*Z_VAL/$Total); +} +?> \ No newline at end of file diff --git a/sections/torrents/vote.php b/sections/torrents/vote.php new file mode 100644 index 00000000..c7947ad9 --- /dev/null +++ b/sections/torrents/vote.php @@ -0,0 +1,34 @@ +get_value('voted_albums_'.$LoggedUser['ID']); +if ($UserVotes === FALSE) { + $DB->query('SELECT GroupID, Type FROM users_votes WHERE UserID='.$LoggedUser['ID']); + $UserVotes = $DB->to_array('GroupID', MYSQL_ASSOC, false); + $Cache->cache_value('voted_albums_'.$LoggedUser['ID'], $UserVotes); +} + +$GroupVotes = $Cache->get_value('votes_'.$GroupID); +if ($GroupVotes === FALSE) { + $DB->query("SELECT Ups AS Ups, Total AS Total FROM torrents_votes WHERE GroupID=$GroupID"); + if ($DB->record_count() == 0) { + $GroupVotes = array('Ups'=>0, 'Total'=>0); + } else { + $GroupVotes = $DB->next_record(MYSQLI_ASSOC, false); + } + $Cache->cache_value('votes_'.$GroupID, $GroupVotes); +} +$TotalVotes = $GroupVotes['Total']; +$UpVotes = $GroupVotes['Ups']; + +$Voted = isset($UserVotes[$GroupID])?$UserVotes[$GroupID]['Type']:false; +?> +
        +
        Favorite Album Votes
        +
        + This has out of total>, including your upvote>, including your downvote. +

        + + id="vote_message">Upvote - Downvote + + id="unvote_message">Changed your mind?
        Clear your vote
        +
        +
        diff --git a/sections/torrents/voter_picks.php b/sections/torrents/voter_picks.php new file mode 100644 index 00000000..3fe4c572 --- /dev/null +++ b/sections/torrents/voter_picks.php @@ -0,0 +1,55 @@ +get_value('similar_albums_'.$GroupID); +if ($Top10 === False) { + + $VotePairs = $Cache->get_value('vote_pairs_'.$GroupID); + if ($VotePairs === False) { + $DB->query("SELECT v.GroupID, SUM(IF(v.Type='Up',1,0)) AS Ups, COUNT(1) AS Total + FROM (SELECT UserID FROM users_votes WHERE GroupID = $GroupID AND Type='Up') AS a + JOIN users_votes AS v USING (UserID) + WHERE v.GroupID <> $GroupID + GROUP BY v.GroupID + HAVING Ups > 0"); + $VotePairs = $DB->to_array('GroupID', MYSQL_ASSOC, false); + $Cache->cache_value('vote_pairs_'.$GroupID, $VotePairs); + } + + $GroupScores = array(); + foreach ($VotePairs as $RatingGroup) { + // Cutting out the junk should speed the sort significantly + $Score = binomial_score($RatingGroup['Ups'], $RatingGroup['Total']); + if ($Score > 0.3) { + $GroupScores[$RatingGroup['GroupID']] = binomial_score($RatingGroup['Ups'], $RatingGroup['Total']); + } + } + + arsort($GroupScores); + $Top10 = array_slice($GroupScores, 0, 10, true); + $Cache->cache_value('similar_albums_'.$GroupID, $Top10, 12*3600); +} +if (count($Top10) > 0) { +?> +
        NameFilesTimeSizeSnatchesSeedersLeechersNameYear' : ''?>FilesTimeSizeSnatchesSeedersLeechers
        [ DL - 0) && ($TorrentInfo['Size'] < 1073741824) - && !$TorrentInfo['PersonalFL'] && empty($TorrentInfo['FreeTorrent']) && ($LoggedUser['CanLeech'] == '1')) { ?> + | FL | CL ] - New!'; } ?> + New!'; + } ?>
        + + + + $MatchGroup) { + $i++; + $Str = Artists::display_artists($MatchGroup['ExtendedArtists']).''.$MatchGroup['Name'].''; +?> + + + + +
        People who like this album also liked... (Show)
        + \ No newline at end of file diff --git a/sections/user/community_stats.php b/sections/user/community_stats.php index 2eea5cc0..ff724a59 100644 --- a/sections/user/community_stats.php +++ b/sections/user/community_stats.php @@ -25,7 +25,7 @@
        Show Snatched Torrents + checked="checked" /> + +
        Posts per page (Forum) @@ -136,7 +155,7 @@ function checked($Checked) {
        Hide release typesSort/Hide release types + + Expand + + + + - + "> @@ -216,6 +282,13 @@ function checked($Checked) { + + + + + + + + + */ ?> + + + + + + + + - + diff --git a/sections/user/index.php b/sections/user/index.php index 2076a560..7e711b60 100644 --- a/sections/user/index.php +++ b/sections/user/index.php @@ -91,6 +91,7 @@ $Cache->delete_value('collage_subs_user_new_'.$UserID); include(SERVER_ROOT.'/sections/user/user.php'); break; + default: if (isset($_REQUEST['id'])) { include(SERVER_ROOT.'/sections/user/user.php'); diff --git a/sections/user/takeedit.php b/sections/user/takeedit.php index db29e22f..c1eb30d0 100644 --- a/sections/user/takeedit.php +++ b/sections/user/takeedit.php @@ -192,19 +192,25 @@ $Options['DisableSmileys'] = (!empty($_POST['disablesmileys']) ? 1 : 0); $Options['DisableAvatars'] = (!empty($_POST['disableavatars']) ? 1 : 0); $Options['DisablePMAvatars'] = (!empty($_POST['disablepmavatars']) ? 1 : 0); +$Options['NotifyOnQuote'] = (!empty($_POST['notifyquotes']) ? 1 : 0); +$Options['ShowSnatched'] = (!empty($_POST['showsnatched']) ? 1 : 0); + if(isset($LoggedUser['DisableFreeTorrentTop10'])) { $Options['DisableFreeTorrentTop10'] = $LoggedUser['DisableFreeTorrentTop10']; } -if(!empty($_POST['hidetypes'])) { - foreach($_POST['hidetypes'] as $Type) { - $Options['HideTypes'][] = (int) $Type; +if(!empty($_POST['sorthide'])) { + $JSON = json_decode($_POST['sorthide']); + foreach($JSON as $J) { + $E = explode("_", $J); + $Options['SortHide'][$E[0]] = $E[1]; } } else { - $Options['HideTypes'] = array(); + $Options['SortHide'] = array(); } + if (check_perms('site_advanced_search')) { $Options['SearchType'] = $_POST['searchtype']; } else { @@ -219,6 +225,32 @@ $DownloadAlt = (isset($_POST['downloadalt']))? 1:0; $UnseededAlerts = (isset($_POST['unseededalerts']))? 1:0; +if(isset($_POST['pushnotifications'])) { + if($_POST['pushnotifications'] == 1) { + $Options['PushService'] = "nma"; + $Options['PushKey'] = $_POST['pushkey']; + } +} +else { + $Options['PushService'] = "0"; +} + +if(is_numeric($_POST['pushservice'])) { + $CanInsert = true; + if($_POST['pushservice'] == 0) { + $DB->query("SELECT PushService FROM users_push_notifications WHERE UserID = '$LoggedUser[ID]'"); + if($DB->record_count() == 0) { + $CanInsert = false; + } + } + if($CanInsert) { + $PushService = db_string($_POST['pushservice']); + $PushOptions = array("PushKey" => trim($_POST['pushkey']), "PushUsername" => trim($_POST['pushusername']), "PushFilters" => array_flip($_POST['pushfilters'])); + $PushOptions = db_string(serialize($PushOptions)); + $DB->query("INSERT INTO users_push_notifications (UserID, PushService, PushOptions) VALUES ('$LoggedUser[ID]', '$PushService', '$PushOptions') + ON DUPLICATE KEY UPDATE PushService = '$PushService', PushOptions = '$PushOptions'"); + } +} // Information on how the user likes to download torrents is stored in cache if($DownloadAlt != $LoggedUser['DownloadAlt']) { $Cache->delete_value('user_'.$LoggedUser['torrent_pass']); @@ -248,6 +280,7 @@ i.StyleURL='".db_string($_POST['styleurl'])."', i.Avatar='".db_string($_POST['avatar'])."', i.SiteOptions='".db_string(serialize($Options))."', + i.NotifyOnQuote = '".db_string($Options['NotifyOnQuote'])."', i.Info='".db_string($_POST['info'])."', i.DownloadAlt='$DownloadAlt', i.UnseededAlerts='$UnseededAlerts', diff --git a/sections/user/user.php b/sections/user/user.php index 5121291f..6fc262ec 100644 --- a/sections/user/user.php +++ b/sections/user/user.php @@ -159,7 +159,16 @@ function check_paranoia_here($Setting) { diff --git a/sections/userhistory/index.php b/sections/userhistory/index.php index 0eb7cd6e..4d772cae 100644 --- a/sections/userhistory/index.php +++ b/sections/userhistory/index.php @@ -57,14 +57,17 @@ break; case 'subscribed_collages': require('subscribed_collages.php'); - break; - case 'catchup_collages': - require('catchup_collages.php'); - break; - - case 'token_history': - require('token_history.php'); - break; + break; + case 'catchup_collages': + require('catchup_collages.php'); + break; + + case 'token_history': + require('token_history.php'); + break; + case 'quote_notifications': + require('quote_notifications.php'); + break; default: //You trying to mess with me query string? To the home page with you! header('Location: index.php'); diff --git a/sections/userhistory/quote_notifications.php b/sections/userhistory/quote_notifications.php new file mode 100644 index 00000000..c241e9b4 --- /dev/null +++ b/sections/userhistory/quote_notifications.php @@ -0,0 +1,96 @@ +query($sql); +$Results = $DB->to_array(false, MYSQLI_ASSOC, false); +$DB->query("SELECT FOUND_ROWS()"); +list($NumResults) = $DB->next_record(); + +?> + +
        +
        +

        + Quote notifications + +

        + +
        + +
        No new quotes.
        + +
        + +
        - - + +
        Quote Notifications + checked="checked" /> + +
        Smileys @@ -230,6 +303,56 @@ function checked($Checked) {
        Push Notifications + + +
        Rippy! + +
        Auto-save Text + checked="checked" /> + +
        Download torrents as text files @@ -264,7 +387,7 @@ function checked($Checked) {
        Info
        IRCKey
        + + + +
        + > + > Quoted by + + +
        + + + diff --git a/sections/userhistory/subscriptions.php b/sections/userhistory/subscriptions.php index c00f285e..ce58abf3 100644 --- a/sections/userhistory/subscriptions.php +++ b/sections/userhistory/subscriptions.php @@ -118,6 +118,7 @@ ?> Catch up    Go to post history    + Quote Notifications    $LoggedUser['EffectiveClass']){ error('You must be a higher user class to view this wiki article'); } +$TextBody = $Text->full_format($Body, false); +$TOC = $Text->parse_toc(0); + View::show_header($Title,'wiki,bbcode'); ?>
        @@ -51,18 +54,16 @@
        diff --git a/static/functions/class_ajax.js b/static/functions/class_ajax.js index d9d55a33..2e823187 100644 --- a/static/functions/class_ajax.js +++ b/static/functions/class_ajax.js @@ -116,13 +116,26 @@ var ajax = { }; //Bookmarks function Bookmark(type, id, newName) { - var lnk = $('#bookmarklink_' + type + '_' + id).raw(); - var oldName = lnk.innerHTML; - ajax.get("bookmarks.php?action=add&type=" + type + "&auth=" + authkey + "&id=" + id, function() { - lnk.onclick = function() { Unbookmark(type, id, oldName); return false; }; - lnk.innerHTML = newName; - lnk.title = 'Remove bookmark'; - }); + if (window.location.pathname.indexOf('top10.php') != -1) { + var oldName = $('.bookmarklink_' + type + '_' + id).raw().innerHTML; + ajax.get("bookmarks.php?action=add&type=" + type + "&auth=" + authkey + "&id=" + id, function() { + var bookmarklinks = $('.bookmarklink_' + type + '_' + id).objects; + for (var i = 0; i < bookmarklinks.length; i++) { + $(bookmarklinks[i].parentNode.parentNode.parentNode).add_class('bookmarked'); + bookmarklinks[i].onclick = function() { Unbookmark(type, id, oldName); return false; }; + bookmarklinks[i].innerHTML = newName; + bookmarklinks[i].title = 'Remove bookmark'; + } + }); + } else { + var lnk = $('#bookmarklink_' + type + '_' + id).raw(); + var oldName = lnk.innerHTML; + ajax.get("bookmarks.php?action=add&type=" + type + "&auth=" + authkey + "&id=" + id, function() { + lnk.onclick = function() { Unbookmark(type, id, oldName); return false; }; + lnk.innerHTML = newName; + lnk.title = 'Remove bookmark'; + }); + } } function Unbookmark(type, id, newName) { @@ -132,6 +145,17 @@ function Unbookmark(type, id, newName) { $('.groupid_' + id).remove(); $('.bookmark_' + id).remove(); }); + } else if (window.location.pathname.indexOf('top10.php') != -1) { + var oldName = $('.bookmarklink_' + type + '_' + id).raw().innerHTML; + ajax.get("bookmarks.php?action=remove&type=" + type + "&auth=" + authkey + "&id=" + id, function() { + var bookmarklinks = $('.bookmarklink_' + type + '_' + id).objects; + for (var i = 0; i < bookmarklinks.length; i++) { + $(bookmarklinks[i].parentNode.parentNode.parentNode).remove_class('bookmarked'); + bookmarklinks[i].onclick = function() { Bookmark(type, id, oldName); return false; }; + bookmarklinks[i].innerHTML = newName; + bookmarklinks[i].title = 'Add bookmark'; + } + }); } else { var lnk = $('#bookmarklink_' + type + '_' + id).raw(); var oldName = lnk.innerHTML; diff --git a/static/functions/class_textareapreview.js b/static/functions/class_textareapreview.js new file mode 100644 index 00000000..ac7764da --- /dev/null +++ b/static/functions/class_textareapreview.js @@ -0,0 +1,79 @@ +var TextareaPreview; +jQuery(document).ready(function ($) { + TextareaPreview = function (id, textarea_id) { + if (typeof(id) === 'number') { + var textarea = document.getElementById(textarea_id || 'quickpost_'+id); + if (textarea) { + this.id = id; + this.init(textarea); + } + } + }; + + TextareaPreview.factory = function (arrays) { + var i = 0, j = arrays.length, t; + for (i; i < j; i++) { + t = arrays[i]; + t = new TextareaPreview(t[0], t[1]); + } + } + + TextareaPreview.prototype = { + constructor: TextareaPreview, + last : false, + init : function (textarea) { + var toggle = $.proxy(this.toggle, this); + this.elements(textarea); + + this.buttons.edit.on('click.preview', toggle); + this.el.preview + .on('dblclick.preview', toggle) + .addClass('text_preview') + .attr('title', 'Double click to edit.'); + + this.buttons.preview + .on('click.preview', $.proxy(this.get, this)) + .toggleClass('hidden'); + }, + elements : function (textarea) { + this.el = { + textarea : $(textarea), + wrap : $('#textarea_wrap_'+this.id), + preview : $('#preview_'+this.id), + pwrap : $('#preview_wrap_'+this.id) + }; + this.buttons = { + edit : $('.button_edit_'+this.id), + preview : $('.button_preview_'+this.id) + }; + }, + toggle : function () { + this.el.wrap.toggleClass('hidden'); + this.el.pwrap.toggleClass('hidden'); + this.buttons.edit.toggleClass('hidden'); + this.buttons.preview.toggleClass('hidden'); + }, + get : function () { + if(this.el.textarea.val().length > 0) { + this.toggle(); + if (this.last !== this.el.textarea.val()) { + this.el.preview.text('Loading . . .'); + this.last = this.el.textarea.val(); + this.post(); + } + } + }, + post : function () { + $.post('ajax.php?action=preview', + { body : this.el.textarea.val() }, + $.proxy(this.html, this), + 'html' + ).fail(function (jqXHR, textStatus) { + alert('Request failed: ' + textStatus); + }); + }, + html : function (data) { + this.el.preview.html(data); + } + }; +}); \ No newline at end of file diff --git a/static/functions/comments.js b/static/functions/comments.js index bd9708a1..c4183d52 100644 --- a/static/functions/comments.js +++ b/static/functions/comments.js @@ -30,10 +30,11 @@ function Quote(post, user, link) { }); } - function Edit_Form(post,key) { + $('#reply_box').toggle(); postid = post; - if (location.href.match(/torrents\.php/)) { + if (location.href.match(/torrents\.php/) || + location.href.match(/artist\.php/)) { boxWidth="50"; } else { boxWidth="80"; @@ -49,6 +50,7 @@ function Edit_Form(post,key) { } function Cancel_Edit(postid) { + $('#reply_box').toggle(); $('#bar' + postid).raw().innerHTML = $('#bar' + postid).raw().oldbar; $('#content' + postid).raw().innerHTML = $('#bar' + postid).raw().cancel; } @@ -68,6 +70,7 @@ function Cancel_Preview(postid) { } function Save_Edit(postid) { + $('#reply_box').toggle(); if (location.href.match(/forums\.php/)) { ajax.post("forums.php?action=takeedit","form" + postid, function (response) { $('#bar' + postid).raw().innerHTML = ""; @@ -86,6 +89,12 @@ function Save_Edit(postid) { $('#preview' + postid).raw().innerHTML = response; $('#editbox' + postid).hide(); }); + } else if (location.href.match(/artist\.php/)) { + ajax.post("artist.php?action=takeedit_post","form" + postid, function (response) { + $('#bar' + postid).raw().innerHTML = ""; + $('#preview' + postid).raw().innerHTML = response; + $('#editbox' + postid).hide(); + }); } else { ajax.post("torrents.php?action=takeedit_post","form" + postid, function (response) { $('#bar' + postid).raw().innerHTML = ""; @@ -110,6 +119,10 @@ function Delete(post) { ajax.get("requests.php?action=delete_comment&auth=" + authkey + "&postid=" + postid, function () { $('#post' + postid).hide(); }); + } else if (location.href.match(/artist\.php/)) { + ajax.get("artist.php?action=delete_comment&auth="+authkey+ "&postid=" + postid, function (){ + $('#post' + postid).hide(); + }); } else { ajax.get("torrents.php?action=delete_post&auth=" + authkey + "&postid=" + postid, function () { $('#post' + postid).hide(); @@ -226,3 +239,59 @@ function AddPollOption(id) { item.appendChild(form); list.appendChild(item); } + +/** + * HTML5-compatible storage system + * Tries to use 'oninput' event to detect text changes and sessionStorage to save it. + * + * new StoreText('some_textarea_id', 'some_form_id') + * The form is required to remove the stored text once it is submitted. + **/ +function StoreText (field, form) { + this.field = document.getElementById(field); + this.form = document.getElementById(form); + this.key = 'auto_save_temp'; + this.load(); +} +StoreText.prototype = { + constructor : StoreText, + load : function () { + if(this.field && this.enabled()){ + this.retrieve(); + this.autosave(); + this.clearForm(); + } + }, + enabled : function () { + return window.sessionStorage && typeof window.sessionStorage === 'object'; + }, + retrieve : function () { + var r = sessionStorage.getItem(this.key); + if (r) { + this.field.value = sessionStorage.getItem(this.key); + } + }, + remove : function () { + sessionStorage.removeItem(this.key); + }, + save : function () { + sessionStorage.setItem(this.key, this.field.value); + }, + autosave : function () { + jQuery(this.field).on(this.getInputEvent(), jQuery.proxy(this.save, this)); + }, + getInputEvent : function () { + var e; + if ('oninput' in this.field) { + e = 'input'; + } else if (document.body.addEventListener) { + e = 'change keyup paste cut'; + } else { + e = 'propertychange'; + } + return e; + }, + clearForm : function () { + jQuery(this.form).submit(jQuery.proxy(this.remove, this)); + } +}; diff --git a/static/functions/notifications.js b/static/functions/notifications.js index 8a8668a1..ad5b36cb 100644 --- a/static/functions/notifications.js +++ b/static/functions/notifications.js @@ -1,5 +1,5 @@ function Clear(torrentid) { - ajax.get("?action=notify_clearitem&torrentid=" + torrentid + "&auth=" + authkey, function() { + ajax.get("?action=notify_clear_item&torrentid=" + torrentid + "&auth=" + authkey, function() { $("#torrent" + torrentid).remove(); }); } diff --git a/static/functions/push_settings.js b/static/functions/push_settings.js new file mode 100644 index 00000000..d096929b --- /dev/null +++ b/static/functions/push_settings.js @@ -0,0 +1,26 @@ +(function ($) { + $(document).ready(function() { + if($("#pushservice").val() > 0) { + $('#pushsettings').show(); + if($("#pushservice").val() == 3) { + $('#pushsettings_username').show(); + } + } + $("#pushservice").change(function() { + if($(this).val() > 0) { + $('#pushsettings').show(500); + if($(this).val() == 3) { + $('#pushsettings_username').show(); + } + else { + $('#pushsettings_username').hide(); + } + } + else { + $('#pushsettings').hide(500); + $('#pushsettings_username').hide(); + } + }); + }); + }(jQuery)); + diff --git a/static/functions/release_sort.js b/static/functions/release_sort.js new file mode 100644 index 00000000..07c81d45 --- /dev/null +++ b/static/functions/release_sort.js @@ -0,0 +1,35 @@ +//Couldn't use an associative array because javascript sorting is stupid http://dev-answers.blogspot.com/2012/03/javascript-object-keys-being-sorted-in.html + +(function($) { + $(document).ready(function() { + serialize(); + $("#sortable").sortable({ + placeholder: "ui-state-highlight", + update: function() { + serialize(); + } + }); + $("#toggle_sortable").click(function () { + $('#sortable_container').slideToggle(function() { + $("#toggle_sortable").text($(this).is(":visible") ? "Collapse" : "Expand"); + }); + }); + }); + function serialize() { + var a = new Array(); + $("#sortable").find("input").each(function (i) { + $(this).unbind("click"); + $(this).click(function() { + var c = $(this).attr("checked") == "checked" ? 1 : 0; + var old_id = $(this).attr("id"); + var new_id = old_id.slice(0, - 1) + c; + $(this).attr("id", new_id); + serialize(); + }); + a.push($(this).attr("id")); + }); + $("#sorthide").val(JSON.stringify(a)); + } +} +(jQuery)); + diff --git a/static/functions/rippy.js b/static/functions/rippy.js index cb6c90f5..956903f5 100644 --- a/static/functions/rippy.js +++ b/static/functions/rippy.js @@ -1,13 +1,14 @@ function say() { - ajax.get("ajax.php?action=rippy", function (message) { - if(message) { - $('#rippy-says').raw().innerHTML = message; - $('#bubble').raw().style.display = "block"; - } else { - $('#bubble').raw().style.display = "none"; - } - } - ); + ajax.get("ajax.php?action=rippy", function(message) { + if (message) { + $('#rippywrap').raw().style.display = "inline"; + $('#rippy-says').raw().innerHTML = message; + $('#bubble').raw().style.display = "block"; + } else { + $('#bubble').raw().style.display = "none"; + + } + }); } function rippyclick() { diff --git a/static/functions/sort.js b/static/functions/sort.js index 11e3f2f6..fe472067 100644 --- a/static/functions/sort.js +++ b/static/functions/sort.js @@ -1,82 +1,105 @@ - var sortCollageTable; - jQuery(document).ready(function ($) { - sortCollageTable = { - counter: function () { - var x = 10; - $('.sort_numbers').each(function () { - this.value = x; - x += 10; - }); - this.serializer(); - }, - color : function () { - var i = 0, css; - $('.drag').each(function () { - css = i % 2 === 0 ? ['rowa', 'rowb'] : ['rowb', 'rowa']; - $(this).removeClass(css[0]).addClass(css[1]); - i++; - }); - }, - serializer : function () { - var s = this.container.sortable('serialize'); - this.serialInput.val(s); - }, - save : function () { - this.form.submit(); - }, - widthFix : function(e, row) { - row.children('td').each(function () { - $(this).width($(this).width()); - }); - return row; - }, - init : function () { - this.container = $('#manage_collage_table'); - this.form = $('#drag_drop_collage_form'); - this.serialInput = $('#drag_drop_collage_sort_order'); - $('.drag_drop_save').toggleClass('hidden'); - - this.container.sortable({ - items: '.drag', - axis: 'y', - containment: '.thin', - forcePlaceholderSize: true, - helper: sortCollageTable.widthFix, - stop: function () { - sortCollageTable.postSort(); - } - }); +var sortableTable; +jQuery(document).ready(function ($) { + sortableTable = { + container : $('#manage_collage_table'), + form : $('#drag_drop_collage_form'), + serialInput : $('#drag_drop_collage_sort_order'), + check : $('#check_all'), + counter : function () { + var x = 10; + $('input.sort_numbers').each(function () { + this.value = x; + x += 10; + }); + this.serializer(); + }, + color : function () { + var i = 0, css; + $('tr.drag').each(function () { + css = i % 2 === 0 ? ['rowa', 'rowb'] : ['rowb', 'rowa']; + $(this).removeClass(css[0]).addClass(css[1]); + i++; + }); + }, + serializer : function () { + this.serialInput.val(this.container.sortable('serialize')); + }, + save : function () { + sortableTable.form.submit(); + }, + widthFix : function(e, row) { + row.children('td').each(function () { + $(this).width($(this).width()); + }); + return row; + }, + init : function () { + $('.drag_drop_save').removeClass('hidden'); - $('.save_sortable_collage').click(function () { - sortCollageTable.save(); - }); - - this.tableSorter(); - }, - tableSorter : function () { - this.container.tablesorter({ - cssHeader : 'headerSort', - textExtraction: sortCollageTable.extractor, - headers : { - 0: { - sorter : false - }, - 6: { - sorter : false - } - } - }); - this.container.bind('sortEnd', function () { - sortCollageTable.postSort(); - }); - }, - extractor : function (node) { - return node.textContent || node.innerText; - }, - postSort : function () { - this.color(); - this.counter(); + this.noteToggle(); + this.draggable(); + this.tableSorter(); + + if (this.check.length !== 0) { + this.checks(); + } else { + $('.save_sortable_collage').click(sortableTable.save); } - }; - sortCollageTable.init(); - }); \ No newline at end of file + }, + draggable : function () { + this.container.sortable({ + items: '.drag', + axis: 'y', + containment: '.thin', + forcePlaceholderSize: true, + helper: sortableTable.widthFix, + stop: sortableTable.postSort + }); + }, + tableSorter : function () { + this.container.tablesorter({ + cssHeader : 'headerSort', + textExtraction: sortableTable.extractor, + headers : { + 0: { + sorter : false + }, + 6: { + sorter : false + } + } + }).on('sortEnd', sortableTable.postSort); + }, + extractor : function (node) { + return node.textContent || node.innerText; + }, + postSort : function () { + sortableTable.color(); + sortableTable.counter(); + }, + noteToggle : function () { + var span = $('(Hide)').click(function (e) { + e.preventDefault(); + $('#drag_drop_textnote > :first-child').toggle(); + $this = $(this); + $this.text($this.text() === '(Hide)' ? '(Show)' : '(Hide)'); + }); + $('#sorting_head').append(' ', span); + }, + checks : function () { + this.check.on('click', 'input', function () { + var s = this.checked ? + 'td.center :checkbox:not(:checked)' : + 'td.center :checked'; + $(s).click(); + }).find('span').html(''); + + this.container.on('click', 'td > :checkbox', function() { + $(this).parents('tr').toggleClass('row_checked'); + }).on('dblclick', 'tr.drag', function () { + $(this).find(':checkbox').click(); + }); + } + }; + sortableTable.init(); +}); \ No newline at end of file diff --git a/static/functions/torrent.js b/static/functions/torrent.js index 28d06de3..3e1cbd42 100644 --- a/static/functions/torrent.js +++ b/static/functions/torrent.js @@ -251,4 +251,54 @@ function Vote(amount, requestid) { } } ); +} + +function DownVoteGroup(groupid, authkey) { + ajax.get('ajax.php?action=votefavorite&do=vote&groupid='+groupid+'&vote=down'+'&auth='+authkey, function (response) { + if (response == 'noaction') { + //No increment + } else if (response == 'success') { + $('#totalvotes').raw().innerHTML = (parseInt($('#totalvotes').raw().innerHTML)) + 1; + } + } + ); + $('#vote_message').hide(); + $('#unvote_message').show(); + $('#upvoted').hide(); + $('#downvoted').show(); +} + +function UpVoteGroup(groupid, authkey) { + ajax.get('ajax.php?action=votefavorite&do=vote&groupid='+groupid+'&vote=up'+'&auth='+authkey, function (response) { + if (response == 'noaction') { + //No increment + } else if (response == 'success') { + // Increment both the upvote count and the total votes count + $('#upvotes').raw().innerHTML = (parseInt($('#upvotes').raw().innerHTML)) + 1; + $('#totalvotes').raw().innerHTML = (parseInt($('#totalvotes').raw().innerHTML)) + 1; + } + } + ); + $('#vote_message').hide(); + $('#unvote_message').show(); + $('#upvoted').show(); + $('#downvoted').hide(); +} + +function UnvoteGroup(groupid, authkey) { + ajax.get('ajax.php?action=votefavorite&do=unvote&groupid='+groupid+'&auth='+authkey, function (response) { + if (response == 'noaction') { + //No increment + } else if (response == 'success-down') { + $('#totalvotes').raw().innerHTML = (parseInt($('#totalvotes').raw().innerHTML)) - 1; + } else if (response == 'success-up') { + $('#totalvotes').raw().innerHTML = (parseInt($('#totalvotes').raw().innerHTML)) - 1; + $('#upvotes').raw().innerHTML = (parseInt($('#upvotes').raw().innerHTML)) - 1; + } + } + ); + $('#vote_message').show(); + $('#unvote_message').hide(); + $('#upvoted').hide(); + $('#downvoted').hide(); } \ No newline at end of file diff --git a/static/functions/upload.js b/static/functions/upload.js index 99e96462..587ae601 100644 --- a/static/functions/upload.js +++ b/static/functions/upload.js @@ -1,6 +1,8 @@ function Categories() { ajax.get('ajax.php?action=upload_section&categoryid=' + $('#categories').raw().value, function (response) { $('#dynamic_form').raw().innerHTML = response; + // Evaluate the code that generates previews. + eval(jQuery('#dynamic_form script.preview_code').html()); }); } diff --git a/static/styles/dark_ambient/style.css b/static/styles/dark_ambient/style.css index e3bb0582..0b1983cf 100644 --- a/static/styles/dark_ambient/style.css +++ b/static/styles/dark_ambient/style.css @@ -10,7 +10,7 @@ body { a, a:visited, a:active { color: #007dc6; - text-decoration: none; + text-decoration: none; } a:hover { @@ -77,7 +77,7 @@ a img { height: 50px; border-right: 1px solid #4f4f4f; margin: 0 0 0 20px; - padding: 0 20px 0 10px; + padding: 0 20px 0 10px; } #footer p:last-child { @@ -147,7 +147,7 @@ input[type="text"] { input, select, textarea { font-family: Arial, sans-serif; font-size: 1em; - border: 1px solid #323232; + border: 1px solid #323232; } textarea { @@ -169,7 +169,7 @@ select { padding: 0 !important; } -.main_column .pad, +.main_column .pad, .sidebar .pad { padding: 10px !important; } @@ -228,15 +228,15 @@ ul#userinfo_minor { width: 200px; } -#menu ul li, +#menu ul li, ul#userinfo_minor li { float: left; display: block; - width: 74px; + width: 74px; } ul#userinfo_minor li { - width: 95px; + width: 95px; } ul#userinfo_username, ul#userinfo_major, ul#userinfo_stats { @@ -271,7 +271,7 @@ ul#userinfo_major li a { } ul#userinfo_major li a:hover { - color: #ffffff; + color: #ffffff; } ul#userinfo_stats li { @@ -291,7 +291,7 @@ ul#userinfo_stats li a { } .blend a:hover, .alertbar a:hover { - color: #fff; + color: #fff; } ul#userinfo_stats li span.stat { @@ -323,7 +323,7 @@ ul#userinfo_minor a:hover { #top10 #nav_top10 a, #wiki #nav_wiki a { font-weight: bold; -} +} .error_message { border: 1px solid #666; @@ -396,7 +396,7 @@ ul#userinfo_stats { ul#userinfo_username { z-index: 6; - padding-left: 320px; + padding-left: 320px; } #alerts { @@ -518,7 +518,7 @@ margin-left:20px; } .label { - width: 15%; + width: 15%; border-right: 1px solid #252525; } @@ -537,14 +537,14 @@ margin-left:20px; margin: 0; } -#content table .colhead a, +#content table .colhead a, #content table .colhead_dark a { color: #989898; font-weight: bold; } -#content table .colhead a:hover, +#content table .colhead a:hover, #content table .colhead_dark a:hover { color: #007dc6; } @@ -569,7 +569,7 @@ margin-left:20px; } -#friends br, +#friends br, #footer br { display: none; } @@ -582,7 +582,7 @@ margin-left:20px; #inbox .vertical_space { width: 50%; - margin: 0 auto; + margin: 0 auto; padding: 20px; } @@ -593,7 +593,7 @@ margin-left:20px; #inbox form .box { width: 100%; - margin: 0 0 20px 0; + margin: 0 0 20px 0; padding: 0; } @@ -638,9 +638,9 @@ margin-left:20px; margin: 0; } -#forums .forum_post td.avatar, -#userhistory .forum_post td.avatar, -#collage .forum_post td.avatar, +#forums .forum_post td.avatar, +#userhistory .forum_post td.avatar, +#collage .forum_post td.avatar, #torrents .forum_post td.avatar { border: 1px solid #303030; padding: 1px; @@ -883,8 +883,8 @@ strong.quoteheader{color: #878787;} } .group_torrent td:first-child { - -} + +} .colhead td, .colhead th, .colhead_dark td { background: #212121 url('images/bar2.png') !important; @@ -936,7 +936,7 @@ strong.quoteheader{color: #878787;} color: #47a9ef; } -#torrents #content .center .box form div input[type="text"], +#torrents #content .center .box form div input[type="text"], #wiki #content .center .box form div input[type="text"], #artist #content .center .box form div input[type="text"] { width: 500px !important; @@ -952,7 +952,7 @@ strong.quoteheader{color: #878787;} height: 200px; } -#torrents #content .center .box form div, +#torrents #content .center .box form div, #wiki #content .center .box form div, #artist #content .center .box form div { text-align: left !important; @@ -995,7 +995,7 @@ strong.quoteheader{color: #878787;} padding: 10px 0; } -.sidebar .box .head, +.sidebar .box .head, .main_column .box .head { background-color: #212121; padding: 10px !important; @@ -1030,7 +1030,7 @@ strong.quoteheader{color: #878787;} padding: 0; } -#wiki .sidebar ul ul { +#wiki .sidebar ul ul, #wiki .sidebar ol ol { margin: 0 0 0 10px; } @@ -1061,7 +1061,7 @@ strong.quoteheader{color: #878787;} margin: 0 !important; } -.sidebar form br, +.sidebar form br, .sidebar .pad br { line-height: 1em; } @@ -1427,11 +1427,11 @@ h3 { width: 130px; } -#user .linkbox, -#artist .linkbox, -#collage .linkbox, +#user .linkbox, +#artist .linkbox, +#collage .linkbox, #forums .linkbox, -#bookmarks .linkbox, +#bookmarks .linkbox, #torrents .linkbox, #wiki .linkbox, #friends .linkbox { @@ -1505,7 +1505,7 @@ h3 { #bookmarks .group span a { float: right; -} +} #bookmarks .group span div a, #bookmarks .group span strong a { float: none; @@ -1996,8 +1996,11 @@ ul#userinfo_random li a:hover { text-align: center; } -.spellcheck { +.spellcheck { margin: 25px 0; font-size: 1.25em; font-weight: bold; } + +tr.torrent .bookmark > a:before { content:""; } +tr.torrent .bookmark > a:after { content:""; } diff --git a/static/styles/global.css b/static/styles/global.css index e3e935ab..dcdc0fd7 100644 --- a/static/styles/global.css +++ b/static/styles/global.css @@ -1,6 +1,19 @@ +.box h3 { + font-size: 140%; +} +.box h4 { + font-size: 130%; +} +.box h5 { + font-size: 120%; +} +.box h6 { + font-size: 110%; +} + pre br { - line-height:0px; - display:none; + line-height: 0px; + display: none; } .center { @@ -28,9 +41,9 @@ ul.collage_images li { } ul.collage_images li a { - display: block; - height: 118px; - overflow: hidden; + display: block; + height: 118px; + overflow: hidden; } ul.collage_images img { @@ -38,8 +51,7 @@ ul.collage_images img { width: 118px; } - -.selected a{ +.selected a { font-weight: bold; text-decoration: underline; } @@ -67,51 +79,51 @@ ul.collage_images img { .line_unchanged { -} +} .log1 { + +} - } - - .log2 { - color: yellow; - } - - .log3 { - color: #0E88C6; - } - - .log4 { +.log2 { + color: yellow; +} + +.log3 { + color: #0E88C6; +} + +.log4 { font-weight: bold; - } - - .log5 { +} + +.log5 { text-decoration: underline; - } - - .good { - font-weight: bold; - color: green; - } - - .bad { - font-weight: bold; - color: red; - } - - .goodish { - font-weight: bold; - color: #35BF00; - } - - .badish { - font-weight: bold; - color: #E5B244; - } - - pre { - overflow: auto; - } +} + +.good { + font-weight: bold; + color: green; +} + +.bad { + font-weight: bold; + color: red; +} + +.goodish { + font-weight: bold; + color: #35BF00; +} + +.badish { + font-weight: bold; + color: #E5B244; +} + +pre { + overflow: auto; +} .hidden { display: none; @@ -121,17 +133,21 @@ ul.collage_images img { display: none; } -form textarea, form input {max-width:100%;} +form textarea,form input { + max-width: 100%; +} a.beta { font-weight: bold; color: #ff0000; } -strong.important_text { + +strong.important_text { color: red; font-weight: bold; } -.invalid, .warning, .error, .new { + +.invalid,.warning,.error,.new { color: #ff0000; } @@ -170,47 +186,168 @@ div#AddArtists a { max-width: 100%; } -.rippywrap { z-index:25; display: block; position: fixed; background: transparent url('../rippy/rippy.png') no-repeat bottom center; color: black; text-align: center; width: 190px; height: 180px; bottom: 0px; right: 0px; } -.rippywrap div.rippy { z-index: 25; height: 111px; width: 190px; position: fixed; bottom: 0px; right: 0px; } -span.rbt { display: block; padding: 8px 0 0; background: url('../rippy/rippy_top.gif') no-repeat top; } -span.rbm { display: block; background: url('../rippy/rippy_middle.gif') repeat bottom; padding: 2px; } -span.rbb { display: block; padding: 4px 0px 18px; margin-bottom: 5px; background: url('../rippy/rippy_bottom.gif') no-repeat bottom; } +.rippywrap { + z-index: 25; + display: block; + position: fixed; + background: transparent url('../rippy/rippy_bday.png') no-repeat bottom + center; + color: black; + text-align: center; + width: 190px; + height: 180px; + bottom: 0px; + right: 0px; +} -span.secondary_class { font-size:85%; font-weight:bold; } -.breadcrumbs { font-weight: bold; text-align: right; } +.rippywrap div.rippy { + z-index: 25; + height: 111px; + width: 190px; + position: fixed; + bottom: 0px; + right: 0px; +} +span.rbt { + display: block; + padding: 8px 0 0; + background: url('../rippy/rippy_top.gif') no-repeat top; +} + +span.rbm { + display: block; + background: url('../rippy/rippy_middle.gif') repeat bottom; + padding: 2px; +} + +span.rbb { + display: block; + padding: 4px 0px 18px; + margin-bottom: 5px; + background: url('../rippy/rippy_bottom.gif') no-repeat bottom; +} + +span.secondary_class { + font-size: 85%; + font-weight: bold; +} + +.breadcrumbs { + font-weight: bold; + text-align: right; +} + +<<<<<<< +HEAD .paranoia_override { - font-style: italic; + font-style: italic; } #manage_collage_table.ui-sortable .drag { - cursor: n-resize; + cursor: n-resize; } #manage_collage_table.ui-sortable .ui-sortable-helper.drag { - cursor:grabbing; - cursor:-moz-grabbing; - cursor:-webkit-grabbing; + cursor: grabbing; + cursor: -moz-grabbing; + cursor: -webkit-grabbing; } -#manage_collage_table .ui-sortable-helper td, -#manage_collage_table .ui-sortable-placeholder { + +#manage_collage_table .ui-sortable-helper td,#manage_collage_table .ui-sortable-placeholder + { border: 0; } + .drag_drop_save { padding: 6px 0; overflow: hidden; } + .headerSort { cursor: pointer; } + .headerSort span { - background: url("../common/table-order.png") no-repeat scroll right -38px transparent; - padding: 0px 20px 0 0; -} -.headerSortDown span { - background: url("../common/table-order.png") no-repeat scroll right 4px transparent; -} -.headerSortUp span { - background: url("../common/table-order.png") no-repeat scroll right -79px transparent; + background: url("../common/table-order.png") no-repeat scroll right + -38px transparent; + padding: 0px 20px 0 0; } +.headerSortDown span { + background: url("../common/table-order.png") no-repeat scroll right 4px + transparent; +} + +.headerSortUp span { + background: url("../common/table-order.png") no-repeat scroll right + -79px transparent; +} + +.album_votes { + text-align: center +} + +.favoritecount { + font-size: 150%; + font-weight: bold; +} + +ul.votedalbums li { + list-style: none; + list-style-type: none; + margin: 0; +} + +tr.torrent .bookmark>a:before { + content: "[ "; + text-decoration: none; + font-weight: normal; +} + +tr.torrent .bookmark>a:after { + content: " ]"; + text-decoration: none; + font-weight: normal; +} + +#sortable { + list-style-type: none; + margin: 0; + padding: 0; + width: 50%; +} + +#sortable li { + padding: 0px; + font-size: 1.2em; + height: 1.5em; +} + + +.ui-state-highlight { + background: #007DC6 /*{bgColorHighlight}*/; + opacity : 0.15; + width: 50%; + +} +.navigation_list { + list-style-position: inside; + margin-top: 10px; + margin-bottom: 20px; +} +.navigation_list > li { + list-style-type: upper-roman !important; +} +.navigation_list li li { + list-style-type: upper-alpha; +} +.navigation_list li li li { + list-style-type: decimal; +} +.navigation_list li li li li { + list-style-type: lower-alpha; +} + +.text_preview { min-height: 100px } + diff --git a/static/styles/gtfo_spaceship/style.css b/static/styles/gtfo_spaceship/style.css index 659f906d..bf88687d 100644 --- a/static/styles/gtfo_spaceship/style.css +++ b/static/styles/gtfo_spaceship/style.css @@ -1409,3 +1409,7 @@ body#forums .poll li.graph { .lightbox .colhead span { font-weight: bold; } + +.navigation_list li { + margin-left: 20px; +} diff --git a/static/styles/kuro/style.css b/static/styles/kuro/style.css index 9f664c92..adc2d972 100644 --- a/static/styles/kuro/style.css +++ b/static/styles/kuro/style.css @@ -888,3 +888,6 @@ form tr { font-size: 1.25em; font-weight: bold; } + +tr.torrent .bookmark > a:before { color:#999; } +tr.torrent .bookmark > a:after { color:#999; } diff --git a/static/styles/layer_cake/style.css b/static/styles/layer_cake/style.css index f155de0d..88355a9c 100644 --- a/static/styles/layer_cake/style.css +++ b/static/styles/layer_cake/style.css @@ -781,3 +781,10 @@ ul .invitetree { font-size: 1.25em; font-weight: bold; } + +tr.torrent .bookmark > a:before { + color:black; +} +tr.torrent .bookmark > a:after { + color:black; +} diff --git a/static/styles/minimal/style.css b/static/styles/minimal/style.css index edf70ac6..41f5ed57 100644 --- a/static/styles/minimal/style.css +++ b/static/styles/minimal/style.css @@ -255,14 +255,14 @@ strong.quoteheader {color: #f1f1f1;} #forums .rowb .min_padding img, #forums .rowa .min_padding img{position:relative; top:3px} -#forums .forum_post tr, -#userhistory .forum_post tr, -#collage .forum_post tr, +#forums .forum_post tr, +#userhistory .forum_post tr, +#collage .forum_post tr, #torrents .forum_post tr{border-bottom:1px solid #757575} -#forums .forum_post, -#userhistory .forum_post, -#collage .forum_post, +#forums .forum_post, +#userhistory .forum_post, +#collage .forum_post, #torrents .forum_post{border:0; margin:0} .avatar{border:0 !important; padding:1px 1px 1px 0; background-color:#161616 !important; width:150px} @@ -271,26 +271,26 @@ strong.quoteheader {color: #f1f1f1;} #requests .forum_post .body{border:0} #requests .forum_post{margin-bottom:0} -#forums .forum_post .body, -#userhistory .forum_post .body, -#collage .forum_post .body, +#forums .forum_post .body, +#userhistory .forum_post .body, +#collage .forum_post .body, #torrents .forum_post .body{padding:0; border-left:0} -#forums .forum_post td, -#userhistory .forum_post td, -#collage .forum_post td, +#forums .forum_post td, +#userhistory .forum_post td, +#collage .forum_post td, #torrents .forum_post td{border-left:0; border-right:0} -#forums .forum_post .body div, -#collage .forum_post .body div, +#forums .forum_post .body div, +#collage .forum_post .body div, #torrents .forum_post .body div, #requests .forum_post .body div{padding:10px 15px} #userhistory .forum_post .body{padding:20px} #userhistory .forum_post tr.colhead_dark{background-image:none} -#forums .forum_post .body div div, -#collage .forum_post .body div div, +#forums .forum_post .body div div, +#collage .forum_post .body div div, #torrents .forum_post .body div div{background:none; padding:0} #forums .forum_post ul{margin:5px 0 0 0; padding:0} @@ -338,18 +338,18 @@ strong.quoteheader {color: #f1f1f1;} .torrent_table tr.group_torrent a, #torrent_table tr.group_torrent a{color:#999; font-weight:normal} .torrent_table tr.group_torrent a:hover, #torrent_table tr.group_torrent a:hover{color:#007dc6} -#torrents #content .center .box form div input[type="text"], -#wiki #content .center .box form div input[type="text"], +#torrents #content .center .box form div input[type="text"], +#wiki #content .center .box form div input[type="text"], #artist #content .center .box form div input[type="text"]{width:500px; margin-bottom:10px} -#torrents #content .center .box form div textarea, -#wiki #content .center .box form div textarea, -#upload textarea#album_desc, -#forums #content .thin .box form .box textarea, +#torrents #content .center .box form div textarea, +#wiki #content .center .box form div textarea, +#upload textarea#album_desc, +#forums #content .thin .box form .box textarea, #forums #quickpost{height:200px} -#torrents #content .center .box form div, -#wiki #content .center .box form div, +#torrents #content .center .box form div, +#wiki #content .center .box form div, #artist #content .center .box form div{text-align:left !important} /* PROFILE PAGE */ @@ -363,10 +363,10 @@ strong.quoteheader {color: #f1f1f1;} .box table{margin:0; background-color:#FFF} #discog_table, #collage_table{margin-top:1px} -.sidebar form br, +.sidebar form br, .sidebar .pad br{line-height:1em} -.main_column .body, +.main_column .body, .sidebar .box .body{/*ADD TAG ON ALBUM PAGE */ padding:10px} .sidebar .box .stats{list-style:none; margin:0; padding:10px} @@ -495,11 +495,11 @@ h3{margin:10px 0} #user #userform{padding:20px 0 0 0} -#user .linkbox, -#artist .linkbox, -#collage .linkbox, -#forums .linkbox, -#bookmarks .linkbox, +#user .linkbox, +#artist .linkbox, +#collage .linkbox, +#forums .linkbox, +#bookmarks .linkbox, #torrents .linkbox{border-bottom:0} #rules #content li{margin:0 0 5px 0} @@ -532,8 +532,17 @@ h3{margin:10px 0} text-align: center; } -.spellcheck { +.spellcheck { margin: 10px 0; font-size: 1.25em; font-weight: bold; } + + +tr.torrent .bookmark > a:before { content:""; } +tr.torrent .bookmark > a:after { content:""; } + +.sidebar .navigation_list li { + margin-left: 20px; +} + diff --git a/static/styles/mono/style.css b/static/styles/mono/style.css index d27079d5..effe0d9f 100644 --- a/static/styles/mono/style.css +++ b/static/styles/mono/style.css @@ -1185,3 +1185,6 @@ table.debug_table td.debug_query_data>div { .nobr { white-space: nowrap; } + +tr.torrent .bookmark > a:before { content:""; } +tr.torrent .bookmark > a:after { content:""; } diff --git a/static/styles/postmod/style.css b/static/styles/postmod/style.css index 5c75e7d0..93a2d718 100644 --- a/static/styles/postmod/style.css +++ b/static/styles/postmod/style.css @@ -1045,3 +1045,10 @@ select:hover, option:hover { ul, ol{ list-style-position: inside; } + +tr.torrent .bookmark > a:before { + color:#646054; +} +tr.torrent .bookmark > a:after { + color:#646054; +} diff --git a/static/styles/proton/style.css b/static/styles/proton/style.css index d4cf3544..f19c26ad 100644 --- a/static/styles/proton/style.css +++ b/static/styles/proton/style.css @@ -10,7 +10,7 @@ body { a, a:visited, a:active { color: #007dc6; - text-decoration: none; + text-decoration: none; } a:hover { @@ -60,7 +60,7 @@ a img { height: 50px; border-left: 1px solid #6f6f6f; margin: 0 20px 0 0; - padding: 0 0 0 20px; + padding: 0 0 0 20px; } #footer p:first-child { @@ -131,7 +131,7 @@ input[type="text"] { input, select, textarea { font-family: Arial, sans-serif; font-size: 1em; - border: 1px solid #9c9c9c; + border: 1px solid #9c9c9c; } textarea { @@ -153,7 +153,7 @@ select { padding: 0 !important; } -.main_column .pad, +.main_column .pad, .sidebar .pad, #blog .pad { padding: 10px !important; @@ -178,7 +178,7 @@ input:focus, textarea:focus, #searchbars input:focus { } #searchbars input:focus { - background: transparent url('images/searchbox.png') 0 -23px no-repeat; + background: transparent url('images/searchbox.png') 0 -23px no-repeat; } input[type="submit"], input[type="button"] { @@ -231,15 +231,15 @@ ul#userinfo_minor { width: 200px; } -#menu ul li, +#menu ul li, ul#userinfo_minor li { float: left; display: block; - width: 74px; + width: 74px; } ul#userinfo_minor li { - width: 95px; + width: 95px; } ul#userinfo_username, ul#userinfo_major, ul#userinfo_stats { @@ -277,7 +277,7 @@ ul#userinfo_major li a { ul#userinfo_major li a:hover { background-color: #575757; - color: #e6e6e6; + color: #e6e6e6; } ul#userinfo_stats li { @@ -313,7 +313,7 @@ ul#userinfo_stats li a { .blend a:hover { background-color: #575757; - color: #e6e6e6; + color: #e6e6e6; } ul#userinfo_stats li span.stat { @@ -345,7 +345,7 @@ ul#userinfo_minor a:hover { #top10 #nav_top10 a, #wiki #nav_wiki a { font-weight: bold; -} +} /* ARRANGING MENUS */ @@ -396,7 +396,7 @@ ul#userinfo_stats { ul#userinfo_username { z-index: 5; - padding-left: 290px; + padding-left: 290px; } #alerts { @@ -468,7 +468,7 @@ ul#userinfo_username { #content { - padding: 20px 20px 20px 20px; + padding: 20px 20px 20px 20px; margin: 38px 0 0 0; background-color: white; color: #575757; @@ -516,7 +516,7 @@ ul#userinfo_username { } .label { - width: 15%; + width: 15%; border-right: 1px solid #e6e6e6; } @@ -535,14 +535,14 @@ ul#userinfo_username { margin: 0; } -#content table .colhead a, +#content table .colhead a, #content table .colhead_dark a { color: #575757; font-weight: bold; } -#content table .colhead a:hover, +#content table .colhead a:hover, #content table .colhead_dark a:hover { color: #007dc6; } @@ -567,7 +567,7 @@ ul#userinfo_username { } -#friends br, +#friends br, #footer br { display: none; } @@ -580,7 +580,7 @@ ul#userinfo_username { #inbox .vertical_space { width: 50%; - margin: 0 auto; + margin: 0 auto; padding: 20px; background: transparent url('images/convo.png') 50% 35px no-repeat; } @@ -592,7 +592,7 @@ ul#userinfo_username { #inbox form .box { width: 100%; - margin: 0 0 20px 0; + margin: 0 0 20px 0; padding: 0; } @@ -641,9 +641,9 @@ ul#userinfo_username { margin: 0 0 10px 0; } -#forums .forum_post td.avatar, -#userhistory .forum_post td.avatar, -#collage .forum_post td.avatar, +#forums .forum_post td.avatar, +#userhistory .forum_post td.avatar, +#collage .forum_post td.avatar, #torrents .forum_post td.avatar, #comments .forum_post td.avatar, #requests .forum_post td.avatar { @@ -734,7 +734,7 @@ ul#userinfo_username { #userhistory .forum_post tr, #comments .forum_post tr, #requests .forum_post tr { - background: transparent url('images/forum_postbgspeech3.png') 149px 100% no-repeat; + background: transparent url('images/forum_postbgspeech3.png') 149px 100% no-repeat; } #userhistory .forum_post tr.colhead_dark { @@ -787,11 +787,11 @@ strong.quoteheader { #torrents .sidebar .box .stats li span.remove_artist a { color: #575757; font-family: monospace; -} +} #torrents .sidebar .box .stats li span.remove_artist a:hover { color: red; -} +} #torrents input[value="Edit torrent"] { margin: 5px 0 30px 0; @@ -1007,7 +1007,7 @@ strong.quoteheader { color: #007dc6; } -#torrents #content .center .box form div input[type="text"], +#torrents #content .center .box form div input[type="text"], #wiki #content .center .box form div input[type="text"], #artist #content .center .box form div input[type="text"] { width: 500px !important; @@ -1023,7 +1023,7 @@ strong.quoteheader { height: 200px; } -#torrents #content .center .box form div, +#torrents #content .center .box form div, #wiki #content .center .box form div, #artist #content .center .box form div { text-align: left !important; @@ -1066,7 +1066,7 @@ strong.quoteheader { padding: 10px 0; } -.sidebar .box .head, +.sidebar .box .head, .main_column .box .head, #blog .box .head { background-color: #f0f0f0; @@ -1106,7 +1106,7 @@ strong.quoteheader { padding: 0; } -#wiki .sidebar ul ul { +#wiki .sidebar ul ul, #wiki .sidebar ol ol { margin: 0 0 0 10px; } @@ -1137,7 +1137,7 @@ strong.quoteheader { margin: 0 !important; } -.sidebar form br, +.sidebar form br, .sidebar .pad br { line-height: 1em; } @@ -1336,7 +1336,7 @@ td.r00 { overflow: auto; } -.lightbox img { +.lightbox img { max-width: 100%; max-height: 100%; background-color: transparent; @@ -1502,11 +1502,11 @@ h3 { width: 130px; } -#user .linkbox, -#artist .linkbox, -#collage .linkbox, +#user .linkbox, +#artist .linkbox, +#collage .linkbox, #forums .linkbox, -#bookmarks .linkbox, +#bookmarks .linkbox, #torrents .linkbox, #wiki .linkbox, #friends .linkbox { @@ -1582,7 +1582,7 @@ h3 { #bookmarks .group span a { float: right; -} +} #bookmarks .group span div a, #bookmarks .group span strong a { float: none; @@ -1726,7 +1726,7 @@ div.invitetree ul.invitetree { text-align: center; } -.spellcheck { +.spellcheck { margin: 25px 0; font-size: 1.25em; font-weight: bold; @@ -1735,3 +1735,6 @@ div.invitetree ul.invitetree { table.noavatar, table.noavatar tr, table.noavatar td.body, table.noavatar td.body div { background-image: none !important; } + +tr.torrent .bookmark > a:before { content:""; } +tr.torrent .bookmark > a:after { content:""; } diff --git a/static/styles/white.cd/style.css b/static/styles/white.cd/style.css index 0089e565..a363ad21 100644 --- a/static/styles/white.cd/style.css +++ b/static/styles/white.cd/style.css @@ -25,3 +25,12 @@ ul.collage_images img { #drag_drop_textnote ul { padding-left: 25px; } + + +tr.torrent .bookmark > a:before { content:""; } +tr.torrent .bookmark > a:after { content:""; } + +.navigation_list li { + margin-left: 20px; +} +