diff --git a/UPDATE_SCRIPT__MOD_ARCHIVE_FOR_THREADS.php b/UPDATE_SCRIPT__MOD_ARCHIVE_FOR_THREADS.php new file mode 100644 index 00000000..9caeea3c --- /dev/null +++ b/UPDATE_SCRIPT__MOD_ARCHIVE_FOR_THREADS.php @@ -0,0 +1,79 @@ +You are about to update the database to allow MOD archive for threads.

'; + $page['body'] .= '

Click here to update database entries.

'; + break; + case 2: + $page['body'] = '

Database have been updated.

'; + + $sql_errors = ""; + $file_errors = ""; + + // Update posts_* table to archive function + // Get list of boards + $boards = listBoards(); + foreach ($boards as &$_board) { + + $query = sprintf("ALTER TABLE `archive_%s` ADD `mod_archived` INT(1) NOT NULL AFTER `featured`", $_board['uri']); + query($query) or $sql_errors .= sprintf("
  • Updated Archive DB for %s
    ", $_board['uri']) . db_error() . '
  • '; + + $_board['dir'] = sprintf($config['board_path'], $_board['uri']); + + // Create Mod Archive threads Folders + if (!file_exists($_board['dir'] . $config['dir']['mod_archive'])) + @mkdir($_board['dir'] . $config['dir']['mod_archive'], 0777) + or $file_errors .= "Couldn't create " . $_board['dir'] . $config['dir']['mod_archive'] . ". Check permissions.
    "; + if (!file_exists($_board['dir'] . $config['dir']['mod_archive'] . $config['dir']['img'])) + @mkdir($_board['dir'] . $config['dir']['mod_archive'] . $config['dir']['img'], 0777) + or $file_errors .= "Couldn't create " . $_board['dir'] . $config['dir']['feamod_archivetured'] . $config['dir']['img'] . ". Check permissions.
    "; + if (!file_exists($_board['dir'] . $config['dir']['mod_archive'] . $config['dir']['thumb'])) + @mkdir($_board['dir'] . $config['dir']['mod_archive'] . $config['dir']['thumb'], 0777) + or $file_errors .= "Couldn't create " . $_board['dir'] . $config['dir']['mod_archive'] . $config['dir']['thumb'] . ". Check permissions.
    "; + if (!file_exists($_board['dir'] . $config['dir']['mod_archive'] . $config['dir']['res'])) + @mkdir($_board['dir'] . $config['dir']['mod_archive'] . $config['dir']['res'], 0777) + or $file_errors .= "Couldn't create " . $_board['dir'] . $config['dir']['mod_archive'] . $config['dir']['res'] . ". Check permissions.
    "; + } + + if (!empty($sql_errors)) + $page['body'] .= '

    SQL errors

    SQL errors were encountered when trying to update the database.

    The errors encountered were:

    '; + if (!empty($file_errors)) + $page['body'] .= '

    File System errors

    File System errors were encountered when trying to create folders.

    The errors encountered were:

    '; + + break; +} + + +echo Element('page.html', $page); + +?> + + diff --git a/inc/archive.php b/inc/archive.php index ab66a3c1..b57e38a4 100644 --- a/inc/archive.php +++ b/inc/archive.php @@ -85,7 +85,7 @@ class Archive { } // Insert Archive Data in Database - $query = prepare(sprintf("INSERT INTO ``archive_%s`` VALUES (:thread_id, :snippet, :lifetime, :files, 0)", $board['uri'])); + $query = prepare(sprintf("INSERT INTO ``archive_%s`` VALUES (:thread_id, :snippet, :lifetime, :files, 0, 0)", $board['uri'])); $query->bindValue(':thread_id', $thread_id, PDO::PARAM_INT); $query->bindValue(':snippet', $thread_data['snippet'], PDO::PARAM_STR); $query->bindValue(':lifetime', time(), PDO::PARAM_INT); @@ -116,7 +116,7 @@ class Archive { return; // Delete all static pages and files for archived threads that has timed out - $query = prepare(sprintf("SELECT `id`, `files` FROM ``archive_%s`` WHERE `lifetime` < :lifetime AND `featured` = 0", $board['uri'])); + $query = prepare(sprintf("SELECT `id`, `files` FROM ``archive_%s`` WHERE `lifetime` < :lifetime AND `featured` = 0 AND `mod_archived` = 0", $board['uri'])); $query->bindValue(':lifetime', strtotime("-" . $config['archive']['lifetime']), PDO::PARAM_INT); $query->execute() or error(db_error($query)); while($thread = $query->fetch(PDO::FETCH_ASSOC)) { @@ -132,11 +132,11 @@ class Archive { // Delete Archive Entries if($query->rowCount() != 0) { - $query = prepare(sprintf("DELETE FROM ``archive_%s`` WHERE `lifetime` < :lifetime AND `featured` = 0", $board['uri'])) or error(db_error()); + $query = prepare(sprintf("DELETE FROM ``archive_%s`` WHERE `lifetime` < :lifetime AND `featured` = 0 AND `mod_archived` = 0", $board['uri'])) or error(db_error()); $query->bindValue(':lifetime', strtotime("-" . $config['archive']['lifetime']), PDO::PARAM_INT); $query->execute() or error(db_error($query)); - modLog(sprintf("Purged %i archived threads due to expiration date", $query->rowCount())); + modLog(sprintf("Purged %d archived threads due to expiration date", $query->rowCount())); } return $query->rowCount(); @@ -148,14 +148,17 @@ class Archive { // Feature thread and replies - static public function featureThread($thread_id) { - global $config, $board; + static public function featureThread($thread_id, $mod_archive = false) { + global $config, $board, $mod; // If featuring of threads is turned off return - if(!$config['feature']['threads']) + if(!$mod_archive && !$config['feature']['threads']) + return; + // If mod archive of threads is turned off return + if($mod_archive && !$config['mod_archive']['threads']) return; - $query = query(sprintf("SELECT `files` FROM ``archive_%s`` WHERE `id` = %d AND `featured` = 0", $board['uri'], (int)$thread_id)) or error(db_error()); + $query = query(sprintf("SELECT `files` FROM ``archive_%s`` WHERE `id` = %d AND " . ($mod_archive?"`mod_archived`":"`featured`") . " = 0", $board['uri'], (int)$thread_id)) or error(db_error()); if(!$thread = $query->fetch(PDO::FETCH_ASSOC)) error($config['error']['invalidpost']); @@ -163,20 +166,24 @@ class Archive { $thread_file_content = @file_get_contents($board['dir'] . $config['dir']['archive'] . $config['dir']['res'] . sprintf($config['file_page'], $thread_id)); // Replace links and posting mode to Archived - $thread_file_content = str_replace(sprintf('src="/' . $config['board_path'] . $config['dir']['archive'], $board['uri']), sprintf('src="/' . $config['board_path'] . $config['dir']['featured'], $board['uri']), $thread_file_content); - $thread_file_content = str_replace(sprintf('href="/' . $config['board_path'] . $config['dir']['archive'], $board['uri']), sprintf('href="/' . $config['board_path'] . $config['dir']['featured'], $board['uri']), $thread_file_content); + $thread_file_content = str_replace(sprintf('src="/' . $config['board_path'] . $config['dir']['archive'], $board['uri']), sprintf('src="/' . $config['board_path'] . ($mod_archive?$config['dir']['mod_archive']:$config['dir']['featured']), $board['uri']), $thread_file_content); + $thread_file_content = str_replace(sprintf('href="/' . $config['board_path'] . $config['dir']['archive'], $board['uri']), sprintf('href="/' . $config['board_path'] . ($mod_archive?$config['dir']['mod_archive']:$config['dir']['featured']), $board['uri']), $thread_file_content); $thread_file_content = str_replace('Archived thread', 'Featured thread', $thread_file_content); // Write altered thread HTML to archive location - @file_put_contents($board['dir'] . $config['dir']['featured'] . $config['dir']['res'] . sprintf($config['file_page'], $thread_id), $thread_file_content, LOCK_EX); + @file_put_contents($board['dir'] . ($mod_archive?$config['dir']['mod_archive']:$config['dir']['featured']) . $config['dir']['res'] . sprintf($config['file_page'], $thread_id), $thread_file_content, LOCK_EX); foreach (json_decode($thread['files']) as $f) { - @copy($board['dir'] . $config['dir']['archive'] . $config['dir']['img'] . $f->file, $board['dir'] . $config['dir']['featured'] . $config['dir']['img'] . $f->file); - @copy($board['dir'] . $config['dir']['archive'] . $config['dir']['thumb'] . $f->thumb, $board['dir'] . $config['dir']['featured'] . $config['dir']['thumb'] . $f->thumb); + @copy($board['dir'] . $config['dir']['archive'] . $config['dir']['img'] . $f->file, $board['dir'] . ($mod_archive?$config['dir']['mod_archive']:$config['dir']['featured']) . $config['dir']['img'] . $f->file); + @copy($board['dir'] . $config['dir']['archive'] . $config['dir']['thumb'] . $f->thumb, $board['dir'] . ($mod_archive?$config['dir']['mod_archive']:$config['dir']['featured']) . $config['dir']['thumb'] . $f->thumb); } // Update DB entry - query(sprintf("UPDATE ``archive_%s`` SET `featured` = 1 WHERE `id` = %d", $board['uri'], (int)$thread_id)) or error(db_error()); + query(sprintf("UPDATE ``archive_%s`` SET " . ($mod_archive?"`mod_archived`":"`featured`") . " = 1 WHERE `id` = %d", $board['uri'], (int)$thread_id)) or error(db_error()); + + // Add mod log entry + modLog(sprintf("Added thread #%d to " . ($mod_archive?"mod archive":"featured threads"), $thread_id)); + // Rebuild Featured Index self::buildFeaturedIndex(); @@ -190,8 +197,8 @@ class Archive { - static public function deleteFeatured($thread_id) { - global $config, $board; + static public function deleteFeatured($thread_id, $mod_archive = false) { + global $config, $board, $mod; $query = query(sprintf("SELECT `id`, `files`, `lifetime` FROM ``archive_%s`` WHERE `featured` = 1", $board['uri'])) or error(db_error()); if(!$thread = $query->fetch(PDO::FETCH_ASSOC)) @@ -200,19 +207,22 @@ class Archive { // Delete Files foreach (json_decode($thread['files']) as $f) { - @unlink($board['dir'] . $config['dir']['featured'] . $config['dir']['img'] . $f->file); - @unlink($board['dir'] . $config['dir']['featured'] . $config['dir']['img'] . $f->thumb); + @unlink($board['dir'] . ($mod_archive?$config['dir']['mod_archive']:$config['dir']['featured']) . $config['dir']['img'] . $f->file); + @unlink($board['dir'] . ($mod_archive?$config['dir']['mod_archive']:$config['dir']['featured']) . $config['dir']['img'] . $f->thumb); } // Delete Thread - @unlink($board['dir'] . $config['dir']['featured'] . $config['dir']['res'] . sprintf($config['file_page'], $thread_id)); + @unlink($board['dir'] . ($mod_archive?$config['dir']['mod_archive']:$config['dir']['featured']) . $config['dir']['res'] . sprintf($config['file_page'], $thread_id)); // Delete Entry in DB if it has timed out if($thread['lifetime'] != 0 && $thread['lifetime'] < strtotime("-" . $config['archive']['lifetime'])) - query(sprintf("DELETE FROM ``archive_%s`` WHERE `id` = %d", $board['uri'], (int)$thread_id)) or error(db_error()); + query(sprintf("DELETE FROM ``archive_%s`` WHERE `id` = %d AND " . ($mod_archive?"`featured`":"`mod_archived`") . " = 0", $board['uri'], (int)$thread_id)) or error(db_error()); else - query(sprintf("UPDATE ``archive_%s`` SET `featured` = 0 WHERE `id` = %d", $board['uri'], (int)$thread_id)) or error(db_error()); + query(sprintf("UPDATE ``archive_%s`` SET " . ($mod_archive?"`mod_archived`":"`featured`") . " = 0 WHERE `id` = %d", $board['uri'], (int)$thread_id)) or error(db_error()); + // Add mod log entry + modLog(sprintf("Deleted thread #%d from " . ($mod_archive?"mod archive":"featured threads"), $thread_id)); + // Rebuild Featured Index self::buildFeaturedIndex(); } @@ -274,15 +284,18 @@ class Archive { - static public function getArchiveList($featured = false) { + static public function getArchiveList($featured = false, $mod_archive = false) { global $config, $board; $archive = false; if($featured) { - $query = query(sprintf("SELECT `id`, `snippet`, `featured` FROM ``archive_%s`` WHERE `featured` = 1 ORDER BY `lifetime` DESC", $board['uri'])) or error(db_error()); + $query = query(sprintf("SELECT `id`, `snippet`, `featured`, `mod_archived` FROM ``archive_%s`` WHERE `featured` = 1 ORDER BY `lifetime` DESC", $board['uri'])) or error(db_error()); + $archive = $query->fetchAll(PDO::FETCH_ASSOC); + } else if($mod_archive) { + $query = query(sprintf("SELECT `id`, `snippet`, `featured`, `mod_archived` FROM ``archive_%s`` WHERE `mod_archived` = 1 ORDER BY `lifetime` DESC", $board['uri'])) or error(db_error()); $archive = $query->fetchAll(PDO::FETCH_ASSOC); } else { - $query = prepare(sprintf("SELECT `id`, `snippet`, `featured` FROM ``archive_%s`` WHERE `lifetime` > :lifetime ORDER BY `lifetime` DESC", $board['uri'])); + $query = prepare(sprintf("SELECT `id`, `snippet`, `featured`, `mod_archived` FROM ``archive_%s`` WHERE `lifetime` > :lifetime ORDER BY `lifetime` DESC", $board['uri'])); $query->bindValue(':lifetime', strtotime("-" . $config['archive']['lifetime']), PDO::PARAM_INT); $query->execute() or error(db_error()); $archive = $query->fetchAll(PDO::FETCH_ASSOC); diff --git a/inc/config.php b/inc/config.php index 2177e507..a9494ee8 100644 --- a/inc/config.php +++ b/inc/config.php @@ -1320,6 +1320,8 @@ $config['dir']['archive'] = 'archive/'; // Directory for "Featured Threads" (threads makred for permanent storage) $config['dir']['featured'] = 'featured/'; + // Directory for "Featured Threads" (threads makred for permanent storage) + $config['dir']['mod_archive'] = 'mod_archive/'; // For load balancing, having a seperate server (and domain/subdomain) for serving static content is @@ -1377,6 +1379,9 @@ // Indicate if link to featured archive should be shown on post and thread page $config['feature']['link_post_page'] = false; + // Indicate if it is possible to mark threads as nostalgic (stored forever but will only be accessable to mods) + $config['mod_archive']['threads'] = true; + // Days to keep archived threads before deletion (ex. "60 minutes", "6 hours", "1 day", "1 week"), if set to false all archived threads are kept forever $config['archive']['lifetime'] = "3 days"; @@ -1766,6 +1771,12 @@ $config['mod']['feature_archived_threads'] = JANITOR; // Delete featured archived threads $config['mod']['delete_featured_archived_threads'] = MOD; + // View mod archive + $config['mod']['view_mod_archive'] = MOD; + // Archive threads for mods + $config['mod']['add_to_mod_archive'] = MOD; + // Archive threads for mods + $config['mod']['remove_from_mod_archive'] = MOD; // Automatically permanently delete posts and threads (set to false if you want to keep for all) $config['mod']['auto_delete_shadow_post'] = MOD; // View shadow deleted posts and threads diff --git a/inc/functions.php b/inc/functions.php index c961f1b2..55ad9b76 100755 --- a/inc/functions.php +++ b/inc/functions.php @@ -563,7 +563,7 @@ function setupBoard($array) { @mkdir($board['dir'] . $config['dir']['res'], 0777) or error("Couldn't create " . $board['dir'] . $config['dir']['img'] . ". Check permissions.", true); - // Create Archive Folders + // Create archive folders if (!file_exists($board['dir'] . $config['dir']['archive'])) @mkdir($board['dir'] . $config['dir']['archive'], 0777) or error("Couldn't create " . $board['dir'] . $config['dir']['archive'] . ". Check permissions.", true); @@ -576,7 +576,7 @@ function setupBoard($array) { if (!file_exists($board['dir'] . $config['dir']['archive'] . $config['dir']['res'])) @mkdir($board['dir'] . $config['dir']['archive'] . $config['dir']['res'], 0777) or error("Couldn't create " . $board['dir'] . $config['dir']['archive'] . $config['dir']['img'] . ". Check permissions.", true); - // Create Featured threads Folders + // Create featured threads folders if (!file_exists($board['dir'] . $config['dir']['featured'])) @mkdir($board['dir'] . $config['dir']['featured'], 0777) or error("Couldn't create " . $board['dir'] . $config['dir']['featured'] . ". Check permissions.", true); @@ -589,6 +589,29 @@ function setupBoard($array) { if (!file_exists($board['dir'] . $config['dir']['featured'] . $config['dir']['res'])) @mkdir($board['dir'] . $config['dir']['featured'] . $config['dir']['res'], 0777) or error("Couldn't create " . $board['dir'] . $config['dir']['featured'] . $config['dir']['img'] . ". Check permissions.", true); + // Create mod archive threads folders + if (!file_exists($board['dir'] . $config['dir']['mod_archive'])) + @mkdir($board['dir'] . $config['dir']['mod_archive'], 0777) + or $file_errors .= "Couldn't create " . $board['dir'] . $config['dir']['mod_archive'] . ". Check permissions.
    "; + if (!file_exists($board['dir'] . $config['dir']['mod_archive'] . $config['dir']['img'])) + @mkdir($board['dir'] . $config['dir']['mod_archive'] . $config['dir']['img'], 0777) + or $file_errors .= "Couldn't create " . $board['dir'] . $config['dir']['feamod_archivetured'] . $config['dir']['img'] . ". Check permissions.
    "; + if (!file_exists($board['dir'] . $config['dir']['mod_archive'] . $config['dir']['thumb'])) + @mkdir($board['dir'] . $config['dir']['mod_archive'] . $config['dir']['thumb'], 0777) + or $file_errors .= "Couldn't create " . $board['dir'] . $config['dir']['mod_archive'] . $config['dir']['thumb'] . ". Check permissions.
    "; + if (!file_exists($board['dir'] . $config['dir']['mod_archive'] . $config['dir']['res'])) + @mkdir($board['dir'] . $config['dir']['mod_archive'] . $config['dir']['res'], 0777) + or $file_errors .= "Couldn't create " . $board['dir'] . $config['dir']['mod_archive'] . $config['dir']['res'] . ". Check permissions.
    "; + // Create shadow delete folders to save files in + if (!file_exists($board['dir'] . $config['dir']['shadow_del'])) + @mkdir($board['dir'] . $config['dir']['shadow_del'], 0777) + or $file_errors .= "Couldn't create " . $board['dir'] . $config['dir']['shadow_del'] . ". Check permissions.
    "; + if (!file_exists($board['dir'] . $config['dir']['shadow_del'] . $config['dir']['img'])) + @mkdir($board['dir'] . $config['dir']['shadow_del'] . $config['dir']['img'], 0777) + or $file_errors .= "Couldn't create " . $board['dir'] . $config['dir']['shadow_del'] . $config['dir']['img'] . ". Check permissions.
    "; + if (!file_exists($board['dir'] . $config['dir']['shadow_del'] . $config['dir']['thumb'])) + @mkdir($board['dir'] . $config['dir']['shadow_del'] . $config['dir']['thumb'], 0777) + or $file_errors .= "Couldn't create " . $board['dir'] . $config['dir']['shadow_del'] . $config['dir']['thumb'] . ". Check permissions.
    "; } function openBoard($uri) { diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 572f3a48..e6a0ec6a 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -375,6 +375,9 @@ function mod_edit_board($boardName) { // Delete archive table $query = query(sprintf('DROP TABLE IF EXISTS ``archive_%s``', $board['uri'])) or error(db_error()); + // Delete shadow delete table + $query = query(sprintf('DROP TABLE IF EXISTS ``shadow_posts_%s``', $board['uri'])) or error(db_error()); + // Clear reports $query = prepare('DELETE FROM ``reports`` WHERE `board` = :id'); $query->bindValue(':id', $board['uri'], PDO::PARAM_STR); @@ -3839,6 +3842,12 @@ function mod_view_archive($boardName) { Archive::featureThread($_POST['id']); } + else if(isset($_POST['mod_archive'], $_POST['id'])) { + if(!hasPermission($config['mod']['add_to_mod_archive'], $board['uri'])) + error($config['error']['noaccess']); + + Archive::featureThread($_POST['id'], true); + } // Get Archive List $archive = Archive::getArchiveList(); @@ -3881,9 +3890,47 @@ function mod_view_archive_featured($boardName) { mod_page(sprintf(_('Featured') . ' %s: ' . $config['board_abbreviation'], _('threads'), $board['uri']), 'mod/archive_featured_list.html', array( 'archive' => $archive, + 'board' => $board, 'token' => make_secure_link_token($board['uri']. '/featured/') )); } + +function mod_view_archive_mod_archive($boardName) { + global $board, $config; + + // If archiving is turned off return + if(!$config['mod_archive']['threads']) + return; + + if(!hasPermission($config['mod']['view_mod_archive'], $board['uri'])) + error($config['error']['noaccess']); + + if (!openBoard($boardName)) + error($config['error']['noboard']); + + if(isset($_POST['delete'], $_POST['id'])) { + if(!hasPermission($config['mod']['remove_from_mod_archive'], $board['uri'])) + error($config['error']['noaccess']); + + Archive::deleteFeatured($_POST['id'], true); + } + + $query = query(sprintf("SELECT `id`, `snippet` FROM ``archive_%s`` WHERE `mod_archived` = 1 ORDER BY `lifetime` DESC", $board['uri'])) or error(db_error()); + $archive = $query->fetchAll(PDO::FETCH_ASSOC); + + foreach($archive as &$thread) + $thread['featured_url'] = sprintf($config['board_path'], $board['uri']) . $config['dir']['mod_archive'] . $config['dir']['res'] . sprintf($config['file_page'], $thread['id']); + + mod_page(sprintf(_('Mod Archive') . ' %s: ' . $config['board_abbreviation'], _('threads'), $board['uri']), 'mod/archive_featured_list.html', array( + 'archive' => $archive, + 'is_mod_archive' => true, + 'board' => $board, + 'token' => make_secure_link_token($board['uri']. '/mod_archive/') + )); +} + + + diff --git a/js/gallery-view.js b/js/gallery-view.js index 2d7d85b4..f4cc7df3 100644 --- a/js/gallery-view.js +++ b/js/gallery-view.js @@ -116,7 +116,7 @@ $(function(){ if (img.match(/\.webm$|\.mp4$|\.ogv$/i)) { // We are handling video nao i = $('