tagging: Allow using titles in for related stories.
[matthijs/upstream/blosxom-plugins.git] / general / slashredir
1 # Blosxom Plugin: slashredir
2 # Author(s): Frank Hecker <hecker@hecker.org>
3 # Version: 0.4
4 # Documentation: See the bottom of this file or type: perldoc slashredir
5
6 package slashredir;
7
8 use strict;
9
10 use CGI qw/:standard :netscape/; 
11
12
13 # --- Configurable variables -----
14
15 my $debug = 1;                          # 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 "slashredir: 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 "slashredir: filter\n" if $debug > 1;
37
38     warn "slashredir: \$path_info: '" . $blosxom::path_info . "'\n"
39         if $debug > 0;
40     warn "slashredir: 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 trailing slashes stripped by
45     # Blosxom and also want the full path including date information.
46
47     my $path = path_info();
48
49     # We check to see if the URI is for an entry page and redirect if the URI
50     # has a trailing slash. Otherwise we check to see if a trailing slash
51     #  needs to be added or removed and redirect if needed.
52     #
53     # Note: We use $blosxom::path_info to check for the presence of a
54     # file extension because the extension may not have been present in the
55     # original URI but might have been added by the extensionless plugin.
56     # (That also implies that this plugin must run after extensionless runs.)
57
58     if ($blosxom::path_info =~ m!\.!) {
59         if ($path =~ m!/$!) {
60             $path =~ s!/+$!!;           # strip *all* trailing slashes
61             redirect($path, "Trailing slash(es) not needed");
62         }
63     } elsif ($path !~ m!/$!) {
64         $path .= '/';                   # add one trailing slash
65         redirect($path, "Adding trailing slash");
66     } elsif ($path =~ m!//+$!) {
67         $path =~ s!//+$!/!;             # remove redundant slash(es)
68         redirect($path, "Removing redundant trailing slash(es)");
69     }
70     1;
71 }
72
73
74 sub skip {
75     warn "slashredir: skip\n" if $debug > 1;
76
77     return $redirecting;                # skip story generation if redirecting
78 }
79
80
81 sub redirect {
82     my ($path, $error_msg) = @_;
83
84     my $uri = "$blosxom::url$path";
85     $uri .= "?" . $ENV{QUERY_STRING} if $ENV{QUERY_STRING};
86
87     warn "slashredir: redirecting to '$uri', '$error_msg'\n"
88         if $debug > 0;
89
90     my $redir_msg = qq!, redirecting to <a href="$uri">$uri</a>.\n!;
91     $blosxom::output = $error_msg . $redir_msg;
92     print "Status: 301\n";
93     print "Location: $uri\n";
94     $redirecting = 1;
95 }
96
97 1;
98
99 __END__
100
101 =head1 NAME
102
103 Blosxom plugin: slashredir
104
105 =head1 SYNOPSIS
106
107 Have Blosxom force a redirect if a URI is not in canonical form with respect
108 to trailing slashes.
109
110 =head1 VERSION
111
112 0.4
113
114 =head1 AUTHOR
115
116 Frank Hecker <hecker@hecker.org>, http://www.hecker.org/
117
118 This plugin is now maintained by the Blosxom Sourceforge Team,
119 <blosxom-devel@lists.sourceforge.net>.
120
121 =head1 DESCRIPTION
122
123 This plugin checks to see whether the requested URI has one or more
124 trailing slashes and if necessary does a browser redirect to the
125 canonical form of the URI. More specifically, URIs for the blog root,
126 categories, and date-based archives should have one (and only one)
127 trailing slash, while URIs for individual entry pages should not have
128 a trailing slash.
129
130 For example, if you request the URI
131
132   http://www.example.com/blog/foo
133
134 where "foo" is a category, this plugin will force a redirect to the
135 URI
136
137   http://www.example.com/blog/foo/
138
139 This plugin essentially causes Blosxom to emulate the default behavior
140 of the Apache web server. The underlying idea is that URIs for Blosxom
141 pages should have trailing slashes if and only if there are (or could
142 be) other URIs for other pages "underneath" the URI in question.
143
144 Thus an individual entry page with a URI of the form
145 ".../entry.flavour" (or ".../entry" if using the extensionless plugin)
146 should not have a trailing slash, because URIs of the form
147 ".../entry.html/foo" (or ".../entry/foo" with extensionless) don't and
148 won't return anything meaningful. However a category page with a URI
149 of the form ".../category" could refer to additional pages with URIs
150 of the form ".../category/foo.html (or ".../category/foo/entry"), and
151 hence the canocical form of the category's URI should be
152 ".../category/".
153
154 Similarly, date-based archive pages with URIs like ".../2004" or
155 ".../2004/10" could have subsidiary URIs for months or days
156 respectively; while days are not subdivided further, per-day archive
157 pages could be requested in non-default flavours, e.g.,
158 ".../2004/10/14/index.rss" (as could per-year and per-month pages as
159 well, of course). Hence for date-based archive pages the canonical
160 form of the URI should also include a trailing slash if the default
161 flavour is being requested.
162
163 Note that using this plugin makes most sense if you are also using URI
164 rewriting rules to hide use of "/cgi-bin/blosxom.cgi" and support URIs
165 similar to those traditionally used to access normal directories and
166 files. This plugin can be used in conjunction with the extensionless
167 plugin, but does not assume or require its use. (See also below.)
168
169 This plugin was inspired by the redirect plugin by Fletcher T. Penny
170 http://www.blosxom.com/plugins/general/redirect.htm and adapts a bit
171 of its code.
172
173 =head1 INSTALLATION AND CONFIGURATION
174
175 Copy this plugin into your Blosxom plugin directory. You do not
176 normally need to rename the plugin; however see the discussion below.
177
178 You can change the value of the variable C<$debug> to 1 if you need to
179 debug the plugin's operation; the plugin will print to the web
180 server's error log the original path component of the URI and the new
181 URI if redirection is to be done.
182
183 This plugin supplies a filter and skip subroutine and can normally
184 coexist with other plugins with filter subroutines. However this
185 plugin needs to be run after the extensionless plugin, since it needs
186 the file extension (provided by extensionless if not already present)
187 to distinguish between individual entry pages and other pages.
188
189 Finally, note that this plugin is sensitive to the exact URI rewriting
190 rules you might have configured (e.g., in an Apache configuration file
191 or in a .htaccess file). In particular, when rewriting URIs to add the
192 name of the Blosxom CGI script (e.g., "/cgi-bin/blosxom.cgi") you need
193 to ensure that such rules preserve any trailing slash on the end of
194 the URI and pass it on to Blosxom.
195
196 =head1 SEE ALSO
197
198 Blosxom Home/Docs/Licensing: http://blosxom.sourceforge.net/
199
200 Blosxom Plugin Docs: http://blosxom.sourceforge.net/documentation/users/plugins.html
201
202 =head1 BUGS
203
204 None known; please send bug reports and feedback to the Blosxom
205 development mailing list <blosxom-devel@lists.sourceforge.net>.
206
207 =head1 LICENSE
208
209 slashredir Blosxom plugin Copyright 2004 Frank Hecker
210
211 Permission is hereby granted, free of charge, to any person obtaining a
212 copy of this software and associated documentation files (the "Software"),
213 to deal in the Software without restriction, including without limitation
214 the rights to use, copy, modify, merge, publish, distribute, sublicense,
215 and/or sell copies of the Software, and to permit persons to whom the
216 Software is furnished to do so, subject to the following conditions:
217
218 The above copyright notice and this permission notice shall be included
219 in all copies or substantial portions of the Software.
220
221 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
222 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
223 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
224 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
225 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
226 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
227 OTHER DEALINGS IN THE SOFTWARE.