Index: bp-core/bp-core-functions.php
===================================================================
--- bp-core/bp-core-functions.php	(revision 4505)
+++ bp-core/bp-core-functions.php	(working copy)
@@ -23,21 +23,21 @@
  */
 function bp_core_get_page_meta() {
 	$page_ids = get_site_option( 'bp-pages' );
-	
+
 	$is_enable_multiblog = is_multisite() && defined( 'BP_ENABLE_MULTIBLOG' ) && BP_ENABLE_MULTIBLOG ? true : false;
 
 	$page_blog_id = $is_enable_multiblog ? get_current_blog_id() : BP_ROOT_BLOG;
 
 	// Upgrading from an earlier version of BP pre-1.3
-	if ( empty( $page_ids ) || isset( $page_ids['members'] ) ) {		
-		if ( empty( $page_ids ) ) {		
+	if ( empty( $page_ids ) || isset( $page_ids['members'] ) ) {
+		if ( empty( $page_ids ) ) {
 			// We're probably coming from an old multisite install
 			$old_page_ids = get_blog_option( $page_blog_id, 'bp-pages' );
 		} else {
 			// We're probably coming from an old single-WP install
 			$old_page_ids = $page_ids;
 		}
-		
+
 		/**
 		 * If $page_ids is found in a blog_option, and it's formatted in the new way (keyed
 		 * by blog_id), it means that this is an MS upgrade. Return false and let the
@@ -45,7 +45,7 @@
 		 */
 		if ( !isset( $old_page_ids['members'] ) )
 			return false;
-			
+
 		// Finally, move the page ids over to site options
 		$new_page_ids = array(
 			$page_blog_id => $old_page_ids
@@ -53,9 +53,9 @@
 
 		update_site_option( 'bp-pages', $new_page_ids );
 	}
-	
+
 	$blog_page_ids = !empty( $page_ids[$page_blog_id] ) ? $page_ids[$page_blog_id] : false;
-	
+
 	return apply_filters( 'bp_core_get_page_meta', $blog_page_ids );
 }
 
@@ -65,7 +65,7 @@
  * bp-pages data is stored in site_options (falls back to options on non-MS), in an array keyed by
  * blog_id. This allows you to change your BP_ROOT_BLOG and go through the setup process again.
  *
- * @package BuddyPress Core 
+ * @package BuddyPress Core
  * @since 1.3
  *
  * @param array $blog_page_ids The IDs of the WP pages corresponding to BP component directories
@@ -76,7 +76,7 @@
 
 	// Generally, we key by the BP_ROOT_BLOG. Exception: when BP_ENABLE_MULTIBLOG is turned on
 	$key = is_multisite() && defined( 'BP_ENABLE_MULTIBLOG' ) && BP_ENABLE_MULTIBLOG ? get_current_blog_id() : BP_ROOT_BLOG;
-	
+
 	$page_ids[$key] = $blog_page_ids;
 
 	update_site_option( 'bp-pages', $page_ids );
@@ -161,16 +161,16 @@
 
 function bp_core_do_network_admin() {
 	$do_network_admin = false;
-	
+
 	if ( is_multisite() && ( !defined( 'BP_ENABLE_MULTIBLOG' ) || !BP_ENABLE_MULTIBLOG ) )
 		$do_network_admin = true;
-	
+
 	return apply_filters( 'bp_core_do_network_admin', $do_network_admin );
 }
 
 function bp_core_admin_hook() {
 	$hook = bp_core_do_network_admin() ? 'network_admin_menu' : 'admin_menu';
-	
+
 	return apply_filters( 'bp_core_admin_hook', $hook );
 }
 
@@ -183,7 +183,7 @@
 function bp_core_admin_menu_init() {
 	if ( !is_super_admin() )
 		return false;
-	
+
 	add_action( bp_core_admin_hook(), 'bp_core_add_admin_menu', 9 );
 
 	require ( BP_PLUGIN_DIR . '/bp-core/admin/bp-core-admin.php' );
@@ -235,16 +235,16 @@
  */
 function bp_core_print_admin_notices() {
 	global $bp;
-	
+
 	// Only the super admin should see messages
 	if ( !is_super_admin() )
 		return;
-	
+
 	// On multisite installs, don't show on the Site Admin of a non-root blog, unless
 	// do_network_admin is overridden
 	if ( is_multisite() && bp_core_do_network_admin() && !bp_is_root_blog() )
 		return;
-		
+
 	// Show the messages
 	if ( !empty( $bp->admin->notices ) ) {
 	?>
@@ -252,7 +252,7 @@
 			<?php foreach( $bp->admin->notices as $notice ) : ?>
 				<p><?php echo $notice ?></p>
 			<?php endforeach ?>
-		</div>		
+		</div>
 	<?php
 	}
 }
@@ -274,11 +274,11 @@
  */
 function bp_core_add_admin_notice( $notice ) {
 	global $bp;
-	
+
 	if ( empty( $bp->admin->notices ) ) {
 		$bp->admin->notices = array();
 	}
-	
+
 	$bp->admin->notices[] = $notice;
 }
 
@@ -300,12 +300,12 @@
 	// Only the super admin gets warnings
 	if ( !is_super_admin() )
 		return;
-		
+
 	// On multisite installs, don't load on a non-root blog, unless do_network_admin is
 	// overridden
 	if ( is_multisite() && bp_core_do_network_admin() && !bp_is_root_blog() )
 		return;
-		
+
 	// Don't show these messages during setup or upgrade
 	if ( isset( $bp->maintenence_mode ) )
 		return;
@@ -316,7 +316,7 @@
 	 */
 	if ( bp_is_active( 'blogs' ) ) {
 		$count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$bp->blogs->table_name}" ) );
-		
+
 		if ( !$count )
 			bp_blogs_record_existing_blogs();
 	}
@@ -327,36 +327,36 @@
 	if ( isset( $_POST['permalink_structure'] ) )
 		return false;
 
-	if ( empty( $wp_rewrite->permalink_structure ) ) { 
+	if ( empty( $wp_rewrite->permalink_structure ) ) {
 		bp_core_add_admin_notice( sprintf( __( '<strong>BuddyPress is almost ready</strong>. You must <a href="%s">update your permalink structure</a> to something other than the default for it to work.', 'buddypress' ), admin_url( 'options-permalink.php' ) ) );
 	}
-	
+
 	/**
 	 * Are you using a BP-compatible theme?
 	 */
-	
+
 	// Get current theme info
 	$ct = current_theme_info();
 
 	// The best way to remove this notice is to add a "buddypress" tag to
 	// your active theme's CSS header.
-	if ( !defined( 'BP_SILENCE_THEME_NOTICE' ) && !in_array( 'buddypress', (array)$ct->tags ) ) { 
+	if ( !defined( 'BP_SILENCE_THEME_NOTICE' ) && !in_array( 'buddypress', (array)$ct->tags ) ) {
 		bp_core_add_admin_notice( sprintf( __( "You'll need to <a href='%s'>activate a <strong>BuddyPress-compatible theme</strong></a> to take advantage of all of BuddyPress's features. We've bundled a default theme, but you can always <a href='%s'>install some other compatible themes</a> or <a href='%s'>update your existing WordPress theme</a>.", 'buddypress' ), admin_url( 'themes.php' ), network_admin_url( 'theme-install.php?type=tag&s=buddypress&tab=search' ), network_admin_url( 'plugin-install.php?type=term&tab=search&s=%22bp-template-pack%22' ) ) );
 	}
-		
+
 	/**
 	 * Check for orphaned directory pages (BP component is disabled, WP page exists)
 	 */
-	 
+
 	$orphaned_pages = array();
 	foreach( $bp->pages as $component_id => $page ) {
-		
+
 		// Some members of $bp->pages will not have corresponding $bp->{component}, so we
 		// skip them. Plugins can add themselves here if necessary.
 		$exceptions = apply_filters( 'bp_pages_without_components', array( 'register', 'activate' ) );
 		if ( in_array( $component_id, $exceptions ) )
 			continue;
-		
+
 		if ( !isset( $bp->{$component_id} ) ) {
 			// We'll need to get some more information about the page for the notice
 			$page_data = get_post( $page->id );
@@ -366,32 +366,32 @@
 				'title'	=> $page_data->post_title
 			);
 		}
-		
+
 	}
-	
+
 	// If orphaned pages are found, post a notice about them.
 	if ( !empty( $orphaned_pages ) ) {
-		
+
 		// Create the string of links to the Edit Page screen for the pages
 		$edit_pages_links = array();
 		foreach( $orphaned_pages as $op ) {
 			$edit_pages_links[] = sprintf( '<a href="%1$s">%2$s</a>', admin_url( 'post.php?action=edit&post=' . $op['id'] ), $op['title'] );
 		}
-		
+
 		$admin_url = bp_core_do_network_admin() ? network_admin_url( 'admin.php?page=bp-general-settings' ) : admin_url( 'admin.php?page=bp-general-settings' );
-		
+
 		$notice = sprintf( __( 'Some of your WordPress pages are linked to BuddyPress components that have been disabled. These pages may continue to show up in your site navigation. Consider <a href="%1$s">reactivating the components</a>, or unpublishing the pages: <strong>%2$s</strong>', 'buddypress' ), $admin_url, implode( ', ', $edit_pages_links ) );
-		
+
 		bp_core_add_admin_notice( $notice );
 	}
-	
+
 	/**
 	 * Check for orphaned BP components (BP component is enabled, no WP page exists)
 	 */
-	
+
 	$orphaned_components = array();
 	$wp_page_components  = array();
-	
+
 	// Only some BP components require a WP page to function - those with a non-empty root_slug
 	foreach( $bp->active_components as $component_id => $is_active ) {
 		if ( !empty( $bp->{$component_id}->root_slug ) ) {
@@ -401,7 +401,7 @@
 			);
 		}
 	}
-	
+
 	// Activate and Register are special cases. They are not components but they need WP pages.
 	// If user registration is disabled, we can skip this step.
 	if ( isset( $bp->site_options['registration'] ) && ( 'user' == $bp->site_options['registration'] || ( 'all' == $bp->site_options['registration'] ) ) ) {
@@ -409,24 +409,24 @@
 			'id'	=> 'activate',
 			'name'	=> __( 'Activate', 'buddypress' )
 		);
-		
+
 		$wp_page_components[] = array(
 			'id'	=> 'register',
 			'name'	=> __( 'Register', 'buddypress' )
 		);
-	}	
-	
-	foreach( $wp_page_components as $component ) {		
+	}
+
+	foreach( $wp_page_components as $component ) {
 		if ( !isset( $bp->pages->{$component['id']} ) ) {
 			$orphaned_components[] = $component['name'];
 		}
 	}
-	
+
 	if ( !empty( $orphaned_components ) ) {
 		$admin_url = bp_core_do_network_admin() ? network_admin_url( 'admin.php?page=bp-general-settings' ) : admin_url( 'admin.php?page=bp-general-settings' );
-		
+
 		$notice = sprintf( __( 'Some BuddyPress components must be associated with WordPress pages for your site to work properly. The following components are missing their required WP pages: <strong>%1$s</strong>. Visit the <a href="%2$s">BuddyPress Components</a> panel, where you can either deactivate unused components or complete the page setup.', 'buddypress' ), implode( ', ', $orphaned_components ), $admin_url );
-		
+
 		bp_core_add_admin_notice( $notice );
 	}
 }
@@ -965,7 +965,7 @@
  */
 function bp_core_add_root_component( $slug ) {
 	global $bp;
-	
+
 	if ( empty( $bp->pages ) )
 		$bp->pages = bp_core_get_page_names();
 
@@ -1007,7 +1007,7 @@
  */
 function bp_is_root_blog( $blog_id = false ) {
 	$is_root_blog = true;
-	
+
 	if ( !$blog_id )
 		$blog_id = get_current_blog_id();
 
@@ -1028,7 +1028,7 @@
  * this function exclusively in the context of the _user_meta() functions. For example,
  *    $last_active = get_user_meta( $user_id, bp_get_user_meta_key( 'last_activity' ), true );
  * Do not hardcode these keys.
- * 
+ *
  * If your plugin introduces custom user metadata that might change between multiple BP instances
  * on a single WP installation, you are strongly recommended to use this function when storing and
  * retrieving metadata.
@@ -1094,4 +1094,22 @@
 	$bp->is_item_mod = apply_filters( 'bp_update_is_item_mod', $is_item_mod, $component );
 }
 
-?>
+/**
+ * Trigger a 404
+ *
+ * @global object $bp Global BuddyPress settings object
+ * @global WP_Query $wp_query WordPress query object
+ * @param string $redirect If 'remove_canonical_direct', remove WordPress' "helpful" redirect_canonical action.
+ * @since 1.3
+ */
+function bp_do_404( $redirect='remove_canonical_direct' ) {
+	global $bp, $wp_query;
+
+	$wp_query->set_404(); 
+	status_header( 404 ); 
+	nocache_headers();
+
+	if ( 'remove_canonical_direct' == $redirect )
+		remove_action( 'template_redirect', 'redirect_canonical' );
+}
+?>
\ No newline at end of file
Index: bp-core/bp-core-template.php
===================================================================
--- bp-core/bp-core-template.php	(revision 4505)
+++ bp-core/bp-core-template.php	(working copy)
@@ -246,8 +246,9 @@
 
 	// A single group
 	} elseif ( bp_is_active( 'groups' ) && !empty( $bp->groups->current_group ) && !empty( $bp->bp_options_nav[$bp->groups->current_group->slug] ) ) {
+		$subnav = isset( $bp->bp_options_nav[$bp->groups->current_group->slug][$bp->current_action]['name'] ) ? $bp->bp_options_nav[$bp->groups->current_group->slug][$bp->current_action]['name'] : '';
 		// translators: "group name | group nav section name"
-		$title = sprintf( __( '%1$s &#124; %2$s', 'buddypress' ), $bp->bp_options_title, $bp->bp_options_nav[$bp->groups->current_group->slug][$bp->current_action]['name'] );
+		$title = sprintf( __( '%1$s &#124; %2$s', 'buddypress' ), $bp->bp_options_title, $subnav );
 
 	// A single item from a component other than groups
 	} elseif ( bp_is_single_item() ) {
Index: bp-core/bp-core-catchuri.php
===================================================================
--- bp-core/bp-core-catchuri.php	(revision 4505)
+++ bp-core/bp-core-catchuri.php	(working copy)
@@ -242,6 +242,14 @@
 				else
 					$bp->displayed_user->id = (int) bp_core_get_userid_from_nicename( urldecode( $bp_uri[$uri_offset + 1] ) );
 
+				if ( empty( $bp->displayed_user->id ) ) {
+					// Prevent components from loading their templates
+					$bp->current_component = ''; 
+
+					bp_do_404();
+					return;
+				}
+
 				// Bump the offset
 				if ( isset( $bp_uri[$uri_offset + 2] ) ) {
 					$bp_uri                = array_merge( array(), array_slice( $bp_uri, $uri_offset + 2 ) );
@@ -351,32 +359,26 @@
  * @since 1.3
  */
 function bp_core_catch_no_access() {
-	global $bp, $wp_query, $bp_unfiltered_uri, $bp_no_status_set;
+	global $bp, $bp_no_status_set;
 
 	// If bp_core_redirect() and $bp_no_status_set is true,
 	// we are redirecting to an accessible page, so skip this check.
 	if ( $bp_no_status_set )
 		return false;
 
-	// If the displayed user was marked as a spammer and the logged-in user is not a super admin, redirect
+	// If the displayed user was marked as a spammer and the logged-in user is not a super admin, 404.
 	if ( isset( $bp->displayed_user->id ) && bp_core_is_user_spammer( $bp->displayed_user->id ) ) {
-		if ( !is_super_admin() )
-			bp_core_redirect( $bp->root_domain );
-		else
+		if ( !$bp->loggedin_user->is_super_admin ) {
+			bp_do_404();
+			return;
+
+		} else {
 			bp_core_add_message( __( 'This user has been marked as a spammer. Only site admins can view this profile.', 'buddypress' ), 'error' );
+		}
 	}
 
-	// If BP_ENABLE_ROOT_PROFILES is not defined and the displayed user does not exist, redirect
-	if ( !$bp->displayed_user->id && isset( $bp_unfiltered_uri[0] ) && $bp_unfiltered_uri[0] == $bp->members->slug && isset( $bp_unfiltered_uri[1] ) )
-		bp_core_redirect( $bp->root_domain );
-
-	// Access control!
 	if ( !isset( $wp_query->queried_object ) && !bp_is_blog_page() ) {
-		if ( is_user_logged_in() ) {
-			bp_core_no_access( array( 'redirect' => false, 'message' => __( 'You do not have access to that page', 'buddypress' ) ) );
-		} else {
-			bp_core_no_access();
-		}
+		bp_do_404();
 	}
 }
 add_action( 'wp', 'bp_core_catch_no_access' );
@@ -402,15 +404,6 @@
 	$r = wp_parse_args( $args, $defaults );
 	extract( $r, EXTR_SKIP );
 
-	// Group filtering
-	// When a user doesn't have access to a group's activity / secondary page, redirect to group's homepage
-	if ( !$redirect ) {
-		if ( bp_is_active( 'groups' ) && bp_is_current_component( 'groups' ) ) {
-			$root = bp_get_group_permalink( $bp->groups->current_group );
-			$message = false;
-		}
-	}
-
 	// Apply filters to these variables
 	$mode		= apply_filters( 'bp_no_access_mode', $mode, $root, $redirect, $message );
 	$redirect	= apply_filters( 'bp_no_access_redirect', $redirect, $root, $message, $mode );
Index: bp-xprofile/bp-xprofile-screens.php
===================================================================
--- bp-xprofile/bp-xprofile-screens.php	(revision 4505)
+++ bp-xprofile/bp-xprofile-screens.php	(working copy)
@@ -13,6 +13,13 @@
  * @uses bp_core_load_template() Looks for and loads a template file within the current member theme (folder/filename)
  */
 function xprofile_screen_display_profile() {
+	global $bp;
+	
+	if ( empty( $bp->displayed_user->id ) ) {
+		bp_do_404();
+		return; 
+	} 
+	
 	$new = isset( $_GET['new'] ) ? $_GET['new'] : '';
 
 	do_action( 'xprofile_screen_display_profile', $new );
@@ -38,8 +45,10 @@
 		bp_core_redirect( $bp->displayed_user->domain . $bp->profile->slug . '/edit/group/1' );
 
 	// Check the field group exists
-	if ( !xprofile_get_field_group( $bp->action_variables[1] ) )
-		bp_core_redirect( bp_get_root_domain() );
+	if ( !xprofile_get_field_group( $bp->action_variables[1] ) ) {
+		bp_do_404();
+		return;
+	}
 
 	// Check to see if any new information has been submitted
 	if ( isset( $_POST['field_ids'] ) ) {
Index: bp-activity/bp-activity-actions.php
===================================================================
--- bp-activity/bp-activity-actions.php	(revision 4505)
+++ bp-activity/bp-activity-actions.php	(working copy)
@@ -26,9 +26,11 @@
 	// Get the activity details
 	$activity = bp_activity_get_specific( array( 'activity_ids' => $bp->action_variables[0] ) );
 
-	// Redirect to root if activity does not exist
-	if ( !$activity = $activity['activities'][0] )
-		bp_core_redirect( bp_get_root_domain() );
+	// 404 if activity does not exist
+	if ( !$activity = $activity['activities'][0] ) {
+		bp_do_404();
+		return;
+	}
 
 	// Do not redirect at default
 	$redirect = false;
Index: bp-activity/bp-activity-screens.php
===================================================================
--- bp-activity/bp-activity-screens.php	(revision 4505)
+++ bp-activity/bp-activity-screens.php	(working copy)
@@ -95,8 +95,11 @@
 	// Get the activity details
 	$activity = bp_activity_get_specific( array( 'activity_ids' => bp_current_action() ) );
 
-	if ( !$activity = $activity['activities'][0] )
-		bp_core_redirect( bp_get_root_domain() );
+	// 404 if activity does not exist
+	if ( !$activity = $activity['activities'][0] ) {
+		bp_do_404();
+		return;
+	}
 
 	// Default access is true
 	$has_access = true;
@@ -105,8 +108,10 @@
 	if ( isset( $bp->groups->id ) && $activity->component == $bp->groups->id ) {
 
 		// Activity is from a group, but groups is currently disabled
-		if ( !bp_is_active( 'groups') )
-			bp_core_redirect( bp_get_root_domain() );
+		if ( !bp_is_active( 'groups') ) {
+			bp_do_404();
+			return;
+		}
 
 		// Check to see if the group is not public, if so, check the
 		// user has access to see this activity
Index: bp-groups/bp-groups-screens.php
===================================================================
--- bp-groups/bp-groups-screens.php	(revision 4505)
+++ bp-groups/bp-groups-screens.php	(working copy)
@@ -103,13 +103,23 @@
 }
 
 function groups_screen_group_forum() {
-	global $bp, $wp_query;
+	global $bp;
 
 	if ( !bp_is_active( 'forums' ) || !bp_forums_is_installed_correctly() )
 		return false;
 
-	if ( bp_is_single_item() && $bp->groups->current_group->user_has_access ) {
+	if ( !empty( $bp->action_variables[0] ) && 'topic' != $bp->action_variables[0] ) {
+		bp_do_404();
+		return;
+	}
 
+	if ( !$bp->groups->current_group->user_has_access ) {
+		bp_core_no_access();
+		return;
+	}
+
+	if ( bp_is_single_item() ) {
+
 		// Fetch the details we need
 		$topic_slug     = !empty( $bp->action_variables[1] ) ? $bp->action_variables[1] : false;
 		$topic_id       = bp_forums_get_topic_id_from_slug( $topic_slug );
@@ -310,9 +320,7 @@
 
 		// Forum topic does not exist
 		} elseif ( !empty( $topic_slug ) && empty( $topic_id ) ) {
-			$wp_query->set_404();
-			status_header( 404 );
-			nocache_headers();
+			bp_do_404();
 			return;
 
 		} else {
@@ -389,15 +397,16 @@
 
 			// Send the invites.
 			groups_send_invites( $bp->loggedin_user->id, $bp->groups->current_group->id );
-
 			bp_core_add_message( __('Group invites sent.', 'buddypress') );
-
 			do_action( 'groups_screen_group_invite', $bp->groups->current_group->id );
+			bp_core_redirect( bp_get_group_permalink( $bp->groups->current_group ) );
 
-			bp_core_redirect( bp_get_group_permalink( $bp->groups->current_group ) );
-		} else {
+		} elseif ( empty( $bp->action_variables[0] ) ) {
 			// Show send invite page
 			bp_core_load_template( apply_filters( 'groups_template_group_invite', 'groups/single/home' ) );
+
+		} else {
+			bp_do_404();
 		}
 	}
 }
Index: bp-groups/bp-groups-loader.php
===================================================================
--- bp-groups/bp-groups-loader.php	(revision 4505)
+++ bp-groups/bp-groups-loader.php	(working copy)
@@ -155,6 +155,18 @@
 			$this->root_slug,
 		) );
 
+		// If the user was attempting to access a group, but no group by that name was
+		// found, 404
+		if ( empty( $this->current_group ) && !empty( $bp->current_action ) && !in_array( $bp->current_action, $this->forbidden_names ) ) {
+			bp_do_404();
+			return;
+		}
+		
+		// Group access control
+		if ( !empty( $this->current_group ) && !$this->current_group->user_has_access ) {
+			bp_core_no_access();
+		}
+
 		// Preconfigured group creation steps
 		$this->group_creation_steps = apply_filters( 'groups_create_group_steps', array(
 			'group-details'  => array(
Index: bp-groups/bp-groups-filters.php
===================================================================
--- bp-groups/bp-groups-filters.php	(revision 4505)
+++ bp-groups/bp-groups-filters.php	(working copy)
@@ -105,8 +105,8 @@
 	elseif ( is_super_admin() )
 		unset( $parts['private'] );
 
-	// Are we a member of this group
-	elseif ( bp_is_single_item() && bp_group_is_member( $bp->groups->current_group->id ) )
+	// No need to filter on a single item
+	elseif ( bp_is_single_item() )
 		unset( $parts['private'] );
 
 	// Check the SQL filter that was passed
