BBS-Universal

 view release on metacpan or  search on metacpan

src/Universal.pm  view on Meta::CPAN

    SOH         => chr(0x01),
    STX         => chr(0x02),
    EOT         => chr(0x04),
    ACK         => chr(0x06),
    NAK         => chr(0x15),
    CAN         => chr(0x18),
    C_CHAR      => 'C',

    SUPPRESS_GO_AHEAD => 3,
    LINEMODE          => 34,
    SE                => 240,
    NOP               => 214,
    DATA_MARK         => 242,
    BREAK             => 243,
    INTERRUPT_PROCESS => 244,
    ABORT_OUTPUT      => 245,
    ARE_YOU_THERE     => 246,
    ERASE_CHARACTER   => 247,
    ERASE_LINE        => 248,
    GO_AHEAD          => 249,
    SB                => 250,
    WILL              => 251,
    WONT              => 252,
    DO                => 253,
    DONT              => 254,
    IAC               => 255,

    PI           => (4 * atan2(1, 1)),
    MENU_CHOICES => ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', '1', '2', '3', '4', '5', '6', '7', '8', '9', '=', '-', '+', '*', '!', '@', '#', '$', '%', '^', '&'],

    SPEEDS       => {    # This depends on the granularity of Time::HiRes
        'FULL'   => 0,
        '300'    => 1 / (300 / 8),
        '600'    => 1 / (600 / 8),
        '1200'   => 1 / (1200 / 8),
        '2400'   => 1 / (2400 / 8),
        '4800'   => 1 / (4800 / 8),
        '9600'   => 1 / (9600 / 8),
        '19200'  => 1 / (19200 / 8),
        '38400'  => 1 / (38400 / 8),
        '57600'  => 1 / (57600 / 8),
        '115200' => 1 / (115200 / 8),
    },
};
use open qw(:std :utf8);

# Modules
use Exporter 'import';
use threads (
    'yield',
    'exit' => 'threads_only',
    'stringify',
);
use Debug::Easy;
use DateTime;
use DBI;
use DBD::mysql;
use File::Basename;
use Time::HiRes qw(time sleep);
use Term::ReadKey;
use Term::ANSIScreen qw( :cursor :screen );
use Term::ANSIColor;
use Text::Format;
use Text::SimpleTable;
use List::Util qw(min max);
use IO::Socket qw(AF_INET SOCK_STREAM SHUT_WR SHUT_RDWR SHUT_RD);
use Cache::Memcached::Fast;
use Number::Format 'format_number';
use XML::RSS::LibXML;
use File::Path;
use File::Which;
use Fcntl qw(:DEFAULT :flock);
use IO::Select;
use POSIX qw(:sys_wait_h);
# use Carp::Always;

BEGIN {
    our @ISA    = qw(Exporter);
    our @EXPORT = qw(
      TRUE
      FALSE
      YES
      NO
      BLOCKING
      NONBLOCKING
      PASSWORD
      ECHO
      SILENT
      NUMERIC

      ANSI
      ASCII
      ATASCII
      PETSCII

      SUPPRESS_GO_AHEAD
      SE
      LINEMODE
      NOP
      DATA_MARK
      BREAK
      INTERRUPT_PROCESS
      ABORT_OUTPUT
      ARE_YOU_THERE
      ERASE_CHARACTER
      ERASE_LINE
      GO_AHEAD
      SB
      WILL
      WONT
      DO
      DONT
      IAC
    );
    our @EXPORT_OK = qw();
    binmode(STDOUT, ":encoding(UTF-8)");

    # VERSIONS #
} ## end BEGIN

sub DESTROY { # Disconnects from the database

src/Universal.pm  view on Meta::CPAN

    }
    $self->{'debug'}->DEBUG(['End Parse Telnet Escape']);
    return (TRUE);
} ## end sub parse_telnet_escape

sub flush_input {
    my $self = shift;

    my $key;
    unless ($self->{'sysop'} || $self->{'local_mode'}) {
        my $handle = $self->{'cl_socket'};
        ReadMode 'noecho', $handle;
        do {
            $key = ReadKey(-1, $handle);
        } until (!defined($key) || $key eq '');
        ReadMode 'restore', $handle;
    } else {
        ReadMode 'ultra-raw';
        do {
            $key = ReadKey(-1);
        } until (!defined($key) || $key eq '');
        ReadMode 'restore';
    } ## end else
    return (TRUE);
} ## end sub flush_input

