Exemple #1
0
def lc_retrieve():
    """
    Returns tuple of ([nicknames,] u'text'), where 'text' describes in Ansi
    color the last callers to the system, and 'nicknames' is simply a list
    of last callers (for lightbar selection key).
    """
    # pylint: disable=R0914
    #         Too many local variables
    from x84.bbs import list_users, get_user, ini, timeago, getterminal
    import time
    term = getterminal()
    udb = dict()
    for handle in list_users():
        user = get_user(handle)
        udb[(user.lastcall, handle)] = (user.calls, user.location)
    padd_handle = (ini.CFG.getint('nua', 'max_user') + 2)
    padd_origin = (ini.CFG.getint('nua', 'max_location') + 2)
    rstr = u''
    nicks = []
    for ((tm_lc, handle), (_nc, origin)) in (reversed(sorted(udb.items()))):
        is_sysop = 'sysop' in get_user(handle).groups
        rstr += (term.bold_red(u'@') if is_sysop else u''
                 ) + (handle.ljust(padd_handle - (2 if is_sysop else 1)))
        rstr += term.red(origin.ljust(padd_origin))
        rstr += timeago(time.time() - tm_lc)
        rstr += u'\n'
        nicks.append(handle)
    return (nicks, rstr.rstrip())
Exemple #2
0
def locate_user(term, point):
    """ Prompt for search pattern and return discovered User. """
    _color1, _color2, _color3 = [
        getattr(term, _color)
        for _color in (color_lowlight, color_highlight, color_field_edit)
    ]

    # show help
    width = term.width - (point.x * 2)
    help_txt = (u'Enter username or glob pattern.  Press escape to cancel.')
    y_offset = 0
    for y_offset, txt in enumerate(term.wrap(help_txt, width=width)):
        echo(term.move(point.y + y_offset, point.x))
        echo(_color1(txt) + term.clear_eol)
    point_prompt = Point(y=point.y + y_offset + 2, x=point.x)

    editor = LineEditor(nua.username_max_length, colors={'highlight': _color3})
    while True:
        # prompt for handle
        echo(term.move(*point_prompt))
        echo(u'handle: ' + term.clear_eol)
        inp = editor.read()

        point = Point(y=point_prompt.y + 2, x=point.x)
        if inp is None:
            # canceled (escape)
            return
        elif u'*' in inp or u'?' in inp:
            # a glob pattern, fetch all usernames
            handles = fnmatch.filter(list_users(), inp)
            if len(handles) == 0:
                echo(u''.join((term.move(*point),
                               u'No matches for {0}.'.format(_color2(inp)),
                               term.clear_eos)))
            elif len(handles) == 1:
                return get_user(handles[0])
            else:
                matches_text = (
                    u'{0} accounts matched, chose one: {1}.'.format(
                        _color2(str(len(handles))),
                        u', '.join(_color2(handle) for handle in handles)))
                echo(term.move(*point))
                for y_offset, txt in enumerate(
                        term.wrap(matches_text, width=width)):
                    echo(term.move(point.y + y_offset, point.x))
                    echo(txt + term.clear_eol)
                    if point.y + y_offset > term.height - 3:
                        # we simply cannot display anymore
                        break
                echo(term.clear_eos)
        else:
            handle = find_user(inp)
            if handle is not None:
                return get_user(handle)
            echo(u''.join(
                (term.move(*point),
                 u'No matches for {0}.'.format(_color2(inp)), term.clear_eos)))
Exemple #3
0
def toplist(parameter):
    session, term = getsession(), getterminal()
    handle = session.user.handle

    counter = 0
    user_handles = list_users()
    username = {}
    feature = {}
    location = {}
    database = {}

    echo(term.red + u' crunching data..')

    for handle in user_handles:

        user_record = get_user(handle)

        if u'sysop' in user_record.groups:
            continue

        if parameter == 'calls':
            database[user_record.handle.encode('utf8')] = user_record.calls
        if parameter == 'msgs':
            database[user_record.handle.encode('utf8')] = user_record.get(
                'msgs_sent', 0)

    for name in sorted(database, key=database.get, reverse=True):
        username[counter] = name

        user_record = get_user(name)
        location[counter] = user_record.location

        feature[counter] = str(database[name])
        counter = counter + 1

    if counter > 10:
        counter = 10    # we only want to display the top ten users

    echo(term.clear())
    showansi('topten.ans')

    if parameter == 'calls':
        echo(term.yellow + term.move(7, 1) +
             u'[ % ]                                                 - tOP tEN cALLERS  [ % ]')
    if parameter == 'msgs':
        echo(term.yellow + term.move(7, 1) +
             u'[ % ]                                                 - tOP tEN wRITERS  [ % ]')

    echo(term.cyan + term.move(9, 3) + u'username' + term.move_x(27) +
         u'group/location' + term.move_x(67) + parameter + u'\n\n')

    for i in range(0, counter):
        echo(term.white + term.move_x(3) +
             username[i] + term.move_x(27) + location[i] + term.move_x(67) + feature[i] + u'\r\n')

    waitprompt()
Exemple #4
0
def locate_user(term, point):
    """ Prompt for search pattern and return discovered User. """
    _color1, _color2, _color3 = [
        getattr(term, _color) for _color in (
            color_lowlight, color_highlight, color_field_edit)]

    # show help
    width = term.width - (point.x * 2)
    help_txt = (u'Enter username or glob pattern.  Press escape to cancel.')
    y_offset = 0
    for y_offset, txt in enumerate(term.wrap(help_txt, width=width)):
        echo(term.move(point.y + y_offset, point.x))
        echo(_color1(txt) + term.clear_eol)
    point_prompt = Point(y=point.y + y_offset + 2, x=point.x)

    editor = LineEditor(nua.username_max_length, colors={'highlight': _color3})
    while True:
        # prompt for handle
        echo(term.move(*point_prompt))
        echo(u'handle: ' + term.clear_eol)
        inp = editor.read()

        point = Point(y=point_prompt.y + 2, x=point.x)
        if inp is None:
            # canceled (escape)
            return
        elif u'*' in inp or u'?' in inp:
            # a glob pattern, fetch all usernames
            handles = fnmatch.filter(list_users(), inp)
            if len(handles) == 0:
                echo(u''.join((term.move(*point),
                               u'No matches for {0}.'.format(_color2(inp)),
                               term.clear_eos)))
            elif len(handles) == 1:
                return get_user(handles[0])
            else:
                matches_text = (
                    u'{0} accounts matched, chose one: {1}.'.format(
                        _color2(str(len(handles))), u', '.join(
                            _color2(handle) for handle in handles)))
                echo(term.move(*point))
                for y_offset, txt in enumerate(
                        term.wrap(matches_text, width=width)):
                    echo(term.move(point.y + y_offset, point.x))
                    echo(txt + term.clear_eol)
                    if point.y + y_offset > term.height - 3:
                        # we simply cannot display anymore
                        break
                echo(term.clear_eos)
        else:
            handle = find_user(inp)
            if handle is not None:
                return get_user(handle)
            echo(u''.join((term.move(*point),
                           u'No matches for {0}.'.format(_color2(inp)),
                           term.clear_eos)))
