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