예제 #1
0
def ban_check(numip, name, subject, comment):
    '''This function raises an exception if the IP address is banned, or
    the post contains a forbidden (non-spam) string. It otherwise returns
    nothing.'''

    session = model.Session()
    table = model.admin

    # IP Banned?
    sql = table.select().where(and_(table.c.type == 'ipban',
                                    table.c.ival1.op('&')(table.c.ival2) \
                                        == table.c.ival2.op('&')(numip)))
    ip_row = session.execute(sql).fetchone()

    if ip_row:
        raise WakaError('Address %s banned. Reason: %s' % \
            (misc.dec_to_dot(numip), ip_row.comment))

    # To determine possible string bans, first normalize input to lowercase.
    comment = comment.lower()
    subject = subject.lower()
    name = name.lower()

    sql = select([table.c.sval1], table.c.type == 'wordban')
    query = session.execute(sql)

    for row in query:
        bad_string = row.sval1.lower()
        if comment.count(bad_string) or subject.count(bad_string) or \
                name.count(bad_string):
            raise WakaError(strings.STRREF)
예제 #2
0
def application(environ, start_response):
    '''Main routing application'''

    local.environ = environ
    request = werkzeug.BaseRequest(environ)

    task = request.values.get('task', request.values.get('action', ''))
    boardname = request.values.get('board', '')


    environ['waka.task'] = task
    environ['waka.boardname'] = boardname
    # Indicate "pop-up window" UI style.
    environ['waka.fromwindow'] = False
    environ['waka.rootpath'] = os.path.join('/', config.BOARD_DIR, '')

    if not task and not boardname:
        environ['waka.board'] = NoBoard()
        return app.check_setup(environ, start_response)

    environ['waka.board'] = NoBoard()
    try:
        if boardname:
            environ['waka.board'] = Board(boardname)
        elif task not in ('entersetup', 'setup', 'loginpanel'):
            raise WakaError("No board parameter set")
        elif task == 'loginpanel':
            raise WakaError("No board parameter set. "
                "If you haven't created boards yet, do it now.")
    except WakaError, e:
        return app.fffffff(environ, start_response, e)
예제 #3
0
def add_staff(username, pt_password, account, reign):
    if not username:
        raise WakaError('A username is necessary.')
    if not pt_password:
        raise WakaError('A password is necessary.')
    if len(pt_password) < 8:
        raise WakaError('Passwords should be eight characters minimum.')
    if len(reign) == 0 and account == MODERATOR:
        raise WakaError('Board reign not specified for moderator account.')

    # Check whether the user exists already.
    try:
        StaffMember.get(username)
    except LoginError:
        # User not found. Good.
        pass
    else:
        raise WakaError('Username exists.')

    session = model.Session()
    table = model.account
    password = misc.hide_critical_data(pt_password, config.SECRET)
    reign_str = ','.join(reign)

    sql = table.insert().values(username=username,
                                password=password,
                                account=account,
                                reign=reign_str,
                                disabled=0)
    session.execute(sql)
예제 #4
0
def add_staff_proxy(admin, mpass, usertocreate, passtocreate, account, reign):
    user = staff.check_password(admin)

    if user.account != staff.ADMIN:
        raise WakaError(strings.INSUFFICIENTPRIVILEGES)

    if account == staff.ADMIN and mpass != config.ADMIN_PASS:
        raise WakaError('Incorrect management password.')

    staff.add_staff(usertocreate, passtocreate, account, reign)

    board = local.environ['waka.board']
    return make_http_forward(
        misc.make_script_url(task='staff', board=board.name),
        config.ALTERNATE_REDIRECT)
예제 #5
0
def do_first_time_setup(admin, username, password):
    # Checks.
    if admin != staff.crypt_pass(config.ADMIN_PASS,
                                 local.environ['REMOTE_ADDR']):
        return make_first_time_setup_gateway()
    if not username:
        raise WakaError('Missing username.')
    if not password:
        raise WakaError('Missing password.')

    staff.add_staff(username, password, staff.ADMIN, [])

    board = local.environ['waka.board']
    return make_http_forward(
        misc.make_script_url(task='loginpanel', board=board.name),
        config.ALTERNATE_REDIRECT)
