├── tools
├── index.php
├── checkup.php
└── ip-whois.php
├── misc
├── modes-parser.php
├── pwa-manifest.php
├── right-click.php
├── ban-exceptions-misc.php
├── ip-whois-misc.php
└── strings.php
├── plugins
├── file_db
│ └── index.php
├── sql_db
│ ├── index.php
│ ├── user-info.php
│ └── SQL
│ │ ├── sql.php
│ │ └── settings.php
├── index.php
└── config_blocks
│ ├── index.php
│ └── config_blocks.php
├── data
├── .htaccess
├── index.php
└── .gitignore
├── config
├── .htaccess
├── index.php
├── .gitignore
└── compat.php
├── .gitignore
├── .gitattributes
├── css
├── index.php
└── unrealircd-admin.css
├── img
├── index.php
├── linen.png
├── favicon.ico
├── patreon.png
├── unreal.jpeg
├── unreal.jpg
├── unreal.png
├── background.jpg
├── wallpaper.jpg
└── no-image-available.jpg
├── js
├── index.php
├── service-worker.js
├── bs-toast.js
├── right-click-menus.js
├── datatables-ellipsis.js
├── unrealircd-admin.js
└── datatables-natural-sort.js
├── Classes
├── index.php
├── class-table.php
├── class-log.php
├── class-notes.php
├── class-message.php
├── class-rpc.php
├── class-plugins.php
├── class-unrealconf.php
├── class-plugin-git.php
├── class-hook.php
├── class-cmodes.php
└── class-upgrade.php
├── .htaccess
├── api
├── index.php
├── overview.php
├── notification.php
├── timeout.php
├── set_rpc_server.php
├── data.php
├── upgrade.php
├── installation.php
├── log.php
├── test_rpc_server.php
├── channels.php
├── server-bans.php
├── users.php
├── plugin.php
├── common_api.php
└── search.php
├── composer.json
├── doc
├── AUTHORS.md
└── CODE_OF_CONDUCT.md
├── Dockerfile
├── inc
├── defines.php
├── footer.php
└── connection.php
├── .github
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── news.php
├── README.md
├── users
└── details.php
├── channels
└── index.php
├── settings
├── add-plugin.php
├── plugins.php
├── user-edit.php
├── user-role-edit.php
└── index.php
├── servers
├── index.php
└── details.php
├── logs
└── index.php
├── login
└── index.php
└── server-bans
└── name-bans.php
/tools/index.php:
--------------------------------------------------------------------------------
1 |
2 | Order allow,deny
3 | Deny from all
4 |
5 |
--------------------------------------------------------------------------------
/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unrealircd/unrealircd-webpanel/main/img/favicon.ico
--------------------------------------------------------------------------------
/img/patreon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unrealircd/unrealircd-webpanel/main/img/patreon.png
--------------------------------------------------------------------------------
/img/unreal.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unrealircd/unrealircd-webpanel/main/img/unreal.jpeg
--------------------------------------------------------------------------------
/img/unreal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unrealircd/unrealircd-webpanel/main/img/unreal.jpg
--------------------------------------------------------------------------------
/img/unreal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unrealircd/unrealircd-webpanel/main/img/unreal.png
--------------------------------------------------------------------------------
/plugins/index.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/api/overview.php:
--------------------------------------------------------------------------------
1 |
12 |
13 |
Configuration Blocks
14 |
15 |
16 | 'active']));
8 | else
9 | {
10 | session_destroy();
11 | die(json_encode(['session' => 'none']));
12 | }
--------------------------------------------------------------------------------
/api/set_rpc_server.php:
--------------------------------------------------------------------------------
1 | $cpuUsage[0],
18 | "memory" => convert($memUsage),
19 | );
20 |
21 | header('Content-Type: application/json');
22 | echo json_encode($data);
23 | ?>
--------------------------------------------------------------------------------
/inc/defines.php:
--------------------------------------------------------------------------------
1 | PDO::ERRMODE_EXCEPTION,
18 | PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
19 | PDO::ATTR_EMULATE_PREPARES => false,
20 | ];
21 | try {
22 | $pdo = new PDO($dsn, $user, $pass, $options);
23 | } catch (\PDOException $e) {
24 | throw new \PDOException($e->getMessage(), (int)$e->getCode());
25 | }
26 | return $pdo;
27 | }
--------------------------------------------------------------------------------
/Classes/class-log.php:
--------------------------------------------------------------------------------
1 | it($strings);
37 | }
38 |
39 | function get_date($year, $month, $day, $hour, $minute)
40 | {
41 | return "$year-$month-$day" . "T$hour-$minute" . "Z";
42 | }
--------------------------------------------------------------------------------
/misc/pwa-manifest.php:
--------------------------------------------------------------------------------
1 | BASE_URL.'img/favicon.ico',
15 | 'sizes' => '64x64',
16 | 'type' => 'image/x-icon'
17 | ],
18 | [
19 | 'src' => BASE_URL.'img/unreal.jpg',
20 | 'sizes' => '128x128',
21 | 'type' => 'image/x-icon'
22 | ]
23 | ];
24 |
25 | $json = json_encode($manifest, JSON_PRETTY_PRINT);
26 | return file_put_contents('../manifest.json', $json) ? true : false;
27 | }
28 |
--------------------------------------------------------------------------------
/api/upgrade.php:
--------------------------------------------------------------------------------
1 | error)
10 | {
11 | error_log("Couldn't create dir.");
12 | return;
13 | }
14 | error_log("Checking for upgrade");
15 | $upgrade->checkForNew();
16 | if (Upgrade::$upgrade_available)
17 | {
18 | error_log("Upgrade available, downloading and installing");
19 | if (!$upgrade->downloadUpgradeZip())
20 | return error_log($upgrade->error);
21 |
22 | else if (!$upgrade->extractZip())
23 | return error_log($upgrade->error);
24 |
25 | $upgrade->cleanupOldFiles();
26 |
27 | if(!$upgrade->extractToWebdir())
28 | return error_log($upgrade->error);
29 |
30 | $upgrade->cleanupDownloadFiles();
31 | error_log("Upgrade was successful!");
32 | }
33 | else
34 | error_log("No upgrade available");
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ValwareIRC
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/misc/right-click.php:
--------------------------------------------------------------------------------
1 | "Copy",
10 | "onclick" => "copy_to_clipboard(window.getSelection().toString())",
11 | "icon" => "fa-clipboard"
12 | ],
13 | [
14 | "text" => "Paste",
15 | "onclick" => "paste_from_clipboard()",
16 | "icon" => "fa-paint-brush",
17 | ],
18 | ];
19 |
20 | // register our menu
21 | Hook::run(HOOKTYPE_RIGHTCLICK_MENU, $menu);
22 |
23 | ?>
24 |
25 |
26 |
--------------------------------------------------------------------------------
/news.php:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | {
2 | console.log("Service Worker installing...");
3 | event.waitUntil(
4 | self.skipWaiting().then(() => {
5 | console.log("Service Worker installed and skipWaiting called.");
6 | }).catch((error) => {
7 | console.error("Error during Service Worker installation:", error);
8 | })
9 | );
10 | });
11 |
12 | self.addEventListener("activate", (event) => {
13 | console.log("Service Worker activated!");
14 | event.waitUntil(
15 | self.clients.claim().then(() => {
16 | console.log("Service Worker claimed clients.");
17 | }).catch((error) => {
18 | console.error("Error during Service Worker activation:", error);
19 | })
20 | );
21 | });
22 |
23 | self.addEventListener("fetch", (event) => {
24 | console.log("Intercepting request for:", event.request.url);
25 | event.respondWith(
26 | fetch(event.request).catch((error) => {
27 | console.error("Fetch failed for:", event.request.url, "Error:", error);
28 | })
29 | );
30 | });
--------------------------------------------------------------------------------
/api/installation.php:
--------------------------------------------------------------------------------
1 | "Configuration file exists."]));
10 |
11 | if (!isset($_POST) || empty($_POST))
12 | die(json_encode(["error" => "Incorrect parameters"]));
13 |
14 | if ($_POST['method'] == "sql")
15 | {
16 | try {
17 | $conn = mysqli_connect($_POST['host'], $_POST['user'], $_POST['password'], $_POST['database']);
18 | } catch(Exception $e)
19 | {
20 | }
21 | // check connection
22 | if (mysqli_connect_errno())
23 | die(json_encode(["error" => "Failed to connect to MySQL: " . mysqli_connect_error()]));
24 |
25 | $sql = "SHOW TABLES LIKE '".$conn->real_escape_string($_POST['table_prefix'])."%'"; // SQL query to check if table exists
26 | $result = $conn->query($sql);
27 | if ($result->num_rows > 0)
28 | die(json_encode(["warn" => "Database already has data"]));
29 |
30 | // close connection
31 | mysqli_close($conn);
32 | die(json_encode(["success" => "SQL Connection successful"]));
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/api/log.php:
--------------------------------------------------------------------------------
1 | log()->getAll($log_list);
26 | if ($response !== false)
27 | {
28 | /* Only supported in later UnrealIRCd versions */
29 | $cnt = 0;
30 | foreach($response as $r)
31 | {
32 | $r = (ARRAY)$r;
33 | $cnt++;
34 | if (($cnt % 100) != 0)
35 | $r["sync_option"] = "no_sync";
36 | send_sse($r);
37 | }
38 | }
39 |
40 | $r = ["sync_option"=>"sync_now"];
41 | send_sse($r);
42 |
43 | api_log_loop($log_list);
44 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## UnrealIRCd Administration WebPanel
2 |
3 | []()
4 | []()
5 | []()
6 | [](https://unrealircd.org)
7 |
8 | The UnrealIRCd Administration WebPanel gives you an overview of your IRC network,
9 | with detailed information about servers, users and channels.
10 | You can easily add and remove server bans, spamfilters and do other administrative tasks,
11 | all from the convenience of your web browser.
12 |
13 | ## Example Overview from Desktop
14 |
15 |
16 |
17 | ## Example Overview from Mobile
18 |
19 |

20 |

21 |
22 |
23 | ## Installation ##
24 | See https://www.unrealircd.org/docs/UnrealIRCd_webpanel for all documentation.
25 |
--------------------------------------------------------------------------------
/api/test_rpc_server.php:
--------------------------------------------------------------------------------
1 | "Incorrect parameters"]));
7 |
8 | foreach(array("tls_verify","host","port","user","password","edit_existing") as $k)
9 | {
10 | if (!isset($_POST[$k]))
11 | die("MISSING: $k");
12 | ${$k} = $_POST[$k];
13 | }
14 |
15 | if ($tls_verify == "false")
16 | $tls_verify = false;
17 | elseif ($tls_verify == "true")
18 | $tls_verify = true;
19 |
20 | if (($edit_existing) && ($password == "****************"))
21 | {
22 | /* If editing existing and password unchanged,
23 | * try to look up existing password.
24 | */
25 | if (isset($config["unrealircd"][$edit_existing]))
26 | {
27 | $password = $config["unrealircd"][$edit_existing]["rpc_password"];
28 | if (str_starts_with($password, "secret:"))
29 | $password = secret_decrypt($password);
30 | }
31 | }
32 |
33 | try {
34 | $rpc = new UnrealIRCd\Connection
35 | (
36 | "wss://$host:$port",
37 | "$user:$password",
38 | ["tls_verify" => $tls_verify]
39 | );
40 | }
41 | catch (Exception $e)
42 | {
43 | die(json_encode(["error" => "Unable to connect to UnrealIRCd: ".$e->getMessage()]));
44 | }
45 |
46 | die(json_encode(["success" => "Successfully connected"]));
47 |
--------------------------------------------------------------------------------
/api/channels.php:
--------------------------------------------------------------------------------
1 | channel()->getAll();
11 |
12 | $columns = array_column($channels, 'num_users');
13 | array_multisort($columns, SORT_DESC, $channels);
14 |
15 | $out = [];
16 | foreach($channels as $channel)
17 | {
18 | $modes = (isset($channel->modes)) ? "+" . explode(" ",$channel->modes)[0] : "";
19 | $topic = '';
20 | if (isset($channel->topic))
21 | $topic = htmlentities(StripControlCharacters($channel->topic), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 | ENT_DISALLOWED);
22 | $date = explode("T", $channel->creation_time)[0];
23 | $out[] = [
24 | "Name" => htmlspecialchars($channel->name),
25 | "Users" => $channel->num_users,
26 | "Modes" => "modes)."\">$modes",
27 | "Topic" => $topic,
28 | "Created" => "creation_time."\">$date",
29 | ];
30 | }
31 |
32 | function custom_sort($a,$b)
33 | {
34 | return $b["Users"] <=> $a["Users"];
35 | }
36 |
37 | usort($out, "custom_sort");
38 |
39 | echo json_encode($out);
40 |
--------------------------------------------------------------------------------
/api/server-bans.php:
--------------------------------------------------------------------------------
1 | serverban()->getAll();
10 |
11 | $out = [];
12 | foreach($tkls as $tkl)
13 | {
14 | $set_in_config = ((isset($tkl->set_in_config) && $tkl->set_in_config) || ($tkl->set_by == "-config-")) ? true : false;
15 | $set_by = $set_in_config ? "Config" : show_nick_only(htmlspecialchars($tkl->set_by));
16 | $select = '';
17 | if (!$set_in_config)
18 | $select = "";
19 |
20 | $out[] = [
21 | "Select" => $select,
22 | "Mask" => htmlspecialchars($tkl->name),
23 | "Type" => $tkl->type_string,
24 | "Duration" => $tkl->duration_string,
25 | "Reason" => htmlspecialchars($tkl->reason),
26 | "Set By" => $set_by,
27 | "Set On" => $tkl->set_at_string,
28 | "Expires" => $tkl->expire_at_string,
29 | ];
30 | }
31 |
32 | function custom_sort($a,$b)
33 | {
34 | return strcmp(strtoupper($a["Mask"]), strtoupper($b["Mask"]));
35 | }
36 |
37 | usort($out, "custom_sort");
38 |
39 | echo json_encode($out);
40 |
--------------------------------------------------------------------------------
/misc/ban-exceptions-misc.php:
--------------------------------------------------------------------------------
1 | $name";
39 | }
40 | return $badges;
41 | }
42 |
--------------------------------------------------------------------------------
/plugins/sql_db/SQL/settings.php:
--------------------------------------------------------------------------------
1 | query($query);
8 | $list = [];
9 | while ($row = $result->fetch())
10 | {
11 | $list[$row['setting_key']] = unserialize($row['setting_value']);
12 | }
13 | return $list;
14 | }
15 | public static function set($key, $val) : int
16 | {
17 | $conn = sqlnew();
18 | $stmt = $conn->prepare("SELECT * FROM " . get_config("mysql::table_prefix") . "settings WHERE setting_key = :name LIMIT 1");
19 | $stmt->execute(["name" => $key]);
20 | if ($stmt->rowCount()) // if it already exists update it
21 | $stmt = $conn->prepare("UPDATE " . get_config("mysql::table_prefix") . "settings SET setting_value = :value WHERE setting_key = :name");
22 |
23 | else // otherwise create it
24 | $stmt = $conn->prepare("INSERT INTO " . get_config("mysql::table_prefix") . "settings (setting_key, setting_value) VALUES (:name, :value)");
25 |
26 | // make sure it's there/correct
27 | $stmt->execute(["name" => $key, "value" => serialize($val)]);
28 | $stmt = $conn->prepare("SELECT * FROM " . get_config("mysql::table_prefix") . "settings WHERE setting_key = :name LIMIT 1");
29 | $stmt->execute(["name" => $key]);
30 | return $stmt->rowCount(); // return 1 or 0 bool-like int
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/config/compat.php:
--------------------------------------------------------------------------------
1 | new config */
4 |
5 | /* Base url */
6 | if (defined('BASE_URL'))
7 | $config["base_url"] = BASE_URL;
8 |
9 | /* UnrealIRCd settings */
10 | if (defined('UNREALIRCD_RPC_USER'))
11 | $config["unrealircd"]["rpc_user"] = UNREALIRCD_RPC_USER;
12 | if (defined('UNREALIRCD_RPC_PASSWORD'))
13 | $config["unrealircd"]["rpc_password"] = UNREALIRCD_RPC_PASSWORD;
14 | if (defined('UNREALIRCD_HOST'))
15 | $config["unrealircd"]["host"] = UNREALIRCD_HOST;
16 | if (defined('UNREALIRCD_PORT'))
17 | $config["unrealircd"]["port"] = UNREALIRCD_PORT;
18 | if (defined('UNREALIRCD_SSL_VERIFY'))
19 | $config["unrealircd"]["tls_verify_cert"] = UNREALIRCD_SSL_VERIFY;
20 |
21 | /* Debug */
22 | if (defined('UNREALIRCD_DEBUG'))
23 | $config["debug"] = UNREALIRCD_DEBUG;
24 |
25 | /* Plugins */
26 | if (defined('PLUGINS'))
27 | $config["plugins"] = PLUGINS;
28 |
29 | /* SQL settings */
30 | if (defined('SQL_IP'))
31 | $config["mysql"]["host"] = SQL_IP;
32 | if (defined('SQL_DATABASE'))
33 | $config["mysql"]["database"] = SQL_DATABASE;
34 | if (defined('SQL_USERNAME'))
35 | $config["mysql"]["username"] = SQL_USERNAME;
36 | if (defined('SQL_PASSWORD'))
37 | $config["mysql"]["password"] = SQL_PASSWORD;
38 | if (defined('SQL_PREFIX'))
39 | $config["mysql"]["table_prefix"] = SQL_PREFIX;
40 |
41 | /* DNS Blacklist */
42 | if (defined('DNSBL'))
43 | $config["dnsbl"] = DNSBL;
44 |
45 | /* Mailer */
46 | if (defined('EMAIL_SETTINGS'))
47 | $config["smtp"] = EMAIL_SETTINGS;
48 |
--------------------------------------------------------------------------------
/plugins/config_blocks/config_blocks.php:
--------------------------------------------------------------------------------
1 | create_sql_table();
23 | }
24 |
25 | /** HOOKTYPE_NAVBAR
26 | * If the current user has permission to manage config blocks,
27 | * add a link to the "Tools" menu about it
28 | */
29 | public static function add_navbar(&$pages)
30 | {
31 | $page_name = "Config Blocks";
32 | $page_link = "plugins/config_blocks/";
33 | if (current_user_can(PERMISSION_CONFIG_BLOCKS))
34 | $pages["Tools"][$page_name] = $page_link;
35 | }
36 |
37 | /** HOOKTYPE_USER_PERMISSION_LIST
38 | * Add a permission in the Panel Users permission list.
39 | */
40 | public static function permission_list(&$list)
41 | {
42 | $list["Can manage Remote Configs in Config Blocks"] = PERMISSION_CONFIG_BLOCKS;
43 | }
44 |
45 | /** Creates the SQL table for storing config block information */
46 | public static function create_sql_table()
47 | {
48 | $conn = sqlnew();
49 | $conn->query("CREATE TABLE IF NOT EXISTS " . get_config("mysql::table_prefix") . "configblocks (
50 | block_id int AUTO_INCREMENT NOT NULL,
51 | block_name VARCHAR(255) NOT NULL,
52 | block_value VARCHAR(255) NOT NULL,
53 | added_ts VARCHAR(255),
54 | added_username VARCHAR(255),
55 | PRIMARY KEY (block_id)
56 | )");
57 | }
58 |
59 | }
--------------------------------------------------------------------------------
/inc/footer.php:
--------------------------------------------------------------------------------
1 |
2 |
53 |
54 |