1 # Blosxom Plugin: entries_cache -*- perl -*-
2 # Author(s): Fletcher T. Penney <http://fletcher.freeshell.org/>
3 # Modified by Steve Schwarz <http://agilitynerd.com/>
5 # Based on entries_index by Rael Dornfest
6 # Documentation help contributed by Iain Cheyne
10 # --- Configurable variables -----
12 $delay = 0; # How many minutes delay before entries are re-indexed?
13 # Set to 0 to force reindexing everytime - this
14 # will provide the same behavior as Rael's
15 # entries_index. Though, I am not sure why one
16 # would do this. At least use a small cache time to
17 # improve performance....
18 # SAS - I set this to zero so comments and new files
19 # are immediately visible.
20 $indexname = "$blosxom::plugin_state_dir/.entries_cache.index";
21 $others_indexname = "$blosxom::plugin_state_dir/.entries_cache.others";
24 $use_date_tags = 1; # Set to 1 to enable parsing meta- keywords
27 $use_UK_dates = 0; # Default is mm/dd/yy (US)
28 # Set to 1 to use dd/mm/yy (UK)
30 $update_meta_date = 0; # Add a meta_date tag if it doesn't exist
31 # This will require that perl has write access to your story files
32 # and that you are using the meta plugin.
34 # NOTE: As of version 0.91, you do not NEED the meta plugin...
36 # Be sure to save your text files with UNIX line endings
37 # (any decent text editor should be able to do this) or use the blok
38 # plugin (http://www.enilnomi.net/download.html#blok).
39 # There is some logic in entries_cache to fix this, but do not rely
42 # Lastly, make sure there is at least one blank line between the
43 # entry title and the body. Again, there is some logic in
44 # entries_cache to fix this, but do not rely on it.
46 # The default meta-keywords are compatible with Eric Sherman's
47 # entries_index_tagged defaults:
49 # http://primitiveworker.org/blo.g/development/blosxom/entries_index_tagged/
51 $meta_timestamp = "meta-creation_timestamp:" unless defined $meta_timestamp;
52 # timestamp_tag is the non-human readable date stamp format
53 # used by entries_index, entries_cache, entries_index_tagged,
56 $meta_date = "meta-creation_date:" unless defined $meta_date;
57 # date_tag is a human readable version
59 $strip_meta_dates = 1; # Strip meta-tags from story so that
60 # they are not displayed. Unnecessary if you are running the
63 $debug = 0; # Debugging flag
65 # --------------------------------
69 use CGI qw/:standard/;
77 $reindex = 1 if (CGI::param('reindex'));
85 my(%files, %indexes, %others);
88 if ( open CACHE, $indexname) {
89 while ($line = <CACHE>) {
90 # Improved backwards compatibility with entries_index
91 if ($line =~ /\s*'?(.*?)'?\s*=>\s*(\d*),?/) {
96 # See if it's time to reindex
97 $reindex = 1 if ( stat($indexname)->mtime lt ($time - $delay*60) );
99 # No index found, so we need to index
103 # Read cached others index
104 if ( open CACHE, $others_indexname) {
105 while ($line = <CACHE>) {
106 # Improved backwards compatibility with entries_index
107 if ($line =~ /\s*'?(.*)'?\s*=>\s*(.*),?/) {
112 # See if it's time to reindex
113 $reindex = 1 if ( stat($others_indexname)->mtime lt ($time - $delay*60) );
115 # No index found, so we need to index
120 # Perform reindexing if necessary
121 # This code was originally copied from entries_index by Rael Dornfest
122 # Check to see if previously indexed files exist, and then rescan
123 # the datadir for any new files, while preserving the old times
125 # Static mode requires some of the code in this section, and the
126 # speed hit is unimportant for static blogs
128 if ($blosxom::static_or_dynamic eq "static") {
135 # If any files not available, err on side of caution and reindex
136 for my $file (keys %files) { -f $file or do { $reindex++; delete $files{$file} }; }
137 for my $other (keys %others) { -f $other or do { $reindex++; delete $others{$other} }; }
143 my $curr_depth = $File::Find::dir =~ tr[/][];
145 # if ( $blosxom::depth and $curr_depth > $blosxom::depth ) {
146 # # We are beyond depth, so remove files
147 # $files{$File::Find::name} and delete $files{$File::Find::name};
148 # $others{$File::Find::name} and delete $others{$File::Find::name};
152 # Adding support for %others
155 m!^$blosxom::datadir/(?:(.*)/)?(.+)\.$blosxom::file_extension$!
156 and $2 ne 'index' and $2 !~ /^\./ and (-r $File::Find::name)
158 # SAS modified so if meta-creation_date or file timestamp are in the future
159 # and we don't want future entries the file won't be included in the file list
161 if (!$blosxom::show_future_entries and
162 ((extract_date($File::Find::name, $files{$File::Find::name}) > time) or
163 (stat($File::Find::name)->mtime > time))) {
164 $files{$File::Find::name} and delete $files{$File::Find::name};
165 $others{$File::Find::name} and delete $others{$File::Find::name};
167 ( $files{$File::Find::name} || ++$reindex )
168 and ( $files{$File::Find::name} =
169 extract_date($File::Find::name,$files{$File::Find::name}) ||
170 $files{$File::Find::name} ||
171 stat($File::Find::name)->mtime )
176 or !-f "$blosxom::static_dir/$1/index." . $blosxom::static_flavours[0]
177 # or stat("$blosxom::static_dir/$1/index." . $blosxom::static_flavours[0])->mtime < stat($File::Find::name)->mtime
178 # Trying to fix for static mode
179 or stat("$blosxom::static_dir/$1/index." . $blosxom::static_flavours[0])->mtime < $files{$File::Find::name}
182 and $d = join('/', (blosxom::nice_date($files{$File::Find::name}))[5,2,3])
183 and $indexes{$d} = $d
184 and $blosxom::static_entries and $indexes{ ($1 ? "$1/" : '') . "$2.$blosxom::file_extension" } = 1;
187 !-d $File::Find::name and -r $File::Find::name and $others{$File::Find::name} = stat($File::Find::name)->mtime
194 # The index was recreated, so we should record the new version
195 if ( open ENTRIES, "> $indexname" ) {
196 foreach (sort keys %files) {
197 print ENTRIES "$_=>$files{$_}\n";
201 warn "couldn't > $indexname: $!\n";
204 if ( open ENTRIES, "> $others_indexname" ) {
205 foreach (sort keys %others) {
206 print ENTRIES "$_=>$others{$_}\n";
210 warn "couldn't > $others_indexname: $!\n";
214 return (\%files, \%indexes, \%others);
220 my ($file, $indexed_date) = @_;
222 my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
224 warn "Entries_Cache: Checking $file for meta-tag\n\tComparing to $indexed_date\n" if ($debug == 1);
226 # This is an attempt for compatibility with Eric Sherman's entries_index_tagged
227 # But it does not handle as many date formats, as there are too many additional
228 # necessary modules that I am not willing to require
230 if ( $use_date_tags != 0) {
233 $line = <FILE>; # Read first line ( ie the title)
236 # now, parse the story, and try to correct misformatted stories
237 while ($line = <FILE>) {
238 if ($line =~ /^$meta_timestamp\s*(\d+)/) {
239 # If present, this format is used
242 warn "Entries_Cache: Found meta_timestamp $result for $file\n" if ($debug == 1);
246 if ($line =~ /^$meta_date\s*(.*)/) {
249 warn "Entries_Cache: Found meta-date $result for $file\n" if ($debug == 1);
250 return parsedate($result);
253 if ( $line !~ /^meta.*?:/i) {
254 # line doesn't start with meta... (ie story was not formatted
255 # for meta-tags), or the meta-tags are finished
257 if ($update_meta_date eq 1) {
258 # Don't mess with stories unless using UNIX line endings.
260 if (($line =~ /\r/) || ($new_story =~ /\r/)) {
261 warn "Entries_Cache: File $file has non-UNIX line endings; cannot update metatags...\n";
265 warn "Entries_Cache: Updating meta-tag for $file\n" if ($debug == 1);
266 if ($indexed_date eq 0 || $indexed_date == "") {
267 $indexed_date = stat($file)->mtime;
268 warn "Entries_Cache: No date for $file, using $indexed_date\n" if ($debug == 1);
271 ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($indexed_date);
274 $hour = sprintf("%02d",$hour);
275 $min = sprintf("%02d",$min);
276 $sec = sprintf("%02d",$sec);
278 warn "Entries_Cache: Adding meta-tag to $file, using $meta_date $mday/$mon/$year $hour:$min:$sec\n" if ($debug == 1);
280 if ($use_UK_dates eq 1) {
281 $new_story .= "$meta_date $mday/$mon/$year $hour:$min:$sec\n\n";
283 $new_story .= "$meta_date $mon/$mday/$year $hour:$min:$sec\n\n";
286 if ( $line !~ /^\s*$/) {
287 # If this line wasn't empty, then add it to story
291 while ($line = <FILE>) {
292 # read remainder of story
297 open (FILE, "> $file") or warn "Unable to update date meta-tag on $file\n";
298 print FILE $new_story;
314 my ($datestring) = @_;
315 #warn "Parsing $datestring\n";
317 # Possible formatting
318 # Month can be 3 letter abbreviation or full name (in English)
319 # Time must be hh:mm or hh:mm:ss in 24 hour format
321 # The remaining 1 or 2 digits are treated as date
322 # ie: May 25 2003 18:40
323 # order is not important as long as pieces are there
325 # Convert the datestring to a time() format
327 # Find "Shorthand" Date
328 if ( $datestring =~ /\d\d?\/\d\d?\/\d\d\d?\d?/) {
329 if ( $use_UK_dates eq 0) {
331 $datestring =~ s/(\d\d?)\/(\d\d?)\/(\d\d\d?\d?)//;
337 $datestring =~ s/(\d\d?)\/(\d\d?)\/(\d\d\d?\d?)//;
343 # Now, clean up year if 2 digit
344 # You may change the 70 to whatever cutoff you like
345 $year += 2000 if ($year < 70 );
346 $year += 1900 if ($year < 100);
350 $mon = 0 if ($datestring =~ s/(Jan|January)//i);
351 $mon = 1 if ($datestring =~ s/(Feb|February)//i);
352 $mon = 2 if ($datestring =~ s/(Mar|March)//i);
353 $mon = 3 if ($datestring =~ s/(Apr|April)//i);
354 $mon = 4 if ($datestring =~ s/(May)//i);
355 $mon = 5 if ($datestring =~ s/(Jun|June)//i);
356 $mon = 6 if ($datestring =~ s/(Jul|July)//i);
357 $mon = 7 if ($datestring =~ s/(Aug|August)//i);
358 $mon = 8 if ($datestring =~ s/(Sep|September)//i);
359 $mon = 9 if ($datestring =~ s/(Oct|October)//i);
360 $mon = 10 if ($datestring =~ s/(Nov|November)//i);
361 $mon = 11 if ($datestring =~ s/(Dec|December)//i);
364 if ($datestring =~ s/(\d\d?):(\d\d)(:\d\d)?//) {
370 if ($datestring =~ s/(\d\d\d\d)//) {
374 if ($datestring =~ s/(\d\d?)//) {
378 return timelocal($sec,$min,$hour,$day,$mon,$year);
383 return 1 if (! $strip_meta_dates);
384 # This code based on Rael's meta plugin
385 my($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_;
387 # Strip date-based meta tags from body
388 $$body_ref =~ s/^$meta_timestamp.*//g;
389 $$body_ref =~ s/^$meta_date.*//g;
401 Blosxom Plug-in: entries_cache
405 Purpose: This plugin reserves original creation timestamp on weblog
406 entries, allowing for editing of entries without altering the original
407 creation time. It maintains an index ($blosxom::plugin_state_dir/
408 .entries_cache.index) of filenames and their creation times. It also adds
409 new entries to the index the first time Blosxom come across them. In
410 addition, it is possible to rely on entries_cache inserting date-based meta
411 tags automatically into entries - this is enabled by the $use_date_tags
412 setting. This makes the entries more portable. Note that if this approach
413 is used, the meta plugin is required: http://www.blosxom.com/downloads/
414 plugins/meta. (NOTE: As of version 0.91 you can use this without the meta
417 Replaces the default $blosxom::entries subroutine
419 The entries_cache plugin is a "souped-up" version of the entries_index
420 plugin. It maintains file modification times in the same manner as the
421 original plugin, but goes one-step further. It uses the modification time
422 of the index file to determine whether to rescan the datadir. If $delay
423 minutes have not passed, it relies on the cached information.
425 You can force a manual scan by appending ?reindex=y to the end of your base
428 The reason for this change is that the original blosxom and the
429 entries_index plugin rescan the datadir each time a page is viewed. This
430 plugin allows you to cache the information to speed up processing times on
431 most page views. According to several posts on the blosxom mailing list,
432 this is one of the big processor hogs. With a $delay setting of 60 minutes,
433 there will only be one page view each hour that has to wait for the full
434 directory scan. To be honest, I have not noticed much of a speed boost
435 during my testing yet, but I imagine it would only appear for sites with a
436 large number of files to be indexed.
443 =head1 VERSION HISTORY
444 0.92 Checks if meta-creation_date is in the future and only displays
445 entry if $show_future_entries is set. Otherwise future articles
446 (by meta-creation_date or file modified time) are not displayed.
447 Don't think this breaks static rendering... haven't tested it.
449 0.91 Improved documentation courtesy of Iain Cheyne - THANKS!!!
450 Now, if you are not running the meta plugin, you will not see any meta tags in your stories
452 0.9 Added parser that detects stories that are not properly formatted for meta-tags and reformats them so that they are.
453 Additionally, it will not update files that have improper line endings ( ie non-UNIX endings).
455 0.8 Fixed typo that caused index to be rebuilt every time... :)
457 0.7 Major revisions - fixed the "Year 1900" bug and an issue with statically generated blogs misbehaving
459 0.61 Fixed bug reading old styled cache files
461 0.6 Added feature to automatically create meta-tags from indexed
464 0.52 Fixed a bug where a new index might not be written
466 0.51 Added dd/mm/yy(yy) and mm/dd/yy(yy) date formatting
468 0.5 Complete rewrite - add support for %others, meta- tags, added backwards compatibility to using the .entries_index.index file from rael's plugin
470 0.2 Removed reliance on Data::Dumper, making it suitable for use on Earthlink
475 Modified by Steve Schwarz
476 based on original code by:
477 Rael Dornfest <rael@oreilly.com>, http://www.raelity.org/
481 Blosxom Home/Docs/Licensing: http://www.raelity.org/apps/blosxom/
483 Blosxom Plugin Docs: http://www.raelity.org/apps/blosxom/plugin.shtml
487 Address bug reports and comments to the Blosxom mailing list
488 [http://www.yahoogroups.com/group/blosxom].
493 Copyright 2003, Fletcher Penney
494 except for portions copied from entries_index and entries_index_tagged
496 Blosxom and original entries_index plugin
497 Copyright 2003, Rael Dornfest
499 Permission is hereby granted, free of charge, to any person obtaining a
500 copy of this software and associated documentation files (the "Software"),
501 to deal in the Software without restriction, including without limitation
502 the rights to use, copy, modify, merge, publish, distribute, sublicense,
503 and/or sell copies of the Software, and to permit persons to whom the
504 Software is furnished to do so, subject to the following conditions:
506 The above copyright notice and this permission notice shall be included
507 in all copies or substantial portions of the Software.
509 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
510 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
511 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
512 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
513 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
514 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
515 OTHER DEALINGS IN THE SOFTWARE.