예제 #6
0
def del_staff_proxy(admin, mpass, username):
    user = staff.check_password(admin)

    if user.account != staff.ADMIN:
        raise WakaError(strings.INSUFFICIENTPRIVILEGES)

    user_to_kill = staff.StaffMember.get(username)
    if user_to_kill.account == staff.ADMIN and mpass != config.ADMIN_PASS:
        raise WakaError('Incorrect management password.')

    staff.del_staff(username)

    board = local.environ['waka.board']
    return make_http_forward(
        misc.make_script_url(task='staff', board=board.name),
        config.ALTERNATE_REDIRECT)
예제 #7
0
def remove_admin_entry(task_data, num, override_log=False, no_redirect=False):
    session = model.Session()
    table = model.admin
    sql = table.select().where(table.c.num == num)
    row = session.execute(sql).fetchone()

    if not row:
        raise WakaError('Entry not found. Deleted?')

    ival1 = row['ival1']
    ip = misc.dec_to_dot(ival1) if ival1 else ''
    string_val = row['sval1']

    if row['total']:
        remove_htaccess_entry(ip)

    sql = table.delete().where(table.c.num == num)
    session.execute(sql)
    task_data.action = row['type'] + '_remove'
    if string_val:
        task_data.contents.append(row['sval1'])
    else:
        task_data.contents.append(ip + ' (' + misc.dec_to_dot(row['ival2']) \
                                  + ')')

    board = local.environ['waka.board']
    forward_url = misc.make_script_url(task='bans', board=board.name)

    return util.make_http_forward(forward_url, config.ALTERNATE_REDIRECT)
예제 #8
0
def task_post(environ, start_response):
    request = environ['werkzeug.request']
    board = environ['waka.board']

    if request.method != 'POST':
        raise WakaError("POST only accepted")

    admin = get_cookie_from_request(request, 'wakaadmin')

    wakapost = WakaPost.from_request(request)

    if wakapost.admin_post:
        return StaffAction(admin, 'admin_post', wakapost=wakapost,
                           board=board).execute()

    # not admin, so let's check for hcaptcha

    style_cookie = get_cookie_from_request(
        request, board.options.get('STYLE_COOKIE', 'wakastyle'))
    hcaptcha = request.values.get('hcaptcha', '').lower()
    is_nokosage = wakapost.email.lower() in ['noko', 'sage']

    import config
    if (config.HCAPTCHA and hcaptcha != config.HCAPTCHA_ANSWER
            and not (config.HCAPTCHA_COOKIE_BYPASS and style_cookie != '')
            and not (config.HCAPTCHA_NOKOSAGE_BYPASS and is_nokosage)):

        return Template(
            'hcaptcha_failed',
            question=config.HCAPTCHA_QUESTION,
            answer=config.HCAPTCHA_ANSWER,
        )

    return board.post_stuff(wakapost)
예제 #9
0
def edit_admin_entry(task_data,
                     num,
                     comment='',
                     ival1=None,
                     ival2='255.255.255.255',
                     sval1='',
                     total=False,
                     sec=None,
                     min=None,
                     hour=None,
                     day=None,
                     month=None,
                     year=None,
                     noexpire=False):
    session = model.Session()
    table = model.admin
    sql = table.select().where(table.c.num == num)
    row = session.execute(sql).fetchone()

    if not row:
        raise WakaError('Entry was not created or was removed.')

    task_data.action = row.type + '_edit'

    if row.type in ('ipban', 'whitelist'):
        if not noexpire:
            try:
                expiration = datetime(int(year), int(month), int(day),
                                      int(hour), int(min), int(sec))
            except:
                raise WakaError('Invalid date.')
            expiration = timegm(expiration.utctimetuple())
        else:
            expiration = 0
        ival1 = misc.dot_to_dec(ival1)
        ival2 = misc.dot_to_dec(ival2)
        task_data.contents.append(ival1 + ' (' + ival2 + ')')
    else:
        expiration = 0
        task_data.contents.append(sval1)

    sql = table.update().where(table.c.num == num)\
               .values(comment=comment, ival1=ival1, ival2=ival2, sval1=sval1,
                       total=total, expiration=expiration)
    row = session.execute(sql)

    return Template('edit_successful')
