diff -urp --strip-trailing-cr ../category/category_display/category_display.install ./category_display/category_display.install
--- ../category/category_display/category_display.install	2009-08-05 06:52:54.000000000 +0200
+++ ./category_display/category_display.install	2009-10-03 16:07:26.000000000 +0200
@@ -91,6 +91,14 @@ function category_display_schema() {
         'default' => 0,
         'description' => 'Whether or not to show a message, if no content is assigned to a category.',
       ),
+      'legacy_redirect' => array(
+        'type' => 'int',
+        'size' => 'tiny',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'Whether or not to redirect from legacy paths (category/xyz) to proper category pages (node/xyz).',
+      ),
     ),
     'primary key' => array('cid'),
   );
@@ -112,3 +120,21 @@ function category_display_update_6000() 
 
   return $ret;
 }
+
+/**
+ * Add a new column for 'legacy_redirect' setting.
+ */
+function category_display_update_6001() {
+  $ret = array();
+
+  $new_field = array(
+    'type' => 'int',
+    'size' => 'tiny',
+    'unsigned' => TRUE,
+    'not null' => TRUE,
+    'default' => 0,
+  );
+  db_add_field($ret, 'category_display', 'legacy_redirect', $new_field);
+
+  return $ret;
+}
diff -urp --strip-trailing-cr ../category/category_display/category_display.module ./category_display/category_display.module
--- ../category/category_display/category_display.module	2009-08-05 06:52:54.000000000 +0200
+++ ./category_display/category_display.module	2009-10-03 16:08:12.000000000 +0200
@@ -220,6 +220,13 @@ function _category_display_form_elements
       '#value' => '</div>',
     );
 
+    $form['legacy_redirect'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Redirect legacy URLs to proper category pages'),
+      '#default_value' => isset($node->category_display['legacy_redirect']) ? $node->category_display['legacy_redirect'] : 0,
+      '#description' => t("Legacy pages similar to core Taxonomy are provided by default (<em>category/xyz</em>, and <em>taxonomy/term/xyz</em> with Taxonomy wrapper module), but these are not equal to proper category pages, lacking navigation display elements, comments, node theming and more. Tick the above checkbox to redirect to a proper category page instead, if more consistent display is desired. Warning: Unlike the original, the redirected page can't process multiple categories at once."),
+    );
+
     $form['display_wrapper_end'] = array(
       '#value' => '</div>',
     );
@@ -377,13 +384,14 @@ function category_display_del_container(
  */
 function _category_display_defaults() {
   return array(
-    'navlinks'      => 0,
-    'toc_for_cats'  => 0,
-    'toc_depth'     => 0,
-    'toc_nodecount' => 0,
-    'nodelinks'     => 1,
-    'show_listing'  => 1,
-    'emptymsg'      => 1,
+    'navlinks'        => 0,
+    'toc_for_cats'    => 0,
+    'toc_depth'       => 0,
+    'toc_nodecount'   => 0,
+    'nodelinks'       => 1,
+    'show_listing'    => 1,
+    'emptymsg'        => 1,
+    'legacy_redirect' => 0,
   );
 }
 
@@ -883,3 +891,17 @@ function theme_category_display_menu_ite
 
   return $output;
 }
