1 # Blosxom Plugin: writeback
2 # Author(s): Rael Dornfest <rael@oreilly.com>
4 # Documentation: See the bottom of this file or type: perldoc writeback
8 # --- Configurable variables -----
10 # Where should I keep the writeback hierarchy?
11 # I suggest: $writeback_dir = "$blosxom::plugin_state_dir/writeback";
13 # NOTE: By setting this variable, you are telling the plug-in to go ahead
14 # and create a writeback directory for you.
15 my $writeback_dir = "";
17 # What flavour should I consider an incoming trackback ping?
18 # Otherwise trackback pings will be ignored!
19 my $trackback_flavour = "trackback";
21 # What file extension should I use for writebacks?
22 # Make sure this is different from that used for your Blosxom weblog
23 # entries, usually txt.
24 my $file_extension = "wb";
26 # What fields are used in your comments form and by trackbacks?
27 my @fields = qw! name url title comment excerpt blog_name !;
29 # --------------------------------
31 # Comments for a story; use as $writeback::writebacks in flavour templates
34 # Count of writebacks for a story; use as $writeback::count in flavour templates
37 # The path and filename of the last story on the page (ideally, only 1 story
38 # in this view) for displaying the trackback URL;
39 # use as $writeback::trackback_path_and_filename in your foot flavour templates
40 $trackback_path_and_filename;
42 # Response to writeback; use as $writeback::writeback_response in
46 # Response to a trackback ping; use as $writeback::trackback_response in
47 # head.trackback flavour template
48 $trackback_response =<<'TRACKBACK_RESPONSE';
49 <?xml version="1.0" encoding="iso-8859-1"?>
56 $blosxom::template{'trackback'} = {
57 'content_type' => 'text/xml',
58 'head' => '$writeback::trackback_response',
64 # --------------------------------
66 use CGI qw/:standard/;
69 my $fh = new FileHandle;
71 # Strip potentially confounding bits from user-configurable variables
72 $writeback_dir =~ s!/$!!; $file_extension =~ s!^\.!!;
74 # Save Name and URL/Email via cookie if the cookies plug-in is available
79 # $writeback_dir must be set to activate writebacks
80 unless ( $writeback_dir ) {
81 warn "blosxom : writeback plugin > The \$writeback_dir configurable variable is not set; please set it to enable writebacks. Writebacks are disabled!\n";
85 # the $writeback_dir exists, but is not a directory
86 if ( -e $writeback_dir and ( !-d $writeback_dir or !-w $writeback_dir ) ) {
87 warn "blosxom : writeback plugin > The \$writeback_dir, $writeback_dir, must be a writeable directory; please move or remove it and Blosxom will create it properly for you. Writebacks are disabled!\n";
91 # the $writeback_dir does not yet exist, so Blosxom will create it
92 if ( !-e $writeback_dir ) {
94 my $mkdir_r = mkdir("$writeback_dir", 0755);
97 ? "blosxom : writeback plugin > \$writeback_dir, $writeback_dir, created.\n"
98 : "blosxom : writeback plugin > There was a problem creating your \$writeback_dir, $writeback_dir. Writebacks are disabled!\n";
100 $mkdir_r or return 0;
102 my $chmod_r = chmod 0755, $writeback_dir;
105 ? "blosxom : writeback plugin > \$writeback_dir, $writeback_dir, set to 0755 permissions.\n"
106 : "blosxom : writeback plugin > There was a problem setting permissions on \$writeback_dir, $writeback_dir. Writebacks are disabled!\n";
108 $chmod_r or return 0;
110 warn "blosxom : writeback plugin > writebacks are enabled!\n";
113 $path_info = path_info();
114 my($path,$fn) = $path_info =~ m!^(?:(.*)/)?(.*)\.$blosxom::flavour!;
115 $path =~ m!^/! or $path = "/$path";
118 # Only spring into action if POSTing to the writeback plug-in
119 if ( request_method() eq 'POST' and (param('plugin') eq 'writeback' or $blosxom::flavour eq $trackback_flavour) ) {
121 foreach ( ('', split /\//, $path) ) {
124 -d "$writeback_dir/$p" or mkdir "$writeback_dir/$p", 0755;
127 if ( $fh->open(">> $writeback_dir$path/$fn.$file_extension") ) {
128 foreach ( @fields ) {
130 $p =~ s/<.*?>//mg; # a gross way to prevent tomfoolery, to be redone
131 $p =~ s/\r?\n\r?/\r/mg;
132 print $fh "$_: $p\n";
137 $trackback_response =~ s!<error></error>!<error>0</error>!m;
138 $trackback_response =~ s!<message></message>\n!!s;
139 $writeback_response = "Thanks for the writeback.";
141 # Make a note to save Name and URL/Email if save_preferences checked
142 param('save_preferences') and $cookie++;
143 # Pre-set Name and URL/Email based on submitted values
144 $pref_name = param('name') || '';
145 $pref_url = param('url') || '';
148 warn "couldn't >> $writeback_dir$path/$fn.$file_extension\n";
150 $trackback_response =~ s!<error></error>!<error>1</error>!m;
151 $trackback_response =~ s!<message>trackback error</message>!!m;
152 $writeback_response = "There was a problem posting your writeback.";
160 my($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_;
162 $path =~ s!^/*!!; $path &&= "/$path";
164 ($writebacks, $count) = ('', 0);
167 # Prepopulate Name and URL/Email with cookie-baked preferences, if any
168 if ( $blosxom::plugins{cookies} > 0 and my $cookie = &cookies::get('writeback') ) {
169 $pref_name ||= $cookie->{'name'};
170 $pref_url ||= $cookie->{'url'};
173 if ( $fh->open("$writeback_dir$path/$filename.$file_extension") ) {
174 foreach my $line (<$fh>) {
175 $line =~ /^(.+?):\s*(.*)$/ and $param{$1} = $2;
176 if ( $line =~ /^-----$/ ) {
178 my $writeback = &$blosxom::template($path,'writeback',$blosxom::flavour) || '<p><b>Name/Blog:</b> $writeback::name$writeback::blog_name<br /><b>URL:</b> $writeback::url<br /><b>Title:</b> $writeback::title<br /><b>Comment/Excerpt:</b> $writeback::comment$writeback::excerpt</p>';
180 $writeback =~ s/\$writeback::(\w+)/$param{$1}/ge;
181 $writebacks .= $writeback;
188 $trackback_path_and_filename = "$path/$filename";
194 $blosxom::plugins{cookies} > 0 and $cookie and &cookies::add(
197 -value=>{ 'name' => param('name'), 'url' => param('url') },
198 -path=>$cookies::path,
199 -domain=>$cookies::domain,
200 -expires=>$cookies::expires
211 Blosxom Plug-in: writeback
215 Provides WriteBacks, a combination of comments and TrackBacks
216 [http://www.movabletype.org/trackback/].
218 All comments and TrackBack pings for a particular story are kept in
219 $writeback_dir/$path/$filename.cmt.
223 Drop this writeback plug-in file into your plug-ins directory
224 (whatever you set as $plugin_dir in blosxom.cgi).
226 Writeback, being a well-behaved plug-in, won't do anything until you set
229 While you can use the same directory as your blosxom $datadir (WriteBacks
230 are saved as path/weblog_entry_name.wb), it's probably better to keep
233 Once set, the next time you visit your site, the writeback plug-in will
234 perform some checks, creating the $writeback_dir and setting appropriate
235 permissions if it doesn't already exist. (Check your error_log for details
236 of what's happening behind the scenes.)
238 Move the contents of the flavours folder included in this distribution
239 into your Blosxom data directory (whatever you set as $datadir in blosxom.cgi).
240 Don't move the folder itself, only the files it contains! If you don't
241 have the the sample flavours handy, you can download them from:
243 http://www.raelity.org/apps/blosxom/downloads/plugins/writeback.zip
245 Point your browser at one of your Blosxom entries, specifying the writeback
246 flavour (e.g. http://localhost/cgi-bin/blosxom.cgi/path/to/a/post.writeback)
252 =head2 FLAVOUR TEMPLATE VARIABLES
254 Wherever you wish all the WriteBacks for a particular story to appear
255 in your flavour templates, use $writeback::writebacks.
257 A count of WriteBacks for each story may be embedded in your flavour
258 templates with $writeback::count.
260 If you'd like, you can embed a "Thanks for the writeback." or
261 "There was a problem posting your writeback." message after posting with
262 $writeback::writeback_response.
264 =head2 SAMPLE FLAVOUR TEMPLATES
266 I've made sample flavour templates available to you to help with any
267 learning curve this plug-in might require.
269 Take a gander at the source HTML/XML for:
271 =item * story.writeback, a basic example of a single-entry story
272 flavour with WriteBacks embedded. You should not use this as your
273 default flavour since every story on the home page would have WriteBacks
274 right there with the story itself.
276 =item * foot.writeback provides a simple comment form for posting to the
277 WriteBack plug-in. NOTE: The writeback plug-in requires the presence
278 of a "plugin" form variable with the value set to "writeback"; this tells
279 the plug-in that it should handle the incoming POSTing data rather than
280 leaving it for another plug-in.
282 =item * writeback.writeback is a sample flavour file for WriteBacks themselves.
283 Think of a WriteBacks flavour file as a story flavour file for individual
288 =head2 FLAVOURING WRITEBACKS
290 While the default does a pretty good job, you can flavour your WriteBacks
291 in the writeback flavour file (e.g. writeback.writeback) using the following
294 =item * $writeback::name$writeback::blog_name - Name entered in comment form or weblog name used in TrackBack ping.
296 =item * $writeback::url - URL entered in comment form or that of writing citing your weblog entry via TrackBack ping.
298 =item * $writeback::title - Title entered into comment form or that of writing citing your weblog entry via TrackBack ping.
300 =item * $writeback::comment$writeback::excerpt - Comment entered into comment aorm or excerpt of writing citing your weblog entry via TrackBack ping.
302 =item * $writeback::pref_name and $writeback::pref_url are prepopulated with the values of the form you just submitted or preferences stored in a 'writeback' cookie, if you've the cookie plug-in installed an enabled.
306 =head2 INVITING AND SUPPORTING TRACKBACKS
308 You should provide the TrackBack ping URL for each story so that those
309 wanting to TrackBack ping you manually know where to ping.
310 $writeback::trackback_path_and_filename, together with $url and
311 a TrackBack flavour will provide them all they need.
313 e.g. $url$writeback::trackback_path_and_filename.trackback
315 The writeback plugin provides an XML response to TrackBack pings in the form
316 of a baked-in trackback flavour. If you alter the value of $trackback_flavour
317 (why would you?), you'll have to create a set of flavour templates by hand; all
318 should be blank save the content_type (text/xml) and head ($writeback::trackback_response).
322 Drop writeback into your plug-ins directory ($blosxom::plugin_dir).
326 =head2 (REQUIRED) SPECIFYING A WRITEBACK DIRECTORY
328 Writeback, being a well-behaved plug-in, won't do anything until you set
329 $writeback_dir, create the directory, and make it write-able by Blosxom.
331 Create a directory to save WriteBacks to (e.g. $plugin_state_dir/writeback),
332 and set $writeback_dir to the path to that directory.
334 While you can use the same directory as your blosxom $datadir (WriteBacks
335 are saved as path/weblog_entry_name.wb), it's probably better to keep
338 The writeback plug-in will create the appropriate paths to mimick your
339 $datadir hierarchy on-the-fly. So, for a weblog entry in
340 $datadir/some/path/or/other/entry.txt, WriteBacks will be kept in
341 $writeback_dir/some/path/or/other/entry.wb.
343 =head2 (OPTIONAL) ALTERING THE TRACKBACK FLAVOUR
345 The $trackback_flavour sets the flavour the plug-in associates with incoming TrackBack pings. Unless this corresponds to the flavour associated with your trackback URL, the writeback plug-in will ignore incoming pings.
347 =head2 (OPTIONAL) SPECIFYING AN EXTENSION FOR WRITEBACK FILES
349 The default extension for WriteBacks is wb. You can change this if
350 you wish by altering the $file_extension value.
352 =head2 (OPTIONAL) SPECIFYING WHAT FIELDS YOU EXPECT IN YOUR COMMENTS FORM
354 The defaults are probably ok here, but you can specify that the writeback
355 plug-in should look for more fields in your comments form by adding to this
356 list. You should keep at least the defaults in place so as not to break
359 my @fields = qw! name url title comment excerpt blog_name !;
367 Rael Dornfest <rael@oreilly.com>, http://www.raelity.org/
371 Blosxom Home/Docs/Licensing: http://www.raelity.org/apps/blosxom/
373 Blosxom Plugin Docs: http://www.raelity.org/apps/blosxom/plugin.shtml
377 Address bug reports and comments to the Blosxom mailing list
378 [http://www.yahoogroups.com/group/blosxom].
382 Blosxom and this Blosxom Plug-in
383 Copyright 2003, Rael Dornfest
385 Permission is hereby granted, free of charge, to any person obtaining a
386 copy of this software and associated documentation files (the "Software"),
387 to deal in the Software without restriction, including without limitation
388 the rights to use, copy, modify, merge, publish, distribute, sublicense,
389 and/or sell copies of the Software, and to permit persons to whom the
390 Software is furnished to do so, subject to the following conditions:
392 The above copyright notice and this permission notice shall be included
393 in all copies or substantial portions of the Software.
395 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
396 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
397 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
398 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
399 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
400 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
401 OTHER DEALINGS IN THE SOFTWARE.