Index: /trunk/php/lib/sanitize_lib.php
===================================================================
--- /trunk/php/lib/sanitize_lib.php (revision 1098)
+++ /trunk/php/lib/sanitize_lib.php (revision 3082)
@@ -38,5 +38,5 @@
                 $inside = preg_replace('!/?>$!', '', $inside);
                 $attrs = '';
-                if (preg_match_all('/\s*(\w+)\s*=(?:([\'"])(.*?)\2|([^\s]+))\s*/', $inside, $matches, PREG_SET_ORDER)) {
+                if (preg_match_all('/\s*(\w+)\s*=(?:([\'"])(.*?)\2|([^\s]+))\s*/s', $inside, $matches, PREG_SET_ORDER)) {
                     foreach ($matches as $match) {
                         $attr = strtolower($match[1]);
@@ -55,5 +55,5 @@
                                 $dec_val = preg_replace('/&#0*58(?:=;|[^0-9])/', ':', $dec_val);
                                 $dec_val = preg_replace('/&#x0*3[Aa](?:=;|[^a-fA-F0-9])/', ':', $dec_val);
-                                if (preg_match('/^(.+?):/', $dec_val, $proto_match)) {
+                                if (preg_match('/^([\s\S]+?):/', $dec_val, $proto_match)) {
                                     $proto = $proto_match[1];
                                     if (preg_match('/[\r\n\t]/', $proto)) {
Index: /trunk/php/lib/function.mtvar.php
===================================================================
--- /trunk/php/lib/function.mtvar.php (revision 2873)
+++ /trunk/php/lib/function.mtvar.php (revision 3082)
@@ -111,4 +111,13 @@
                 }
             }
+            else {
+                if (array_key_exists('to_json', $args) && $args['to_json']) {
+                    if (function_exists('json_encode')) {
+                        $return_val = json_encode($value);
+                    } else {
+                        $return_val = '';
+                    }
+                }
+            }
         }
         elseif (is_array($value)) {
@@ -140,9 +149,10 @@
             }
             else {
-                if (!array_key_exists('to_json', $args) && $args['to_json']) {
-                    $glue = $args['glue'];
-                    if (!isset($glue))
-                        $glue = '';
-                    $return_val = implode($glue, $value);
+                if (array_key_exists('to_json', $args) && $args['to_json']) {
+                    if (function_exists('json_encode')) {
+                        $return_val = json_encode($value);
+                    } else {
+                        $return_val = '';
+                    }
                 }
             }
Index: /trunk/php/lib/thumbnail_lib.php
===================================================================
--- /trunk/php/lib/thumbnail_lib.php (revision 2691)
+++ /trunk/php/lib/thumbnail_lib.php (revision 3082)
@@ -56,5 +56,5 @@
     }
 
-    function _make_dest_name ($w, $h, $format, $dest_type) {
+    function _make_dest_name ($w, $h, $format, $dest_type, $id) {
         $output = $this->src_type;
         if ($dest_type != 'auto') {
@@ -82,9 +82,11 @@
         $patterns[1] = '/%h/';
         $patterns[2] = '/%f/';
-        $patterns[3] = '/%x/';
+        $patterns[3] = '/%i/';
+        $patterns[4] = '/%x/';
         $replacement[0] = $w;
         $replacement[1] = $h;
         $replacement[2] = $basename;
-        $replacement[3] = $ext;
+        $replacement[3] = $id;
+        $replacement[4] = $ext;
 
         return preg_replace($patterns, $replacement, $format);
@@ -92,5 +94,5 @@
 
     # Load or generate a thumbnail.
-    function get_thumbnail (&$dest, &$width, &$height, $scale = 0, $format = '%f-thumb-%wx%h%x', $dest_type = 'auto') {
+    function get_thumbnail (&$dest, &$width, &$height, $id, $scale = 0, $format = '%f-thumb-%wx%h-%i%x', $dest_type = 'auto') {
         if (empty($this->src_file)) return false;
         if (!file_exists($this->src_file)) return false;
@@ -130,5 +132,5 @@
         # Decide a destination file name
         if (empty($dest)) {
-            $dest = $this->_make_dest_name($thumb_w_name, $thumb_h_name, $format, $dest_type);
+            $dest = $this->_make_dest_name($thumb_w_name, $thumb_h_name, $format, $dest_type, $id);
         }
 
Index: /trunk/php/lib/modifier.setvar.php
===================================================================
--- /trunk/php/lib/modifier.setvar.php (revision 1174)
+++ /trunk/php/lib/modifier.setvar.php (revision 3082)
@@ -9,7 +9,10 @@
     global $mt;
     $ctx =& $mt->context();
-    $vars =& $ctx->__stash['vars'];
+    if (array_key_exists('__inside_set_hashvar', $ctx->__stash)) {
+        $vars =& $ctx->__stash['__inside_set_hashvar'];
+    } else {
+        $vars =& $ctx->__stash['vars'];
+    }
     $vars[$name] = $text;
     return '';
 }
-?>
Index: /trunk/php/lib/MTUtil.php
===================================================================
--- /trunk/php/lib/MTUtil.php (revision 3034)
+++ /trunk/php/lib/MTUtil.php (revision 3082)
@@ -1301,5 +1301,5 @@
     $dest;
     $thumb_name = $static_file_path.DIRECTORY_SEPARATOR.$image_path.DIRECTORY_SEPARATOR.$format;
-    if (!$thumb->get_thumbnail($dest, $thumb_w, $thumb_h, $scale, $thumb_name, 'png')) {
+    if (!$thumb->get_thumbnail($dest, $thumb_w, $thumb_h, $asset['asset_id'], $scale, $thumb_name, 'png')) {
         return '';
     }
@@ -1314,5 +1314,5 @@
 
 # for compatibility...
-function make_thumbnail_file($src, $dest, $width, $height, $scale = 0, $dest_type = 'auto') {
+function make_thumbnail_file($src, $dest, $width, $height, $scale = 0, $dest_type = 'auto', $id = 0) {
     require_once('thumbnail_lib.php');
     $thumb = new Thumbnail($src);
@@ -1320,10 +1320,10 @@
     $thumb_w = $width;
     $thumb_h = $height;
-    $thumb->get_thumbnail($dest, $thumb_w, $thumb_h, $scale, null, $dest_type);
+    $thumb->get_thumbnail($dest, $thumb_w, $thumb_h, $id, $scale, null, $dest_type);
 
     return array($thumb_w, $thumb_h);
 }
 
-function get_thumbnail_file($asset, $blog, $width = 0, $height = 0, $scale = 0, $format = '%f-thumb-%wx%h%x') {
+function get_thumbnail_file($asset, $blog, $width = 0, $height = 0, $scale = 0, $format = '%f-thumb-%wx%h-%i%x') {
     # Get parameter
     $site_path = $blog['blog_site_path'];
@@ -1338,7 +1338,13 @@
     $ts = preg_replace('![^0-9]!', '', $asset['asset_created_on']);
     $date_stamp = format_ts('%Y/%m', $ts, $blog);
-    $cache_dir = $site_path . DIRECTORY_SEPARATOR . $cache_path . DIRECTORY_SEPARATOR . $date_stamp . DIRECTORY_SEPARATOR;
+    $base_path = $site_path;
+    if (preg_match('/^%a/', $asset['asset_file_path']) && !empty($blog['blog_archive_path'])) {
+        $base_path = $blog['blog_archive_path'];
+        $base_path = preg_replace('/\/$/', '', $base_path);
+    }
+
+    $cache_dir = $base_path . DIRECTORY_SEPARATOR . $cache_path . DIRECTORY_SEPARATOR . $date_stamp . DIRECTORY_SEPARATOR;
     $thumb_name = $cache_dir . $format;
- 
+
     # generate thumbnail
     require_once('thumbnail_lib.php');
@@ -1347,5 +1353,5 @@
     $thumb_h = $height;
     $dest;
-    if (!$thumb->get_thumbnail($dest, $thumb_w, $thumb_h, $scale, $thumb_name)) {
+    if (!$thumb->get_thumbnail($dest, $thumb_w, $thumb_h, $asset['asset_id'], $scale, $thumb_name)) {
         return '';
     }
@@ -1353,9 +1359,11 @@
     # make url
     $basename = basename($dest);
-    $site_url = $blog['blog_site_url'];
-    if (!preg_match('!/$!', $site_url))
-        $site_url .= '/';
-
-    $thumb_url = $site_url . $cache_path . '/' . $date_stamp . '/' . $basename;
+    $base_url = $blog['blog_site_url'];
+    if (preg_match('/^%a/', $asset['asset_file_path']) && !empty($blog['blog_archive_url']))
+        $base_url = $blog['blog_archive_url'];
+    if (!preg_match('!/$!', $base_url))
+        $base_url .= '/';
+
+    $thumb_url = $base_url . $cache_path . '/' . $date_stamp . '/' . $basename;
 
     return array($thumb_url, $thumb_w, $thumb_h, $thumb_name);
Index: /trunk/php/mt.php
===================================================================
--- /trunk/php/mt.php (revision 3019)
+++ /trunk/php/mt.php (revision 3082)
@@ -10,5 +10,5 @@
 define('PRODUCT_VERSION', '4.21');
 
-$PRODUCT_NAME = '__PRODUCT_NAME__';
+$PRODUCT_NAME = 'Movable Type Pro';
 if($PRODUCT_NAME == '__PRODUCT' . '_NAME__')
     $PRODUCT_NAME = 'Movable Type';
Index: /trunk/lib/MT/Asset/Image.pm
===================================================================
--- /trunk/lib/MT/Asset/Image.pm (revision 2635)
+++ /trunk/lib/MT/Asset/Image.pm (revision 3082)
@@ -231,5 +231,5 @@
 
     require MT::Util;
-    my $format = $param{Format} || MT->translate('%f-thumb-%wx%h%x');
+    my $format = $param{Format} || MT->translate('%f-thumb-%wx%h-%i%x');
     my $width  = $param{Width}  || 'auto';
     my $height = $param{Height} || 'auto';
@@ -550,4 +550,5 @@
                     $app->translate( "Invalid basename '[_1]'", $rel_path ) );
             }
+            $rel_path .= '-' . $asset->id;
             my $ext = $blog->file_extension || '';
             $ext = '.' . $ext if $ext ne '';
@@ -567,13 +568,5 @@
               File::Spec->catfile( $root_path, $rel_path . $ext );
 
-            ## If the popup filename already exists, we don't want to overwrite
-            ## it, because it could contain valuable data; so we'll just make
-            ## sure to generate the name uniquely.
             my ( $i, $rel_path_ext ) = ( 0, $rel_path . $ext );
-            while ( $fmgr->exists($abs_file_path) ) {
-                $rel_path_ext = $rel_path . ++$i . $ext;
-                $abs_file_path =
-                  File::Spec->catfile( $root_path, $rel_path_ext );
-            }
             $pseudo_path = File::Spec->catfile( $pseudo_path, $rel_path_ext );
             my ( $vol, $dirs, $basename ) =
@@ -600,5 +593,7 @@
                 $original   = $asset_html->clone;
                 $asset_html->blog_id($blog_id);
-                $asset_html->url($pseudo_path);
+                my $pseudo_url = $pseudo_path;
+                $pseudo_url  =~ s!\\!/!g;
+                $asset_html->url($pseudo_url);
                 $asset_html->label($app->translate("Popup Page for [_1]", $asset->label || $asset->file_name));
                 $asset_html->file_path($pseudo_path);
@@ -610,5 +605,5 @@
             } else {
                 $original   = $asset_html->clone;
-            }                
+            }
 
             # Select back the real URL for callbacks
Index: /trunk/lib/MT/Upgrade/v4.pm
===================================================================
--- /trunk/lib/MT/Upgrade/v4.pm (revision 3014)
+++ /trunk/lib/MT/Upgrade/v4.pm (revision 3082)
@@ -350,35 +350,5 @@
             version_limit => 4.0047,
             priority      => 3.2,
-            updater       => {
-                type      => 'entry',
-                label     => 'Assigning entry comment and TrackBack counts...',
-                condition => sub {
-                    require MT::Comment;
-                    my $comment_count = MT::Comment->count(
-                        {
-                            entry_id => $_[0]->id,
-                            visible  => 1,
-                        }
-                    );
-                    $_[0]->comment_count($comment_count);
-                    require MT::Trackback;
-                    require MT::TBPing;
-                    my $tb = MT::Trackback->load( { entry_id => $_[0]->id } );
-                    my $ping_count;
-                    if ($tb) {
-                        my $ping_count = MT::TBPing->count(
-                            {
-                                tb_id   => $tb->id,
-                                visible => 1,
-                            }
-                        );
-                        $_[0]->ping_count($ping_count);
-                    }
-                    ( $comment_count || $ping_count );
-                },
-                # only count once and set it, so code do nothing.
-                # it doesn't have the unnecessary save.
-                code => sub { 1; },
-            },
+            code          => \&core_update_entry_counts,
         },
         'core_assign_object_embedded' => {
@@ -490,34 +460,4 @@
                     $file_template =~ s/%-C/<MTCategoryLabel dirify="-">/g;
                     $map->file_template($file_template);
-                },
-            },
-        },
-        'core_assign_all_permisssions_blog_admin' => {
-            version_limit => 4.0063,
-            priority => 3.4,
-            updater => {
-                type => 'permission',
-                label => 'Assigning all permissions to blog administrator...',
-                condition => sub {
-                    $_[0]->can_administer_blog && $_[0]->blog_id;
-                },
-                code => sub {
-                    my ($perm) = shift;
-                    $perm->set_full_permissions;
-                },
-            },
-        },
-        'core_recover_sysadmin_permissions' => {
-            version_limit => 4.0066,
-            priority => 3.5,
-            updater => {
-                type => 'permission',
-                label => 'Recover permissions of system administrators...',
-                condition => sub {
-                    !$_[0]->blog_id && !$_[0]->has('administer') && $_[0]->can_administer_blog;
-                },
-                code => sub {
-                    my ($perm) = shift;
-                    $perm->set_permissions('system');
                 },
             },
@@ -1062,4 +1002,6 @@
         'limit'      => 101,
         'fetchonly' => [ 'id' ],  # meta is added to the select list separately
+        'sort'      => 'id',
+        'direction' => 'ascend',
         $offset ? ( 'offset' => $offset ) : ()
     };
@@ -1188,3 +1130,90 @@
 }
 
+sub core_update_entry_counts {
+    my $self = shift;
+    my (%param) = @_;
+
+    my $class = MT->model('entry');
+    return $self->error($self->translate_escape("Error loading class: [_1].", $param{type}))
+        unless $class;
+
+    my $msg = $self->translate_escape("Assigning entry comment and TrackBack counts...");
+    my $offset = $param{offset} || 0;
+    my $count = $param{count};
+    if (!$count) {
+        $count = $class->count({ class => '*' });
+    }
+    return unless $count;
+    if ($offset) {
+        $self->progress(sprintf("$msg (%d%%)", ($offset/$count*100)), $param{step});
+    } else {
+        $self->progress($msg, $param{step});
+    }
+
+    my $continue = 0;
+    my $driver = $class->driver;
+
+    my $iter = $class->load_iter({ class => '*' }, { offset => $offset, limit => $MAX_ROWS+1 });
+    my $start = time;
+    my ( %touched, %c, %tb );
+    my $rows = 0;
+    while (my $e = $iter->()) {
+        $rows++;
+        $c{$e->id} = $e;
+        if (my $tb = $e->trackback) {
+            $tb{$tb->id} = $e;
+        }
+        $continue = 1, last if scalar $rows == $MAX_ROWS;
+    }
+    if ( $continue ) {
+        $iter->end;
+        $offset += $rows;
+    }
+
+    # now gather counts -- comments
+    if (my $grp_iter = MT::Comment->count_group_by({
+        visible => 1,
+        entry_id => [ keys %c ],
+    }, {
+        group => ['entry_id'],
+    })) {
+        while (my ($count, $id) = $grp_iter->()) {
+            my $e = $c{$id} or next;
+            if ((!defined $e->comment_count) || (($e->comment_count || 0) != $count)) {
+                $e->comment_count($count);
+                $touched{$e->id} = $e;
+            }
+        }
+    }
+
+    # pings
+    if ( %tb ) {
+        if (my $grp_iter = MT::TBPing->count_group_by({
+            visible => 1,
+            tb_id => [ keys %tb ],
+        }, {
+            group => ['tb_id'],
+        })) {
+            while (my ($count, $id) = $grp_iter->()) {
+                my $e = $tb{$id} or next;
+                if ((!defined $e->ping_count) || (($e->ping_count || 0) != $count)) {
+                    $e->ping_count($count);
+                    $touched{$e->id} = $e;
+                }
+            }
+        }
+    }
+
+    foreach my $e (values %touched) {
+        $e->save;
+    }
+
+    if ($continue) {
+        return { offset => $offset, count => $count };
+    } else {
+        $self->progress("$msg (100%)", $param{step});
+    }
+    1;
+}
+
 1;
Index: /trunk/lib/MT/Upgrade.pm
===================================================================
--- /trunk/lib/MT/Upgrade.pm (revision 3013)
+++ /trunk/lib/MT/Upgrade.pm (revision 3082)
@@ -166,5 +166,10 @@
         $code = MT->handler_to_coderef($code);
         my $result = $code->($self, %param, %update_params, step => $name);
-        if ((defined $result) && ($result > 1)) {
+        if (ref $result eq 'HASH') {
+            $param{$_} = $result->{$_} for keys %$result;
+            $result = 1;
+            $self->add_step($name, %param);
+        }
+        elsif ((defined $result) && ($result > 1)) {
             $param{offset} = $result; $result = 1;
             $self->add_step($name, %param);
@@ -216,4 +221,5 @@
         my $fn = \%MT::Upgrade::functions;
         my @these_steps = @steps;
+
         while (@these_steps) {
             my $step = shift @these_steps;
@@ -225,4 +231,9 @@
                                       $fn->{$b->[0]}->{priority} } @these_steps;
             }
+
+            # Reset the request to eliminate any caching that may be
+            # happening there (objects tend to cache into the request
+            # with the 'cache_property' method)
+            MT->request->reset;
         }
         return 1;
@@ -838,4 +849,91 @@
 }
 
+sub core_update_entry_counts {
+    my $self = shift;
+    my (%param) = @_;
+
+    my $class = MT->model('entry');
+    return $self->error($self->translate_escape("Error loading class: [_1].", $param{type}))
+        unless $class;
+
+    my $msg = $self->translate_escape("Assigning entry comment and TrackBack counts...");
+    my $offset = $param{offset} || 0;
+    my $count = $param{count};
+    if (!$count) {
+        $count = $class->count({ class => '*' });
+    }
+    return unless $count;
+    if ($offset) {
+        $self->progress(sprintf("$msg (%d%%)", ($offset/$count*100)), $param{step});
+    } else {
+        $self->progress($msg, $param{step});
+    }
+
+    my $continue = 0;
+    my $driver = $class->driver;
+
+    my $iter = $class->load_iter({ class => '*' }, { offset => $offset, limit => $MAX_ROWS+1 });
+    my $start = time;
+    my ( %touched, %c, %tb );
+    my $rows = 0;
+    while (my $e = $iter->()) {
+        $rows++;
+        $c{$e->id} = $e;
+        if (my $tb = $e->trackback) {
+            $tb{$tb->id} = $e;
+        }
+        $continue = 1, last if scalar $rows == $MAX_ROWS;
+    }
+    if ( $continue ) {
+        $iter->end;
+        $offset += $rows;
+    }
+
+    # now gather counts -- comments
+    if (my $grp_iter = MT::Comment->count_group_by({
+        visible => 1,
+        entry_id => [ keys %c ],
+    }, {
+        group => ['entry_id'],
+    })) {
+        while (my ($count, $id) = $grp_iter->()) {
+            my $e = $c{$id} or next;
+            if ((!defined $e->comment_count) || (($e->comment_count || 0) != $count)) {
+                $e->comment_count($count);
+                $touched{$e->id} = $e;
+            }
+        }
+    }
+
+    # pings
+    if ( %tb ) {
+        if (my $grp_iter = MT::TBPing->count_group_by({
+            visible => 1,
+            tb_id => [ keys %tb ],
+        }, {
+            group => ['tb_id'],
+        })) {
+            while (my ($count, $id) = $grp_iter->()) {
+                my $e = $tb{$id} or next;
+                if ((!defined $e->ping_count) || (($e->ping_count || 0) != $count)) {
+                    $e->ping_count($count);
+                    $touched{$e->id} = $e;
+                }
+            }
+        }
+    }
+
+    foreach my $e (values %touched) {
+        $e->save;
+    }
+
+    if ($continue) {
+        return { offset => $offset, count => $count };
+    } else {
+        $self->progress("$msg (100%)", $param{step});
+    }
+    1;
+}
+
 sub core_update_records {
     my $self = shift;
@@ -858,7 +956,10 @@
     }
     my $offset = $param{offset};
+    my $count = $param{count};
+    if (!$count) {
+        $count = $class->count;
+    }
+    return unless $count;
     if ($offset) {
-        my $count = $class->count;
-        return unless $count;
         $self->progress(sprintf("$msg (%d%%)", ($offset/$count*100)), $param{step});
     } else {
@@ -893,12 +994,11 @@
             }
             $code->($obj);
-            use Data::Dumper;
             $obj->save()
-                or return $self->error($self->translate_escape("Error saving [_1] record # [_3]: [_2]... [_4].", $class_label, $obj->errstr, $obj->id, Dumper($obj)));
+                or return $self->error($self->translate_escape("Error saving [_1] record # [_3]: [_2]...", $class_label, $obj->errstr, $obj->id));
             $continue = 1, last if time > $start + $MAX_TIME;
         }
     }
     if ($continue) {
-        return $offset;
+        return { offset => $offset, count => $count };
     } else {
         $self->progress("$msg (100%)", $param{step});
Index: /trunk/lib/MT/TemplateMap.pm
===================================================================
--- /trunk/lib/MT/TemplateMap.pm (revision 2966)
+++ /trunk/lib/MT/TemplateMap.pm (revision 3082)
@@ -107,4 +107,8 @@
             }
         }
