]> bicyclesonthemoon.info Git - ott/bsta/blobdiff - opomba.1.pl
improve GOTO handling
[ott/bsta] / opomba.1.pl
index 2ae8adc8169584f35c0f4ee1bd351fd19fad13fe..639097a9774708b42f646d866ccc3a58fe016bd0 100644 (file)
@@ -27,16 +27,18 @@ use Encode ('encode', 'decode');
 
 ###PERL_LIB: use lib /botm/lib/bsta
 use botm_common (
+       'HTTP_STATUS',
        'read_header_env', 'url_query_decode',
-       'read_data_file', 'write_data_file',
+       'write_data_file',
        'html_entity_encode_dec',
        'open_encoded',
        'join_path',
        'merge_url',
-       'make_id'
+       'make_id',
+       'http_header_status'
 );
 use bsta_lib (
-       'TEXT_MODE',
+       'TEXT_MODE', 'STATE',
        'get_password',
        'fail_method', 'fail_content_type',
        'redirect',
@@ -44,7 +46,12 @@ use bsta_lib (
        'print_html_head_start', 'print_html_head_end',
        'print_html_body_start', 'print_html_body_end',
        'bb_to_html', 'eval_bb',
-       'merge_settings'
+       'merge_settings',
+       'write_index', 'write_static_viewer_page',
+       'read_settings', 'read_state',
+       'read_words', 'write_words',
+       'read_words_list', 'write_words_list'
+       
 );
 
 ###PERL_PATH_SEPARATOR:     PATH_SEPARATOR     = /
@@ -52,9 +59,9 @@ use bsta_lib (
 ###PERL_CGI_VIEWER_PATH:    CGI_VIEWER_PATH    = /bsta/v
 ###PERL_CGI_WORDS_PATH:     CGI_WORDS_PATH     = /bsta/w
 
-###PERL_DATA_SETTINGS_PATH: DATA_SETTINGS_PATH = /botm/data/bsta/settings
 ###PERL_DATA_WORDS_PATH:    DATA_WORDS_PATH    = /botm/data/bsta/words/
 
+###PERL_LOG_SPAM_PATH:      LOG_SPAM_PATH      = /botm/log/bsta/words_spam.log
 ###PERL_LOG_WORDS_PATH:     LOG_WORDS_PATH     = /botm/log/bsta/words.log
 
 ###PERL_WEBSITE_NAME:       WEBSITE_NAME       = Bicycles on the Moon
@@ -71,25 +78,30 @@ srand ($time-$$);
 
 my %http;
 my %cgi;
+my %state;
 my %settings;
 my %words_data;
 my %post_data;
+my %last_post_data;
 
 my @post_list;
 
 my $method;
 my $frame;
 my $ID;
+my $last_ID;
 my $password;
 my $password_ok;
+my $access;
 my $edit = 0;
 my $remove = 0;
 my $post = 0;
 my $quote;
 my $words_data_path;
-my $post_data_path;
 my $index;
 my $page;
+my $ong_state;
+my $last_frame;
 my $fh;
 my $r;
 
@@ -101,7 +113,7 @@ if ($ENV{'REQUEST_METHOD'} =~ /^(HEAD|GET|POST)$/) {
        $method = $1;
 }
 else {
-       exit fail_method($ENV{'REQUEST_METHOD'}, 'GET, POST, HEAD');
+       exit fail_method($ENV{'REQUEST_METHOD'}, ['GET', 'POST', 'HEAD']);
 }
 
 %http = read_header_env(\%ENV);
@@ -132,7 +144,10 @@ if ($cgi{'i'} =~ /^.+$/) {
 }
 $password = get_password(\%cgi);
 
-%settings   = read_data_file(DATA_SETTINGS_PATH());
+%settings = read_settings();
+%state    = read_state();
+$ong_state = int($state{'state'});
+$last_frame = int($state{'last'});
 
 $password_ok = ($password eq $settings{'password'});
 
@@ -159,15 +174,23 @@ else {
 }
 
 if ($ID ne '') {
-       $post_data_path = join_path(PATH_SEPARATOR(), DATA_WORDS_PATH(), $ID);
-       %post_data = read_data_file($post_data_path);
+       %post_data = read_words($ID);
        if ($post_data{'frame'} ne '') {
                $frame = int($post_data{'frame'});
        }
 }
 
-if ($frame eq '') {
-       exit output(0, '400 Bad Request', 'Frame ID not specified.');
+unless ($frame ne '') {
+       exit output(0, HTTP_STATUS->{'bad_request'}, 'Frame ID not specified.');
+}
+$access = (
+       $password_ok || (
+               ($ong_state >= STATE->{'waiting'}) &&
+               ($frame <= $last_frame)
+       )
+);
+unless ($access) {
+       exit output(0, HTTP_STATUS->{'forbidden'}, 'Not allowed to post this here now');
 }
 
 $words_data_path = join_path(PATH_SEPARATOR(), DATA_WORDS_PATH(), $frame);
@@ -178,15 +201,12 @@ unless (open_encoded($fh, "+<:encoding(UTF-8)", $words_data_path)) {
        }
 }
 unless (flock($fh, 2)) {
-       exit output(0, '500 Internal Server Error', 'Failed locking data file.', 1);
+       exit output(0, HTTP_STATUS->{'internal_server_error'}, 'Failed locking data file.', 1);
 }
 
-%words_data = read_data_file(
+%words_data = read_words_list(
        $fh, # file
-       '',  # encoding
-       0,   # no header
        0,   # header only
-       1    # as list
 );
 
 @post_list = @{$words_data{'content'}};
@@ -202,44 +222,44 @@ for (my $i=0; $i< scalar(@post_list); $i +=1) {
 if ($remove || ($ID ne '')) {
        unless ($index ne '') {
                close($fh);
-               exit output(0, '404 Not Found', $remove ? 'Nothing to remove.' : 'No such message.');
+               exit output(0, HTTP_STATUS->{'not_found'}, $remove ? 'Nothing to remove.' : 'No such message.');
        }
        unless ($cgi{'key'} eq $post_data{'key'}) {
                close($fh);
-               exit output(0, '400 Bad Request', 'Invalid request.');
+               exit output(0, HTTP_STATUS->{'bad_request'}, 'Invalid request.');
        }
 }
 if ($remove) {
-       if ($cgi{'i'} eq '') { # followed a link, not confirmed yet
+       unless (($method eq 'POST') && ($cgi{'i'} ne '')) { # followed a link, not confirmed yet
                close($fh);
                exit output(0, '', '', 1);
        }
 }
 else {
-       unless ($post) { # followed a link, not confirmed yet
+       unless (($method eq 'POST') && $post) { # followed a link, not confirmed yet
                close($fh);
                exit output(0, '', '', 1);
        }
 }
 if (!$remove) {
        unless ($cgi{'words'} ne '') {
-               exit output(0, '400 Bad Request', 'Where are your words?', 1);
+               exit output(0, HTTP_STATUS->{'bad_request'}, 'Where are your words?', 1);
        }
 }
 unless ($cgi{'username'} ne '') {
        close($fh);
-       exit output(0, '400 Bad Request', 'Missing user name.', 1);
+       exit output(0, HTTP_STATUS->{'bad_request'}, 'Missing user name.', 1);
 }
 if ($remove || ($ID ne '')) {
        unless ($cgi{'username'} eq $post_data{'name'}) {
                close($fh);
-               exit output(0, '403 Forbidden', 'Wrong user name.', 1);
+               exit output(0, HTTP_STATUS->{'forbidden'}, 'Wrong user name.', 1);
        }
 }
 if ($remove || ($ID ne '')) {
                unless ($cgi{'password'} ne '') {
                close($fh);
-               exit output(0, '400 Bad Request', 'Missing password.', 1);
+               exit output(0, HTTP_STATUS->{'bad_request'}, 'Missing password.', 1);
        }
        unless (
                ($cgi{'password'} eq $post_data{'password'}) || (
@@ -248,7 +268,7 @@ if ($remove || ($ID ne '')) {
                )
        ) {
                close($fh);
-               exit output(0, '403 Forbidden', 'Wrong password.', 1);
+               exit output(0, HTTP_STATUS->{'forbidden'}, 'Wrong password.', 1);
        }
        if ($password_ok) {
                $cgi{'password'} = $post_data{'password'};
@@ -256,8 +276,24 @@ if ($remove || ($ID ne '')) {
 }
 unless ($cgi{'password2'} eq '') {
        close($fh);
-       exit output(0, '', 'Please don\'t write anything in the place which should remain empty.', 1);
        # no error code to confuse spambot :)
+       output(0, '', 'Please don\'t write anything in the place which should remain empty.', 1);
+       if (open_encoded($fh, ">>:encoding(UTF-8)", LOG_SPAM_PATH())) {
+               $cgi{'content'} = $cgi{'words'};
+               $cgi{'empty'} = $cgi{'password2'};
+               delete($cgi{'words'});
+               delete ($cgi{'password'});
+               delete ($cgi{'password2'});
+               print $fh "$time SPAM $ID\n";
+               write_data_file(
+                       $fh, \%cgi, '',
+                       0, 0, 0,
+                       '>>', 1
+               );
+               print $fh "\n\n";
+               close ($fh);
+       }
+       exit;
 }
 
 # all conditions fulfilled
@@ -267,17 +303,10 @@ if ($remove) {
        $words_data{'posts'} = scalar(@post_list);
        $words_data{'content'} = \@post_list;
        
-       $r = write_data_file(
-               $fh, # file 
-               \%words_data,
-               '',  # encoding
-               0,   # no header
-               0,   # header only
-               1    # as list
-       );
+       $r = write_words_list($fh, \%words_data);
        unless ($r) {
                close($fh);
-               exit output(0, '500 Internal Server Error', 'Failed writing data file.');
+               exit output(0, HTTP_STATUS->{'internal_server_error'}, 'Failed writing data file.');
        }
        
        close ($fh);
@@ -304,13 +333,25 @@ if ($ID eq '') {
 if ($index eq '') {
        $index = scalar(@post_list);
        $page = int($index / COMMENT_PAGE_LENGTH());
+       if ($index > 0) {
+               $last_ID = $post_list[-1];
+               %last_post_data = read_words($last_ID);
+               if (
+                       ($cgi{'username'} eq $last_post_data{'name'   }) &&
+                       ($cgi{'words'   } eq $last_post_data{'content'})
+               ) { # duplicate post
+                       $index -= 1;
+                       $page = int($index / COMMENT_PAGE_LENGTH());
+                       $ID = $last_ID;
+                       close ($fh);
+                       exit output(1);
+               }
+       }
        push @post_list, $ID;
 }
 $words_data{'posts'} = scalar(@post_list);
 $words_data{'content'} = \@post_list;
 
-$post_data_path = join_path(PATH_SEPARATOR(), DATA_WORDS_PATH(), $ID);
-
 $post_data{'frame'} = $frame;
 $post_data{'name'} = $cgi{'username'};
 $post_data{'password'} = $cgi{'password'};
@@ -329,27 +370,36 @@ if ($post_data{'key'} eq '') {
 }
 $post_data{'content'} = $cgi{'words'};
 
-$r = write_data_file($post_data_path, \%post_data);
+$r = write_words($ID, \%post_data);
 unless ($r) {
        close($fh);
-       exit output(0, '500 Internal Server Error', 'Failed writing post file.', 1, 0);
+       exit output(0, HTTP_STATUS->{'internal_server_error'}, 'Failed writing post file.', 1, 0);
 }
 
-$r = write_data_file(
-       $fh, # file 
-       \%words_data,
-       '',  # encoding
-       0,   # no header
-       0,   # header only
-       1    # as list
-);
+$r = write_words_list($fh, \%words_data);
 unless ($r) {
        close($fh);
-       exit output(0, '500 Internal Server Error', 'Failed writing data file.', 1, 0);
+       exit output(0, HTTP_STATUS->{'internal_server_error'}, 'Failed writing data file.', 1, 0);
 }
 
 close($fh);
 
+if (($frame == 0) && ($ong_state > STATE->{'inactive'})) {
+       write_index(\%state, \%settings);
+}
+elsif ($frame >= 1) {
+       write_static_viewer_page(
+               $frame,
+               \%state,
+               \%settings,
+               '', # default
+               '', # frame data
+               '', # prev frame data
+               '', # next frame data
+               \%words_data
+       );
+}
+
 if (open_encoded($fh, ">>:encoding(UTF-8)", LOG_WORDS_PATH())) {
        delete ($post_data{'password'});
        print $fh "$time POST $ID\n";
@@ -368,7 +418,6 @@ exit output(1);
 sub output {
        (my $done, my $status, my $message, my $show_content) = @_;
        
-       
        my $return_url = merge_url(
                {'path' => CGI_VIEWER_PATH()},
                {
@@ -382,14 +431,13 @@ sub output {
                }
        );
        if ($done) {
-               return redirect ($method, $return_url, 303);
+               return redirect($method, $return_url, HTTP_STATUS->{'see_other'});
        }
        
-       print "Content-type: text/html\n";
        if ($status ne '') {
-               print 'Status: '.$status."\n";
+               print http_header_status($status);
        }
-       print "\n";
+       print "Content-type: text/html; charset=UTF-8\n\n";
        if ($method eq 'HEAD') {
                return;
        }
@@ -407,6 +455,9 @@ sub output {
        else {
                $title = 'Words';
        }
+       if ($frame ne '') {
+               $title = $frame.'. '.$title;
+       }
        
        if ($cgi{'username'} ne '') {
                $name = $cgi{'username'}
@@ -422,8 +473,7 @@ sub output {
                $content = $cgi{'words'};
        }
        elsif ($quote ne '') {
-               my $quote_data_path = join_path(PATH_SEPARATOR(), DATA_WORDS_PATH(), $quote);
-               my %quote_data = read_data_file($quote_data_path);
+               my %quote_data = read_words($quote);
                $content = '[quote="'.$quote_data{'name'}.'"]'.$quote_data{'content'}.'[/quote]';
        }
        elsif (($cgi{'edit'} ne '') || $remove) {
@@ -433,11 +483,11 @@ sub output {
                $content = '';
        }
        
+       my $_password = $password_ok ? html_entity_encode_dec($settings{'password'}, 1) : '';
        my $_key = html_entity_encode_dec($post_data{'key'}, 1);
        my $_ID = html_entity_encode_dec($ID, 1);
        my $_title = html_entity_encode_dec($title, 1);
        my $_message = html_entity_encode_dec($message, 1);
-       my $_password = html_entity_encode_dec($settings{'password'}, 1);
        my $_story = html_entity_encode_dec($settings{'story'}, 1);
        my $_name = html_entity_encode_dec($name, 1);
        my $_content = html_entity_encode_dec($content, 1);
@@ -472,9 +522,9 @@ sub output {
                print '   </div>'."\n";
        }
        
+       print '   <div id="insw" class="ins">'."\n";
+       
        if ($show_content) {
-               print '   <div id="insw" class="ins">'."\n";
-               
                print '    <div class="undertext" id="words">'."\n";
                print '     <form method="post" action="'.$_post_url.'">'."\n";
                unless ($remove) {
@@ -518,18 +568,24 @@ sub output {
                        print '       Preview:'."\n";
                        print '      </div>'."\n";
                        print '      <div class="opomba_text">'."\n";
-                 print bb_to_html(eval_bb($content, 0))."\n";
+                 print bb_to_html(
+                               eval_bb(
+                                       $content,
+                                       0,
+                                       $password_ok ? $settings{'password'} : ''
+                               )
+                       )."\n";
                        print '      </div>'."\n";
                        print '     </div>'."\n";
                }
                print '    </div>'."\n";
-               print '    <div id="underlinks">'."\n";
-               print '     <a href="'.$_return_url.'">Return</a>'."\n";
-               print '    </div>'."\n";
-               
-               print '   </div>'."\n";
        }
+       print '    <div id="underlinks">'."\n";
+       print '     <a href="'.$_return_url.'">Return</a>'."\n";
+       print '    </div>'."\n";
+       
+       print '   </div>'."\n";
        
-       print_html_body_end(\*STDOUT); # , $ong_state == STATE->{'inactive'}
+       print_html_body_end(\*STDOUT, $ong_state == STATE->{'inactive'});
        print_html_end(\*STDOUT);
 }