Bearsampp 2026.9.23
Loading...
Searching...
No Matches
class.bin.xlight.php
Go to the documentation of this file.
1<?php
2/*
3 *
4 * * Copyright (c) 2021-2026 Bearsampp
5 * * License: GNU General Public License version 3 or later; see LICENSE.txt
6 * * Website: https://bearsampp.com
7 * * Github: https://github.com/Bearsampp
8 *
9 */
10
17class BinXlight extends Module
18{
22 const SERVICE_NAME = 'bearsamppxlight';
26 const SERVICE_PARAMS = ' -startall';
27
31 const ROOT_CFG_ENABLE = 'xlightEnable';
35 const ROOT_CFG_VERSION = 'xlightVersion';
36
40 const LOCAL_CFG_EXE = 'xlightExe';
44 const LOCAL_CFG_SSL_PORT = 'xlightSslPort';
48 const LOCAL_CFG_PORT = 'xlightPort';
49
53 private $service;
57 private $log;
58
62 private $exe;
66 private $port;
70 private $SslPort;
71
78 public function __construct($id, $type)
79 {
80 Log::initClass($this);
81 $this->reload($id, $type);
82 }
83
90 public function reload($id = null, $type = null)
91 {
93 Log::reloadClass($this);
94
95 $this->name = $bearsamppLang->getValue(Lang::XLIGHT);
96 $this->version = $bearsamppConfig->getRaw(self::ROOT_CFG_VERSION);
97 parent::reload($id, $type);
98
99 $this->enable = $this->enable && $bearsamppConfig->getRaw(self::ROOT_CFG_ENABLE);
100 $this->service = new Win32Service(self::SERVICE_NAME);
101 $this->log = Path::getLogsPath() . '/xlight.log';
102
103 if ($this->bearsamppConfRaw !== false) {
104 $this->exe = $this->symlinkPath . '/' . $this->bearsamppConfRaw[self::LOCAL_CFG_EXE];
105 $this->SslPort = intval($this->bearsamppConfRaw[self::LOCAL_CFG_SSL_PORT]);
106 $this->port = intval($this->bearsamppConfRaw[self::LOCAL_CFG_PORT]);
107 }
108
109 if (!$this->enable) {
110 Log::info($this->name . ' is not enabled!');
111
112 return;
113 }
114 if (!is_dir($this->currentPath)) {
115 Log::error(sprintf($bearsamppLang->getValue(Lang::ERROR_FILE_NOT_FOUND), $this->name . ' ' . $this->version, $this->currentPath));
116
117 return;
118 }
119 if (!is_dir($this->symlinkPath)) {
120 Log::error(sprintf($bearsamppLang->getValue(Lang::ERROR_FILE_NOT_FOUND), $this->name . ' ' . $this->version, $this->symlinkPath));
121
122 return;
123 }
124 if (!is_file($this->bearsamppConf)) {
125 Log::error(sprintf($bearsamppLang->getValue(Lang::ERROR_CONF_NOT_FOUND), $this->name . ' ' . $this->version, $this->bearsamppConf));
126
127 return;
128 }
129 if (!is_file($this->exe)) {
130 Log::error(sprintf($bearsamppLang->getValue(Lang::ERROR_EXE_NOT_FOUND), $this->name . ' ' . $this->version, $this->exe));
131
132 return;
133 }
134 if (empty($this->SslPort)) {
135 Log::error(sprintf($bearsamppLang->getValue(Lang::ERROR_INVALID_PARAMETER), self::LOCAL_CFG_SSL_PORT, $this->SslPort));
136
137 return;
138 }
139 if (empty($this->port)) {
140 Log::error(sprintf($bearsamppLang->getValue(Lang::ERROR_INVALID_PARAMETER), self::LOCAL_CFG_PORT, $this->port));
141
142 return;
143 }
144
145 $nssm = new Nssm(self::SERVICE_NAME);
146 $nssm->setDisplayName(APP_TITLE . ' ' . $this->getName());
147 $nssm->setBinPath($this->exe);
148 $nssm->setParams(sprintf(self::SERVICE_PARAMS, $this->SslPort, $this->port));
149 $nssm->setStart(Nssm::SERVICE_DEMAND_START);
150 $nssm->setStdout(Path::getLogsPath() . '/xlight.log');
151 $nssm->setStderr(Path::getLogsPath() . '/xlight.error.log');
152
153 $this->service->setNssm($nssm);
154 }
155
161 protected function replaceAll($params)
162 {
163 $content = file_get_contents($this->bearsamppConf);
164
165 foreach ($params as $key => $value) {
166 $content = preg_replace('|' . $key . ' = .*|', $key . ' = ' . '"' . $value . '"', $content);
167 $this->bearsamppConfRaw[$key] = $value;
168 switch ($key) {
169 case self::LOCAL_CFG_SSL_PORT:
170 $this->SslPort = intval($value);
171 break;
172 case self::LOCAL_CFG_PORT:
173 $this->port = intval($value);
174 break;
175 }
176 }
177
178 file_put_contents($this->bearsamppConf, $content);
179
180 self::invalidateConfigCacheForPath($this->bearsamppConf);
181 }
182
188 public function rebuildConf()
189 {
190 global $bearsamppRegistry;
191
192 $exists = $bearsamppRegistry->exists(
194 'SYSTEM\CurrentControlSet\Services\\' . self::SERVICE_NAME . '\Parameters',
196 );
197 if ($exists) {
198 return $bearsamppRegistry->setExpandStringValue(
200 'SYSTEM\CurrentControlSet\Services\\' . self::SERVICE_NAME . '\Parameters',
202 sprintf(self::SERVICE_PARAMS, $this->SslPort, $this->port)
203 );
204 }
205
206 return false;
207 }
208
218 public function changePort($port, $checkUsed = false, $wbProgressBar = null)
219 {
220 global $bearsamppWinbinder;
221
222 if (!Util::isValidPort($port)) {
223 Log::error($this->getName() . ' port not valid: ' . $port);
224
225 return false;
226 }
227
228 $port = intval($port);
229 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
230
231 $isPortInUse = ServiceHelper::isPortInUse($port);
232 if (!$checkUsed || $isPortInUse === false) {
233 // bearsampp.conf
234 $this->setPort($port);
235 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
236
237 // conf
238 $this->update();
239 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
240
241 return true;
242 }
243
244 Log::debug($this->getName() . ' port in used: ' . $port . ' - ' . $isPortInUse);
245
246 return $isPortInUse;
247 }
248
257 public function checkPort($port, $showWindow = false)
258 {
259 global $bearsamppLang, $bearsamppWinbinder;
260 $boxTitle = sprintf($bearsamppLang->getValue(Lang::CHECK_PORT_TITLE), $this->getName(), $port);
261
262 if (!Util::isValidPort($port)) {
263 Log::error($this->getName() . ' port not valid: ' . $port);
264
265 return false;
266 }
267
269 if (!empty($headers)) {
270 if (UtilString::contains($headers[0], 'Xlight')) {
271 Log::debug($this->getName() . ' port ' . $port . ' is used by: ' . str_replace('220 ', '', $headers[0]));
272 if ($showWindow) {
273 $bearsamppWinbinder->messageBoxInfo(
274 sprintf($bearsamppLang->getValue(Lang::PORT_USED_BY), $port, str_replace('220 ', '', $headers[0])),
275 $boxTitle
276 );
277 }
278
279 return true;
280 }
281 Log::debug($this->getName() . ' port ' . $port . ' is used by another application');
282 if ($showWindow) {
283 $bearsamppWinbinder->messageBoxWarning(
284 sprintf($bearsamppLang->getValue(Lang::PORT_NOT_USED_BY), $port),
285 $boxTitle
286 );
287 }
288 } else {
289 Log::debug($this->getName() . ' port ' . $port . ' is not used');
290 if ($showWindow) {
291 $bearsamppWinbinder->messageBoxError(
292 sprintf($bearsamppLang->getValue(Lang::PORT_NOT_USED), $port),
293 $boxTitle
294 );
295 }
296 }
297
298 return false;
299 }
300
309 public function switchVersion($version, $showWindow = false)
310 {
311 Log::debug('Switch ' . $this->name . ' version to ' . $version);
312
313 return $this->updateConfig($version, 0, $showWindow);
314 }
315
325 protected function updateConfig($version = null, $sub = 0, $showWindow = false)
326 {
327 global $bearsamppLang, $bearsamppWinbinder;
328
329 if (!$this->enable) {
330 return true;
331 }
332
333 $version = $version == null ? $this->version : $version;
334 Log::debug(($sub > 0 ? str_repeat(' ', 2 * $sub) : '') . 'Update ' . $this->name . ' ' . $version . ' config');
335
336 $boxTitle = sprintf($bearsamppLang->getValue(Lang::SWITCH_VERSION_TITLE), $this->getName(), $version);
337
338 $bearsamppConf = str_replace('xlight' . $this->getVersion(), 'xlight' . $version, $this->bearsamppConf);
339 if (!file_exists($bearsamppConf)) {
340 Log::error('bearsampp config files not found for ' . $this->getName() . ' ' . $version);
341 if ($showWindow) {
342 $bearsamppWinbinder->messageBoxError(
343 sprintf($bearsamppLang->getValue(Lang::BEARSAMPP_CONF_NOT_FOUND_ERROR), $this->getName() . ' ' . $version),
344 $boxTitle
345 );
346 }
347
348 return false;
349 }
350
351 $bearsamppConfRaw = parse_ini_file($bearsamppConf);
352 if ($bearsamppConfRaw === false || !isset($bearsamppConfRaw[self::ROOT_CFG_VERSION]) || $bearsamppConfRaw[self::ROOT_CFG_VERSION] != $version) {
353 Log::error('bearsampp config file malformed for ' . $this->getName() . ' ' . $version);
354 if ($showWindow) {
355 $bearsamppWinbinder->messageBoxError(
356 sprintf($bearsamppLang->getValue(Lang::BEARSAMPP_CONF_MALFORMED_ERROR), $this->getName() . ' ' . $version),
357 $boxTitle
358 );
359 }
360
361 return false;
362 }
363
364 // bearsampp.conf
365 $this->setVersion($version);
366
367 return true;
368 }
369
375 public function setVersion($version)
376 {
377 global $bearsamppConfig;
378 $this->version = $version;
379 $bearsamppConfig->replace(self::ROOT_CFG_VERSION, $version);
380 $this->reload();
381 }
382
388 public function getService()
389 {
390 return $this->service;
391 }
392
399 public function setEnable($enabled, $showWindow = false)
400 {
401 global $bearsamppConfig, $bearsamppLang, $bearsamppWinbinder;
402
403 if ($enabled == Config::ENABLED && !is_dir($this->currentPath)) {
404 Log::debug($this->getName() . ' cannot be enabled because bundle ' . $this->getVersion() . ' does not exist in ' . $this->currentPath);
405 if ($showWindow) {
406 $bearsamppWinbinder->messageBoxError(
407 sprintf($bearsamppLang->getValue(Lang::ENABLE_BUNDLE_NOT_EXIST), $this->getName(), $this->getVersion(), $this->currentPath),
408 sprintf($bearsamppLang->getValue(Lang::ENABLE_TITLE), $this->getName())
409 );
410 }
411 $enabled = Config::DISABLED;
412 }
413
414 Log::info($this->getName() . ' switched to ' . ($enabled == Config::ENABLED ? 'enabled' : 'disabled'));
415 $this->enable = $enabled == Config::ENABLED;
416 $bearsamppConfig->replace(self::ROOT_CFG_ENABLE, $enabled);
417
418 $this->reload();
419 if ($this->enable) {
420 ServiceHelper::installService($this, $this->port, null, $showWindow);
421 } else {
422 ServiceHelper::removeService($this->service, $this->name);
423 }
424 }
425
431 public function getLog()
432 {
433 return $this->log;
434 }
435
441 public function getExe()
442 {
443 return $this->exe;
444 }
445
451 public function getUiPort()
452 {
453 return $this->SslPort;
454 }
455
461 public function setSslPort($SslPort)
462 {
463 $this->replace(self::LOCAL_CFG_SSL_PORT, $SslPort);
464 }
465
471 public function getPort()
472 {
473 return $this->port;
474 }
475
481 public function setPort($port)
482 {
483 $this->replace(self::LOCAL_CFG_PORT, $port);
484 }
485}
486
global $bearsamppLang
global $bearsamppRoot
replaceAll($params)
updateConfig($version=null, $sub=0, $showWindow=false)
const LOCAL_CFG_SSL_PORT
switchVersion($version, $showWindow=false)
const ROOT_CFG_ENABLE
setVersion($version)
checkPort($port, $showWindow=false)
changePort($port, $checkUsed=false, $wbProgressBar=null)
setEnable($enabled, $showWindow=false)
reload($id=null, $type=null)
const ROOT_CFG_VERSION
__construct($id, $type)
setSslPort($SslPort)
const DISABLED
const ENABLED
static getHeaders($host, $port, $ssl=false)
const ENABLE_BUNDLE_NOT_EXIST
const BEARSAMPP_CONF_MALFORMED_ERROR
const ERROR_EXE_NOT_FOUND
const ERROR_CONF_NOT_FOUND
const BEARSAMPP_CONF_NOT_FOUND_ERROR
const PORT_NOT_USED
const ERROR_INVALID_PARAMETER
const ENABLE_TITLE
const PORT_NOT_USED_BY
const XLIGHT
const SWITCH_VERSION_TITLE
const CHECK_PORT_TITLE
const PORT_USED_BY
const ERROR_FILE_NOT_FOUND
static info($data, $file=null)
static debug($data, $file=null)
static reloadClass($classInstance)
static error($data, $file=null)
static initClass($classInstance)
update($sub=0, $showWindow=false)
static invalidateConfigCacheForPath($sourcePath)
replace($key, $value)
const INFO_APP_PARAMETERS
const SERVICE_DEMAND_START
static getLogsPath($aetrayPath=false)
const HKEY_LOCAL_MACHINE
static installService($bin, $port, $syntaxCheckCmd, $showWindow=false)
static removeService($service, $name)
static isPortInUse($port)
static isValidPort($port)
static contains($string, $search)
global $bearsamppConfig
Definition homepage.php:46
const APP_LOCALHOST
Definition root.php:21
const APP_TITLE
Definition root.php:19