sub get_key {
    my $self     = shift;
    my $echo     = shift;
    my $blocking = shift;

    my $key     = undef;
    my $mode    = $self->{'USER'}->{'text_mode'};
    my $timeout = $self->{'USER'}->{'timeout'} * 60;
    local $/ = "\x{00}";
    if ($self->{'sysop'} || $self->{'local_mode'}) {
        ReadMode 'ultra-raw';
        $key = ($blocking) ? ReadKey($timeout) : ReadKey(-1);
        ReadMode 'restore';
        threads->yield;
    } elsif ($self->is_connected()) {
        my $handle = $self->{'cl_socket'};
        ReadMode 'ultra-raw', $self->{'cl_socket'};
        my $escape;
        do {
            $escape = FALSE;
            $key    = ($blocking) ? ReadKey($timeout, $handle) : ReadKey(-1, $handle);
            if ($key eq chr(255)) {    # IAC sequence
                my $command = ReadKey($timeout, $handle);
                my $option  = ReadKey($timeout, $handle);
                $self->parse_telnet_escape(ord($command), ord($option));
                $escape = TRUE;
            } ## end if ($key eq chr(255))
        } until (!$escape || $self->is_connected());
        ReadMode 'restore', $self->{'cl_socket'};
        threads->yield;
    } ## end elsif ($self->is_connected...)
    return ($key) if ($key eq chr(13));
    if ($key eq chr(127) or $key eq chr(7)) {
        if ($mode eq 'ANSI') {
            $key = $self->{'ansi_meta'}->{'cursor'}->{'BACKSPACE'}->{'out'};
        } elsif ($mode eq 'ATASCII') {
            $key = $self->{'atascii_meta'}->{'BACKSPACE'}->{'out'};
        } elsif ($mode eq 'PETSCII') {
            $key = $self->{'petscii_meta'}->{'BACKSPACE'}->{'out'};
        } else {
            $key = $self->{'ascii_meta'}->{'BACKSPACE'}->{'out'};
        }
        $self->output("$key $key") if ($echo);
    } ## end if ($key eq chr(127) or...)
    threads->yield;
    return ($key);
} ## end sub get_key


sub get_line {
    my $self = shift;
    my $type = shift;
    my $line = shift;

    my $echo    = $type->{'type'};
    my $limit   = $type->{'max'};
    my $choices = $type->{'choices'} if (exists($type->{'choices'}));
    if (exists($type->{'default'})) {
        $line = $type->{'default'};
    }

    $self->{'debug'}->DEBUG(['Start Get Line']);
    $self->flush_input();

    my $key;

    $self->output($line) if ($line ne '');
    my $mode = $self->{'USER'}->{'text_mode'};
    my $backspace;
    if ($mode eq 'ANSI') {
        $backspace = $self->{'ansi_meta'}->{'cursor'}->{'BACKSPACE'}->{'out'};
    } elsif ($mode eq 'ATASCII') {
        $backspace = $self->{'atascii_meta'}->{'BACKSPACE'}->{'out'};
    } elsif ($mode eq 'PETSCII') {
        $backspace = $self->{'petscii_meta'}->{'BACKSPACE'}->{'out'};
    } else {
        $backspace = $self->{'ascii_meta'}->{'BACKSPACE'}->{'out'};
    }

    if ($echo == PASSWORD) {
        $self->{'debug'}->DEBUG(['  Mode:  PASSWORD']);
        while (($self->is_connected() || $self->{'local_mode'}) && $key ne chr(13) && $key ne chr(3)) {
            if (length($line) <= $limit) {
                $key = $self->get_key(SILENT, BLOCKING);
                return ('') if (defined($key) && $key eq chr(3));
                if (defined($key) && $key ne '') {
                    if ($key eq $backspace) {
                        my $len = length($line);
                        if ($len > 0) {
                            $self->output("$key $key");
                            chop($line);
                        }
                    } elsif ($key ne chr(13) && $key ne chr(3) && $key ne chr(10) && ord($key) > 31 && ord($key) < 127) {
                        $self->output('*');
                        $line .= $key;
                    } else {
                        $self->output('[% RING BELL %]');
                    }
                } ## end if (defined($key) && $key...)
            } else {
                $key = $self->get_key(SILENT, BLOCKING);
                if (defined($key) && $key eq chr(3)) {
                    return ('');
                }
                if (defined($key) && ($key eq $backspace)) {
                    $key = $backspace;
                    $self->output("$key $key");
                    chop($line);
                } else {
                    $self->output('[% RING BELL %]');
                }
            } ## end else [ if (length($line) <= $limit)]
        } ## end while (($self->is_connected...))
    } elsif ($echo == RADIO) {
        $self->{'debug'}->DEBUG(['  Mode:  RADIO']);

        my $mapping;
        my @menu_choices = @{$self->{'MENU CHOICES'}};

        foreach my $choice (@{$choices}) {
            $mapping->{ shift(@menu_choices) } = {
                'command'      => $choice,
                'color'        => 'WHITE',
                'access_level' => 'USER',
                'text'         => $choice,
            }
        }
        $self->output("\n\n");
        $self->show_choices($mapping);
        $self->prompt('Choose');
        my $key;



( run in 0.744 second using v1.01-cache-2.11-cpan-39bf76dae61 )