122 'windows_misses' => 0
135 if (isset($_SERVER[
'argv'])) {
136 if ($type ==
'text') {
137 return (isset($_SERVER[
'argv'][$name]) && !empty($_SERVER[
'argv'][$name])) ? trim($_SERVER[
'argv'][$name]) :
'';
138 } elseif ($type ==
'numeric') {
139 return (isset($_SERVER[
'argv'][$name]) && is_numeric($_SERVER[
'argv'][$name])) ? intval($_SERVER[
'argv'][$name]) :
'';
140 } elseif ($type ==
'boolean') {
141 return (isset($_SERVER[
'argv'][$name])) ? true :
false;
142 } elseif ($type ==
'array') {
143 return (isset($_SERVER[
'argv'][$name]) && is_array($_SERVER[
'argv'][$name])) ? $_SERVER[
'argv'][$name] : array();
160 if (is_string($name)) {
161 if ($type ==
'text') {
162 $value = (isset($_GET[$name]) && !empty($_GET[$name])) ? stripslashes($_GET[$name]) :
'';
164 return filter_var($value, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
165 } elseif ($type ==
'numeric') {
166 return (isset($_GET[$name]) && is_numeric($_GET[$name])) ? intval($_GET[$name]) :
'';
167 } elseif ($type ==
'boolean') {
168 return (isset($_GET[$name])) ? true :
false;
169 } elseif ($type ==
'array') {
170 return (isset($_GET[$name]) && is_array($_GET[$name])) ? $_GET[$name] : array();
187 if (is_string($name)) {
188 if ($type ==
'text') {
189 return (isset($_POST[$name]) && !empty($_POST[$name])) ? stripslashes(trim($_POST[$name])) :
'';
190 } elseif ($type ==
'number') {
191 return (isset($_POST[$name]) && is_numeric($_POST[$name])) ? intval($_POST[$name]) :
'';
192 } elseif ($type ==
'float') {
193 return (isset($_POST[$name]) && is_numeric($_POST[$name])) ? floatval($_POST[$name]) :
'';
194 } elseif ($type ==
'boolean') {
195 return (isset($_POST[$name])) ? true :
false;
196 } elseif ($type ==
'array') {
197 return (isset($_POST[$name]) && is_array($_POST[$name])) ? $_POST[$name] : array();
198 } elseif ($type ==
'content') {
199 return (isset($_POST[$name]) && !empty($_POST[$name])) ? trim($_POST[$name]) :
'';
216 $sanitized = preg_replace(
'/[^0-9]/',
'', (
string)$pid);
218 if (empty($sanitized)) {
223 $pidInt = (int)$sanitized;
226 if ($pidInt <= 0 || $pidInt > 2147483647) {
243 $portStr = trim((
string)
$port);
246 if ($portStr ===
'' || !preg_match(
'/^\d+$/', $portStr)) {
251 $portInt = (int)$portStr;
254 if ($portInt < 1 || $portInt > 65535) {
271 if (!is_string($serviceName) || empty($serviceName)) {
277 $sanitized = preg_replace(
'/[^a-zA-Z0-9_-]/',
'', $serviceName);
279 if (empty($sanitized)) {
280 self::logWarning(
'Service name became empty after sanitization: ' . $serviceName);
285 if (strlen($sanitized) > 256) {
286 $sanitized = substr($sanitized, 0, 256);
301 if (!is_string($path) || empty($path)) {
306 $sanitized = str_replace(
"\0",
'', $path);
309 $pathWithoutEnvVars = preg_replace(
'/%[^%]+%/',
'', $sanitized);
310 if (strpos($pathWithoutEnvVars,
'..') !==
false) {
317 $sanitized = preg_replace(
'/[<>"|?*\x00-\x1F]/',
'', $sanitized);
331 if (!is_string($output)) {
336 $output = str_replace(
"\0",
'', $output);
339 return htmlspecialchars($output, ENT_QUOTES | ENT_HTML5,
'UTF-8');
352 if (!empty($string) && !empty($search)) {
353 $result = stripos($string, $search);
375 if ($string ===
null || $string ===
'') {
379 $length = strlen($search);
381 return (substr($string, 0, $length) === $search);
395 public static function endWith($string, $search)
397 $length = strlen($search);
398 $start = $length * -1;
400 return (substr($string, $start) === $search);
412 public static function random($length = 32, $withNumeric =
true)
414 $characters =
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
416 $characters .=
'0123456789';
419 $charactersLength = strlen($characters);
423 for ($i = 0; $i < $length; $i++) {
425 $randomIndex = random_int(0, $charactersLength - 1);
426 $randomString .= $characters[$randomIndex];
428 }
catch (Exception $e) {
429 self::logError(
'Failed to generate cryptographically secure random string: ' . $e->getMessage());
433 return $randomString;
448 return bin2hex(random_bytes($length));
449 }
catch (Exception $e) {
450 self::logError(
'Failed to generate secure token: ' . $e->getMessage());
467 return random_bytes($length);
468 }
catch (Exception $e) {
469 self::logError(
'Failed to generate secure bytes: ' . $e->getMessage());
485 foreach ($paths as $path) {
506 $handle = @opendir($path);
511 while (
false !== ($file = readdir($handle))) {
512 if ($file ==
'.' || $file ==
'..' || in_array($file, $exclude)) {
515 if (is_dir($path .
'/' . $file)) {
523 $r = @unlink($path .
'/' . $file);
547 if (substr($path, strlen($path) - 1, 1) !=
'/') {
550 $files = glob($path .
'*', GLOB_MARK);
551 foreach ($files as $file) {
570 private static function findFile($startPath, $findFile)
574 $handle = @opendir($startPath);
579 while (
false !== ($file = readdir($handle))) {
580 if ($file ==
'.' || $file ==
'..') {
583 if (is_dir($startPath .
'/' . $file)) {
588 } elseif ($file == $findFile) {
608 return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)
609 || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
634 '/^define\((.*?)' . $var .
'(.*?),/' =>
'define(\'' . $var .
'\',
' . (is_int($value) ? $value : '\
'' . $value .
'\'') .
');'
646 if (file_exists($path)) {
647 $lines = file($path);
648 $fp = fopen($path,
'w');
649 foreach ($lines as $nb => $line) {
650 $replaceDone =
false;
651 foreach ($replaceList as $regex => $replace) {
652 if (preg_match($regex, $line, $matches)) {
653 $countParams = preg_match_all(
'/{{(\d+)}}/', $replace, $paramsMatches);
654 if ($countParams > 0 && $countParams <= count($matches)) {
655 foreach ($paramsMatches[1] as $paramsMatch) {
656 $replace = str_replace(
'{{' . $paramsMatch .
'}}', $matches[$paramsMatch], $replace);
663 fwrite($fp, $replace . PHP_EOL);
688 $handle = @opendir($path);
693 while (
false !== ($file = readdir($handle))) {
694 $filePath = $path .
'/' . $file;
695 if ($file !=
'.' && $file !=
'..' && is_dir($filePath) && $file !=
'current') {
696 $result[] = str_replace(basename($path),
'', $file);
713 list($usec, $sec) = explode(
' ', microtime());
715 return ((
float)$usec + (
float)$sec);
720 global $bearsamppRegistry;
723 $value = $bearsamppRegistry->getValue(
733 $value .=
$bearsamppBins->getApache()->getSymlinkPath() .
'/bin;';
739 $value .=
$bearsamppBins->getPhp()->getSymlinkPath() .
'/imagick;';
744 if ($bearsamppTools->getComposer()->isEnable()) {
745 $value .= $bearsamppTools->getComposer()->getSymlinkPath() .
';';
746 $value .= $bearsamppTools->getComposer()->getSymlinkPath() .
'/vendor/bin;';
748 if ($bearsamppTools->getGhostscript()->isEnable()) {
749 $value .= $bearsamppTools->getGhostscript()->getSymlinkPath() .
'/bin;';
751 if ($bearsamppTools->getGit()->isEnable()) {
752 $value .= $bearsamppTools->getGit()->getSymlinkPath() .
'/bin;';
754 if ($bearsamppTools->getNgrok()->isEnable()) {
755 $value .= $bearsamppTools->getNgrok()->getSymlinkPath() .
';';
757 if ($bearsamppTools->getPerl()->isEnable()) {
758 $value .= $bearsamppTools->getPerl()->getSymlinkPath() .
'/perl/site/bin;';
759 $value .= $bearsamppTools->getPerl()->getSymlinkPath() .
'/perl/bin;';
760 $value .= $bearsamppTools->getPerl()->getSymlinkPath() .
'/c/bin;';
762 if ($bearsamppTools->getPython()->isEnable()) {
763 $value .= $bearsamppTools->getPython()->getSymlinkPath() .
'/bin;';
765 if ($bearsamppTools->getRuby()->isEnable()) {
766 $value .= $bearsamppTools->getRuby()->getSymlinkPath() .
'/bin;';
784 global $bearsamppRegistry;
786 return $bearsamppRegistry->setStringValue(
801 global $bearsamppRegistry;
803 return $bearsamppRegistry->getValue(
819 global $bearsamppRegistry;
821 return $bearsamppRegistry->setStringValue(
836 global $bearsamppRegistry;
838 return $bearsamppRegistry->getValue(
854 global $bearsamppRegistry;
856 return $bearsamppRegistry->setExpandStringValue(
871 global $bearsamppRegistry;
873 return $bearsamppRegistry->getValue(
897 return file_exists(self::getStartupLnkPath());
920 if (file_exists($startupLnkPath)) {
921 return @unlink($startupLnkPath);
936 private static function log($data, $type, $file =
null)
942 error_log(
'[' . $type .
'] ' . $data);
947 if (!self::$shutdownRegistered) {
948 register_shutdown_function([__CLASS__,
'flushLogBuffer']);
949 self::$shutdownRegistered =
true;
976 self::$logBuffer[] = [
982 self::$logStats[
'buffered']++;
985 if (count(self::$logBuffer) >= self::$logBufferSize || $type == self::LOG_ERROR) {
999 if (empty(self::$logBuffer)) {
1007 foreach (self::$logBuffer as $log) {
1008 if (!isset($logsByFile[$log[
'file']])) {
1009 $logsByFile[$log[
'file']] = [];
1011 $logsByFile[$log[
'file']][] = $log;
1015 foreach ($logsByFile as $file => $logs) {
1017 foreach ($logs as $log) {
1018 $content .=
'[' . date(
'Y-m-d H:i:s', $log[
'time']) .
'] # ' .
1020 $log[
'type'] .
': ' . $log[
'data'] . PHP_EOL;
1024 @file_put_contents($file, $content, FILE_APPEND | LOCK_EX);
1025 self::$logStats[
'writes']++;
1028 self::$logStats[
'flushed'] += count(self::$logBuffer);
1029 self::$logBuffer = [];
1040 return self::$logStats;
1052 if ($size > 0 && $size <= 1000) {
1053 self::$logBufferSize = $size;
1064 return self::$logBufferSize;
1088 $separator =
'========================================================================================' . PHP_EOL;
1089 foreach ($logs as $log) {
1090 if (!file_exists($log)) {
1093 $logContent = @file_get_contents($log);
1094 if ($logContent !==
false && !self::endWith($logContent, $separator)) {
1095 file_put_contents($log, $separator, FILE_APPEND);
1109 self::log($data, self::LOG_TRACE, $file);
1121 self::log($data, self::LOG_DEBUG, $file);
1131 public static function logInfo($data, $file =
null)
1133 self::log($data, self::LOG_INFO, $file);
1145 self::log($data, self::LOG_WARNING, $file);
1157 self::log($data, self::LOG_ERROR, $file);
1187 if (is_dir(
'C:\Windows\System32\WindowsPowerShell')) {
1188 return self::findFile(
'C:\Windows\System32\WindowsPowerShell',
'powershell.exe');
1204 public static function findRepos($initPath, $startPath, $checkFile, $maxDepth = 1)
1206 $depth = substr_count(str_replace($initPath,
'', $startPath),
'/');
1209 $handle = @opendir($startPath);
1214 while (
false !== ($file = readdir($handle))) {
1215 if ($file ==
'.' || $file ==
'..') {
1218 if (is_dir($startPath .
'/' . $file) && ($initPath == $startPath || $depth <= $maxDepth)) {
1219 $tmpResults =
self::findRepos($initPath, $startPath .
'/' . $file, $checkFile, $maxDepth);
1220 foreach ($tmpResults as $tmpResult) {
1223 } elseif (is_file($startPath .
'/' . $checkFile) && !in_array($startPath,
$result)) {
1252 $cacheKey =
'w_' . $path;
1253 if (isset(self::$pathFormatCache[$cacheKey])) {
1254 self::$pathFormatStats[
'windows_hits']++;
1255 return self::$pathFormatCache[$cacheKey];
1258 self::$pathFormatStats[
'windows_misses']++;
1261 $result = str_replace(
'/',
'\\', $path);
1264 if (count(self::$pathFormatCache) < self::$pathFormatCacheMaxSize) {
1265 self::$pathFormatCache[$cacheKey] =
$result;
1268 $removeCount = (int)(self::$pathFormatCacheMaxSize * 0.1);
1269 self::$pathFormatCache = array_slice(self::$pathFormatCache, $removeCount,
null,
true);
1270 self::$pathFormatCache[$cacheKey] =
$result;
1295 $cacheKey =
'u_' . $path;
1296 if (isset(self::$pathFormatCache[$cacheKey])) {
1297 self::$pathFormatStats[
'unix_hits']++;
1298 return self::$pathFormatCache[$cacheKey];
1301 self::$pathFormatStats[
'unix_misses']++;
1304 $result = str_replace(
'\\',
'/', $path);
1307 if (count(self::$pathFormatCache) < self::$pathFormatCacheMaxSize) {
1308 self::$pathFormatCache[$cacheKey] =
$result;
1311 $removeCount = (int)(self::$pathFormatCacheMaxSize * 0.1);
1312 self::$pathFormatCache = array_slice(self::$pathFormatCache, $removeCount,
null,
true);
1313 self::$pathFormatCache[$cacheKey] =
$result;
1327 return self::$pathFormatStats;
1338 self::$pathFormatCache = [];
1339 self::$pathFormatStats = [
1342 'windows_hits' => 0,
1343 'windows_misses' => 0
1354 return count(self::$pathFormatCache);
1366 $type = pathinfo($path, PATHINFO_EXTENSION);
1367 $data = file_get_contents($path);
1369 return 'data:image/' . $type .
';base64,' . base64_encode($data);
1381 return iconv(
'UTF-8',
'WINDOWS-1252//IGNORE', $data);
1393 return iconv(
'WINDOWS-1252',
'UTF-8//IGNORE', $data);
1425 foreach ($pids as $pid) {
1445 $statusFile =
$bearsamppCore->getTmpPath() .
'/loading_status.txt';
1446 file_put_contents($statusFile, json_encode([
'text' => $text]));
1456 $statusFile =
$bearsamppCore->getTmpPath() .
'/loading_status.txt';
1457 if (file_exists($statusFile)) {
1458 @unlink($statusFile);
1472 public static function getFilesToScan($path =
null, $useCache =
true, $forceRefresh =
false)
1475 $cacheKey = md5(serialize($path));
1478 if ($useCache && !$forceRefresh) {
1480 if ($cachedResult !==
false) {
1481 self::$fileScanStats[
'hits']++;
1482 self::logDebug(
'File scan cache HIT (saved expensive scan operation)');
1483 return $cachedResult;
1487 self::$fileScanStats[
'misses']++;
1495 foreach ($pathsToScan as $pathToScan) {
1497 $findFiles =
self::findFiles($pathToScan[
'path'], $pathToScan[
'includes'], $pathToScan[
'recursive']);
1498 foreach ($findFiles as $findFile) {
1501 self::logDebug($pathToScan[
'path'] .
' scanned in ' . round(self::getMicrotime() - $pathStartTime, 3) .
's');
1504 $totalTime = round(self::getMicrotime() - $startTime, 3);
1505 self::logInfo(
'Full file scan completed in ' . $totalTime .
's (' . count(
$result) .
' files found)');
1528 if (self::$fileScanCache !==
null && isset(self::$fileScanCache[$cacheKey])) {
1529 $cache = self::$fileScanCache[$cacheKey];
1532 if (time() - $cache[
'timestamp'] < self::$fileScanCacheDuration) {
1533 return $cache[
'data'];
1535 self::$fileScanStats[
'invalidations']++;
1536 unset(self::$fileScanCache[$cacheKey]);
1545 $cacheFile =
$bearsamppRoot->getTmpPath() .
'/filescan_cache_' . $cacheKey .
'.dat';
1547 if (file_exists($cacheFile)) {
1548 $fileContents = @file_get_contents($cacheFile);
1550 if ($fileContents ===
false) {
1555 if (!self::verifyCacheIntegrity($fileContents, $cacheKey)) {
1556 self::logWarning(
'File scan cache integrity check failed for key: ' . $cacheKey .
'. Possible tampering detected.');
1557 @unlink($cacheFile);
1561 $cacheData = @unserialize($fileContents);
1563 if ($cacheData !==
false && isset($cacheData[
'timestamp']) && isset($cacheData[
'data']) && isset($cacheData[
'hmac'])) {
1565 if (time() - $cacheData[
'timestamp'] < self::$fileScanCacheDuration) {
1567 if (self::$fileScanCache ===
null) {
1568 self::$fileScanCache = [];
1570 self::$fileScanCache[$cacheKey] = $cacheData;
1572 return $cacheData[
'data'];
1575 self::$fileScanStats[
'invalidations']++;
1576 @unlink($cacheFile);
1580 self::logWarning(
'Invalid cache structure detected for key: ' . $cacheKey);
1581 @unlink($cacheFile);
1604 'timestamp' => time(),
1610 if (self::$fileScanCache ===
null) {
1611 self::$fileScanCache = [];
1613 self::$fileScanCache[$cacheKey] = $cacheData;
1617 $cacheFile =
$bearsamppRoot->getTmpPath() .
'/filescan_cache_' . $cacheKey .
'.dat';
1618 @file_put_contents($cacheFile, serialize($cacheData), LOCK_EX);
1631 if (self::$cacheIntegrityKey ===
null) {
1636 $keyFile =
$bearsamppRoot->getTmpPath() .
'/cache_integrity.key';
1638 if (file_exists($keyFile)) {
1639 $key = @file_get_contents($keyFile);
1640 if ($key !==
false && strlen($key) === 64) {
1641 self::$cacheIntegrityKey = $key;
1642 return self::$cacheIntegrityKey;
1648 self::$cacheIntegrityKey = bin2hex(random_bytes(32));
1649 @file_put_contents($keyFile, self::$cacheIntegrityKey, LOCK_EX);
1650 }
catch (Exception $e) {
1651 self::logError(
'Failed to generate cache integrity key: ' . $e->getMessage());
1653 self::$cacheIntegrityKey = hash(
'sha256', uniqid(
'bearsampp_cache_',
true));
1658 self::$cacheIntegrityKey = bin2hex(random_bytes(32));
1659 }
catch (Exception $e) {
1660 self::$cacheIntegrityKey = hash(
'sha256', uniqid(
'bearsampp_cache_',
true));
1665 return self::$cacheIntegrityKey;
1679 $message = serialize($data) . $cacheKey;
1680 return hash_hmac(
'sha256', $message, $key);
1693 $cacheData = @unserialize($fileContents);
1695 if ($cacheData ===
false || !isset($cacheData[
'hmac']) || !isset($cacheData[
'data'])) {
1702 return hash_equals($expectedHmac, $cacheData[
'hmac']);
1715 self::$fileScanCache =
null;
1720 $cacheFiles = glob($tmpPath .
'/filescan_cache_*.dat');
1722 if ($cacheFiles !==
false) {
1723 foreach ($cacheFiles as $cacheFile) {
1724 @unlink($cacheFile);
1726 self::logInfo(
'Cleared ' . count($cacheFiles) .
' file scan cache files');
1731 self::$fileScanStats = [
1734 'invalidations' => 0
1745 return self::$fileScanStats;
1757 if ($seconds > 0 && $seconds <= 86400) {
1758 self::$fileScanCacheDuration = $seconds;
1759 self::logDebug(
'File scan cache duration set to ' . $seconds .
' seconds');
1770 return self::$fileScanCacheDuration;
1805 'includes' => array(
''),
1806 'recursive' =>
false
1812 'includes' => array(
''),
1813 'recursive' =>
false
1819 'includes' => array(
'openssl.cfg'),
1820 'recursive' =>
false
1826 'includes' => array(
'alias.conf'),
1827 'recursive' =>
false
1832 foreach ($folderList as $folder) {
1834 'path' =>
$bearsamppBins->getApache()->getRootPath() .
'/' . $folder,
1835 'includes' => array(
'.ini',
'.conf'),
1842 foreach ($folderList as $folder) {
1844 'path' =>
$bearsamppBins->getPhp()->getRootPath() .
'/' . $folder,
1845 'includes' => array(
'.php',
'.bat',
'.ini',
'.reg',
'.inc'),
1852 foreach ($folderList as $folder) {
1854 'path' =>
$bearsamppBins->getMysql()->getRootPath() .
'/' . $folder,
1855 'includes' => array(
'my.ini'),
1856 'recursive' =>
false
1862 foreach ($folderList as $folder) {
1864 'path' =>
$bearsamppBins->getMariadb()->getRootPath() .
'/' . $folder,
1865 'includes' => array(
'my.ini'),
1866 'recursive' =>
false
1872 foreach ($folderList as $folder) {
1874 'path' =>
$bearsamppBins->getPostgresql()->getRootPath() .
'/' . $folder,
1875 'includes' => array(
'.conf',
'.bat',
'.ber'),
1882 foreach ($folderList as $folder) {
1884 'path' =>
$bearsamppBins->getNodejs()->getRootPath() .
'/' . $folder .
'/etc',
1885 'includes' => array(
'npmrc'),
1889 'path' =>
$bearsamppBins->getNodejs()->getRootPath() .
'/' . $folder .
'/node_modules/npm',
1890 'includes' => array(
'npmrc'),
1891 'recursive' =>
false
1897 foreach ($folderList as $folder) {
1899 'path' => $bearsamppTools->getComposer()->getRootPath() .
'/' . $folder,
1900 'includes' => array(
'giscus.json'),
1901 'recursive' =>
false
1907 foreach ($folderList as $folder) {
1909 'path' => $bearsamppTools->getPowerShell()->getRootPath() .
'/' . $folder,
1910 'includes' => array(
'console.xml',
'.ini',
'.btm'),
1917 foreach ($folderList as $folder) {
1919 'path' => $bearsamppTools->getPython()->getRootPath() .
'/' . $folder .
'/bin',
1920 'includes' => array(
'.bat'),
1921 'recursive' =>
false
1924 'path' => $bearsamppTools->getPython()->getRootPath() .
'/' . $folder .
'/settings',
1925 'includes' => array(
'winpython.ini'),
1926 'recursive' =>
false
1932 foreach ($folderList as $folder) {
1934 'path' => $bearsamppTools->getRuby()->getRootPath() .
'/' . $folder .
'/bin',
1935 'includes' => array(
'!.dll',
'!.exe'),
1936 'recursive' =>
false
1952 private static function findFiles($startPath, $includes = array(
''), $recursive =
true)
1956 $handle = @opendir($startPath);
1961 while (
false !== ($file = readdir($handle))) {
1962 if ($file ==
'.' || $file ==
'..') {
1965 if (is_dir($startPath .
'/' . $file) && $recursive) {
1967 foreach ($tmpResults as $tmpResult) {
1970 } elseif (is_file($startPath .
'/' . $file)) {
1971 foreach ($includes as $include) {
1972 if (self::startWith($include,
'!')) {
1973 $include = ltrim($include,
'!');
1974 if (self::startWith($file,
'.') && !self::endWith($file, $include)) {
1976 } elseif ($file != $include) {
1979 } elseif (self::endWith($file, $include) || $file == $include || empty($include)) {
1999 public static function changePath($filesToScan, $rootPath =
null)
2004 'countChangedOcc' => 0,
2005 'countChangedFiles' => 0
2008 $rootPath = $rootPath !=
null ? $rootPath :
$bearsamppRoot->getRootPath();
2014 foreach ($filesToScan as $fileToScan) {
2015 $tmpCountChangedOcc = 0;
2016 $fileContentOr = file_get_contents($fileToScan);
2017 $fileContent = $fileContentOr;
2020 preg_match(
'#' . $unixOldPath .
'#i', $fileContent, $unixMatches);
2021 if (!empty($unixMatches)) {
2022 $fileContent = str_replace($unixOldPath, $unixCurrentPath, $fileContent, $countChanged);
2023 $tmpCountChangedOcc += $countChanged;
2025 preg_match(
'#' . str_replace(
'\\',
'\\\\', $windowsOldPath) .
'#i', $fileContent, $windowsMatches);
2026 if (!empty($windowsMatches)) {
2027 $fileContent = str_replace($windowsOldPath, $windowsCurrentPath, $fileContent, $countChanged);
2028 $tmpCountChangedOcc += $countChanged;
2033 if (!empty($unixMatches)) {
2035 $tmpCountChangedOcc += $countChanged;
2038 if (!empty($windowsMatches)) {
2040 $tmpCountChangedOcc += $countChanged;
2043 if ($fileContentOr != $fileContent) {
2044 $result[
'countChangedOcc'] += $tmpCountChangedOcc;
2045 $result[
'countChangedFiles'] += 1;
2046 file_put_contents($fileToScan, $fileContent);
2050 self::logDebug(
'changePath() completed: ' .
$result[
'countChangedFiles'] .
' files changed, ' .
$result[
'countChangedOcc'] .
' total occurrences');
2071 $resultArray = json_decode(
$result,
true);
2072 if (isset($resultArray[
'tag_name']) && isset($resultArray[
'assets'][0][
'browser_download_url'])) {
2073 $tagName = $resultArray[
'tag_name'];
2074 $downloadUrl = $resultArray[
'assets'][0][
'browser_download_url'];
2075 $name = $resultArray[
'name'];
2080 return [
'version' => $tagName,
'html_url' => $downloadUrl,
'name' => $name];
2110 public static function getWebsiteUrl($path =
'', $fragment =
'', $utmSource =
true)
2115 if (!empty($path)) {
2116 $url .=
'/' . ltrim($path,
'/');
2119 $url = rtrim($url,
'/') .
'/?utm_source=bearsampp-' .
$bearsamppCore->getAppVersion();
2121 if (!empty($fragment)) {
2152 $data = get_headers($url,
true);
2153 if (isset($data[
'Content-Length'])) {
2154 $size = intval($data[
'Content-Length']);
2170 if ((!$unit && $size >= 1 << 30) || $unit ==
'GB') {
2171 return number_format($size / (1 << 30), 2) .
'GB';
2173 if ((!$unit && $size >= 1 << 20) || $unit ==
'MB') {
2174 return number_format($size / (1 << 20), 2) .
'MB';
2176 if ((!$unit && $size >= 1 << 10) || $unit ==
'KB') {
2177 return number_format($size / (1 << 10), 2) .
'KB';
2180 return number_format($size) .
' bytes';
2204 if (function_exists(
'curl_version')) {
2211 $rebuildResult = array();
2215 $rebuildResult[] = $row;
2221 foreach (
$result as $header) {
2244 $context = stream_context_create(array(
2246 'verify_peer' =>
false,
2247 'verify_peer_name' =>
false,
2248 'allow_self_signed' =>
true,
2252 $fp = @fopen($url,
'r',
false, $context);
2254 $meta = stream_get_meta_data($fp);
2255 $result = isset($meta[
'wrapper_data']) ? $meta[
'wrapper_data'] :
$result;
2278 curl_setopt($ch, CURLOPT_RETURNTRANSFER,
true);
2279 curl_setopt($ch, CURLOPT_VERBOSE,
true);
2280 curl_setopt($ch, CURLOPT_HEADER,
true);
2281 curl_setopt($ch, CURLOPT_URL, $url);
2282 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
false);
2290 $responseHeaders = explode(
"\r\n\r\n",
$response, 2);
2291 if (!isset($responseHeaders[0]) || empty($responseHeaders[0])) {
2295 return explode(
"\n", $responseHeaders[0]);
2314 $context = stream_context_create(array(
2316 'verify_peer' =>
false,
2317 'verify_peer_name' =>
false,
2318 'allow_self_signed' =>
true,
2322 $fp = @stream_socket_client(($ssl ?
'ssl://' :
'') . $host .
':' .
$port, $errno, $errstr, 5, STREAM_CLIENT_CONNECT, $context);
2325 $result = explode(PHP_EOL, $out);
2330 $rebuildResult = array();
2334 $rebuildResult[] = $row;
2340 foreach (
$result as $header) {
2360 curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
2361 curl_setopt($ch, CURLOPT_RETURNTRANSFER,
true);
2362 curl_setopt($ch, CURLOPT_VERBOSE,
true);
2363 curl_setopt($ch, CURLOPT_URL, $url);
2364 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
false);
2365 curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
2366 $data = curl_exec($ch);
2367 if (curl_errno($ch)) {
2373 if (PHP_VERSION_ID < 80500) {
2390 $localIP =
'127.0.0.1';
2393 $errorReporting = error_reporting();
2398 $connection = @fsockopen($localIP,
$port);
2401 error_reporting($errorReporting);
2403 if (is_resource($connection)) {
2404 fclose($connection);
2407 return $process !=
null ? $process :
'N/A';
2422 return preg_match(
'/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i', $domainName)
2423 && preg_match(
'/^.{1,253}$/', $domainName)
2424 && preg_match(
'/^[^\.]{1,63}(\.[^\.]{1,63})*$/', $domainName);
2436 return ctype_alnum($string);
2453 if (method_exists($bin,
'initData')) {
2457 $name = $bin->getName();
2458 $service = $bin->getService();
2462 if ($isPortInUse ===
false) {
2463 if (!$service->isInstalled()) {
2465 if ($service->start()) {
2466 self::logInfo(sprintf(
'%s service successfully installed. (name: %s ; port: %s)', $name, $service->getName(),
$port));
2468 $bearsamppWinbinder->messageBoxInfo(
2477 $serviceErrorLog = sprintf(
'Error during the installation of %s service', $name);
2478 if (!empty($syntaxCheckCmd)) {
2479 $cmdSyntaxCheck = $bin->getCmdLineOutput($syntaxCheckCmd);
2480 if (!$cmdSyntaxCheck[
'syntaxOk']) {
2482 $serviceErrorLog .= sprintf(
' (conf errors detected : %s)', $cmdSyntaxCheck[
'content']);
2487 $bearsamppWinbinder->messageBoxError($serviceError, $boxTitle);
2493 $bearsamppWinbinder->messageBoxWarning(
2501 } elseif ($service->isRunning()) {
2502 self::logWarning(sprintf(
'%s service already installed and running', $name));
2504 $bearsamppWinbinder->messageBoxWarning(
2512 self::logError(sprintf(
'Port %s is used by an other application : %s',
$port, $isPortInUse));
2514 $bearsamppWinbinder->messageBoxError(
2540 if ($service->isInstalled()) {
2541 if ($service->delete()) {
2542 self::logInfo(sprintf(
'%s service successfully removed', $name));
2546 self::logError(sprintf(
'Error during the uninstallation of %s service', $name));
2566 public static function startService($bin, $syntaxCheckCmd, $showWindow =
false)
2570 if (method_exists($bin,
'initData')) {
2574 $name = $bin->getName();
2575 $service = $bin->getService();
2578 if (!$service->start()) {
2580 $serviceErrorLog = sprintf(
'Error while starting the %s service', $name);
2581 if (!empty($syntaxCheckCmd)) {
2582 $cmdSyntaxCheck = $bin->getCmdLineOutput($syntaxCheckCmd);
2583 if (!$cmdSyntaxCheck[
'syntaxOk']) {
2585 $serviceErrorLog .= sprintf(
' (conf errors detected : %s)', $cmdSyntaxCheck[
'content']);
2590 $bearsamppWinbinder->messageBoxError($serviceError, $boxTitle);
2608 $part = !empty($part) ?
'/' . $part :
null;
2622 $part = !empty($part) ?
'/' . $part :
null;
2636 $file = !empty($file) ?
'/' . $file :
null;
2652 $handle = @opendir($path);
2657 while (
false !== ($file = readdir($handle))) {
2658 $filePath = $path .
'/' . $file;
2659 if ($file !=
'.' && $file !=
'..' && is_dir($filePath) && $file !=
'current') {
2682 $nssmEnvPathsFile =
$bearsamppRoot->getRootPath() .
'/nssmEnvPaths.dat';
2684 if (is_file($nssmEnvPathsFile)) {
2685 $paths = explode(PHP_EOL, file_get_contents($nssmEnvPathsFile));
2686 foreach ($paths as $path) {
2687 $path = trim($path);
2688 if (stripos($path,
':') ===
false) {
2691 if (is_dir($path)) {
2718 if (!is_dir($folderPath)) {
2719 mkdir($folderPath, 0777,
true);
2723 file_put_contents($filepath, $content);
2725 $bearsamppWinbinder->exec(
$bearsamppConfig->getNotepad(),
'"' . $filepath .
'"');
2737 $stringfile =
$bearsamppCore->getResourcesPath() .
'/string.dat';
2738 $encryptedFile =
$bearsamppCore->getResourcesPath() .
'/github.dat';
2739 $method =
'AES-256-CBC';
2742 $stringPhrase = @file_get_contents($stringfile);
2743 if ($stringPhrase ===
false) {
2744 Util::logDebug(
"Failed to read the file at path: {$stringfile}");
2749 $stringKey = convert_uudecode($stringPhrase);
2752 $encryptedData = file_get_contents($encryptedFile);
2753 if ($encryptedData ===
false) {
2754 Util::logDebug(
"Failed to read the file at path: {$encryptedFile}");
2760 $data = base64_decode($encryptedData);
2761 if ($data ===
false) {
2762 Util::logDebug(
"Failed to decode the data from path: {$encryptedFile}");
2768 $ivLength = openssl_cipher_iv_length($method);
2769 $iv = substr($data, 0, $ivLength);
2770 $encrypted = substr($data, $ivLength);
2773 $decrypted = openssl_decrypt($encrypted, $method, $stringKey, 0, $iv);
2774 if ($decrypted ===
false) {
2775 Util::logDebug(
"Decryption failed for data from path: {$encryptedFile}");
2795 'Accept: application/vnd.github+json',
2796 'Authorization: Token ' . $Token,
2798 'X-GitHub-Api-Version: 2022-11-28'
2812 $connected = @fsockopen(
'www.google.com', 80);
static getProcessUsingPort($port)
const PATH_LIN_PLACEHOLDER
const PATH_WIN_PLACEHOLDER
const START_SERVICE_ERROR
const START_SERVICE_TITLE
const INSTALL_SERVICE_TITLE
const STARTUP_SERVICE_SYNTAX_ERROR
const SERVICE_INSTALL_ERROR
const SERVICE_ALREADY_INSTALLED
const PROCESSOR_REG_SUBKEY
const PROCESSOR_REG_ENTRY
static logError($data, $file=null)
static findRepos($initPath, $startPath, $checkFile, $maxDepth=1)
static setLogBufferSize($size)
static getPathFormatCacheSize()
static installService($bin, $port, $syntaxCheckCmd, $showWindow=false)
static getWebsiteUrlNoUtm($path='', $fragment='')
static clearPathFormatCache()
static disableLaunchStartup()
static getRemoteFilesize($url, $humanFileSize=true)
static getGithubUrl($part=null)
static deleteFolder($path)
static logInitClass($classInstance)
static getHeaders($host, $port, $ssl=false)
static removeService($service, $name)
static setFileScanCacheDuration($seconds)
static logTrace($data, $file=null)
static sanitizeServiceName($serviceName)
static isValidPort($port)
static cleanArgv($name, $type='text')
static cp1252ToUtf8($data)
static setAppPathRegKey($value)
static logInfo($data, $file=null)
static imgToBase64($path)
static contains($string, $search)
static getVersionList($path)
static getHttpHeaders($pingUrl)
static utf8ToCp1252($data)
static isValidDomainName($domainName)
static getLatestVersion($url)
static getFolderList($path)
static getAppBinsRegKey($fromRegistry=true)
static getAppPathRegKey()
static getGithubRawUrl($file)
static getChangelogUrl($utmSource=true)
static generateSecureToken($length=32)
static openFileContent($caption, $content)
static logDebug($data, $file=null)
static $cacheIntegrityKey
static isAlphanumeric($string)
static logReloadClass($classInstance)
static getCacheIntegrityKey()
static getFileScanStats()
static getFileScanCacheDuration()
static startWith($string, $search)
static getLogBufferSize()
static getGithubUserUrl($part=null)
static humanFileSize($size, $unit='')
static clearLoadingText()
static $fileScanCacheDuration
static clearFileScanCache()
static random($length=32, $withNumeric=true)
static endWith($string, $search)
static formatWindowsPath($path)
static changePath($filesToScan, $rootPath=null)
static getWebsiteUrl($path='', $fragment='', $utmSource=true)
static formatUnixPath($path)
static isPortInUse($port)
static cleanGetVar($name, $type='text')
static $pathFormatCacheMaxSize
static generateCacheHMAC($data, $cacheKey)
static $shutdownRegistered
static findFiles($startPath, $includes=array(''), $recursive=true)
static getFilesToScan($path=null, $useCache=true, $forceRefresh=false)
static replaceDefine($path, $var, $value)
static clearFolder($path, $exclude=array())
static sanitizeOutput($output)
static setupCurlHeaderWithToken()
static getPathFormatStats()
static setFileScanCache($cacheKey, $data)
static generateSecureBytes($length=32)
static clearFolders($paths, $exclude=array())
static getFopenHttpHeaders($url)
static startService($bin, $syntaxCheckCmd, $showWindow=false)
static sanitizePort($port)
static sanitizePath($path)
static cleanPostVar($name, $type='text')
static findFile($startPath, $findFile)
static getCurlHttpHeaders($url)
static getFileScanCache($cacheKey)
static log($data, $type, $file=null)
static updateLoadingText($text)
static enableLaunchStartup()
static getStartupLnkPath()
static setSysPathRegKey($value)
static replaceInFile($path, $replaceList)
static getSysPathRegKey()
static getPowerShellPath()
static getProcessorRegKey()
static checkInternetState()
static setAppBinsRegKey($value)
static logWarning($data, $file=null)
static verifyCacheIntegrity($fileContents, $cacheKey)
static createShortcut($savePath)
static getStartupPath($file=null)
const APP_GITHUB_USERAGENT