Exemple #5
0
def toplist(parameter):
    session, term = getsession(), getterminal()
    handle = session.user.handle

    counter = 0
    user_handles = list_users()
    username = {}
    feature = {}
    location = {}
    database = {}

    echo(term.red+u' crunching data..')

    for handle in user_handles:

       user_record = get_user(handle)

       if u'sysop' in user_record.groups:
           continue

       if parameter == 'calls':
           database[user_record.handle.encode('utf8')] = user_record.calls
       if parameter == 'msgs':
           database[user_record.handle.encode('utf8')] = user_record.get('msgs_sent',0)

    for name in sorted(database, key=database.get, reverse=True):
       username[counter] = name

       user_record = get_user(name)
       location[counter] = user_record.location

       feature[counter] = str(database[name])
       counter = counter + 1

    if counter > 10:
        counter = 10    # we only want to display the top ten users

    echo(term.clear())
    showansi('topten.ans')

    if parameter == 'calls':
        echo(term.yellow+term.move(7,1)+u'[ % ]                                                 - tOP tEN cALLERS  [ % ]')
    if parameter == 'msgs':
        echo(term.yellow+term.move(7,1)+u'[ % ]                                                 - tOP tEN wRITERS  [ % ]')

    echo(term.cyan+term.move(9,3)+u'username'+term.move_x(27)+u'group/location'+term.move_x(67)+parameter+u'\n\n')

    for i in range (0, counter):
        echo(term.white+term.move_x(3)+username[i]+term.move_x(27)+location[i]+term.move_x(67)+feature[i]+u'\r\n')

    waitprompt()
Exemple #6
0
def refresh_opts(pager, handle):
    """ Refresh pager border with command keys available. """
    from x84.bbs import getsession, getterminal, get_user, find_user, Ansi
    session, term = getsession(), getterminal()
    if not handle or not find_user(handle):
        has_plan = 0
    else:
        has_plan = 0 != len(get_user(handle).get('.plan', u'').strip())
    decorate = lambda key, desc: u''.join((
        term.red_underline(key,),
        u':',
        term.yellow(desc.split()[0]), u' ',
        u' '.join(desc.split()[1:]),
        u' ' if len(desc.split()) > 1 else u'',))
    statusline = u''.join((
        term.bold_yellow(u'- '),
        decorate(u'Escape/q', 'Uit'),
        decorate(u'v', 'iEW .PLAN') if has_plan else u'',
        decorate(u'e', 'dit USR') if 'sysop' in session.user.groups else u'',
        term.bold_yellow(u'-'),
    ))
    if len(Ansi(statusline)) < (pager.visible_width - 4):
        return pager.border() + pager.footer(statusline)
    else:
        return pager.border() + pager.footer(term.bold_red('q') + u':uit')
Exemple #7
0
def iter_userlist():
    handles = sorted(list_users(), key=unicode.lower)
    timenow = time.time()
    return (user_record(handle=user.handle,
                        location=user.location,
                        timeago=timenow - user.lastcall)
            for user in (get_user(handle) for handle in handles))
Exemple #8
0
def refresh_opts(pager, handle):
    """ Refresh pager border with command keys available. """
    from x84.bbs import getsession, getterminal, get_user, find_user, Ansi
    session, term = getsession(), getterminal()
    if not handle or not find_user(handle):
        has_plan = 0
    else:
        has_plan = 0 != len(get_user(handle).get('.plan', u'').strip())
    decorate = lambda key, desc: u''.join((
        term.red_underline(key,),
        u':',
        term.yellow(desc.split()[0]), u' ',
        u' '.join(desc.split()[1:]),
        u' ' if len(desc.split()) > 1 else u'',))
    statusline = u''.join((
        term.bold_yellow(u'- '),
        decorate(u'Escape/q', 'Uit'),
        decorate(u'v', 'iEW .PLAN') if has_plan else u'',
        decorate(u'e', 'dit USR') if 'sysop' in session.user.groups else u'',
        term.bold_yellow(u'-'),
    ))
    if len(Ansi(statusline)) < (pager.visible_width - 4):
        return pager.border() + pager.footer(statusline)
    else:
        return pager.border() + pager.footer(term.bold_red('q') + u':uit')
Exemple #9
0
def main(anonymous=False, new=False, username=''):
    """ Main procedure. """
    from x84.bbs import (
        getsession,
        getterminal,
        find_user,
        get_user,
        User,
    )

    session, term = getsession(), getterminal()
    session.activity = 'sftp'

    if anonymous:
        user = User(u'anonymous')
    else:
        assert not new, ("new@ user not supported by SFTP.")

        # ProperCase user-specified handle
        handle = find_user(username)
        assert handle is not None, handle

        # fetch user record
        user = get_user(handle)

    # assign session user, just as top.py function login()
    session.user = user

    while True:
        inp = term.inkey()  # should block indefinately
        log = logging.getLogger(__name__)
        log.warn('Got inkey: {0!r}'.format(inp))
Exemple #10
0
def authenticate_user(handle, password):
    """ Return True if the given handle and password are correct. """

    # artificial delay -- this ensures people cannot guess
    # for user accounts, where existing ones would delay a
    # long while, but unknown users are quickly denied.
    artificial_delay = max(1.0, random.randrange(0, unknown_sleep * 100) / 100)

    matching_handle = find_user(handle)
    if matching_handle is None:
        log.debug('Failed login for {handle}: no such user.'
                  .format(handle=handle))
        time.sleep(artificial_delay)
        return False

    elif not password.strip():
        log.debug('Failed login for {handle}: password not provided.'
                  .format(handle=handle))
        time.sleep(artificial_delay)
        return False

    user = get_user(matching_handle)
    if user.auth(password):
        # success !
        log.debug('Login succeeded for {handle}.'
                  .format(handle=handle))
        return user

    log.debug('Failed login for {handle}: wrong password.'
              .format(handle=handle))
    return False
Exemple #11
0
def iter_userlist():
    handles = sorted(list_users(), key=unicode.lower)
    timenow = time.time()
    return (user_record(handle=user.handle,
                        location=user.location,
                        timeago=timenow - user.lastcall)
            for user in (get_user(handle) for handle in handles))
Exemple #12
0
def authenticate_user(handle, password):
    """ Return True if the given handle and password are correct. """

    # artificial delay -- this ensures people cannot guess
    # for user accounts, where existing ones would delay a
    # long while, but unknown users are quickly denied.
    artificial_delay = max(1.0, random.randrange(0, unknown_sleep * 100) / 100)

    matching_handle = find_user(handle)
    if matching_handle is None:
        log.debug(
            'Failed login for {handle}: no such user.'.format(handle=handle))
        time.sleep(artificial_delay)
        return False

    elif not password.strip():
        log.debug('Failed login for {handle}: password not provided.'.format(
            handle=handle))
        time.sleep(artificial_delay)
        return False

    user = get_user(matching_handle)
    if user.auth(password):
        # success !
        log.debug('Login succeeded for {handle}.'.format(handle=handle))
        return user

    log.debug(
        'Failed login for {handle}: wrong password.'.format(handle=handle))
    return False
Exemple #13
0
def view_plan(handle):
    """ Display .plan file for handle. """
    from x84.bbs import getterminal, echo, Ansi, get_user
    term = getterminal()
    echo(u'\r\n\r\n')
    echo(Ansi(get_user(handle).get('.plan', u'No Plan.')).wrap(term.width))
    echo(u'\r\n')
    pak()
Exemple #14
0
def get_next_user(tgt_user):
    """ Get next user in sorted order. """
    handles = sorted(list_users())
    try:
        current_idx = handles.index(tgt_user.handle)
    except ValueError:
        # what if we just deleted the target user?
        # inject it back into `handles' list and try again
        handles = sorted(handles + [tgt_user.handle])
        current_idx = handles.index(tgt_user.handle)
    idx = min(current_idx + 1, len(handles) - 1)
    try:
        return get_user(handles[idx])
    except KeyError:
        # and what if we deleted the last user of the list?
        # take the previous one.
        return get_user(handles[idx - 1])
