Overview
The trackback API for Movable Type 3.2 uses the internal numeric ID of the trackback object as the key. This has two problems:
- There is no relationship between the trackback key and information in an entry, making clever URL rewriting infeasible.
- It is an easy target for junkers, who can trivially guess valid values.
This was unavoidable in previous versions of Movable Type, but with the release of 3.2 and its use of globally unique “basenames” for entries, we can do better.
This modification changes the trackback API to use identifying strings instead of numerics as the trackback key. The trackback object identifiers become completely internal (as was done for entry identifiers in 3.2). This overcomes both of the issues listed above.
This project is currently in beta. It has been deployed only several production weblogs, including this one. You can test it out by doing a trackback to this entry using the URL in the “Trackback URL” link below, or using the URL for this entry with “/ping” appended. Please put text that indicates a test if you do test it, so I can clean those out.
NB: This modification explicitly forbids the use of numeric trackback ids. If installed and followed with a complete rebuild, this should not affect legitimate weblogs as the trackback URLs are pulled from your webpages, which will have the new, correct trackback URLs in it.
Implementation
Two files in the base distribution must be modified. You can pick up the modified versions of the files here or, if you’re paranoid like me, you can do the modifications yourself. Once the files have been modified, you will need to a full rebuild to update all of the trackback URLs. At that point the modified trackback API should be fully operational.
Trackback.pm Modification
The lib/MT/App/Trackback.pm file must be modified. Note that there are two files named Trackback.pm in the distribution, be sure to edit the correct one.
Around line 97, there is a subroutine _get_params. Remove this subroutine and replace it with the following subroutine:
sub _get_tb {
my $app = shift;
my ($tb, $pass); # Trackback object and password to return
my ($key, $name); # local vars for internal computations
if (my $pi = $app->path_info) {
$pi =~ s!^/!!; # drop leading slash
($key, $name, $pass) = split /\//, $pi;
if ($key =~ m/\d+/) {
$app->error($app->translate(
'Numeric trackback IDs are no longer accepted'));
} elsif (lc($key) eq 'entry') {
require MT::Entry;
$name =~ s/\..*$//; # strip any extension
if (my $entry = MT::Entry->load({ basename => $name})) {
$tb = MT::Trackback->load({ entry_id => $entry->id});
$app->error($app->translate(
'No trackbacks for entry with basename [_1]', $name))
if not $tb;
} else {
$app->error($app->translate('No entry with basename [_1]', $name));
}
} elsif ($key =~ m/^cat/i) {
require MT::Category;
if (my $cat = MT::Category->load({ label => $name })) {
$tb = MT::Trackback->load({ category_id => $cat->id });
$app->error($app->translate(
'No trackbacks for category with label [_1]', $name))
if not $tb;
} else {
$app->error($app->translate(
'No category with label [_1]', $name));
}
} else {
$app->error($app->translate(
'Invalid trackback target key [_1]', $key));
}
} else {
$app->error($app->translate(
'Track request URL incorrectly formatted.
The trackback target path information was missing'));
}
($tb, $pass);
}
Around line 150, in subroutine ping, change
my($tb_id, $pass) = $app->_get_params;
return $app->_response(Error =>
$app->translate("Need a TrackBack ID (tb_id)."))
unless $tb_id;
require MT::Trackback;
my $tb = MT::Trackback->load($tb_id)
or return $app->_response(Error =>
$app->translate("Invalid TrackBack ID '[_1]'", $tb_id));
to
my($tb, $pass) = $app->_get_tb;
return $app->_response(Error => $app->errstr) unless $tb;
Around line 185, change
no_utf8($tb_id, $title, $excerpt, $url, $blog_name);
to
no_utf8($title, $excerpt, $url, $blog_name);
Around line 213, change
$ping->tb_id($tb_id);
to
$ping->tb_id($tb->id);
In subroutine rss, around line 369, change
my($tb_id, $pass) = $app->_get_params;
my $tb = MT::Trackback->load($tb_id)
or return $app->_response(Error =>
$app->translate("Invalid TrackBack ID '[_1]'", $tb_id));
to
my ($tb, $pass) = $app->_get_tb;
return $app->_response(Error => $app->errstr) unless $tb;
ContextHandlers.pm Modification
The file lib/MT/Template/ContextHandlers.pm should be modified. This is not strictly required, but if this is not done then you will have to construct all trackback related data by hand in the templates rather than using the standard tags.
In subroutine _hdlr_entry_id, around line 1125, change
$path . $cfg->TrackbackScript . '/' . $tb->id;
to
$path . $cfg->TrackbackScript . '/entry/' . $e->basename;
In subroutine _hdlr_entry_tb_data, around line 1138, change
$path .= $cfg->TrackbackScript . '/' . $tb->id;
to
$path .= $cfg->TrackbackScript . '/entry/' . $e->basename;
In subroutine _hdlr_category_tb_link, around line 2639, change
$path . $cfg->TrackbackScript . '/' . $tb->id;
to
$path . $cfg->TrackbackScript . '/cat/' . $cat->label;
Other Notes, Techniques and Caveats
There are several things to keep in mind once this modification is installed.
Friendly trackback URLs
One of the drivers for this modification was a request for “friendlier” trackback URLs. In particular, the desire was to be able to have other weblogs link via trackback to a post by using the URL of the post with “/ping” appended as the trackback URL. This requires
- Installing this modification
- An Apache webserver
- Access to the Apache configuration file or
.htaccessfiles to enable mod_rewrite
Also note that this works only for individual archives.
To set it up, in the top level directory for the individual archives, place text like the following in a .htaccess file:
RewriteEngine On # Support trackback pings by appending "/ping" to an individual archive URL. RewriteRule /([^/]+)/ping$ /cgi-bin/mt/mt-tb.cgi/entry/$1
You need to make sure that the path “/cgi-bin/mt/mt-tb.cgi/” is correct for your installation. This is easy to find, simply look at your current trackback URL.
In theory, this should be easily extensible to supporting category trackback pings, although I never use categories so I have not experimented on it directly yet. Note that the URL must be of the form “…/cat/…” instead of “…/entry/…” for category trackbacks.
NB: The name logic for trackbacks automatically strips extensions, so that you can use both “my_cool_post” and “my_cool_post.html” as the name for the trackback URL. This was done to support this technique.
Trackback URL display
One effect of this modification is to make the trackback URLs noticeably longer. This can cause problems with formatting, particularly of popups. What I have done is change explicit display of the trackback URLs to a link with the link text “Trackback URL”. The reader can then either right-click and use the “copy this link” option (available in FireFox, IE and Opera) or use the “friendlier” trackback URLs.
This project originally inspired by a request from Sherwin Techico on the ProNet mailing list
Trackback URL: http://blog.thought-mesh.net/solidwallofcode/movable_type/mt_32_patch_tra.php/ping
How do you put in .htaccess - I host with Yahoo and they don’t allow me to upload any file with a . in it
Or by . do you mean the relative directory?
If you can’t upload such files, that you can’t use the rewrite trick. I suspect Yahoo! doesn’t allow it because it would vastly increase their support costs. You might ask if they support any form of URL rewriting or “mod rewrite”. I will update the documentation to indicate that you need to be running Apache and have access to a .htaccess file to make it work.
And, in all seriousness, if you are not already familiar with .htaccess files, you don’t want to try this yourself.
AOG - Have you looked into updating these instructions for MT 3.3? Or is it all the same?
Yes and no.
Yes I have the patch for 3.31 and 3.32, but no, it’s not the same. I will try to get the write up out in the next day or two.
MT 3.3 patch for trackback by name is up. It’s potentially a little rough, so let me know via e-mail if you have any problems. As far as I can tell, there are no changes to Trackback.pm between the 3.3 versions, although I would be a little careful with ContextHandlers.pm.