diff --git a/phpBB/adm/admin_attachments.php b/phpBB/adm/admin_attachments.php
index e129930dee..a4e6ecfed1 100644
--- a/phpBB/adm/admin_attachments.php
+++ b/phpBB/adm/admin_attachments.php
@@ -356,7 +356,7 @@ if ($submit && $mode == 'orphan')
 		while ($row = $db->sql_fetchrow($result))
 		{
 			echo sprintf($user->lang['UPLOADING_FILE_TO'], $upload_list[$row['post_id']], $row['post_id']) . '<br />';
-			if (!$auth->acl_get('f_attach', $row['forum_id']))
+			if (!$auth->acl_gets('f_attach', 'u_attach', $row['forum_id']))
 			{
 				echo '<span style="color:red">' . sprintf($user->lang['UPLOAD_DENIED_FORUM'], $forum_names[$row['forum_id']]) . '</span><br /><br />';
 			}
@@ -716,7 +716,7 @@ function marklist(match, name, status)
 
 <?php
 	$sql = 'SELECT physical_filename 
-		FROM ' . ATTACHMENTS_DESC_TABLE;
+		FROM ' . ATTACHMENTS_TABLE;
 	$result = $db->sql_query($sql);
 
 	while ($row = $db->sql_fetchrow($result))
@@ -918,6 +918,9 @@ function upload_file($post_id, $topic_id, $forum_id, $upload_dir, $filename)
 	if ($filedata['post_attach'] && !sizeof($filedata['error']))
 	{
 		$message_parser->attachment_data = array(
+			'post_id'			=> $post_id,
+			'poster_id'			=> $user->data['user_id'],
+			'topic_id'			=> $topic_id,
 			'physical_filename'	=> $filedata['destination_filename'],
 			'real_filename'		=> $filedata['filename'],
 			'comment'			=> $message_parser->filename_data['filecomment'],
@@ -936,17 +939,6 @@ function upload_file($post_id, $topic_id, $forum_id, $upload_dir, $filename)
 
 		$db->sql_transaction();
 
-		$sql = 'INSERT INTO ' . ATTACHMENTS_DESC_TABLE . ' ' . $db->sql_build_array('INSERT', $attach_sql);
-		$db->sql_query($sql);
-
-		$attach_sql = array(
-			'attach_id'		=> $db->sql_nextid(),
-			'post_id'		=> $post_id,
-			'privmsgs_id'	=> 0,
-			'user_id_from'	=> $user->data['user_id'],
-			'user_id_to'	=> 0
-		);
-
 		$sql = 'INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $attach_sql);
 		$db->sql_query($sql);
 
diff --git a/phpBB/adm/admin_forums.php b/phpBB/adm/admin_forums.php
index ee88d4d0f5..f30d63eb83 100644
--- a/phpBB/adm/admin_forums.php
+++ b/phpBB/adm/admin_forums.php
@@ -1307,6 +1307,8 @@ function delete_forum_content($forum_id)
 	switch (SQL_LAYER)
 	{
 		case 'mysql4':
+			// Use delete_attachments('topic', $ids, false) here...
+		
 			// Select then delete all attachments
 			$sql = 'SELECT d.physical_filename, d.thumbnail
 				FROM ' . POSTS_TABLE . ' p, ' . ATTACHMENTS_DESC_TABLE . ' d, ' . ATTACHMENTS_TABLE . " a
diff --git a/phpBB/common.php b/phpBB/common.php
index 0187566308..4e1bc628bc 100644
--- a/phpBB/common.php
+++ b/phpBB/common.php
@@ -149,7 +149,6 @@ define('ACL_DEPS_TABLE', $table_prefix.'auth_deps');
 define('ACL_PRESETS_TABLE', $table_prefix.'auth_presets');
 define('ACL_USERS_TABLE', $table_prefix.'auth_users');
 define('ATTACHMENTS_TABLE', $table_prefix.'attachments');
-define('ATTACHMENTS_DESC_TABLE', $table_prefix.'attach_desc');
 define('BANLIST_TABLE', $table_prefix.'banlist');
 define('BBCODES_TABLE', $table_prefix.'bbcodes');
 define('BOTS_TABLE', $table_prefix.'bots');
diff --git a/phpBB/download.php b/phpBB/download.php
index 209a969caf..c728777d02 100644
--- a/phpBB/download.php
+++ b/phpBB/download.php
@@ -36,7 +36,7 @@ if (!$config['allow_attachments'])
 }
 
 $sql = 'SELECT *
-	FROM ' . ATTACHMENTS_DESC_TABLE . "
+	FROM ' . ATTACHMENTS_TABLE . "
 	WHERE attach_id = $download_id";
 $result = $db->sql_query_limit($sql, 1);
 
@@ -46,42 +46,24 @@ if (!($attachment = $db->sql_fetchrow($result)))
 }
 $db->sql_freeresult($result);
 
-// get forum_id for attachment authorization or private message authorization
-$authorised = false;
-
 // Additional query, because of more than one attachment assigned to posts and private messages
-$sql = 'SELECT a.*, p.forum_id, f.forum_password, f.parent_id
-	FROM ' . ATTACHMENTS_TABLE . ' a, ' . POSTS_TABLE . ' p, ' . FORUMS_TABLE . ' f
-	WHERE a.attach_id = ' . $attachment['attach_id'] . '
-		AND ((a.post_id = p.post_id AND p.forum_id = f.forum_id) 
-			OR a.post_id = 0)';
-$result = $db->sql_query($sql);
-
-while ($row = $db->sql_fetchrow($result))
-{
-	if ($row['post_id'] && $auth->acl_get('f_download', $row['forum_id']))
-	{
-		if ($row['forum_password'])
-		{
-			// Do something else ... ?
-			login_forum_box($row);
-		}
-
-		$authorised = TRUE;
-		break;
-	}
-	else
-	{
-		if ($config['allow_pm_attach'] && ($user->data['user_id'] == $row['user_id_2'] || $user->data['user_id'] == $row['user_id_1']))
-		{
-			$authorised = TRUE;
-			break;
-		}
-	}
-}
+$sql = 'SELECT p.forum_id, f.forum_password, f.parent_id
+	FROM ' . POSTS_TABLE . ' p, ' . FORUMS_TABLE . ' f
+	WHERE p.post_id = ' . $attachment['post_id'] . '
+		AND p.forum_id = f.forum_id';
+$result = $db->sql_query_limit($sql, 1);
+$row = $db->sql_fetchrow($result);
 $db->sql_freeresult($result);
 
-if (!$authorised)
+if ($auth->acl_gets('f_download', 'u_download', $row['forum_id']))
+{
+	if ($row['forum_password'])
+	{
+		// Do something else ... ?
+		login_forum_box($row);
+	}
+}
+else
 {
 	trigger_error('SORRY_AUTH_VIEW_ATTACH');
 }
@@ -105,7 +87,7 @@ if ($thumbnail)
 else
 {
 	// Update download count
-	$sql = 'UPDATE ' . ATTACHMENTS_DESC_TABLE . ' 
+	$sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' 
 		SET download_count = download_count + 1 
 		WHERE attach_id = ' . $attachment['attach_id'];
 	$db->sql_query($sql);
diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/mysql.php
index f5f89e3d1e..82eef2290b 100644
--- a/phpBB/includes/db/mysql.php
+++ b/phpBB/includes/db/mysql.php
@@ -381,7 +381,7 @@ class sql_db
 	// DEBUG
 	function sql_report($mode, $query = '')
 	{
-		if (empty($_GET['explain']))
+		if (empty($_REQUEST['explain']))
 		{
 			return;
 		}
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php
index 9eac5d44ce..3faef1a8de 100644
--- a/phpBB/includes/functions_admin.php
+++ b/phpBB/includes/functions_admin.php
@@ -431,7 +431,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = TRUE)
 	}
 	unset($table_ary);
 
-	delete_attachments($post_ids);
+	delete_attachments('post', $post_ids, FALSE);
 
 	$db->sql_transaction('commit');
 
@@ -466,215 +466,152 @@ function delete_posts($where_type, $where_ids, $auto_sync = TRUE)
 }
 
 // Delete Attachments
-function delete_attachments($post_id_array = -1, $attach_id_array = -1, $page = 'post', $user_id = -1)
+// mode => (post, topic, attach, user)
+// ids => (post_ids, topic_ids, attach_ids, user_ids)
+// resync => set this to false if you are deleting posts or topics...
+function delete_attachments($mode, $ids, $resync = TRUE)
 {
 	global $db;
 
-	if ($post_id_array == -1 && $attach_id_array == -1 && $page == -1)
+	if (is_array($ids))
 	{
-		return;
+		$ids = array_unique($ids);
 	}
-
-	// Generate Array, if it's not an array
-	if ($post_id_array == -1 && $attach_id_array != -1)
-	{
-		$post_id_array = array();
-
-		if (!is_array($attach_id_array))
-		{
-			$attach_id_array = (strstr($attach_id_array, ',')) ? explode(',', str_replace(', ', ',', $attach_id_array)) : array((int) $attach_id_array);
-		}
 	
-		// Get the post_ids to fill the array
-		$sql = 'SELECT ' . (($page == 'privmsgs') ? 'privmsgs_id' : 'post_id') . ' as id 
-			FROM ' . ATTACHMENTS_TABLE . ' 
-			WHERE attach_id IN (' . implode(', ', $attach_id_array) . ')
-			GROUP BY id';
-		$result = $db->sql_query($sql);
-
-		if (!($row = $db->sql_fetchrow($result)))
-		{
-			return;
-		}
-
-		do
-		{
-			$post_id_array[] = $row['id'];
-		}
-		while ($row = $db->sql_fetchrow($result));
-		$db->sql_freeresult($result);
-	}
-		
-	if (!is_array($post_id_array))
+	if (!sizeof($ids))
 	{
-		if (trim($post_id_array) == '')
-		{
-			return;
-		}
-
-		$post_id_array = (strstr($post_id_array, ',')) ? explode(',', str_replace(', ', ',', $attach_id_array)) : array((int) $post_id_array);
-	}
-		
-	if (!count($post_id_array))
-	{
-		return;
+		return false;
 	}
 
-	// First of all, determine the post id and attach_id
-	if ($attach_id_array == -1)
-	{
-		$attach_id_array = array();
+	$sql_id = ($mode == 'user') ? 'poster_id' : (($mode == 'post') ? 'post_id' : (($mode == 'topic') ? 'topic_id' : 'attach_id'));
 
-		// Get the attach_ids to fill the array
-		$sql = 'SELECT attach_id 
+	$post_ids = $topic_ids = $physical = array();
+
+	// Collect post and topics ids for later use
+	if ($mode == 'attach' || $mode == 'user' || ($mode == 'topic' && $resync))
+	{
+		$sql = 'SELECT post_id, topic_id, physical_filename, thumbnail
 			FROM ' . ATTACHMENTS_TABLE . '
-			WHERE ' . (($page == 'privmsgs') ? 'privmsgs_id' : 'post_id') . ' IN (' . implode(', ', $post_id_array) . ')
-			GROUP BY attach_id';
+			WHERE ' . $sql_id . ' IN (' . implode(', ', $ids) . ')';
 		$result = $db->sql_query($sql);
-
-		if (!($row = $db->sql_fetchrow($result)))
-		{
-			return;
-		}
-
-		do
-		{
-			$attach_id_array[] = $row['attach_id'];
-		}
-		while ($row = $db->sql_fetchrow($result));
-		$db->sql_freeresult($result);
-	}
-	
-	if (!is_array($attach_id_array))
-	{
-		$attach_id_array = (strstr($post_id_array, ',')) ? explode(',', str_replace(', ', ',', $attach_id_array)) : array((int) $attach_id_array);
-	}
-
-	if (!count($attach_id_array))
-	{
-		return;
-	}
-
-	$sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' 
-		WHERE attach_id IN (' . implode(', ', $attach_id_array) . ') 
-			AND post_id IN (' . implode(', ', $post_id_array) . ')';
-	$db->sql_query($sql);
-	
-	foreach ($attach_id_array as $attach_id)
-	{
-		$sql = 'SELECT attach_id 
-			FROM ' . ATTACHMENTS_TABLE . " 
-			WHERE attach_id = $attach_id";
-		$select_result = $db->sql_query($sql);			
-
-		if (!is_array($db->sql_fetchrow($select_result)))
-		{
-			$sql = 'SELECT attach_id, physical_filename, thumbnail
-				FROM ' . ATTACHMENTS_DESC_TABLE . "
-				WHERE attach_id = $attach_id";
-			$result = $db->sql_query($sql);	
-		
-			// delete attachments
-			while ($row = $db->sql_fetchrow($result))
-			{
-				phpbb_unlink($row['physical_filename'], 'file');
-				if ($row['thumbnail'])
-				{
-					phpbb_unlink($row['physical_filename'], 'thumbnail');
-				}
-					
-				$sql = 'DELETE FROM ' . ATTACHMENTS_DESC_TABLE . '
-					WHERE attach_id = ' . $row['attach_id'];
-				$db->sql_query($sql);
-			}
-			$db->sql_freeresult($result);
-		}
-		$db->sql_freeresult($select_result);
-	}
-	
-	// Now Sync the Topic/PM
-	if ($page == 'privmsgs')
-	{
-		foreach ($post_id_array as $privmsgs_id)
-		{
-			$sql = 'SELECT attach_id 
-				FROM ' . ATTACHMENTS_TABLE . ' 
-				WHERE privmsgs_id = ' . $privmsgs_id;
-			$select_result = $db->sql_query($sql);
-
-			if (!is_array($db->sql_fetchrow($select_result)))
-			{
-				$sql = 'UPDATE ' . PRIVMSGS_TABLE . ' 
-					SET privmsgs_attachment = 0 
-					WHERE privmsgs_id = ' . $privmsgs_id;
-				$db->sql_query($sql);
-			}
-			$db->sql_freeresult($select_result);
-		}
-	}
-	else
-	{
-		$sql = 'SELECT topic_id 
-			FROM ' . POSTS_TABLE . ' 
-			WHERE post_id IN (' . implode(', ', $post_id_array) . ') 
-			GROUP BY topic_id';
-		$result = $db->sql_query($sql);
-	
+			
 		while ($row = $db->sql_fetchrow($result))
 		{
-			$topic_id = $row['topic_id'];
-
-			$sql = 'SELECT post_id 
-				FROM ' . POSTS_TABLE . "
-				WHERE topic_id = $topic_id
-				GROUP BY post_id";
-			$result2 = $db->sql_query($sql);		
-			
-			$post_ids = array();
-
-			while ($post_row = $db->sql_fetchrow($result2))
-			{
-				$post_ids[] = $post_row['post_id'];
-			}
-			$db->sql_freeresult($result2);
-
-			if (count($post_ids))
-			{
-				$post_id_sql = implode(', ', $post_ids);
-	
-				$sql = 'SELECT attach_id 
-					FROM ' . ATTACHMENTS_TABLE . "
-					WHERE post_id IN ($post_id_sql)";
-				$select_result = $db->sql_query_limit($sql, 1);
-				$set_id = (!is_array($db->sql_fetchrow($select_result))) ? 0 : 1;
-				$db->sql_freeresult($select_result);
-
-				$sql = 'UPDATE ' . TOPICS_TABLE . " 
-					SET topic_attachment = $set_id 
-					WHERE topic_id = $topic_id";
-				$db->sql_query($sql);
-				
-				foreach ($post_ids as $post_id)
-				{
-					$sql = 'SELECT attach_id 
-						FROM ' . ATTACHMENTS_TABLE . " 
-						WHERE post_id = $post_id";
-					$select_result = $db->sql_query_limit($sql, 1);
-					$set_id = (!is_array($db->sql_fetchrow($select_result))) ? 0 : 1;
-					$db->sql_freeresult($select_result);
-		
-					$sql = 'UPDATE ' . POSTS_TABLE . " 
-						SET post_attachment = $set_id
-						WHERE post_id = $post_id";
-					$db->sql_query($sql);
-				}
-			}
+			$post_ids[] = $row['post_id'];
+			$topic_ids[] = $row['topic_id'];
+			$physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail']);
 		}
 		$db->sql_freeresult($result);
 	}
 
-	// TODO
-	// Return number of deleted attachments
+	if ($mode == 'post')
+	{
+		$sql = 'SELECT topic_id, physical_filename, thumbnail
+			FROM ' . ATTACHMENTS_TABLE . '
+			WHERE post_id IN (' . implode(', ', $ids) . ')';
+		$result = $db->sql_query($sql);
+			
+		while ($row = $db->sql_fetchrow($result))
+		{
+			$topic_ids[] = $row['topic_id'];
+			$physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail']);
+		}
+		$db->sql_freeresult($result);
+	}
+
+	// Delete attachments
+	$db->sql_query('DELETE FROM ' . ATTACHMENTS_TABLE . ' WHERE ' . $sql_id . ' IN (' . implode(', ', $ids) . ')');
+	$num_deleted = $db->sql_affectedrows();
+
+	// Delete attachments from filesystem
+	foreach ($physical as $file_ary)
+	{
+		phpbb_unlink($file_ary['filename'], 'file');
+		if ($file_ary['thumbnail'])
+		{
+			phpbb_unlink($file_ary['filename'], 'thumbnail');
+		}
+	}
+
+	if ($mode == 'topic' && !$resync)
+	{
+		return $num_deleted;
+	}
+
+	if ($mode == 'post')
+	{
+		$post_ids = $ids;
+	}
+	unset($ids);
+
+	$post_ids = array_unique($post_ids);
+	$topic_ids = array_unique($topic_ids);
+
+	// Update post indicators
+	if ($mode == 'post' || $mode == 'topic')
+	{
+		$db->sql_query('UPDATE ' . POSTS_TABLE . ' 
+				SET post_attachment = 0
+				WHERE post_id IN (' . implode(', ', $post_ids) . ')');
+	}
+
+	if ($mode == 'user' || $mode == 'attach')
+	{
+		$remaining = array();
+
+		$sql = 'SELECT post_id
+				FROM ' . ATTACHMENTS_TABLE . ' 
+				WHERE post_id IN (' . implode(', ', $post_ids) . ')';
+		$result = $db->sql_query($sql);
+					
+		while ($row = $db->sql_fetchrow($result))
+		{
+			$remaining[] = $row['post_id'];		
+		}
+		$db->sql_fetchrow($result);
+
+		$unset_ids = array_diff($post_ids, $remaining);
+		if (sizeof($delete_ids))
+		{
+			$db->sql_query('UPDATE ' . POSTS_TABLE . ' 
+				SET post_attachment = 0
+				WHERE post_id IN (' . implode(', ', $unset_ids) . ')');
+		}
+	}
+
+	// Update topic indicator
+	if ($mode == 'topic')
+	{
+		$db->sql_query('UPDATE ' . TOPICS_TABLE . '
+			SET topic_attachment = 0
+			WHERE topic_id IN (' . implode(', ', $topic_ids) . ')');
+	}
+
+	if ($mode == 'post' || $mode == 'user' || $mode == 'attach')
+	{
+		$remaining = array();
+
+		$sql = 'SELECT topic_id
+				FROM ' . ATTACHMENTS_TABLE . ' 
+				WHERE topic_id IN (' . implode(', ', $topic_ids) . ')';
+		$result = $db->sql_query($sql);
+
+		while ($row = $db->sql_fetchrow($result))
+		{
+			$remaining[] = $row['topic_id'];		
+		}
+		$db->sql_fetchrow($result);
+
+		$unset_ids = array_diff($topic_ids, $remaining);
+		if (sizeof($unset_ids))
+		{
+			$db->sql_query('UPDATE ' . TOPICS_TABLE . ' 
+				SET topic_attachment = 0
+				WHERE topic_id IN (' . implode(', ', $unset_ids) . ')');
+		}
+	}
+	
+	return $num_deleted;
 }
 
 function delete_topic_shadows($max_age, $forum_id = '', $auto_sync = TRUE)
diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php
index 17ba765b8f..d96f2cb9c9 100644
--- a/phpBB/includes/functions_display.php
+++ b/phpBB/includes/functions_display.php
@@ -292,6 +292,8 @@ function display_attachments($attachment_data, &$update_count, $force_physical =
 	global $extensions, $template;
 	global $config, $user, $phpbb_root_path, $phpEx, $SID, $censors;
 
+	$upload_dir = ($config['upload_dir'][0] == '/' || ($config['upload_dir'][0] != '/' && $config['upload_dir'][1] == ':')) ? $config['upload_dir'] : $phpbb_root_path . $config['upload_dir'];
+
 	if (empty($censors))
 	{
 		$censors = array();
@@ -304,14 +306,12 @@ function display_attachments($attachment_data, &$update_count, $force_physical =
 		obtain_attach_extensions($extensions);
 	}
 
-	$update_count = array();
-
 	foreach ($attachment_data as $attachment)
 	{
 		// Some basics...
 		$attachment['extension'] = strtolower(trim($attachment['extension']));
-		$filename = $config['upload_dir'] . '/' . $attachment['physical_filename'];
-		$thumbnail_filename = $config['upload_dir'] . '/thumbs/t_' . $attachment['physical_filename'];
+		$filename = $upload_dir . '/' . $attachment['physical_filename'];
+		$thumbnail_filename = $upload_dir . '/thumbs/t_' . $attachment['physical_filename'];
 
 		$upload_image = '';
 
diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php
index 92557fbb78..2de8b424c3 100644
--- a/phpBB/includes/message_parser.php
+++ b/phpBB/includes/message_parser.php
@@ -746,7 +746,7 @@ class parse_message
 				}
 				else
 				{
-					delete_attachments($post_id, intval($this->attachment_data[$index]['attach_id']));
+					delete_attachments('attach', array(intval($this->attachment_data[$index]['attach_id'])));
 				}
 				
 				unset($this->attachment_data[$index]);
diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php
index ccaf4beca7..bcaabdceb8 100644
--- a/phpBB/includes/ucp/ucp_main.php
+++ b/phpBB/includes/ucp/ucp_main.php
@@ -133,7 +133,7 @@ class ucp_main extends module
 						'LAST_POST_IMG' 	=> $last_post_img,
 						'NEWEST_POST_IMG' 	=> $newest_post_img,
 						'TOPIC_FOLDER_IMG' 	=> $user->img($folder_img, $folder_alt),
-						'ATTACH_ICON_IMG'	=> ($auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_attach', '') : '',
+						'ATTACH_ICON_IMG'	=> ($auth->acl_gets('f_download', 'u_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_attach', '') : '',
 
 						'S_ROW_COUNT'		=> $i, 
 						'S_USER_POSTED'		=> (!empty($row['mark_type'])) ? true : false, 
@@ -487,7 +487,7 @@ class ucp_main extends module
 						'LAST_POST_IMG' 	=> $last_post_img,
 						'NEWEST_POST_IMG' 	=> $newest_post_img,
 						'TOPIC_FOLDER_IMG' 	=> $user->img($folder_img, $folder_alt),
-						'ATTACH_ICON_IMG'	=> ($auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_attach', '') : '',
+						'ATTACH_ICON_IMG'	=> ($auth->acl_gets('f_download', 'u_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_attach', '') : '',
 
 						'S_ROW_COUNT'		=> $i++, 
 						'S_USER_POSTED'		=> (!empty($row['mark_type'])) ? true : false, 
diff --git a/phpBB/install/schemas/mysql_schema.sql b/phpBB/install/schemas/mysql_schema.sql
index 305676fbbe..77b50d3b75 100644
--- a/phpBB/install/schemas/mysql_schema.sql
+++ b/phpBB/install/schemas/mysql_schema.sql
@@ -4,19 +4,12 @@
 # $Id$
 #
 
-# Table: phpbb_attachments
-CREATE TABLE phpbb_attachments (
-  attach_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
-  post_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
-  privmsgs_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
-  user_id_from mediumint(8) NOT NULL,
-  user_id_to mediumint(8) NOT NULL,
-  KEY attach_id (attach_id)
-);
-
 # Table: phpbb_attachments_desc
-CREATE TABLE phpbb_attach_desc (
+CREATE TABLE phpbb_attachments (
   attach_id mediumint(8) UNSIGNED NOT NULL auto_increment,
+  post_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
+  topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
+  poster_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
   physical_filename varchar(255) NOT NULL,
   real_filename varchar(255) NOT NULL,
   download_count mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
@@ -28,6 +21,9 @@ CREATE TABLE phpbb_attach_desc (
   thumbnail tinyint(1) DEFAULT '0' NOT NULL,
   PRIMARY KEY (attach_id),
   KEY filetime (filetime),
+  KEY post_id (post_id),
+  KEY topic_id (topic_id),
+  KEY poster_id (poster_id),
   KEY physical_filename (physical_filename(10)),
   KEY filesize (filesize)
 );
diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql
index 844ffcf2bd..095c3c3328 100644
--- a/phpBB/install/schemas/schema_data.sql
+++ b/phpBB/install/schemas/schema_data.sql
@@ -168,7 +168,7 @@ INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_post', 1);
 INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_reply', 1);
 INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_quote', 1);
 INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_edit', 1);
-INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_lock', 1);
+INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_user_lock', 1);
 INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_delete', 1);
 INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_bump', 1);
 INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_poll', 1);
@@ -192,6 +192,7 @@ INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_ignoreflood',
 INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_postcount', 1);
 INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_moderate', 1);
 INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_report', 1);
+INSERT INTO phpbb_auth_options (auth_option, is_local) VALUES ('f_subscribe', 1);
 
 INSERT INTO phpbb_auth_options (auth_option, is_local, is_global) VALUES ('m_', 1, 1);
 INSERT INTO phpbb_auth_options (auth_option, is_local, is_global) VALUES ('m_edit', 1, 1);
@@ -259,6 +260,8 @@ INSERT INTO phpbb_auth_options (auth_option, is_global) VALUES ('u_chgpasswd', 1
 INSERT INTO phpbb_auth_options (auth_option, is_global) VALUES ('u_chgcensors', 1);
 INSERT INTO phpbb_auth_options (auth_option, is_global) VALUES ('u_search', 1);
 INSERT INTO phpbb_auth_options (auth_option, is_global) VALUES ('u_savedrafts', 1);
+INSERT INTO phpbb_auth_options (auth_option, is_global) VALUES ('u_download', 1);
+INSERT INTO phpbb_auth_options (auth_option, is_global) VALUES ('u_attach', 1);
 
 
 # MSSQL IDENTITY phpbb_styles ON #
@@ -407,11 +410,11 @@ INSERT INTO phpbb_auth_groups (group_id, forum_id, auth_option_id, auth_setting)
 
 # REGISTERED/REGISTERED COPPA groups - common forum rights
 INSERT INTO phpbb_auth_groups (group_id, forum_id, auth_option_id, auth_setting) SELECT 4, 0, auth_option_id, 1 FROM phpbb_auth_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_chggrp', 'u_viewonline', 'u_chgname');
-INSERT INTO phpbb_auth_groups (group_id, forum_id, auth_option_id, auth_setting) SELECT 4, 1, auth_option_id, 1 FROM phpbb_auth_options WHERE auth_option IN ('f_', 'f_list', 'f_read', 'f_post', 'f_reply', 'f_quote', 'f_edit', 'f_delete', 'f_vote', 'f_download', 'f_bbcode', 'f_smilies', 'f_img', 'f_flash', 'f_sigs', 'f_search', 'f_email', 'f_print', 'f_postcount');
-INSERT INTO phpbb_auth_groups (group_id, forum_id, auth_option_id, auth_setting) SELECT 4, 2, auth_option_id, 1 FROM phpbb_auth_options WHERE auth_option IN ('f_', 'f_list', 'f_read', 'f_post', 'f_reply', 'f_quote', 'f_edit', 'f_delete', 'f_vote', 'f_votechg', 'f_download', 'f_bbcode', 'f_smilies', 'f_img', 'f_flash', 'f_sigs', 'f_search', 'f_email', 'f_print', 'f_postcount', 'f_report');
+INSERT INTO phpbb_auth_groups (group_id, forum_id, auth_option_id, auth_setting) SELECT 4, 1, auth_option_id, 1 FROM phpbb_auth_options WHERE auth_option IN ('f_', 'f_list', 'f_read', 'f_post', 'f_reply', 'f_quote', 'f_edit', 'f_delete', 'f_vote', 'f_download', 'f_bbcode', 'f_smilies', 'f_img', 'f_flash', 'f_sigs', 'f_search', 'f_email', 'f_print', 'f_postcount', 'f_subscribe');
+INSERT INTO phpbb_auth_groups (group_id, forum_id, auth_option_id, auth_setting) SELECT 4, 2, auth_option_id, 1 FROM phpbb_auth_options WHERE auth_option IN ('f_', 'f_list', 'f_read', 'f_post', 'f_reply', 'f_quote', 'f_edit', 'f_delete', 'f_vote', 'f_votechg', 'f_download', 'f_bbcode', 'f_smilies', 'f_img', 'f_flash', 'f_sigs', 'f_search', 'f_email', 'f_print', 'f_postcount', 'f_report', 'f_subscribe');
 INSERT INTO phpbb_auth_groups (group_id, forum_id, auth_option_id, auth_setting) SELECT 5, 0, auth_option_id, 1 FROM phpbb_auth_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_chgcensors', 'u_chggrp', 'u_viewonline', 'u_chgname');
-INSERT INTO phpbb_auth_groups (group_id, forum_id, auth_option_id, auth_setting) SELECT 5, 1, auth_option_id, 1 FROM phpbb_auth_options WHERE auth_option IN ('f_', 'f_list', 'f_read', 'f_post', 'f_reply', 'f_quote', 'f_edit', 'f_delete', 'f_vote', 'f_download', 'f_bbcode', 'f_smilies', 'f_img', 'f_flash', 'f_sigs', 'f_search', 'f_email', 'f_print', 'f_postcount');
-INSERT INTO phpbb_auth_groups (group_id, forum_id, auth_option_id, auth_setting) SELECT 5, 2, auth_option_id, 1 FROM phpbb_auth_options WHERE auth_option IN ('f_', 'f_list', 'f_read', 'f_post', 'f_reply', 'f_quote', 'f_edit', 'f_delete', 'f_vote', 'f_votechg', 'f_download', 'f_bbcode', 'f_smilies', 'f_img', 'f_flash', 'f_sigs', 'f_search', 'f_email', 'f_print', 'f_postcount', 'f_report');
+INSERT INTO phpbb_auth_groups (group_id, forum_id, auth_option_id, auth_setting) SELECT 5, 1, auth_option_id, 1 FROM phpbb_auth_options WHERE auth_option IN ('f_', 'f_list', 'f_read', 'f_post', 'f_reply', 'f_quote', 'f_edit', 'f_delete', 'f_vote', 'f_download', 'f_bbcode', 'f_smilies', 'f_img', 'f_flash', 'f_sigs', 'f_search', 'f_email', 'f_print', 'f_postcount', 'f_subscribe');
+INSERT INTO phpbb_auth_groups (group_id, forum_id, auth_option_id, auth_setting) SELECT 5, 2, auth_option_id, 1 FROM phpbb_auth_options WHERE auth_option IN ('f_', 'f_list', 'f_read', 'f_post', 'f_reply', 'f_quote', 'f_edit', 'f_delete', 'f_vote', 'f_votechg', 'f_download', 'f_bbcode', 'f_smilies', 'f_img', 'f_flash', 'f_sigs', 'f_search', 'f_email', 'f_print', 'f_postcount', 'f_report', 'f_subscribe');
 
 # GUESTS, INACTIVE, INACTIVE_COPPA group - basic rights
 INSERT INTO phpbb_auth_groups (group_id, forum_id, auth_option_id, auth_setting) SELECT 1, 1, auth_option_id, 1 FROM phpbb_auth_options WHERE auth_option IN ('f_list', 'f_read', 'f_post', 'f_reply', 'f_quote', 'f_bbcode', 'f_search', 'f_print');
diff --git a/phpBB/language/en/lang_admin.php b/phpBB/language/en/lang_admin.php
index 4d6d5949c0..a008f8c5e6 100644
--- a/phpBB/language/en/lang_admin.php
+++ b/phpBB/language/en/lang_admin.php
@@ -425,7 +425,7 @@ $lang += array(
 	'acl_f_reply'		=> 'Can reply to posts',
 	'acl_f_quote'		=> 'Can quote posts',
 	'acl_f_edit'		=> 'Can edit own posts',
-	'acl_f_lock'		=> 'Can lock own topics',
+	'acl_f_user_lock'	=> 'Can lock own topics',
 	'acl_f_delete'		=> 'Can delete own posts',
 	'acl_f_poll'		=> 'Can create polls',
 	'acl_f_vote'		=> 'Can vote in polls',
@@ -448,6 +448,8 @@ $lang += array(
 	'acl_f_ignoreflood' => 'Can ignore flood limit',
 	'acl_f_postcount'	=> 'Increment post counter',
 	'acl_f_moderate'	=> 'Posts are moderated',
+	'acl_f_bump'		=> 'Can bump topics',
+	'acl_f_subscribe'	=> 'Can subscribe forum',
 
 	'acl_u_hideonline'	=> 'Can hide online status', 
 	'acl_u_viewonline'	=> 'Can view all online',
@@ -463,7 +465,9 @@ $lang += array(
 	'acl_u_chgpasswd'	=> 'Can change password',
 	'acl_u_chgcensors'	=> 'Can disable word censors',
 	'acl_u_search'		=> 'Can search board',
-	'acl_u_savedrafts'	=> 'Can save drafts'
+	'acl_u_savedrafts'	=> 'Can save drafts',
+	'acl_u_download'	=> 'Can download files',
+	'acl_u_attach'		=> 'Can attach files'
 );
 
 // User pruning
diff --git a/phpBB/posting.php b/phpBB/posting.php
index f4d001f4f3..fb0711ee62 100644
--- a/phpBB/posting.php
+++ b/phpBB/posting.php
@@ -688,7 +688,7 @@ if ($submit || $preview || $refresh)
 		{
 			// Lock/Unlock Topic
 			$change_topic_status = $topic_status;
-			$perm_lock_unlock = ($auth->acl_get('m_lock', $forum_id) || ($auth->acl_get('f_lock', $forum_id) && $user->data['user_id'] != ANONYMOUS && $user->data['user_id'] == $topic_poster)) ? TRUE : FALSE;
+			$perm_lock_unlock = ($auth->acl_get('m_lock', $forum_id) || ($auth->acl_get('f_user_lock', $forum_id) && $user->data['user_id'] != ANONYMOUS && $user->data['user_id'] == $topic_poster)) ? TRUE : FALSE;
 
 			if ($topic_status == ITEM_LOCKED && !$topic_lock && $perm_lock_unlock)
 			{
@@ -967,7 +967,7 @@ $s_hidden_fields = ($mode == 'reply' || $mode == 'quote') ? '<input type="hidden
 $s_hidden_fields .= '<input type="hidden" name="lastclick" value="' . $current_time . '" />';
 $s_hidden_fields .= (isset($check_value)) ? '<input type="hidden" name="status_switch" value="' . $check_value . '" />' : '';
 
-$form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || @ini_get('file_uploads') == '0' || !$config['allow_attachments'] || !$auth->acl_get('f_attach', $forum_id)) ? '' : 'enctype="multipart/form-data"';
+$form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || @ini_get('file_uploads') == '0' || !$config['allow_attachments'] || !$auth->acl_gets('f_attach', 'u_attach', $forum_id)) ? '' : 'enctype="multipart/form-data"';
 
 // Start assigning vars for main posting page ...
 $template->assign_vars(array(
@@ -1013,7 +1013,7 @@ $template->assign_vars(array(
 	'S_SIGNATURE_CHECKED' 	=> ($sig_checked) ? ' checked="checked"' : '',
 	'S_NOTIFY_ALLOWED'		=> ($user->data['user_id'] != ANONYMOUS) ? TRUE : FALSE,
 	'S_NOTIFY_CHECKED' 		=> ($notify_checked) ? ' checked="checked"' : '',
-	'S_LOCK_TOPIC_ALLOWED'	=> (($mode == 'edit' || $mode == 'reply' || $mode == 'quote') && ($auth->acl_get('m_lock', $forum_id) || ($auth->acl_get('f_lock', $forum_id) && $user->data['user_id'] != ANONYMOUS && $user->data['user_id'] == $topic_poster))) ? TRUE : FALSE,
+	'S_LOCK_TOPIC_ALLOWED'	=> (($mode == 'edit' || $mode == 'reply' || $mode == 'quote') && ($auth->acl_get('m_lock', $forum_id) || ($auth->acl_get('f_user_lock', $forum_id) && $user->data['user_id'] != ANONYMOUS && $user->data['user_id'] == $topic_poster))) ? TRUE : FALSE,
 	'S_LOCK_TOPIC_CHECKED'	=> ($lock_topic_checked) ? ' checked="checked"' : '',
 	'S_LOCK_POST_ALLOWED'	=> ($mode == 'edit' && $auth->acl_get('m_edit', $forum_id)) ? TRUE : FALSE,
 	'S_LOCK_POST_CHECKED'	=> ($lock_post_checked) ? ' checked="checked"' : '',
@@ -1051,7 +1051,7 @@ else if ($mode == 'edit' && !empty($poll_last_vote) && ($auth->acl_get('f_poll',
 }
 
 // Attachment entry
-if ($auth->acl_get('f_attach', $forum_id) && $config['allow_attachments'] && $form_enctype != '')
+if ($auth->acl_gets('f_attach', 'u_attach', $forum_id) && $config['allow_attachments'] && $form_enctype != '')
 {
 	$template->assign_vars(array(
 		'S_SHOW_ATTACH_BOX'	=> TRUE)
diff --git a/phpBB/search.php b/phpBB/search.php
index c026f0c104..6cbf4d4208 100644
--- a/phpBB/search.php
+++ b/phpBB/search.php
@@ -782,7 +782,7 @@ if ($search_keywords || $search_author || $search_id)
 			'TOPIC_FOLDER_IMG' 	=> $user->img($folder_img, $folder_alt),
 			'TOPIC_ICON_IMG'	=> (!empty($icons[$row['icon_id']])) ? '<img src="' . $config['icons_path'] . '/' . $icons[$row['icon_id']]['img'] . '" width="' . $icons[$row['icon_id']]['width'] . '" height="' . $icons[$row['icon_id']]['height'] . '" alt="" title="" />' : '',
 			'POST_ICON_IMG'		=> (!empty($icons[$row['icon_id']])) ? '<img src="' . $config['icons_path'] . '/' . $icons[$row['icon_id']]['img'] . '" width="' . $icons[$row['icon_id']]['width'] . '" height="' . $icons[$row['icon_id']]['height'] . '" alt="" title="" />' : '',
-			'ATTACH_ICON_IMG'	=> ($auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_attach', '') : '',
+			'ATTACH_ICON_IMG'	=> ($auth->acl_gets('f_download', 'u_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_attach', '') : '',
 			'MINI_POST_IMG' => ($row['post_time'] > $user->data['user_lastvisit'] && $row['post_time'] > $topic_last_read && $user->data['user_id'] != ANONYMOUS) ? $user->img('icon_post_new', $user->lang['NEW_POST']) : $user->img('icon_post', $user->lang['POST']), 
 
 			'U_VIEW_TOPIC'		=> $view_topic_url,
diff --git a/phpBB/styles/subSilver/template/ucp_footer.html b/phpBB/styles/subSilver/template/ucp_footer.html
index a475c217d3..f9d794855d 100644
--- a/phpBB/styles/subSilver/template/ucp_footer.html
+++ b/phpBB/styles/subSilver/template/ucp_footer.html
@@ -1,10 +1,14 @@
 
 <br clear="all" />
 
-<!-- IF S_DISPLAY_MARK_ALL -->
+<!-- IF S_DISPLAY_MARK_ALL or S_DISPLAY_PAGINATION -->
 <table width="100%" cellspacing="2" border="0" align="center">
 	<tr>
-		<td class="gensmall" align="right" valign="middle"><b><a href="javascript:marklist('ucp', true);">{L_MARK_ALL}</a> :: <a  href="javascript:marklist('ucp', false);">{L_UNMARK_ALL}</a></td> 
+<!-- IF S_DISPLAY_PAGINATION -->
+		<td width="20%">&nbsp;</td>
+		<td class="nav" align="left" valign="middle">{PAGE_NUMBER}</td>
+<!-- ENDIF -->
+		<td align="right" valign="middle"><!-- IF S_DISPLAY_MARK_ALL --><b class="gensmall"><a href="javascript:marklist('ucp', true);">{L_MARK_ALL}</a> :: <a  href="javascript:marklist('ucp', false);">{L_UNMARK_ALL}</a></b><br /><!-- ENDIF --><!-- IF S_DISPLAY_PAGINATION --><span class="nav">{PAGINATION}</span><!-- ENDIF --></td> 
 	</tr>
 </table>
 <!-- ENDIF -->
diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php
index c6455c5914..5cf33a33b4 100644
--- a/phpBB/viewforum.php
+++ b/phpBB/viewforum.php
@@ -187,7 +187,7 @@ if ($forum_data['forum_type'] == FORUM_POST)
 
 	// Forum rules, subscription info and word censors
 	$s_watching_forum = $s_watching_forum_img = '';
-	if (($config['email_enable'] || $config['jab_enable']) && $config['allow_forum_notify'])
+	if (($config['email_enable'] || $config['jab_enable']) && $config['allow_forum_notify'] && $auth->acl_get('f_subscribe', $forum_id))
 	{
 		$notify_status = (isset($forum_data['notify_status'])) ? $forum_data['notify_status'] : NULL;
 		watch_topic_forum('forum', $s_watching_forum, $s_watching_forum_img, $user->data['user_id'], $forum_id, $notify_status);
@@ -542,7 +542,7 @@ if ($forum_data['forum_type'] == FORUM_POST)
 				'NEWEST_POST_IMG' 	=> $newest_post_img,
 				'TOPIC_FOLDER_IMG' 	=> $user->img($folder_img, $folder_alt),
 				'TOPIC_ICON_IMG'	=> (!empty($icons[$row['icon_id']])) ? '<img src="' . $config['icons_path'] . '/' . $icons[$row['icon_id']]['img'] . '" width="' . $icons[$row['icon_id']]['width'] . '" height="' . $icons[$row['icon_id']]['height'] . '" alt="" title="" />' : '',
-				'ATTACH_ICON_IMG'	=> ($auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_attach', '') : '',
+				'ATTACH_ICON_IMG'	=> ($auth->acl_gets('f_download', 'u_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_attach', '') : '',
 
 				'S_ROW_COUNT'			=> $i, 
 				'S_TOPIC_TYPE_SWITCH'	=> ($s_type_switch == $s_type_switch_test) ? -1 : $s_type_switch_test, 
diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php
index 0787c32510..5fe0e099b3 100644
--- a/phpBB/viewtopic.php
+++ b/phpBB/viewtopic.php
@@ -410,7 +410,7 @@ gen_forum_rules('topic', $forum_id);
 
 // Quick mod tools
 $topic_mod = '';
-$topic_mod .= ($auth->acl_get('m_lock', $forum_id) || ($auth->acl_get('f_lock', $forum_id) && $user->data['user_id'] != ANONYMOUS && $user->data['user_id'] == $topic_poster)) ? (($topic_status == ITEM_UNLOCKED) ? '<option value="lock">' . $user->lang['LOCK_TOPIC'] . '</option>' : '<option value="unlock">' . $user->lang['UNLOCK_TOPIC'] . '</option>') : '';
+$topic_mod .= ($auth->acl_get('m_lock', $forum_id) || ($auth->acl_get('f_user_lock', $forum_id) && $user->data['user_id'] != ANONYMOUS && $user->data['user_id'] == $topic_poster)) ? (($topic_status == ITEM_UNLOCKED) ? '<option value="lock">' . $user->lang['LOCK_TOPIC'] . '</option>' : '<option value="unlock">' . $user->lang['UNLOCK_TOPIC'] . '</option>') : '';
 $topic_mod .= ($auth->acl_get('m_delete', $forum_id)) ? '<option value="delete_topic">' . $user->lang['DELETE_TOPIC'] . '</option>' : '';
 $topic_mod .= ($auth->acl_get('m_move', $forum_id)) ? '<option value="move">' . $user->lang['MOVE_TOPIC'] . '</option>' : '';
 $topic_mod .= ($auth->acl_get('m_split', $forum_id)) ? '<option value="split">' . $user->lang['SPLIT_TOPIC'] . '</option>' : '';
@@ -961,15 +961,14 @@ unset($id_cache);
 // Pull attachment data
 if (count($attach_list))
 {
-	if ($auth->acl_get('f_download', $forum_id))
+	if ($auth->acl_gets('f_download', 'u_download', $forum_id))
 	{
 		include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
 
-		$sql = 'SELECT a.post_id, d.* 
-			FROM ' . ATTACHMENTS_TABLE . ' a, ' . ATTACHMENTS_DESC_TABLE . ' d
-			WHERE a.post_id IN (' . implode(', ', $attach_list) . ')
-				AND a.attach_id = d.attach_id
-			ORDER BY d.filetime ' . ((!$config['display_order']) ? 'DESC' : 'ASC') . ', a.post_id ASC';
+		$sql = 'SELECT * 
+			FROM ' . ATTACHMENTS_TABLE . '
+			WHERE post_id IN (' . implode(', ', $attach_list) . ')
+			ORDER BY filetime ' . ((!$config['display_order']) ? 'DESC' : 'ASC') . ', post_id ASC';
 		$result = $db->sql_query($sql);
 
 		while ($row = $db->sql_fetchrow($result))
@@ -1256,7 +1255,7 @@ if (!preg_match("#&t=$topic_id#", $user->data['session_page']))
 	// Update the attachment download counts
 	if (sizeof($update_count))
 	{
-		$sql = 'UPDATE ' . ATTACHMENTS_DESC_TABLE . ' 
+		$sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' 
 			SET download_count = download_count + 1 
 			WHERE attach_id IN (' . implode(', ', array_unique($update_count)) . ')';
 		$db->sql_query($sql);