root/trunk/index.cgi

Revision 74, 12.3 kB (checked in by jdixon, 1 year ago)

move template html files into themes

  • Property svn:executable set to
Line 
1
2 # Blogsum
3 # Copyright (c) 2009 Jason Dixon <jason@dixongroup.net>
4 # All rights reserved.
5
6
7 ###########################
8 # pragmas and vars        #
9 ###########################
10 use strict;
11 use Blogsum::Config;
12 my $database = $Blogsum::Config::database;
13 my $blog_theme = $Blogsum::Config::blog_theme;
14 my $blog_title = $Blogsum::Config::blog_title;
15 my $blog_subtitle = $Blogsum::Config::blog_subtitle;
16 my $blog_url = $Blogsum::Config::blog_url;
17 my $blog_owner = $Blogsum::Config::blog_owner;
18 my $blog_rights = $Blogsum::Config::blog_rights;
19 my $feed_updates = $Blogsum::Config::feed_updates;
20 my $captcha_pubkey = $Blogsum::Config::captcha_pubkey;
21 my $captcha_seckey = $Blogsum::Config::captcha_seckey;
22 my $comment_max_length = $Blogsum::Config::comment_max_length;
23 my $comments_allowed = $Blogsum::Config::comments_allowed;
24 my $smtp_server = $Blogsum::Config::smtp_server;
25 my $smtp_sender = $Blogsum::Config::smtp_sender;
26 my $articles_per_page = $Blogsum::Config::articles_per_page;
27 my $google_analytics_id = $Blogsum::Config::google_analytics_id;
28 my $google_webmaster_id = $Blogsum::Config::google_webmaster_id;
29
30
31 ###########################
32 # main execution          #
33 ###########################
34 my $cgi = CGI->new;
35 my $dbh = DBI->connect("DBI:SQLite:dbname=$database", '', '', { RaiseError => 1 }) || die $DBI::errstr;
36 my $template = HTML::Template->new(filename => "themes/${blog_theme}/index.tmpl", die_on_bad_params => 0);
37 if ($cgi->param('rss')) {
38         output_rss();
39 } else {
40         read_comment() if $comments_allowed;
41         my $articles = get_articles();
42         my $archives = get_archives();
43         $template->param( archives => $archives );
44         $template->param( theme => $blog_theme );
45         $template->param( title => $blog_title );
46         $template->param( subtitle => $blog_subtitle );
47         $template->param( copyright => $blog_rights );
48         $template->param( google_analytics_id => $google_analytics_id );
49         $template->param( google_webmaster_id => $google_webmaster_id );
50         if (@{$articles}) {
51                 $template->param( articles => $articles );
52                 if ($cgi->param('uri') && $comments_allowed) {
53                         $template->param( comment_form => 1 );
54                         $template->param( comment_max_length => $comment_max_length );
55                         $template->param( id => $articles->[0]->{'id'} );
56                 }
57         } else {
58                 $template->param( error => '404 post not found' );
59         }
60         print $cgi->header(), $template->output;
61 }
62 $dbh->disconnect;
63
64
65 ###########################
66 # subfunctions            #
67 ###########################
68
69 sub output_rss {
70
71         my $version = ($cgi->param('rss') == 2) ? '2.0' : '1.0';
72         my $rss = XML::RSS->new( version => $version );
73
74         $rss->channel (
75                 title => $blog_title,
76                 link => $blog_url,
77                 description => $blog_subtitle,
78                 dc => {
79                         subject => $blog_title,
80                         creator => $blog_owner,
81                         publisher => $blog_owner,
82                         rights => $blog_rights,
83                         language => 'en-us',
84                 },
85                 syn => {
86                         updatePeriod => $feed_updates,
87                         updateFrequency => 1,
88                         updateBase => '1901-01-01T00:00+00:00',
89                 }
90         );
91
92         my $articles = get_articles();
93         for my $item (@{$articles}) {
94                 $item->{'date'} =~ /(\d{4})\-(\d{2})\-\d{2} \d{2}\:\d{2}\:\d{2}/;
95                 ($item->{'year'}, $item->{'month'}) = ($1, $2);
96                 my $link = sprintf("%s%s/%s/%s", $blog_url, $item->{'year'}, $item->{'month'}, $item->{'uri'});
97
98                 if ($version eq '2.0') {
99                         $rss->add_item (
100                                 title => $item->{'title'},
101                                 link => $link,
102                                 description => $item->{'body'},
103                                 author => $item->{'author'},
104                                 category => [split(/,/, $item->{'tags'})],
105                                 comments => $link . '#comments',
106                                 pubDate => POSIX::strftime("%a, %d %b %Y %H:%M:%S %Z", gmtime($item->{'epoch'})),
107                         );
108                 } else {
109                         $rss->add_item (
110                                 title => $item->{'title'},
111                                 link => $link,
112                                 description => $item->{'body'},
113                                 dc => {
114                                         subject => $blog_title,
115                                         creator => $item->{'author'},
116                                         date => POSIX::strftime("%a, %d %b %Y %H:%M:%S %Z", gmtime($item->{'epoch'})),
117                                 },
118                         );
119                 }
120         }
121         print $cgi->header('application/rss+xml'), $rss->as_string;
122 }
123
124 sub get_articles {
125
126         my $page;
127         my $offset;
128         my $limit_clause;
129         my $where_clause;
130         my $j = 0;
131         my $show_comments = 0;
132
133         $articles_per_page = ($articles_per_page > 0) ? $articles_per_page : -1;
134         if ($cgi->param('page') && POSIX::isdigit($cgi->param('page'))) {
135                 $page = $cgi->param('page');
136                 $offset = ($page - 1) * $articles_per_page;
137         } else {
138                 $page = 1;
139                 $offset = 0;
140         }
141         $limit_clause = " LIMIT $articles_per_page OFFSET $offset";
142
143         if (($cgi->param('year') =~ /\d{4}/)&& (1900 < $cgi->param('year')) && ($cgi->param('year') < 2036)) {
144                 $where_clause .= 'WHERE date LIKE \'%' . $cgi->param('year');
145                 $j++;
146                 if (($cgi->param('month') =~ /\d{2}/) && (0 < $cgi->param('month')) && ($cgi->param('month') < 12)) {
147                         $where_clause .= '-' . $cgi->param('month') . '%\' AND enabled=1 ';
148                         $j++;
149                         if ($cgi->param('uri') =~ /\w+/) {
150                                 $where_clause .= 'AND uri=? AND enabled=1 ';
151                                 $limit_clause = '';
152                                 $j++;
153                                 $show_comments=1;
154                         }
155                 } else {
156                         $where_clause .= "\%' AND enabled=1 ";
157                 }
158         } elsif ($cgi->param('search')) {
159                 $where_clause .= "WHERE (tags LIKE ? OR author LIKE ?) AND enabled=1 ";
160
161         } elsif ($cgi->param('id')) {
162                 $where_clause .= 'WHERE id=? AND enabled=1 ';
163                 $limit_clause = '';
164                 $show_comments=1;
165
166         } else {
167                 $where_clause .= 'WHERE enabled=1 ';
168         }
169
170         my $query = 'SELECT *, strftime("%s", date) AS epoch FROM articles ' . $where_clause . 'ORDER BY date DESC' . $limit_clause;
171         my $sth = $dbh->prepare($query);
172        
173         if ($j == 3) {
174                 $sth->execute($cgi->param('uri')) || die $dbh->errstr;
175         } elsif ($cgi->param('search')) {
176                 my $search_tag = sprintf("%%%s%%", $cgi->param('search'));
177                 $sth->execute($search_tag, $search_tag) || die $dbh->errstr;
178         } elsif ($cgi->param('id')) {
179                 $sth->execute($cgi->param('id')) || die $dbh->errstr;
180         } else {
181                 $sth->execute() || die $dbh->errstr;
182         }
183
184         my @articles;
185         while (my $result = $sth->fetchrow_hashref) {
186                 $result->{'date'} =~ /(\d{4})\-(\d{2})\-\d{2} \d{2}\:\d{2}\:\d{2}/;
187                 ($result->{'year'}, $result->{'month'}) = ($1, $2);
188                 # cut off readmore if we're on the front page
189                 if (($result->{'body'} =~ /<!--readmore-->/) && ($j < 3) && !($cgi->param('rss'))) {
190                         $result->{'body'} =~ /(.*)\<\!\-\-readmore\-\-\>/s;
191                         $result->{'body'} = $1;
192                         $result->{'readmore'}++;
193                 }
194                 $result->{'tag_loop'} = format_tags($result->{'tags'}) if ($result->{'tags'});
195                 my $comments = get_comments(article_id => $result->{'id'}, enabled => 1);
196                 $result->{'comments_count'} = scalar(@{$comments});
197                 if ($show_comments) {
198                         $result->{'comments'} = $comments;
199                 }
200                 push(@articles, $result);
201         }
202
203         my $query2 = 'SELECT count(*) as total FROM articles WHERE enabled=1';
204         my $sth2 = $dbh->prepare($query2);
205         $sth2->execute || die $dbh->errstr;
206         my $article_count = $sth2->fetchrow_hashref->{'total'};
207         if ($j < 3) {
208                 $template->param( page_next => ($page + 1) ) if ($article_count > ($offset + $articles_per_page));
209                 $template->param( page_last => ($page - 1) ) if (($page > 1) && ($article_count > $offset));
210         }
211
212         return (\@articles);
213 }
214
215 sub get_archives {
216
217         my %history;
218         my @archives;
219         my @archives_compressed;
220         my $current_year = $cgi->param('year') || ((localtime)[5] + 1900);
221         my %months = (
222                         '01' => 'January',
223                         '02' => 'February',
224                         '03' => 'March',
225                         '04' => 'April',
226                         '05' => 'May',
227                         '06' => 'June',
228                         '07' => 'July',
229                         '08' => 'August',
230                         '09' => 'September',
231                         '10' => 'October',
232                         '11' => 'November',
233                         '12' => 'December',
234         );
235         my $current_month = $cgi->param('month') || sprintf("%0.2d", ((localtime)[4] + 1));
236
237         my $query = 'SELECT * FROM articles WHERE enabled=1 ORDER BY date DESC';
238         my $sth = $dbh->prepare($query);
239         $sth->execute || die $dbh->errstr;
240         while (my $result = $sth->fetchrow_hashref) {
241                 $result->{'date'} =~ /(\d{4})\-(\d{2})\-\d{2} \d{2}\:\d{2}\:\d{2}/;
242                 ($result->{'year'}, $result->{'month'}) = ($1, $2);
243                 my $title = my $full_title = $result->{'title'};
244                 if (length($title) > 28) {
245                         $title = substr($title, 0, 25) . '...';
246                 }
247
248                 if (($result->{'year'} eq $current_year) && ($result->{'month'} eq $current_month) && $result->{'uri'}) {
249                         push(@{$history{$result->{'year'}}{$result->{'month'}}->{'uri_loop'}},
250                                 {
251                                         year => $result->{'year'},
252                                         month => $result->{'month'},
253                                         month_name => $months{$result->{'month'}},
254                                         title => $title,
255                                         full_title => $full_title,
256                                         uri => $result->{'uri'},
257                                 }
258                         );
259                 } else {
260                         $history{$result->{'year'}}->{$result->{'month'}}->{'count'}++;
261                 }
262                 $history{$result->{'year'}}->{'count'}++;
263
264         }
265
266         for my $year (sort {$b <=> $a} keys %history) {
267                 no strict "refs";
268                 for my $month (sort {$b <=> $a} keys %{$history{$year}}) {
269                         my $m = {
270                                 'year' => $year,
271                                 'month' => $month,
272                                 'month_name' => $months{$month},
273                                 'count' => $history{$year}->{$month}->{'count'},
274                         };
275                         # check to see if uri_loop exists first
276                         if ($history{$year}->{$month}->{'uri_loop'}) {
277                                 $m->{'uri_loop'} = $history{$year}->{$month}->{'uri_loop'};
278                         }
279                         push(@{$history{$year}->{'month_loop'}}, $m) unless ($month eq 'count');
280                 }
281                 my $y = {
282                         'year' => $year,
283                         'count' => $history{$year}->{'count'},
284                 };
285                 # check to see if we're showing this year, and that month_loop exists
286                 if (($year eq $current_year) && $history{$year}->{'month_loop'}) {
287                         $y->{'month_loop'} = $history{$year}->{'month_loop'};
288                 }
289                 push(@{$history{'year_loop'}}, $y) unless ($year eq 'count');
290         }
291                
292         return \@{$history{'year_loop'}};
293 }
294
295 sub format_tags {
296
297         my $tags = shift;
298         my @tags;
299
300         foreach (split(/,/, $tags)) {
301                 push(@tags, { 'tag' => $_ });
302         }
303
304         return \@tags;
305 }
306
307 sub read_comment {
308
309         my $captcha = Captcha::reCAPTCHA->new;
310         my %friendly_errors = (
311                         'invalid-site-public-key'       => "oh noes, this shouldn't happen",
312                         'invalid-site-private-key'      => "oh noes, this shouldn't happen",
313                         'invalid-request-cookie'        => "oh noes, this shouldn't happen",
314                         'verify-params-incorrect'       => "oh noes, this shouldn't happen",
315                         'invalid-referrer'                      => "oh noes, this shouldn't happen",
316                         'recaptcha-not-reachable'       => "oh noes, this shouldn't happen",
317                         'incorrect-captcha-sol'         => "oopsie, try again",
318         );
319
320         if ($cgi->param('recaptcha_response_field') && $cgi->param('comment') && $cgi->param('id')) {
321
322                 # test our captcha
323                 my $result = $captcha->check_answer( $captcha_seckey, $ENV{'REMOTE_ADDR'}, $cgi->param('recaptcha_challenge_field'), $cgi->param('recaptcha_response_field') );
324
325                 if ($result->{'is_valid'}) {
326
327                         # save comment
328                         my $comment = HTML::Entities::encode($cgi->param('comment'));
329                         my $stmt = "INSERT INTO comments VALUES (NULL, ?, datetime('now'), ?, ?, ?, ?, 0)";
330                         my $sth = $dbh->prepare($stmt);
331                         my $comment_name = $cgi->param('name') ? substr($cgi->param('name'), 0, 100) : 'anonymous';
332                         my $comment_email = $cgi->param('email') ? substr($cgi->param('email'), 0, 100) : undef;
333                         my $comment_url = $cgi->param('url') ? substr($cgi->param('url'), 0, 100) : undef;
334                         my $comment_body = substr(HTML::Entities::encode($cgi->param('comment')), 0, $comment_max_length);
335                         $sth->execute($cgi->param('id'), $comment_name, $comment_email, $comment_url, $comment_body) || die $dbh->errstr;
336                         $template->param( message => 'comment awaiting moderation, thank you' );
337
338                         # send email notification
339                         my $smtp = Net::SMTP->new($smtp_server);
340                         $smtp->mail($ENV{USER});
341                         $smtp->to("$blog_owner\n");
342                         $smtp->data();
343                         $smtp->datasend("From: $smtp_sender\n");
344                         $smtp->datasend("To: $blog_owner\n");
345                         $smtp->datasend("Subject: $blog_title comment submission\n\n");
346                         $smtp->datasend("You have received a new comment submission.\n\n");
347                         $smtp->datasend(sprintf("From: %s\n", $comment_name));
348                         $smtp->datasend(sprintf("Date: %s\n", scalar(localtime)));
349                         $smtp->datasend(sprintf("Comment:\n\"%s\"\n\n", $comment_body));
350                         $smtp->datasend("Moderate comments at ${blog_url}admin.cgi?view=moderate\n");
351                         $smtp->dataend();
352                         $smtp->quit;
353                 } else {
354                         $template->param( error => $friendly_errors{ $result->{'error'} } );
355                         $template->param( name => $cgi->param('name') );
356                         $template->param( email => $cgi->param('email') );
357                         $template->param( url => $cgi->param('url') );
358                         $template->param( comment => $cgi->param('comment') );
359                         $template->param( id => $cgi->param('id') );
360                 }
361         }
362         # present the challenge
363         $template->param( captcha => $captcha->get_html( $captcha_pubkey ) );
364 }
365
366 sub get_comments {
367
368         my %args = @_;
369
370         my $query = 'SELECT * FROM comments WHERE article_id=? AND enabled=? ORDER BY date ASC';
371         my $sth = $dbh->prepare($query);
372         $sth->execute($args{'article_id'}, $args{'enabled'}) || die $dbh->errstr;
373         my @comments;
374         while (my $result = $sth->fetchrow_hashref) {
375                 push(@comments, $result);
376         }
377         return \@comments;
378 }
379
Note: See TracBrowser for help on using the browser.