49 foreach ($paths as $path) {
70 $handle = @opendir($path);
75 while (
false !== ($file = readdir($handle))) {
76 if ($file ==
'.' || $file ==
'..' || in_array($file, $exclude)) {
79 if (is_dir($path .
'/' . $file)) {
87 $r = @unlink($path .
'/' . $file);
111 $path = rtrim($path,
'/\\') .
'/';
112 $files = glob($path .
'*', GLOB_MARK);
114 if ($files ===
false) {
115 Log::error(
"deleteFolder(): Failed to glob path: " . $path);
119 foreach ($files as $file) {
120 $normalizedFile = rtrim($file,
'/\\');
122 if (is_link($normalizedFile)) {
123 if (!@unlink($normalizedFile) && !@rmdir($normalizedFile)) {
124 Log::error(
"deleteFolder(): Failed to unlink symlink: " . $normalizedFile);
126 } elseif (is_dir($file)) {
129 if (!@unlink($normalizedFile)) {
130 Log::error(
"deleteFolder(): Failed to unlink file: " . $normalizedFile);
135 if (!@rmdir($path)) {
138 Log::error(
"deleteFolder(): Failed to remove directory: " . $path);
152 public static function findFile($startPath, $findFile)
156 $handle = @opendir($startPath);
161 while (
false !== ($file = readdir($handle))) {
162 if ($file ==
'.' || $file ==
'..') {
165 if (is_dir($startPath .
'/' . $file)) {
170 } elseif ($file == $findFile) {
190 return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)
191 || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
215 if (strtoupper(substr(PHP_OS, 0, 3)) !==
'WIN') {
217 if (function_exists(
'posix_geteuid')) {
218 return posix_geteuid() === 0;
227 if ($output !==
null) {
229 if (stripos($output,
'Access is denied') !==
false ||
230 stripos($output,
'System error 5') !==
false ||
231 stripos($output,
'Zugriff verweigert') !==
false) {
237 if (stripos($output,
'There are no entries') !==
false ||
238 stripos($output,
'These workstations') !==
false ||
239 preg_match(
'/\\\\\\\\/', $output)) {
246 if ($output !==
null && !empty($output)) {
248 if (stripos($output,
'S-1-16-12288') !==
false ||
249 stripos($output,
'S-1-5-32-544') !==
false) {
254 if (stripos($output,
'S-1-16-8192') !==
false) {
261 $testFile = getenv(
'SystemRoot') .
'\\Temp\\bearsampp_admin_test_' . uniqid() .
'.tmp';
262 $result = @file_put_contents($testFile,
'test');
282 '/^define\((.*?)' . $var .
'(.*?),/' =>
'define(\'' . $var .
'\',
' . (is_int($value) ? $value : '\
'' . $value .
'\'') .
');'
294 if (file_exists($path)) {
295 $lines = file($path);
296 $fp = fopen($path,
'w');
297 foreach ($lines as $nb => $line) {
298 $replaceDone =
false;
299 foreach ($replaceList as $regex => $replace) {
300 if (preg_match($regex, $line, $matches)) {
301 $currentReplace = $replace;
302 $countParams = preg_match_all(
'/{{(\d+)}}/', $currentReplace, $paramsMatches);
303 if ($countParams > 0 && $countParams <= count($matches)) {
304 foreach ($paramsMatches[1] as $paramsMatch) {
305 $currentReplace = str_replace(
'{{' . $paramsMatch .
'}}', $matches[$paramsMatch], $currentReplace);
308 Log::trace(
'Replace in file ' . $path .
' :');
311 Log::trace(
'## new: ' . trim($currentReplace));
314 $ending = (preg_match(
"/\r\n$/", $line)) ?
"\r\n" : (preg_match(
"/\n$/", $line) ?
"\n" :
"");
315 fwrite($fp, rtrim($currentReplace) . $ending);
341 $handle = @opendir($path);
346 $prefix = basename($path);
348 while (
false !== ($file = readdir($handle))) {
349 $filePath = $path .
'/' . $file;
350 if ($file !=
'.' && $file !=
'..' && is_dir($filePath) && $file !=
'current') {
351 if (strpos($file, $prefix) === 0) {
352 $version = substr($file, strlen($prefix));
373 list($usec, $sec) = explode(
' ', microtime());
375 return ((
float)$usec + (
float)$sec);
388 return $lnk ? file_exists($lnk) :
false;
401 if (!$shortcutPath) {
423 if (file_exists($startupLnkPath)) {
424 return @unlink($startupLnkPath);
442 public static function findRepos($initPath, $startPath, $checkFile, $maxDepth = 1)
444 $depth = substr_count(str_replace($initPath,
'', $startPath),
'/');
447 $handle = @opendir($startPath);
452 while (
false !== ($file = readdir($handle))) {
453 if ($file ==
'.' || $file ==
'..') {
456 if (is_dir($startPath .
'/' . $file) && ($initPath == $startPath || $depth <= $maxDepth)) {
457 $tmpResults =
self::findRepos($initPath, $startPath .
'/' . $file, $checkFile, $maxDepth);
458 foreach ($tmpResults as $tmpResult) {
461 } elseif (is_file($startPath .
'/' . $checkFile) && !in_array($startPath,
$result)) {
480 $type = pathinfo($path, PATHINFO_EXTENSION);
481 $data = file_get_contents($path);
483 return 'data:image/' . $type .
';base64,' . base64_encode($data);
496 if ($direction ===
'to_utf8') {
512 return iconv(
'UTF-8',
'WINDOWS-1252//IGNORE', $data);
524 return iconv(
'WINDOWS-1252',
'UTF-8//IGNORE', $data);
555 foreach ($pids as $pid) {
576 file_put_contents($statusFile, json_encode([
'text' => $text]));
587 if (file_exists($statusFile)) {
588 @unlink($statusFile);
602 public static function getFilesToScan($path =
null, $useCache =
true, $forceRefresh =
false)
605 $cacheKey = md5(serialize($path));
608 if ($useCache && !$forceRefresh) {
610 if ($cachedResult !==
false) {
612 Log::debug(
'File scan cache HIT (saved expensive scan operation)');
613 return $cachedResult;
618 Log::debug(
'File scan cache MISS (performing full scan)');
625 foreach ($pathsToScan as $pathToScan) {
627 $findFiles =
self::findFiles($pathToScan[
'path'], $pathToScan[
'includes'], $pathToScan[
'recursive']);
628 foreach ($findFiles as $findFile) {
631 Log::debug($pathToScan[
'path'] .
' scanned in ' . round(self::getMicrotime() - $pathStartTime, 3) .
's');
634 $totalTime = round(self::getMicrotime() - $startTime, 3);
635 Log::info(
'Full file scan completed in ' . $totalTime .
's (' . count(
$result) .
' files found)');
679 'includes' => array(
''),
686 'includes' => array(
''),
693 'includes' => array(
'openssl.cfg'),
700 'includes' => array(
'alias.conf'),
706 foreach ($folderList as $folder) {
709 'includes' => array(
'.ini',
'.conf'),
716 foreach ($folderList as $folder) {
719 'includes' => array(
'.php',
'.bat',
'.ini',
'.reg',
'.inc'),
726 foreach ($folderList as $folder) {
729 'includes' => array(
'my.ini'),
736 foreach ($folderList as $folder) {
739 'includes' => array(
'my.ini'),
744 if (is_dir($dataPath)) {
747 'includes' => array(
'my.ini'),
755 foreach ($folderList as $folder) {
758 'includes' => array(
'.conf',
'.bat',
'.ber'),
765 foreach ($folderList as $folder) {
768 'includes' => array(
'npmrc'),
773 'includes' => array(
'npmrc'),
780 foreach ($folderList as $folder) {
783 'includes' => array(
'giscus.json'),
790 foreach ($folderList as $folder) {
793 'includes' => array(
'console.xml',
'.ini',
'.btm'),
800 foreach ($folderList as $folder) {
803 'includes' => array(
'.bat'),
808 'includes' => array(
'winpython.ini'),
815 foreach ($folderList as $folder) {
818 'includes' => array(
'!.dll',
'!.exe'),
835 private static function findFiles($startPath, $includes = array(
''), $recursive =
true)
839 $handle = @opendir($startPath);
844 while (
false !== ($file = readdir($handle))) {
845 if ($file ==
'.' || $file ==
'..') {
848 if (is_dir($startPath .
'/' . $file) && $recursive) {
850 foreach ($tmpResults as $tmpResult) {
853 } elseif (is_file($startPath .
'/' . $file)) {
854 foreach ($includes as $include) {
856 $include = ltrim($include,
'!');
859 } elseif ($file != $include) {
891 $resultArray = json_decode(
$result,
true);
892 if (isset($resultArray[
'tag_name']) && isset($resultArray[
'assets'][0][
'browser_download_url'])) {
893 $tagName = $resultArray[
'tag_name'];
894 $downloadUrl = $resultArray[
'assets'][0][
'browser_download_url'];
895 $name = $resultArray[
'name'];
896 Log::debug(
'Latest version tag name: ' . $tagName);
900 return [
'version' => $tagName,
'html_url' => $downloadUrl,
'name' => $name];
902 Log::error(
'Tag name, download URL, or name not found in the response: ' .
$result);
917 public static function getWebsiteUrl($path =
'', $fragment =
'', $utmSource =
true)
923 $url .=
'/' . ltrim($path,
'/');
926 $url = rtrim($url,
'/') .
'/?utm_source=bearsampp-' .
$bearsamppCore->getAppVersion();
928 if (!empty($fragment)) {
960 $data = get_headers($url,
true);
961 if (isset($data[
'Content-Length'])) {
962 $size = intval($data[
'Content-Length']);
983 return match ($unit) {
984 'GB' => number_format($size / (1 << 30), 2) .
'GB',
985 'MB' => number_format($size / (1 << 20), 2) .
'MB',
986 'KB' => number_format($size / (1 << 10), 2) .
'KB',
987 default => number_format($size) .
' bytes',
992 return human_readable_size($size, precision: 2);
1002 global $bearsamppRegistry;
1003 $processor = $bearsamppRegistry->getProcessorRegKey();
1017 if (function_exists(
'curl_version')) {
1024 $rebuildResult = array();
1028 $rebuildResult[] = $row;
1034 foreach (
$result as $header) {
1057 $context = stream_context_create(array(
1059 'verify_peer' =>
false,
1060 'verify_peer_name' =>
false,
1061 'allow_self_signed' =>
true,
1065 $fp = @fopen($url,
'r',
false, $context);
1067 $meta = stream_get_meta_data($fp);
1068 $result = isset($meta[
'wrapper_data']) ? $meta[
'wrapper_data'] :
$result;
1091 curl_setopt($ch, CURLOPT_RETURNTRANSFER,
true);
1092 curl_setopt($ch, CURLOPT_VERBOSE,
true);
1093 curl_setopt($ch, CURLOPT_HEADER,
true);
1094 curl_setopt($ch, CURLOPT_URL, $url);
1095 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
false);
1103 $responseHeaders = explode(
"\r\n\r\n",
$response, 2);
1104 if (!isset($responseHeaders[0]) || empty($responseHeaders[0])) {
1108 return explode(
"\n", $responseHeaders[0]);
1127 $context = stream_context_create(array(
1129 'verify_peer' =>
false,
1130 'verify_peer_name' =>
false,
1131 'allow_self_signed' =>
true,
1135 $fp = @stream_socket_client(($ssl ?
'ssl://' :
'') . $host .
':' .
$port, $errno, $errstr, 5, STREAM_CLIENT_CONNECT, $context);
1138 $result = explode(PHP_EOL, $out);
1143 $rebuildResult = array();
1147 $rebuildResult[] = $row;
1153 foreach (
$result as $header) {
1173 curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
1174 curl_setopt($ch, CURLOPT_RETURNTRANSFER,
true);
1175 curl_setopt($ch, CURLOPT_VERBOSE,
true);
1176 curl_setopt($ch, CURLOPT_URL, $url);
1177 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
false);
1178 curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
1179 $data = curl_exec($ch);
1180 if (curl_errno($ch)) {
1181 Log::error(
'CURL Error: ' . curl_error($ch));
1186 if (PHP_VERSION_ID < 80500) {
1203 $localIP =
'127.0.0.1';
1206 $errorReporting = error_reporting();
1211 $connection = @fsockopen($localIP,
$port);
1214 error_reporting($errorReporting);
1216 if (is_resource($connection)) {
1217 fclose($connection);
1220 return $process !=
null ? $process :
'N/A';
1235 return filter_var($domainName, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) !==
false;
1252 if (method_exists($bin,
'initData')) {
1256 $name = $bin->getName();
1257 $service = $bin->getService();
1261 if ($isPortInUse ===
false) {
1262 if (!$service->isInstalled()) {
1264 if ($service->start()) {
1265 Log::info(sprintf(
'%s service successfully installed. (name: %s ; port: %s)', $name, $service->getName(),
$port));
1267 $bearsamppWinbinder->messageBoxInfo(
1276 $serviceErrorLog = sprintf(
'Error during the installation of %s service', $name);
1277 if (!empty($syntaxCheckCmd)) {
1278 $cmdSyntaxCheck = $bin->getCmdLineOutput($syntaxCheckCmd);
1279 if (!$cmdSyntaxCheck[
'syntaxOk']) {
1281 $serviceErrorLog .= sprintf(
' (conf errors detected : %s)', $cmdSyntaxCheck[
'content']);
1286 $bearsamppWinbinder->messageBoxError($serviceError, $boxTitle);
1290 Log::warning(sprintf(
'%s service already installed', $name));
1292 $bearsamppWinbinder->messageBoxWarning(
1300 } elseif ($service->isRunning()) {
1301 Log::warning(sprintf(
'%s service already installed and running', $name));
1303 $bearsamppWinbinder->messageBoxWarning(
1311 Log::error(sprintf(
'Port %s is used by an other application : %s',
$port, $isPortInUse));
1313 $bearsamppWinbinder->messageBoxError(
1334 Log::error(
'$service not an instance of Win32Service');
1339 if ($service->isInstalled()) {
1340 if ($service->delete()) {
1341 Log::info(sprintf(
'%s service successfully removed', $name));
1345 Log::error(sprintf(
'Error during the uninstallation of %s service', $name));
1350 Log::warning(sprintf(
'%s service does not exist', $name));
1365 public static function startService($bin, $syntaxCheckCmd, $showWindow =
false)
1369 if (method_exists($bin,
'initData')) {
1373 $name = $bin->getName();
1374 $service = $bin->getService();
1377 if (!$service->start()) {
1379 $serviceErrorLog = sprintf(
'Error while starting the %s service', $name);
1380 if (!empty($syntaxCheckCmd)) {
1381 $cmdSyntaxCheck = $bin->getCmdLineOutput($syntaxCheckCmd);
1382 if (!$cmdSyntaxCheck[
'syntaxOk']) {
1384 $serviceErrorLog .= sprintf(
' (conf errors detected : %s)', $cmdSyntaxCheck[
'content']);
1389 $bearsamppWinbinder->messageBoxError($serviceError, $boxTitle);
1409 if (empty($user) || !is_string($user)) {
1414 $user = rawurlencode($user);
1418 return "https://github.com/{$user}";
1421 if (empty($repo) || !is_string($repo)) {
1424 $repo = rawurlencode($repo);
1425 return "https://github.com/{$user}/{$repo}";
1428 if (empty($repo) || empty($branch) || empty($path) || !is_string($repo) || !is_string($branch) || !is_string($path)) {
1431 $repo = rawurlencode($repo);
1432 $branch = rawurlencode($branch);
1434 $path = ltrim($path,
'/');
1435 $segments = array_map(
'rawurlencode', explode(
'/', $path));
1436 $pathEncoded = implode(
'/', $segments);
1438 return "https://raw.githubusercontent.com/{$user}/{$repo}/{$branch}/{$pathEncoded}";
1465 $connected = @fsockopen(
'www.google.com', 80);
1486 $handle = @opendir($path);
1491 while (
false !== ($file = readdir($handle))) {
1492 $filePath = $path .
'/' . $file;
1493 if ($file !=
'.' && $file !=
'..' && is_dir($filePath) && $file !=
'current') {
1518 file_put_contents($tmpFile, $content);
1522 $bearsamppCore->getWinbinder()->exec($editor,
'"' . $tmpFile .
'"');
1535 'Accept: application/vnd.github.v3+json'
static getProcessUsingPort($port)
static set($cacheKey, $data)
static shellExec(string $command)
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
static info($data, $file=null)
static debug($data, $file=null)
static warning($data, $file=null)
static trace($data, $file=null)
static error($data, $file=null)
static getExeFilePath($aetrayPath=false)
static getAliasPath($aetrayPath=false)
static getRootPath($aetrayPath=false)
static getIconsPath($aetrayPath=false)
static getResourcesPath($aetrayPath=false)
static getVhostsPath($aetrayPath=false)
static getOpenSslPath($aetrayPath=false)
static formatUnixPath($path)
static getPhpExe($aetrayPath=false)
static getTmpPath($aetrayPath=false)
static getModuleRootPath($module)
static getStartupLnkPath()
static findRepos($initPath, $startPath, $checkFile, $maxDepth=1)
static installService($bin, $port, $syntaxCheckCmd, $showWindow=false)
static getWebsiteUrlNoUtm($path='', $fragment='')
static disableLaunchStartup()
static getRemoteFilesize($url, $humanFileSize=true)
static getGithubUrl($type='user', $user=APP_GITHUB_USER, $repo=null, $branch=null, $path=null)
static deleteFolder($path)
static getHeaders($host, $port, $ssl=false)
static removeService($service, $name)
static isValidPort($port)
static cp1252ToUtf8($data)
static imgToBase64($path)
static getVersionList($path)
static getHttpHeaders($pingUrl)
static utf8ToCp1252($data)
static isValidDomainName($domainName)
static getLatestVersion($url)
static getFolderList($path)
static getGithubUserUrl()
static humanFileSize(int $size, string $unit='')
static openFileContent($caption, $content)
static clearLoadingText()
static getWebsiteUrl($path='', $fragment='', $utmSource=true)
static isPortInUse($port)
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 setupCurlHeaderWithToken()
static convertEncoding($data, $direction='to_cp1252')
static clearFolders($paths, $exclude=array())
static getFopenHttpHeaders($url)
static startService($bin, $syntaxCheckCmd, $showWindow=false)
static findFile($startPath, $findFile)
static getCurlHttpHeaders($url)
static updateLoadingText($text)
static enableLaunchStartup()
static replaceInFile($path, $replaceList)
static checkInternetState()
static contains($string, $search)
static startWith($string, $search)
static endWith($string, $search)
static createShortcut($shortcutPath, $targetPath, $workingDir='', $description='', $iconPath='')
const APP_GITHUB_USERAGENT