[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: movabletype-opensource upcoming uploads



On Sat, Jul 12, 2008 at 12:02:47AM +0200, Luk Claes wrote:
> Dominic Hargreaves wrote:
> 
> > I just wanted to check with the release team about the state of
> > movabletype-opensource.
> 
> > However, ideally I would like to ship the final 4.2 release with lenny.
> > Upstream are planning one more release candidate (probably) and then a
> > final release towards the end of July. This is after the advertised
> > freeze; however I anticipate the delta between rc4 and final to be quite
> > small, and to only contain bugfixes.
> > 
> > Would a freeze exception for rc4 and/or the final release package be
> > approved, if required?
> 
> It depends on what the changes are, how big they are and how much risk
> of breakage there is when the package is frozen... If it are only
> bugfixes chances are big we would consider it.

4.2 has now been released, a bit later than hoped.

Comparing 4.2~rc4-1 with 4.2-1 is a bit tedious because of a perltidy
run by upstream and a large number of translation updates.

If we look at the upstream repository
http://code.sixapart.com/svn/movabletype/branches/release-42/
and generate two diffs representing changes between rc4 and final:

r2834:2876
r2877:2922

(ie ignoring the perltidy) and manually excluding doc/translations
changes and changes in the test suite then we get the slightly more
palatable diff attached:

 37 files changed, 245 insertions(+), 165 deletions(-)

Also notable is that Movable Type have mentioned several security issues
being fixed in rc5, though they aren't too specific:

http://www.movabletype.org/2008/08/movable_type_42_rc5_and_security_updates.html

Given all this, the low popcon count and lack of reverse dependencies,
and the fact that Six Apart do a *lot* of their own QA, I think that the
final package is a suitable candidate for lenny.

Thanks,
Dominic.

-- 
Dominic Hargreaves | http://www.larted.org.uk/~dom/
PGP key 5178E2A5 from the.earth.li (keyserver,web,email)
Index: php/lib/function.mtvar.php
===================================================================
--- php/lib/function.mtvar.php	(revision 2834)
+++ php/lib/function.mtvar.php	(revision 2876)
@@ -57,7 +57,7 @@
             $key = $args['key'];
     }
 
