Patching MT 3.15

This set of patches consists of fixes for the MTQuickLinks plugin, MT Blacklist 2.04B and Textile 2. The issues for the first two of these are related and involve path problems on MS Windows based servers.

lib/MT.pm

Method init, around line 235. This corrects an error where Movable Type uses a leading ‘/’ character to indicate an absolute path to a plugin. The correct mechanism is to use the file_name_is_absolute method from File::Spec.

Original:

    $mt->{mt_dir} = dirname($cfg_file||"")
        if !$mt->{mt_dir} || $mt->{mt_dir} !~ m|^/|;
    $mt->{mt_dir} = $ENV{PWD} if !$mt->{mt_dir} || $mt->{mt_dir} !~ m|^/|;
    $mt->{mt_dir} = dirname($ARGV[0])
        if (!$mt->{mt_dir} || $mt->{mt_dir}) !~ m|^/| && $ARGV[0];
    $mt->{mt_dir} = dirname($ENV{SCRIPT_FILENAME}) 
        if (!$mt->{mt_dir} || $mt->{mt_dir} !~ m|^/|) && $ENV{SCRIPT_FILENAME};

Modified:

    $mt->{mt_dir} = dirname($cfg_file||"")
       if !$mt->{mt_dir}
       || not File::Spec->file_name_is_absolute($mt->{mt_dir});
    $mt->{mt_dir} = $ENV{PWD} if !$mt->{mt_dir}
       || not File::Spec->file_name_is_absolute($mt->{mt_dir});
    $mt->{mt_dir} = dirname($ARGV[0])
       if (!$mt->{mt_dir}
       || not File::Spec->file_name_is_absolute($mt->{mt_dir})) && $ARGV[0];
    $mt->{mt_dir} = dirname($ENV{SCRIPT_FILENAME}) 
       if (!$mt->{mt_dir}
       || not File::Spec->file_name_is_absolute($mt->{mt_dir}))
       && $ENV{SCRIPT_FILENAME};

Method init, around line 305. This corrects a problem where backslashes in a Windows path causes a regular expression substitution to fail. This fix by itself is enough of a patch to Movable Type to enable MTQuickLinks, but additional patches described in that link are required. I believe that it is necessary for fixing MtBlacklist 2.04B as well but I haven’t tested that without this fix.

The fix has two parts.

  • Use quotemeta to make the path a literal regexp
  • When compressing multiple slashes in the path, compress backslashes as well

Original:

my $plugin_path = $plugin;
$plugin_envelope = $plugin_path;
$plugin_envelope =~ s|$plugin_dir|/plugins/|;
$plugin_envelope =~ s|/+|/|;

Modified:

my $plugin_path = $plugin;
$plugin_envelope = $plugin_path;
my $local_dir = quotemeta($plugin_dir);
$plugin_envelope =~ s|$local_dir|/plugins/|;
$plugin_envelope =~ s|[/\\]+|/|go;

lib/MT/App.pm

In method load_tmpl, around line 432. The problem here is that the path for ancillary templates does not include the MtBlacklist plugin directory. This is the one case where I don’t understand how it works at all, as opposed to not on MS Windows. I can only presume that the HTML::Template package has some subtle difference where the MS Windows version does not automatically search the directory containing the base template.

The fix is to add the plugin template path as a path for template searching.

Original:

  my $alt_path = File::Spec->catfile($app->{mt_dir},
    $app->{plugin_template_path});
  $tmpl = HTML::Template->new_file(
    File::Spec->catfile($alt_path, $file),
    path => [ File::Spec->catdir($path, $app->{template_dir}) ],
    die_on_bad_params => 0, global_vars => 1, @p);

Modified:

my $alt_path = File::Spec->catfile($app->{mt_dir},
  $app->{plugin_template_path});
$tmpl = HTML::Template->new_file(
  File::Spec->catfile($alt_path, $file),
  path => [ $alt_path, File::Spec->catdir($path, $app->{template_dir}) ],
  die_on_bad_params => 0, global_vars => 1, @p);            

plugins/Blacklist/lib/Blacklist/App.pm

In method bluri, around line 615. The problem here is that URLs on the left menu contain backslashes. Firefox, at least, does not recognize these as local absolute paths and so prefixes them with the full URL path. This fix flips the slashes so that the URLs are recognized properly.

Original:

sub bluri { File::Spec->catdir($_[0]->blpath,$_[0]->blscript) }

Modified:

sub bluri {
    my $uri = File::Spec->catdir($_[0]->blpath,$_[0]->blscript);
    $uri =~ s|\\|/|g;
    $uri;
}

lib/MT/Template/Context.pm

This fix is required for the proper operation of Textile. Without this, permalinks for links generated from the format “Text”:#post-id# are incorrect. The problem is that if () is passed in when the archive type is missing (i.e., the default is desired), it disappears because of argument flattening. Another value that is not a list and is false needs to be used. I chose to use the empty string. Additional discussion is available at this post on the Movable type forums.

Method _hdlr_entry_permalink, around line 1055

Original:

    $e->permalink($args ? $args->{archive_type} : (), 
		  { valid_html => $args->{valid_html} });

Modified:

    $e->permalink($args ? $args->{archive_type} : '', 
		  { valid_html => $args->{valid_html} });

lib/MT/XMLRPCServer.pm

This patch fixes a few minor issues in the XML RPC interface for Movable Type but its primary purpose is to provide a more powerful RPC interace. It is recommended only for those who are working directly with the RPC. If the writeup doesn’t make any sense, you don’t need this patch.

Comment Preview not formatted

This is a bug in the default templates for Movable Type 3.15. To fix it, remove the string convert_breaks=”0” from the MTCommentPreviewBody tag in the template. Why the formatting is explicitly suppressed I have no idea.

MTEntryModifiedDate generates bad output

This bug appears to be cause by a column in the database not having its type changed correctly during upgrade from 2.6 to 3.1. In 2.6 the modified_on column was of type DATETIME. In 3.1 it was changed to TIMESTAMP(14). The bizarre part of that is that created_on was not changed. Why it seemed desirable to have different types for these two timestamps is incomprehensible to me. The problem arises because the old DATETIME format contains non-numeric characters and the new type does not. This causes confusion when the data is processed. My hack that aleviated the problem simply removes any non-numeric characters from the timestamp before sending it on.

In file lib/MT/Template/Context.pm, in subroutine _hdlr_entry_mod_date, around line 865,

$args->{ts} = $_[0]->{modification_timestamp};
$args->{ts} =~ s/[^[:digit:]]//go #AOG Add this line
_hdlr_date($_[0], $args);