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) {
257 if (PHP_VERSION_ID >= 80500) {
258 $initCommandAttr = \Pdo\Mysql::ATTR_INIT_COMMAND;
260 $initCommandAttr = \PDO::MYSQL_ATTR_INIT_COMMAND;
264 \PDO::ATTR_TIMEOUT => $timeout,
265 \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
266 $initCommandAttr =>
"SET SESSION sql_mode=''"
269 $dsn =
'mysql:host=127.0.0.1;port=' .
$port;
270 $cachedConnection = new \PDO($dsn, $this->rootUser, $this->rootPwd, $options);
272 }
catch (\PDOException $e) {
275 $bearsamppWinbinder->messageBoxWarning(
286 $stmt = $cachedConnection->query(
"SELECT @@version, @@version_comment");
287 $row = $stmt->fetch(\PDO::FETCH_NUM);
300 $bearsamppWinbinder->messageBoxWarning(
310 $bearsamppWinbinder->messageBoxInfo(
316 $totalTime = round(microtime(
true) - $startTime, 2);
320 }
catch (\PDOException $e) {
323 $bearsamppWinbinder->messageBoxWarning(
343 global $bearsamppWinbinder;
344 $startTime = microtime(
true);
348 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
353 \PDO::ATTR_TIMEOUT => $timeout,
354 \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
358 $dbLink = new \PDO($dsn, $this->rootUser, $currentPwd, $options);
360 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
363 $stmt = $dbLink->query(
'SELECT VERSION()');
366 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
369 if (version_compare(
$version,
'5.7.6',
'>=')) {
371 $sql =
"ALTER USER '{$this->rootUser}'@'localhost' IDENTIFIED BY :password";
372 $stmt = $dbLink->prepare($sql);
373 $stmt->bindParam(
':password', $newPwd);
376 $sql =
"SET PASSWORD FOR '{$this->rootUser}'@'localhost' = PASSWORD(:password)";
377 $stmt = $dbLink->prepare($sql);
378 $stmt->bindParam(
':password', $newPwd);
381 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
384 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
385 $dbLink->query(
'FLUSH PRIVILEGES');
387 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
390 }
catch (\PDOException $e) {
391 $error = $e->getMessage();
394 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
396 if (!empty($error)) {
397 $totalTime = round(microtime(
true) - $startTime, 2);
398 Util::logTrace(
"MySQL password change failed in {$totalTime}s: " . $error);
404 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
409 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
411 $totalTime = round(microtime(
true) - $startTime, 2);
412 Util::logTrace(
"MySQL password change completed in {$totalTime}s");
427 global $bearsamppWinbinder;
428 $startTime = microtime(
true);
429 $currentPwd = $currentPwd ==
null ? $this->rootPwd : $currentPwd;
433 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
436 static $passwordCache = [];
437 $cacheKey = md5($this->rootUser .
':' . $currentPwd .
':' . $this->port);
439 if (isset($passwordCache[$cacheKey]) && (time() - $passwordCache[$cacheKey][
'time']) < 30) {
440 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
441 $totalTime = round(microtime(
true) - $startTime, 2);
442 Util::logTrace(
"MySQL password check completed from cache in {$totalTime}s");
443 return $passwordCache[$cacheKey][
'result'];
449 if (PHP_VERSION_ID >= 80500) {
450 $initCommandAttr = \Pdo\Mysql::ATTR_INIT_COMMAND;
452 $initCommandAttr = \PDO::MYSQL_ATTR_INIT_COMMAND;
456 \PDO::ATTR_TIMEOUT => $timeout,
457 \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
458 $initCommandAttr =>
"SET SESSION sql_mode=''"
462 $dbLink = new \PDO($dsn, $this->rootUser, $currentPwd, $options);
465 $dbLink->query(
'SELECT 1');
469 $passwordCache[$cacheKey] = [
474 }
catch (\PDOException $e) {
475 $error = $e->getMessage();
478 $passwordCache[$cacheKey] = [
480 'time' => time() - 25
484 $bearsamppWinbinder->incrProgressBar($wbProgressBar);
486 if (!empty($error)) {
487 $totalTime = round(microtime(
true) - $startTime, 2);
488 Util::logTrace(
"MySQL password check failed in {$totalTime}s: " . $error);
492 $totalTime = round(microtime(
true) - $startTime, 2);
493 Util::logTrace(
"MySQL password check completed in {$totalTime}s");
525 if (!$this->enable) {
530 Util::logDebug(($sub > 0 ? str_repeat(
' ', 2 * $sub) :
'') .
'Update ' . $this->name .
' ' .
$version .
' config');
545 $bearsamppWinbinder->messageBoxError(
558 $bearsamppWinbinder->messageBoxError(
572 '/^port(.*?)=(.*?)(\d+)/' =>
'port = ' . $this->port
576 $bearsamppApps->getPhpmyadmin()->update($sub + 1);
596 $startTime = microtime(
true);
601 $perfSchemaDir =
$dataDir .
'/performance_schema';
603 if (version_compare(
$version,
'5.7.0',
'<')) {
604 Util::logTrace(
'MySQL version below 5.7.0, skipping initialization');
612 Util::logTrace(
'MySQL data directory does not exist; initialization required');
615 if (!is_dir($perfSchemaDir)) {
616 Util::logTrace(
'performance_schema directory missing; reinitialization required');
629 $backupDir =
$dataDir .
'_bak_' . date(
'Ymd_His');
630 if (@rename(
$dataDir, $backupDir)) {
631 Util::logTrace(
'Backed up existing data directory to: ' . $backupDir);
633 Util::logTrace(
'Failed to backup existing data directory; attempting to clear it');
635 $it = new \RecursiveDirectoryIterator(
$dataDir, \FilesystemIterator::SKIP_DOTS);
636 $files = new \RecursiveIteratorIterator($it, \RecursiveIteratorIterator::CHILD_FIRST);
637 foreach ($files as $file) {
638 if ($file->isDir()) {
639 @rmdir($file->getPathname());
641 @unlink($file->getPathname());
645 }
catch (\Throwable $t) {
646 Util::logTrace(
'Error clearing data directory: ' . $t->getMessage());
659 }
catch (\Throwable $e) {
660 Util::logTrace(
'Error during MySQL initialization via Batch: ' . $e->getMessage());
666 if (!is_dir($perfSchemaDir)) {
667 Util::logTrace(
'MySQL initialization appears to have failed: performance_schema still missing');
672 $totalTime = round(microtime(
true) - $startTime, 2);
673 Util::logTrace(
"MySQL initialization completed in {$totalTime}s");
695 if ($cmd == self::CMD_SYNTAX_CHECK) {
697 } elseif ($cmd == self::CMD_VARIABLES) {
706 if (file_exists($bin)) {
707 $tmpResult =
Batch::exec(
'mysqlGetCmdLineOutput',
'"' . $bin .
'" ' . $cmd .
' ' . $outputFrom, 5);
708 if ($tmpResult !==
false && is_array($tmpResult)) {
709 $result[
'syntaxOk'] = empty($tmpResult) || !
Util::contains(trim($tmpResult[count($tmpResult) - 1]),
'[ERROR]');
710 for ($i = 0; $i < $removeLines; $i++) {
711 unset($tmpResult[$i]);
713 $result[
'content'] = trim(str_replace($bin,
'', implode(PHP_EOL, $tmpResult)));
749 public function setEnable($enabled, $showWindow =
false)
756 $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