예제 #10
0
    def password(self, new):
        if len(new) < 8:
            raise WakaError('Passwords should be at least eight characters!')

        new = misc.hide_critical_data(new, config.SECRET)

        self._update_db(password=new)
        self._password = new
예제 #11
0
def global_cache_rebuild_proxy(task_data):
    if task_data.user.account != staff.ADMIN:
        raise WakaError(strings.INSUFFICIENTPRIVILEGES)
    Popen([sys.executable, sys.argv[0], 'rebuild_global_cache'],
          env=util.proxy_environ())
    referer = local.environ['HTTP_REFERER']
    task_data.contents.append(referer)
    return util.make_http_forward(referer, config.ALTERNATE_REDIRECT)
예제 #12
0
    def make_sql_interface_panel(self, sql='', nuke=''):
        if self.user.account != staff.ADMIN:
            raise WakaError(strings.INSUFFICIENTPRIVILEGES)

        results = []

        if sql or nuke:
            if nuke != local.environ['waka.board'].options['NUKE_PASS']:
                raise WakaError(strings.WRONGPASS)

            session = model.Session()
            if sql:
                for sql in sql.split('\r\n'):
                    # Execute teh string.
                    try:
                        results.append('>>> ' + sql)
                        row = session.execute(sql)
                    except Exception as errstr:
                        results.append('ERROR: %s' % (errstr))
                    else:
                        try:
                            results.append(str(row.fetchall()))
                        except:
                            results.append('OK')
            else:
                # Remove board table contents and board list entry.
                try:
                    board = local.environ['waka.board']
                    board.table.drop(bind=model.engine, checkfirst=True)
                    del model._boards[board.name]
                    model.common.delete().where(model.common.c.board \
                                                == board.name)
                except Exception as errstr:
                    results.append('ERROR %s' % (errstr))
                else:
                    results.append('Comment table dropped. You should '
                                   'delete/move the board folder now.')
        else:
            results.append('Leave textarea blank to delete the board.\n\n'
                           '(It is recommended that you disable site access '
                           'while entering SQL or deleting boards.)')

        Template.__init__(self,
                          'sql_interface_template',
                          results='<br />'.join(results))
예제 #13
0
def make_first_time_setup_page(admin):
    if not hasattr(config, 'ADMIN_PASS'):
        raise WakaError("ADMIN_PASS not set in config")

    if admin == config.ADMIN_PASS:
        admin = staff.crypt_pass(admin, local.environ['REMOTE_ADDR'])
        return Template('account_setup', admin=admin)
    else:
        return make_first_time_setup_gateway()
예제 #14
0
    def make_admin_report_panel(self, sortby='date', order='desc'):
        sortby_type = sortby
        sortby_dir = order

        session = model.Session()
        table = model.report
        sql = table.select()

        # Enforce limited moderation reign.
        if self.user.account == staff.MODERATOR:
            sql = sql.where(table.c.board.in_(self.user.reign))

        # Determine order.
        if sortby_type in ('board', 'postnum', 'date'):
            try:
                column = getattr(table.c, sortby_type)
            except AttributeError:
                raise WakaError('Sort-by column is absent from table.')
            sort = column.desc
            if sortby_dir == 'asc':
                sort = column.asc
            sql = sql.order_by(sort(), table.c.date.desc())
        else:
            sql = sql.order_by(table.c.date.desc())

        # Paginate.
        res = model.Page(sql, self.page, self.perpage)

        # Hidden input fields.
        inputs = [{
            'name': 'task',
            'value': 'reports'
        }, {
            'name': 'order',
            'value': sortby_dir
        }, {
            'name': 'sortby',
            'value': sortby_type
        }]

        rooturl = misc.make_script_url(task='reports',
                                       sortby=sortby_type,
                                       order=sortby_dir,
                                       _amp=True)

        Template.__init__(self,
                          'report_panel_template',
                          reports=res.rows,
                          sortby=sortby_type,
                          order=sortby_dir,
                          number_of_pages=res.total_pages,
                          rowcount=res.total_entries,
                          inputs=inputs,
                          rooturl=rooturl)
