Bearsampp 2026.9.23
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
18const APP_AUTHOR_NAME = 'N6REJ';
19const APP_TITLE = 'Bearsampp';
20const APP_WEBSITE = 'https://bearsampp.com';
21const APP_LOCALHOST = '127.0.0.1';
22const APP_LICENSE = 'GPL3 License';
23const APP_GITHUB_USER = 'Bearsampp';
24const APP_GITHUB_REPO = 'Bearsampp';
25const APP_GITHUB_USERAGENT = 'Bearsampp';
26const APP_GITHUB_LATEST_URL = 'https://api.github.com/repos/' . APP_GITHUB_USER . '/' . APP_GITHUB_REPO . '/releases/latest';
27const RETURN_TAB = ' ';
28
29// Membership Pro API key & URL
30// NOTE: This key is a PUBLIC identifier baked into an open-source (GPL-3) build.
31// It is not a secret/credential and must not be used for authorization decisions;
32// license validation relies on the per-user DOWNLOADID + server-side check instead.
33const QUICKPICK_API_KEY = '4abe15e5-95f2-4663-ad12-eadb245b28b4';
34const QUICKPICK_API_URL = APP_WEBSITE . '/index.php?option=com_osmembership&task=api.get_active_plan_ids&api_key=';
35
36// URL where quickpick-releases.json lives
37const QUICKPICK_JSON_URL = 'https://raw.githubusercontent.com/' . APP_GITHUB_USER . '/' . APP_GITHUB_REPO . '/main/core/resources/quickpick-releases.json';
38
39// GitHub API proxy. Authentication for GitHub requests is handled server-side
40// (the real PAT is held by the proxy at bearsampp.com and never ships with the
41// client). The proxy key below is a PUBLIC shared identifier baked into an
42// open-source (GPL-3) build - it only gates proxy usage/rate limits and must
43// never be treated as a credential. All GitHub-hosted traffic is routed here.
44const APP_GITHUB_PROXY_URL = APP_WEBSITE . '/proxy.php';
45const APP_GITHUB_PROXY_KEY = '050390e9727be9a24566d641d17a16fdfafb639b14db443e70718f9334851154';
46
47// CRITICAL: Check for elevation IMMEDIATELY - must be FAST to minimize console window visibility
48if (isset($_SERVER['argv']) && isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] === 'startup') {
49 $flagFile = sys_get_temp_dir() . '/bearsampp_no_admin.lock';
50
51 // Quick exit if we already determined no admin recently
52 if (file_exists($flagFile) && (time() - filemtime($flagFile)) < 10) {
53 $currentPid = getmypid();
54 $killCmd = 'powershell.exe -WindowStyle Hidden -Command "Stop-Process -Id ' . (int)$currentPid . ' -Force -ErrorAction SilentlyContinue; Stop-Process -Name bearsampp -Force -ErrorAction SilentlyContinue"';
55 try {
56 // WScript.Shell.Run with style=0 (hidden) avoids cmd.exe flash that popen causes
57 $wshKill = new COM('WScript.Shell');
58 $wshKill->Run($killCmd, 0, false);
59 } catch (Exception $e) {
60 pclose(popen($killCmd, 'r'));
61 }
62 exit(1);
63 }
64
65 // FAST elevation check - use WScript.Shell.Run with hidden window (style=0) to avoid console flash
66 $isElevated = false;
67 try {
68 $wsh = new COM('WScript.Shell');
69 // intWindowStyle=0 = completely hidden (no window, no taskbar entry), bWaitOnReturn=true
70 // net session exits 0 when elevated, non-zero when access denied
71 $exitCode = $wsh->Run('net session', 0, true);
72 $isElevated = ($exitCode === 0);
73 } catch (Exception $e) {
74 // COM unavailable — fall back to shell_exec (may flash briefly)
75 $netOutput = @shell_exec('net session 2>&1');
76 if ($netOutput !== null) {
77 if (stripos($netOutput, 'Access is denied') === false &&
78 stripos($netOutput, 'System error 5') === false &&
79 $netOutput !== '') {
80 $isElevated = true;
81 }
82 }
83 }
84
85 if (!$isElevated) {
86 // Create flag file immediately
87 @file_put_contents($flagFile, time());
88
89 // Load language file for error message
90 $langFile = dirname(__FILE__) . '/langs/english.lang';
91 $langData = @parse_ini_file($langFile);
92
93 // Get localized messages
94 $title = isset($langData['errorAdminRequiredTitle']) ? $langData['errorAdminRequiredTitle'] : 'Administrator Rights Required';
95 $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.';
96
97 // Replace placeholders
98 $messageText = sprintf($messageText, APP_TITLE);
99 $messageText = str_replace('@nl@', '|||NEWLINE|||', $messageText);
100
101 // Split by newline placeholder
102 $messageParts = explode('|||NEWLINE|||', $messageText);
103
104 // Create PowerShell script that handles everything (no window flashing)
105 $psFile = sys_get_temp_dir() . '/bearsampp_admin_error.ps1';
106 $flagFilePs = str_replace('/', '\\', $flagFile);
107 $psFilePs = str_replace('/', '\\', $psFile);
108
109 // Escape for PowerShell
110 $title = str_replace("'", "''", $title);
111 $currentPid = getmypid();
112
113 // PowerShell script that shows message FIRST, then kills processes
114 $psContent = "# Show error message using Windows Forms\n";
115 $psContent .= "Add-Type -AssemblyName System.Windows.Forms\n";
116
117 // Build message from parts
118 $psContent .= "\$messageParts = @(\n";
119 $lastIndex = count($messageParts) - 1;
120 foreach ($messageParts as $index => $part) {
121 $part = str_replace("'", "''", trim($part));
122 // Don't add comma after last item
123 $comma = ($index < $lastIndex) ? ',' : '';
124 $psContent .= " '" . $part . "'" . $comma . "\n";
125 }
126 $psContent .= ")\n";
127 $psContent .= "\$message = \$messageParts -join [Environment]::NewLine\n";
128 $psContent .= "[System.Windows.Forms.MessageBox]::Show(\$message, '" . $title . "', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error) | Out-Null\n";
129 $psContent .= "\n";
130 $psContent .= "# After user clicks OK, kill only Bearsampp-related processes\n";
131 $psContent .= "Stop-Process -Id " . (int)$currentPid . " -Force -ErrorAction SilentlyContinue\n";
132 $psContent .= "Stop-Process -Name bearsampp -Force -ErrorAction SilentlyContinue\n";
133 $psContent .= "\n";
134 $psContent .= "# Clean up\n";
135 $psContent .= "Remove-Item -Path '" . $flagFilePs . "' -Force -ErrorAction SilentlyContinue\n";
136 $psContent .= "Remove-Item -Path '" . $psFilePs . "' -Force -ErrorAction SilentlyContinue\n";
137
138 @file_put_contents($psFile, $psContent);
139
140 // Launch PowerShell to show the error message — use COM Run(style=0) to avoid cmd.exe flash
141 if (isset($wsh)) {
142 $wsh->Run('powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File "' . $psFile . '"', 0, false);
143 } else {
144 pclose(popen('start "" powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File "' . $psFile . '"', 'r'));
145 }
146
147 // Exit immediately - PowerShell will handle showing the message and cleanup
148 exit(1);
149 } else {
150 // We're elevated, clean up any old flag
151 @unlink($flagFile);
152 }
153}
154
159require_once dirname(__FILE__) . '/classes/class.path.php';
160require_once dirname(__FILE__) . '/classes/class.root.php';
161$bearsamppRoot = new Root(dirname(__FILE__));
162$bearsamppRoot->register();
163
174$bearsamppCacert = Path::getPhpPath() . '/extras/ssl/cacert.pem';
175if (is_file($bearsamppCacert)) {
176 stream_context_set_default(array(
177 'ssl' => array(
178 'verify_peer' => true,
179 'verify_peer_name' => true,
180 'allow_self_signed' => false,
181 'cafile' => $bearsamppCacert,
182 )
183 ));
184}
185
190$bearsamppAction->process();
191
196if ($bearsamppRoot->isRoot()) {
197 $currentAction = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
198 if ($currentAction !== Action::LOADING && $currentAction !== Action::STARTUP) {
199 Log::debug('root.php: script ending, calling Util::stopLoading() for action: ' . $currentAction);
201 }
202}
203
208$locale = $bearsamppLang->getValue('locale');
global $bearsamppLang
global $bearsamppRoot
const LOADING
const STARTUP
static debug($data, $file=null)
static getPhpPath($aetrayPath=false)
static stopLoading()
$bearsamppCacert
Definition root.php:174
const QUICKPICK_JSON_URL
Definition root.php:37
const APP_GITHUB_USERAGENT
Definition root.php:25
if(is_file($bearsamppCacert)) $bearsamppAction
Definition root.php:189
const APP_GITHUB_PROXY_URL
Definition root.php:44
const APP_AUTHOR_NAME
Definition root.php:18
const APP_WEBSITE
Definition root.php:20
$locale
Definition root.php:208
const APP_GITHUB_USER
Definition root.php:23
const APP_GITHUB_REPO
Definition root.php:24
const QUICKPICK_API_URL
Definition root.php:34
const APP_LICENSE
Definition root.php:22
const APP_GITHUB_PROXY_KEY
Definition root.php:45
const APP_GITHUB_LATEST_URL
Definition root.php:26
const QUICKPICK_API_KEY
Definition root.php:33
const RETURN_TAB
Definition root.php:27
const APP_LOCALHOST
Definition root.php:21
const APP_TITLE
Definition root.php:19