Exemple #15
0
def get_next_user(tgt_user):
    """ Get next user in sorted order. """
    handles = sorted(list_users())
    try:
        current_idx = handles.index(tgt_user.handle)
    except ValueError:
        # what if we just deleted the target user?
        # inject it back into `handles' list and try again
        handles = sorted(handles + [tgt_user.handle])
        current_idx = handles.index(tgt_user.handle)
    idx = min(current_idx + 1, len(handles) - 1)
    try:
        return get_user(handles[idx])
    except KeyError:
        # and what if we deleted the last user of the list?
        # take the previous one.
        return get_user(handles[idx - 1])
Exemple #16
0
def migrate_105lc():
    from x84.bbs import echo, DBProxy, list_users, get_user
    # migrating lastcallers database for 1.0.5 upgrade
    lc = DBProxy('lastcalls')
    for handle in list_users():
        user = get_user(handle)
        lc[(handle)] = (user.lastcall, user.calls, user.location)
        echo('\r\n' + user.handle + '.')
    echo('\r\n\r\nlast callers db rebuilt!')
Exemple #17
0
def migrate_105lc():
    # migrating lastcallers database for 1.0.5 upgrade
    from x84.bbs import echo, DBProxy, list_users, get_user
    lc = DBProxy('lastcalls')
    for handle in list_users():
        user = get_user(handle)
        lc[(handle)] = (user.lastcall, user.calls, user.location)
        echo(u'\r\n' + user.handle + '.')
    echo('\r\n\r\nlast callers db rebuilt!')
Exemple #18
0
def iter_userlist():
    handles = sorted(list_users(), key=unicode.lower)
    timenow = time.time()
    user_record = collections.namedtuple('userlist',
                                         ['handle', 'location', 'timeago'])
    return (user_record(handle=user.handle,
                        location=user.location,
                        timeago=timenow - user.lastcall)
            for user in (get_user(handle) for handle in handles))
Exemple #19
0
def iter_userlist():
    handles = sorted(list_users(), key=unicode.lower)
    timenow = time.time()
    user_record = collections.namedtuple('userlist', [
        'handle', 'location', 'timeago'])
    return (user_record(handle=user.handle,
                        location=user.location,
                        timeago=timenow - user.lastcall)
            for user in (get_user(handle) for handle in handles))
Exemple #20
0
def check_user_password(username, password):
    """ Boolean return when username and password match user record. """
    from x84.bbs import find_user, get_user
    handle = find_user(username)
    if handle is None:
        return False
    user = get_user(handle)
    if user is None:
        return False
    return password and user.auth(password)
Exemple #21
0
def check_user_password(username, password):
    """ Boolean return when username and password match user record. """
    from x84.bbs import find_user, get_user
    handle = find_user(username)
    if handle is None:
        return False
    user = get_user(handle)
    if user is None:
        return False
    return password and user.auth(password)
Exemple #22
0
def view_plan(handle):
    """ Display .plan file for handle. """
    from x84.bbs import getterminal, echo, Ansi, get_user, find_user
    term = getterminal()
    echo(u'\r\n\r\n')
    if not find_user(handle):
        echo(Ansi(u'No Plan.'))
    else:
        echo(Ansi(get_user(handle).get('.plan', u'No Plan.')).wrap(term.width))
    echo(u'\r\n')
    pak()
Exemple #23
0
def get_user_record(handle):
    """
    Find and return User class instance by given ``handle``.

    If handle is ``anonymous``, Create and return a new User object.
    """
    if handle == u'anonymous':
        log.debug('anonymous login'.format(handle))
        return User(u'anonymous')

    log.debug('login by {0!r}'.format(handle))
    return get_user(handle)
Exemple #24
0
def get_user_record(handle):
    """
    Find and return User class instance by given ``handle``.

    If handle is ``anonymous``, Create and return a new User object.
    """
    if handle == u'anonymous':
        log.debug('anonymous login')
        return User(u'anonymous')

    log.debug('login by {0!r}'.format(handle))
    return get_user(handle)
Exemple #25
0
def main(handle=None):
    """ Main procedure. """
    # pylint: disable=W0603
    #         Using the global statement
    from x84.bbs import getsession, getterminal
    from x84.bbs import get_user
    session, term = getsession(), getterminal()
    user = session.user if ('sysop' not in session.user.groups
            ) or (handle is None) else get_user(handle)
    global EXIT
    while not EXIT:
        session.activity = 'User profile editor'
        dummy_pager(user)
Exemple #26
0
def main(handle=None):
    """ Main procedure. """
    # pylint: disable=W0603
    #         Using the global statement
    from x84.bbs import getsession, getterminal
    from x84.bbs import get_user
    session, term = getsession(), getterminal()
    user = session.user if ('sysop' not in session.user.groups
            ) or (handle is None) else get_user(handle)
    global EXIT
    while not EXIT:
        session.activity = 'User profile editor'
        dummy_pager(user)
Exemple #27
0
def get_user_record(handle):
    """
    根据 handle 参数(最前面的 matrix  传递过来的)获得用户信息
    Find and return User class instance by given ``handle``.

    If handle is ``anonymous``, Create and return a new User object.
    """
    log = logging.getLogger(__name__)

    if handle == u'anonymous':
        log.debug('anonymous login'.format(handle))
        return User(u'anonymous')

    log.debug('login by {0!r}'.format(handle))
    return get_user(handle)
Exemple #28
0
def matches_email(handle, email):
    """ Return User record for handle if it matches email. """
    matching_handle = find_user(handle)
    user = matching_handle and get_user(matching_handle)
    if not user:
        log.debug("password reset failed, no such user {0} for email {1}.".format(handle, email))
        return False
    elif not user.email.strip():
        log.debug("password reset failed, user {0} has no email on file.".format(handle))
        return False
    elif email.lower() != user.email.lower():
        log.debug("pasword reset failed, email mismatch: {0} != {1}.".format(email, user.email))
        return False

    # success !
    return user
Exemple #29
0
Fichier : chat.py Projet : hick/x84
def show_say(handle, tgt_channel, mesg):
    """ return terminal sequence for /say performed by handle. """
    from x84.bbs import getsession, getterminal, get_user
    session, term = getsession(), getterminal()
    return u''.join((
        time.strftime('%H:%M'),
        u' ',
        term.bold_black(u'<'),
        (term.bold_red(u'@') if handle != 'anonymous'
         and 'sysop' in get_user(handle).groups else u''),
        (handle if handle != session.handle else term.bold(handle)),
        (u':%s' % (tgt_channel, ) if 'sysop' in session.user.groups else u''),
        term.bold_black(u'>'),
        u' ',
        mesg,
    ))
Exemple #30
0
def show_say(handle, tgt_channel, mesg):
    """ return terminal sequence for /say performed by handle. """
    from x84.bbs import getsession, getterminal, get_user
    session, term = getsession(), getterminal()
    return u''.join((
        time.strftime('%H:%M'), u' ',
        term.bold_black(u'<'),
        (term.bold_red(u'@') if handle != 'anonymous'
            and 'sysop' in get_user(handle).groups
            else u''),
        (handle if handle != session.handle
            else term.bold(handle)),
        (u':%s' % (tgt_channel,)
            if 'sysop' in session.user.groups
            else u''),
        term.bold_black(u'>'), u' ',
        mesg,))