+        elsif ( $_[0] && $_[0]->{blog_id} ) {
+            # for cases where we remove with a blog_id parameter
+            $blog_id = $_[0]->{blog_id};
+        }
 
         my $maps_iter = MT::TemplateMap->count_group_by(
Index: /trunk/lib/MT/Blog.pm
===================================================================
--- /trunk/lib/MT/Blog.pm (revision 2606)
+++ /trunk/lib/MT/Blog.pm (revision 3082)
@@ -870,6 +870,6 @@
         );
         while (my $tmpl = $iter->()) {
+            my @old_widgets = split /,/, $tmpl->modulesets;
             $tmpl_processor->($new_blog_id, \$counter, $tmpl, \%tmpl_map);
-            my @old_widgets = split /,/, $tmpl->modulesets;
             my @new_widgets;
             push @new_widgets, $tmpl_map{$_}
Index: /trunk/lib/MT/L10N/ja.pm
===================================================================
--- /trunk/lib/MT/L10N/ja.pm (revision 2923)
+++ /trunk/lib/MT/L10N/ja.pm (revision 3082)
@@ -730,5 +730,5 @@
 	'Error converting image: [_1]' => 'ç»åãå€æã§ããŸããã§ãã: [_1]',
 	'Error creating thumbnail file: [_1]' => 'ãµã ããŒã«ãäœæã§ããŸããã§ãã: [_1]',
-	'%f-thumb-%wx%h%x' => '%f-thumb-%wx%h%x',
+	'%f-thumb-%wx%h-%i%x' => '%f-thumb-%wx%h-%i%x',
 	'Can\'t load image #[_1]' => 'ID:[_1]ã®ç»åãã­ãŒãã§ããŸããã§ããã',
 	'View image' => 'è¡šç€º',
@@ -852,4 +852,5 @@
 	'Writing to \'[_1]\' failed: [_2]' => '\'[_1]\'ã«æžãèŸŒããŸããã§ãã: [_2]',
 	'Renaming tempfile \'[_1]\' failed: [_2]' => 'ãã³ãã©ãªãã¡ã€ã«\'[_1]\'ã®ååãå€æŽã§ããŸããã§ãã: [_2]',
+	'Blog, BlogID or Template param must be specified.' => 'Blog, BlogID, ãŸãã¯Templateã®ãããããæå®ããŠãã ããã',
 	'Template \'[_1]\' does not have an Output File.' => 'ãã³ãã¬ãŒã\'[_1]\'ã«ã¯åºåãã¡ã€ã«ã®èš­å®ããããŸããã',
 	'An error occurred while publishing scheduled entries: [_1]' => 'æ¥ææå®ããããã­ã°èšäºã®åæ§ç¯äž­ã«ãšã©ãŒãçºçããŸãã: [_1]',
@@ -1139,6 +1140,4 @@
 	'IP Banning' => 'IPçŠæ­¢ãªã¹ã',
 	'Removing tag failed: [_1]' => 'ã¿ã°ãåé€ã§ããŸããã§ãã: [_1]',
-	'You can\'t delete that category because it has sub-categories. Move or delete the sub-categories first if you want to delete this one.' => 'ãµãã«ããŽãªã®ããã«ããŽãªã¯åé€ã§ããŸããããµãã«ããŽãªãå
-ã«åé€ããããç§»åããŠãã ããã',
 	'Loading MT::LDAP failed: [_1].' => 'MT::LDAPã®èª­ã¿èŸŒã¿ã«å€±æããŸãã: [_1]',
 	'System templates can not be deleted.' => 'ã·ã¹ãã ãã³ãã¬ãŒãã¯åé€ã§ããŸããã',
@@ -1874,5 +1873,6 @@
 	'Mapping template ID [_1] to [_2].' => 'ãã³ãã¬ãŒã(ID:[_1])ã[_2]ã«ãããã³ã°ããŠããŸã...',
 	'Error loading class: [_1].' => 'ã¯ã©ã¹ãã­ãŒãã§ããŸããã§ãã: [_1]',
-	'Error saving [_1] record # [_3]: [_2]... [_4].' => '[_1](ID: [_3])ã®ä¿å­äž­ã«ãšã©ãŒãçºçããŸãã: [_2]... [_4]',
+	'Assigning entry comment and TrackBack counts...' => 'ã³ã¡ã³ããšãã©ãã¯ããã¯ã®ä»¶æ°ãèš­å®ããŠããŸã....',
+	'Error saving [_1] record # [_3]: [_2]...' => '[_1]ã®ã¬ã³ãŒã(ID:[_3])ãä¿å­ã§ããŸããã§ãã: [_2]',
 	'Creating entry category placements...' => 'ãã­ã°èšäºãšã«ããŽãªã®é¢é£ä»ããäœæããŠããŸã...',
 	'Updating category placements...' => 'ã«ããŽãªã®é¢é£ä»ããæŽæ°ããŠããŸã...',
@@ -1926,5 +1926,4 @@
 	'Assigning blog page layout...' => 'ãã­ã°ã«ããŒãžã¬ã€ã¢ãŠããèš­å®ããŠããŸã...',
 	'Assigning author basename...' => 'ãŠãŒã¶ãŒã«ããŒã¹ããŒã ãèš­å®ããŠããŸã...',
-	'Assigning entry comment and TrackBack counts...' => 'ã³ã¡ã³ããšãã©ãã¯ããã¯ã®ä»¶æ°ãèš­å®ããŠããŸã....',
 	'Assigning embedded flag to asset placements...' => 'ã¢ã€ãã ã®é¢é£ä»ãã®æç¡ãèš­å®ããŠããŸã...',
 	'Updating template build types...' => 'ãã³ãã¬ãŒãã®ãã«ããªãã·ã§ã³ãèš­å®ããŠããŸã...',
@@ -2105,6 +2104,4 @@
 ¥å',
 	'Batch Edit Entries' => 'ãã­ã°èšäºã®äžæ¬ç·šé',
-	'Publish Pages' => 'ãŠã§ãããŒãžãå
-¬é',
 	'Unpublish Pages' => 'ãŠã§ãããŒãžã®å
 ¬éãåãæ¶ã',
@@ -2152,5 +2149,4 @@
 	'Comments in the last 7 days' => 'æè¿7æ¥éä»¥å
 ã®ã³ã¡ã³ã',
-	'E-mail Templates' => 'ã¡ãŒã«ãã³ãã¬ãŒã',
 	'Tags with entries' => 'ãã­ã°èšäºã®ã¿ã°',
 	'Tags with pages' => 'ãŠã§ãããŒãžã®ã¿ã°',
@@ -3794,4 +3790,8 @@
 	'You must set a valid Site URL.' => 'æå¹ãªãµã€ãURLãæå®ããŠãã ããã',
 	'You must set a valid Local Site Path.' => 'æå¹ãªãµã€ããã¹ãæå®ããŠãã ããã',
+	'You must set Local Archive Path.' => 'ã¢ãŒã«ã€ããã¹ãæå®ããå¿
+èŠããããŸãã',
+	'You must set a valid Archive URL.' => 'æå¹ãªã¢ãŒã«ã€ãURLãæå®ããŠãã ããã',
+	'You must set a valid Local Archive Path.' => 'æå¹ãªã¢ãŒã«ã€ããã¹ãæå®ããŠãã ããã',
 	'Publishing Paths' => 'å
 ¬éãã¹',
Index: /trunk/lib/MT/CMS/Asset.pm
===================================================================
--- /trunk/lib/MT/CMS/Asset.pm (revision 2802)
+++ /trunk/lib/MT/CMS/Asset.pm (revision 3082)
@@ -151,5 +151,5 @@
             push @blog_ids, $_->blog_id
               foreach grep { $_->can_edit_assets } @perms;
-            $terms{blog_id} = \@blog_ids;
+            $terms{blog_id} = @blog_ids ? \@blog_ids : 0;
         }
     }
