Index: lib/MT/App/Viewer.pm
===================================================================
--- lib/MT/App/Viewer.pm	(revision 1117)
+++ lib/MT/App/Viewer.pm	(working copy)
@@ -26,10 +26,6 @@
 
 my %view_handlers = (
     'index' => \&_view_index,
-    'Individual' => \&_view_entry,
-    'Page' => \&_view_entry,
-    'Category' => \&_view_category,
-    'Author' => \&_view_author,
     '*' => \&_view_archive,
 );
 
@@ -40,7 +36,8 @@
     $R->stash('live_view', 1);
 
     ## Process the path info.
-    my $uri = $app->param('uri') || $app->path_info;
+    my $uri = $app->param('uri') || $app->path_info || $ENV{REQUEST_URI};
+    $uri =~ s!/$!!;
     my $blog_id = $app->param('blog_id');
 
     ## Check ExcludeBlogs and IncludeBlogs to see if this blog is
@@ -68,11 +65,12 @@
     });
     if (@fi) {
         if (my $tmpl = MT::Template->load($fi[0]->template_id)) {
-            my $handler = $view_handlers{$tmpl->type};
+            my $handler = $view_handlers{$fi[0]->archive_type};
             $handler ||= $view_handlers{'*'};
             return $handler->($app, $fi[0], $tmpl);
         }
     }
+    $app->response_code('404'); # 404 Not Found
     if (my $tmpl = MT::Template->load({ blog_id => $blog_id,
         type => 'dynamic_error' })) {
         my $ctx = $tmpl->context;
@@ -96,29 +94,15 @@
 sub _view_index {
     my $app = shift;
     my($fi, $tmpl) = @_;
-    my $q = $app->param;
 
     my $ctx = $tmpl->context;
-    if ($tmpl->text =~ m/<MT:?Entries/i) {
-        my $limit = $q->param('limit');
-        my $offset = $q->param('offset');
-        if ($limit || $offset) {
-            $limit ||= 20;
-            my %arg = (
-                'sort' => 'authored_on',
-                direction => 'descend',
-                limit => $limit,
-                ($offset ? (offset => $offset) : ()),
-            );
-            my @entries = MT::Entry->load({ blog_id => $app->{__blog_id},
-                status => MT::Entry::RELEASE() }, \%arg);
-            $ctx->stash('entries', delay(sub{\@entries}));
-        }
-    }
     my $out = $tmpl->build($ctx)
         or return $app->error($app->translate("Template publishing failed: [_1]", $tmpl->errstr));
-    (my $ext = $tmpl->outfile) =~ s/.*\.//;
-    my $mime = $MimeTypes{$ext} || 'text/html';
+    my $mime = $ctx->stash('content_type');
+    unless ($mime) {
+        (my $ext = $tmpl->outfile) =~ s/.*\.//;
+        $mime = $MimeTypes{$ext} || 'text/html';
+    }
     $app->send_http_header($mime);
     $app->print($out);
     $app->{no_print_body} = 1;
@@ -226,6 +210,94 @@
     $out;
 }
 
+sub _view_archive {
+    my $app = shift;
+    my ($fi, $tmpl) = @_;
+    my $ctx = $tmpl->context;
+
+    # archive type
+    my $at = $fi->archive_type
+        or return $app->error($app->translate("Parameter '[_1]' is required", 'ArchiveType'));
+    $ctx->{current_archive_type} = $at;
+
+    # archiver
+    my $archiver = MT->registry('archive_types')->{$at};
+
+    # blog
+    if ($fi->blog_id) {
+        my $blog = MT::Blog->load($fi->blog_id);
+        $ctx->{__stash}{blog} = $blog;
+    }
+
+    # entry_based
+    if ($fi->entry_id) {
+        my $entry = MT::Entry->load($fi->entry_id)
+            or return $app->error($app->translate(
+                "Parameter '[_1]' is required", 'Entry'
+            ));
+        return $app->error($app->translate(
+            "Entry [_1] is not published", $fi->entry_id
+        ))
+            unless $entry->status == MT::Entry::RELEASE();
+        $ctx->var('entry_archive', 1);
+        $ctx->{__stash}{entry} = $entry;
+    }
+
+    # date_based
+    if ($fi->startdate) {
+        if (my $range = $archiver->date_range) {
+            my ($start, $end) = $range->($fi->startdate);
+            my $entry = MT::Entry->load({
+                authored_on => [$start, $end],
+                status => MT::Entry::RELEASE(),
+            }, {
+                range_incl => { authored_on => 1 },
+                limit => 1,
+            })
+                or return $app->error($app->translate("Parameter '[_1]' is required", 'Entry'));
+            $ctx->var('datebased_archive', 1);
+            $ctx->{current_timestamp}     = $start if $start;
+            $ctx->{current_timestamp_end} = $end   if $end;
+        }
+    }
+
+    # category_based
+    if ($fi->category_id) {
+        require MT::Category;
+        my $cat = MT::Category->load($fi->category_id);
+        $ctx->var('category_archive', 1);
+        $ctx->{__stash}{archive_category} = $cat;
+    }
+
+    # author_based
+    if ($fi->author_id) {
+        require MT::Author;
+        my $author = MT::Author->load($fi->author_id);
+        $ctx->var('author_archive', 1);
+        $ctx->{__stash}{author} = $author;
+    }
+
+    if (my $template_params = $archiver->template_params) {
+        $tmpl->param($template_params);
+    }
+    if (my $archive_group_entries = $archiver->archive_group_entries) {
+        $ctx->stash('entries', delay(sub { $archive_group_entries->($ctx) }));
+    }
+
+    my $out = $tmpl->build($ctx)
+        or return $app->error($app->translate("Archive publishing failed: [_1]", $tmpl->errstr));
+
+    my $content_type = $ctx->stash('content_type');
+    unless ($content_type) {
+        (my $ext = $tmpl->outfile) =~ s/.*\.//;
+        $content_type = $MimeTypes{$ext} || 'text/html';
+    }
+    $app->send_http_header($content_type);
+    $app->print($out);
+    $app->{no_print_body} = 1;
+    1;
+}
+
 1;
 __END__
 
