BBS-Universal

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

```bash
        sudo mysql -u root --skip-password < sql/database_setup.sql
```

You can use the default menu files or change them to your own taste.  See the manual for details.

## DESCRIPTION

A 100% Perl BBS server.  It supports ASCII, ANSI, ATASCII and PETSCII text formats.

* NOTE:  This is still a work in progress.  The ASCII and ANSI features work fine.  ATASCII and PETSCII have not yet been refined and tested.  Also, file upload/download has not been tested.

## CONFIGURATION

The system requires a very minimal static configuration file to give access to the database.  The rest of the configuration is stored in the database.

The file **conf/bbs.rc** :

```
# Minimum Configuration for BBS Universal.  Only Database info goes here.
# The rest resides in the Database.  Comments and empty lines are ignored

files/sysop/manual-sysop-commands.ANSI  view on Meta::CPAN

[% BOLD %][% B_YELLOW %][% BLACK %] SYSOP EDIT CONFIGURATION [% RESET %][% YELLOW %]🭬[% RESET %]

Edit the system configuration

[% BOLD %][% B_YELLOW %][% BLACK %] SYSOP EDIT FILE CATEGORIES [% RESET %][% YELLOW %]🭬[% RESET %]

Edit file system categories

[% BOLD %][% B_YELLOW %][% BLACK %] SYSOP EDIT NEW USERS [% RESET %][% YELLOW %]🭬[% RESET %]

[% JUSTIFIED %]All users default to "USER" access level.  This is a read-only access level.  This command lists each new ueser and allows you to raise their access level to "VETERAN".  Veterans are allowed to post and download/upload files.[% ENDJUST...

[% BOLD %][% B_YELLOW %][% BLACK %] SYSOP EDIT USER [% RESET %][% YELLOW %]🭬[% RESET %]

This allows you to edit any arbitrary user and their attributes.

[% HORIZONTAL RULE BLUE %][% BOLD %][% B_BLUE %][% BRIGHT YELLOW %] SYSOP LIST COMMANDS[% RESET %]

This lists the SysOp commands.

[% BOLD %][% B_YELLOW %][% BLACK %] SYSOP LIST FILES [% RESET %][% YELLOW %]🭬[% RESET %]

lib/BBS/Universal.pm  view on Meta::CPAN

            my $self = shift;
            return ($self->load_menu('files/main/files_menu'));
        },
        'LIST FILES SUMMARY' => sub {
            my $self = shift;
            $self->files_list_summary(FALSE);
            return ($self->load_menu('files/main/files_menu'));
        },
        'UPLOAD FILE' => sub {
            my $self = shift;
            $self->files_upload_choices();
            return ($self->load_menu('files/main/files_menu'));
        },
        'LIST FILES DETAILED' => sub {
            my $self = shift;
            $self->files_list_detailed(FALSE);
            return ($self->load_menu('files/main/files_menu'));
        },
        'SEARCH FILES SUMMARY' => sub {
            my $self = shift;
            $self->files_list_summary(TRUE);

lib/BBS/Universal.pm  view on Meta::CPAN


sub files_list_summary {
    my ($self, $search) = @_;

    $self->{'debug'}->DEBUG(['Start Files List Summary']);
    my $sth;
    my $filter;
    if ($search) {
        $self->prompt('Search for (blank for all)');
        $filter = $self->get_line({ 'type' => STRING, 'max' => 255, 'default' => '' });
        $sth    = $self->{'dbh'}->prepare('SELECT * FROM files_view WHERE (filename LIKE ? OR title LIKE ?) AND category_id=? ORDER BY uploaded DESC');
        $sth->execute('%' . $filter . '%', '%' . $filter . '%', $self->{'USER'}->{'file_category'});
    } else {
        $sth = $self->{'dbh'}->prepare('SELECT * FROM files_view WHERE category_id=? ORDER BY uploaded DESC');
        $sth->execute($self->{'USER'}->{'file_category'});
    }
    my @files;
    my $max_filename = 10;
    my $max_title    = 20;
    if ($sth->rows > 0) {
        while (my $row = $sth->fetchrow_hashref()) {
            push(@files, $row);
            $max_filename = max(length($row->{'filename'}), $max_filename);
            $max_title    = max(length($row->{'title'}),    $max_title);

lib/BBS/Universal.pm  view on Meta::CPAN

        } elsif ($mapping->{$key}->{'command'} eq 'REMOVE FILE' && $self->check_access_level($mapping->{$key}->{'access_level'})) {
            return (TRUE);
        } elsif ($mapping->{$key}->{'command'} eq 'NEXT') {
            return (TRUE);
        } elsif ($mapping->{$key}->{'command'} eq 'BACK') {
            return (FALSE);
        }
    } ## end while ($self->is_connected...)
} ## end sub files_choices

sub files_upload_choices {
    my ($self) = @_;
    my $ckey;

    $self->prompt('File Name? ');
    my $file = $self->get_line({ 'type' => FILENAME, 'max' => 255, 'default' => '' });
    my $ext  = uc($file =~ /\.(.*?)$/);

    $self->prompt('Title (Fiendly name)? ');
    my $title = $self->get_line({ 'type' => STRING, 'max' => 255, 'default' => '' });

lib/BBS/Universal.pm  view on Meta::CPAN

        return (FALSE);
    }
    if ($? == -1) {
        $self->{'debug'}->ERROR(["Could not execute rz:  $!"]);
    } elsif ($? & 127) {
        $self->{'debug'}->ERROR(["File Transfer Aborted:  $!"]);
    } else {
        $self->{'debug'}->DEBUG(['File Transfer Successful']);
    }
    return (TRUE);
} ## end sub files_upload_choices

sub files_list_detailed {
    my ($self, $search) = @_;

    $self->{'debug'}->DEBUG(['Start Files List Detailed']);
    my $sth;
    my $filter;
    my $columns = $self->{'USER'}->{'max_columns'};
    if ($search) {
        $self->prompt('Search for');
        $filter = $self->get_line({ 'type' => STRING, 'max' => 255, 'default' => '' });
        $sth    = $self->{'dbh'}->prepare('SELECT * FROM files_view WHERE (filename LIKE ? OR title LIKE ?) AND category_id=? ORDER BY uploaded DESC');
        $sth->execute('%' . $filter . '%', '%' . $filter . '%', $self->{'USER'}->{'file_category'});
    } else {
        $sth = $self->{'dbh'}->prepare('SELECT * FROM files_view WHERE category_id=? ORDER BY uploaded DESC');
        $sth->execute($self->{'USER'}->{'file_category'});
    }
    my @files;
    if ($sth->rows > 0) {
        $self->{'debug'}->DEBUGMAX(\@files);
        my $table;
        my $mode = $self->{'USER'}->{'text_mode'};
        while (my $row = $sth->fetchrow_hashref()) {
            push(@files, $row);
        }

lib/BBS/Universal.pm  view on Meta::CPAN

                $self->output("\n" . '[% HORIZONTAL RULE GREEN %]' . "\n");
                $self->output('[% B_BLUE %][% BRIGHT WHITE %]       TITLE [% RESET %] ' . $record->{'title'} . "\n");
                $self->output('[% B_BLUE %][% BRIGHT WHITE %]    FILENAME [% RESET %] ' . $record->{'filename'} . "\n");
                $self->output('[% B_BLUE %][% BRIGHT WHITE %]   FILE SIZE [% RESET %] ' . format_number($record->{'file_size'}) . "\n");
                if ($record->{'prefer_nickname'}) {
                    $self->output('[% B_BLUE %][% BRIGHT WHITE %]    UPLOADER [% RESET %] ' . $record->{'nickname'} . "\n");
                } else {
                    $self->output('[% B_BLUE %][% BRIGHT WHITE %]    UPLOADER [% RESET %] ' . $record->{'fullname'} . "\n");
                }
                $self->output('[% B_BLUE %][% BRIGHT WHITE %]   FILE TYPE [% RESET %] ' . $record->{'type'} . "\n");
                $self->output('[% B_BLUE %][% BRIGHT WHITE %]    UPLOADED [% RESET %] ' . $record->{'uploaded'} . "\n");
                $self->output('[% B_BLUE %][% BRIGHT WHITE %]      THUMBS [% RESET %] [% THUMBS UP SIGN %] ' . (0 + $record->{'thumbs_up'}) . '   [% THUMBS DOWN SIGN %] ' . (0 + $record->{'tumbs_down'}) . "\n");
                $self->output('[% HORIZONTAL RULE GREEN %]' . "\n");
            } else {
                $self->output("\n      TITLE: " . $record->{'title'} . "\n");
                $self->output('   FILENAME: ' . $record->{'filename'} . "\n");
                $self->output('  FILE SIZE: ' . format_number($record->{'file_size'}) . "\n");
                if ($record->{'prefer_nickname'}) {
                    $self->output('   UPLOADER: ' . $record->{'nickname'} . "\n");
                } else {
                    $self->output('   UPLOADER: ' . $record->{'fullname'} . "\n");
                }
                $self->output('  FILE TYPE: ' . $record->{'type'} . "\n");
                $self->output('   UPLOADED: ' . $record->{'uploaded'} . "\n");
                $self->output('  THUMBS UP: ' . (0 + $record->{'thumbs_up'}) . "\n");
                $self->output('THUMBS DOWN: ' . (0 + $record->{'thumbs_down'}) . "\n");
            } ## end else [ if ($mode eq 'ANSI') ]
            last unless ($self->files_choices($record));
        } ## end foreach my $record (@files)
    } elsif ($search) {
        $self->output("\nSorry '$filter' not found");
    } else {
        $self->output("\nSorry, this file category is empty\n");
    }

lib/BBS/Universal.pm  view on Meta::CPAN

sub files_receive_file_zmodem {
    my ($self, $file) = @_;
    $self->{'debug'}->DEBUG(['Start files_receive_file_zmodem (using lrzsz)']);

    my $sock = $self->{'cl_socket'};
    unless ($sock) {
        $self->{'debug'}->ERROR(["No client socket for ZMODEM receive"]);
        return 0;
    }

    $self->output("\nStart Zmodem file upload\n");

    # When rz receives files it writes them into the current working directory.
    # Use the destination directory from config (same place other uploads are stored).
    my $dest_dir = $self->{'CONF'}->{'BBS ROOT'} . '/' . $self->{'CONF'}->{'FILES PATH'} . '/' . $self->{'USER'}->{'file_category_path'};

    # ensure directory exists
    unless (-d $dest_dir) {
        File::Path::mkpath($dest_dir);
        if ($@) {
            $self->{'debug'}->ERROR(["Failed to create dest dir $dest_dir: $@"]);
            return 0;
        }
    } ## end unless (-d $dest_dir)

    # We will chdir in the child before exec so the received file lands in $dest_dir.
    # Use rz --binary --quiet. Depending on lrzsz version you may want --overwrite or --keep
    my @args = ('--binary', '--overwrite', '--quiet');

    my $ok = $self->_run_on_socket('rz', \@args, $dest_dir);

    $self->output("\nFile upload complete\n");
    $self->{'debug'}->DEBUG(['End files_receive_file_zmodem (using lrzsz)']);
    return $ok;
} ## end sub files_receive_file_zmodem

 

# package BBS::Universal::Messages;

sub messages_initialize {
    my $self = shift;

lib/BBS/Universal.pm  view on Meta::CPAN

    my $bbs_versions = $self->sysop_versions_format($sections, TRUE);

    # Visual config
    $self->{'sysop_menu_colors'} = [91, 93, 92, 95, 94, 96];
    $self->{'sysop_menu_files'}  = ['', '', '', '', ''];

    # Default user capability flags
    $self->{'flags_default'} = {
        'prefer_nickname' => 'ON',
        'view_files'      => 'ON',
        'upload_files'    => 'OFF',
        'download_files'  => 'ON',
        'remove_files'    => 'OFF',
        'read_message'    => 'ON',
        'post_message'    => 'ON',
        'remove_message'  => 'OFF',
        'sysop'           => 'OFF',
        'show_email'      => 'OFF',
    };

    # Tokens (static + dynamic)

lib/BBS/Universal.pm  view on Meta::CPAN

            date_format
            baud_rate
            text_mode
            max_columns
            max_rows
            timeout
            retro_systems
            accomplishments
            prefer_nickname
            view_files
            upload_files
            download_files
            remove_files
            play_fortunes
            read_message
            post_message
            remove_message
            sysop
            banned
            login_time
            logout_time

lib/BBS/Universal.pm  view on Meta::CPAN

        'logout_time'     => { 'type' => STRING,  'max' => 10,  'min' => 10 },
        'text_mode'       => { 'type' => RADIO,   'max' => 7,   'min' => 9, 'choices' => ['ANSI', 'ASCII', 'ATASCII', 'PETSCII'], 'default' => 'ASCII', },
        'max_rows'        => { 'type' => NUMERIC, 'max' => 3,   'min' => 3, 'default' => 25 },
        'max_columns'     => { 'type' => NUMERIC, 'max' => 3,   'min' => 3, 'default' => 80 },
        'timeout'         => { 'type' => NUMERIC, 'max' => 5,   'min' => 5, 'default' => 10 },
        'retro_systems'   => { 'type' => STRING,  'max' => 120, 'min' => 40 },
        'accomplishments' => { 'type' => STRING,  'max' => 120, 'min' => 40 },
        'prefer_nickname' => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'view_files'      => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'ON' },
        'banned'          => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'upload_files'    => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'download_files'  => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'remove_files'    => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'read_message'    => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'ON' },
        'post_message'    => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'remove_message'  => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'play_fortunes'   => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'ON' },
        'sysop'           => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'password'        => { 'type' => STRING,  'max' => 64,  'min' => 32 },
    };

lib/BBS/Universal.pm  view on Meta::CPAN

                my $size = format_number($row->{$name});
                $sizes->{$name} = max(length($size), $sizes->{$name});
            } else {
                $sizes->{$name} = max(length($row->{$name}), $sizes->{$name});
            }
        } ## end foreach my $name (keys %{$row...})
    } ## end while (my $row = $sth->fetchrow_hashref...)
    $sth->finish();
    my $table;
    if ($wsize > 150) {
        $table = Text::SimpleTable->new(max(5, $sizes->{'title'}), max(8, $sizes->{'filename'}), max(4, $sizes->{'type'}), max(11, $sizes->{'description'}), max(8, $sizes->{'username'}), max(4, $sizes->{'file_size'}), max(8, $sizes->{'uploaded'}), ma...
        $table->row('TITLE', 'FILENAME', 'TYPE', 'DESCRIPTION', 'UPLOADER', 'SIZE', 'UPLOADED', 'THUMBS UP', 'THUMBS DOWN');
    } else {
        $table = Text::SimpleTable->new(max(5, $sizes->{'filename'}), max(8, $sizes->{'title'}), max(4, $sizes->{'extension'}), max(11, $sizes->{'description'}), max(8, $sizes->{'username'}), max(4, $sizes->{'file_size'}), max(9, $sizes->{'thumbs_up'...
        $table->row('TITLE', 'FILENAME', 'TYPE', 'DESCRIPTION', 'UPLOADER', 'SIZE', 'THUMBS UP', 'THUMBS DOWN');
    }
    $table->hr();
    $sth = $self->{'dbh'}->prepare('SELECT * FROM files_view WHERE category_id=?');
    $sth->execute($self->{'USER'}->{'file_category'});
    my $category;

    while (my $row = $sth->fetchrow_hashref()) {
        if ($wsize > 150) {
            $table->row($row->{'title'}, $row->{'filename'}, $row->{'type'}, $row->{'description'}, $row->{'username'}, format_number($row->{'file_size'}), $row->{'uploaded'}, sprintf('%-06u', $row->{'thumbs_up'}), sprintf('%-06u', $row->{'thumbs_dow...
        } else {
            $table->row($row->{'title'}, $row->{'filename'}, $row->{'extension'}, $row->{'description'}, $row->{'username'}, format_number($row->{'file_size'}), sprintf('%-06u', $row->{'thumbs_up'}), sprintf('%-06u', $row->{'thumbs_down'}));
        }
        $category = $row->{'category'};
    } ## end while (my $row = $sth->fetchrow_hashref...)
    $sth->finish();
    $self->sysop_output("\n" . '[% B_ORANGE %][% BLACK %] Current Category [% RESET %] [% BRIGHT YELLOW %][% BLACK RIGHT-POINTING TRIANGLE %][% RESET %] [% BRIGHT WHITE %][% FILE CATEGORY %][% RESET %]');
    my $tbl = $table->twin('YELLOW')->draw();
    while ($tbl =~ / (TITLE|FILENAME|TYPE|DESCRIPTION|UPLOADER|SIZE|UPLOADED|THUMBS UP|THUMBS DOWN) /) {
        my $ch  = $1;

lib/BBS/Universal.pm  view on Meta::CPAN

                $tbl =~ s/$ch/$new/g;
            } ## end while ($tbl =~ / (CHOICE|FIELD|VALUE|No|Yes|USER. VETERAN. JUNIOR SYSOP. SYSOP|YEAR.MONTH.DAY, MONTH.DAY.YEAR, DAY.MONTH.YEAR|300. 600. 1200. 2400. 4800. 9600. 19200. FULL|ASCII. ANSI. ATASCII. PETSCII|Minutes) /)
            $self->sysop_output('[% CLS %]' . $tbl . "\n");
            $self->sysop_show_choices($mapping);
            $self->sysop_prompt('Choose');
            do {
                $key = uc($self->sysop_keypress());
            } until ('1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ' =~ /$key/i);
            if ($key !~ /$key_exit/i) {
                print 'Edit > (', $choice{$key}, ' = ', $user_row->{ $choice{$key} }, ') > ';
                if ($choice{$key} =~ /^(play_fortunes|prefer_nickname|view_files|upload_files|download_files|remove_files|read_message|post_message|remove_message|sysop)$/) {
                    $user_row->{ $choice{$key} } = ($user_row->{ $choice{$key} } == 1) ? 0 : 1;
                    my $sth = $self->{'dbh'}->prepare('UPDATE permissions SET ' . $choice{$key} . '= !' . $choice{$key} . '  WHERE id=?');
                    $sth->execute($user_row->{'id'});
                    $sth->finish();
                } elsif($choice{$key} =~ /text_mode/) {
                    my $new = $self->sysop_get_line($self->{'SYSOP FIELD TYPES'}->{ $choice{$key} }, $user_row->{ $choice{$key} });
                    $user_row->{ $choice{$key} } = $new;
                    my $sth = $self->{'dbh'}->prepare('UPDATE users SET ' . $choice{$key} . '=? WHERE id=?');
                    $sth->execute($new, $self->{'text_modes'}->{$user_row->{'id'}});
                    $sth->finish();
                } else {
                    my $new = $self->sysop_get_line($self->{'SYSOP FIELD TYPES'}->{ $choice{$key} }, $user_row->{ $choice{$key} });
                    $user_row->{ $choice{$key} } = $new;
                    my $sth = $self->{'dbh'}->prepare('UPDATE users SET ' . $choice{$key} . '=? WHERE id=?');
                    $sth->execute($new, $user_row->{'id'});
                    $sth->finish();
                } ## end else [ if ($choice{$key} =~ /^(prefer_nickname|view_files|upload_files|download_files|remove_files|read_message|post_message|remove_message|sysop)$/)]
            } else {
                print "BACK\n";
            }
        } until ($key =~ /$key_exit/i);
    } elsif ($search ne '') {
        print "User not found!\n\n";
    }
    $self->{'debug'}->DEBUG(['End SysOp User Edit']);
    return (TRUE);
} ## end sub sysop_user_edit

lib/BBS/Universal.pm  view on Meta::CPAN

                $key = uc($self->sysop_keypress());
            } until ('1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ' =~ /$key/i);
            if ($key !~ /$key_exit/i) {
                print 'Edit > (', $choice{$key}, ' = ', $user_row->{ $choice{$key} }, ') > ';
                my $new = $self->sysop_get_line(ECHO, 1 + $self->{'SYSOP FIELD TYPES'}->{ $choice{$key} }->{'max'}, $user_row->{ $choice{$key} });
                unless ($new eq '') {
                    $new =~ s/^(Yes|On)$/1/i;
                    $new =~ s/^(No|Off)$/0/i;
                }
                $user_row->{ $choice{$key} } = $new;
                if ($key =~ /prefer_nickname|view_files|upload_files|download_files|remove_files|read_message|post_message|remove_message|sysop/) {
                    my $sth = $self->{'dbh'}->prepare('UPDATE permissions SET ' . choice { $key } . '=? WHERE id=?');
                    $sth->execute($new, $user_row->{'id'});
                    $sth->finish();
                } else {
                    my $sth = $self->{'dbh'}->prepare('UPDATE users SET ' . $choice{$key} . '=? WHERE id=?');
                    $sth->execute($new, $user_row->{'id'});
                    $sth->finish();
                }
            } else {
                print "BACK\n";

lib/BBS/Universal.pm  view on Meta::CPAN

    my $results  = $sth->fetchrow_hashref();
    my $response = FALSE;
    if (defined($results)) {
        $self->{'USER'} = $results;
        delete($self->{'USER'}->{'password'});
        foreach my $field (    # For numeric values
            qw(
            show_email
            prefer_nickname
            view_files
            upload_files
            download_files
            remove_files
            read_message
            post_message
            remove_message
            play_fortunes
            banned
            sysop
            )
        ) {

lib/BBS/Universal.pm  view on Meta::CPAN

        }
    );
    $sth->execute($user_template->{'username'}, $user_template->{'given'}, $user_template->{'family'}, $user_template->{'nickname'}, $user_template->{'email'}, $user_template->{'accomplishments'}, $user_template->{'retro_systems'}, $user_template->{'...
    $sth->finish;
    $sth = $self->{'dbh'}->prepare(
        q{
            INSERT INTO permissions (
                id,
                prefer_nickname,
                view_files,
                upload_files,
                download_files,
                remove_files,
                read_message,
                show_email,
                post_message,
                remove_message,
                sysop,
                play_fortunes,
                timeout)
              VALUES (LAST_INSERT_ID(),?,?,?,?,?,?,?,?,?,?,?,?,?);
        }
    );
    $sth->execute($user_template->{'prefer_nickname'}, $user_template->{'view_files'}, $user_template->{'upload_files'}, $user_template->{'download_files'}, $user_template->{'remove_files'}, $user_template->{'read_message'}, $user_template->{'show_em...
    my $response;

    if ($self->{'dbh'}->err) {
        $self->{'dbh'}->rollback;
        $sth->finish();
        $response = FALSE;
    } else {
        $self->{'dbh'}->commit;
        $sth->finish();
        $response = TRUE;

lib/BBS/Universal.pm  view on Meta::CPAN

        $table .= sprintf('%-15s=%-25s', 'BIRTHDAY',        $self->users_get_date($self->{'USER'}->{'birthday'})) . "\n";
        $table .= sprintf('%-15s=%-25s', 'LOCATION',        $self->{'USER'}->{'location'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'BAUD RATE',       $self->{'USER'}->{'baud_rate'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'LAST LOGIN',      $self->{'USER'}->{'login_time'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'LAST LOGOUT',     $self->{'USER'}->{'logout_time'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'TEXT MODE',       $self->{'USER'}->{'text_mode'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'IDLE TIMEOUT',    $self->{'USER'}->{'timeout'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'SHOW EMAIL',      $self->yes_no($self->{'USER'}->{'show_email'},      FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'PREFER NICKNAME', $self->yes_no($self->{'USER'}->{'prefer_nickname'}, FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'VIEW FILES',      $self->yes_no($self->{'USER'}->{'view_files'},      FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'UPLOAD FILES',    $self->yes_no($self->{'USER'}->{'upload_files'},    FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'DOWNLOAD FILES',  $self->yes_no($self->{'USER'}->{'download_files'},  FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'REMOVE FILES',    $self->yes_no($self->{'USER'}->{'remove_files'},    FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'READ MESSAGES',   $self->yes_no($self->{'USER'}->{'read_message'},    FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'POST MESSAGES',   $self->yes_no($self->{'USER'}->{'post_message'},    FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'REMOVE MESSAGES', $self->yes_no($self->{'USER'}->{'remove_message'},  FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'PLAY FORTUNES',   $self->yes_no($self->{'USER'}->{'play_fortunes'},   FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'ACCESS LEVEL',    $self->{'USER'}->{'access_level'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'RETRO SYSTEMS',   $self->{'USER'}->{'retro_systems'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'ACCOMPLISHMENTS', $self->{'USER'}->{'accomplishments'}) . "\n";
    } elsif ((($width + 22) * 2) <= $columns) {

lib/BBS/Universal.pm  view on Meta::CPAN

        $table->row('FIELD', 'VALUE', 'FIELD', 'VALUE');
        $table->hr();
        $table->row('ACCOUNT NUMBER',  $self->{'USER'}->{'id'},                                    'USERNAME',        $self->{'USER'}->{'username'});
        $table->row('FULLNAME',        $self->{'USER'}->{'fullname'},                              'NICKNAME',        $self->{'USER'}->{'nickname'});
        $table->row('EMAIL',           $self->{'USER'}->{'email'},                                 'SCREEN',          $self->{'USER'}->{'max_columns'} . 'x' . $self->{'USER'}->{'max_rows'});
        $table->row('BIRTHDAY',        $self->users_get_date($self->{'USER'}->{'birthday'}),       'LOCATION',        $self->{'USER'}->{'location'});
        $table->row('BAUD RATE',       $self->{'USER'}->{'baud_rate'},                             'LAST LOGIN',      $self->users_get_date($self->{'USER'}->{'login_time'}));
        $table->row('DATE FORMAT',     $self->{'USER'}->{'date_format'},                           'LAST LOGOUT',     $self->users_get_date($self->{'USER'}->{'logout_time'}));
        $table->row('IDLE TIMEOUT',    $self->{'USER'}->{'timeout'},                               'TEXT MODE',       $self->{'USER'}->{'text_mode'});
        $table->row('PREFER NICKNAME', $self->yes_no($self->{'USER'}->{'prefer_nickname'}, FALSE), 'VIEW FILES',      $self->yes_no($self->{'USER'}->{'view_files'}, FALSE));
        $table->row('UPLOAD FILES',    $self->yes_no($self->{'USER'}->{'upload_files'}, FALSE),    'DOWNLOAD FILES',  $self->yes_no($self->{'USER'}->{'download_files'}, FALSE));
        $table->row('REMOVE FILES',    $self->yes_no($self->{'USER'}->{'remove_files'}, FALSE),    'READ MESSAGES',   $self->yes_no($self->{'USER'}->{'read_message'}, FALSE));
        $table->row('POST MESSAGES',   $self->yes_no($self->{'USER'}->{'post_message'}, FALSE),    'REMOVE MESSAGES', $self->yes_no($self->{'USER'}->{'remove_message'}, FALSE));
        $table->row('SHOW EMAIL',      $self->yes_no($self->{'USER'}->{'show_email'}, FALSE),      'ACCESS LEVEL',    $self->{'USER'}->{'access_level'});
		$table->row('PLAY FORTUNES',   $self->yes_no($self->{'USER'}->{'play_fortunes'}, FALSE),   'ACCOMPLISHMENTS', $self->{'USER'}->{'accomplishments'});
		$table->row('RETRO SYSTEMS',   $self->{'USER'}->{'retro_systems'},'','');
    } else {
        $width = min($width + 7, $self->{'USER'}->{'max_columns'} - 7);
        $table = Text::SimpleTable->new(15, $width);
        $table->row('FIELD', 'VALUE');
        $table->hr();

lib/BBS/Universal.pm  view on Meta::CPAN

        $table->row('BIRTHDAY',        $self->users_get_date($self->{'USER'}->{'birthday'}));
        $table->row('LOCATION',        $self->{'USER'}->{'location'});
        $table->row('BAUD RATE',       $self->{'USER'}->{'baud_rate'});
        $table->row('LAST LOGIN',      $self->{'USER'}->{'login_time'});
        $table->row('LAST LOGOUT',     $self->{'USER'}->{'logout_time'});
        $table->row('TEXT MODE',       $self->{'USER'}->{'text_mode'});
        $table->row('IDLE TIMEOUT',    $self->{'USER'}->{'timeout'});
        $table->row('SHOW EMAIL',      $self->yes_no($self->{'USER'}->{'show_email'},      FALSE));
        $table->row('PREFER NICKNAME', $self->yes_no($self->{'USER'}->{'prefer_nickname'}, FALSE));
        $table->row('VIEW FILES',      $self->yes_no($self->{'USER'}->{'view_files'},      FALSE));
        $table->row('UPLOAD FILES',    $self->yes_no($self->{'USER'}->{'upload_files'},    FALSE));
        $table->row('DOWNLOAD FILES',  $self->yes_no($self->{'USER'}->{'download_files'},  FALSE));
        $table->row('REMOVE FILES',    $self->yes_no($self->{'USER'}->{'remove_files'},    FALSE));
        $table->row('READ MESSAGES',   $self->yes_no($self->{'USER'}->{'read_message'},    FALSE));
        $table->row('POST MESSAGES',   $self->yes_no($self->{'USER'}->{'post_message'},    FALSE));
        $table->row('REMOVE MESSAGES', $self->yes_no($self->{'USER'}->{'remove_message'},  FALSE));
        $table->row('PLAY FORTUNES',   $self->yes_no($self->{'USER'}->{'play_fortunes'},   FALSE));
        $table->row('ACCESS LEVEL',    $self->{'USER'}->{'access_level'});
        $table->row('RETRO SYSTEMS',   $self->{'USER'}->{'retro_systems'});
        $table->row('ACCOMPLISHMENTS', $self->{'USER'}->{'accomplishments'});
    } ## end else [ if ($columns <= 40) ]

lib/BBS/Universal/Commands.pm  view on Meta::CPAN

            my $self = shift;
            return ($self->load_menu('files/main/files_menu'));
        },
        'LIST FILES SUMMARY' => sub {
            my $self = shift;
            $self->files_list_summary(FALSE);
            return ($self->load_menu('files/main/files_menu'));
        },
        'UPLOAD FILE' => sub {
            my $self = shift;
            $self->files_upload_choices();
            return ($self->load_menu('files/main/files_menu'));
        },
        'LIST FILES DETAILED' => sub {
            my $self = shift;
            $self->files_list_detailed(FALSE);
            return ($self->load_menu('files/main/files_menu'));
        },
        'SEARCH FILES SUMMARY' => sub {
            my $self = shift;
            $self->files_list_summary(TRUE);

lib/BBS/Universal/FileTransfer.pm  view on Meta::CPAN


sub files_list_summary {
    my ($self, $search) = @_;

    $self->{'debug'}->DEBUG(['Start Files List Summary']);
    my $sth;
    my $filter;
    if ($search) {
        $self->prompt('Search for (blank for all)');
        $filter = $self->get_line({ 'type' => STRING, 'max' => 255, 'default' => '' });
        $sth    = $self->{'dbh'}->prepare('SELECT * FROM files_view WHERE (filename LIKE ? OR title LIKE ?) AND category_id=? ORDER BY uploaded DESC');
        $sth->execute('%' . $filter . '%', '%' . $filter . '%', $self->{'USER'}->{'file_category'});
    } else {
        $sth = $self->{'dbh'}->prepare('SELECT * FROM files_view WHERE category_id=? ORDER BY uploaded DESC');
        $sth->execute($self->{'USER'}->{'file_category'});
    }
    my @files;
    my $max_filename = 10;
    my $max_title    = 20;
    if ($sth->rows > 0) {
        while (my $row = $sth->fetchrow_hashref()) {
            push(@files, $row);
            $max_filename = max(length($row->{'filename'}), $max_filename);
            $max_title    = max(length($row->{'title'}),    $max_title);

lib/BBS/Universal/FileTransfer.pm  view on Meta::CPAN

        } elsif ($mapping->{$key}->{'command'} eq 'REMOVE FILE' && $self->check_access_level($mapping->{$key}->{'access_level'})) {
            return (TRUE);
        } elsif ($mapping->{$key}->{'command'} eq 'NEXT') {
            return (TRUE);
        } elsif ($mapping->{$key}->{'command'} eq 'BACK') {
            return (FALSE);
        }
    } ## end while ($self->is_connected...)
} ## end sub files_choices

sub files_upload_choices {
    my ($self) = @_;
    my $ckey;

    $self->prompt('File Name? ');
    my $file = $self->get_line({ 'type' => FILENAME, 'max' => 255, 'default' => '' });
    my $ext  = uc($file =~ /\.(.*?)$/);

    $self->prompt('Title (Fiendly name)? ');
    my $title = $self->get_line({ 'type' => STRING, 'max' => 255, 'default' => '' });

lib/BBS/Universal/FileTransfer.pm  view on Meta::CPAN

        return (FALSE);
    }
    if ($? == -1) {
        $self->{'debug'}->ERROR(["Could not execute rz:  $!"]);
    } elsif ($? & 127) {
        $self->{'debug'}->ERROR(["File Transfer Aborted:  $!"]);
    } else {
        $self->{'debug'}->DEBUG(['File Transfer Successful']);
    }
    return (TRUE);
} ## end sub files_upload_choices

sub files_list_detailed {
    my ($self, $search) = @_;

    $self->{'debug'}->DEBUG(['Start Files List Detailed']);
    my $sth;
    my $filter;
    my $columns = $self->{'USER'}->{'max_columns'};
    if ($search) {
        $self->prompt('Search for');
        $filter = $self->get_line({ 'type' => STRING, 'max' => 255, 'default' => '' });
        $sth    = $self->{'dbh'}->prepare('SELECT * FROM files_view WHERE (filename LIKE ? OR title LIKE ?) AND category_id=? ORDER BY uploaded DESC');
        $sth->execute('%' . $filter . '%', '%' . $filter . '%', $self->{'USER'}->{'file_category'});
    } else {
        $sth = $self->{'dbh'}->prepare('SELECT * FROM files_view WHERE category_id=? ORDER BY uploaded DESC');
        $sth->execute($self->{'USER'}->{'file_category'});
    }
    my @files;
    if ($sth->rows > 0) {
        $self->{'debug'}->DEBUGMAX(\@files);
        my $table;
        my $mode = $self->{'USER'}->{'text_mode'};
        while (my $row = $sth->fetchrow_hashref()) {
            push(@files, $row);
        }

lib/BBS/Universal/FileTransfer.pm  view on Meta::CPAN

                $self->output("\n" . '[% HORIZONTAL RULE GREEN %]' . "\n");
                $self->output('[% B_BLUE %][% BRIGHT WHITE %]       TITLE [% RESET %] ' . $record->{'title'} . "\n");
                $self->output('[% B_BLUE %][% BRIGHT WHITE %]    FILENAME [% RESET %] ' . $record->{'filename'} . "\n");
                $self->output('[% B_BLUE %][% BRIGHT WHITE %]   FILE SIZE [% RESET %] ' . format_number($record->{'file_size'}) . "\n");
                if ($record->{'prefer_nickname'}) {
                    $self->output('[% B_BLUE %][% BRIGHT WHITE %]    UPLOADER [% RESET %] ' . $record->{'nickname'} . "\n");
                } else {
                    $self->output('[% B_BLUE %][% BRIGHT WHITE %]    UPLOADER [% RESET %] ' . $record->{'fullname'} . "\n");
                }
                $self->output('[% B_BLUE %][% BRIGHT WHITE %]   FILE TYPE [% RESET %] ' . $record->{'type'} . "\n");
                $self->output('[% B_BLUE %][% BRIGHT WHITE %]    UPLOADED [% RESET %] ' . $record->{'uploaded'} . "\n");
                $self->output('[% B_BLUE %][% BRIGHT WHITE %]      THUMBS [% RESET %] [% THUMBS UP SIGN %] ' . (0 + $record->{'thumbs_up'}) . '   [% THUMBS DOWN SIGN %] ' . (0 + $record->{'tumbs_down'}) . "\n");
                $self->output('[% HORIZONTAL RULE GREEN %]' . "\n");
            } else {
                $self->output("\n      TITLE: " . $record->{'title'} . "\n");
                $self->output('   FILENAME: ' . $record->{'filename'} . "\n");
                $self->output('  FILE SIZE: ' . format_number($record->{'file_size'}) . "\n");
                if ($record->{'prefer_nickname'}) {
                    $self->output('   UPLOADER: ' . $record->{'nickname'} . "\n");
                } else {
                    $self->output('   UPLOADER: ' . $record->{'fullname'} . "\n");
                }
                $self->output('  FILE TYPE: ' . $record->{'type'} . "\n");
                $self->output('   UPLOADED: ' . $record->{'uploaded'} . "\n");
                $self->output('  THUMBS UP: ' . (0 + $record->{'thumbs_up'}) . "\n");
                $self->output('THUMBS DOWN: ' . (0 + $record->{'thumbs_down'}) . "\n");
            } ## end else [ if ($mode eq 'ANSI') ]
            last unless ($self->files_choices($record));
        } ## end foreach my $record (@files)
    } elsif ($search) {
        $self->output("\nSorry '$filter' not found");
    } else {
        $self->output("\nSorry, this file category is empty\n");
    }

lib/BBS/Universal/FileTransfer.pm  view on Meta::CPAN

sub files_receive_file_zmodem {
    my ($self, $file) = @_;
    $self->{'debug'}->DEBUG(['Start files_receive_file_zmodem (using lrzsz)']);

    my $sock = $self->{'cl_socket'};
    unless ($sock) {
        $self->{'debug'}->ERROR(["No client socket for ZMODEM receive"]);
        return 0;
    }

    $self->output("\nStart Zmodem file upload\n");

    # When rz receives files it writes them into the current working directory.
    # Use the destination directory from config (same place other uploads are stored).
    my $dest_dir = $self->{'CONF'}->{'BBS ROOT'} . '/' . $self->{'CONF'}->{'FILES PATH'} . '/' . $self->{'USER'}->{'file_category_path'};

    # ensure directory exists
    unless (-d $dest_dir) {
        File::Path::mkpath($dest_dir);
        if ($@) {
            $self->{'debug'}->ERROR(["Failed to create dest dir $dest_dir: $@"]);
            return 0;
        }
    } ## end unless (-d $dest_dir)

    # We will chdir in the child before exec so the received file lands in $dest_dir.
    # Use rz --binary --quiet. Depending on lrzsz version you may want --overwrite or --keep
    my @args = ('--binary', '--overwrite', '--quiet');

    my $ok = $self->_run_on_socket('rz', \@args, $dest_dir);

    $self->output("\nFile upload complete\n");
    $self->{'debug'}->DEBUG(['End files_receive_file_zmodem (using lrzsz)']);
    return $ok;
} ## end sub files_receive_file_zmodem
1;

lib/BBS/Universal/SysOp.pm  view on Meta::CPAN

    my $bbs_versions = $self->sysop_versions_format($sections, TRUE);

    # Visual config
    $self->{'sysop_menu_colors'} = [91, 93, 92, 95, 94, 96];
    $self->{'sysop_menu_files'}  = ['', '', '', '', ''];

    # Default user capability flags
    $self->{'flags_default'} = {
        'prefer_nickname' => 'ON',
        'view_files'      => 'ON',
        'upload_files'    => 'OFF',
        'download_files'  => 'ON',
        'remove_files'    => 'OFF',
        'read_message'    => 'ON',
        'post_message'    => 'ON',
        'remove_message'  => 'OFF',
        'sysop'           => 'OFF',
        'show_email'      => 'OFF',
    };

    # Tokens (static + dynamic)

lib/BBS/Universal/SysOp.pm  view on Meta::CPAN

            date_format
            baud_rate
            text_mode
            max_columns
            max_rows
            timeout
            retro_systems
            accomplishments
            prefer_nickname
            view_files
            upload_files
            download_files
            remove_files
            play_fortunes
            read_message
            post_message
            remove_message
            sysop
            banned
            login_time
            logout_time

lib/BBS/Universal/SysOp.pm  view on Meta::CPAN

        'logout_time'     => { 'type' => STRING,  'max' => 10,  'min' => 10 },
        'text_mode'       => { 'type' => RADIO,   'max' => 7,   'min' => 9, 'choices' => ['ANSI', 'ASCII', 'ATASCII', 'PETSCII'], 'default' => 'ASCII', },
        'max_rows'        => { 'type' => NUMERIC, 'max' => 3,   'min' => 3, 'default' => 25 },
        'max_columns'     => { 'type' => NUMERIC, 'max' => 3,   'min' => 3, 'default' => 80 },
        'timeout'         => { 'type' => NUMERIC, 'max' => 5,   'min' => 5, 'default' => 10 },
        'retro_systems'   => { 'type' => STRING,  'max' => 120, 'min' => 40 },
        'accomplishments' => { 'type' => STRING,  'max' => 120, 'min' => 40 },
        'prefer_nickname' => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'view_files'      => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'ON' },
        'banned'          => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'upload_files'    => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'download_files'  => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'remove_files'    => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'read_message'    => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'ON' },
        'post_message'    => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'remove_message'  => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'play_fortunes'   => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'ON' },
        'sysop'           => { 'type' => BOOLEAN, 'max' => 5,   'min' => 5, 'choices' => ['ON', 'OFF'], 'default' => 'OFF' },
        'password'        => { 'type' => STRING,  'max' => 64,  'min' => 32 },
    };

lib/BBS/Universal/SysOp.pm  view on Meta::CPAN

                my $size = format_number($row->{$name});
                $sizes->{$name} = max(length($size), $sizes->{$name});
            } else {
                $sizes->{$name} = max(length($row->{$name}), $sizes->{$name});
            }
        } ## end foreach my $name (keys %{$row...})
    } ## end while (my $row = $sth->fetchrow_hashref...)
    $sth->finish();
    my $table;
    if ($wsize > 150) {
        $table = Text::SimpleTable->new(max(5, $sizes->{'title'}), max(8, $sizes->{'filename'}), max(4, $sizes->{'type'}), max(11, $sizes->{'description'}), max(8, $sizes->{'username'}), max(4, $sizes->{'file_size'}), max(8, $sizes->{'uploaded'}), ma...
        $table->row('TITLE', 'FILENAME', 'TYPE', 'DESCRIPTION', 'UPLOADER', 'SIZE', 'UPLOADED', 'THUMBS UP', 'THUMBS DOWN');
    } else {
        $table = Text::SimpleTable->new(max(5, $sizes->{'filename'}), max(8, $sizes->{'title'}), max(4, $sizes->{'extension'}), max(11, $sizes->{'description'}), max(8, $sizes->{'username'}), max(4, $sizes->{'file_size'}), max(9, $sizes->{'thumbs_up'...
        $table->row('TITLE', 'FILENAME', 'TYPE', 'DESCRIPTION', 'UPLOADER', 'SIZE', 'THUMBS UP', 'THUMBS DOWN');
    }
    $table->hr();
    $sth = $self->{'dbh'}->prepare('SELECT * FROM files_view WHERE category_id=?');
    $sth->execute($self->{'USER'}->{'file_category'});
    my $category;

    while (my $row = $sth->fetchrow_hashref()) {
        if ($wsize > 150) {
            $table->row($row->{'title'}, $row->{'filename'}, $row->{'type'}, $row->{'description'}, $row->{'username'}, format_number($row->{'file_size'}), $row->{'uploaded'}, sprintf('%-06u', $row->{'thumbs_up'}), sprintf('%-06u', $row->{'thumbs_dow...
        } else {
            $table->row($row->{'title'}, $row->{'filename'}, $row->{'extension'}, $row->{'description'}, $row->{'username'}, format_number($row->{'file_size'}), sprintf('%-06u', $row->{'thumbs_up'}), sprintf('%-06u', $row->{'thumbs_down'}));
        }
        $category = $row->{'category'};
    } ## end while (my $row = $sth->fetchrow_hashref...)
    $sth->finish();
    $self->sysop_output("\n" . '[% B_ORANGE %][% BLACK %] Current Category [% RESET %] [% BRIGHT YELLOW %][% BLACK RIGHT-POINTING TRIANGLE %][% RESET %] [% BRIGHT WHITE %][% FILE CATEGORY %][% RESET %]');
    my $tbl = $table->twin('YELLOW')->draw();
    while ($tbl =~ / (TITLE|FILENAME|TYPE|DESCRIPTION|UPLOADER|SIZE|UPLOADED|THUMBS UP|THUMBS DOWN) /) {
        my $ch  = $1;

lib/BBS/Universal/SysOp.pm  view on Meta::CPAN

                $tbl =~ s/$ch/$new/g;
            } ## end while ($tbl =~ / (CHOICE|FIELD|VALUE|No|Yes|USER. VETERAN. JUNIOR SYSOP. SYSOP|YEAR.MONTH.DAY, MONTH.DAY.YEAR, DAY.MONTH.YEAR|300. 600. 1200. 2400. 4800. 9600. 19200. FULL|ASCII. ANSI. ATASCII. PETSCII|Minutes) /)
            $self->sysop_output('[% CLS %]' . $tbl . "\n");
            $self->sysop_show_choices($mapping);
            $self->sysop_prompt('Choose');
            do {
                $key = uc($self->sysop_keypress());
            } until ('1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ' =~ /$key/i);
            if ($key !~ /$key_exit/i) {
                print 'Edit > (', $choice{$key}, ' = ', $user_row->{ $choice{$key} }, ') > ';
                if ($choice{$key} =~ /^(play_fortunes|prefer_nickname|view_files|upload_files|download_files|remove_files|read_message|post_message|remove_message|sysop)$/) {
                    $user_row->{ $choice{$key} } = ($user_row->{ $choice{$key} } == 1) ? 0 : 1;
                    my $sth = $self->{'dbh'}->prepare('UPDATE permissions SET ' . $choice{$key} . '= !' . $choice{$key} . '  WHERE id=?');
                    $sth->execute($user_row->{'id'});
                    $sth->finish();
                } elsif($choice{$key} =~ /text_mode/) {
                    my $new = $self->sysop_get_line($self->{'SYSOP FIELD TYPES'}->{ $choice{$key} }, $user_row->{ $choice{$key} });
                    $user_row->{ $choice{$key} } = $new;
                    my $sth = $self->{'dbh'}->prepare('UPDATE users SET ' . $choice{$key} . '=? WHERE id=?');
                    $sth->execute($new, $self->{'text_modes'}->{$user_row->{'id'}});
                    $sth->finish();
                } else {
                    my $new = $self->sysop_get_line($self->{'SYSOP FIELD TYPES'}->{ $choice{$key} }, $user_row->{ $choice{$key} });
                    $user_row->{ $choice{$key} } = $new;
                    my $sth = $self->{'dbh'}->prepare('UPDATE users SET ' . $choice{$key} . '=? WHERE id=?');
                    $sth->execute($new, $user_row->{'id'});
                    $sth->finish();
                } ## end else [ if ($choice{$key} =~ /^(prefer_nickname|view_files|upload_files|download_files|remove_files|read_message|post_message|remove_message|sysop)$/)]
            } else {
                print "BACK\n";
            }
        } until ($key =~ /$key_exit/i);
    } elsif ($search ne '') {
        print "User not found!\n\n";
    }
    $self->{'debug'}->DEBUG(['End SysOp User Edit']);
    return (TRUE);
} ## end sub sysop_user_edit

lib/BBS/Universal/SysOp.pm  view on Meta::CPAN

                $key = uc($self->sysop_keypress());
            } until ('1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ' =~ /$key/i);
            if ($key !~ /$key_exit/i) {
                print 'Edit > (', $choice{$key}, ' = ', $user_row->{ $choice{$key} }, ') > ';
                my $new = $self->sysop_get_line(ECHO, 1 + $self->{'SYSOP FIELD TYPES'}->{ $choice{$key} }->{'max'}, $user_row->{ $choice{$key} });
                unless ($new eq '') {
                    $new =~ s/^(Yes|On)$/1/i;
                    $new =~ s/^(No|Off)$/0/i;
                }
                $user_row->{ $choice{$key} } = $new;
                if ($key =~ /prefer_nickname|view_files|upload_files|download_files|remove_files|read_message|post_message|remove_message|sysop/) {
                    my $sth = $self->{'dbh'}->prepare('UPDATE permissions SET ' . choice { $key } . '=? WHERE id=?');
                    $sth->execute($new, $user_row->{'id'});
                    $sth->finish();
                } else {
                    my $sth = $self->{'dbh'}->prepare('UPDATE users SET ' . $choice{$key} . '=? WHERE id=?');
                    $sth->execute($new, $user_row->{'id'});
                    $sth->finish();
                }
            } else {
                print "BACK\n";

lib/BBS/Universal/Users.pm  view on Meta::CPAN

    my $results  = $sth->fetchrow_hashref();
    my $response = FALSE;
    if (defined($results)) {
        $self->{'USER'} = $results;
        delete($self->{'USER'}->{'password'});
        foreach my $field (    # For numeric values
            qw(
            show_email
            prefer_nickname
            view_files
            upload_files
            download_files
            remove_files
            read_message
            post_message
            remove_message
            play_fortunes
            banned
            sysop
            )
        ) {

lib/BBS/Universal/Users.pm  view on Meta::CPAN

        }
    );
    $sth->execute($user_template->{'username'}, $user_template->{'given'}, $user_template->{'family'}, $user_template->{'nickname'}, $user_template->{'email'}, $user_template->{'accomplishments'}, $user_template->{'retro_systems'}, $user_template->{'...
    $sth->finish;
    $sth = $self->{'dbh'}->prepare(
        q{
            INSERT INTO permissions (
                id,
                prefer_nickname,
                view_files,
                upload_files,
                download_files,
                remove_files,
                read_message,
                show_email,
                post_message,
                remove_message,
                sysop,
                play_fortunes,
                timeout)
              VALUES (LAST_INSERT_ID(),?,?,?,?,?,?,?,?,?,?,?,?,?);
        }
    );
    $sth->execute($user_template->{'prefer_nickname'}, $user_template->{'view_files'}, $user_template->{'upload_files'}, $user_template->{'download_files'}, $user_template->{'remove_files'}, $user_template->{'read_message'}, $user_template->{'show_em...
    my $response;

    if ($self->{'dbh'}->err) {
        $self->{'dbh'}->rollback;
        $sth->finish();
        $response = FALSE;
    } else {
        $self->{'dbh'}->commit;
        $sth->finish();
        $response = TRUE;

lib/BBS/Universal/Users.pm  view on Meta::CPAN

        $table .= sprintf('%-15s=%-25s', 'BIRTHDAY',        $self->users_get_date($self->{'USER'}->{'birthday'})) . "\n";
        $table .= sprintf('%-15s=%-25s', 'LOCATION',        $self->{'USER'}->{'location'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'BAUD RATE',       $self->{'USER'}->{'baud_rate'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'LAST LOGIN',      $self->{'USER'}->{'login_time'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'LAST LOGOUT',     $self->{'USER'}->{'logout_time'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'TEXT MODE',       $self->{'USER'}->{'text_mode'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'IDLE TIMEOUT',    $self->{'USER'}->{'timeout'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'SHOW EMAIL',      $self->yes_no($self->{'USER'}->{'show_email'},      FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'PREFER NICKNAME', $self->yes_no($self->{'USER'}->{'prefer_nickname'}, FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'VIEW FILES',      $self->yes_no($self->{'USER'}->{'view_files'},      FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'UPLOAD FILES',    $self->yes_no($self->{'USER'}->{'upload_files'},    FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'DOWNLOAD FILES',  $self->yes_no($self->{'USER'}->{'download_files'},  FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'REMOVE FILES',    $self->yes_no($self->{'USER'}->{'remove_files'},    FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'READ MESSAGES',   $self->yes_no($self->{'USER'}->{'read_message'},    FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'POST MESSAGES',   $self->yes_no($self->{'USER'}->{'post_message'},    FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'REMOVE MESSAGES', $self->yes_no($self->{'USER'}->{'remove_message'},  FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'PLAY FORTUNES',   $self->yes_no($self->{'USER'}->{'play_fortunes'},   FALSE)) . "\n";
        $table .= sprintf('%-15s=%-25s', 'ACCESS LEVEL',    $self->{'USER'}->{'access_level'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'RETRO SYSTEMS',   $self->{'USER'}->{'retro_systems'}) . "\n";
        $table .= sprintf('%-15s=%-25s', 'ACCOMPLISHMENTS', $self->{'USER'}->{'accomplishments'}) . "\n";
    } elsif ((($width + 22) * 2) <= $columns) {

lib/BBS/Universal/Users.pm  view on Meta::CPAN

        $table->row('FIELD', 'VALUE', 'FIELD', 'VALUE');
        $table->hr();
        $table->row('ACCOUNT NUMBER',  $self->{'USER'}->{'id'},                                    'USERNAME',        $self->{'USER'}->{'username'});
        $table->row('FULLNAME',        $self->{'USER'}->{'fullname'},                              'NICKNAME',        $self->{'USER'}->{'nickname'});
        $table->row('EMAIL',           $self->{'USER'}->{'email'},                                 'SCREEN',          $self->{'USER'}->{'max_columns'} . 'x' . $self->{'USER'}->{'max_rows'});
        $table->row('BIRTHDAY',        $self->users_get_date($self->{'USER'}->{'birthday'}),       'LOCATION',        $self->{'USER'}->{'location'});
        $table->row('BAUD RATE',       $self->{'USER'}->{'baud_rate'},                             'LAST LOGIN',      $self->users_get_date($self->{'USER'}->{'login_time'}));
        $table->row('DATE FORMAT',     $self->{'USER'}->{'date_format'},                           'LAST LOGOUT',     $self->users_get_date($self->{'USER'}->{'logout_time'}));
        $table->row('IDLE TIMEOUT',    $self->{'USER'}->{'timeout'},                               'TEXT MODE',       $self->{'USER'}->{'text_mode'});
        $table->row('PREFER NICKNAME', $self->yes_no($self->{'USER'}->{'prefer_nickname'}, FALSE), 'VIEW FILES',      $self->yes_no($self->{'USER'}->{'view_files'}, FALSE));
        $table->row('UPLOAD FILES',    $self->yes_no($self->{'USER'}->{'upload_files'}, FALSE),    'DOWNLOAD FILES',  $self->yes_no($self->{'USER'}->{'download_files'}, FALSE));
        $table->row('REMOVE FILES',    $self->yes_no($self->{'USER'}->{'remove_files'}, FALSE),    'READ MESSAGES',   $self->yes_no($self->{'USER'}->{'read_message'}, FALSE));
        $table->row('POST MESSAGES',   $self->yes_no($self->{'USER'}->{'post_message'}, FALSE),    'REMOVE MESSAGES', $self->yes_no($self->{'USER'}->{'remove_message'}, FALSE));
        $table->row('SHOW EMAIL',      $self->yes_no($self->{'USER'}->{'show_email'}, FALSE),      'ACCESS LEVEL',    $self->{'USER'}->{'access_level'});
		$table->row('PLAY FORTUNES',   $self->yes_no($self->{'USER'}->{'play_fortunes'}, FALSE),   'ACCOMPLISHMENTS', $self->{'USER'}->{'accomplishments'});
		$table->row('RETRO SYSTEMS',   $self->{'USER'}->{'retro_systems'},'','');
    } else {
        $width = min($width + 7, $self->{'USER'}->{'max_columns'} - 7);
        $table = Text::SimpleTable->new(15, $width);
        $table->row('FIELD', 'VALUE');
        $table->hr();

lib/BBS/Universal/Users.pm  view on Meta::CPAN

        $table->row('BIRTHDAY',        $self->users_get_date($self->{'USER'}->{'birthday'}));
        $table->row('LOCATION',        $self->{'USER'}->{'location'});
        $table->row('BAUD RATE',       $self->{'USER'}->{'baud_rate'});
        $table->row('LAST LOGIN',      $self->{'USER'}->{'login_time'});
        $table->row('LAST LOGOUT',     $self->{'USER'}->{'logout_time'});
        $table->row('TEXT MODE',       $self->{'USER'}->{'text_mode'});
        $table->row('IDLE TIMEOUT',    $self->{'USER'}->{'timeout'});
        $table->row('SHOW EMAIL',      $self->yes_no($self->{'USER'}->{'show_email'},      FALSE));
        $table->row('PREFER NICKNAME', $self->yes_no($self->{'USER'}->{'prefer_nickname'}, FALSE));
        $table->row('VIEW FILES',      $self->yes_no($self->{'USER'}->{'view_files'},      FALSE));
        $table->row('UPLOAD FILES',    $self->yes_no($self->{'USER'}->{'upload_files'},    FALSE));
        $table->row('DOWNLOAD FILES',  $self->yes_no($self->{'USER'}->{'download_files'},  FALSE));
        $table->row('REMOVE FILES',    $self->yes_no($self->{'USER'}->{'remove_files'},    FALSE));
        $table->row('READ MESSAGES',   $self->yes_no($self->{'USER'}->{'read_message'},    FALSE));
        $table->row('POST MESSAGES',   $self->yes_no($self->{'USER'}->{'post_message'},    FALSE));
        $table->row('REMOVE MESSAGES', $self->yes_no($self->{'USER'}->{'remove_message'},  FALSE));
        $table->row('PLAY FORTUNES',   $self->yes_no($self->{'USER'}->{'play_fortunes'},   FALSE));
        $table->row('ACCESS LEVEL',    $self->{'USER'}->{'access_level'});
        $table->row('RETRO SYSTEMS',   $self->{'USER'}->{'retro_systems'});
        $table->row('ACCOMPLISHMENTS', $self->{'USER'}->{'accomplishments'});
    } ## end else [ if ($columns <= 40) ]

sql/database_setup.sql  view on Meta::CPAN

    access_level    ENUM('USER','VETERAN','JUNIOR SYSOP','SYSOP') NOT NULL DEFAULT 'USER',
    login_time      TIMESTAMP NOT NULL DEFAULT NOW(),
    logout_time     TIMESTAMP NOT NULL DEFAULT NOW(),
    text_mode       TINYINT UNSIGNED NOT NULL
);

CREATE TABLE permissions (
    id              INT UNSIGNED PRIMARY KEY,
    show_email      BOOLEAN DEFAULT FALSE,
    view_files      BOOLEAN DEFAULT FALSE,
    upload_files    BOOLEAN DEFAULT FALSE,
    download_files  BOOLEAN DEFAULT FALSE,
    remove_files    BOOLEAN DEFAULT FALSE,
    read_message    BOOLEAN DEFAULT FALSE,
    post_message    BOOLEAN DEFAULT FALSE,
    remove_message  BOOLEAN DEFAULT FALSE,
    sysop           BOOLEAN DEFAULT FALSE,
    prefer_nickname BOOLEAN DEFAULT FALSE,
    play_fortunes   BOOLEAN DEFAULT TRUE,
    banned          BOOLEAN DEFAULT FALSE,
    timeout         SMALLINT UNSIGNED DEFAULT 10

sql/database_setup.sql  view on Meta::CPAN


CREATE TABLE files (
    id           INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    filename     VARCHAR(255) NOT NULL,
    title        VARCHAR(255) NOT NULL,
    user_id      INT UNSIGNED NOT NULL DEFAULT 1,
    category     INT UNSIGNED NOT NULL DEFAULT 1,
    file_type    SMALLINT NOT NULL,
    description  TEXT NOT NULL,
    file_size    BIGINT UNSIGNED NOT NULL,
    uploaded     TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    thumbs_up    INT UNSIGNED DEFAULT 0,
    thumbs_down  INT UNSIGNED DEFAULT 0
);

CREATE TABLE file_types (
    id        SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    type      VARCHAR(255),
    extension VARCHAR(5)
);

sql/database_setup.sql  view on Meta::CPAN

	rss_feed_categories.title            AS rss_category_title,
    users.email                          AS email,
    users.access_level                   AS access_level,
    text_modes.text_mode                 AS text_mode,
    permissions.timeout                  AS timeout,
    users.retro_systems                  AS retro_systems,
    users.accomplishments                AS accomplishments,
    permissions.show_email               AS show_email,
    permissions.prefer_nickname          AS prefer_nickname,
    permissions.view_files               AS view_files,
    permissions.upload_files             AS upload_files,
    permissions.download_files           AS download_files,
    permissions.remove_files             AS remove_files,
    permissions.read_message             AS read_message,
    permissions.post_message             AS post_message,
    permissions.remove_message           AS remove_message,
    permissions.sysop                    AS sysop,
    permissions.play_fortunes            AS play_fortunes,
    permissions.banned                   AS banned
 FROM
    users

sql/database_setup.sql  view on Meta::CPAN

    files.id                             AS id,
    files.filename                       AS filename,
    files.title                          AS title,
    file_categories.title                AS category,
    file_categories.id                   AS category_id,
	file_categories.path                 AS category_path,
    file_types.type                      AS type,
    file_types.extension                 AS extension,
    files.description                    AS description,
    files.file_size                      AS file_size,
    files.uploaded                       AS uploaded,
    files.thumbs_up                      AS thumbs_up,
    files.thumbs_down                    AS thumbs_down,
    users.username                       AS username,
    users.nickname                       AS nickname,
    permissions.prefer_nickname          AS prefer_nickname,
    CONCAT(users.given,' ',users.family) AS fullname

FROM
    files
INNER JOIN

sql/database_setup.sql  view on Meta::CPAN

        'System','Operator',
        (SELECT text_modes.id FROM text_modes WHERE text_modes.text_mode='ANSI'),
        'FULL',
        'I manage and maintain this system',
        'Stuff',
        now(),
        'SYSOP',
        264,
        50
    );
INSERT INTO permissions (id,view_files,show_email,upload_files,download_files,remove_files,read_message,post_message,remove_message,sysop,timeout)
    VALUES (
        LAST_INSERT_ID(),
        true,
        true,
        true,
        true,
        true,
        true,
        true,
        true,



( run in 2.454 seconds using v1.01-cache-2.11-cpan-b16cb0d3907 )