Bearsampp 2026.7.11
Loading...
Searching...
No Matches
root.php
Go to the documentation of this file.
1<?php
2/*
3 * Copyright (c) 2022 - 2024 Bearsampp
4 * License: GNU General Public License version 3 or later; see LICENSE.txt
5 * Website: https://bearsampp.com
6 * Github: https://github.com/Bearsampp
7 */
8
12const APP_AUTHOR_NAME = 'N6REJ';
13const APP_TITLE = 'Bearsampp';
14const APP_WEBSITE = 'https://bearsampp.com';
15const APP_LICENSE = 'GPL3 License';
16const APP_GITHUB_USER = 'Bearsampp';
17const APP_GITHUB_REPO = 'Bearsampp';
18const APP_GITHUB_USERAGENT = 'Bearsampp';
19const APP_GITHUB_LATEST_URL = 'https://api.github.com/repos/' . APP_GITHUB_USER . '/' . APP_GITHUB_REPO . '/releases/latest';
20const RETURN_TAB = ' ';
21
22// Membership Pro API key & URL
23const QUICKPICK_API_KEY = '4abe15e5-95f2-4663-ad12-eadb245b28b4';
24const QUICKPICK_API_URL = 'https://bearsampp.com/index.php?option=com_osmembership&task=api.get_active_plan_ids&api_key=';
25
26// URL where quickpick-releases.json lives
27const QUICKPICK_JSON_URL = 'https://raw.githubusercontent.com/' . APP_GITHUB_USER . '/' . APP_GITHUB_REPO . '/main/core/resources/quickpick-releases.json';
28
29// CRITICAL: Check for elevation IMMEDIATELY - must be FAST to minimize console window visibility
30if (isset($_SERVER['argv']) && isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] === 'startup') {
31 $flagFile = sys_get_temp_dir() . '/bearsampp_no_admin.lock';
32
33 // Quick exit if we already determined no admin recently
34 if (file_exists($flagFile) && (time() - filemtime($flagFile)) < 10) {
35 $currentPid = getmypid();
36 $killCmd = 'powershell.exe -WindowStyle Hidden -Command "Stop-Process -Id ' . (int)$currentPid . ' -Force -ErrorAction SilentlyContinue; Stop-Process -Name bearsampp -Force -ErrorAction SilentlyContinue"';
37 try {
38 // WScript.Shell.Run with style=0 (hidden) avoids cmd.exe flash that popen causes
39 $wshKill = new COM('WScript.Shell');
40 $wshKill->Run($killCmd, 0, false);
41 } catch (Exception $e) {
42 pclose(popen($killCmd, 'r'));
43 }
44 exit(1);
45 }
46
47 // FAST elevation check - use WScript.Shell.Run with hidden window (style=0) to avoid console flash
48 $isElevated = false;
49 try {
50 $wsh = new COM('WScript.Shell');
51 // intWindowStyle=0 = completely hidden (no window, no taskbar entry), bWaitOnReturn=true
52 // net session exits 0 when elevated, non-zero when access denied
53 $exitCode = $wsh->Run('net session', 0, true);
54 $isElevated = ($exitCode === 0);
55 } catch (Exception $e) {
56 // COM unavailable — fall back to shell_exec (may flash briefly)
57 $netOutput = @shell_exec('net session 2>&1');
58 if ($netOutput !== null) {
59 if (stripos($netOutput, 'Access is denied') === false &&
60 stripos($netOutput, 'System error 5') === false &&
61 $netOutput !== '') {
62 $isElevated = true;
63 }
64 }
65 }
66
67 if (!$isElevated) {
68 // Create flag file immediately
69 @file_put_contents($flagFile, time());
70
71 // Load language file for error message
72 $langFile = dirname(__FILE__) . '/langs/english.lang';
73 $langData = @parse_ini_file($langFile);
74
75 // Get localized messages
76 $title = isset($langData['errorAdminRequiredTitle']) ? $langData['errorAdminRequiredTitle'] : 'Administrator Rights Required';
77 $messageText = isset($langData['errorAdminRequiredText']) ? $langData['errorAdminRequiredText'] : '%s requires administrator privileges to install and manage Windows services.@nl@@nl@Please right-click on bearsampp.exe and select "Run as administrator" to start the application.';
78
79 // Replace placeholders
80 $messageText = sprintf($messageText, APP_TITLE);
81 $messageText = str_replace('@nl@', '|||NEWLINE|||', $messageText);
82
83 // Split by newline placeholder
84 $messageParts = explode('|||NEWLINE|||', $messageText);
85
86 // Create PowerShell script that handles everything (no window flashing)
87 $psFile = sys_get_temp_dir() . '/bearsampp_admin_error.ps1';
88 $flagFilePs = str_replace('/', '\\', $flagFile);
89 $psFilePs = str_replace('/', '\\', $psFile);
90
91 // Escape for PowerShell
92 $title = str_replace("'", "''", $title);
93 $currentPid = getmypid();
94
95 // PowerShell script that shows message FIRST, then kills processes
96 $psContent = "# Show error message using Windows Forms\n";
97 $psContent .= "Add-Type -AssemblyName System.Windows.Forms\n";
98
99 // Build message from parts
100 $psContent .= "\$messageParts = @(\n";
101 $lastIndex = count($messageParts) - 1;
102 foreach ($messageParts as $index => $part) {
103 $part = str_replace("'", "''", trim($part));
104 // Don't add comma after last item
105 $comma = ($index < $lastIndex) ? ',' : '';
106 $psContent .= " '" . $part . "'" . $comma . "\n";
107 }
108 $psContent .= ")\n";
109 $psContent .= "\$message = \$messageParts -join [Environment]::NewLine\n";
110 $psContent .= "[System.Windows.Forms.MessageBox]::Show(\$message, '" . $title . "', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error) | Out-Null\n";
111 $psContent .= "\n";
112 $psContent .= "# After user clicks OK, kill only Bearsampp-related processes\n";
113 $psContent .= "Stop-Process -Id " . (int)$currentPid . " -Force -ErrorAction SilentlyContinue\n";
114 $psContent .= "Stop-Process -Name bearsampp -Force -ErrorAction SilentlyContinue\n";
115 $psContent .= "\n";
116 $psContent .= "# Clean up\n";
117 $psContent .= "Remove-Item -Path '" . $flagFilePs . "' -Force -ErrorAction SilentlyContinue\n";
118 $psContent .= "Remove-Item -Path '" . $psFilePs . "' -Force -ErrorAction SilentlyContinue\n";
119
120 @file_put_contents($psFile, $psContent);
121
122 // Launch PowerShell to show the error message — use COM Run(style=0) to avoid cmd.exe flash
123 if (isset($wsh)) {
124 $wsh->Run('powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File "' . $psFile . '"', 0, false);
125 } else {
126 pclose(popen('start "" powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File "' . $psFile . '"', 'r'));
127 }
128
129 // Exit immediately - PowerShell will handle showing the message and cleanup
130 exit(1);
131 } else {
132 // We're elevated, clean up any old flag
133 @unlink($flagFile);
134 }
135}
136
141require_once dirname(__FILE__) . '/classes/class.path.php';
142require_once dirname(__FILE__) . '/classes/class.root.php';
143$bearsamppRoot = new Root(dirname(__FILE__));
144$bearsamppRoot->register();
145
150$bearsamppAction->process();
151
156if ($bearsamppRoot->isRoot()) {
157 $currentAction = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
158 if ($currentAction !== Action::LOADING && $currentAction !== Action::STARTUP) {
159 Log::debug('root.php: script ending, calling Util::stopLoading() for action: ' . $currentAction);
161 }
162}
163
168$locale = $bearsamppLang->getValue('locale');
global $bearsamppLang
global $bearsamppRoot
const LOADING
const STARTUP
static debug($data, $file=null)
static stopLoading()
const QUICKPICK_JSON_URL
Definition root.php:27
const APP_GITHUB_USERAGENT
Definition root.php:18
const APP_AUTHOR_NAME
Definition root.php:12
const APP_WEBSITE
Definition root.php:14
$locale
Definition root.php:168
const APP_GITHUB_USER
Definition root.php:16
const APP_GITHUB_REPO
Definition root.php:17
const QUICKPICK_API_URL
Definition root.php:24
const APP_LICENSE
Definition root.php:15
const APP_GITHUB_LATEST_URL
Definition root.php:19
const QUICKPICK_API_KEY
Definition root.php:23
const RETURN_TAB
Definition root.php:20
$bearsamppAction
Definition root.php:149
const APP_TITLE
Definition root.php:13