Add entries_cache_meta to general.
[matthijs/upstream/blosxom-plugins.git] / general / autocorrect
1 # Blosxom Plugin: autocorrect                                      -*- perl -*-
2 # Author: Todd Larason (jtl@molehill.org)
3 # Version: 0+1i
4 # Blosxom Home/Docs/Licensing: http://blosxom.sourceforge.net/
5 # AutoCorrect plugin Home/Docs/Licensing:
6 #  http://molelog.molehill.org/blox/Computers/Internet/Web/Blosxom/AutoCorrect/
7
8 package autocorrect;
9
10 # --- Configuration Variables ---
11
12 $debug_level = 0;
13
14 # -------------------------------
15
16
17 use CGI;
18 use FileHandle;
19
20 my $package = 'autocorrect';
21 my @goodhits = ();
22 my $activated = 0;
23 my %template = ();
24 my $flav_cache;
25
26 sub debug {
27     my ($level, @msg) = @_;
28
29     if ($debug_level >= $level) {
30         print STDERR "$package debug $level: @msg\n";
31     }
32 }
33
34 sub load_template {
35  my ($bit) = @_;
36  my $fh = new FileHandle;
37     
38  return $flav_cache{$bit} ||=
39   ($fh->open("< $blosxom::datadir/$package.$bit.$blosxom::flavour") ?
40     join '',<$fh> : $template{$blosxom::flavour}{$bit}) ||
41   ($fh->open("< $blosxom::datadir/$package.$bit.$blosxom::default_flavour") ?
42     join '',<$fh> : $template{$blosxom::default_flavour}{$bit}) || 
43   ($fh->open("< $blosxom::datadir/$package.$bit.html") ?
44     join '',<$fh> : $template{html}{$bit}) || 
45   '';
46 }
47
48
49 sub report {
50     my ($bit, $path, $text) = @_;
51
52     my $f = load_template($bit);
53     $f =~ s/((\$[\w:]+)|(\$\{[\w:]+\}))/$1 . "||''"/gee;
54     return $f;
55 }
56
57 sub start {
58     if ($blosxom::static_or_dynamic eq 'dynamic') {
59         debug(1, "start() called, enabled");
60         while (<DATA>) {
61             last if /^(__END__)?$/;
62             my ($flavour, $comp, $txt) = split ' ',$_,3;
63             $txt =~ s:\\n:\n:g;
64             $template{$flavour}{$comp} = $txt;
65         }
66         return 1;
67     } else {
68         debug(1, "start() called, but in static mode -- not enabling");
69         return 0;
70     }
71 }
72
73 sub filter {
74     my ($pkg, $files_ref) = @_;
75     my $datepart;
76     my $path_info = path_info();
77
78     debug(2, "filter() called, path_info = $path_info");
79
80     # handle normal cases as fast as possible -- no path, a category
81     # path, or a category + file that exists
82     return 1 if ($path_info eq '');
83     return 1 if ($path_info !~ s!\.[^.]+$!.$blosxom::file_extension!);
84     return 1 if (defined($files_ref->{"$blosxom::datadir$path_info"}));
85
86     debug(2, "fasttrack failed, splitting path");
87
88     # at this point, $path_info is (category + optional date + filename)
89     # and either the file doesn't exist in that category, or the
90     # date field is being used along with a full filename
91
92     # this is straight from blosxom itself, and should be kept in-sync
93     my @path_info = split '/', $path_info;
94     my $filename = pop @path_info;
95     return 1 if ($filename eq "index.$blosxom::file_extension");
96     shift @path_info; # remove empty '' before first /
97     $path_info = '';
98     while ($path_info[0] and 
99            $path_info[0] =~ /^[a-zA-Z].*$/ and 
100            $path_info[0] !~ /(.*)\.(.*)/) { 
101         $path_info .= '/' . shift @path_info; 
102     }
103
104     debug(2, "path_info=$path_info, filename=$filename");
105
106     # @path_info may have date info in it still, but we're not interested
107
108     return 1 if defined($files_ref->{"blosxom::datadir$path_info/$filename"});
109     
110     debug(2, "Still not found, looking for good matches");
111
112     # okay, it doesn't exist -- it's okay to spend some time now, since
113     # slow results are better than no results
114
115     # XXX this should be quite a bit smarter -- 'sounds like', 'typoed like'
116     # look at what mod_speling does
117     $activated = 1;
118     foreach (keys %$files_ref) {
119         my ($this_filename) = m:([^/]+)$:;
120         if ($filename eq $this_filename) {
121             push(@goodhits, $_);
122             debug(2, "Found good hit: $_");
123         }
124     }
125     $files_ref->{"$blosxom::datadir$path_info/$filename"} =     
126         $#goodhits == 0 ? $files_ref->{$goodhits[0]} : time;
127     return 1;
128 }
129
130 sub story {
131     return 1 if !$activated;
132     my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_;
133
134     if ($#goodhits == -1) {
135         debug(2, "in story(), no good hits");
136         $$title_ref = report('not_found_title');
137         $$body_ref  = report('not_found_body');
138     } elsif ($#goodhits == 0) {
139         debug(2, "in story(), 1 good hit");
140         # just one, easy case to deal with
141         my $fh = new FileHandle;
142         if ($fh->open($goodhits[0])) {
143             debug(3, "opened $goodhits[0]");
144             # convert from filename to path+filename (w/o extension)
145             $goodhits[0] =~ s!$blosxom::datadir(.*)\.[^./]+$!\1!;
146             chomp(my $title = <$fh>);
147             $$title_ref = report('found_one_title', $goodhits[0], $title);
148             $$body_ref = report('found_one_body',$goodhits[0],(join '',<$fh>));
149         } else {
150             debug(3, "Couldn't open $goodhits[0]: $!");
151             $goodhits[0] =~ s!$blosxom::datadir(.*)\.[^./]+$!\1!;
152             $$title_ref = report('error_title', $goodhits[0]);
153             $$body_ref = report('error_body', $goodhits[0]);
154         }
155     } else {
156         debug(2, "in story(), multiple matches");
157         $$title_ref = report('multi_title');
158         $$body_ref = report('multi_body_head');
159         map {
160             $_ =~ s!$blosxom::datadir(.*)\.[^./]+$!\1!; 
161             $$body_ref .= report('multi_body_item', $_)
162         } @goodhits;
163         $$body_ref .= report('multi_body_foot');
164     }
165     return 1;
166 }
167
168 1;
169 __DATA__
170 html not_found_title Not Found
171 html not_found_body <p>The file you asked for doesn't exist, and I'm afraid I couldn't find a good match for it.  I'm sorry.</p>\n
172 html found_one_title $text
173 html found_one_body <p>The file you asked for doesn't exist; it may have been moved.  This is actually <a href="$blosxom::url$path.$blosxom::flavour">$path</a>.</p><hr>$text
174 html error_title Error
175 html error_body <p>The file you asked for doesn't exist, and I thought I'd found a replacement with $path, but I can't open it.  Sorry</p>
176 html multi_title Possible Matches
177 html multi_body_head <p>The file you asked for doesn't exist.  Some possible matches are:</p><ul>\n
178 html multi_body_item <li><a href="$blosxom::url$path.$blosxom::flavour">$path</a></li>\n
179 html multi_body_foot </ul>\n
180 __END__