Linux ip-172-31-33-47 5.4.0-1045-aws #47~18.04.1-Ubuntu SMP Tue Apr 13 15:58:14 UTC 2021 x86_64
Apache/2.4.29 (Ubuntu)
: 172.31.33.47 | : 216.73.216.46
Cant Read [ /etc/named.conf ]
7.4.20
www-data
www.github.com/MadExploits
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
CPANEL RESET
CREATE WP USER
README
+ Create Folder
+ Create File
/
var /
www /
html /
stage /
phpmyadmin /
tests /
unit /
[ HOME SHELL ]
Name
Size
Permission
Action
Advisory
[ DIR ]
drwxr-xr-x
Charsets
[ DIR ]
drwxr-xr-x
Command
[ DIR ]
drwxr-xr-x
Config
[ DIR ]
drwxr-xr-x
ConfigStorage
[ DIR ]
drwxr-xr-x
Container
[ DIR ]
drwxr-xr-x
Controllers
[ DIR ]
drwxr-xr-x
Crypto
[ DIR ]
drwxr-xr-x
Database
[ DIR ]
drwxr-xr-x
Dbal
[ DIR ]
drwxr-xr-x
Display
[ DIR ]
drwxr-xr-x
Engines
[ DIR ]
drwxr-xr-x
Error
[ DIR ]
drwxr-xr-x
Export
[ DIR ]
drwxr-xr-x
Gis
[ DIR ]
drwxr-xr-x
Html
[ DIR ]
drwxr-xr-x
Http
[ DIR ]
drwxr-xr-x
Identifiers
[ DIR ]
drwxr-xr-x
Import
[ DIR ]
drwxr-xr-x
Navigation
[ DIR ]
drwxr-xr-x
Partitioning
[ DIR ]
drwxr-xr-x
Plugins
[ DIR ]
drwxr-xr-x
Properties
[ DIR ]
drwxr-xr-x
Query
[ DIR ]
drwxr-xr-x
Replication
[ DIR ]
drwxr-xr-x
Routing
[ DIR ]
drwxr-xr-x
Server
[ DIR ]
drwxr-xr-x
Setup
[ DIR ]
drwxr-xr-x
Stubs
[ DIR ]
drwxr-xr-x
Table
[ DIR ]
drwxr-xr-x
Theme
[ DIR ]
drwxr-xr-x
Tracking
[ DIR ]
drwxr-xr-x
Triggers
[ DIR ]
drwxr-xr-x
Utils
[ DIR ]
drwxr-xr-x
WebAuthn
[ DIR ]
drwxr-xr-x
_data
[ DIR ]
drwxr-xr-x
AbstractTestCase.php
5.3
KB
-rw-r--r--
ApplicationTest.php
1.63
KB
-rw-r--r--
BookmarkTest.php
3.56
KB
-rw-r--r--
BrowseForeignersTest.php
6.29
KB
-rw-r--r--
CacheTest.php
3.02
KB
-rw-r--r--
CharsetsTest.php
5.3
KB
-rw-r--r--
ConfigTest.php
31.22
KB
-rw-r--r--
ConsoleTest.php
1.38
KB
-rw-r--r--
CoreTest.php
23.3
KB
-rw-r--r--
CreateAddFieldTest.php
19.21
KB
-rw-r--r--
DatabaseInterfaceTest.php
29.52
KB
-rw-r--r--
DbTableExistsTest.php
2.9
KB
-rw-r--r--
EncodingTest.php
5.89
KB
-rw-r--r--
EnvironmentTest.php
478
B
-rw-r--r--
FieldHelper.php
1.09
KB
-rw-r--r--
FieldMetadataTest.php
3.54
KB
-rw-r--r--
FileListingTest.php
3.54
KB
-rw-r--r--
FileTest.php
2.02
KB
-rw-r--r--
FlashMessagesTest.php
1.96
KB
-rw-r--r--
FontTest.php
6.13
KB
-rw-r--r--
FooterTest.php
5.19
KB
-rw-r--r--
GitTest.php
15.08
KB
-rw-r--r--
HeaderTest.php
11.05
KB
-rw-r--r--
IndexColumnTest.php
2.73
KB
-rw-r--r--
IndexTest.php
4.18
KB
-rw-r--r--
InsertEditTest.php
80.72
KB
-rw-r--r--
IpAllowDenyTest.php
6.62
KB
-rw-r--r--
LanguageTest.php
8.44
KB
-rw-r--r--
LinterTest.php
3.57
KB
-rw-r--r--
ListDatabaseTest.php
2.26
KB
-rw-r--r--
LoggingTest.php
570
B
-rw-r--r--
MenuTest.php
1.63
KB
-rw-r--r--
MessageTest.php
14.44
KB
-rw-r--r--
MimeTest.php
990
B
-rw-r--r--
NormalizationTest.php
15.38
KB
-rw-r--r--
OpenDocumentTest.php
1.67
KB
-rw-r--r--
OperationsTest.php
2.19
KB
-rw-r--r--
ParseAnalyzeTest.php
2.1
KB
-rw-r--r--
PdfTest.php
1.4
KB
-rw-r--r--
PluginsTest.php
4.69
KB
-rw-r--r--
ProfilingTest.php
730
B
-rw-r--r--
ResponseRendererTest.php
1.71
KB
-rw-r--r--
SanitizeTest.php
6.99
KB
-rw-r--r--
ScriptsTest.php
3.66
KB
-rw-r--r--
SessionTest.php
741
B
-rw-r--r--
ShowGrantsTest.php
1.78
KB
-rw-r--r--
SqlQueryFormTest.php
5.85
KB
-rw-r--r--
SqlTest.php
30.76
KB
-rw-r--r--
StorageEngineTest.php
18.19
KB
-rw-r--r--
SystemDatabaseTest.php
4.72
KB
-rw-r--r--
TemplateTest.php
5.61
KB
-rw-r--r--
TransformationsTest.php
10.52
KB
-rw-r--r--
TwoFactorTest.php
21.18
KB
-rw-r--r--
TypesByDatabaseVersionTest.php
31.86
KB
-rw-r--r--
TypesTest.php
20.45
KB
-rw-r--r--
UniqueConditionTest.php
13.26
KB
-rw-r--r--
UrlRedirectorTest.php
1.48
KB
-rw-r--r--
UrlTest.php
8.56
KB
-rw-r--r--
UserPasswordTest.php
2.5
KB
-rw-r--r--
UserPreferencesTest.php
12.02
KB
-rw-r--r--
UserPrivilegesFactoryTest.php
5.82
KB
-rw-r--r--
UtilTest.php
55.46
KB
-rw-r--r--
VersionInformationTest.php
9.62
KB
-rw-r--r--
VersionTest.php
1.25
KB
-rw-r--r--
ZipExtensionTest.php
5.31
KB
-rw-r--r--
Delete
Unzip
Zip
${this.title}
Close
Code Editor : InsertEditTest.php
<?php declare(strict_types=1); namespace PhpMyAdmin\Tests; use PhpMyAdmin\ColumnFull; use PhpMyAdmin\Config; use PhpMyAdmin\ConfigStorage\Relation; use PhpMyAdmin\Core; use PhpMyAdmin\Current; use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\Dbal\Warning; use PhpMyAdmin\EditField; use PhpMyAdmin\FileListing; use PhpMyAdmin\InsertEdit; use PhpMyAdmin\InsertEditColumn; use PhpMyAdmin\ResponseRenderer; use PhpMyAdmin\Table\Table; use PhpMyAdmin\Template; use PhpMyAdmin\Tests\Stubs\DbiDummy; use PhpMyAdmin\Tests\Stubs\DummyResult; use PhpMyAdmin\Transformations; use PhpMyAdmin\Url; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Medium; use ReflectionProperty; use function hash; use function is_object; use function is_scalar; use function is_string; use function mb_substr; use function md5; use function password_verify; use function sprintf; use const MYSQLI_PRI_KEY_FLAG; use const MYSQLI_TYPE_DECIMAL; use const MYSQLI_TYPE_TIMESTAMP; use const MYSQLI_TYPE_TINY; #[CoversClass(InsertEdit::class)] #[CoversClass(EditField::class)] #[CoversClass(InsertEditColumn::class)] #[Medium] class InsertEditTest extends AbstractTestCase { protected DatabaseInterface $dbi; protected DbiDummy $dummyDbi; private InsertEdit $insertEdit; /** * Setup for test cases */ protected function setUp(): void { parent::setUp(); $this->setLanguage(); $this->setGlobalConfig(); $this->dummyDbi = $this->createDbiDummy(); $this->dbi = $this->createDatabaseInterface($this->dummyDbi); DatabaseInterface::$instance = $this->dbi; $config = Config::getInstance(); $config->settings['ServerDefault'] = 1; Current::$database = 'db'; Current::$table = 'table'; $config->settings['LimitChars'] = 50; $config->settings['LongtextDoubleTextarea'] = false; $config->settings['ShowFieldTypesInDataEditView'] = true; $config->settings['ShowFunctionFields'] = true; $config->settings['ProtectBinary'] = 'blob'; $config->settings['MaxSizeForInputField'] = 10; $config->settings['MinSizeForInputField'] = 2; $config->settings['TextareaRows'] = 5; $config->settings['TextareaCols'] = 4; $config->settings['CharTextareaRows'] = 5; $config->settings['CharTextareaCols'] = 6; $config->settings['AllowThirdPartyFraming'] = false; $config->settings['SendErrorReports'] = 'ask'; $config->settings['DefaultTabDatabase'] = 'structure'; $config->settings['ShowDatabasesNavigationAsTree'] = true; $config->settings['DefaultTabTable'] = 'browse'; $config->settings['NavigationTreeDefaultTabTable'] = 'structure'; $config->settings['NavigationTreeDefaultTabTable2'] = ''; $config->settings['Confirm'] = true; $config->settings['LoginCookieValidity'] = 1440; $config->settings['enable_drag_drop_import'] = true; $this->insertEdit = new InsertEdit( $this->dbi, new Relation($this->dbi), new Transformations(), new FileListing(), new Template(), $config, ); $this->dbi->setVersion([ '@@version' => '10.9.3-MariaDB-1:10.9.3+maria~ubu2204', '@@version_comment' => 'mariadb.org binary distribution', ]); } /** * Teardown all objects */ protected function tearDown(): void { parent::tearDown(); $response = new ReflectionProperty(ResponseRenderer::class, 'instance'); $response->setValue(null, null); DatabaseInterface::$instance = null; } /** * Test for getFormParametersForInsertForm */ public function testGetFormParametersForInsertForm(): void { $whereClause = ['foo' => 'bar ', '1' => ' test']; $_POST['clause_is_unique'] = false; $_POST['sql_query'] = 'SELECT a'; $GLOBALS['goto'] = 'index.php'; $result = $this->insertEdit->getFormParametersForInsertForm( 'dbname', 'tablename', [], $whereClause, 'localhost', ); self::assertSame( [ 'db' => 'dbname', 'table' => 'tablename', 'goto' => 'index.php', 'err_url' => 'localhost', 'sql_query' => 'SELECT a', 'where_clause[foo]' => 'bar', 'where_clause[1]' => 'test', 'clause_is_unique' => false, ], $result, ); } /** * Test for getFormParametersForInsertForm */ public function testGetFormParametersForInsertFormGet(): void { $whereClause = ['foo' => 'bar ', '1' => ' test']; $_GET['clause_is_unique'] = false; $_GET['sql_query'] = 'SELECT a'; $_GET['sql_signature'] = Core::signSqlQuery($_GET['sql_query']); $GLOBALS['goto'] = 'index.php'; $result = $this->insertEdit->getFormParametersForInsertForm( 'dbname', 'tablename', [], $whereClause, 'localhost', ); self::assertSame( [ 'db' => 'dbname', 'table' => 'tablename', 'goto' => 'index.php', 'err_url' => 'localhost', 'sql_query' => 'SELECT a', 'where_clause[foo]' => 'bar', 'where_clause[1]' => 'test', 'clause_is_unique' => false, ], $result, ); } /** * Test for analyzeWhereClauses */ public function testAnalyzeWhereClause(): void { $clauses = ['a=1', 'b="fo\o"']; $resultStub1 = self::createMock(DummyResult::class); $resultStub2 = self::createMock(DummyResult::class); $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $dbi->expects(self::exactly(2)) ->method('query') ->willReturn($resultStub1, $resultStub2); $resultStub1->expects(self::once()) ->method('fetchAssoc') ->willReturn(['assoc1']); $resultStub2->expects(self::once()) ->method('fetchAssoc') ->willReturn(['assoc2']); $dbi->expects(self::exactly(2)) ->method('getFieldsMeta') ->willReturn([], []); DatabaseInterface::$instance = $dbi; $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'analyzeWhereClauses', [$clauses, 'table', 'db'], ); self::assertSame( [['a=1', 'b="fo\\\\o"'], [$resultStub1, $resultStub2], [['assoc1'], ['assoc2']], false], $result, ); } /** * Test for showEmptyResultMessageOrSetUniqueCondition */ public function testShowEmptyResultMessageOrSetUniqueCondition(): void { $meta = FieldHelper::fromArray([ 'type' => MYSQLI_TYPE_DECIMAL, 'flags' => MYSQLI_PRI_KEY_FLAG, 'table' => 'table', 'orgname' => 'orgname', ]); $resultStub = self::createMock(DummyResult::class); $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $dbi->expects(self::once()) ->method('getFieldsMeta') ->with($resultStub) ->willReturn([$meta]); DatabaseInterface::$instance = $dbi; $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'showEmptyResultMessageOrSetUniqueCondition', [['1' => ['1' => 1]], 1, [], 'SELECT', ['1' => $resultStub]], ); self::assertTrue($result); // case 2 Config::getInstance()->settings['ShowSQL'] = false; $responseMock = $this->getMockBuilder(ResponseRenderer::class) ->disableOriginalConstructor() ->onlyMethods(['addHtml']) ->getMock(); $restoreInstance = ResponseRenderer::getInstance(); $response = new ReflectionProperty(ResponseRenderer::class, 'instance'); $response->setValue(null, $responseMock); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'showEmptyResultMessageOrSetUniqueCondition', [[false], 0, ['1'], 'SELECT', ['1' => 'result1']], ); $response->setValue(null, $restoreInstance); self::assertFalse($result); } public function testLoadFirstRow(): void { $resultStub = self::createMock(DummyResult::class); $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $dbi->expects(self::once()) ->method('query') ->with('SELECT * FROM `db`.`table` LIMIT 1;') ->willReturn($resultStub); DatabaseInterface::$instance = $dbi; $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'loadFirstRow', ['table', 'db'], ); self::assertSame($resultStub, $result); } /** @return list<array{int, array<false>}> */ public static function dataProviderConfigValueInsertRows(): array { return [[2, [false, false]], [3, [false, false, false]]]; } /** * Test for loadFirstRow * * @param array<false> $rowsValue */ #[DataProvider('dataProviderConfigValueInsertRows')] public function testGetInsertRows(int $configValue, array $rowsValue): void { Config::getInstance()->settings['InsertRows'] = $configValue; $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getInsertRows', [], ); self::assertSame($rowsValue, $result); } /** * Test for showTypeOrFunction */ public function testShowTypeOrFunction(): void { $config = Config::getInstance(); $config->settings['ShowFieldTypesInDataEditView'] = true; $config->settings['ServerDefault'] = 1; $urlParams = ['ShowFunctionFields' => 2]; $result = $this->insertEdit->showTypeOrFunction('function', $urlParams, false); self::assertStringContainsString('index.php?route=/table/change', $result); self::assertStringContainsString( 'ShowFunctionFields=1&ShowFieldTypesInDataEditView=1&goto=index.php%3Froute%3D%2Fsql', $result, ); self::assertStringContainsString('Function', $result); // case 2 $result = $this->insertEdit->showTypeOrFunction('function', $urlParams, true); self::assertStringContainsString('index.php?route=/table/change', $result); self::assertStringContainsString( 'ShowFunctionFields=0&ShowFieldTypesInDataEditView=1&goto=index.php%3Froute%3D%2Fsql', $result, ); self::assertStringContainsString('Function', $result); // case 3 $result = $this->insertEdit->showTypeOrFunction('type', $urlParams, false); self::assertStringContainsString('index.php?route=/table/change', $result); self::assertStringContainsString( 'ShowFunctionFields=1&ShowFieldTypesInDataEditView=1&goto=index.php%3Froute%3D%2Fsql', $result, ); self::assertStringContainsString('Type', $result); // case 4 $result = $this->insertEdit->showTypeOrFunction('type', $urlParams, true); self::assertStringContainsString('index.php?route=/table/change', $result); self::assertStringContainsString( 'ShowFunctionFields=1&ShowFieldTypesInDataEditView=0&goto=index.php%3Froute%3D%2Fsql', $result, ); self::assertStringContainsString('Type', $result); } /** * Test for getColumnTitle */ public function testGetColumnTitle(): void { $fieldName = 'f1<'; self::assertSame( $this->callFunction( $this->insertEdit, InsertEdit::class, 'getColumnTitle', [$fieldName, []], ), 'f1<', ); $comments = []; $comments['f1<'] = 'comment>'; $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getColumnTitle', [$fieldName, $comments], ); $result = $this->parseString($result); self::assertStringContainsString('title="comment>"', $result); self::assertStringContainsString('f1<', $result); } /** * Test for isColumn */ public function testIsColumn(): void { $types = ['binary', 'varbinary']; $columnType = 'binaryfoo'; self::assertTrue($this->insertEdit->isColumn($columnType, $types)); $columnType = 'Binaryfoo'; self::assertTrue($this->insertEdit->isColumn($columnType, $types)); $columnType = 'varbinaryfoo'; self::assertTrue($this->insertEdit->isColumn($columnType, $types)); $columnType = 'barbinaryfoo'; self::assertFalse($this->insertEdit->isColumn($columnType, $types)); $types = ['char', 'varchar']; $columnType = 'char(10)'; self::assertTrue($this->insertEdit->isColumn($columnType, $types)); $columnType = 'VarChar(20)'; self::assertTrue($this->insertEdit->isColumn($columnType, $types)); $columnType = 'foochar'; self::assertFalse($this->insertEdit->isColumn($columnType, $types)); $types = ['blob', 'tinyblob', 'mediumblob', 'longblob']; $columnType = 'blob'; self::assertTrue($this->insertEdit->isColumn($columnType, $types)); $columnType = 'bloB'; self::assertTrue($this->insertEdit->isColumn($columnType, $types)); $columnType = 'mediumBloB'; self::assertTrue($this->insertEdit->isColumn($columnType, $types)); $columnType = 'tinyblobabc'; self::assertTrue($this->insertEdit->isColumn($columnType, $types)); $columnType = 'longblob'; self::assertTrue($this->insertEdit->isColumn($columnType, $types)); $columnType = 'foolongblobbar'; self::assertFalse($this->insertEdit->isColumn($columnType, $types)); } /** * Test for getNullifyCodeForNullColumn */ public function testGetNullifyCodeForNullColumn(): void { $foreignData = []; $foreigners = ['foreign_keys_data' => []]; $column = new InsertEditColumn( 'f', 'enum(ababababababababababa)', false, '', null, '', -1, false, false, false, false, ); self::assertSame( '1', $this->callFunction( $this->insertEdit, InsertEdit::class, 'getNullifyCodeForNullColumn', [$column, $foreigners, []], ), ); $column = new InsertEditColumn( 'f', 'enum(abababababab20)', false, '', null, '', -1, false, false, false, false, ); self::assertSame( '2', $this->callFunction( $this->insertEdit, InsertEdit::class, 'getNullifyCodeForNullColumn', [$column, $foreigners, []], ), ); $column = new InsertEditColumn('f', 'set', false, '', null, '', -1, false, false, false, false); self::assertSame( '3', $this->callFunction( $this->insertEdit, InsertEdit::class, 'getNullifyCodeForNullColumn', [$column, $foreigners, []], ), ); $column = new InsertEditColumn('f', '', false, '', null, '', -1, false, false, false, false); $foreigners['f'] = ['something'/* What should the mocked value actually be? */]; $foreignData['foreign_link'] = ''; self::assertSame( '4', $this->callFunction( $this->insertEdit, InsertEdit::class, 'getNullifyCodeForNullColumn', [$column, $foreigners, $foreignData], ), ); } /** * Test for getTextarea */ public function testGetTextarea(): void { $config = Config::getInstance(); $config->settings['TextareaRows'] = 20; $config->settings['TextareaCols'] = 10; $config->settings['CharTextareaRows'] = 7; $config->settings['CharTextareaCols'] = 1; $config->settings['LimitChars'] = 20; $column = new InsertEditColumn( 'f', 'char(10)', false, '', null, 'auto_increment', 20, false, false, true, false, ); (new ReflectionProperty(InsertEdit::class, 'fieldIndex'))->setValue($this->insertEdit, 2); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getTextarea', [$column, 'a', 'b', '', 'abc/', 'foobar', 'CHAR'], ); $result = $this->parseString($result); self::assertStringContainsString( '<textarea name="fieldsb" class="char charField" ' . 'data-maxlength="10" rows="7" cols="1" dir="abc/" ' . 'id="field_2_3" tabindex="2" data-type="CHAR">', $result, ); } /** * Test for getHtmlInput */ public function testGetHTMLinput(): void { Config::getInstance()->settings['ShowFunctionFields'] = true; $column = new InsertEditColumn('f', 'date', false, 'PRI', null, '', -1, false, false, false, false); (new ReflectionProperty(InsertEdit::class, 'fieldIndex'))->setValue($this->insertEdit, 23); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getHtmlInput', [$column, 'a', 'b', 30, 'c', 'DATE'], ); self::assertSame( '<input type="text" name="fieldsa" value="b" size="30" data-type="DATE"' . ' class="textfield datefield" onchange="c" tabindex="23" id="field_23_3">', $result, ); // case 2 datetime $column = new InsertEditColumn('f', 'datetime', false, 'PRI', null, '', -1, false, false, false, false); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getHtmlInput', [$column, 'a', 'b', 30, 'c', 'DATE'], ); self::assertSame( '<input type="text" name="fieldsa" value="b" size="30" data-type="DATE"' . ' class="textfield datetimefield" onchange="c" tabindex="23" id="field_23_3">', $result, ); // case 3 timestamp $column = new InsertEditColumn('f', 'timestamp', false, 'PRI', null, '', -1, false, false, false, false); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getHtmlInput', [$column, 'a', 'b', 30, 'c', 'DATE'], ); self::assertSame( '<input type="text" name="fieldsa" value="b" size="30" data-type="DATE"' . ' class="textfield datetimefield" onchange="c" tabindex="23" id="field_23_3">', $result, ); // case 4 int $column = new InsertEditColumn('f', 'int(11)', false, 'PRI', null, '', -1, false, false, false, false); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getHtmlInput', [$column, 'a', 'b', 11, 'c', 'INT'], ); self::assertSame( '<input type="text" name="fieldsa" value="b" size="11" min="-2147483648" max="2147483647" data-type="INT"' . ' class="textfield" onchange="c" tabindex="23" inputmode="numeric" id="field_23_3">', $result, ); } /** * Test for getMaxUploadSize */ public function testGetMaxUploadSize(): void { $config = Config::getInstance(); $config->set('max_upload_size', 257); $pmaType = 'tinyblob'; $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getMaxUploadSize', [$pmaType], ); self::assertSame("(Max: 256B)\n", $result); // case 2 $config->set('max_upload_size', 250); $pmaType = 'tinyblob'; $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getMaxUploadSize', [$pmaType], ); self::assertSame("(Max: 250B)\n", $result); } /** * Test for getValueColumnForOtherDatatypes */ public function testGetValueColumnForOtherDatatypes(): void { $column = new InsertEditColumn('f', 'char(25)', false, '', null, '', 20, false, false, true, false); $config = Config::getInstance(); $config->settings['CharEditing'] = ''; $config->settings['MaxSizeForInputField'] = 30; $config->settings['MinSizeForInputField'] = 10; $config->settings['TextareaRows'] = 20; $config->settings['TextareaCols'] = 10; $config->settings['CharTextareaRows'] = 7; $config->settings['CharTextareaCols'] = 1; $config->settings['LimitChars'] = 50; $config->settings['ShowFunctionFields'] = true; $extractedColumnSpec = []; $extractedColumnSpec['spec_in_brackets'] = '25'; (new ReflectionProperty(InsertEdit::class, 'fieldIndex'))->setValue($this->insertEdit, 22); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getValueColumnForOtherDatatypes', [ $column, 'defchar', 'a', 'b', 'c', '<', '/', '<', "foo\nbar", $extractedColumnSpec, ], ); self::assertSame( "a\na\n" . '<textarea name="fieldsb" class="char charField" ' . 'data-maxlength="25" rows="7" cols="1" dir="/" ' . 'id="field_22_3" onchange="c" tabindex="22" data-type="CHAR">' . '<</textarea>', $result, ); // case 2: (else) $column = new InsertEditColumn( 'f', 'timestamp', false, '', null, 'auto_increment', 20, false, false, false, false, ); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getValueColumnForOtherDatatypes', [ $column, 'defchar', 'a', 'b', 'c', '<', '/', '<', "foo\nbar", $extractedColumnSpec, ], ); self::assertSame( "a\n" . '<input type="text" name="fieldsb" value="<" size="20" data-type="' . 'DATE" class="textfield datetimefield" onchange="c" tabindex="22" id="field_22_3"' . '><input type="hidden" name="auto_incrementb" value="1">' . '<input type="hidden" name="fields_typeb" value="timestamp">', $result, ); // case 3: (else -> datetime) $column = new InsertEditColumn( 'f', 'datetime', false, '', null, 'auto_increment', 20, false, false, false, false, ); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getValueColumnForOtherDatatypes', [ $column, 'defchar', 'a', 'b', 'c', '<', '/', '<', "foo\nbar", $extractedColumnSpec, ], ); $result = $this->parseString($result); self::assertStringContainsString('<input type="hidden" name="fields_typeb" value="datetime">', $result); // case 4: (else -> date) $column = new InsertEditColumn('f', 'date', false, '', null, 'auto_increment', 20, false, false, false, false); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getValueColumnForOtherDatatypes', [ $column, 'defchar', 'a', 'b', 'c', '<', '/', '<', "foo\nbar", $extractedColumnSpec, ], ); $result = $this->parseString($result); self::assertStringContainsString('<input type="hidden" name="fields_typeb" value="date">', $result); // case 5: (else -> bit) $column = new InsertEditColumn('f', 'bit', false, '', null, 'auto_increment', 20, false, false, false, false); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getValueColumnForOtherDatatypes', [ $column, 'defchar', 'a', 'b', 'c', '<', '/', '<', "foo\nbar", $extractedColumnSpec, ], ); $result = $this->parseString($result); self::assertStringContainsString('<input type="hidden" name="fields_typeb" value="bit">', $result); // case 6: (else -> uuid) $column = new InsertEditColumn('f', 'uuid', false, '', null, 'auto_increment', 20, false, false, false, false); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getValueColumnForOtherDatatypes', [ $column, 'defchar', 'a', 'b', 'c', '<', '/', '<', "foo\nbar", $extractedColumnSpec, ], ); $result = $this->parseString($result); self::assertStringContainsString('<input type="hidden" name="fields_typeb" value="uuid">', $result); } /** * Test for getColumnSize */ public function testGetColumnSize(): void { $column = new InsertEditColumn( 'f', 'char(10)', false, '', null, 'auto_increment', 20, false, false, true, false, ); $specInBrackets = '45'; $config = Config::getInstance(); $config->settings['MinSizeForInputField'] = 30; $config->settings['MaxSizeForInputField'] = 40; self::assertSame( 40, $this->callFunction( $this->insertEdit, InsertEdit::class, 'getColumnSize', [$column, $specInBrackets], ), ); self::assertSame('textarea', $config->settings['CharEditing']); // case 2 $column = new InsertEditColumn( 'f', 'char(10)', false, '', null, 'auto_increment', 20, false, false, false, false, ); self::assertSame( 30, $this->callFunction( $this->insertEdit, InsertEdit::class, 'getColumnSize', [$column, $specInBrackets], ), ); } /** * Test for getContinueInsertionForm */ public function testGetContinueInsertionForm(): void { $whereClauseArray = ['a<b']; $config = Config::getInstance(); $config->settings['InsertRows'] = 1; $config->settings['ServerDefault'] = 1; $GLOBALS['goto'] = 'index.php'; $_POST['where_clause'] = true; $_POST['sql_query'] = 'SELECT 1'; $result = $this->insertEdit->getContinueInsertionForm('tbl', 'db', $whereClauseArray, 'localhost'); self::assertStringContainsString( '<form id="continueForm" method="post" action="' . Url::getFromRoute('/table/change') . '" name="continueForm" class="row g-3">', $result, ); self::assertStringContainsString('<input type="hidden" name="db" value="db">', $result); self::assertStringContainsString('<input type="hidden" name="table" value="tbl">', $result); self::assertStringContainsString('<input type="hidden" name="goto" value="index.php">', $result); self::assertStringContainsString('<input type="hidden" name="err_url" value="localhost">', $result); self::assertStringContainsString('<input type="hidden" name="sql_query" value="SELECT 1">', $result); self::assertStringContainsString('<input type="hidden" name="where_clause[0]" value="a<b">', $result); } public function testIsWhereClauseNumeric(): void { self::assertFalse(InsertEdit::isWhereClauseNumeric(null)); self::assertFalse(InsertEdit::isWhereClauseNumeric('')); self::assertFalse(InsertEdit::isWhereClauseNumeric([])); self::assertTrue(InsertEdit::isWhereClauseNumeric('`actor`.`actor_id` = 1')); self::assertTrue(InsertEdit::isWhereClauseNumeric(['`actor`.`actor_id` = 1'])); self::assertFalse(InsertEdit::isWhereClauseNumeric('`actor`.`first_name` = \'value\'')); self::assertFalse(InsertEdit::isWhereClauseNumeric(['`actor`.`first_name` = \'value\''])); } /** * Test for getHeadAndFootOfInsertRowTable */ public function testGetHeadAndFootOfInsertRowTable(): void { $config = Config::getInstance(); $config->settings['ShowFieldTypesInDataEditView'] = true; $config->settings['ShowFunctionFields'] = true; $config->settings['ServerDefault'] = 1; $urlParams = ['ShowFunctionFields' => 2]; $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getHeadAndFootOfInsertRowTable', [$urlParams], ); $result = $this->parseString($result); self::assertStringContainsString('index.php?route=/table/change', $result); self::assertStringContainsString('ShowFunctionFields=1&ShowFieldTypesInDataEditView=0', $result); self::assertStringContainsString('ShowFunctionFields=0&ShowFieldTypesInDataEditView=1', $result); } /** * Test for getSpecialCharsAndBackupFieldForExistingRow */ public function testGetSpecialCharsAndBackupFieldForExistingRow(): void { $currentRow = $extractedColumnSpec = []; $currentRow['f'] = null; $_POST['default_action'] = 'insert'; $column = new InsertEditColumn( 'f', 'char(10)', false, 'PRI', null, 'fooauto_increment', 20, false, false, true, false, ); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getSpecialCharsAndBackupFieldForExistingRow', [$currentRow, $column, [], 'a', false], ); self::assertEquals( [true, null, null, null, '<input type="hidden" name="fields_preva" value="">'], $result, ); // Case 2 (bit) unset($_POST['default_action']); $currentRow['f'] = '123'; $extractedColumnSpec['spec_in_brackets'] = '20'; $column = new InsertEditColumn( 'f', 'bit', false, 'PRI', null, 'fooauto_increment', 20, false, false, true, false, ); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getSpecialCharsAndBackupFieldForExistingRow', [$currentRow, $column, $extractedColumnSpec, 'a', false], ); self::assertEquals( [false, '', '00000000000001111011', null, '<input type="hidden" name="fields_preva" value="123">'], $result, ); $currentRow['f'] = 'abcd'; $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getSpecialCharsAndBackupFieldForExistingRow', [$currentRow, $column, $extractedColumnSpec, 'a', true], ); self::assertEquals( [false, '', 'abcd', null, '<input type="hidden" name="fields_preva" value="abcd">'], $result, ); // Case 3 (bit) $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); DatabaseInterface::$instance = $dbi; $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); $currentRow['f'] = '123'; $extractedColumnSpec['spec_in_brackets'] = '20'; $column = new InsertEditColumn( 'f', 'geometry', false, 'PRI', null, 'fooauto_increment', 20, false, false, true, false, ); $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getSpecialCharsAndBackupFieldForExistingRow', [$currentRow, $column, $extractedColumnSpec, 'a', false], ); self::assertEquals( [false, '', "'',", null, '<input type="hidden" name="fields_preva" value="\'\',">'], $result, ); // Case 4 (else) $column = new InsertEditColumn( 'f', 'char', false, 'PRI', null, 'fooauto_increment', 20, false, true, true, false, ); $config = Config::getInstance(); $config->settings['ProtectBinary'] = false; $currentRow['f'] = '11001'; $extractedColumnSpec['spec_in_brackets'] = '20'; $config->settings['ShowFunctionFields'] = true; $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getSpecialCharsAndBackupFieldForExistingRow', [$currentRow, $column, $extractedColumnSpec, 'a', false], ); self::assertSame( [ false, '3131303031', '3131303031', '3131303031', '<input type="hidden" name="fields_preva" value="3131303031">', ], $result, ); // Case 5 $currentRow['f'] = "11001\x00"; $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getSpecialCharsAndBackupFieldForExistingRow', [$currentRow, $column, $extractedColumnSpec, 'a', false], ); self::assertSame( [ false, '313130303100', '313130303100', '313130303100', '<input type="hidden" name="fields_preva" value="313130303100">', ], $result, ); } /** * Test for getSpecialCharsForInsertingMode */ #[DataProvider('providerForTestGetSpecialCharsForInsertingMode')] public function testGetSpecialCharsForInsertingMode( string|null $defaultValue, string $trueType, string $expected, ): void { $config = Config::getInstance(); $config->settings['ProtectBinary'] = false; $config->settings['ShowFunctionFields'] = true; /** @var string $result */ $result = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getSpecialCharsForInsertingMode', [$defaultValue, $trueType], ); self::assertSame($expected, $result); } /** * Data provider for test getSpecialCharsForInsertingMode() * * @return array<string, array{string|null, string, string}> */ public static function providerForTestGetSpecialCharsForInsertingMode(): array { return [ 'bit' => [ 'b\'101\'', 'bit', '101', ], 'char' => [ null, 'char', '', ], 'time with CURRENT_TIMESTAMP value' => [ 'CURRENT_TIMESTAMP', 'time', 'CURRENT_TIMESTAMP', ], 'time with current_timestamp() value' => [ 'current_timestamp()', 'time', 'current_timestamp()', ], 'time with no dot value' => [ '10', 'time', '10.000000', ], 'time with dot value' => [ '10.08', 'time', '10.080000', ], 'any text with escape text default' => [ '"lorem\"ipsem"', 'text', 'lorem"ipsem', ], 'varchar with html special chars' => [ 'hello world<br><b>lorem</b> ipsem', 'varchar', 'hello world<br><b>lorem</b> ipsem', ], ]; } /** * Test for setSessionForEditNext */ public function testSetSessionForEditNext(): void { $meta = FieldHelper::fromArray([ 'type' => MYSQLI_TYPE_DECIMAL, 'flags' => MYSQLI_PRI_KEY_FLAG, 'orgname' => 'orgname', 'table' => 'table', 'orgtable' => 'table', ]); $row = ['1' => 1]; $resultStub = self::createMock(DummyResult::class); $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $dbi->expects(self::once()) ->method('query') ->with('SELECT * FROM `db`.`table` WHERE `a` > 2 LIMIT 1;') ->willReturn($resultStub); $resultStub->expects(self::once()) ->method('fetchRow') ->willReturn($row); $dbi->expects(self::once()) ->method('getFieldsMeta') ->with($resultStub) ->willReturn([$meta]); DatabaseInterface::$instance = $dbi; Current::$database = 'db'; Current::$table = 'table'; $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); $this->insertEdit->setSessionForEditNext('`a` = 2'); self::assertSame('CONCAT(`table`.`orgname`) IS NULL', $_SESSION['edit_next']); } /** * Test for getGotoInclude */ public function testGetGotoInclude(): void { $GLOBALS['goto'] = '123.php'; Current::$table = ''; self::assertSame( '/database/sql', $this->insertEdit->getGotoInclude('index'), ); Current::$table = 'tbl'; self::assertSame( '/table/sql', $this->insertEdit->getGotoInclude('index'), ); $GLOBALS['goto'] = 'index.php?route=/database/sql'; self::assertSame( '/database/sql', $this->insertEdit->getGotoInclude('index'), ); self::assertSame('', Current::$table); $GLOBALS['goto'] = 'index.php?route=/sql&server=2'; self::assertSame( '/sql', $this->insertEdit->getGotoInclude('index'), ); $_POST['after_insert'] = 'new_insert'; self::assertSame( '/table/change', $this->insertEdit->getGotoInclude('index'), ); } /** * Test for getErrorUrl */ public function testGetErrorUrl(): void { Config::getInstance()->settings['ServerDefault'] = 1; self::assertSame( 'index.php?route=/table/change&lang=en', $this->insertEdit->getErrorUrl([]), ); $_POST['err_url'] = 'localhost'; self::assertSame( 'localhost', $this->insertEdit->getErrorUrl([]), ); } /** * Test for executeSqlQuery */ public function testExecuteSqlQuery(): void { $query = ['SELECT * FROM `test_db`.`test_table`;', 'SELECT * FROM `test_db`.`test_table_yaml`;']; Config::getInstance()->settings['IgnoreMultiSubmitErrors'] = false; $_POST['submit_type'] = ''; $dbi = DatabaseInterface::getInstance(); $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); $result = $this->insertEdit->executeSqlQuery($query); self::assertSame([], $result[3]); } /** * Test for executeSqlQuery */ public function testExecuteSqlQueryWithTryQuery(): void { $query = ['SELECT * FROM `test_db`.`test_table`;', 'SELECT * FROM `test_db`.`test_table_yaml`;']; Config::getInstance()->settings['IgnoreMultiSubmitErrors'] = true; $_POST['submit_type'] = ''; $dbi = DatabaseInterface::getInstance(); $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); $result = $this->insertEdit->executeSqlQuery($query); self::assertSame([], $result[3]); } /** * Test for getWarningMessages */ public function testGetWarningMessages(): void { $warnings = [ Warning::fromArray(['Level' => 'Error', 'Code' => '1001', 'Message' => 'Message 1']), Warning::fromArray(['Level' => 'Warning', 'Code' => '1002', 'Message' => 'Message 2']), ]; $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $dbi->expects(self::once()) ->method('getWarnings') ->willReturn($warnings); DatabaseInterface::$instance = $dbi; $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); $result = (array) $this->callFunction( $this->insertEdit, InsertEdit::class, 'getWarningMessages', [], ); self::assertSame(['Error: #1001 Message 1', 'Warning: #1002 Message 2'], $result); } /** * Test for getDisplayValueForForeignTableColumn */ public function testGetDisplayValueForForeignTableColumn(): void { $map = []; $map['f']['foreign_db'] = 'information_schema'; $map['f']['foreign_table'] = 'TABLES'; $map['f']['foreign_field'] = 'f'; $resultStub = self::createMock(DummyResult::class); $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $dbi->expects(self::once()) ->method('tryQuery') ->with('SELECT `TABLE_COMMENT` FROM `information_schema`.`TABLES` WHERE `f`=1') ->willReturn($resultStub); $resultStub->expects(self::once()) ->method('numRows') ->willReturn(2); $resultStub->expects(self::once()) ->method('fetchValue') ->with(0) ->willReturn('2'); DatabaseInterface::$instance = $dbi; $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); $result = $this->insertEdit->getDisplayValueForForeignTableColumn('=1', $map, 'f'); self::assertEquals(2, $result); } /** * Test for getLinkForRelationalDisplayField */ public function testGetLinkForRelationalDisplayField(): void { Config::getInstance()->settings['ServerDefault'] = 1; $_SESSION['tmpval']['relational_display'] = 'K'; $map = []; $map['f']['foreign_db'] = 'information_schema'; $map['f']['foreign_table'] = 'TABLES'; $map['f']['foreign_field'] = 'f'; $result = $this->insertEdit->getLinkForRelationalDisplayField($map, 'f', '=1', 'a>', 'b<'); $sqlSignature = Core::signSqlQuery('SELECT * FROM `information_schema`.`TABLES` WHERE `f`=1'); self::assertSame( '<a href="index.php?route=/sql&db=information_schema&table=TABLES&pos=0&' . 'sql_signature=' . $sqlSignature . '&' . 'sql_query=SELECT+%2A+FROM+%60information_schema%60.%60TABLES%60+WHERE' . '+%60f%60%3D1&lang=en" title="a>">b<</a>', $result, ); $_SESSION['tmpval']['relational_display'] = 'D'; $result = $this->insertEdit->getLinkForRelationalDisplayField($map, 'f', '=1', 'a>', 'b<'); self::assertSame( '<a href="index.php?route=/sql&db=information_schema&table=TABLES&pos=0&' . 'sql_signature=' . $sqlSignature . '&' . 'sql_query=SELECT+%2A+FROM+%60information_schema%60.%60TABLES%60+WHERE' . '+%60f%60%3D1&lang=en" title="b<">a></a>', $result, ); } /** * Test for transformEditedValues */ public function testTransformEditedValues(): void { $_SESSION[' HMAC_secret '] = hash('sha1', 'test'); $editedValues = [['c' => 'cname']]; $config = Config::getInstance(); $config->settings['DefaultTransformations']['PreApPend'] = ['', '']; $config->settings['ServerDefault'] = 1; $_POST['where_clause'] = '1'; $_POST['where_clause_sign'] = Core::signSqlQuery($_POST['where_clause']); $transformation = ['transformation_options' => "'','option ,, quoted',abd"]; $result = $this->insertEdit->transformEditedValues( 'db', 'table', $transformation, $editedValues, 'Text_Plain_PreApPend.php', 'c', ['a' => 'b'], 'transformation', ); self::assertSame( ['a' => 'b', 'transformations' => ['cnameoption ,, quoted']], $result, ); } /** * Test for getQueryValuesForInsert */ public function testGetQueryValuesForInsert(): void { // Simple insert $result = $this->insertEdit->getQueryValueForInsert( new EditField( 'fld', 'foo', '', false, false, false, '', null, null, false, ), false, '', ); self::assertSame("'foo'", $result); // Test for file upload $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '0x123', '', false, false, false, '', null, null, true, ), false, '', ); self::assertSame('0x123', $result); // Test functions $this->dummyDbi->addResult( 'SELECT UUID()', [ ['uuid1234'],// Minimal working setup for 2FA ], ); // case 1 $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '', '', false, false, false, 'UUID', null, null, false, ), false, '', ); self::assertSame("'uuid1234'", $result); // case 2 $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', "'", '', false, false, false, 'AES_ENCRYPT', '', null, false, ), false, '', ); self::assertSame("AES_ENCRYPT('\\'','')", $result); // case 3 $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', "'", '', false, false, false, 'ABS', null, null, false, ), false, '', ); self::assertSame("ABS('\\'')", $result); // case 4 $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '', '', false, false, false, 'RAND', null, null, false, ), false, '', ); self::assertSame('RAND()', $result); // case 5 $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', "a'c", '', false, false, false, 'PHP_PASSWORD_HASH', null, null, false, ), false, '', ); self::assertTrue(password_verify("a'c", mb_substr($result, 1, -1))); // case 7 $result = $this->insertEdit->getQueryValueForInsert( new EditField('', "'POINT(3 4)',4326", '', true, false, false, 'ST_GeomFromText', null, null, false), false, '', ); self::assertSame('ST_GeomFromText(\'POINT(3 4)\',4326)', $result); // case 8 $result = $this->insertEdit->getQueryValueForInsert( new EditField('', 'POINT(3 4),4326', '', true, false, false, 'ST_GeomFromText', null, null, false), false, '', ); self::assertSame('ST_GeomFromText(\'POINT(3 4)\',4326)', $result); // case 9 $result = $this->insertEdit->getQueryValueForInsert( new EditField('', "'POINT(3 4)'", '', true, false, false, 'ST_GeomFromText', null, null, false), false, '', ); self::assertSame('ST_GeomFromText(\'POINT(3 4)\')', $result); // case 10 $result = $this->insertEdit->getQueryValueForInsert( new EditField('', 'POINT(3 4)', '', true, false, false, 'ST_GeomFromText', null, null, false), false, '', ); self::assertSame('ST_GeomFromText(\'POINT(3 4)\')', $result); // Test different data types // Datatype: protected copied from the databse Current::$table = 'test_table'; $result = $this->insertEdit->getQueryValueForInsert( new EditField( 'name', '', 'protected', false, false, false, '', null, null, false, ), true, '`id` = 4', ); self::assertSame('0x313031', $result); // An empty value for auto increment column should be converted to NULL $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '', // empty for null '', true, false, false, '', null, null, false, ), false, '', ); self::assertSame('NULL', $result); // Simple empty value $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '', '', false, false, false, '', null, null, false, ), false, '', ); self::assertSame("''", $result); // Datatype: set $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '', // doesn't matter what the value is 'set', false, false, false, '', null, null, false, ), false, '', ); self::assertSame("''", $result); // Datatype: protected with no value should produce an empty string $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '', 'protected', false, false, false, '', null, null, false, ), false, '', ); self::assertSame('', $result); // Datatype: protected with null flag set $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '', 'protected', false, true, false, '', null, null, false, ), false, '', ); self::assertSame('NULL', $result); // Datatype: bit $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '20\'12', 'bit', false, false, false, '', null, null, false, ), false, '', ); self::assertSame("b'00010'", $result); // Datatype: date $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '20\'12', 'date', false, false, false, '', null, null, false, ), false, '', ); self::assertSame("'20\\'12'", $result); // A NULL checkbox $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '', 'set', false, true, false, '', null, null, false, ), false, '', ); self::assertSame('NULL', $result); // Datatype: protected but NULL checkbox was unchecked without uploading a file $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '', 'protected', false, false, true, // was previously NULL '', null, null, false, // no upload ), false, '', ); self::assertSame("''", $result); // Datatype: date with default value $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', 'current_timestamp()', 'date', false, false, true, // NULL should be ignored '', null, null, false, ), false, '', ); self::assertSame('current_timestamp()', $result); // Datatype: hex without 0x $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '222aaafff', 'hex', false, false, false, '', null, null, false, ), false, '', ); self::assertSame('0x222aaafff', $result); // Datatype: hex with 0x $result = $this->insertEdit->getQueryValueForInsert( new EditField( '', '0x222aaafff', 'hex', false, false, false, '', null, null, false, ), false, '', ); self::assertSame('0x222aaafff', $result); } /** * Test for getQueryValuesForUpdate */ public function testGetQueryValuesForUpdate(): void { // Simple update $result = $this->insertEdit->getQueryValueForUpdate( new EditField( 'fld', 'foo', '', false, false, false, '', null, null, false, ), ); self::assertSame("`fld` = 'foo'", $result); // Update of null when it was null previously $result = $this->insertEdit->getQueryValueForUpdate( new EditField( 'fld', '', // null fields will have no value '', false, true, true, '', null, null, false, ), ); self::assertSame('', $result); // Update of null when it was NOT null previously $result = $this->insertEdit->getQueryValueForUpdate( new EditField( 'fld', '', // null fields will have no value '', false, true, false, '', null, '', // in edit mode the previous value will be empty string false, ), ); self::assertSame('`fld` = NULL', $result); // Update to NOT null when it was null previously $result = $this->insertEdit->getQueryValueForUpdate( new EditField( 'fld', "ab'c", '', false, false, true, '', null, null, false, ), ); self::assertSame("`fld` = 'ab\'c'", $result); // Test to see if a zero-string is not ignored $result = $this->insertEdit->getQueryValueForUpdate( new EditField( 'fld', '0', // zero-string provided as value '', false, false, false, '', null, null, false, ), ); self::assertSame("`fld` = '0'", $result); // Test to check if blob field that was left unchanged during edit will be ignored $result = $this->insertEdit->getQueryValueForUpdate( new EditField( 'fld', '', // no value 'protected', false, false, false, '', null, null, false, ), ); self::assertSame('', $result); // Test to see if a field will be ignored if it the value is unchanged $result = $this->insertEdit->getQueryValueForUpdate( new EditField( 'fld', "a'b", '', false, false, false, '', null, "a'b", false, ), ); self::assertSame('', $result); // Test that an empty value uses the uuid function to generate a value $result = $this->insertEdit->getQueryValueForUpdate( new EditField( 'fld', "''", 'uuid', false, false, false, '', null, '', false, ), ); self::assertSame('`fld` = uuid()', $result); // Test that the uuid function as a value uses the uuid function to generate a value $result = $this->insertEdit->getQueryValueForUpdate( new EditField( 'fld', "'uuid()'", 'uuid', false, false, false, '', null, '', false, ), ); self::assertSame('`fld` = uuid()', $result); // Test that the uuid function as a value uses the uuid function to generate a value $result = $this->insertEdit->getQueryValueForUpdate( new EditField( 'fld', 'uuid()', 'uuid', false, false, false, '', null, '', false, ), ); self::assertSame('`fld` = uuid()', $result); // Test that the uuid type does not have a default value other than null when it is nullable $result = $this->insertEdit->getQueryValueForUpdate( new EditField( 'fld', '', 'uuid', false, true, false, '', null, '', false, ), ); self::assertSame('`fld` = NULL', $result); } /** * Test for verifyWhetherValueCanBeTruncatedAndAppendExtraData */ public function testVerifyWhetherValueCanBeTruncatedAndAppendExtraData(): void { $extraData = ['isNeedToRecheck' => true]; $_POST['where_clause'] = []; $_POST['where_clause'][0] = 1; $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $resultStub = self::createMock(DummyResult::class); $dbi->expects(self::exactly(3)) ->method('tryQuery') ->with('SELECT `table`.`a` FROM `db`.`table` WHERE 1') ->willReturn($resultStub); $meta1 = FieldHelper::fromArray(['type' => MYSQLI_TYPE_TINY]); $meta2 = FieldHelper::fromArray(['type' => MYSQLI_TYPE_TINY]); $meta3 = FieldHelper::fromArray(['type' => MYSQLI_TYPE_TIMESTAMP]); $dbi->expects(self::exactly(3)) ->method('getFieldsMeta') ->willReturn([$meta1], [$meta2], [$meta3]); $resultStub->expects(self::exactly(3)) ->method('fetchValue') ->willReturn(false, '123', '2013-08-28 06:34:14'); DatabaseInterface::$instance = $dbi; $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); $this->insertEdit->verifyWhetherValueCanBeTruncatedAndAppendExtraData('db', 'table', 'a', $extraData); self::assertFalse($extraData['isNeedToRecheck']); $this->insertEdit->verifyWhetherValueCanBeTruncatedAndAppendExtraData('db', 'table', 'a', $extraData); self::assertSame('123', $extraData['truncatableFieldValue']); self::assertTrue($extraData['isNeedToRecheck']); $this->insertEdit->verifyWhetherValueCanBeTruncatedAndAppendExtraData('db', 'table', 'a', $extraData); self::assertSame('2013-08-28 06:34:14.000000', $extraData['truncatableFieldValue']); self::assertTrue($extraData['isNeedToRecheck']); } /** * Test for getTableColumns */ public function testGetTableColumns(): void { $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $dbi->expects(self::once()) ->method('selectDb') ->with('db'); $columns = [ new ColumnFull('b', 'd', null, false, '', null, '', '', ''), new ColumnFull('f', 'h', null, true, '', null, '', '', ''), ]; $dbi->expects(self::once()) ->method('getColumns') ->with('db', 'table') ->willReturn($columns); DatabaseInterface::$instance = $dbi; $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); $result = $this->insertEdit->getTableColumns('db', 'table'); self::assertEquals( [ new ColumnFull('b', 'd', null, false, '', null, '', '', ''), new ColumnFull('f', 'h', null, true, '', null, '', '', ''), ], $result, ); } /** * Test for determineInsertOrEdit */ public function testDetermineInsertOrEdit(): void { $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $resultStub = self::createMock(DummyResult::class); $dbi->expects(self::exactly(2)) ->method('query') ->willReturn($resultStub); DatabaseInterface::$instance = $dbi; $_POST['where_clause'] = '1'; $_SESSION['edit_next'] = '1'; $_POST['ShowFunctionFields'] = true; $_POST['ShowFieldTypesInDataEditView'] = true; $_POST['after_insert'] = 'edit_next'; $config = Config::getInstance(); $config->settings['InsertRows'] = 2; $config->settings['ShowSQL'] = false; $_POST['default_action'] = 'insert'; $responseMock = $this->getMockBuilder(ResponseRenderer::class) ->disableOriginalConstructor() ->onlyMethods(['addHtml']) ->getMock(); $restoreInstance = ResponseRenderer::getInstance(); $response = new ReflectionProperty(ResponseRenderer::class, 'instance'); $response->setValue(null, $responseMock); $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); $result = $this->insertEdit->determineInsertOrEdit('1', 'db', 'table'); self::assertEquals( [false, null, [1], null, [$resultStub], [[]], false, 'edit_next'], $result, ); // case 2 unset($_POST['where_clause']); unset($_SESSION['edit_next']); $_POST['default_action'] = ''; $result = $this->insertEdit->determineInsertOrEdit(null, 'db', 'table'); $response->setValue(null, $restoreInstance); self::assertSame( [true, null, [], null, $resultStub, [false, false], false, 'edit_next'], $result, ); } /** * Test for getCommentsMap */ public function testGetCommentsMap(): void { $config = Config::getInstance(); $config->settings['ShowPropertyComments'] = false; $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $dbi->expects(self::once()) ->method('getColumns') ->with('db', 'table', true) ->willReturn([new ColumnFull('d', 'd', null, false, '', null, '', '', 'b')]); $dbi->expects(self::any()) ->method('getTable') ->willReturn(new Table('table', 'db', $dbi)); DatabaseInterface::$instance = $dbi; $this->insertEdit = new InsertEdit( $dbi, new Relation($dbi), new Transformations(), new FileListing(), new Template(), Config::getInstance(), ); self::assertSame( [], $this->insertEdit->getCommentsMap('db', 'table'), ); $config->settings['ShowPropertyComments'] = true; self::assertSame( ['d' => 'b'], $this->insertEdit->getCommentsMap('db', 'table'), ); } /** * Test for getHtmlForIgnoreOption */ public function testGetHtmlForIgnoreOption(): void { $expected = '<input type="checkbox" %sname="insert_ignore_1"' . ' id="insert_ignore_1"><label for="insert_ignore_1">' . 'Ignore</label><br>' . "\n"; $checked = 'checked="checked" '; self::assertSame( sprintf($expected, $checked), $this->insertEdit->getHtmlForIgnoreOption(1), ); self::assertSame( sprintf($expected, ''), $this->insertEdit->getHtmlForIgnoreOption(1, false), ); } /** * Test for getHtmlForInsertEditFormColumn */ public function testGetHtmlForInsertEditFormColumn(): void { $_SESSION[' HMAC_secret '] = hash('sha1', 'test'); $GLOBALS['plugin_scripts'] = []; $foreigners = ['foreign_keys_data' => []]; $tableColumn = new ColumnFull('col', 'varchar(20)', null, true, '', null, '', 'insert,update,select', ''); $repopulate = [md5('col') => 'val']; $columnMime = [ 'input_transformation' => 'Input/Image_JPEG_Upload.php', 'input_transformation_options' => '150', ]; // Test w/ input transformation $actual = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getHtmlForInsertEditFormColumn', [ $tableColumn, 0, [], -1, false, [], 0, false, $foreigners, 'table', 'db', 0, '', '', $repopulate, $columnMime, '', ], ); $actual = $this->parseString($actual); self::assertStringContainsString('col', $actual); self::assertStringContainsString('<option>AES_ENCRYPT</option>', $actual); self::assertStringContainsString('<span class="column_type" dir="ltr">varchar(20)</span>', $actual); self::assertStringContainsString('<tr class="noclick">', $actual); self::assertStringContainsString('<span class="default_value hide">', $actual); self::assertStringContainsString('<img src="" width="150" height="100" alt="Image preview here">', $actual); self::assertStringContainsString( '<input type="file" ' . 'name="fields_upload[multi_edit][0][d89e2ddb530bb8953b290ab0793aecb0]" ' . 'accept="image/*" ' . 'class="image-upload"' . '>', $actual, ); // Test w/o input_transformation $tableColumn = new ColumnFull('qwerty', 'datetime', null, true, '', null, '', 'insert,update,select', ''); $repopulate = [md5('qwerty') => '12-10-14']; $actual = $this->callFunction( $this->insertEdit, InsertEdit::class, 'getHtmlForInsertEditFormColumn', [ $tableColumn, 0, [], -1, true, [], 0, false, $foreigners, 'table', 'db', 0, '', '', $repopulate, [], '', ], ); $actual = $this->parseString($actual); self::assertStringContainsString('qwerty', $actual); self::assertStringContainsString('<option>UUID</option>', $actual); self::assertStringContainsString('<span class="column_type" dir="ltr">datetime</span>', $actual); self::assertStringContainsString( '<input type="text" name="fields[multi_edit][0][d8578edf8458ce06fbc5bb76a58c5ca4]" value="12-10-14.000000"', $actual, ); self::assertStringContainsString( '<select name="funcs[multi_edit][0][d8578edf8458ce06fbc5bb76a58c5ca4]"' . ' onchange="return verificationsAfterFieldChange(\'d8578edf8458ce06fbc5bb76a58c5ca4\',' . ' \'0\', \'datetime\')" id="field_1_1">', $actual, ); self::assertStringContainsString('<option>DATE</option>', $actual); self::assertStringContainsString( '<input type="hidden" name="fields_null_prev[multi_edit][0][d8578edf8458ce06fbc5bb76a58c5ca4]">', $actual, ); self::assertStringContainsString( '<input type="checkbox" class="checkbox_null"' . ' name="fields_null[multi_edit][0][d8578edf8458ce06fbc5bb76a58c5ca4]" id="field_1_2"' . ' aria-label="Use the NULL value for this column.">', $actual, ); self::assertStringContainsString( '<input type="hidden" class="nullify_code"' . ' name="nullify_code[multi_edit][0][d8578edf8458ce06fbc5bb76a58c5ca4]" value="5"', $actual, ); self::assertStringContainsString( '<input type="hidden" class="hashed_field"' . ' name="hashed_field[multi_edit][0][d8578edf8458ce06fbc5bb76a58c5ca4]" ' . 'value="d8578edf8458ce06fbc5bb76a58c5ca4">', $actual, ); self::assertStringContainsString( '<input type="hidden" class="multi_edit"' . ' name="multi_edit[multi_edit][0][d8578edf8458ce06fbc5bb76a58c5ca4]" value="[multi_edit][0]"', $actual, ); } /** * Test for getHtmlForInsertEditRow */ public function testGetHtmlForInsertEditRow(): void { $GLOBALS['plugin_scripts'] = []; $config = Config::getInstance(); $config->settings['LongtextDoubleTextarea'] = true; $config->settings['CharEditing'] = 'input'; $config->settings['TextareaRows'] = 10; $config->settings['TextareaCols'] = 11; $foreigners = ['foreign_keys_data' => []]; $tableColumns = [ new ColumnFull('test', 'longtext', null, true, '', null, '', 'select,insert,update,references', ''), ]; $resultStub = self::createMock(DummyResult::class); $resultStub->expects(self::any()) ->method('getFieldsMeta') ->willReturn([FieldHelper::fromArray(['type' => 0, 'length' => -1])]); $actual = $this->insertEdit->getHtmlForInsertEditRow( [], $tableColumns, [], $resultStub, false, [], false, $foreigners, 'table', 'db', 0, 'ltr', [], ['wc'], ); self::assertStringContainsString('test', $actual); self::assertStringContainsString('<th>Column</th>', $actual); self::assertStringContainsString('<a', $actual); self::assertStringContainsString('<th class="w-50">Value</th>', $actual); self::assertStringContainsString('<span class="column_type" dir="ltr">longtext</span>', $actual); self::assertStringContainsString( '<textarea name="fields[multi_edit][0][098f6bcd4621d373cade4e832627b4f6]" id="field_1_3"' . ' data-type="CHAR" dir="ltr" rows="20" cols="22"', $actual, ); } /** * Test for getHtmlForInsertEditRow based on the column privilges */ public function testGetHtmlForInsertEditRowBasedOnColumnPrivileges(): void { $GLOBALS['plugin_scripts'] = []; $config = Config::getInstance(); $config->settings['LongtextDoubleTextarea'] = true; $config->settings['CharEditing'] = 'input'; $foreigners = ['foreign_keys_data' => []]; // edit $tableColumns = [ new ColumnFull('foo', 'longtext', null, true, '', null, '', 'select,insert,update,references', ''), new ColumnFull('bar', 'longtext', null, true, '', null, '', 'select,insert,references', ''), ]; $resultStub = self::createMock(DummyResult::class); $resultStub->expects(self::any()) ->method('getFieldsMeta') ->willReturn([ FieldHelper::fromArray(['type' => 0, 'length' => -1]), FieldHelper::fromArray(['type' => 0, 'length' => -1]), FieldHelper::fromArray(['type' => 0, 'length' => -1]), ]); $actual = $this->insertEdit->getHtmlForInsertEditRow( [], $tableColumns, [], $resultStub, false, [], false, $foreigners, 'table', 'db', 0, '', [], ['wc'], ); self::assertStringContainsString('foo', $actual); self::assertStringContainsString('bar', $actual); // insert $tableColumns = [ new ColumnFull('foo', 'longtext', null, true, '', null, '', 'select,insert,update,references', ''), new ColumnFull('bar', 'longtext', null, true, '', null, '', 'select,update,references', ''), new ColumnFull('point', 'point', null, false, '', null, '', 'select,update,references', ''), ]; $actual = $this->insertEdit->getHtmlForInsertEditRow( [], $tableColumns, [], $resultStub, true, [], false, $foreigners, 'table', 'db', 0, '', [], ['wc'], ); self::assertStringContainsString('foo', $actual); self::assertStringContainsString( '<textarea name="fields[multi_edit][0][37b51d194a7513e45b56f6524f2d51f2]"', $actual, ); self::assertStringContainsString( '<a href="#" ><span class="text-nowrap"><img src="themes/dot.gif" title="Edit/Insert"' . ' alt="Edit/Insert" class="icon ic_b_edit"> Edit/Insert</span></a>', $actual, ); } /** * Convert mixed type value to string */ private function parseString(mixed $value): string { if (is_string($value)) { return $value; } if (is_object($value) || is_scalar($value)) { return (string) $value; } return ''; } }
Close