Exemple #31
0
def merge_mystic():
    """ Example script to merge csv records into userbase. """
    # pylint: disable=R0914
    #         Too many local variables
    from x84.bbs import ini, echo, getch, User, get_user, find_user
    import os
    # you must modify variable ``do_write`` to commit changes,
    # csv format; 'user:pass:origin:email\n', in iso8859-1 encoding.
    do_write = False
    inp_file = os.path.join(ini.CFG.get('system', 'datapath'),
                            'mystic_dat.csv')
    lno = 0
    for lno, line in enumerate(open(inp_file, 'r')):
        handle = line.split(':', 1)[0].strip().decode('iso8859-1')
        attrs = line.rstrip().split(':')[2:]
        (_password, _location, _email) = attrs
        (_password,
         _location, _email) = (_password.strip().decode('iso8859-1'),
                               _location.strip().decode('iso8859-1'),
                               _email.strip().decode('iso8859-1'))
        echo(u''.join((
            u'\r\n',
            handle,
            u': ',
            '%d ' % (len(_password)),
            '%s ' % (_location),
            '%s ' % (_email),
        )))
        match = find_user(handle)
        if match is None:
            user = User(handle)
            user.location = _location
            user.email = _email
            user.password = _password
        else:
            user = get_user(match)
        user.groups.add('old-school')
        if do_write:
            user.save()
    echo('\r\n\r\n%d lines processed.' % (lno, ))
    getch()
Exemple #32
0
def check_user_pubkey(username, public_key):
    """ Boolean return when public_key matches user record. """
    from x84.bbs import find_user, get_user
    log = logging.getLogger(__name__)
    handle = find_user(username)
    if handle is None:
        return False
    user_pubkey = get_user(handle).get('pubkey', False)
    if not user_pubkey:
        log.debug('{0} attempted pubkey authentication, '
                  'but no public key on record for the user.'.format(username))
        return False
    try:
        stored_pubkey = parse_public_key(user_pubkey)
    except (ValueError, Exception):
        import sys
        (exc_type, exc_value, exc_traceback) = sys.exc_info()
        log.debug('{0} for stored public key of user {1!r}: '
                  '{2}'.format(exc_type, username, exc_value))
    else:
        return stored_pubkey == public_key
Exemple #33
0
def matches_email(handle, email):
    """ Return User record for handle if it matches email. """
    matching_handle = find_user(handle)
    user = matching_handle and get_user(matching_handle)
    if not user:
        log.debug(
            'password reset failed, no such user {0} for email {1}.'.format(
                handle, email))
        return False
    elif not user.email.strip():
        log.debug(
            'password reset failed, user {0} has no email on file.'.format(
                handle))
        return False
    elif email.lower() != user.email.lower():
        log.debug('pasword reset failed, email mismatch: {0} != {1}.'.format(
            email, user.email))
        return False

    # success !
    return user
Exemple #34
0
def lc_retrieve():
    """
    Returns tuple of ([nicknames,] u'text'), where 'text' describes in Ansi
    color the last callers to the system, and 'nicknames' is simply a list
    of last callers (for lightbar selection key).
    """
    # pylint: disable=R0914
    #         Too many local variables
    from x84.bbs import get_user, ini, timeago, getterminal
    from x84.bbs import DBProxy
    import time
    term = getterminal()
    udb = DBProxy('lastcalls')
    # re-order by time called; unfortunate ..; note that sqlite
    # encodes unicode as utf-8; but doesn't decode it on retrieval,
    # of dict keys; possible upstream patching opportunity here,
    sortdb = {}
    for ((handle), (tm_lc, _nc, origin)) in (udb.items()):
        while tm_lc in sortdb:
            tm_lc += 0.1
        sortdb[tm_lc] = [handle.decode('utf-8'), _nc, origin]

    padd_handle = (ini.CFG.getint('nua', 'max_user') + 2)
    padd_origin = (ini.CFG.getint('nua', 'max_location') + 2)
    rstr = u''
    nicks = []
    for tm_lc, (handle, _nc, origin) in (reversed(sorted(sortdb.items()))):
        try:
            is_sysop = 'sysop' in get_user(handle).groups
        except KeyError:
            # anonymous/deleted accts,
            is_sysop = False
        rstr += (term.bold_red(u'@') if is_sysop else u''
                 ) + (term.ljust(handle,
                     (padd_handle - (2 if is_sysop else 1))))
        rstr += term.red(origin.ljust(padd_origin))
        rstr += timeago(time.time() - tm_lc)
        rstr += u'\n'
        nicks.append(handle)
    return (nicks, rstr.rstrip())
Exemple #35
0
def check_user_pubkey(username, public_key):
    """ Boolean return when public_key matches user record. """
    from x84.bbs import find_user, get_user
    log = logging.getLogger(__name__)
    handle = find_user(username)
    if handle is None:
        return False
    user_pubkey = get_user(handle).get('pubkey', False)
    if not user_pubkey:
        log.debug('{0} attempted pubkey authentication, '
                  'but no public key on record for the user.'
                  .format(username))
        return False
    try:
        stored_pubkey = parse_public_key(user_pubkey)
    except (ValueError, Exception):
        import sys
        (exc_type, exc_value, exc_traceback) = sys.exc_info()
        log.debug('{0} for stored public key of user {1!r}: '
                  '{2}'.format(exc_type, username, exc_value))
    else:
        return stored_pubkey == public_key
Exemple #36
0
def merge_mystic():
    """ Example script to merge csv records into userbase. """
    # pylint: disable=R0914
    #         Too many local variables
    from x84.bbs import ini, echo, getch, User, get_user, find_user
    import os
    # you must modify variable ``do_write`` to commit changes,
    # csv format; 'user:pass:origin:email\n', in iso8859-1 encoding.
    do_write = False
    inp_file = os.path.join(
        ini.CFG.get('system', 'datapath'),
        'mystic_dat.csv')
    lno = 0
    for lno, line in enumerate(open(inp_file, 'r')):
        handle = line.split(':', 1)[0].strip().decode('iso8859-1')
        attrs = line.rstrip().split(':')[2:]
        (_password, _location, _email) = attrs
        (_password, _location, _email) = (
            _password.strip().decode('iso8859-1'),
            _location.strip().decode('iso8859-1'),
            _email.strip().decode('iso8859-1'))
        echo(u''.join((u'\r\n',
                       handle, u': ',
                       '%d ' % (len(_password)),
                       '%s ' % (_location),
                       '%s ' % (_email),)))
        match = find_user(handle)
        if match is None:
            user = User(handle)
            user.location = _location
            user.email = _email
            user.password = _password
        else:
            user = get_user(match)
        user.groups.add('old-school')
        if do_write:
            user.save()
    echo(u'\r\n\r\n%d lines processed.' % (lno,))
    getch()
Exemple #37
0
def main(handle=None):
    """ Main procedure. """
    dirty = -1
    session, term = getsession(), getterminal()
    tgt_user = get_user(handle) if handle else session.user
    legal_input_characters = string.letters + u'<>'

    # re-display entire screen on loop,
    while True:

        # full-screen refresh on -1; otherwise only the fields (such as when an
        # edit has occurred).  dirty = -1 is set on screen resize, for example.
        if dirty == -1:
            # display banner, discover (y,x) point after,
            point_margin = show_banner(term)

            # forward-calculate the prompt (y,x) point
            point_prompt = Point(y=point_margin.y + 15, x=point_margin.x)

        # get all field values and locations,
        fields = get_display_fields(tgt_user, point=point_margin)

        # display all fields and prompt
        echo(display_options(term, fields))
        echo(display_prompt(term, session, point=point_prompt))

        dirty = 0

        # blocking loop until screen refresh or keystroke
        event = None
        while event is None:
            # This dual input/refresh trick only works here, receiving
            # raw (undecoded) keyboard data as 'inp' because we don't
            # require the use of any application keys or multi-byte
            # sequences, only alphabetic characters.
            event, data = session.read_events(('input', 'refresh'))
            if event == 'refresh':
                dirty = -1
                break

            inp = data
            if inp in legal_input_characters:
                # display command input
                echo(inp.decode('ascii'))

            if inp == u'q':
                # [q]uit
                echo(u'\r\n')
                return
            elif inp == u'\x0c':
                # [^L] refresh
                dirty = -1
                break
            elif inp == u'f' and session.user.is_sysop:
                tgt_user = locate_user(term, point_prompt) or tgt_user
                break
            elif inp == u'd':
                # yes, you can delete yourself !!
                if delete_user(term, tgt_user, point_prompt):
                    if tgt_user == session.user:
                        # but if you delete yourself,
                        # you must logoff.
                        goto('logoff')

                    # otherwise, move to next user
                    tgt_user = get_next_user(tgt_user)
                break
            elif inp == u'<' and session.user.is_sysop:
                tgt_user = get_prev_user(tgt_user)
                break
            elif inp == u'>' and session.user.is_sysop:
                tgt_user = get_next_user(tgt_user)
                break
            elif inp in string.letters:
                if do_command(term, session, inp, fields, tgt_user,
                              point_prompt):
                    # when returning True, perform full-screen refresh,
                    break
                else:
                    # otherwise, clean prompt field
                    time.sleep(0.2)
                    echo(u'\b \b')
            elif inp in legal_input_characters:
                # though legal, not authorized: clean prompt field
                time.sleep(0.2)
                echo(u'\b \b')
            event = None
        dirty = dirty or 1