Index: /trunk/lib/MT/CMS/Blog.pm
===================================================================
--- /trunk/lib/MT/CMS/Blog.pm (revision 3001)
+++ /trunk/lib/MT/CMS/Blog.pm (revision 3082)
@@ -532,5 +532,5 @@
     my $type = $app->param('_type') || 'entry';
     my @ids  = $app->param('id');
-    $app->{goback} = "window.location='" . $app->return_uri . "'";
+    $app->{goback} = $app->return_uri;
     $app->{value} ||= $app->translate('Go Back');
     if ( $type eq 'entry' ) {
@@ -611,7 +611,5 @@
                 $edit_type = $entry ? $entry->class : 'entry';
             }
-            $app->{goback} =
-              "window.location='"
-              . $app->object_edit_uri( $edit_type, $obj_id ) . "'";
+            $app->{goback} = $app->object_edit_uri( $edit_type, $obj_id );
             $app->{value} ||= $app->translate('Go Back');
         }
@@ -691,8 +689,20 @@
     elsif ($type) {
         my $special = 0;
-        my @options = $app->{rebuild_options} ||= {};
+        my @options;
+        my $opts = $app->registry("rebuild_options") || {};
+        if ($opts) {
+            foreach my $opt ( keys %$opts ) {
+                $opts->{$opt}{key} ||= $opt;
+                push @options, $opts->{$opt};
+            }
+        }
         $app->run_callbacks( 'rebuild_options', $app, \@options );
         for my $optn (@options) {
             if ( ( $optn->{key} || '' ) eq $type ) {
+                my $code = $optn->{code};
+                unless ( ref($code) eq 'CODE' ) {
+                    $code = MT->handler_to_coderef($code);
+                    $optn->{code} = $code;
+                }
                 $optn->{code}->();
                 $special = 1;
Index: /trunk/lib/MT/CMS/Dashboard.pm
===================================================================
--- /trunk/lib/MT/CMS/Dashboard.pm (revision 2812)
+++ /trunk/lib/MT/CMS/Dashboard.pm (revision 3082)
@@ -404,24 +404,35 @@
 
     my $terms = {};
+    my $args = {};
     $terms->{blog_id} = $blog_id if $blog_id;
     $terms->{object_datasource} = 'entry';
-    my $args = {};
     $args->{group} = [ 'tag_id' ];
     $args->{sort} = '1'; # sort by count(*)
     $args->{direction} = 'descend';
     $args->{limit} = 100;
+    $args->{join} = MT::Tag->join_on(undef, { id => \'= objecttag_tag_id', is_private => 1 },
+        { not => { is_private => 1 } } );
 
     my $iter = $app->model('objecttag')->count_group_by($terms, $args);
     my @tag_loop;
+    my @tag_ids;
     my $ntags = 0;
     my $min = undef;
     my $max = undef;
     while (my ($count, $tag_id) = $iter->()) {
-        my $tag = MT::Tag->load($tag_id) or next;
-        next if $tag->is_private; # weed these from the dashboard
         $ntags += $count;
         $min = defined $min ? ($count < $min ? $count : $min) : $count;
         $max = defined $max ? ($count > $max ? $count : $max) : $count;
-        push @tag_loop, { name => $tag->name, count => $count };
+        push @tag_loop, { id => $tag_id, count => $count };
+        push @tag_ids, $tag_id;
+    }
+
+    if ( @tag_ids ) {
+        my $iter = MT::Tag->load_iter( { id => \@tag_ids } );
+        my %tags;
+        while ( my $t = $iter->() ) {
+            $tags{ $t->id } = $t->name;
+        }
+        $_->{name} = $tags{$_->{id}} for @tag_loop;
     }
 
Index: /trunk/lib/MT/CMS/Common.pm
===================================================================
--- /trunk/lib/MT/CMS/Common.pm (revision 3039)
+++ /trunk/lib/MT/CMS/Common.pm (revision 3082)
@@ -961,8 +961,4 @@
         }
         elsif ( $type eq 'category' ) {
-            my @kids = MT::Category->load( { parent => $id } );
-            return $app->errtrans(
-"You can't delete that category because it has sub-categories. Move or delete the sub-categories first if you want to delete this one."
-            ) if @kids;
             if ( $app->config('DeleteFilesAtRebuild') ) {
                 require MT::Blog;
Index: /trunk/lib/MT/CMS/Entry.pm
===================================================================
--- /trunk/lib/MT/CMS/Entry.pm (revision 2994)
+++ /trunk/lib/MT/CMS/Entry.pm (revision 3082)
@@ -676,5 +676,9 @@
     $param{list_filters}        = $app->list_filters('entry');
     $param{can_power_edit}      = $blog_id && !$is_power_edit;
-    $param{can_republish}       = $blog_id ? $perms->can_rebuild : 1;
+    $param{can_republish}       = $blog_id
+                                    ? $perms->can_rebuild
+                                    : $app->user->is_superuser
+                                        ? 1
+                                        : 0;
     $param{is_power_edit}       = $is_power_edit;
     $param{saved_deleted}       = $q->param('saved_deleted');
@@ -1058,5 +1062,5 @@
 
     my $class = $app->model($type)
-      or retrun $app->errtrans("Invalid parameter");
+      or return $app->errtrans("Invalid parameter");
 
     my $cat_class = $app->model( $class->container_type );
Index: /trunk/lib/MT/ObjectDriver/Driver/DBI.pm
===================================================================
--- /trunk/lib/MT/ObjectDriver/Driver/DBI.pm (revision 2664)
+++ /trunk/lib/MT/ObjectDriver/Driver/DBI.pm (revision 3082)
@@ -580,5 +580,5 @@
 =item * post_group_by
 
-    callback($class, \$value, \@retrunvals)
+    callback($class, \$value, \@returnvals)
 
 Callback issued prior to returning the number and additional return
Index: /trunk/lib/MT/Tag.pm
===================================================================
--- /trunk/lib/MT/Tag.pm (revision 2632)
+++ /trunk/lib/MT/Tag.pm (revision 3082)
@@ -176,5 +176,9 @@
         object_datasource => $datasource
     }, { unique => 1, %jargs });
-    my @tags = MT::Tag->load($terms, $args);
+    my @tags;
+    my $iter = MT::Tag->load_iter($terms, $args);
+    while ( my $tag = $iter->() ) {
+        push @tags, $tag;
+    }
     @tags;
 }
@@ -335,9 +339,12 @@
     } else {
         require MT::ObjectTag;
-        @tags = MT::Tag->search(undef, {  
+        my $iter = MT::Tag->load_iter(undef, {
             sort => 'name',  
             join => [ 'MT::ObjectTag', 'tag_id', { object_id => $obj->id,
                 object_datasource => $obj->datasource }, { unique => 1 } ],       
         });
+        while ( my $tag = $iter->() ) {
+            push @tags, $tag;
+        }
         $cache->set($memkey, [ map { $_->id } @tags ], TAG_CACHE_TIME);
     }
Index: /trunk/lib/MT/App.pm
===================================================================
--- /trunk/lib/MT/App.pm (revision 3017)
+++ /trunk/lib/MT/App.pm (revision 3082)
@@ -2420,10 +2420,10 @@
     if ( $type eq 'dialog' ) {
         $param->{name}   ||= $app->{name}   || 'dialog';
-        $param->{goback} ||= $app->{goback} || 'closeDialog()';
+        $param->{goback} ||= "window.location='" . $app->{goback} . "'" || 'closeDialog()';
         $param->{value}  ||= $app->{value}  || $app->translate("Close");
         $param->{dialog} = 1;
     }
     else {
-        $param->{goback} ||= $app->{goback} || 'history.back()';
+        $param->{goback} ||= "window.location='" . $app->{goback} . "'" || 'history.back()';
         $param->{value}  ||= $app->{value}  || $app->translate("Go Back");
     }
Index: /trunk/lib/MT/Template/Context.pm
===================================================================
--- /trunk/lib/MT/Template/Context.pm (revision 3035)
+++ /trunk/lib/MT/Template/Context.pm (revision 3082)
@@ -321,5 +321,5 @@
     # If no blog IDs specified, use the current blog
     if ( ! $blog_ids ) {
-        $terms->{$col} = $blog_id if $col eq 'blog_id';
+        $terms->{$col} = $blog_id if $blog_id && $col eq 'blog_id';
     } 
     # If exclude blogs, set the terms and the NOT arg for load
Index: /trunk/lib/MT/Template/ContextHandlers.pm
===================================================================
--- /trunk/lib/MT/Template/ContextHandlers.pm (revision 3062)
+++ /trunk/lib/MT/Template/ContextHandlers.pm (revision 3082)
@@ -721,5 +721,10 @@
 sub _fltr_setvar {
     my ($str, $arg, $ctx) = @_;
-    $ctx->var($arg, $str);
+    if ( my $hash = $ctx->{__inside_set_hashvar} ) {
+        $hash->{$arg} = $str;
+    }
+    else {
+        $ctx->var($arg, $str);
+    }
     return '';
 }
@@ -10144,5 +10149,5 @@
     unless (ref $blog) {
         my $blog_id = $blog || $args->{offset_blog_id};
-        if ($blog) {
+        if ($blog_id) {
             $blog = MT->model('blog')->load($blog_id);
             return $ctx->error( MT->translate( 'Can\'t load blog #[_1].', $blog_id ) )
@@ -10155,5 +10160,5 @@
         my($y, $mo, $d, $h, $m, $s) = $ts =~ /(\d\d\d\d)[^\d]?(\d\d)[^\d]?(\d\d)[^\d]?(\d\d)[^\d]?(\d\d)[^\d]?(\d\d)/;
         $mo--;
-        my $server_offset = $blog->server_offset;
+        my $server_offset = ($blog && $blog->server_offset) || MT->config->TimeOffset;
         if ((localtime (timelocal ($s, $m, $h, $d, $mo, $y )))[8]) {
             $server_offset += 1;
@@ -10173,5 +10178,5 @@
         my $tz = 'Z';
         unless ($args->{utc}) {
-            my $so = $blog->server_offset;
+            my $so = ($blog && $blog->server_offset) || MT->config->TimeOffset;
             my $partial_hour_offset = 60 * abs($so - int($so));
             if ($format eq 'rfc822') {
@@ -15948,5 +15953,5 @@
     if (my $ext = $args->{file_ext}) {
         my @exts = split(',', $args->{file_ext});
-        if (!$assets) {
+        if ($assets) {
             push @filters, sub { my $a = $_[0]->file_ext; grep(m/$a/, @exts) };
         } else {
Index: /trunk/lib/MT/App/Search.pm
===================================================================
--- /trunk/lib/MT/App/Search.pm (revision 2991)
+++ /trunk/lib/MT/App/Search.pm (revision 3082)
@@ -227,5 +227,5 @@
             else {
                 $blog_id =~ s/\D+//g;    # only numeric values.
-                $blog_list{$type}{$blog_id} = 1;
+                $blog_list{$type}{$blog_id} = 1 if $blog_id;
             }
         }
Index: /trunk/lib/MT/App/CMS.pm
===================================================================
--- /trunk/lib/MT/App/CMS.pm (revision 3039)
+++ /trunk/lib/MT/App/CMS.pm (revision 3082)
@@ -748,5 +748,5 @@
                 handler => sub {
                     my ( $terms, $args ) = @_;
-                    my $ts = time - 10 * 24 * 60 * 60;
+                    my $ts = time - 7 * 24 * 60 * 60;
                     $ts = epoch2ts( MT->app->blog, $ts );
                     $args->{join} = MT::Comment->join_on(
@@ -1050,77 +1050,4 @@
                     $terms->{created_on}            = [ $from, $to ];
                     $args->{range_incl}{created_on} = 1;
-                },
-            },
-        },
-        template => {
-            index_templates => {
-                label   => "Index Templates",
-                order   => 100,
-                handler => sub {
-                    my ( $terms, $args ) = @_;
-
-                    # FIXME: enumeration of types
-                    $terms->{type} = 'index';
-                },
-                condition => sub {
-                    $app->param('blog_id');
-                },
-            },
-            archive_templates => {
-                label   => "Archive Templates",
-                order   => 200,
-                handler => sub {
-                    my ( $terms, $args ) = @_;
-                    $terms->{type}
-                        = [ 'individual', 'page', 'archive', 'category' ];
-                },
-                condition => sub {
-                    $app->param('blog_id');
-                },
-            },
-            module_templates => {
-                label   => "Template Modules",
-                order   => 400,
-                handler => sub {
-                    my ($terms) = @_;
-                    $terms->{type} = 'custom';
-                },
-            },
-            email_templates => {
-                label   => "E-mail Templates",
-                order   => 300,
-                handler => sub {
-                    my ($terms) = @_;
-                    $terms->{type} = 'email';
-                },
-                condition => sub {
-                    !$app->param('blog_id');
-                },
-            },
-            system_templates => {
-                label   => "System Templates",
-                order   => 200,
-                handler => sub {
-                    my ($terms) = @_;
-                    my $scope;
-                    my $set;
-                    if ( my $blog_id = $app->param('blog_id') ) {
-                        my $blog = $app->model('blog')->load($blog_id);
-                        $set = $blog->template_set;
-                        $scope .= 'system';
-                    }
-                    else {
-                        $terms->{blog_id} = 0;
-                        $scope = 'global:system';
-                    }
-                    my @tmpl_path
-                        = ( $set && ( $set ne 'mt_blog' ) )
-                        ? ( "template_sets", $set, 'templates', $scope )
-                        : ( "default_templates", $scope );
-                    my $sys_tmpl = MT->registry(@tmpl_path) || {};
-                    $terms->{type} = [ keys %$sys_tmpl ];
-                },
-                condition => sub {
-                    $app->param('blog_id');
                 },
             },
@@ -2438,25 +2365,50 @@
 
             # this is the template that likely caused the rebuild error
-            push @{ $param->{button_loop} ||= [] },
-                {
-                link => $app->uri(
-                    mode => 'view',
-                    args => {
-                        blog_id => $tmpl->blog_id,
-                        '_type' => 'template',
-                        id      => $tmpl->id
+            my $tmpl_edit_link = $app->uri(
+                        mode => 'view',
+                        args => {
+                            blog_id => $tmpl->blog_id,
+                            '_type' => 'template',
+                            id      => $tmpl->id
+                        }
+                    );
+
+            if ( $app->param('fs') ) {
+                $param->{fs} = 1;
+                if ( exists $app->{goback} ) {
+                    $param->{goback} = "window.location='" . $app->{goback} . "'";
+                    if ( $tmpl_edit_link ne $app->{goback} ) {
+                        push @{ $param->{button_loop} ||= [] },
+                          {
+                            link => $tmpl_edit_link,
+                            label => $app->translate("Edit Template"),
+                          };
                     }
-                ),
-                label => $app->translate("Edit Template"),
-                };
-        }
-
-        my $blog_id = $app->param('blog_id');
-        my $url     = $app->uri(
-            mode => 'rebuild_confirm',
-            args => { blog_id => $blog_id }
-        );
-        $param->{goback} ||= qq{window.location='$url'};
-        $param->{value}  ||= $app->translate('Go Back');
+                }
+                else {
+                    $param->{goback} = "window.location='$tmpl_edit_link'";
+                }
+            }
+            else {
+                push @{ $param->{button_loop} ||= [] },
+                  {
+                    link => $tmpl_edit_link,
+                    label => $app->translate("Edit Template"),
+                  };
+            }
+        }
+
+        if ( !exists( $param->{goback} ) && exists( $app->{goback} ) ) {
+            $param->{goback} = "window.location='" . $app->{goback} . "'";
+        }
+        else {
+            my $blog_id = $app->param('blog_id');
+            my $url     = $app->uri(
+                mode => 'rebuild_confirm',
+                args => { blog_id => $blog_id }
+            );
+            $param->{goback} ||= qq{window.location='$url'};
+        }
+        $param->{value} ||= $app->{value} || $app->translate('Go Back');
     }
 
Index: /trunk/lib/MT/Template.pm
===================================================================
--- /trunk/lib/MT/Template.pm (revision 2973)
+++ /trunk/lib/MT/Template.pm (revision 3082)
@@ -335,5 +335,5 @@
     $obj->modulesets( join ',', @ids )
         if scalar @ids != scalar @inst;
-    $obj->text($text) if $text;
+    $obj->text($text);
     return $obj->SUPER::save;
 }
Index: /trunk/lib/MT/Permission.pm
===================================================================
--- /trunk/lib/MT/Permission.pm (revision 2099)
+++ /trunk/lib/MT/Permission.pm (revision 3082)
@@ -85,4 +85,18 @@
 }
 
+sub global_perms {
+    my $perm = shift;
+
+    return undef unless $perm->author_id;
+    return $perm unless $perm->blog_id;
+
+    $perm->cache_property(
+        'global_perms',
+        sub {
+            __PACKAGE__->load( { author_id => $perm->author_id, blog_id => 0 });
+        }
+    );
+}
+
 # Legend:
 # author_id || blog_id || permissions
@@ -289,11 +303,20 @@
                         && $author->is_superuser );
                     return 1
-                      if ( ( $set eq 'blog' )
+                      if ( ( $_[0]->blog_id )
                         && $_[0]->has('administer_blog') );
                 }
             }
+            # return negative if a restriction is present
             return undef
               if $_[0]->restrictions && $_[0]->restrictions =~ /'$perm'/i;
-            ( defined($cur_perm) && $cur_perm =~ /'$perm'/i ) ? 1 : undef;
+            # return positive if permission is set in this permission set
+            return 1 if defined($cur_perm) && $cur_perm =~ /'$perm'/i;
+            # test for global-level permission
+            return 1
+              if $_[0]->author_id
+              && $_[0]->blog_id
+              && $_[0]->global_perms
+              && $_[0]->global_perms->has($perm);
+            return undef;
         };
     }
Index: /trunk/lib/MT/WeblogPublisher.pm
===================================================================
--- /trunk/lib/MT/WeblogPublisher.pm (revision 3001)
+++ /trunk/lib/MT/WeblogPublisher.pm (revision 3082)
@@ -1416,6 +1416,9 @@
     require MT::Template::Context;
     require MT::Entry;
+
     my $blog;
-    unless ( $blog = $param{Blog} ) {
+    $blog = $param{Blog}
+        if defined $param{Blog};
+    if (!$blog && defined $param{BlogID}) {
         my $blog_id = $param{BlogID};
         $blog = MT::Blog->load($blog_id)
@@ -1428,7 +1431,13 @@
     }
     my $tmpl = $param{Template};
-    unless ($blog) {
+    if ($tmpl && (!$blog || $blog->id != $tmpl->blog_id)) {
         $blog = MT::Blog->load( $tmpl->blog_id );
     }
+
+    return $mt->error(
+        MT->translate(
+            "Blog, BlogID or Template param must be specified.")
+    ) unless $blog;
+
     return 1 if $blog->is_dynamic;
     my $iter;
Index: /trunk/lib/MT.pm
===================================================================
--- /trunk/lib/MT.pm (revision 3019)
+++ /trunk/lib/MT.pm (revision 3082)
@@ -32,7 +32,7 @@
     ( $VERSION, $SCHEMA_VERSION ) = ( '4.21', '4.0068' );
     ( $PRODUCT_NAME, $PRODUCT_CODE, $PRODUCT_VERSION, $VERSION_ID, $PORTAL_URL ) = (
-        '__PRODUCT_NAME__', 'MT',
+        'Movable Type Pro', 'MT',
         '4.21', '4.21',
-        '__PORTAL_URL__'
+        'http://www.sixapart.com/movabletype/'
     );
 
@@ -108,5 +108,5 @@
 
 sub build_id {
-    my $build_id = '__BUILD_ID__';
+    my $build_id = '-en-trunk-r3063-20081002';
     $build_id = '' if $build_id eq '__BUILD_' . 'ID__';
     return $build_id;
Index: /trunk/build/Build.pm
===================================================================
--- /trunk/build/Build.pm (revision 1681)
+++ /trunk/build/Build.pm (revision 3082)
@@ -152,5 +152,5 @@
     ($self->{'short-lang=s'} = $self->{'lang=s'}) =~ s/([a-z]{2})_[A-Z]{2}$/$1/o;
 
-    $self->{'pack=s'} ||= 'MT';
+    $self->{'pack=s'} ||= 'MTOS';
     $ENV{BUILD_PACKAGE}  = $self->{'pack=s'};
     $ENV{BUILD_LANGUAGE} = $self->{'lang=s'};
Index: /trunk/t/35-tags.dat
===================================================================
--- /trunk/t/35-tags.dat (revision 2696)
+++ /trunk/t/35-tags.dat (revision 3082)
@@ -323,17 +323,17 @@
 { "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetProperty property='description'$></MTAssets>", "e" : "This is a test photo."}, #271
 { "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetFileExt$></MTAssets>", "e" : "jpg"}, #272
-{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailURL width='160'$></MTAssets>", "e" : "http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-160xauto.jpg"}, #273
-{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailURL height='240'$></MTAssets>", "e" : "http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-autox240.jpg"}, #274
-{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailURL scale='75'$></MTAssets>", "e" : "http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-480x360.jpg"}, #275
+{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailURL width='160'$></MTAssets>", "e" : "http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-160xauto-1.jpg"}, #273
+{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailURL height='240'$></MTAssets>", "e" : "http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-autox240-1.jpg"}, #274
+{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailURL scale='75'$></MTAssets>", "e" : "http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-480x360-1.jpg"}, #275
 { "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetLink$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\">test.jpg</a>"}, #276
-{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-640x480.jpg\" width=\"640\" height=\"480\" alt=\"\" /></a>"}, #277
-{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink width='160'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-160xauto.jpg\" width=\"160\" height=\"120\" alt=\"\" /></a>"}, #278
-{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink height='240'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-autox240.jpg\" width=\"320\" height=\"240\" alt=\"\" /></a>"}, #279
-{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink scale='100'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-640x480.jpg\" width=\"640\" height=\"480\" alt=\"\" /></a>"}, #280
+{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-640x480-1.jpg\" width=\"640\" height=\"480\" alt=\"\" /></a>"}, #277
+{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink width='160'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-160xauto-1.jpg\" width=\"160\" height=\"120\" alt=\"\" /></a>"}, #278
+{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink height='240'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-autox240-1.jpg\" width=\"320\" height=\"240\" alt=\"\" /></a>"}, #279
+{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink scale='100'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-640x480-1.jpg\" width=\"640\" height=\"480\" alt=\"\" /></a>"}, #280
 { "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetLink new_window='1'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\" target=\"_blank\">test.jpg</a>"}, #281
-{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink new_window='1'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\" target=\"_blank\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-640x480.jpg\" width=\"640\" height=\"480\" alt=\"\" /></a>"}, #282
-{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink new_window='1' width='160'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\" target=\"_blank\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-160xauto.jpg\" width=\"160\" height=\"120\" alt=\"\" /></a>"}, #283
-{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink new_window='1' scale='100'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\" target=\"_blank\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-640x480.jpg\" width=\"640\" height=\"480\" alt=\"\" /></a>"}, #284
-{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink new_window='1' scale='100'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\" target=\"_blank\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-640x480.jpg\" width=\"640\" height=\"480\" alt=\"\" /></a>"}, #285
+{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink new_window='1'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\" target=\"_blank\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-640x480-1.jpg\" width=\"640\" height=\"480\" alt=\"\" /></a>"}, #282
+{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink new_window='1' width='160'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\" target=\"_blank\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-160xauto-1.jpg\" width=\"160\" height=\"120\" alt=\"\" /></a>"}, #283
+{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink new_window='1' scale='100'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\" target=\"_blank\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-640x480-1.jpg\" width=\"640\" height=\"480\" alt=\"\" /></a>"}, #284
+{ "r" : "1", "t" : "<MTAssets lastn='1'><$MTAssetThumbnailLink new_window='1' scale='100'$></MTAssets>", "e" : "<a href=\"http://narnia.na/nana/images/test.jpg\" target=\"_blank\"><img src=\"http://narnia.na/nana/assets_c/CURRENT_YEAR/CURRENT_MONTH/test-thumb-640x480-1.jpg\" width=\"640\" height=\"480\" alt=\"\" /></a>"}, #285
 { "r" : "1", "t" : "<$MTAssetCount$>", "e" : "2"}, #286
 { "r" : "1", "t" : "<MTAssets lastn='1'><MTAssetTags><$MTTagName$>; </MTAssetTags></MTAssets>", "e" : "alpha; beta; gamma; "}, #287
Index: /trunk/mt-static/js/archetype_editor.js
===================================================================
--- /trunk/mt-static/js/archetype_editor.js (revision 2560)
+++ /trunk/mt-static/js/archetype_editor.js (revision 3082)
@@ -427,11 +427,11 @@
         html = html.replace(/<(br|img|input|param)([^>]+)?([^\/])?>/g, "<$1$2$3 />");
 
-        // #4 - get absolute path and delete from converted URL 
-        var d = this.document.createElement('div');
-        d.innerHTML = '<a href="dummy.html"></a>';
-        var path = d.innerHTML;
-        path = path.toLowerCase();
-        path = path.replace(/<a href="(.*)dummy.html"><\/a>/, "$1");
+        // #4 - get absolute path and delete from converted URL
+        var path = this.document.URL;
+        path = path.replace(/(.*)editor-content.html.*/, "$1");
         var regex = new RegExp(path, "g");
+        html = html.replace(regex, "");
+        /* XXX for save on ff */
+        regex = new RegExp(path.replace(/~/, "%7E"), "g");
         html = html.replace(regex, "");
 
Index: /trunk/tmpl/cms/include/template_table.tmpl
===================================================================
--- /trunk/tmpl/cms/include/template_table.tmpl (revision 2934)
+++ /trunk/tmpl/cms/include/template_table.tmpl (revision 3082)
@@ -25,5 +25,5 @@
     <mt:if name="template_type" eq="index">
         <a href="javascript:void(0)"
-            onclick="doForMarkedInThisWindow(getByID('<$mt:var name="template_type"$>-listing-form'), '<__trans phrase="template" escape="js">', '<__trans phrase="templates" escape="js">', 'id', 'publish_index_templates', {}, '<__trans phrase="to publish" escape="js">'); return false;"
+            onclick="doForMarkedInThisWindow(getByID('<$mt:var name="template_type" default="template"$>-listing-form'), '<__trans phrase="template" escape="js">', '<__trans phrase="templates" escape="js">', 'id', 'publish_index_templates', {}, '<__trans phrase="to publish" escape="js">'); return false;"
             accesskey="a"
             title="<__trans phrase="Publish selected templates (a)">"
@@ -31,5 +31,5 @@
     <mt:else if name="template_type" eq="archive">
         <a href="javascript:void(0)"
-            onclick="doForMarkedInThisWindow(getByID('<$mt:var name="template_type"$>-listing-form'), '<__trans phrase="template" escape="js">', '<__trans phrase="templates" escape="js">', 'id', 'publish_archive_templates', {}, '<__trans phrase="to publish" escape="js">'); return false;"
+            onclick="doForMarkedInThisWindow(getByID('<$mt:var name="template_type" default="template"$>-listing-form'), '<__trans phrase="template" escape="js">', '<__trans phrase="templates" escape="js">', 'id', 'publish_archive_templates', {}, '<__trans phrase="to publish" escape="js">'); return false;"
             accesskey="a"
             title="<__trans phrase="Publish selected templates (a)">"
@@ -37,5 +37,5 @@
     </mt:if>
     <a href="javascript:void(0)"
-        onclick="doRemoveItems(getByID('<$mt:var name="template_type"$>-listing-form'), '<__trans phrase="template" escape="js">', '<__trans phrase="templates" escape="js">'); return false;"
+        onclick="doRemoveItems(getByID('<$mt:var name="template_type" default="template"$>-listing-form'), '<__trans phrase="template" escape="js">', '<__trans phrase="templates" escape="js">'); return false;"
         accesskey="x"
         title="<__trans phrase="Delete selected [_1] (x)" params="<$mt:var name="object_label_plural"$>">"
@@ -74,5 +74,5 @@
         <tbody>
     </mt:if>
-            <tr class="<mt:if name="__odd__">odd<mt:else>even</mt:if> template-<$mt:var name="template_type"$>">
+            <tr class="<mt:if name="__odd__">odd<mt:else>even</mt:if> template-<$mt:var name="template_type" default="template"$>">
                 <td class="cb"><input type="checkbox" name="id" class="select" value="<mt:var name="id">" /></td>
                 <td class="template-name"><a href="<mt:var name="script_url">?__mode=view&amp;_type=template&amp;id=<mt:var name="id">&amp;blog_id=<mt:var name="blog_id">"><mt:var name="name" escape="html"></a></td>
@@ -139,5 +139,5 @@
 <mt:else>
     <mt:if name="blog_id">
-    <div id="<$mt:var name="template_type"$>-listing" class="listing zero-state-listing zero-state">
+    <div id="<$mt:var name="template_type" default="template"$>-listing" class="listing zero-state-listing zero-state">
         <div class="listing-header">
             <$mt:var name="listing_header"$>
Index: /trunk/tmpl/cms/error.tmpl
===================================================================
--- /trunk/tmpl/cms/error.tmpl (revision 2784)
+++ /trunk/tmpl/cms/error.tmpl (revision 3082)
@@ -24,4 +24,6 @@
                 <mt:if name="dialog">
                 onclick="if ( window.opener ) { window.close(); } else { window.parent.closeDialog('<mt:var name="link" escape="js">'); }; return false;"
+                <mt:elseif name="fs">
+                onclick="window.location='<mt:var name="link" escape="js">'; return false;"
                 <mt:else>
                 onclick="if ( window.opener ) { window.opener.location.href='<mt:var name="link" escape="js">'; window.close(); } else { window.open('<mt:var name="link" escape="js">') }; return false;"
Index: /trunk/tmpl/cms/list_template.tmpl
===================================================================
--- /trunk/tmpl/cms/list_template.tmpl (revision 2622)
+++ /trunk/tmpl/cms/list_template.tmpl (revision 3082)
@@ -21,4 +21,5 @@
         </mt:if>
         </ul>
+        <$mtapp:ListFilters$>
     </mtapp:widget>
     <mtapp:widget
Index: /trunk/tmpl/cms/widget/blog_stats_tag_cloud.tmpl
===================================================================
--- /trunk/tmpl/cms/widget/blog_stats_tag_cloud.tmpl (revision 1857)
+++ /trunk/tmpl/cms/widget/blog_stats_tag_cloud.tmpl (revision 3082)
@@ -5,4 +5,5 @@
 
     <div id="tag-panel" class="<mt:unless name="tab" eq="tag">hidden</mt:unless>" mt:tab-content="tag">
+<mt:Section cache_prefix="tagcloud" period="3600" by_blog="1" by_user="1">
         <div id="tag-cloud">
             <ul id="tag-cloud-list">
@@ -12,4 +13,5 @@
             </ul>
         </div>
+</mt:Section>
         <div id="tag-cloud-recent-entries"></div>
     </div>
Index: /trunk/tmpl/cms/cfg_archives.tmpl
===================================================================
--- /trunk/tmpl/cms/cfg_archives.tmpl (revision 2213)
+++ /trunk/tmpl/cms/cfg_archives.tmpl (revision 3082)
@@ -116,4 +116,16 @@
         return false;
     }
+    if (f.enable_archive_paths.checked) {
+        if (!f.archive_path.value) {
+            alert('<__trans phrase="You must set Local Archive Path." escape="singlequotes">');
+            return false;
+        } else if (!is_valid_url(f.archive_url.value)){
+            alert('<__trans phrase="You must set a valid Archive URL." escape="singlequotes">');
+            return false;
+        } else if (!is_valid_path(f.archive_path.value)){
+            alert('<__trans phrase="You must set a valid Local Archive Path." escape="singlequotes">');
+            return false;
+        }
+    }
     f.site_url.disabled = false;
     f.site_path.disabled = false;
@@ -126,12 +138,11 @@
 }
 function is_valid_path(path_){
-    for(i = 0; i < path_.length; i++){
-        var buf = escape(path_.substr(i, 1));
-        if (buf.match(/^%u.*/)){
-            return false;
-        }
-        if (buf.match(/(%.{2}){2}?/)){
-        	return false;
-        }
+    var str = path_.replace(/[ "%<>\[\\\]\^`{\|}~]/g, "");
+    str = encodeURI(str);
+    if (str.indexOf('%') != -1) {
+        return false;
+    }
+    if (str.match(/\.\./)) {
+        return false;
     }
     return true;
