Fix: setup script problem with sqlite, fixes #90
This commit is contained in:
parent
f68f5a9d49
commit
eeb7ec7532
@ -10,8 +10,13 @@ chown nginx:nginx /run/nginx
|
|||||||
sed -i "s/^nobody:.*$/nobody:x:1000:50::nobody:\/:\/sbin\/nologin/" /etc/passwd
|
sed -i "s/^nobody:.*$/nobody:x:1000:50::nobody:\/:\/sbin\/nologin/" /etc/passwd
|
||||||
sed -i "s/^nobody:.*$/nobody:x:50:/" /etc/group
|
sed -i "s/^nobody:.*$/nobody:x:50:/" /etc/group
|
||||||
|
|
||||||
sed -i "s/^\$dbuser = .*$/\$dbuser = \"ulogger\";/" /var/www/html/config.php
|
if [ "$ULOGGER_DB_DRIVER" = "sqlite" ]; then
|
||||||
sed -i "s/^\$dbpass = .*$/\$dbpass = \"${DB_USER_PASS}\";/" /var/www/html/config.php
|
sed -i "s/^\$dbuser = .*$//" /var/www/html/config.php
|
||||||
|
sed -i "s/^\$dbpass = .*$//" /var/www/html/config.php
|
||||||
|
else
|
||||||
|
sed -i "s/^\$dbuser = .*$/\$dbuser = \"ulogger\";/" /var/www/html/config.php
|
||||||
|
sed -i "s/^\$dbpass = .*$/\$dbpass = \"${DB_USER_PASS}\";/" /var/www/html/config.php
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$ULOGGER_DB_DRIVER" = "pgsql" ]; then
|
if [ "$ULOGGER_DB_DRIVER" = "pgsql" ]; then
|
||||||
export PGDATA=/data
|
export PGDATA=/data
|
||||||
|
63
.tests/tests/DbTest.php
Normal file
63
.tests/tests/DbTest.php
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
if (!defined("ROOT_DIR")) { define("ROOT_DIR", __DIR__ . "/../.."); }
|
||||||
|
require_once(__DIR__ . "/../../helpers/db.php");
|
||||||
|
|
||||||
|
class DbTest extends TestCase {
|
||||||
|
|
||||||
|
public function testGetDbNameValidNames() {
|
||||||
|
$testDbName = "testDbName";
|
||||||
|
$defaultDSNs = [
|
||||||
|
"mysql:host=db.example.com;port=3306;dbname=$testDbName",
|
||||||
|
"mysql:host=db.example.com;dbname=$testDbName;port=3306",
|
||||||
|
"mysql:dbname=$testDbName;host=db.example.com;port=3306",
|
||||||
|
"mysql:unix_socket=/tmp/mysql.sock;dbname=$testDbName;charset=utf8",
|
||||||
|
"pgsql:host=localhost;port=5432;dbname=$testDbName;user=myuser;password=mypass",
|
||||||
|
"pgsql:host=db.example.com port=31075 dbname=$testDbName",
|
||||||
|
"pgsql:host=db.example.com port=31075 dbname=$testDbName user=myuser password=mypass",
|
||||||
|
"sqlite:$testDbName",
|
||||||
|
"sqlite2:$testDbName",
|
||||||
|
"sqlite3:$testDbName"
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($defaultDSNs as $dsn) {
|
||||||
|
$this->assertEquals($testDbName, uDb::getDbName($dsn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetDbNameEmptyNames() {
|
||||||
|
$testDbName = "";
|
||||||
|
$defaultDSNs = [
|
||||||
|
"mysql:host=db.example.com;port=3306;dbname=",
|
||||||
|
"mysql:host=db.example.com;port=3306",
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
"unsupported:host=localhost;port=5432;dbname=;user=test;password=mypass",
|
||||||
|
"corrupt",
|
||||||
|
"pgsql:",
|
||||||
|
"sqlite",
|
||||||
|
"sqlite3",
|
||||||
|
"sqlite:"
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($defaultDSNs as $dsn) {
|
||||||
|
$this->assertEquals($testDbName, uDb::getDbName($dsn));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetDbFilename() {
|
||||||
|
$testFileNames = [
|
||||||
|
"C:\\Program Files\\Database.db",
|
||||||
|
":memory:",
|
||||||
|
"/tmp/testdb.db3"
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($testFileNames as $fileName) {
|
||||||
|
$this->assertEquals($fileName, uDb::getDbName("sqlite:$fileName"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
49
.tests/tests/SetupTest.php
Normal file
49
.tests/tests/SetupTest.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once(__DIR__ . "/../lib/UloggerAPITestCase.php");
|
||||||
|
|
||||||
|
class SetupTest extends UloggerAPITestCase {
|
||||||
|
private $script = "/scripts/setup.php";
|
||||||
|
|
||||||
|
public function testPrePhase() {
|
||||||
|
$response = $this->http->get($this->script);
|
||||||
|
$this->assertEquals(200, $response->getStatusCode(), "Unexpected status code");
|
||||||
|
$body = (string) $response->getBody();
|
||||||
|
$this->assertContains("<input type=\"hidden\" name=\"command\" value=\"setup\">", $body);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetupPhase() {
|
||||||
|
$options = [
|
||||||
|
"http_errors" => false,
|
||||||
|
"form_params" => [ "command" => "setup" ]
|
||||||
|
];
|
||||||
|
$response = $this->http->post($this->script, $options);
|
||||||
|
$this->assertEquals(200, $response->getStatusCode(), "Unexpected status code");
|
||||||
|
$body = (string) $response->getBody();
|
||||||
|
$this->assertContains("<input type=\"hidden\" name=\"command\" value=\"adduser\">", $body);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdduserPhase() {
|
||||||
|
$options = [
|
||||||
|
"http_errors" => false,
|
||||||
|
"form_params" => [
|
||||||
|
"command" => "adduser",
|
||||||
|
"login" => $this->testUser,
|
||||||
|
"pass" => $this->testPass,
|
||||||
|
"pass2" => $this->testPass
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$response = $this->http->post($this->script, $options);
|
||||||
|
$this->assertEquals(200, $response->getStatusCode(), "Unexpected status code");
|
||||||
|
$body = (string) $response->getBody();
|
||||||
|
$this->assertContains("<span class=\"ok\">", $body);
|
||||||
|
$this->assertEquals(2, $this->getConnection()->getRowCount("users"), "Wrong row count");
|
||||||
|
$expected = [ "id" => 2, "login" => $this->testUser ];
|
||||||
|
$actual = $this->getConnection()->createQueryTable("users", "SELECT id, login FROM users WHERE id = 2");
|
||||||
|
$this->assertTableContains($expected, $actual, "Wrong actual table data");
|
||||||
|
$this->assertTrue(password_verify($this->testPass, $this->pdoGetColumn("SELECT password FROM users WHERE id = 2")), "Wrong actual password hash");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -101,6 +101,11 @@
|
|||||||
return self::$tables[$name];
|
return self::$tables[$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns function name for getting date-time column value as unix timestamp
|
||||||
|
* @param string $column
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function unix_timestamp($column) {
|
public function unix_timestamp($column) {
|
||||||
switch (self::$driver) {
|
switch (self::$driver) {
|
||||||
default:
|
default:
|
||||||
@ -116,6 +121,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns function name for getting date-time column value as 'YYYY-MM-DD hh:mm:ss'
|
||||||
|
* @param string $column
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function from_unixtime($column) {
|
public function from_unixtime($column) {
|
||||||
switch (self::$driver) {
|
switch (self::$driver) {
|
||||||
default:
|
default:
|
||||||
@ -131,10 +141,44 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set character set
|
||||||
|
* @param string $charset
|
||||||
|
*/
|
||||||
private function setCharset($charset) {
|
private function setCharset($charset) {
|
||||||
if (self::$driver == "pgsql" || self::$driver == "mysql") {
|
if (self::$driver == "pgsql" || self::$driver == "mysql") {
|
||||||
$this->query("SET NAMES '$charset'");
|
$this->query("SET NAMES '$charset'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract database name from DSN
|
||||||
|
* @param string $dsn
|
||||||
|
* @return string Empty string if not found
|
||||||
|
*/
|
||||||
|
static public function getDbName($dsn) {
|
||||||
|
$name = "";
|
||||||
|
if (strpos($dsn, ":") !== false) {
|
||||||
|
list($scheme, $dsnWithoutScheme) = explode(":", $dsn, 2);
|
||||||
|
switch ($scheme) {
|
||||||
|
case "sqlite":
|
||||||
|
case "sqlite2":
|
||||||
|
case "sqlite3":
|
||||||
|
$pattern = "/(.+)/";
|
||||||
|
break;
|
||||||
|
case "pgsql":
|
||||||
|
$pattern = "/dbname=([^; ]+)/";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$pattern = "/dbname=([^;]+)/";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$result = preg_match($pattern, $dsnWithoutScheme, $matches);
|
||||||
|
if ($result === 1) {
|
||||||
|
$name = $matches[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
@ -24,50 +24,52 @@ $enabled = false;
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* no user modifications should be needed below */
|
/* no user modifications should be needed below */
|
||||||
|
|
||||||
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
|
if (version_compare(PHP_VERSION, "5.4.0", "<")) {
|
||||||
die("Sorry, ulogger will not work with PHP version lower than 5.4 (you have " . PHP_VERSION . ")");
|
die("Sorry, ulogger will not work with PHP version lower than 5.4 (you have " . PHP_VERSION . ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
define("ROOT_DIR", dirname(__DIR__));
|
define("ROOT_DIR", dirname(__DIR__));
|
||||||
require_once(ROOT_DIR . "/helpers/user.php");
|
require_once(ROOT_DIR . "/helpers/db.php");
|
||||||
require_once(ROOT_DIR . "/helpers/config.php");
|
require_once(ROOT_DIR . "/helpers/config.php");
|
||||||
require_once(ROOT_DIR . "/helpers/utils.php");
|
|
||||||
require_once(ROOT_DIR . "/helpers/lang.php");
|
require_once(ROOT_DIR . "/helpers/lang.php");
|
||||||
|
require_once(ROOT_DIR . "/helpers/user.php");
|
||||||
|
require_once(ROOT_DIR . "/helpers/utils.php");
|
||||||
|
|
||||||
$command = uUtils::postString('command');
|
$command = uUtils::postString("command");
|
||||||
|
|
||||||
$lang = (new uLang(uConfig::$lang))->getStrings();
|
$lang = (new uLang(uConfig::$lang))->getStrings();
|
||||||
$langSetup = (new uLang(uConfig::$lang))->getSetupStrings();
|
$langSetup = (new uLang(uConfig::$lang))->getSetupStrings();
|
||||||
|
|
||||||
$prefix = preg_replace('/[^a-z0-9_]/i', '', uConfig::$dbprefix);
|
$prefix = preg_replace("/[^a-z0-9_]/i", "", uConfig::$dbprefix);
|
||||||
$tPositions = $prefix . "positions";
|
$tPositions = $prefix . "positions";
|
||||||
$tTracks = $prefix . "tracks";
|
$tTracks = $prefix . "tracks";
|
||||||
$tUsers = $prefix . "users";
|
$tUsers = $prefix . "users";
|
||||||
$dbDriver = null;
|
|
||||||
|
|
||||||
$messages = [];
|
$messages = [];
|
||||||
|
|
||||||
switch ($command) {
|
switch ($command) {
|
||||||
case "setup":
|
case "setup":
|
||||||
|
|
||||||
$error = false;
|
$error = false;
|
||||||
try {
|
try {
|
||||||
$options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ];
|
$pdo = getPdo();
|
||||||
$pdo = new PDO(uConfig::$dbdsn, uConfig::$dbuser, uConfig::$dbpass, $options);
|
|
||||||
$dbDriver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
|
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
$messages[] = "<span class=\"warn\">{$langSetup["dbconnectfailed"]}</span>";
|
$messages[] = "<span class=\"warn\">{$langSetup["dbconnectfailed"]}</span>";
|
||||||
$messages[] = sprintf($langSetup["serversaid"], "<b>" . $e->getMessage() . "</b>");
|
$messages[] = sprintf($langSetup["serversaid"], "<b>" . htmlentities($e->getMessage()) . "</b>");
|
||||||
$messages[] = $langSetup["checkdbsettings"];
|
$messages[] = $langSetup["checkdbsettings"];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
$queries = getQueries();
|
$queries = getQueries($pdo->getAttribute(PDO::ATTR_DRIVER_NAME));
|
||||||
|
$pdo->beginTransaction();
|
||||||
foreach ($queries as $query) {
|
foreach ($queries as $query) {
|
||||||
$pdo->query($query);
|
$pdo->query($query);
|
||||||
}
|
}
|
||||||
|
$pdo->commit();
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
|
$pdo->rollBack();
|
||||||
$messages[] = "<span class=\"warn\">{$langSetup["dbqueryfailed"]}</span>";
|
$messages[] = "<span class=\"warn\">{$langSetup["dbqueryfailed"]}</span>";
|
||||||
$messages[] = sprintf($langSetup["serversaid"], "<b>" . $e->getMessage() . "</b>");
|
$messages[] = sprintf($langSetup["serversaid"], "<b>" . htmlentities($e->getMessage()) . "</b>");
|
||||||
$error = true;
|
$error = true;
|
||||||
}
|
}
|
||||||
$pdo = null;
|
$pdo = null;
|
||||||
@ -85,8 +87,8 @@ switch ($command) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "adduser":
|
case "adduser":
|
||||||
$login = uUtils::postString('login');
|
$login = uUtils::postString("login");
|
||||||
$pass = uUtils::postPass('pass');
|
$pass = uUtils::postPass("pass");
|
||||||
|
|
||||||
if (uUser::add($login, $pass) !== false) {
|
if (uUser::add($login, $pass) !== false) {
|
||||||
$messages[] = "<span class=\"ok\">{$langSetup["congratulations"]}</span>";
|
$messages[] = "<span class=\"ok\">{$langSetup["congratulations"]}</span>";
|
||||||
@ -107,7 +109,7 @@ switch ($command) {
|
|||||||
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
|
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!function_exists('password_hash')) {
|
if (!function_exists("password_hash")) {
|
||||||
$messages[] = $langSetup["passfuncwarn"];
|
$messages[] = $langSetup["passfuncwarn"];
|
||||||
$messages[] = $langSetup["passfunchack"];
|
$messages[] = $langSetup["passfunchack"];
|
||||||
$messages[] = sprintf($langSetup["lineshouldread"], "<br><span class=\"warn\">//require_once(ROOT_DIR . \"/helpers/password.php\");</span><br>", "<br><span class=\"ok\">require_once(ROOT_DIR . \"/helpers/password.php\");</span>");
|
$messages[] = sprintf($langSetup["lineshouldread"], "<br><span class=\"warn\">//require_once(ROOT_DIR . \"/helpers/password.php\");</span><br>", "<br><span class=\"ok\">require_once(ROOT_DIR . \"/helpers/password.php\");</span>");
|
||||||
@ -121,18 +123,7 @@ switch ($command) {
|
|||||||
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
|
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (empty(uConfig::$dbdsn) || ($dbDriver != "sqlite" && empty(uConfig::$dbuser))) {
|
if (ini_get("session.auto_start") == "1") {
|
||||||
if ($dbDriver == "sqlite") {
|
|
||||||
$required = "\$dbdsn";
|
|
||||||
} else {
|
|
||||||
$required = "\$dbdsn, \$dbuser, \$dbpass";
|
|
||||||
}
|
|
||||||
$messages[] = sprintf($langSetup["nodbsettings"], $required);
|
|
||||||
$messages[] = $langSetup["dorestart"];
|
|
||||||
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ini_get("session.auto_start") == '1') {
|
|
||||||
$messages[] = sprintf($langSetup["optionwarn"], "session.auto_start", "0 (off)");
|
$messages[] = sprintf($langSetup["optionwarn"], "session.auto_start", "0 (off)");
|
||||||
$messages[] = $langSetup["dorestart"];
|
$messages[] = $langSetup["dorestart"];
|
||||||
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
|
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
|
||||||
@ -144,14 +135,42 @@ switch ($command) {
|
|||||||
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
|
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$messages[] = sprintf($langSetup["scriptdesc"], "'$tPositions', '$tTracks', '$tUsers'", "<b>" . getDbname(uConfig::$dbdsn) . "</b>");
|
if (empty(uConfig::$dbdsn)) {
|
||||||
|
$messages[] = sprintf($langSetup["nodbsettings"], "\$dbdsn");
|
||||||
|
$messages[] = $langSetup["dorestart"];
|
||||||
|
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$pdo = getPdo();
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$isSqlite = stripos(uConfig::$dbdsn, "sqlite") === 0;
|
||||||
|
if (!$isSqlite && empty(uConfig::$dbuser)) {
|
||||||
|
$messages[] = sprintf($langSetup["nodbsettings"], "\$dbuser, \$dbpass");
|
||||||
|
} else {
|
||||||
|
$messages[] = $langSetup["dbconnectfailed"];
|
||||||
|
$messages[] = $langSetup["checkdbsettings"];
|
||||||
|
$messages[] = sprintf($langSetup["serversaid"], "<b>" . htmlentities($e->getMessage()) . "</b>");
|
||||||
|
}
|
||||||
|
$messages[] = $langSetup["dorestart"];
|
||||||
|
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$pdo = null;
|
||||||
|
$dbName = uDb::getDbName(uConfig::$dbdsn);
|
||||||
|
$dbName = empty($dbName) ? '""' : "<b>" . htmlentities($dbName) . "</b>";
|
||||||
|
$messages[] = sprintf($langSetup["scriptdesc"], "'$tPositions', '$tTracks', '$tUsers'", $dbName);
|
||||||
$messages[] = $langSetup["scriptdesc2"];
|
$messages[] = $langSetup["scriptdesc2"];
|
||||||
$messages[] = "<form method=\"post\" action=\"setup.php\"><input type=\"hidden\" name=\"command\" value=\"setup\"><button>{$langSetup["startbutton"]}</button></form>";
|
$messages[] = "<form method=\"post\" action=\"setup.php\"><input type=\"hidden\" name=\"command\" value=\"setup\"><button>{$langSetup["startbutton"]}</button></form>";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getQueries() {
|
/**
|
||||||
global $tPositions, $tUsers, $tTracks, $dbDriver;
|
* @param string $dbDriver
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function getQueries($dbDriver) {
|
||||||
|
global $tPositions, $tUsers, $tTracks;
|
||||||
|
|
||||||
$queries = [];
|
$queries = [];
|
||||||
switch ($dbDriver) {
|
switch ($dbDriver) {
|
||||||
@ -284,26 +303,14 @@ function getQueries() {
|
|||||||
return $queries;
|
return $queries;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDbname($dsn) {
|
/**
|
||||||
if (strpos($dsn, ':') !== false) {
|
* @return PDO
|
||||||
list($scheme, $dsnWithoutScheme) = explode(':', $dsn, 2);
|
* @throws PDOException
|
||||||
switch ($scheme) {
|
*/
|
||||||
case 'sqlite':
|
function getPdo() {
|
||||||
case 'sqlite2':
|
$options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION];
|
||||||
case 'sqlite3':
|
$pdo = new PDO(uConfig::$dbdsn, uConfig::$dbuser, uConfig::$dbpass, $options);
|
||||||
return $dsnWithoutScheme;
|
return $pdo;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
$pattern = '~dbname=([^;]*)(?:;|$)~';
|
|
||||||
$result = preg_match($pattern, $dsnWithoutScheme, $matches);
|
|
||||||
if ($result === 1 && !empty($matches[1])) {
|
|
||||||
return $matches[1];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "noname";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user