Exemple #38
0
def get_prev_user(tgt_user):
    """ Get previous user in sorted order. """
    handles = sorted(list_users())
    idx = max(handles.index(tgt_user.handle) - 1, 0)
    return get_user(handles[idx])
Exemple #39
0
def dummy_pager(last_callers):
    """ Dummy pager for displaying last callers """
    # pylint: disable=R0914
    #         Too many local variables
    from x84.bbs import getterminal, getsession, echo, getch, ini, find_user
    from x84.bbs import LineEditor, Ansi, list_users, get_user, gosub
    session, term = getsession(), getterminal()
    msg_prompt = (
        u'\r\n%sONtiNUE, %stOP, %sON-StOP %siEW .PlAN%s ?\b\b' % (
        term.bold(u'[c]'),
        term.bold(u'[s]'),
        term.bold(u'n'),
        term.bold(u'[v]'),
        u' [e]dit USR' if (
        'sysop' in session.user.groups) else u'',))
    msg_partial = u'PARtiAl MAtChES'
    msg_prompt_handle = u'ViEW .PlAN ::- ENtER hANdlE: '

    redraw()
    echo(u'\r\n\r\n')
    nonstop = False
    row = 10  # after-art,
    for txt in last_callers:
        echo(Ansi(txt).ljust(term.width / 2).center(term.width))
        echo(u'\r\n')
        row += 1
        if ((not nonstop and row > 0 and 0 == (row % (term.height - 3)))
                or (row == len(last_callers) - 1)):
            echo(msg_prompt)
            inp = getch()
            row = 2
            if inp in (u's', u'S', u'q', u'Q', term.KEY_EXIT):
                return
            if inp in (u'v', u'V') or 'sysop' in session.user.groups and (
                    inp in (u'e', u'E')):
                echo(u'\r\n\r\n')
                echo(msg_prompt_handle)
                handle = LineEditor(ini.CFG.getint('nua', 'max_user')).read()
                usrlist = list_users()
                if handle is None or 0 == len(handle.strip()):
                    continue
                handle = handle.strip()
                if handle.lower() in [nick.lower() for nick in list_users()]:
                    nick = ((_nick for _nick in usrlist
                        if _nick.lower() == handle.lower()).next())
                    if find_user(nick):
                        user = get_user(nick)
                        if 'sysop' in session.user.groups and (
                                inp in (u'e', u'E')):
                            gosub('profile', user.handle)
                        else:
                            view_plan(user.handle)
                else:
                    misses = [nick for nick in usrlist.keys()
                              if nick.lower().startswith(handle[:1].lower())]
                    if len(misses) > 0:
                        echo(u'%s:\r\n\r\n%s\r\n' % (msg_partial,
                            Ansi(', '.join(misses)).wrap(term.width)))
                    continue
            if inp in ('n', u'N'):
                nonstop = True
            echo(u'\r\n\r\n')
    pak()
Exemple #40
0
def main(handle=None):
    """ Main procedure. """
    # pylint: disable=R0914,R0912,R0915
    #         Too many local variables
    #         Too many branches
    #         Too many statements
    from x84.bbs import getsession, getterminal, echo, getch
    from x84.bbs import goto, gosub, User, get_user, DBProxy
    import logging
    import time
    session, term = getsession(), getterminal()
    session.activity = 'top'
    logger = logging.getLogger()

    # 0. just a gimmicky example,
    gosub('productive')

    # 1. determine & assign user record,
    if handle in (None, u'', 'anonymous',):
        logger.info('anonymous login by %s.', session.sid)
        session.user = User(u'anonymous')
    else:
        logger.debug('%r logged in.', handle)
        session.user = get_user(handle)
        timeout = session.user.get('timeout', None)
        if timeout is not None:
            echo(u'\r\n\r\nUsing preferred timeout of %ss.\r\n' % (
                timeout,))
            session.send_event('set-timeout', timeout)

    # 2. update call records
    session.user.calls += 1
    session.user.lastcall = time.time()
    if session.user.handle != 'anonymous':
        session.user.save()

    # record into " last caller " record
    key = (session.user.handle)
    lcall = (session.user.lastcall, session.user.calls, session.user.location)
    db = DBProxy('lastcalls')
    db[key] = lcall

    # 3. if no preferred charset run charset.py selector
    if (session.user.get('charset', None) is None
            or session.user.handle == 'anonymous'):
        gosub('charset')
        session.activity = 'top'
    else:
        # load default charset
        session.encoding = session.user.get('charset')
        fun = term.bold_green(' (EXCEllENt!)')
        if session.encoding != 'utf8':
            fun = term.bold_red(u' (bUMMER!)')
        echo(u'\r\n\r\nUsing preferred charset, %s%s.\r\n' % (
            session.encoding, fun))

    # 4. impress with art, prompt for quick login (goto 'main'),
    if session.user.get('expert', False):
        dirty = True
        while True:
            if session.poll_event('refresh'):
                dirty = True
            if dirty:
                session.activity = 'top'
                display_intro()
                echo(u'\r\n QUiCk lOGiN [yn] ?\b\b')
            dirty = False
            inp = getch(1)
            if inp in (u'y', u'Y'):
                goto('main')
            elif inp in (u'n', u'N'):
                break
            elif inp in (u'!',):
                gosub('charset')
                dirty = True
    else:
        ynbar = get_ynbar()
        dirty = True
        while not ynbar.selected:
            if session.poll_event('refresh'):
                dirty = True
            if dirty:
                # redraw yes/no
                session.activity = 'top'
                swp = ynbar.selection
                ynbar = get_ynbar()
                ynbar.selection = swp
                display_intro()
                echo(redraw_quicklogin(ynbar))
            dirty = False
            inp = getch(1)
            if inp in (u'!',):
                gosub('charset')
                dirty = True
            elif inp is not None:
                echo(ynbar.process_keystroke(inp))
                if ynbar.quit:
                    goto('main')
        if ynbar.selection == ynbar.left:
            goto('main')

    # 5. last callers
    gosub('lc')
    session.activity = 'top'

    # 6. check for new public/private msgs,
    gosub('readmsgs', set())
    session.activity = 'top'

    # 7. news
    gosub('news')
    session.activity = 'top'

    # 8. one-liners
    gosub('ol')
    session.activity = 'top'

    # 9. weather
    if session.user.get('location', None):
        gosub('weather')
    session.activity = 'top'

    # 10. automsg
    gosub('automsg')
    
    goto('main')