+
+/**
+ * Redirect the user from a legacy category page (category/% or taxonomy/term/%)
+ * to a fully-blown category page (node/%), if applicable.
+ * This is called directly from category_page().
+ */
+function category_display_legacy_page_redirect($cid) {
+  $node = node_load($cid);
+  $cnid = !empty($node->category['cnid']) ? $node->category['cnid'] : $node->nid;
+  $container_info = category_display_get_container($cnid);
+  if ($container_info->legacy_redirect) {
+    drupal_goto('node/'. $cid);
+  }
+}
diff -urp --strip-trailing-cr ../category/category.pages.inc ./category.pages.inc
--- ../category/category.pages.inc	2009-08-05 06:52:53.000000000 +0200
+++ ./category.pages.inc	2009-10-03 15:19:23.000000000 +0200
@@ -30,6 +30,12 @@ function category_page($str_cids = '', $
 
       switch ($op) {
         case 'page':
+          // Allow category_display to redirect the user to a fully-blown
+          // category page, if desired.
+          if (module_exists('category_display')) {
+            category_display_legacy_page_redirect($cids[0]);
+          }
+
           // Build breadcrumb based on first hierarchy of first category:
           $current->cid = $cids[0];
           $breadcrumb = array();
@@ -54,8 +60,10 @@ function category_page($str_cids = '', $
           // Only display the description if we have a single category, to avoid clutter and confusion.
           if (count($cids) == 1) {
             $category = node_load($cids[0]);
-            // HTML will be removed from feed description, so no need to filter here.
-            $channel['description'] = $category->teaser;
+            // Always apply proper input format, even if HTML is going to be removed later,
+            // so that we don't break the output for complex formatters, and avoid exposure
+            // of unfiltered data (such as various pseudo-tags, or even php code).
+            $channel['description'] = check_markup($category->teaser, $category->format, FALSE);
           }
 
           $result = category_select_nodes($cids, $categories['operator'], $depth, FALSE);
@@ -95,12 +103,14 @@ function theme_category_page($cids, $res
   // Only display the description if we have a single category, to avoid clutter and confusion.
   if (count($cids) == 1) {
     $category = node_load($cids[0]);
-    $description = $category->teaser;
 
     // Check that a description is set.
-    if (!empty($description)) {
+    if (!empty($category->teaser)) {
       $output .= '<div class="category-category-description">';
-      $output .= filter_xss_admin($description);
+      // Always apply proper input format, so that we don't break the output
+      // for complex formatters, and avoid exposure of unfiltered data
+      // (such as various pseudo-tags, or even php code).
+      $output .= check_markup($category->teaser, $category->format, FALSE);
       $output .= '</div>';
     }
   }
@@ -120,7 +130,10 @@ function category_feed($cid) {
     if (!empty($cat) && !empty($cat->category)) {
       $channel['link'] = url('node/'. $cid, array('absolute' => TRUE));
       $channel['title'] = variable_get('site_name', 'drupal') .' - '. check_plain($cat->title);
-      $channel['description'] = $cat->teaser;
+      // Always apply proper input format, even if HTML is going to be removed later,
+      // so that we don't break the output for complex formatters, and avoid exposure
+      // of unfiltered data (such as various pseudo-tags, or even php code).
+      $channel['description'] = check_markup($cat->teaser, $cat->format, FALSE);
 
       if ($cat->category['depth'] < 0) {
         $cat->category['depth'] = 'all';
diff -urp --strip-trailing-cr ../category/wrappers/taxonomy/taxonomy.module.php ./wrappers/taxonomy/taxonomy.module.php
--- ../category/wrappers/taxonomy/taxonomy.module.php	2009-08-05 06:52:54.000000000 +0200
+++ ./wrappers/taxonomy/taxonomy.module.php	2009-10-03 15:03:21.000000000 +0200
@@ -87,14 +87,16 @@ function taxonomy_menu() {
 }
 
 /**
- * Menu callback; redirects the user to a taxonomy term's new category page.
+ * Menu callback; shows a taxonomy term's new category page.
  */
 function taxonomy_term_page($str_tids = '', $depth = 0, $op = 'page') {
-  require_once './' . drupal_get_path('module', 'category')
-  ."/category.pages.inc";
+  module_load_include('inc', 'category', 'category.pages');
   return category_page($str_tids, $depth, $op);
 }
 
+/**
+ * Save a vocabulary.
+ */
 function taxonomy_save_vocabulary(&$edit, $nodeapi_call = FALSE) {
   if (!$nodeapi_call) {
     $node = _taxonomy_vocabulary_into_container($edit);
