74 $this->enable = $this->enable &&
$bearsamppConfig->getRaw(self::ROOT_CFG_ENABLE);
78 if ($this->bearsamppConfRaw !==
false) {
79 $this->exe = $this->symlinkPath .
'/' . $this->bearsamppConfRaw[self::LOCAL_CFG_EXE];
80 $this->conf = $this->symlinkPath .
'/' . $this->bearsamppConfRaw[self::LOCAL_CFG_CONF];
81 $this->port = $this->bearsamppConfRaw[self::LOCAL_CFG_PORT];
82 $this->rootUser = isset($this->bearsamppConfRaw[self::LOCAL_CFG_ROOT_USER]) ? $this->bearsamppConfRaw[self::LOCAL_CFG_ROOT_USER] :
'root';
83 $this->rootPwd = isset($this->bearsamppConfRaw[self::LOCAL_CFG_ROOT_PWD]) ? $this->bearsamppConfRaw[self::LOCAL_CFG_ROOT_PWD] :
'';
84 $this->cliExe = $this->symlinkPath .
'/' . $this->bearsamppConfRaw[self::LOCAL_CFG_CLI_EXE];
85 $this->admin = $this->symlinkPath .
'/' . $this->bearsamppConfRaw[self::LOCAL_CFG_ADMIN];
86 $this->dataDir = $this->symlinkPath .
'/data';
94 if (!is_dir($this->currentPath)) {
99 if (!is_dir($this->symlinkPath)) {
104 if (!is_file($this->bearsamppConf)) {
109 if (!is_file($this->exe)) {
114 if (!is_file($this->conf)) {
119 if (!is_numeric($this->port) || $this->port <= 0) {
124 if (empty($this->rootUser)) {
129 if (!is_file($this->cliExe)) {
134 if (!is_file($this->admin)) {
141 $this->service->setBinPath($this->exe);
142 $this->service->setParams(self::SERVICE_NAME);
154 $content = file_get_contents($this->bearsamppConf);
156 foreach ($params as $key => $value) {
157 $content = preg_replace(
'|' . $key .
' = .*|', $key .
' = ' .
'"' . $value .
'"', $content);
158 $this->bearsamppConfRaw[$key] = $value;
160 case self::LOCAL_CFG_PORT:
161 $this->port = $value;
163 case self::LOCAL_CFG_ROOT_USER:
164 $this->rootUser = $value;
166 case self::LOCAL_CFG_ROOT_PWD:
167 $this->rootPwd = $value;
172 file_put_contents($this->bearsamppConf, $content);
186 global $bearsamppWinbinder;
195 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
198 if (!$checkUsed || $isPortInUse ===
false) {
201 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
205 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
227 $startTime = microtime(
true);
236 $fp = @fsockopen(
'127.0.0.1',
$port, $errno, $errstr, $timeout);
240 $bearsamppWinbinder->messageBoxError(
250 static $cachedConnection =
null;
251 static $lastPort =
null;
253 if ($cachedConnection ===
null || $lastPort !==
$port) {
256 \PDO::ATTR_TIMEOUT => $timeout,
257 \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
258 \PDO::MYSQL_ATTR_INIT_COMMAND =>
"SET SESSION sql_mode=''"
261 $dsn =
'mysql:host=127.0.0.1;port=' .
$port;
262 $cachedConnection = new \PDO($dsn, $this->rootUser, $this->rootPwd, $options);
264 }
catch (\PDOException $e) {
267 $bearsamppWinbinder->messageBoxWarning(
278 $stmt = $cachedConnection->query(
"SELECT @@version, @@version_comment");
279 $row = $stmt->fetch(\PDO::FETCH_NUM);
292 $bearsamppWinbinder->messageBoxWarning(
302 $bearsamppWinbinder->messageBoxInfo(
308 $totalTime = round(microtime(
true) - $startTime, 2);
312 }
catch (\PDOException $e) {
315 $bearsamppWinbinder->messageBoxWarning(
335 global $bearsamppWinbinder;
336 $startTime = microtime(
true);
340 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
345 \PDO::ATTR_TIMEOUT => $timeout,
346 \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
350 $dbLink = new \PDO($dsn, $this->rootUser, $currentPwd, $options);
352 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
355 $stmt = $dbLink->query(
'SELECT VERSION()');
358 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
361 if (version_compare(
$version,
'5.7.6',
'>=')) {
363 $sql =
"ALTER USER '{$this->rootUser}'@'localhost' IDENTIFIED BY :password";
364 $stmt = $dbLink->prepare($sql);
365 $stmt->bindParam(
':password', $newPwd);
368 $sql =
"SET PASSWORD FOR '{$this->rootUser}'@'localhost' = PASSWORD(:password)";
369 $stmt = $dbLink->prepare($sql);
370 $stmt->bindParam(
':password', $newPwd);
373 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
376 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
377 $dbLink->query(
'FLUSH PRIVILEGES');
379 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
382 }
catch (\PDOException $e) {
383 $error = $e->getMessage();
386 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
388 if (!empty($error)) {
389 $totalTime = round(microtime(
true) - $startTime, 2);
390 Util::logTrace(
"MySQL password change failed in {$totalTime}s: " . $error);
396 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
401 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
403 $totalTime = round(microtime(
true) - $startTime, 2);
404 Util::logTrace(
"MySQL password change completed in {$totalTime}s");
419 global $bearsamppWinbinder;
420 $startTime = microtime(
true);
421 $currentPwd = $currentPwd ==
null ? $this->rootPwd : $currentPwd;
425 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
428 static $passwordCache = [];
429 $cacheKey = md5($this->rootUser .
':' . $currentPwd .
':' . $this->port);
431 if (isset($passwordCache[$cacheKey]) && (time() - $passwordCache[$cacheKey][
'time']) < 30) {
432 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
433 $totalTime = round(microtime(
true) - $startTime, 2);
434 Util::logTrace(
"MySQL password check completed from cache in {$totalTime}s");
435 return $passwordCache[$cacheKey][
'result'];
440 \PDO::ATTR_TIMEOUT => $timeout,
441 \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
442 \PDO::MYSQL_ATTR_INIT_COMMAND =>
"SET SESSION sql_mode=''"
446 $dbLink = new \PDO($dsn, $this->rootUser, $currentPwd, $options);
449 $dbLink->query(
'SELECT 1');
453 $passwordCache[$cacheKey] = [
458 }
catch (\PDOException $e) {
459 $error = $e->getMessage();
462 $passwordCache[$cacheKey] = [
464 'time' => time() - 25
468 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
470 if (!empty($error)) {
471 $totalTime = round(microtime(
true) - $startTime, 2);
472 Util::logTrace(
"MySQL password check failed in {$totalTime}s: " . $error);
476 $totalTime = round(microtime(
true) - $startTime, 2);
477 Util::logTrace(
"MySQL password check completed in {$totalTime}s");
509 if (!$this->enable) {
514 Util::logDebug(($sub > 0 ? str_repeat(
' ', 2 * $sub) :
'') .
'Update ' . $this->name .
' ' .
$version .
' config');
529 $bearsamppWinbinder->messageBoxError(
542 $bearsamppWinbinder->messageBoxError(
556 '/^port(.*?)=(.*?)(\d+)/' =>
'port = ' . $this->port
560 $bearsamppApps->getPhpmyadmin()->update($sub + 1);
580 $startTime = microtime(
true);
585 $perfSchemaDir =
$dataDir .
'/performance_schema';
587 if (version_compare(
$version,
'5.7.0',
'<')) {
588 Util::logTrace(
'MySQL version below 5.7.0, skipping initialization');
596 Util::logTrace(
'MySQL data directory does not exist; initialization required');
599 if (!is_dir($perfSchemaDir)) {
600 Util::logTrace(
'performance_schema directory missing; reinitialization required');
613 $backupDir =
$dataDir .
'_bak_' . date(
'Ymd_His');
614 if (@rename(
$dataDir, $backupDir)) {
615 Util::logTrace(
'Backed up existing data directory to: ' . $backupDir);
617 Util::logTrace(
'Failed to backup existing data directory; attempting to clear it');
619 $it = new \RecursiveDirectoryIterator(
$dataDir, \FilesystemIterator::SKIP_DOTS);
620 $files = new \RecursiveIteratorIterator($it, \RecursiveIteratorIterator::CHILD_FIRST);
621 foreach ($files as $file) {
622 if ($file->isDir()) {
623 @rmdir($file->getPathname());
625 @unlink($file->getPathname());
629 }
catch (\Throwable $t) {
630 Util::logTrace(
'Error clearing data directory: ' . $t->getMessage());
643 }
catch (\Throwable $e) {
644 Util::logTrace(
'Error during MySQL initialization via Batch: ' . $e->getMessage());
650 if (!is_dir($perfSchemaDir)) {
651 Util::logTrace(
'MySQL initialization appears to have failed: performance_schema still missing');
656 $totalTime = round(microtime(
true) - $startTime, 2);
657 Util::logTrace(
"MySQL initialization completed in {$totalTime}s");
679 if ($cmd == self::CMD_SYNTAX_CHECK) {
681 } elseif ($cmd == self::CMD_VARIABLES) {
690 if (file_exists($bin)) {
691 $tmpResult =
Batch::exec(
'mysqlGetCmdLineOutput',
'"' . $bin .
'" ' . $cmd .
' ' . $outputFrom, 5);
692 if ($tmpResult !==
false && is_array($tmpResult)) {
693 $result[
'syntaxOk'] = empty($tmpResult) || !
Util::contains(trim($tmpResult[count($tmpResult) - 1]),
'[ERROR]');
694 for ($i = 0; $i < $removeLines; $i++) {
695 unset($tmpResult[$i]);
697 $result[
'content'] = trim(str_replace($bin,
'', implode(PHP_EOL, $tmpResult)));
733 public function setEnable($enabled, $showWindow =
false)
740 $bearsamppWinbinder->messageBoxError(
static initializeMysql($path)
static exec($basename, $content, $timeout=true, $catchOutput=true, $standalone=false, $silent=true, $rebuild=true)
updateConfig($version=null, $sub=0, $showWindow=false)
const LOCAL_CFG_ROOT_USER
changeRootPassword($currentPwd, $newPwd, $wbProgressBar=null)
switchVersion($version, $showWindow=false)
checkPort($port, $showWindow=false)
changePort($port, $checkUsed=false, $wbProgressBar=null)
setEnable($enabled, $showWindow=false)
initData($path=null, $version=null)
reload($id=null, $type=null)
checkRootPassword($currentPwd=null, $wbProgressBar=null)
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 ERROR_INVALID_PARAMETER
const SWITCH_VERSION_TITLE
const PORT_USED_BY_ANOTHER_DBMS
const ERROR_FILE_NOT_FOUND
update($sub=0, $showWindow=false)
static logError($data, $file=null)
static installService($bin, $port, $syntaxCheckCmd, $showWindow=false)
static logInitClass($classInstance)
static removeService($service, $name)
static logTrace($data, $file=null)
static isValidPort($port)
static logInfo($data, $file=null)
static contains($string, $search)
static logDebug($data, $file=null)
static logReloadClass($classInstance)
static startWith($string, $search)
static isPortInUse($port)
static replaceInFile($path, $replaceList)
const SERVER_ERROR_NORMAL
const SERVICE_DEMAND_START