Exemple #41
0
def main(handle):
    """ Main procedure. """
    # pylint: disable=R0914,R0915,R0911
    #         Too many local variables
    #         Too many statements
    #         Too many return statements
    # by request from midget; a password reset form
    session, term = getsession(), getterminal()
    session.activity = 'resetting password for %s' % (handle, )
    user = get_user(handle)
    logger = logging.getLogger()

    prompt_email = u'\r\n\r\nENtER E-MAil fOR %r: '
    msg_nfound = u'\r\n\r\n%r NOt fOUNd iN USERbASE.'
    msg_cancelled = u'\r\n CANCEllEd.'
    msg_wrong = u'\r\n\r\nWRONG'
    msg_mailsubj = u'passkey for %s' % (ini.CFG.get('system', 'bbsname'))
    msg_mailbody = u'Your passkey is %r'
    msg_mailfrom = ini.CFG.get('system', 'mail_addr')
    msg_sent = u'\r\n\r\nPASSkEY hAS bEEN SENt tO %s.'
    prompt_passkey = u'\r\n\r\nENtER PASSkEY: '
    msg_verified = u'\r\n\r\nYOU hAVE bEEN VERifiEd.'

    echo(term.normal)
    if not handle in list_users():
        echo(term.bold_red(msg_nfound))
        getch()
        return False

    width = ini.CFG.getint('nua', 'max_email')
    email = None
    tries = 0
    while True:
        tries += 1
        if tries > 5:
            logger.warn('%r email retries exceeded', handle)
            return False
        echo(prompt_email % (handle, ))
        try_email = LineEditor(width).read()
        if try_email is None or 0 == len(try_email):
            echo(term.normal + msg_cancelled)
            return False

        # fetch user record email
        email = get_user(handle).email
        if email is None or 0 == len(email):
            logger.warn('%r missing email address, cannot send', handle)
            echo(term.bold_red(msg_wrong))

        elif email.lower() != try_email.lower():
            logger.warn('%r failed email %r (try: %r)', handle, email,
                        try_email)
            echo(term.bold_red(msg_wrong))

        else:
            logger.info('%r requests password reset to %r', handle, email)
            break

    # generate a 'passkey' and e-mail out of band, and request input
    passkey = base64.encodestring(os.urandom(ini.CFG.getint(
        'nua', 'max_pass')))[:ini.CFG.getint('nua', 'max_pass')]
    msg = MIMEText(msg_mailbody % (passkey, ))
    msg['From'] = msg_mailfrom
    msg['To'] = email
    msg['Subject'] = msg_mailsubj
    # pylint: disable=W0703
    #         Catching too general exception Exception
    err = None
    try:
        smtp = smtplib.SMTP(ini.CFG.get('system', 'mail_smtphost'))
        smtp.sendmail(msg_mailfrom, [email], msg.as_string())
        smtp.quit()
    except Exception as err:
        logger.exception(err)
        echo('u\r\n\r\n' + term.bold_red(str(err)) + u'\r\n')
        getch(2)
        return False

    echo(msg_sent % (email, ))
    width = len(passkey)
    email = None
    tries = 0
    while True:
        tries += 1
        if tries > 5:
            logger.warn("passkey retries exceeded for user '%s'", handle)
            return False

        echo(term.normal + u'\r\n\r\n')
        echo(prompt_passkey)
        try_passkey = LineEditor(width).read()
        if try_passkey is None or 0 == len(try_passkey):
            echo(term.normal + msg_cancelled)
            logger.warn("cancelled passkey for user '%s'", handle)
            return False

        if passkey == try_passkey:
            echo(term.bold_green(msg_verified))
            echo(u'\r\n\r\n')
            break
        logger.warn("failed passkey for user '%s': '%s', tried '%s')", handle,
                    passkey, try_passkey)
        echo(term.bold_red(msg_wrong))

    set_password(user)
    user.save()
    return True
Exemple #42
0
def main():
    """ Main procedure. """
    # pylint: disable=R0914,R0911
    #         Too many local variables
    import logging
    from x84.bbs import getsession, getterminal, ini, echo, get_user, goto
    from x84.bbs import find_user, showcp437
    from x84.engine import __url__ as url
    logger = logging.getLogger()
    session, term = getsession(), getterminal()
    session.activity = u'Logging in'
    handle = (session.env.get('USER', '').decode('iso8859-1', 'replace'))
    anon_allowed_msg = u"'%s' login enabled.\r\n" % (
        term.bold_cyan('anonymous',))
    # pylint: disable=E1103
    #         Instance of '_Chainmap' has no 'split' member
    #         (but some types could not be inferred)
    newcmds = ini.CFG.get('matrix', 'newcmds').split()
    apply_msg = u"'%s' to create new account.\r\n" % (
        term.bold_cyan(newcmds[0]),)
    allow_apply = ini.CFG.getboolean('nua', 'allow_apply')
    enable_anonymous = ini.CFG.getboolean('matrix', 'enable_anonymous')
    enable_pwreset = ini.CFG.getboolean('matrix', 'enable_pwreset')
    bbsname = ini.CFG.get('system', 'bbsname')
    artfile = os.path.join(os.path.dirname(__file__), 'art', 'xz-1984.ans')
    topscript = ini.CFG.get('matrix', 'topscript')
    max_tries = 10
    session.flush_event('refresh')
    #uname()
    # display banner
    echo(u''.join((
        term.normal, u'\r\n',
        u'Connected to %s, see %s for source\r\n' % (bbsname, url),)))
    for line in showcp437(artfile):
        echo(line)
    echo(term.normal)
    echo (u''.join((
        u'\r\n\r\n',
        term.bold(u'tERM'), u': ',
        term.cyan_underline(session.env['TERM']),
        u'\r\n',
        term.bold(u'diMENSiONs'), u': ', '%s%s%s' % (
            term.bold_cyan(str(term.width)),
            term.cyan(u'x'),
            term.bold_cyan(str(term.height)),),
        u'\r\n',
        term.bold(u'ENCOdiNG'), u': ',
        term.cyan_underline(session.encoding),
        u'\r\n\r\n',
        anon_allowed_msg if enable_anonymous else u'',
        apply_msg if allow_apply else u'',
    )))
    # http://www.termsys.demon.co.uk/vtansi.htm
    # disable line-wrapping
    echo(unichr(27) + u'[7l')

    # http://www.xfree86.org/4.5.0/ctlseqs.html
    # Save xterm icon and window title on stack.
    echo(unichr(27) + u'[22;0t')

    if handle:
        echo('\r\nHello, %s!' % (handle,))
        match = find_user(handle)
        if match is not None:
            handle = match
        else:
            handle = ''

    # prompt for username & password
    for _num in range(0, max_tries):
        handle = get_username(handle)
        if handle != u'':
            session.activity = u'Logging in'
            user = get_user(handle)
            if try_pass(user):
                goto(topscript, user.handle)
            echo(u'\r\n\r\n')
            if enable_pwreset:
                try_reset(user)
            else:
                logger.info('%r failed password', handle)
    logger.warn('maximum tries exceeded')
    goto('logoff')