-    if (preg_match('/^$/', $name)) {
+    if (preg_match('/^\$/', $name)) {
         $name = $vars[$name];
         if (!isset($name))
             return $ctx->error($ctx->mt->translate(
@@ -182,4 +182,3 @@
     }
     return $return_val;
 }
-?>
Index: php/lib/function.mtsetvar.php
===================================================================
--- php/lib/function.mtsetvar.php	(revision 2834)
+++ php/lib/function.mtsetvar.php	(revision 2876)
@@ -50,7 +50,7 @@
             $key = $args['key'];
     }
 
-    if (preg_match('/^$/', $name)) {
+    if (preg_match('/^\$/', $name)) {
         $name = $vars[$name];
         if (!isset($name))
             return $ctx->error($ctx->mt->translate(
@@ -147,4 +147,3 @@
     }
     return '';
 }
-?>
Index: php/lib/block.mtsetvarblock.php
===================================================================
--- php/lib/block.mtsetvarblock.php	(revision 2834)
+++ php/lib/block.mtsetvarblock.php	(revision 2876)
@@ -40,7 +40,7 @@
                 $key = $args['key'];
         }
 
-        if (preg_match('/^$/', $name)) {
+        if (preg_match('/^\$/', $name)) {
             $name = $vars[$name];
             if (!isset($name))
                 return $ctx->error($ctx->mt->translate(
@@ -139,4 +139,3 @@
     }
     return '';
 }
-?>
Index: default_templates/javascript.mtml
===================================================================
--- default_templates/javascript.mtml	(revision 2834)
+++ default_templates/javascript.mtml	(revision 2876)
@@ -234,7 +234,6 @@
     if (u.name) str += "name:'" + mtEscapeJS(u.name) + "';";
     if (u.url) str += "url:'" + mtEscapeJS(u.url) + "';";
     if (u.email) str += "email:'" + mtEscapeJS(u.email) + "';";
-    if (u.auth_type) str += "auth_type:'" + u.auth_type + "';";
     if (u.is_authenticated) str += "is_authenticated:'1';";
     if (u.profile) str += "profile:'" + mtEscapeJS(u.profile) + "';";
     if (u.userpic) str += "userpic:'" + mtEscapeJS(u.userpic) + "';";
@@ -259,7 +258,7 @@
 
     var u = {};
     var m;
-    while (m = s.match(/^((name|url|email|auth_type|is_authenticated|profile|userpic|sid|is_trusted|is_author|is_banned|can_post|can_comment):'([^']+?)';?)/)) {
+    while (m = s.match(/^((name|url|email|is_authenticated|profile|userpic|sid|is_trusted|is_author|is_banned|can_post|can_comment):'([^']+?)';?)/)) {
         s = s.substring(m[1].length);
         if (m[2].match(/^(is|can)_/)) // boolean fields
             u[m[2]] = m[3] == '1' ? true : false;
Index: lib/MT/Upgrade.pm
===================================================================
--- lib/MT/Upgrade.pm	(revision 2834)
+++ lib/MT/Upgrade.pm	(revision 2876)
@@ -739,6 +739,34 @@
                             };
                         }
                     }
+                    else {
+                        # FIXME: copied from MT::CMS::Dashboard
+                        my %default_widgets = (
+                            'new_version'   => {
+                                order => -1,
+                                set => 'main',
+                                template => 'widget/new_version.tmpl',
+                                singular => 1
+                            },
+                            'blog_stats' => {
+                                param => { tab => 'entry' },
+                                order => 1,
+                                set => 'main'
+                            },
+                            'this_is_you-1' => { order => 1, set => 'sidebar' },
+                            'mt_shortcuts'  => { order => 2, set => 'sidebar' },
+                            'mt_news'       => { order => 3, set => 'sidebar' },
+                        );
+                        my $blog_iter = MT->model('blog')->load_iter(
+                            undef,
+                            { fetchonly => ['id'] }
+                        );
+                        while ( my $blog = $blog_iter->() ) {
+                            my $set = 'dashboard:blog:' . $blog->id;
+                            $widget_store->{$set} = \%default_widgets;
+                        }
+                        $widget_store->{'dashboard:system'} = \%default_widgets;
+                    }
                     $user->widgets($widget_store);
                 },
             },
@@ -1147,7 +1175,6 @@
     my $driver = $db_class->dbi_driver;
     my $dbh = $driver->rw_handle;
     my $dbd = $driver->dbd;
-    my $stmt = $dbd->sql_class->new;
 
     my $meta_col = $param{meta_column} || 'meta';
 
@@ -1155,16 +1182,20 @@
     my $db_defs = $ddl->column_defs($db_class);
     return 0 unless $db_defs && exists($db_defs->{$meta_col});
 
-    my $id_col = $dbd->db_column_name($class->datasource, 'id');
-    $meta_col = $dbd->db_column_name($class->datasource, $meta_col);
-    $stmt->add_where( $meta_col => { not_null => 1 } );
-    $stmt->limit( 101 );
-
-    my $sql = join ' ', 'SELECT', $meta_col, ',', $id_col, 'FROM',
-        $driver->table_for($class),
-        $stmt->as_sql_where(),
-        $stmt->as_limit;
-
+    my $terms = {
+        $meta_col => { not_null => 1 }
+    };
+    my $args = {
+        'limit'      => 101,
+        'fetchonly' => [ 'id' ],  # meta is added to the select list separately
+        $offset ? ( 'offset' => $offset ) : ()
+    };
+    my $stmt = $driver->prepare_statement( $class, $terms, $args );
+    my $db_meta_col = $dbd->db_column_name($class->datasource, $meta_col);
+    ## Meta column has to be added in here because it's already
+    ## gone from the column_names - something fetchonly relies on
+    $stmt->add_select( $db_meta_col => $db_meta_col );
+    my $sql = $stmt->as_sql;
     my $sth = $dbh->prepare($sql);
     return 0 if !$sth; # ignore this operation if _meta column doesn't exist
     $sth->execute
@@ -1190,7 +1221,7 @@
     my $cfclass = MT->model('field');
     while (my $row = $sth->fetchrow_arrayref) {
         $rows++;
-        my ($rawmeta, $id) = @$row;
+        my ($id, $rawmeta) = @$row;  ## add_select pushes the column - it should be in this order
         if (defined $rawmeta) {
             push @ids, $id;
             if ($rawmeta =~ m/^SERG/) {
@@ -1246,9 +1277,10 @@
 
     # now, clear the meta column for each of the objects touched
     if (@ids) {
+        my $id_col = $dbd->db_column_name($class->datasource, 'id');
         my $list = join ",", @ids;
         my $sql = join " ", "UPDATE", $driver->table_for($class),
-            "SET", $meta_col, "=NULL WHERE", $id_col, " IN ($list)";
+            "SET", $db_meta_col, "=NULL WHERE", $id_col, " IN ($list)";
         $dbh->do($sql);
     }
 
@@ -1260,8 +1292,7 @@
             # if the driver cannot drop a column, it is likely
             # to get dropped as the table is updated for other
             # new columns anyway.
-            $sql = $dbd->ddl_class->drop_column_sql($class,
-                $param{meta_column} || 'meta');
+            $sql = $dbd->ddl_class->drop_column_sql($class, $meta_col);
             $self->add_step('core_drop_meta_for_table', class => $db_class, sql => $sql);
         }
         $self->progress($msg . ' (100%)', $pid);
@@ -1279,7 +1310,15 @@
     eval "require $class;";
     my $driver = $class->dbi_driver;
     my $dbh = $driver->rw_handle;
-    $dbh->do($sql);
+    my $err;
+    eval {
+        $dbh->do($sql) or $err = $dbh->errstr;
+    };
+    # ignore drop errors; the column has probably been
+    # removed already
+    #if ($err) {
+    #    print STDERR "$err: $sql\n";
+    #}
 
     return 0;
 }

Index: lib/MT/Object.pm
===================================================================
--- lib/MT/Object.pm	(revision 2834)
+++ lib/MT/Object.pm	(revision 2876)
@@ -361,9 +361,9 @@
         if (defined *{$package.'::new'}) {
             return $package;
         } else {
-            eval "# line " . __LINE__ . " " . __FILE__ . "\nno warnings 'all';use $package;";
+            eval "# line " . __LINE__ . " " . __FILE__ . "\nno warnings 'all';require $package;";
             return $package unless $@;
-            eval "# line " . __LINE__ . " " . __FILE__ . "\nno warnings 'all';use $pkg; $package->new;";
+            eval "# line " . __LINE__ . " " . __FILE__ . "\nno warnings 'all';require $pkg; $package->new;";
             return $package unless $@;
         }
     }
@@ -1035,7 +1035,7 @@
     my $key = $param->{key} || $obj->datasource . '_id';
     my $obj_id = $obj->id;
     for my $class (@classes) {
-        eval "# line " . __LINE__ . " " . __FILE__ . "\nno warnings 'all';use $class;";
+        eval "# line " . __LINE__ . " " . __FILE__ . "\nno warnings 'all';require $class;";
         $class->remove({ $key => $obj_id });
     }
     1;
Index: lib/MT/CMS/Template.pm
===================================================================
--- lib/MT/CMS/Template.pm	(revision 2834)
+++ lib/MT/CMS/Template.pm	(revision 2876)
@@ -774,6 +774,8 @@
     my $tmpl;
     my $user_id = $app->user->id;
 
+    return unless $app->validate_magic;
+
     # We can only do previews on blog templates. Have to publish
     # the preview file somewhere!
     return $app->errtrans("Invalid request.") unless $blog;
@@ -996,6 +998,7 @@
     }
     $param{template_loop} = \@data;
     $param{object_type}  = $type;
+    $app->request('preview_object', $tmpl);
     return $app->load_tmpl( 'preview_template_strip.tmpl', \%param );
 }
 
@@ -1661,9 +1664,10 @@
         $param->{'template_set_count'} = scalar @sets;
         $param->{'template_set_loop'} = \@sets;
 
-        $param->{screen_id} = "refresh-templates-dialog";
     }
 
+    $param->{screen_id} = "refresh-templates-dialog";
+
     # load template sets
     $app->build_page('dialog/refresh_templates.tmpl',
         $param);
Index: lib/MT/CMS/User.pm
===================================================================
--- lib/MT/CMS/User.pm	(revision 2834)
+++ lib/MT/CMS/User.pm	(revision 2876)
@@ -1068,6 +1068,7 @@
     my $app = shift;
 
     my $user = $app->user;
+    return unless $app->validate_magic;
 
     my $blogs   = $app->param('blog')   || '';
     my $authors = $app->param('author') || '';
Index: lib/MT/CMS/Entry.pm
===================================================================
--- lib/MT/CMS/Entry.pm	(revision 2834)
+++ lib/MT/CMS/Entry.pm	(revision 2876)
@@ -1023,6 +1023,7 @@
         return $app->load_tmpl( 'preview_entry.tmpl', \%param );
     }
     else {
+        $app->request('preview_object', $entry);
         return $app->load_tmpl( 'preview_strip.tmpl', \%param );
     }
 }
Index: lib/MT/App.pm
===================================================================
--- lib/MT/App.pm	(revision 2834)
+++ lib/MT/App.pm	(revision 2876)
@@ -992,7 +992,6 @@
                 email => $commenter->email,
                 userpic => scalar $commenter->userpic_url,
                 profile => "", # profile link url