예제 #15
0
def global_cache_rebuild_proxy(task_data):
    if task_data.user.account != staff.ADMIN:
        raise WakaError(strings.INUSUFFICENTPRIVLEDGES)
    Popen([
        sys.executable, sys.argv[0], 'rebuild_global_cache',
        local.environ['DOCUMENT_ROOT'], local.environ['SCRIPT_NAME'],
        local.environ['SERVER_NAME']
    ])
    referer = local.environ['HTTP_REFERER']
    task_data.contents.append(referer)
    return util.make_http_forward(referer, config.ALTERNATE_REDIRECT)
예제 #16
0
def update_spam_file(task_data, spam):
    if task_data.user.account == staff.MODERATOR:
        raise WakaError(strings.INUSUFFICENTPRIVLEDGES)

    # Dump all contents to first spam file.
    with open(config.SPAM_FILES[0], 'w') as f:
        f.write(spam)

    board = local.environ['waka.board']
    forward_url = misc.make_script_url(task='spam', board=board.name)

    return util.make_http_forward(forward_url, config.ALTERNATE_REDIRECT)
예제 #17
0
def get_action_name(action_to_view, debug=0):
    try:
        name = ACTION_TRANSLATION[action_to_view]['name']
        content = ACTION_TRANSLATION[action_to_view]['content']
    except KeyError:
        raise WakaError('Missing action key or unknown action key.')

    if not debug:
        return name
    elif debug == 1:
        return (name, content)
    else:
        return content
예제 #18
0
def edit_staff_proxy(admin,
                     mpass,
                     username,
                     newpassword=None,
                     newclass=None,
                     originalpassword='',
                     reign=None,
                     disable=None):

    user = staff.check_password(admin)

    if user.username == username:
        if misc.hide_critical_data(originalpassword, config.SECRET) \
           != user.password:
            raise WakaError(strings.WRONGPASS)
        newclass = None
        reign = None
    elif user.account == staff.ADMIN:
        edited_user = staff.StaffMember.get(username)
        if edited_user.account == staff.ADMIN and mpass != config.ADMIN_PASS:
            raise WakaError('Incorrect management password.')
    else:
        raise WakaError(strings.INSUFFICIENTPRIVILEGES)

    staff.edit_staff(username,
                     clear_pass=newpassword,
                     new_class=newclass,
                     reign=reign,
                     disable=disable)

    board = local.environ['waka.board']

    forward_task = 'admin' if user.username == username else 'staff'

    return make_http_forward(
        misc.make_script_url(task=forward_task, board=board.name),
        config.ALTERNATE_REDIRECT)
예제 #19
0
def task_editpost(environ, start_response):
    request = environ['werkzeug.request']
    board = environ['waka.board']

    if request.method != 'POST':
        raise WakaError("POST only accepted")

    admin = get_cookie_from_request(request, 'wakaadmin')

    wakapost = WakaPost.from_request(request)

    if wakapost.admin_post:
        return StaffAction(admin, 'admin_edit', wakapost=wakapost,
                           board=board).execute()
    else:
        return board.edit_stuff(wakapost)
예제 #20
0
def add_proxy_entry(task_data, type, ip, timestamp):
    session = model.Session()
    table = model.proxy

    if not misc.validate_ip(ip):
        raise WakaError(strings.BADIP)

    age = config.PROXY_WHITE_AGE if type == 'white' else config.PROXY_BLACK_AGE
    timestamp = int(timestamp or '0') - age + time.time()
    date = misc.make_date(time.time(), style=config.DATE_STYLE)

    query = table.delete().where(table.c.ip == ip)
    session.execute(query)

    query = table.insert().values(type=type,
                                  ip=ip,
                                  timestamp=timestamp,
                                  date=date)
    session.execute(query)

    board = local.environ['waka.board']
    forward_url = misc.make_script_url(task='proxy', board=board.name)

    return util.make_http_forward(forward_url, config.ALTERNATE_REDIRECT)