Exemple #43
0
def main(handle):
    """ Main procedure. """
    # pylint: disable=R0914,R0915,R0911
    #         Too many local variables
    #         Too many statements
    #         Too many return statements
    # by request from midget; a password reset form
    session, term = getsession(), getterminal()
    session.activity = 'resetting password for %s' % (handle,)
    user = get_user(handle)
    logger = logging.getLogger()

    prompt_email = u'\r\n\r\nENtER E-MAil fOR %r: '
    msg_nfound = u'\r\n\r\n%r NOt fOUNd iN USERbASE.'
    msg_cancelled = u'\r\n CANCEllEd.'
    msg_wrong = u'\r\n\r\nWRONG'
    msg_mailsubj = u'passkey for %s' % (ini.CFG.get('system', 'bbsname'))
    msg_mailbody = u'Your passkey is %r'
    msg_mailfrom = ini.CFG.get('system', 'mail_addr')
    msg_sent = u'\r\n\r\nPASSkEY hAS bEEN SENt tO %s.'
    prompt_passkey = u'\r\n\r\nENtER PASSkEY: '
    msg_verified = u'\r\n\r\nYOU hAVE bEEN VERifiEd.'

    echo(term.normal)
    if not handle in list_users():
        echo(term.bold_red(msg_nfound))
        getch()
        return False

    width = ini.CFG.getint('nua', 'max_email')
    email = None
    tries = 0
    while True:
        tries += 1
        if tries > 5:
            logger.warn('%r email retries exceeded', handle)
            return False
        echo(prompt_email % (handle,))
        try_email = LineEditor(width).read()
        if try_email is None or 0 == len(try_email):
            echo(term.normal + msg_cancelled)
            return False

        # fetch user record email
        email = get_user(handle).email
        if email is None or 0 == len(email):
            logger.warn('%r missing email address, cannot send', handle)
            echo(term.bold_red(msg_wrong))

        elif email.lower() != try_email.lower():
            logger.warn('%r failed email %r (try: %r)', handle,
                        email, try_email)
            echo(term.bold_red(msg_wrong))

        else:
            logger.info('%r requests password reset to %r', handle, email)
            break

    # generate a 'passkey' and e-mail out of band, and request input
    passkey = base64.encodestring(
        os.urandom(ini.CFG.getint('nua', 'max_pass'))
    )[:ini.CFG.getint('nua', 'max_pass')]
    msg = MIMEText(msg_mailbody % (passkey,))
    msg['From'] = msg_mailfrom
    msg['To'] = email
    msg['Subject'] = msg_mailsubj
    # pylint: disable=W0703
    #         Catching too general exception Exception
    err = None
    try:
        smtp = smtplib.SMTP(ini.CFG.get('system', 'mail_smtphost'))
        smtp.sendmail(msg_mailfrom, [email], msg.as_string())
        smtp.quit()
    except Exception as err:
        logger.exception(err)
        echo('u\r\n\r\n' + term.bold_red(str(err)) + u'\r\n')
        getch(2)
        return False

    echo(msg_sent % (email,))
    width = len(passkey)
    email = None
    tries = 0
    while True:
        tries += 1
        if tries > 5:
            logger.warn("passkey retries exceeded for user '%s'", handle)
            return False

        echo(term.normal + u'\r\n\r\n')
        echo(prompt_passkey)
        try_passkey = LineEditor(width).read()
        if try_passkey is None or 0 == len(try_passkey):
            echo(term.normal + msg_cancelled)
            logger.warn("cancelled passkey for user '%s'", handle)
            return False

        if passkey == try_passkey:
            echo(term.bold_green(msg_verified))
            echo(u'\r\n\r\n')
            break
        logger.warn("failed passkey for user '%s': '%s', tried '%s')",
                    handle, passkey, try_passkey)
        echo(term.bold_red(msg_wrong))

    set_password(user)
    user.save()
    return True
Exemple #44
0
def dummy_pager(last_callers):
    """ Dummy pager for displaying last callers """
    # pylint: disable=R0914
    #         Too many local variables
    from x84.bbs import getterminal, getsession, echo, getch, ini
    from x84.bbs import LineEditor, Ansi, list_users, get_user, gosub
    session, term = getsession(), getterminal()
    msg_prompt = (
        u'\r\n%sONtiNUE, %stOP, %sON-StOP %siEW .PlAN%s ?\b\b' % (
        term.bold(u'[c]'),
        term.bold(u'[s]'),
        term.bold(u'n'),
        term.bold(u'[v]'),
        u' [e]dit USR' if (
        'sysop' in session.user.groups) else u'',))
    msg_partial = u'PARtiAl MAtChES'
    msg_prompt_handle = u'ViEW .PlAN ::- ENtER hANdlE: '

    redraw()
    echo(u'\r\n\r\n')
    nonstop = False
    row = 10  # after-art,
    for txt in last_callers:
        echo(Ansi(txt).ljust(term.width / 2).center(term.width))
        echo(u'\r\n')
        row += 1
        if ((not nonstop and row > 0 and 0 == (row % (term.height - 3)))
                or (row == len(last_callers) - 1)):
            echo(msg_prompt)
            inp = getch()
            row = 2
            if inp in (u's', u'S', u'q', u'Q', term.KEY_EXIT):
                return
            if inp in (u'v', u'V') or 'sysop' in session.user.groups and (
                    inp in (u'e', u'E')):
                echo(u'\r\n\r\n')
                echo(msg_prompt_handle)
                handle = LineEditor(ini.CFG.getint('nua', 'max_user')).read()
                usrlist = list_users()
                if handle is None or 0 == len(handle.strip()):
                    continue
                handle = handle.strip()
                if handle.lower() in [nick.lower() for nick in list_users()]:
                    user = get_user((nick for nick in usrlist
                                     if nick.lower() == handle.lower()).next())
                    if 'sysop' in session.user.groups and (
                            inp in (u'e', u'E')):
                        gosub('profile', user.handle)
                    else:
                        view_plan(user.handle)
                else:
                    misses = [nick for nick in usrlist.keys()
                              if nick.lower().startswith(handle[:1].lower())]
                    if len(misses) > 0:
                        echo(u'%s:\r\n\r\n%s\r\n' % (msg_partial,
                            Ansi(', '.join(misses)).wrap(term.width)))
                    continue
            if inp in ('n', u'N'):
                nonstop = True
            echo(u'\r\n\r\n')
    pak()
Exemple #45
0
def main(handle=None):
    """ Main procedure. """
    dirty = -1
    session, term = getsession(), getterminal()
    tgt_user = get_user(handle) if handle else session.user
    legal_input_characters = string.letters + u'<>'

    # re-display entire screen on loop,
    while True:

        # full-screen refresh on -1; otherwise only the fields (such as when an
        # edit has occurred).  dirty = -1 is set on screen resize, for example.
        if dirty == -1:
            # display banner, discover (y,x) point after,
            point_margin = show_banner(term)

            # forward-calculate the prompt (y,x) point
            point_prompt = Point(y=point_margin.y + 15, x=point_margin.x)

        # get all field values and locations,
        fields = get_display_fields(tgt_user, point=point_margin)

        # display all fields and prompt
        echo(display_options(term, fields))
        echo(display_prompt(term, session, point=point_prompt))

        dirty = 0

        # blocking loop until screen refresh or keystroke
        event = None
        while event is None:
            # This dual input/refresh trick only works here, receiving
            # raw (undecoded) keyboard data as 'inp' because we don't
            # require the use of any application keys or multi-byte
            # sequences, only alphabetic characters.
            event, data = session.read_events(('input', 'refresh'))
            if event == 'refresh':
                dirty = -1
                break

            inp = data
            if inp in legal_input_characters:
                # display command input
                echo(inp.decode('ascii'))

            if inp == u'q':
                # [q]uit
                echo(u'\r\n')
                return
            elif inp == u'\x0c':
                # [^L] refresh
                dirty = -1
                break
            elif inp == u'f' and session.user.is_sysop:
                tgt_user = locate_user(term, point_prompt) or tgt_user
                break
            elif inp == u'd':
                # yes, you can delete yourself !!
                if delete_user(term, tgt_user, point_prompt):
                    if tgt_user == session.user:
                        # but if you delete yourself,
                        # you must logoff.
                        goto('logoff')

                    # otherwise, move to next user
                    tgt_user = get_next_user(tgt_user)
                break
            elif inp == u'<' and session.user.is_sysop:
                tgt_user = get_prev_user(tgt_user)
                break
            elif inp == u'>' and session.user.is_sysop:
                tgt_user = get_next_user(tgt_user)
                break
            elif inp in string.letters:
                if do_command(
                        term, session, inp, fields, tgt_user, point_prompt):
                    # when returning True, perform full-screen refresh,
                    break
                else:
                    # otherwise, clean prompt field
                    time.sleep(0.2)
                    echo(u'\b \b')
            elif inp in legal_input_characters:
                # though legal, not authorized: clean prompt field
                time.sleep(0.2)
                echo(u'\b \b')
            event = None
        dirty = dirty or 1
