tagging: Allow using titles in for related stories.
[matthijs/upstream/blosxom-plugins.git] / general / canonicaluri
1 # Blosxom Plugin: canonicaluri
2 # Author(s): Frank Hecker <hecker@hecker.org>
3 # Version: 0.6
4 # Documentation: See the bottom of this file or type: perldoc canonicaluri
5
6 package canonicaluri;
7
8 use strict;
9
10 use CGI qw/:standard :netscape/; 
11
12
13 # --- Configurable variables -----
14
15 my $debug = 0;                          # set to 1 to print debug messages
16
17 # --------------------------------
18
19
20 use vars qw!$redirecting!;              # 1 if we are redirecting, 0 if not
21
22
23 sub start {
24     warn "canonicaluri: start\n" if $debug > 1;
25
26     $redirecting = 0;
27
28     # Activate this plugin only when doing dynamic page generation.
29     return $blosxom::static_or_dynamic eq 'dynamic' ? 1 : 0;
30 }
31
32
33 sub filter {
34     my ($pkg, $files_ref) = @_;
35
36     warn "canonicaluri: filter\n" if $debug > 1;
37
38     warn "canonicaluri: \$blosxom::path_info: '" . $blosxom::path_info . "'\n"
39         if $debug > 0;
40     warn "canonicaluri: path_info(): '" . path_info() . "'\n"
41         if $debug > 0;
42
43     # We need a copy of the original PATH_INFO, prior to Blosxom having
44     # parsed it, because we need to see the original URI passed into
45     # Blosxom, including whether the URI had an index.* component, trailing
46     # slash, or file extension.
47
48     my $path = path_info();
49
50     # If the requested URI has an explicit "index.*" component where the
51     # the file extension corresponds to the default flavour (typically
52     #  "html") then we rewrite the URI to strip the "index.*" component
53     # (and any spurious slashes after it) and leave a single trailing slash.
54
55     $path =~ s!/index\.$blosxom::default_flavour/*$!/!;
56
57     warn "canonicaluri: \$path (after index.html check): '" . $path . "'\n"
58         if $debug > 0;
59
60     # If the requested URI has an explicit "index.*" component for any
61     # flavour other than the default then we rewrite the URI if necessary
62     # to remove any trailing slashes.
63
64     $path =~ s!/(index\.[^./]*)/*$!/$1!;
65
66     warn "canonicaluri: \$path (after index.foo check): '" . $path . "'\n"
67         if $debug > 0;
68
69     # If the URI has a trailing slash but corresponds to an individual entry
70     # then we rewrite the URI to remove the trailing slash. On the other hand
71     # if the URI does not have a trailing slash but corresponds to a category
72     # or archive page then we rewrite the URI to add the trailing slash
73     # unless an "index.*" component is present in the URI.
74
75     if ($path =~ m!/$!) {               # trailing slash, remove if need be
76         $blosxom::path_info =~ m!\.! and $path =~ s!/+$!!;
77     } else {                            # no trailing slash, add if needed
78         $blosxom::path_info !~ m!\.!
79             and $path !~ m!/index.[^./]*$!
80             and $path =~ s!$!/!;
81     }
82
83     warn "canonicaluri: \$path (after slash check): '" . $path . "'\n"
84         if $debug > 0;
85
86     # If the URI has a flavour extension corresponding to the default flavour
87     # (typically "html") then we rewrite the URI to remove the extension.
88
89     $path =~ s!\.$blosxom::default_flavour!!;
90
91     warn "canonicaluri: \$path (after extension check): '" . $path . "'\n"
92         if $debug > 0;
93
94     # If we have rewritten the URI then we force a redirect to the new URI.
95
96     $path ne path_info() and redirect($path);
97
98     1;
99 }
100
101
102 sub skip {
103     warn "canonicaluri: skip\n" if $debug > 1;
104
105     return $redirecting;                # skip story generation if redirecting
106 }
107
108
109 sub redirect {
110     my ($path) = @_;
111
112     my $uri = "$blosxom::url$path";
113     $uri .= "?" . $ENV{QUERY_STRING} if $ENV{QUERY_STRING};
114
115     warn "canonicaluri: redirecting to '$uri'\n"
116         if $debug > 0;
117
118     $blosxom::output = qq!Redirecting to <a href="$uri">$uri</a>.\n!;
119     print "Status: 301\n";
120     print "Location: $uri\n";
121     $redirecting = 1;
122 }
123
124 1;
125
126 __END__
127
128 =head1 NAME
129
130 Blosxom plugin: canonicaluri
131
132 =head1 SYNOPSIS
133
134 Have Blosxom force a redirect if a URI is not in canonical form with
135 respect to index.* component, trailing slash, or flavour extension.
136
137 =head1 VERSION
138
139 0.6
140
141 =head1 AUTHOR
142
143 Frank Hecker <hecker@hecker.org>, http://www.hecker.org/
144
145 This plugin is now maintained by the Blosxom Sourceforge Team,
146 <blosxom-devel@lists.sourceforge.net>.
147
148 =head1 DESCRIPTION
149
150 This plugin checks to see whether the requested URI is in the
151 canonical form for the type of page being requested, and if necessary
152 does a browser redirect to the canonical form of the URI. The
153 canonical forms are defined as follows:
154
155 =over
156
157 =item * URIs for the blog root, categories, and date-based archives
158 should not have an "index.*" component if the flavour being requested
159 is the default flavour, and if an "index.*" component is not present
160 then the URI should have one (and only one) trailing slash.
161
162 =item * URIs for individual entry pages should not have a trailing
163 slash and also should not have a flavour extension if the flavour
164 being requested is the default flavour (typically "html").
165
166 =back
167
168 For example, if you request the URIs
169
170   http://www.example.com/blog/foo
171
172 or
173
174   http://www.example.com/blog/foo/index.html
175
176 where "foo" is a category and "html" is the default flavour, this
177 plugin will force a redirect to the canonical URI
178
179   http://www.example.com/blog/foo/
180
181 Similarly, if you request the URIs
182
183   http://www.example.com/blog/foo/
184
185 or
186
187   http://www.example.com/blog/foo.html
188
189 where "foo" is an individual entry and "html" is the default flavour,
190 this plugin will force a redirect to the canonical URI
191
192   http://www.example.com/blog/foo
193
194 Note that using this plugin makes the most sense if you are also using
195 URI rewriting rules to hide use of "/cgi-bin/blosxom.cgi" and support
196 URIs similar to those traditionally used to access normal directories
197 and files. This plugin should also be used in conjunction with the
198 extensionless plugin in order to recognize extensionless URIs for
199 individual entries. (See also below.)
200
201 This plugin was inspired by the redirect plugin by Fletcher T. Penny
202 http://www.blosxom.com/plugins/general/redirect.htm and adapts a bit
203 of its code.
204
205 =head1 INSTALLATION AND CONFIGURATION
206
207 Copy this plugin into your Blosxom plugin directory. You do not
208 normally need to rename the plugin; however see the discussion below.
209
210 You can change the value of the variable C<$debug> to 1 if you need to
211 debug the plugin's operation; the plugin will print to the web
212 server's error log the original path component of the URI and the new
213 URI if redirection is to be done.
214
215 This plugin supplies a filter and skip subroutine and can normally
216 coexist with other plugins with filter subroutines. However this
217 plugin needs to be run after the extensionless plugin, since it needs
218 the flavour extension on C<$blosxom::path_info> (provided by
219 extensionless if not already present) to distinguish between
220 individual entry pages and other pages.
221
222 Finally, note that this plugin is sensitive to the exact URI rewriting
223 rules you might have configured (e.g., in the Apache httpd.conf
224 configuration file or in a .htaccess file). In particular, when
225 rewriting URIs to add the name of the Blosxom CGI script (e.g.,
226 "/cgi-bin/blosxom.cgi") you need to ensure that such rules preserve
227 any trailing slash on the end of the URI and pass it on to Blosxom.
228
229 =head1 SEE ALSO
230
231 Blosxom Home/Docs/Licensing: http://blosxom.sourceforge.net/
232
233 Blosxom Plugin Docs: http://blosxom.sourceforge.net/documentation/users/plugins.html
234
235 =head1 BUGS
236
237 This plugin depends on the Apache URI rewriting rules to enforce the
238 restriction that a URI should never have more than one trailing
239 slash. The plugin as presently written can't handle this case properly
240 because it depends on the C<path_info()> function to get the URI path,
241 and the C<path_info()> value has already been stripped of any excess
242 trailing slashes that might have been present in the original URI.
243
244 Please send bug reports and feedback to the Blosxom development mailing 
245 list <blosxom-devel@lists.sourceforge.net>.
246
247 =head1 LICENSE
248
249 canonicaluri Blosxom plugin Copyright 2004 Frank Hecker
250
251 Permission is hereby granted, free of charge, to any person obtaining a
252 copy of this software and associated documentation files (the "Software"),
253 to deal in the Software without restriction, including without limitation
254 the rights to use, copy, modify, merge, publish, distribute, sublicense,
255 and/or sell copies of the Software, and to permit persons to whom the
256 Software is furnished to do so, subject to the following conditions:
257
258 The above copyright notice and this permission notice shall be included
259 in all copies or substantial portions of the Software.
260
261 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
262 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
263 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
264 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
265 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
266 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
267 OTHER DEALINGS IN THE SOFTWARE.