예제 #21
0
    def make_admin_activity_panel(self,
                                  view='',
                                  user_to_view=None,
                                  action_to_view=None,
                                  ip_to_view=None,
                                  post_to_view=None,
                                  sortby_name='date',
                                  sortby_dir='desc'):

        board = self.board

        template_view = 'staff_activity_unfiltered'
        action_name = action_content = ''

        table = model.activity
        account_table = model.account

        dual_table_select = [
            account_table.c.username, account_table.c.account,
            account_table.c.disabled, table.c.action, table.c.info,
            table.c.date, table.c.ip
        ]
        sql = select(dual_table_select,
                     from_obj=[
                         table.join(
                             account_table,
                             table.c.username == model.account.c.username)
                     ])

        rooturl_args = dict(task='stafflog',
                            board=board.name,
                            view=view,
                            sortby=sortby_name,
                            order=sortby_dir,
                            _amp=True)

        if view == 'user':
            if not user_to_view:
                raise WakaError('Please select a user to view.')
            template_view = 'staff_activity_by_user'
            sql = sql.where(table.c.username == user_to_view)
            rooturl_args['usertoview'] = user_to_view

        elif view == 'action':
            if not action_to_view:
                raise WakaError('Please select an action to view.')
            template_view = 'staff_activity_by_actions'
            (action_name, action_content) \
                = staff_tasks.get_action_name(action_to_view, 1)
            sql = sql.where(table.c.action == action_to_view)
            rooturl_args['actiontoview'] = action_to_view

        elif view == 'ip':
            if not ip_to_view:
                raise WakaError('Please specify an IP address to view.')
            template_view = 'staff_activity_by_ip_address'
            sql = sql.where(table.c.info.like('%' + ip_to_view + '%'))
            rooturl_args['iptoview'] = ip_to_view

        elif view == 'post':
            if not post_to_view:
                raise WakaError('Post key missing.')
            template_view = 'staff_activity_by_post'
            sql = sql.where(table.c.info.like('%' + post_to_view + '%'))
            rooturl_args['posttoview'] = post_to_view

        rooturl = misc.make_script_url(**rooturl_args)

        # Acquire staff info.
        session = model.Session()
        staff_get = model.account.select()
        staff = session.execute(staff_get).fetchall()

        # Establish list of hidden inputs.
        inputs = [{
            'name': 'actiontoview',
            'value': action_to_view
        }, {
            'name': 'task',
            'value': 'stafflog'
        }, {
            'name': 'posttoview',
            'value': post_to_view
        }, {
            'name': 'usertoview',
            'value': user_to_view
        }, {
            'name': 'iptoview',
            'value': ip_to_view
        }, {
            'name': 'order',
            'value': sortby_dir
        }, {
            'name': 'sortby',
            'value': sortby_name
        }, {
            'name': 'view',
            'value': view
        }]

        if self.board:
            inputs.append({'name': 'board', 'value': self.board.name})

        # Apply sorting.
        if sortby_name and hasattr(table.c, sortby_name):
            order_col = getattr(table.c, sortby_name)
            if sortby_dir.lower() == 'asc':
                sort_spec = order_col.asc()
            else:
                sort_spec = order_col.desc()
            sql = sql.order_by(sort_spec)

        res = model.Page(sql, self.page, self.perpage)

        Template.__init__(self,
                          template_view,
                          user_to_view=user_to_view,
                          entries=res.rows,
                          staff=staff,
                          rowcount=res.total_entries,
                          numberofpages=res.total_pages,
                          view=view,
                          order=sortby_dir,
                          action_name=action_name,
                          content_name=action_content,
                          sortby=sortby_name,
                          number_of_pages=res.total_pages,
                          rooturl=rooturl,
                          inputs=inputs)
예제 #22
0
def move_thread(task_data, parent, src_brd_obj, dest_brd_obj):
    if not parent:
        raise WakaError('No thread specified.')
    if src_brd_obj.name == dest_brd_obj.name:
        raise WakaError('Source and destination boards match.')

    # Check administrative access rights to both boards.
    user = task_data.user
    src_brd_obj.check_access(user)
    dest_brd_obj.check_access(user)

    session = model.Session()
    src_table = src_brd_obj.table
    dest_table = dest_brd_obj.table

    sql = select([src_table.c.parent], src_table.c.num == parent)
    row = session.execute(sql).fetchone()

    if not row:
        raise WakaError('Thread not found.')
    elif row[0]:
        # Automatically correct if reply instead of thread was given.
        parent = row[0]

    sql = src_table.select().where(or_(src_table.c.num == parent,
                                       src_table.c.parent == parent))\
                            .order_by(src_table.c.num.asc())
    thread = [dict(x.items()) for x in session.execute(sql).fetchall()]

    # Indicate OP post number after insertion.
    new_parent = 0

    # List of images/thumbs to move around.
    image_move = []
    thumb_move = []

    lasthit = time.time()

    # DB operations
    for post in thread:
        # Grab post contents as dictionary of updates. Remove primary key.
        del post['num']

        post['lasthit'] = lasthit
        image = post['image']
        thumbnail = post['thumbnail']

        if image:
            image_move.append(image)
        if re.match(src_brd_obj.options['THUMB_DIR'], thumbnail):
            thumb_move.append(thumbnail)

        # Update post reference links.
        if new_parent:
            post['parent'] = new_parent

            new_comment = re.sub(r'a href="(.*?)'
                + os.path.join(src_brd_obj.path,
                               src_brd_obj.options['RES_DIR'],
                               '%d%s' % (int(parent)), config.PAGE_EXT),
                r'a href="\1' + os.path.join(\
                               dest_brd_obj.path,
                               dest_brd_obj.options['RES_DIR'],
                               '%d%s' % (int((new_parent), config.PAGE_EXT))),
                post['comment'])

            post['comment'] = new_comment

        sql = dest_table.insert().values(**post)
        result = session.execute(sql)

        if not new_parent:
            new_parent = result.inserted_primary_key[0]

    # Nested associate for moving files in bulk.
    def rename_files(filename_list, dir_type):
        for filename in filename_list:
            src_filename = os.path.join(src_brd_obj.path, filename)
            dest_filename = re.sub('^/?' + src_brd_obj.options[dir_type],
                                   dest_brd_obj.options[dir_type], filename)
            dest_filename = os.path.join(dest_brd_obj.path, dest_filename)
            os.rename(src_filename, dest_filename)

    # File transfer operations.
    rename_files(image_move, 'IMG_DIR')
    rename_files(thumb_move, 'THUMB_DIR')

    dest_brd_obj.build_cache()
    dest_brd_obj.build_thread_cache(new_parent)

    src_brd_obj.delete_stuff([parent], '', False, False, caller='internal')

    forward_url = misc.make_script_url(task='mpanel',
                                       board=dest_brd_obj.name,
                                       page=('t%s' % new_parent))

    # Log.
    task_data.contents.append('/%s/%d to /%s/%d' \
                              % (src_brd_obj.name, int(parent),
                                 dest_brd_obj.name, int(new_parent)))

    return util.make_http_forward(forward_url)
예제 #23
0
 def ret_func(*args, **kwargs):
     self = args[0]
     if self.user.account != staff.ADMIN:
         raise WakaError(strings.INUSUFFICENTPRIVLEDGES)
     f(*args, **kwargs)
예제 #24
0
 def account(self, new):
     if new in CLASSES:
         self._update_db(account=new)
         self._class = new
     else:
         raise WakaError('Invalid class name %s' % new)
예제 #25
0
def add_admin_entry(task_data,
                    option,
                    comment,
                    ip='',
                    mask='255.255.255.255',
                    sval1='',
                    total='',
                    expiration=0,
                    caller=''):
    session = model.Session()
    table = model.admin

    ival1 = ival2 = 0

    if not comment:
        raise WakaError(strings.COMMENT_A_MUST)
    if option in ('ipban', 'whitelist'):
        if not ip:
            raise WakaError('IP address required.')
        if not mask:
            mask = '255.255.255.255'
        # Convert to decimal.
        (ival1, ival2) = (misc.dot_to_dec(ip), misc.dot_to_dec(mask))
        sql = table.select().where(table.c.type == option)
        query = session.execute(sql)

        for row in query:
            try:
                if int(row.ival1) & int(row.ival2) == ival1 & ival2:
                    raise WakaError('IP address and mask match ban #%d.' % \
                                    (row.num))
            except ValueError:
                raise WakaError("Entry #%s on ban table is inconsistent. "
                                "This shouldn't happen." % row.num)
        # Add info to task data.
        content = ip + (' (' + mask + ')' if mask else '')

        if total == 'yes':
            add_htaccess_entry(ip)
            content += ' (no browse)'

        content += ' "' + comment + '"'
        task_data.contents.append(content)
    else:
        if not sval1:
            raise WakaError(strings.STRINGFIELDMISSING)
        sql = table.select().where(
            and_(table.c.sval1 == sval1, table.c.type == option))
        row = session.execute(sql).fetchone()

        if row:
            raise WakaError('Duplicate String in ban #%d.' % (row.num))
        # Add ifno to task data.
        task_data.contents.append(sval1)

    comment = str_format.clean_string(\
        str_format.decode_string(comment, config.CHARSET))
    expiration = int(expiration) if expiration else 0
    if expiration:
        expiration = expiration + time.time()

    sql = table.insert().values(type=option,
                                comment=comment,
                                ival1=int(ival1),
                                ival2=int(ival2),
                                sval1=sval1,
                                total=total,
                                expiration=expiration)
    result = session.execute(sql)

    task_data.admin_id = result.inserted_primary_key[0]

    # Add specific action name to task data.
    task_data.action = option

    board = local.environ['waka.board']
    forward_url = misc.make_script_url(task='bans', board=board.name)

    if caller == 'window':
        return Template('edit_successful')
    return util.make_http_forward(forward_url, config.ALTERNATE_REDIRECT)
예제 #26
0
 def check_access(self, board_name):
     if self.account == MODERATOR and board_name not in self.reign:
         raise WakaError('Access to this board (%s) denied.' % board_name)
예제 #27
0
    def make_admin_trash_panel(self):
        board = self.board
        table = model.backup
        session = model.Session()
        template_kwargs = {}

        # List of current threads *and* orphaned posts.
        threads = []

        if str(self.page).startswith('t'):
            self.page = self.page[1:]
            sql = table.select().where(and_(or_(table.c.postnum == self.page,
                                                table.c.parent == self.page),
                                            table.c.board_name == board.name))\
                                .order_by(table.c.timestampofarchival.desc(),
                                          table.c.postnum.asc())
            thread = [dict(x.items()) for x in session.execute(sql).fetchall()]

            if not thread:
                raise WakaError('Thread not found.')

            threads = [{'posts': thread}]

            template_kwargs = {
                'postform':
                board.options['ALLOW_TEXTONLY']
                or board.options['ALLOW_IMAGES'],
                'image_inp':
                board.options['ALLOW_IMAGES'],
                'textonly_inp':
                0,
                'threads':
                threads,
                'thread':
                self.page,
                'parent':
                self.page
            }

        elif config.POST_BACKUP:
            max_res = board.options['IMAGES_PER_PAGE']

            sqlcond = and_(
                or_(
                    table.c.parent == 0,
                    and_(
                        table.c.parent > 0,
                        not_(
                            exists([table.c.num],
                                   table.c.parent == table.c.postnum)))),
                table.c.board_name == board.name)

            # Acquire the number of full threads *and* orphaned posts.
            sql = select([func.count()], sqlcond, table)\
                  .order_by(table.c.timestampofarchival.desc(),
                              table.c.postnum.asc())

            thread_ct = session.execute(sql).fetchone()[0]

            total = int(thread_ct + max_res - 1) / max_res
            offset = self.page * max_res

            (pages, prevpage, nextpage) \
                = board.get_board_page_data(self.page, total,
                                            admin_page='postbackups')

            last_page = len(pages) - 1
            if self.page > last_page and last_page > 0:
                self.page = last_page

            sql = table.select().where(sqlcond)\
                  .order_by(table.c.timestampofarchival.desc(),
                              table.c.num.asc())\
                  .limit(board.options['IMAGES_PER_PAGE'])\
                  .offset(offset)
            threads = [{'posts' : [dict(x.items())]} \
                for x in session.execute(sql)]

            # Loop through 'posts' key in each dictionary in the threads
            # list.
            for item in threads:
                thread = item['posts']
                threadnum = thread[0]['postnum']
                postcount = imgcount = shownimages = 0

                # Orphaned?
                item['standalone'] = 0

                if not thread[0]['parent']:
                    sql = select(
                        [func.count(), func.count(table.c.image)],
                        table.c.parent == threadnum, table)

                    (postcount, imgcount) = session.execute(sql).fetchone()

                    max_res = board.options['REPLIES_PER_THREAD']
                    offset = postcount - imgcount if postcount > max_res \
                                                  else 0

                    sql = table.select().where(table.c.parent == threadnum)\
                            .order_by(table.c.timestampofarchival.desc(),
                                      table.c.postnum.asc())\
                            .limit(max_res)\
                            .offset(offset)
                    thread.extend([dict(x.items()) \
                                       for x in session.execute(sql)])

                else:
                    item['standalone'] = 1

                for post in thread:
                    image_dir \
                        = os.path.join(board.path, board.options['IMG_DIR'])

                    thumb_dir \
                        = os.path.join(board.path, board.options['THUMB_DIR'])

                    base_thumb = os.path.basename(post['thumbnail'] or '')
                    base_image = os.path.basename(post['image'] or '')

                    base_filename = (post['image'] or '')\
                        .replace(image_dir, '').lstrip('/')

                    backup_dir = os.path.join(board.url,
                                              board.options['ARCHIVE_DIR'],
                                              board.options['BACKUP_DIR'])

                    if post['image']:
                        post['image'] = os.path.join(backup_dir, base_image)
                        shownimages += 1

                    if re.match(board.options['THUMB_DIR'], post['thumbnail']
                                or ''):
                        post['thumbnail'] \
                            = os.path.join(backup_dir, base_thumb)

                item['omit'] = postcount - max_res if postcount > max_res\
                                                   else 0

                item['omitimages'] = imgcount - shownimages \
                                     if imgcount > shownimages else 0

                template_kwargs = {'postform' \
                                      : board.options['ALLOW_TEXTONLY'] or
                                        board.options['ALLOW_IMAGES'],
                                  'image_inp' : board.options['ALLOW_IMAGES'],
                                   'textonly_inp' \
                                      : board.options['ALLOW_IMAGES'] and
                                        board.options['ALLOW_TEXTONLY'],
                                   'nextpage' : nextpage,
                                   'prevpage' : prevpage,
                                   'threads' : threads,
                                   'pages' : pages}

        Template.__init__(self, 'backup_panel_template', **template_kwargs)
예제 #28
0
 def ret_func(*args, **kwargs):
     self = args[0]
     if self.user.account == staff.MODERATOR:
         raise WakaError(strings.INSUFFICIENTPRIVILEGES)
     f(*args, **kwargs)
예제 #29
0
    def make_admin_post_search_panel(self, search, text, caller='internal'):
        board = self.board
        session = model.Session()
        table = board.table

        board.check_access(self.user)

        popup = caller != 'board'

        if search.find('IP Address') != -1:
            try:
                sql = table.select()\
                           .where(table.c.ip == misc.dot_to_dec(text))
            except ValueError:
                raise WakaError('Please enter a valid IP.')
            search_type = 'IP'
        elif search.find('Text String') != -1:
            sql = table.select().where(table.c.comment.like('%' + text + '%'))
            search_type = 'text string'
        elif search.find('Author') != -1:
            sql = table.select().where(
                or_(table.c.name.like('%' + text + '%'),
                    table.c.trip.like('%' + text + '%')))
            search_type = 'author'
        else:
            sql = table.select().where(table.c.num == text)
            search_type = 'ID'

        if search_type != 'ID':
            page = model.Page(sql, self.page, self.perpage)
            rowcount = page.total_entries
            total_pages = page.total_pages
            posts = page.rows
            if not posts:
                raise WakaError("No posts found for %s %s" %
                                (search_type, text))
        else:
            rowcount = total_pages = 1
            row = session.execute(sql).fetchone()
            if not row:
                raise WakaError("Post not found. (It may have just been"
                                " deleted.)")
            posts = [row]

        inputs = [{
            'name': 'board',
            'value': board.name
        }, {
            'name': 'task',
            'value': 'searchposts'
        }, {
            'name': 'text',
            'value': text
        }, {
            'name': 'caller',
            'value': caller
        }, {
            'name': 'search',
            'value': search
        }]

        rooturl = misc.make_script_url(task='searchposts',
                                       board=board.name,
                                       caller=caller,
                                       search=search,
                                       text=text,
                                       _amp=True)

        Template.__init__(self,
                          'post_search',
                          num=id,
                          posts=posts,
                          search=search,
                          text=text,
                          inputs=inputs,
                          number_of_pages=total_pages,
                          rooturl=rooturl,
                          rowcount=rowcount,
                          popup=popup)