Exemple #46
0
def get_prev_user(tgt_user):
    """ Get previous user in sorted order. """
    handles = sorted(list_users())
    idx = max(handles.index(tgt_user.handle) - 1, 0)
    return get_user(handles[idx])
Exemple #47
0
def main():
    """ Main procedure. """
    # pylint: disable=R0914,R0911
    #         Too many local variables
    import logging
    from x84.bbs import getsession, getterminal, ini, echo, get_user, goto
    from x84.bbs import find_user, showcp437
    from x84.engine import __url__ as url
    import random, time, glob
    logger = logging.getLogger()
    session, term = getsession(), getterminal()
    session.activity = u'Logging in'
    handle = (session.env.get('USER', '').decode('iso8859-1', 'replace'))
    anon_allowed_msg = u"'%s' login enabled.\r\n" % (term.bold_cyan(
        'anonymous', ))
    # pylint: disable=E1103
    #         Instance of '_Chainmap' has no 'split' member
    #         (but some types could not be inferred)
    newcmds = ini.CFG.get('matrix', 'newcmds').split()
    apply_msg = u"'%s' to create new account.\r\n" % (term.bold_cyan(
        newcmds[0]), )
    allow_apply = ini.CFG.getboolean('nua', 'allow_apply')
    enable_anonymous = ini.CFG.getboolean('matrix', 'enable_anonymous')
    enable_pwreset = ini.CFG.getboolean('matrix', 'enable_pwreset')
    bbsname = ini.CFG.get('system', 'bbsname')
    headers = glob.glob(
        os.path.join(os.path.dirname(__file__), "art", "YOSBBS*.ANS"))
    bannername = "YOSBBS" + str(random.randrange(
        1, len(headers))).zfill(2) + ".ANS"
    artfile = os.path.join(os.path.dirname(__file__), 'art', bannername)
    topscript = ini.CFG.get('matrix', 'topscript')
    max_tries = 10
    session.flush_event('refresh')
    #uname()
    # display banner
    echo(u''.join((
        term.normal,
        u'\r\n',
        u'Connected to %s, see %s for source\r\n' % (bbsname, url),
    )))
    time.sleep(1)
    echo(term.clear())
    for line in showcp437(artfile):
        echo(line)
    echo(term.normal)
    echo(term.move(term.height - 2, 0))
    echo(u''.join((
        term.bold(u'tERM'),
        u': ',
        term.cyan_underline(session.env['TERM']),
        term.bold(u' diMENSiONs'),
        u': ',
        '%s%s%s' % (
            term.bold_cyan(str(term.width)),
            term.cyan(u'x'),
            term.bold_cyan(str(term.height)),
        ),
        term.bold(u' ENCOdiNG'),
        u': ',
        term.cyan_underline(session.encoding),
        anon_allowed_msg if enable_anonymous else u'',
        u' ',
        apply_msg if allow_apply else u'',
    )))
    # http://www.termsys.demon.co.uk/vtansi.htm
    # disable line-wrapping
    echo(unichr(27) + u'[7l')

    # http://www.xfree86.org/4.5.0/ctlseqs.html
    # Save xterm icon and window title on stack.
    echo(unichr(27) + u'[22;0t')

    if handle:
        echo('\r\nHello, %s!' % (handle, ))
        match = find_user(handle)
        if match is not None:
            handle = match
        else:
            handle = ''

    # prompt for username & password
    for _num in range(0, max_tries):
        handle = get_username(handle)
        if handle != u'':
            session.activity = u'Logging in'
            user = get_user(handle)
            if try_pass(user):
                goto(topscript, user.handle)
            echo(u'\r\n\r\n')
            if enable_pwreset:
                try_reset(user)
            else:
                logger.info('%r failed password', handle)
    logger.warn('maximum tries exceeded')
    goto('logoff')
Exemple #48
0
def main(handle=None):
    """ Main procedure. """
    # pylint: disable=R0914,R0912,R0915
    #         Too many local variables
    #         Too many branches
    #         Too many statements
    from x84.bbs import getsession, getterminal, echo, getch
    from x84.bbs import goto, gosub, User, get_user, DBProxy
    import logging
    import time
    session, term = getsession(), getterminal()
    session.activity = 'top'
    logger = logging.getLogger()

    # 0. just a gimmicky example,
#    gosub('productive')

    # 1. determine & assign user record,
    if handle in (None, u'', 'anonymous',):
        logger.info('anonymous login by %s.', session.sid)
        session.user = User(u'anonymous')
    else:
        logger.debug('%r logged in.', handle)
        session.user = get_user(handle)
        timeout = session.user.get('timeout', None)
        if timeout is not None:
            echo(u'\r\n\r\nUsing preferred timeout of %ss.\r\n' % (
                timeout,))
            session.send_event('set-timeout', timeout)

    # 2. update call records
    session.user.calls += 1
    session.user.lastcall = time.time()
    if session.user.handle != 'anonymous':
        session.user.save()

    # record into " last caller " record
    key = (session.user.handle)
    lcall = (session.user.lastcall, session.user.calls, session.user.location)
    db = DBProxy('lastcalls')
    db[key] = lcall

    # 3. if no preferred charset run charset.py selector
    if (session.user.get('charset', None) is None
            or session.user.handle == 'anonymous'):
        gosub('charset')
        session.activity = 'top'
    else:
        # load default charset
        session.encoding = session.user.get('charset')
        fun = term.bold_green(' (EXCEllENt!)')
        if session.encoding != 'utf8':
            fun = term.bold_red(u' (bUMMER!)')
        echo(u'\r\n\r\nUsing preferred charset, %s%s.\r\n' % (
            session.encoding, fun))

    echo(term.clear())
    # 4. impress with art, prompt for quick login (goto 'main'),
    if session.user.get('expert', False):
        dirty = True
        while True:
            if session.poll_event('refresh'):
                dirty = True
            if dirty:
                session.activity = 'top'
                display_intro()
                echo(u'\r\n QUiCk lOGiN [yn] ?\b\b')
            dirty = False
            inp = getch(1)
            if inp in (u'y', u'Y'):
                goto('main')
            elif inp in (u'n', u'N'):
                break
            elif inp in (u'!',):
                gosub('charset')
                dirty = True
    else:
        ynbar = get_ynbar()
        dirty = True
        while not ynbar.selected:
            if session.poll_event('refresh'):
                dirty = True
            if dirty:
                # redraw yes/no
                session.activity = 'top'
                swp = ynbar.selection
                ynbar = get_ynbar()
                ynbar.selection = swp
                display_intro()
                echo(redraw_quicklogin(ynbar))
            dirty = False
            inp = getch(1)
            if inp in (u'!',):
                gosub('charset')
                dirty = True
            elif inp is not None:
                echo(ynbar.process_keystroke(inp))
                if ynbar.quit:
                    goto('main')
        if ynbar.selection == ynbar.left:
            goto('main')

    # 5. last callers
    gosub('lc')
    session.activity = 'top'

    # 6. check for new public/private msgs,
#   gosub('readmsgs', set())
#   session.activity = 'top'

    # 7. news
    gosub('news')
    session.activity = 'top'

    # 8. one-liners
    gosub('ol')
    session.activity = 'top'

    # 9. weather
#   if session.user.get('location', None):
#       gosub('weather')

    goto('main')