-                auth_type => ($commenter->auth_type eq 'MT' ? "1" : "0"),
                 is_authenticated => "1",
                 is_trusted => ($commenter->is_trusted($blog_id) ? "1" : "0"),
                 is_author => ($commenter->type == MT::Author::AUTHOR() ? "1" : "0"),
@@ -1162,7 +1161,7 @@
     my $nick_escaped = MT::Util::escape_unicode( $nick );
 
     my $timeout;
-    if ( $user->auth_type eq 'MT' ) {
+    if ( $user->type == MT::Author::AUTHOR() ) {
         if ($app->param('remember')) {
             # 10 years, same as app sign-in 'remember me'
             $timeout = '+3650d';
Index: lib/MT/AtomServer.pm
===================================================================
--- lib/MT/AtomServer.pm	(revision 2834)
+++ lib/MT/AtomServer.pm	(revision 2876)
@@ -787,7 +787,7 @@
         unless $app->{perms}->can_edit_entry($entry, $app->{user});
 
     # Delete archive file
-    my $blog = MT::Blog->load($entry->blog_id);
+    $blog = MT::Blog->load($entry->blog_id);
     my %recip = $app->publisher->rebuild_deleted_entry(
         Entry => $entry,
         Blog  => $blog);
Index: lib/MT/Template/ContextHandlers.pm
===================================================================
--- lib/MT/Template/ContextHandlers.pm	(revision 2834)
+++ lib/MT/Template/ContextHandlers.pm	(revision 2876)
@@ -2547,11 +2547,13 @@
     my ($ctx, $args, $cond) = @_;
 
     my $start = (exists $args->{from} ? $args->{from} : $args->{start}) || 0;
-    $start = 0 unless $start =~ /^\d+$/;
+    $start = 0 unless $start =~ /^-?\d+$/;
     my $end = (exists $args->{to} ? $args->{to} : $args->{end}) || 0;
-    return q() unless $end =~ /^\d+$/;
+    return q() unless $end =~ /^-?\d+$/;
     my $incr = $args->{increment} || $args->{step} || 1;
+    # FIXME: support negative "step" values
     $incr = 1 unless $incr =~ /^\d+$/;
+    $incr = 1 unless $incr;
 
     my $builder = $ctx->stash('builder');
     my $tokens = $ctx->stash('tokens');
@@ -3361,7 +3363,7 @@
         $key = $args->{key} if exists $args->{key};
     }
 
-    if ($name =~ m/^$/) {
+    if ($name =~ m/^\$/) {
         $name = $ctx->var($name);
     }
 
@@ -3384,7 +3386,7 @@
                 $value = _hdlr_pass_tokens(@_) or return;
             } elsif (ref($value) eq 'ARRAY') {
                 if ( defined $index ) {
-                    if ($index =~ /^\d+$/) {
+                    if ($index =~ /^-?\d+$/) {
                         $value = $value->[ $index ];
                     } else {
                         $value = undef; # fall through to any 'default'
@@ -4450,8 +4452,10 @@
     <$mt:Var name="contents"$>
     (footer stuff)
 
-B<Attributes:>
+B<Important:> Modules used as IncludeBlocks should never be processed as a Server Side Include or be cached
 
+=head4 Attributes:
+
 =over 4
 
 =item * var (optional)
@@ -5489,7 +5493,7 @@
     my($ctx, $args) = @_;
     my $tag = lc $ctx->stash('tag');
     my $name = $args->{name} || $args->{var};
-    if ($name =~ m/^$/) {
+    if ($name =~ m/^\$/) {
         $name = $ctx->var($name);
     }
     return $ctx->error(MT->translate(
@@ -5657,7 +5661,7 @@
         $key = $args->{key} if exists $args->{key};
     }
 
-    if ($name =~ m/^$/) {
+    if ($name =~ m/^\$/) {
         $name = $ctx->var($name);
         return $ctx->error(MT->translate(
             "You used a [_1] tag without a valid name attribute.", "<MT$tag>" ))
@@ -5683,7 +5687,7 @@
         $existing = $existing->{ $key };
     }
     elsif ( 'ARRAY' eq ref($existing) ) {
-        $existing = ( defined $index && ( $index =~ /^\d+$/ ) )
+        $existing = ( defined $index && ( $index =~ /^-?\d+$/ ) )
           ? $existing->[ $index ] 
           : undef;
     }
@@ -5716,7 +5720,7 @@
         return $ctx->error( MT->translate("'[_1]' is not an array.", $name) )
             unless 'ARRAY' eq ref($data);
         return $ctx->error( MT->translate("Invalid index.") )
-            unless $index =~ /^\d+$/;
+            unless $index =~ /^-?\d+$/;
         $data->[ $index ] = $val;
     }
     elsif ( defined $func ) {
Index: lib/MT/App/CMS.pm
===================================================================
--- lib/MT/App/CMS.pm	(revision 2834)
+++ lib/MT/App/CMS.pm	(revision 2876)
@@ -40,8 +40,8 @@
     return {
         'tools'     => "${pkg}Tools::system_check",
         'dashboard' => "${pkg}Dashboard::dashboard",
-        'menu'      => '${pkg}Dashboard::dashboard',
-        'admin'     => '${pkg}Dashboard::dashboard',
+        'menu'      => "${pkg}Dashboard::dashboard",
+        'admin'     => "${pkg}Dashboard::dashboard",
 
         ## Generic handlers
         'save'           => "${pkg}Common::save",
Index: lib/MT/Template.pm
===================================================================
--- lib/MT/Template.pm	(revision 2834)
+++ lib/MT/Template.pm	(revision 2876)
@@ -56,6 +56,7 @@
         'rebuild_me' => 1,
         'build_dynamic' => 0,
         'build_type' => 1,
+        'build_interval' => 0,
     },
     meta => 1,
     child_of => 'MT::Blog',
Index: lib/MT/XMLRPCServer.pm
===================================================================
--- lib/MT/XMLRPCServer.pm	(revision 2834)
+++ lib/MT/XMLRPCServer.pm	(revision 2876)
@@ -346,6 +346,7 @@
     $entry->excerpt($item->{mt_excerpt}) if $item->{mt_excerpt};
     $entry->text_more($item->{mt_text_more}) if $item->{mt_text_more};
     $entry->keywords($item->{mt_keywords}) if $item->{mt_keywords};
+    $entry->created_by($author->id);
 
     if (my $tags = $item->{mt_tags}) {
         require MT::Tag;
@@ -475,6 +476,7 @@
     $entry->excerpt($item->{mt_excerpt}) if defined $item->{mt_excerpt};
     $entry->text_more($item->{mt_text_more}) if defined $item->{mt_text_more};
     $entry->keywords($item->{mt_keywords}) if defined $item->{mt_keywords};
+    $entry->modified_by($author->id);
     if (my $tags = $item->{mt_tags}) {
         require MT::Tag;
         my $tag_delim = chr($author->entry_prefs->{tag_delim});
@@ -491,8 +493,9 @@
         require MT::DateTime;
         $entry->status(MT::Entry::FUTURE())
             if MT::DateTime->compare(
-                a => $entry->authored_on,
-                b => { value => time(), type => 'epoch' } ) > 0;
+                blog => $blog,
+                a    => $entry->authored_on,
+                b    => { value => time(), type => 'epoch' } ) > 0;
     }
     $entry->discover_tb_from_entry();
 
Index: plugins/StyleCatcher/lib/StyleCatcher/CMS.pm
===================================================================
--- plugins/StyleCatcher/lib/StyleCatcher/CMS.pm	(revision 2834)
+++ plugins/StyleCatcher/lib/StyleCatcher/CMS.pm	(revision 2876)
@@ -134,6 +134,7 @@
     # format of 'key: value' in comment-space
     # The remixer only uses name, author, description at the moment.
     my $app = shift;
+    return $app->json_error( $app->errstr ) unless $app->validate_magic;
 
     my $data = fetch_themes($app->param('url'))
         or return $app->json_error( $app->errstr );
Index: plugins/StyleCatcher/tmpl/view.tmpl
===================================================================
--- plugins/StyleCatcher/tmpl/view.tmpl	(revision 2834)
+++ plugins/StyleCatcher/tmpl/view.tmpl	(revision 2876)
@@ -490,6 +490,7 @@
             'method': 'POST',
             'arguments': {
                 '__mode': 'stylecatcher_js',
+                'magic_token': '<mt:var name="magic_token">',
                 'url': url
             }
         });
Index: mt-static/mt.js
===================================================================
--- mt-static/mt.js	(revision 2834)
+++ mt-static/mt.js	(revision 2876)
@@ -1481,15 +1481,17 @@
 
 
     eventSubmit: function( event ) {
+        this.eventSubmitForm = undefined;
+
         var form = DOM.getFirstAncestorByTagName( event.target, "form", true );
         if ( !form )
             return;
-            
+
         if ( form.getAttribute( "mt:once" ) ) {
-        
             if ( form.submitted )
                 return event.stop();
-        
+
+            this.eventSubmitForm = form;
             this.toggleSubmit( form, true );
         }
 
@@ -1501,6 +1503,13 @@
 
 
     eventBeforeUnload: function( event ) {
+        /* re-enables disabled controls onunload, so they are enabled
+           if the user navigates back */
+        if ( this.eventSubmitForm ) {
+            this.toggleSubmit( this.eventSubmitForm, false );
+            this.submitted = false;
+        }
+
         if ( this.changed ) {
             if ( this.constructor.Editor )
                 return event.returnValue = Editor.strings.unsavedChanges;
Index: tmpl/cms/include/template_table.tmpl
===================================================================
--- tmpl/cms/include/template_table.tmpl	(revision 2834)
+++ tmpl/cms/include/template_table.tmpl	(revision 2876)
@@ -42,7 +42,7 @@
         ><__trans phrase="Delete"></a>
     </mt:unless></mt:unless>
 </mt:setvarblock>
-<mt:setvarblock name="table_id"><mt:var name="template_type">-listing</mt:setvarblock>
+<mt:setvarblock name="table_id"><mt:var name="template_type" default="template">-listing</mt:setvarblock>
 <mtapp:listing id="$table_id" hide_pager="1" class="show-all" listing_class="show-actions-bar-top" type="template">
     <mt:if __first__>
         <thead>
Index: tmpl/cms/dialog/refresh_templates.tmpl
===================================================================
--- tmpl/cms/dialog/refresh_templates.tmpl	(revision 2834)
+++ tmpl/cms/dialog/refresh_templates.tmpl	(revision 2876)
@@ -73,7 +73,7 @@
         label_class="top-label"
         show_label="0"
         show_hint="1"
-        hint="<__trans phrase="Updates current templates while retaining any user-created or user-modified templates.">">
+        hint="<__trans phrase="Updates current templates while retaining any user-created templates.">">
         <div class="field-header">
             <label for="refresh_type_refresh"><input type="radio" name="refresh_type" id="refresh_type_refresh" value="refresh" onclick="disable('template_set');toggleHidden('confirm-clean');toggleHidden('confirm-refresh');" checked="checked" /> <$mt:var name="refresh_label"$></label>
         </div>
Index: default_templates/category_archive_list.mtml
===================================================================
--- default_templates/category_archive_list.mtml	(revision 2877)
+++ default_templates/category_archive_list.mtml	(revision 2922)
@@ -7,7 +7,7 @@
         <ul>
         </mt:SubCatIsFirst>
         <mt:If tag="CategoryCount">
-            <li><a href="<$mt:CategoryArchiveLink$>"<mt:If tag="CategoryDescription"> title="<$mt:CategoryDescription$>"</mt:If>><__trans phrase="[_1] ([_2])" params="<$mt:CategoryLabel$>%%<$mt:CategoryCount$>"></a>
+            <li><a href="<$mt:CategoryArchiveLink$>"<mt:If tag="CategoryDescription"> title="<$mt:CategoryDescription remove_html="1" encode_html="1"$>"</mt:If>><__trans phrase="[_1] ([_2])" params="<$mt:CategoryLabel$>%%<$mt:CategoryCount$>"></a>
         <mt:Else>
             <li><$mt:CategoryLabel$>
         </mt:If>
Index: default_templates/openid.mtml
===================================================================
--- default_templates/openid.mtml	(revision 2877)
+++ default_templates/openid.mtml	(revision 2922)
@@ -2,7 +2,7 @@
 <div class="widget-openid widget">
     <div class="widget-content">
         <em><__trans phrase="[_1] accepted here" params="<strong>OpenID</strong>"></em>
-        <a href="<__trans phrase="http://www.movabletype.com/openid/";>"><__trans phrase="Learn more about OpenID"></a>
+        <a href="<__trans phrase="http://www.sixapart.com/labs/openid/";>"><__trans phrase="Learn more about OpenID"></a>
     </div>
 </div>
 </mt:IfRegistrationAllowed>
Index: lib/MT/Upgrade.pm
===================================================================
--- lib/MT/Upgrade.pm	(revision 2877)
+++ lib/MT/Upgrade.pm	(revision 2922)
@@ -834,7 +834,7 @@
                     require MT::Template;
                     my $styles = MT::Template->load({ blog_id => $blog->id, identifier => 'styles' });
                     if ($styles) {
-                        if ($styles->text =~ m{ <mt:?setvar \s+ name="page_layout" \s+ value="([^"]+)"> }xmsi) {
+                        if ($styles->text =~ m{ <\$?mt:?setvar \s+ name="page_layout" \s+ value="([^"]+)"\$?> }xmsi) {
                             $layout = $1;
                         }
                     }
Index: lib/MT/ConfigMgr.pm
===================================================================
--- lib/MT/ConfigMgr.pm	(revision 2877)
+++ lib/MT/ConfigMgr.pm	(revision 2922)
@@ -208,6 +208,8 @@
 sub save_config {
     my $class = shift;
     my $mgr = $class->instance;
+    # prevent saving when the db row wasn't read already
+    return 0 unless $mgr->{__read_db};
     return 0 unless $mgr->is_dirty();
     my $data = '';
     my $settings = $mgr->{__dbvar};
@@ -301,6 +303,7 @@
             $mgr->set($var, $val, 1);
         }
     }
+    $mgr->{__read_db} = 1;
     1;
 }
 
Index: lib/MT/Object.pm
===================================================================
--- lib/MT/Object.pm	(revision 2877)
+++ lib/MT/Object.pm	(revision 2922)
@@ -497,7 +497,7 @@
             vclob
         ) ],
         indexes => {
-            id_type    => { columns => [ $id_field, 'type' ] },
+            #id_type    => { columns => [ $id_field, 'type' ] }, # redundant
             type_vchar => { columns => [ 'type', 'vchar_idx'     ] },
             type_vdt   => { columns => [ 'type', 'vdatetime_idx' ] },
             type_vint  => { columns => [ 'type', 'vinteger_idx'  ] },
Index: lib/MT/ObjectDriver/DDL/mysql.pm
===================================================================
--- lib/MT/ObjectDriver/DDL/mysql.pm	(revision 2877)
+++ lib/MT/ObjectDriver/DDL/mysql.pm	(revision 2922)
@@ -96,6 +96,7 @@
         $coltype = $ddl->db2type($coltype);
         $defs->{$colname}{type} = $coltype;
         $defs->{$colname}{auto} = ($row->{Extra} =~ m/auto_increment/i) ? 1 : 0;
+        $defs->{$colname}{key}  = $row->{Key} eq 'PRI' ? 1 : 0;
         if (($coltype eq 'string') && $size) {
             $defs->{$colname}{size} = $size;
         }
Index: lib/MT/ObjectDriver/DDL/SQLite.pm
===================================================================
--- lib/MT/ObjectDriver/DDL/SQLite.pm	(revision 2877)
+++ lib/MT/ObjectDriver/DDL/SQLite.pm	(revision 2922)
@@ -100,6 +100,7 @@
         or return undef;
     $sth->execute or return undef;
     my $defs = {};
+    my @pks;
     while (my $row = $sth->fetchrow_hashref) {
         my $colname = lc $row->{name};
         $colname =~ s/^\Q$field_prefix\E_//i;
@@ -108,13 +109,13 @@
             $defs->{$colname}{size} = $1;
         }
         $defs->{$colname}{type} = $coltype;
+        # TODO: isn't key for pks, not foreign keys?
         if ($colname =~ m/_id$/) {
             $defs->{$colname}{key} = 1;
         }
-        if ( ($coltype eq 'integer') && $row->{pk} ) {
-            # with sqlite, integer primary keys auto increment. always.
+        if ($row->{pk}) {
             $defs->{$colname}{key} = 1;
-            $defs->{$colname}{auto} = 1;
+            push @pks, $colname;
         }
         $defs->{$colname}{not_null} = 1
             if $row->{notnull};
@@ -123,6 +124,15 @@
     }
     $sth->finish;
     return undef unless %$defs;
+
+    if (@pks && 1 == scalar @pks) {
+        my ($colname) = @pks;
+        if ($defs->{$colname}{type} eq 'integer') {
+            # with sqlite, simple integer primary keys auto increment. always.
+            $defs->{$colname}{auto} = 1;
+        }
+    }
+
     return $defs;
 }
 
@@ -172,15 +182,14 @@
     my $ddl = shift;
     my ($class) = @_;
 
-    my $table_name = $class->table_name;
-    my $props = $class->properties;
+    my $table_name   = $class->table_name;
+    my $props        = $class->properties;
     my $field_prefix = $class->datasource;
-    my $indexes = $props->{indexes};
+    my $indexes      = $props->{indexes};
+    my $pk           = $props->{primary_key};
 
     my @stmts;
     if ($indexes) {
-        # FIXME: Handle possible future primary key tuple case
-        my $pk = $props->{primary_key};
         foreach my $name (keys %$indexes) {
             next if $pk && $name eq $pk;
             if (ref $indexes->{$name} eq 'HASH') {
@@ -198,6 +207,11 @@
             }
         }
     }
+    if ($pk && 'ARRAY' eq ref $pk) {
+        my @columns = map { join q{_}, $field_prefix, $_ } @$pk;
+        my $columns = join q{, }, @columns;
+        push @stmts, "PRIMARY KEY ($columns)";
+    }
     if (@stmts) {
         return ',' . join("\n", @stmts);
     }
Index: lib/MT/ObjectDriver/DDL.pm
===================================================================
--- lib/MT/ObjectDriver/DDL.pm	(revision 2877)
+++ lib/MT/ObjectDriver/DDL.pm	(revision 2922)
@@ -27,8 +27,22 @@
 sub index_table {()}
 sub create_sequence {}
 sub drop_sequence {}
-sub unique_constraint_sql { '' }
 
+sub unique_constraint_sql {
+    my $ddl = shift;
+    my ($class) = @_;
+
+    my $pk = $class->properties->{primary_key};
+    return q{} if !ref $pk || 'ARRAY' ne ref $pk;
+
+    my $driver = $class->driver;
+    my $dbd = $driver->dbd;
+    my $table = $class->table_name;
+
+    my @key_fields = map { $dbd->db_column_name($table, $_) } @$pk;
+    return ', PRIMARY KEY (' . join(q{, }, @key_fields) . ')';
+}
+
 sub table_exists {
     my $ddl = shift;
     my ($class) = @_;
@@ -257,8 +271,8 @@
 
     my @stmts;
     if ($indexes) {
-        # FIXME: Handle possible future primary key tuple case
         my $pk = $props->{primary_key};
+        undef $pk if ref $pk;  # ignore complex key
         foreach my $name (keys %$indexes) {
             next if $pk && $name eq $pk;
             push @stmts, $ddl->index_column_sql($class, $name);
@@ -282,7 +296,7 @@
     my $field_prefix = $class->datasource;
     my $pk = $props->{primary_key};
     if (!ref $indexes->{$name}) {
-        if (!($pk && $name eq $pk)) {
+        if (!$pk || ref $pk || $name ne $pk) {
             push @stmts, "CREATE INDEX ${table_name}_$name ON $table_name (${field_prefix}_$name)";
         }
     }
@@ -361,8 +375,10 @@
         }
         $default = ' DEFAULT ' . $value;
     }
-    my $key = '';
-    $key = ' PRIMARY KEY' if $def->{key};
+    my $key = !$def->{key}                          ? q{}
+            : ref $class->properties->{primary_key} ? q{}
+            :                                         ' PRIMARY KEY'
+            ;
     return $field_prefix . '_' . $name . ' ' . $type . $nullable . $default . $key;
 }
 
Index: lib/MT/CMS/Search.pm
===================================================================
--- lib/MT/CMS/Search.pm	(revision 2877)
+++ lib/MT/CMS/Search.pm	(revision 2922)
@@ -385,10 +385,6 @@
     ## we look for a comma (not a valid character in a column name) and split
     ## on it if it's there.
     if ( ($search || '') ne '' ) {
-        my $enc = $app->charset;
-        $search = MT::I18N::encode_text( $search, 'utf-8', $enc )
-          if ( $enc !~ m/utf-?8/i )
-          && ( 'dialog_grant_role' eq $app->param('__mode') );
         $search = quotemeta($search) unless $is_regex;
         $search = '(?i)' . $search   unless $case;
     }
Index: lib/MT/CMS/Tag.pm
===================================================================
--- lib/MT/CMS/Tag.pm	(revision 2877)
+++ lib/MT/CMS/Tag.pm	(revision 2922)
@@ -155,9 +155,7 @@
     my $blog_id      = $app->param('blog_id');
     my $obj_class    = $app->model($obj_ds) or return;
     my $tag_name     = $app->param('tag') or return;
-    if ( 'utf-8' ne lc( $app->config->PublishCharset) ) {
-        $tag_name = MT::I18N::encode_text( $tag_name, 'utf-8', $app->config->PublishCharset );
-    }
+
     my $tag_obj =
       $tag_class->load( { name => $tag_name }, { binary => { name => 1 } } );
 
Index: lib/MT/CMS/Template.pm
===================================================================
--- lib/MT/CMS/Template.pm	(revision 2877)
+++ lib/MT/CMS/Template.pm	(revision 2922)
@@ -310,6 +310,8 @@
                 $param->{enabled_archive_types} = join(", ", sort keys %at);
                 $param->{static_maps} = $build_type == MT::PublishOption::DYNAMIC() ? 0 : 1;
                 $param->{build_type_0} = 1 unless $build_type_0;
+            } else {
+                $param->{can_rebuild} = 0;
             }
         }
         # publish options
@@ -558,7 +560,7 @@
         if $app->param('dirty');
 
     $param->{can_preview} = 1
-        if (!$param->{is_special}) && (!$obj || ($obj && ($obj->outfile || '') !~ m/\.(css|xml|rss|js)$/));
+        if (!$param->{is_special}) && (!$obj || ($obj && ($obj->outfile || '') !~ m/\.(css|xml|rss|js)$/)) && (!exists $param->{can_preview});
 
     1;
 }
@@ -2161,6 +2163,8 @@
     $return_args =~ s/^\?//;
 
     $app->return_args( $return_args );
+    return $app->call_return unless %ats;
+
     $app->param( 'template_id', $tmpl_id );
     $app->param( 'single_template', 1 ); # forces fullscreen mode
     $app->param( 'type', join(",", keys %ats) );
Index: lib/MT/CMS/Category.pm
===================================================================
--- lib/MT/CMS/Category.pm	(revision 2877)
+++ lib/MT/CMS/Category.pm	(revision 2922)
@@ -275,12 +275,6 @@
     }
 
     my $label = $app->param('label');
-    my $enc   = $app->config->PublishCharset;
-
-    # XMLHttpRequest always send text in UTF-8... right?
-    if ( 'utf-8' ne lc($enc) ) {
-        $label = MT::I18N::encode_text( $label, 'utf-8', $enc );
-    }
     my $basename = $app->param('basename');
     if ( !defined($label) || ( $label =~ m/^\s*$/ ) ) {
         return $app->json_error( $app->translate("Invalid request.") );
Index: lib/MT/CMS/Common.pm
===================================================================
--- lib/MT/CMS/Common.pm	(revision 2877)
+++ lib/MT/CMS/Common.pm	(revision 2922)
@@ -449,18 +449,7 @@
         if ($sess_obj) {
             my $data = $sess_obj->thaw_data;
             if ($data) {
-
-                # XMLHttpRequest always send text in UTF-8... right?
-                if ( 'utf-8' eq lc($enc) ) {
-                    $q->param( $_, $data->{$_} ) for keys %$data;
-                }
-                else {
-                    foreach ( keys %$data ) {
-                        my $encoded =
-                          MT::I18N::encode_text( $data->{$_}, 'utf-8', $enc );
-                        $q->param( $_, $encoded );
-                    }
-                }
+                $q->param( $_, $data->{$_} ) for keys %$data;
                 $param{'recovered_object'} = 1;
             }
             else {
Index: lib/MT/CMS/Tools.pm
===================================================================
--- lib/MT/CMS/Tools.pm	(revision 2877)
+++ lib/MT/CMS/Tools.pm	(revision 2922)
@@ -1435,21 +1435,8 @@
 sub convert_to_html {
     my $app    = shift;
     my $format = $app->param('format');
-    my $text   = $app->param('text');
-    # XMLHttpRequest always send text in UTF-8... right?
-    if ( defined $text ) {
-        $text = encode_text($text, 'utf-8', $app->config->PublishCharset);
-    } 
-    else {
-        $text = '' ;
-    }
-    my $text_more = $app->param('text_more');
-    if ( defined $text_more ) {
-        $text_more = encode_text($text_more, 'utf-8', $app->config->PublishCharset);
-    } 
-    else {
-        $text_more = '' ;
-    }
+    my $text   = $app->param('text') || '';
+    my $text_more = $app->param('text_more') || '';
     my $result = {
         text      => $app->apply_text_filters( $text,      [$format] ),
         text_more => $app->apply_text_filters( $text_more, [$format] ),
Index: lib/MT/CMS/Entry.pm
===================================================================
--- lib/MT/CMS/Entry.pm	(revision 2877)
+++ lib/MT/CMS/Entry.pm	(revision 2922)
@@ -2042,7 +2042,6 @@
         my $entry = MT::Entry->load($id)
           or return $app->errtrans(
             "One of the entries ([_1]) did not actually exist", $id );
-        next if $entry->status == $new_status;
         if ( $app->config('DeleteFilesAtRebuild')
             && ( MT::Entry::RELEASE() eq $entry->status ) )
         {
Index: lib/MT/App.pm
===================================================================
--- lib/MT/App.pm	(revision 2877)
+++ lib/MT/App.pm	(revision 2922)
@@ -2,7 +2,7 @@
 # This program is distributed under the terms of the
 # GNU General Public License, version 2.
 #
-# $Id: App.pm 2846 2008-07-28 02:46:54Z fumiakiy $
+# $Id$
 
 package MT::App;
 
@@ -815,7 +815,17 @@
         my @p       = $q->param();
         my $charset = $app->charset;
         require Encode;
+        require MT::I18N::default;
         $charset = 'UTF-8' if $charset =~ m/utf-?8/i;
+        my $request_charset = $charset;
+        if ( my $content_type = $q->content_type() ) {
+            if ( $content_type =~ m/;[ ]+charset=(.+)/i ) {
+                $request_charset = lc $1;
+                $request_charset =~ s/^\s+|\s+$//gs;
+            }
+        }
+        my $transcode = $request_charset ne $charset ? 1 : 0;
+        my %params;
         foreach my $p (@p) {
             if ( $p =~ m/[^\x20-\x7E]/ ) {
 
@@ -824,18 +834,42 @@
             }
 
             my @d = $q->param($p);
+            my @param;
             foreach my $d (@d) {
-                next
-                    if ( !defined $d )
-                    || ( $d eq '' )
-                    || ( $d !~ m/[^\x20-\x7E]/ );
+                if ( ( !defined $d )
+                  || ( $d eq '' )
+                  || ( $d !~ m/[^\x20-\x7E]/ ) )
+                {
+                    push @param, $d if $transcode;
+                    next;
+                }
+                $d = MT::I18N::default->encode_text_encode( $d, $request_charset, $charset )
+                    if $transcode;
+                my $saved = $d;
                 eval { Encode::decode( $charset, $d, 1 ); };
                 return $app->errtrans(
                     "Invalid request: corrupt character data for character set [_1]",
                     $charset
                 ) if $@;
+                push @param, $saved if $transcode;
             }
+            if ( $transcode && @param ) {
+                if ( 1 == scalar(@param) ) {
+                    $params{ $p } = $param[0];
+                }
+                else {
+                    $params{ $p } = [ @param ];
+                }
+            }
         }
+        while ( my ( $key, $val ) = each %params ) {
+            if ( ref $val ) {
+                $app->param( $key, @{ $params{ $key } } ) ;
+            }
+            else {
+                $app->param( $key, $val );
+            }
+        }
 
         return 1;
     }
Index: lib/MT/App/Trackback.pm
===================================================================
--- lib/MT/App/Trackback.pm	(revision 2877)
+++ lib/MT/App/Trackback.pm	(revision 2922)
@@ -38,15 +38,8 @@
     my $q = $app->param;
 
     # attempt to determine character set encoding based on
-    # 'charset' parameter or 'charset' in content-type header:
+    # 'charset' parameter:
     my $enc = $q->param('charset');
-    unless ($enc) {
-        my $content_type = $q->content_type();
-        if ( $content_type =~ m/;[ ]+charset=(.+)/i ) {
-            $enc = lc $1;
-            $enc =~ s/^\s+|\s+$//gs;
-        }
-    }
     local $app->{charset} = $enc if $enc;
     return $app->SUPER::validate_request_params();
 }
@@ -252,26 +245,12 @@
         );
     }
 
-    my ( $title, $excerpt, $url, $blog_name, $enc )
+    my ( $title, $excerpt, $url, $blog_name )
         = map scalar $q->param($_),
-        qw( title excerpt url blog_name charset);
+        qw( title excerpt url blog_name);
 
-    unless ($enc) {
-        my $content_type = $q->content_type();
-        if ( $content_type =~ m/;[ ]+charset=(.+)/i ) {
-            $enc = lc $1;
-            $enc =~ s/^\s+|\s+$//gs;
-        }
-    }
-
     no_utf8( $tb_id, $title, $excerpt, $url, $blog_name );
 
-    # guess encoding as possible
-    $enc = MT::I18N::guess_encoding( $excerpt . $title . $blog_name )
-        unless $enc;
-    ( $title, $excerpt, $blog_name )
-        = map { encode_text( $_, $enc ) } ( $title, $excerpt, $blog_name );
-
     return $app->_response(
         Error => $app->translate("Need a Source URL (url).") )
         unless $url;
Index: lib/MT/App/CMS.pm
===================================================================
--- lib/MT/App/CMS.pm	(revision 2877)
+++ lib/MT/App/CMS.pm	(revision 2922)
@@ -421,16 +421,6 @@
     my $pkg = '$Core::MT::CMS::';
     return {
         'entry' => {
-            'set_published' => {
-                label      => "Publish Entries",
-                order      => 100,
-                code       => "${pkg}Entry::publish_entries",
-                permission => 'edit_all_posts,publish_post',
-                condition  => sub {
-                    return 0 if $app->mode eq 'view';
-                    return $app->blog && $app->blog->site_path ? 1 : 0;
-                },
-            },
             'set_draft' => {
                 label      => "Unpublish Entries",
                 order      => 200,
@@ -476,16 +466,6 @@
             },
         },
         'page' => {
-            'set_published' => {
-                label      => "Publish Pages",
-                order      => 100,
-                code       => "${pkg}Entry::publish_entries",
-                permission => 'manage_pages',
-                condition  => sub {
-                    return 0 if $app->mode eq 'view';
-                    return $app->blog && $app->blog->site_path ? 1 : 0;
-                },
-            },
             'set_draft' => {
                 label      => "Unpublish Pages",
                 order      => 200,
@@ -595,7 +575,7 @@
             'untrust' => {
                 label      => "Untrust Commenter(s)",
                 order      => 100,
-                code       => "{$pkg}Comment::untrust_commenter",
+                code       => "${pkg}Comment::untrust_commenter",
                 permission => 'manage_feedback',
             },
             'unban' => {
Index: lib/MT/Template.pm
===================================================================
--- lib/MT/Template.pm	(revision 2877)
+++ lib/MT/Template.pm	(revision 2922)
@@ -328,11 +328,15 @@
 
     my $string_tmpl = '<mt:include widget="%s">';
     my $text = q();
+    my @ids;
     foreach my $wid (@inst) {
         my ( $tmpl ) = grep { $_->id eq $wid } @widgets;
         next unless $tmpl;
         $text .= sprintf( $string_tmpl, $tmpl->name );
+        push @ids, $wid;
     }
+    $obj->modulesets( join ',', @ids )
+        if scalar @ids != scalar @inst;
     $obj->text($text) if $text;
     return $obj->SUPER::save;
 }
@@ -660,6 +664,25 @@
     $tmpl->remove_children({ key => 'template_id' });
 }
 
+sub post_remove_widget {
+    my $tmpl = shift;
+    return unless $tmpl->type eq 'widget';
+
+    my $iter = MT::Template->load_iter({
+        blog_id => [ $tmpl->blog_id, 0 ],
+        type    => 'widgetset',
+    });
+    my @resave;
+    while ( my $ws = $iter->() ) {
+        my @mods = split( ',', $ws->modulesets );
+        if ( grep { $_ == $tmpl->id } @mods ) {
+            push @resave, $ws;
+        }
+    }
+    $_->save for @resave;
+}
+__PACKAGE__->add_trigger('post_remove' => \&post_remove_widget);
+
 # Some DOM-inspired methods (replicating the interface, so it's more
 # familiar to those who know DOM)
 sub getElementsByTagName {
Index: lib/MT/Component.pm
===================================================================
--- lib/MT/Component.pm	(revision 2877)
+++ lib/MT/Component.pm	(revision 2922)
@@ -153,7 +153,7 @@
     return unless -f $path;
     require YAML::Tiny;
     my $y = eval { YAML::Tiny->read($path) }
-        or die "Error reading $path: " . $YAML::Tiny::errstr;
+        or die "Error reading $path: " . (YAML::Tiny->errstr||$@||$!);
     if ( ref($y) ) {
 
         # skip over non-hash elements
@@ -520,8 +520,7 @@
                         if ( -f $f ) {
                             require YAML::Tiny;
                             my $y = eval { YAML::Tiny->read($f) }
-                                or die "Error reading $f: "
-                                    . $YAML::Tiny::errstr;
+                                or die "Error reading $f: " . (YAML::Tiny->errstr||$@||$!);
                             # skip over non-hash elements
                             shift @$y
                                 while @$y && ( ref( $y->[0] ) ne 'HASH' );
Index: plugins/StyleCatcher/lib/StyleCatcher/CMS.pm
===================================================================
--- plugins/StyleCatcher/lib/StyleCatcher/CMS.pm	(revision 2877)
+++ plugins/StyleCatcher/lib/StyleCatcher/CMS.pm	(revision 2922)
@@ -267,7 +267,7 @@
 '/* This is the StyleCatcher theme addition. Do not remove this block. */';
     my $footer = '/* end StyleCatcher imports */';
     my $styles = $header . "\n";
-    $styles .= "\@import url(".File::Spec->catfile($app->static_path, $base_css).");\n" if $base_css;
+    $styles .= "\@import url(".MT::Util::caturl($app->static_path, $base_css).");\n" if $base_css;
     $styles .= "\@import url($url);\n";
     $styles .= $footer;
     print STDERR "styles=$styles\n";
Index: t/lib/MT/Test.pm
===================================================================
--- t/lib/MT/Test.pm	(revision 2877)
+++ t/lib/MT/Test.pm	(revision 2922)
@@ -57,6 +57,11 @@
             push @to_export, $opt;
         }
     }
+
+    # We need *some* instance created up front, to initialize the database
+    # factory etc properly, so do so now.
+    MT->instance;
+
     # Export requested or all exportable functions.
     $pkg->export_to_level(1, @to_export || qw( :DEFAULT ));
 }
Index: mt-static/js/tc/client.js
===================================================================
--- mt-static/js/tc/client.js	(revision 2877)
+++ mt-static/js/tc/client.js	(revision 2922)
@@ -88,7 +88,7 @@
                 args.push( a + '=' + e( param['arguments'][a] ) );
             contents = args.join('&');
         }
-        c.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
+        c.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8' );
     }
     c.send( contents );
     return c;
Index: tmpl/feeds/feed_comment.tmpl
===================================================================
--- tmpl/feeds/feed_comment.tmpl	(revision 2877)
+++ tmpl/feeds/feed_comment.tmpl	(revision 2922)
@@ -71,7 +71,7 @@
 
         &lt;li&gt;&lt;a href="<TMPL_VAR NAME=MT_URL>?__mode=list_comments&amp;blog_id=<TMPL_VAR NAME=LOG.COMMENT.BLOG_ID>"&gt;<MT_TRANS phrase="From this blog">&lt;/a&gt;&lt;/li&gt;
 
-        &lt;li&gt;&lt;a href="<TMPL_VAR NAME=MT_URL>?__mode=view&amp;_type=entry&amp;blog_id=<TMPL_VAR NAME=LOG.COMMENT.BLOG_ID>&amp;id=<TMPL_VAR NAME=LOG.COMMENT.ENTRY.ID>&amp;tab=comments"&gt;<MT_TRANS phrase="On this entry">&lt;/a&gt;&lt;/li&gt;
+        &lt;li&gt;&lt;a href="<TMPL_VAR NAME=MT_URL>?__mode=list_comment&amp;blog_id=<TMPL_VAR NAME=LOG.COMMENT.BLOG_ID>&amp;filter_key=_comments_by_entry&amp;filter_val=<TMPL_VAR NAME=LOG.COMMENT.ENTRY_ID>"&gt;<MT_TRANS phrase="On this entry">&lt;/a&gt;&lt;/li&gt;
 
         <TMPL_IF NAME=LOG.COMMENT.AUTHOR.AUTHENTICATED>
         &lt;li&gt;&lt;a href="<TMPL_VAR NAME=MT_URL>?__mode=view&amp;_type=commenter&amp;id=<TMPL_VAR NAME=LOG.COMMENT.AUTHOR.ID>&amp;blog_id=<TMPL_VAR NAME=LOG.COMMENT.BLOG_ID>&amp;tab=comments"&gt;<MT_TRANS phrase="By commenter identity">&lt;/a&gt;&lt;/li&gt;
Index: tmpl/feeds/feed_ping.tmpl
===================================================================
--- tmpl/feeds/feed_ping.tmpl	(revision 2877)
+++ tmpl/feeds/feed_ping.tmpl	(revision 2922)
@@ -68,7 +68,7 @@
         &lt;strong&gt;<MT_TRANS phrase="More like this">:&lt;/strong&gt;&lt;br /&gt;
         &lt;li&gt;&lt;a href="<TMPL_VAR NAME=MT_URL>?__mode=list_pings&amp;blog_id=<TMPL_VAR NAME=LOG.TBPING.BLOG_ID>"&gt;<MT_TRANS phrase="From this blog">&lt;/a&gt;&lt;/li&gt;
 
-        <TMPL_IF NAME=LOG.TBPING.ENTRY.ID>&lt;li&gt;&lt;a href="<TMPL_VAR NAME=MT_URL>?__mode=view&amp;_type=entry&amp;blog_id=<TMPL_VAR NAME=LOG.TBPING.BLOG_ID>&amp;id=<TMPL_VAR NAME=LOG.TBPING.ENTRY.ID>&amp;tab=pings"&gt;<MT_TRANS phrase="On this entry">&lt;/a&gt;&lt;/li&gt;
+        <TMPL_IF NAME=LOG.TBPING.ENTRY.ID>&lt;li&gt;&lt;a href="<TMPL_VAR NAME=MT_URL>?__mode=list_pings&amp;blog_id=<TMPL_VAR NAME=LOG.TBPING.BLOG_ID>&amp;filter=entry_id&amp;filter_val=<TMPL_VAR NAME=LOG.TBPING.ENTRY.ID>"&gt;<MT_TRANS phrase="On this entry">&lt;/a&gt;&lt;/li&gt;
 
         </TMPL_IF>&lt;li&gt;&lt;a href="<TMPL_VAR NAME=MT_URL>?__mode=search_replace&amp;blog_id=<TMPL_VAR NAME=LOG.TBPING.BLOG_ID>&amp;_type=ping&amp;search=<TMPL_VAR NAME=LOG.TBPING.BLOG_NAME ESCAPE=URL>&amp;do_search=1"&gt;<MT_TRANS phrase="By source blog">&lt;/a&gt;&lt;/li&gt;
 

Reply to: