This site is developed to XHTML and CSS2 W3C standards. If you see this paragraph, your browser does not support those standards and you need to upgrade. Visit WaSP for a variety of options.

php pastebin - collaborative irc debugging view php source

Paste #726

Posted by: web
Posted on: 2026-09-17 19:13:38
Age: 3 hrs ago
Views: 5
import os
import re
import subprocess
from bottle import run, route, request, redirect, template

# Простая HTML-страница со встроенными стилями
HTML_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>NNTP (INN2) Web Panel</title>
    <style>
        body { font-family: sans-serif; max-width: 700px; margin: 40px auto; padding: 0 20px; background: #f4f6f9; color: #333; }
        .box { background: white; padding: 20px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-bottom: 20px; }
        h2 { margin-top: 0; color: #2c3e50; border-bottom: 2px solid #eee; padding-bottom: 10px; }
        input[type="text"] { width: 70%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; font-size: 16px; }
        button { padding: 10px 20px; background: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; }
        button:hover { background: #2980b9; }
        button.del { background: #e74c3c; padding: 5px 10px; font-size: 14px; }
        button.del:hover { background: #c0392b; }
        table { width: 100%; border-collapse: collapse; margin-top: 10px; }
        th, td { text-align: left; padding: 12px; border-bottom: 1px solid #eee; }
        th { background: #f8f9fa; color: #555; }
        .error { color: #721c24; background: #f8d7da; padding: 10px; border-radius: 4px; margin-bottom: 15px; }
        .success { color: #155724; background: #d4edda; padding: 10px; border-radius: 4px; margin-bottom: 15px; }
    </style>
</head>
<body>
    <h1>NNTP (INN2) Управление Сервером</h1>
    
    % if msg:
        <div class="success">{{msg}}</div>
    % end
    % if err:
        <div class="error">{{err}}</div>
    % end

    <div class="box">
        <h2>Создать новую группу / подгруппу</h2>
        <form action="/create" method="post">
            <input type="text" name="group_name" placeholder="например: local.chat.forum" required>
            <button type="submit">Создать</button>
        </form>
    </div>

    <div class="box">
        <h2>Активные группы на сервере</h2>
        <table>
            <tr>
                <th>Имя группы</th>
                <th>Статус</th>
                <th>Действие</th>
            </tr>
            % for group, status in groups:
            <tr>
                <td><strong>{{group}}</strong></td>
                <td>{{status}} (открыта)</td>
                <td>
                    % if group not in ['control', 'junk']:
                    <form action="/delete" method="post" style="display:inline;" onsubmit="return confirm('Удалить группу {{group}}?');">
                        <input type="hidden" name="group_name" value="{{group}}">
                        <button type="submit" class="del">Удалить</button>
                    </form>
                    % else:
                    <span style="color:#aaa;">системная</span>
                    % end
                </td>
            </tr>
            % end
        </table>
    </div>
</body>
</html>
"""

def run_nntp_cmd(action, group_name=""):
    """Прямой и безопасный вызов ctlinnd через системный шелл, исключающий ошибки парсинга аргументов"""
    if action == "list":
        cmd = "sudo -u news ctlinnd list active"
    elif action == "create":
        cmd = f"sudo -u news ctlinnd newgroup {group_name} y"
    elif action == "delete":
        cmd = f"sudo -u news ctlinnd rmgroup {group_name}"
    else:
        return False, "Неверное действие"

    res = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    if res.returncode == 0:
        return True, res.stdout
    else:
        return False, res.stderr if res.stderr else res.stdout

def get_active_groups():
    success, output = run_nntp_cmd("list")
    if not success:
        return []
    
    parsed_groups = []
    for line in output.strip().split("\n"):
        if not line: continue
        parts = line.split()
        if len(parts) >= 4:
            parsed_groups.append((parts[0], parts[3]))
    return parsed_groups

@route('/')
def index():
    err = request.query.get('err', '')
    msg = request.query.get('msg', '')
    return template(HTML_TEMPLATE, groups=get_active_groups(), err=err, msg=msg)

@route('/create', method='POST')
def create():
    group_name = request.forms.get('group_name', '').strip()
    if not group_name or not re.match(r"^[a-zA-Z0-9\.-]+$", group_name):
        return redirect('/?err=Invalid+group+name')
    
    success, out = run_nntp_cmd("create", group_name)
    if success:
        return redirect(f'/?msg=Group+{group_name}+created+successfully')
    else:
        return redirect(f'/?err={out.replace(" ", "+")}')

@route('/delete', method='POST')
def delete():
    group_name = request.forms.get('group_name', '').strip()
    if group_name in ['control', 'junk']:
        return redirect('/?err=Cannot+delete+system+groups')
        
    success, out = run_nntp_cmd("delete", group_name)
    if success:
        return redirect(f'/?msg=Group+{group_name}+deleted')
    else:
        return redirect(f'/?err={out.replace(" ", "+")}')

# Запуск веб-сервера на порту 8080 для всех IP адресов
if __name__ == '__main__':
    run(host='0.0.0.0', port=8080, debug=True)

Download raw | Create new paste

© BitByByte, 2026.
Downgrade Counter