Merge branch 'QA_5_1' into STABLE
This commit is contained in:
commit
81ca97b26b
13
.browserslistrc
Normal file
13
.browserslistrc
Normal file
@ -0,0 +1,13 @@
|
||||
# https://github.com/browserslist/browserslist#readme
|
||||
|
||||
>= 1%
|
||||
last 1 major version
|
||||
not dead
|
||||
Chrome >= 45
|
||||
Firefox >= 38
|
||||
Edge >= 12
|
||||
Explorer >= 10
|
||||
iOS >= 9
|
||||
Safari >= 9
|
||||
Android >= 4.4
|
||||
Opera >= 30
|
||||
@ -10,5 +10,8 @@ charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[{*.{sql,scss,css,twig},package.json,.travis.yml}]
|
||||
[{*.{sql,scss,css,twig,yml},package.json}]
|
||||
indent_size = 2
|
||||
|
||||
[*.twig]
|
||||
insert_final_newline = false
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
js/vendor/
|
||||
js/dist/
|
||||
tmp/
|
||||
vendor/
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
{
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:no-jquery/deprecated"
|
||||
"plugin:no-jquery/deprecated",
|
||||
"plugin:compat/recommended"
|
||||
],
|
||||
"plugins": ["no-jquery"],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"jquery": true
|
||||
},
|
||||
"globals": {
|
||||
@ -34,9 +36,6 @@
|
||||
"new-cap": "error",
|
||||
"no-array-constructor": "error",
|
||||
"no-eval": "error",
|
||||
"no-jquery/no-event-shorthand": "off",
|
||||
"no-jquery/no-is-array": "off",
|
||||
"no-jquery/no-sizzle": "off",
|
||||
"no-loop-func": "error",
|
||||
"no-multiple-empty-lines": "error",
|
||||
"no-new-func": "error",
|
||||
|
||||
16
.gitattributes
vendored
16
.gitattributes
vendored
@ -1,7 +1,6 @@
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
.github export-ignore
|
||||
.travis.yml export-ignore
|
||||
.scrutinizer.yml export-ignore
|
||||
.jshintrc export-ignore
|
||||
.stylelintrc.json export-ignore
|
||||
@ -12,14 +11,21 @@ codecov.yml export-ignore
|
||||
build.xml export-ignore
|
||||
phpcs.xml.dist export-ignore
|
||||
phpstan.neon.dist export-ignore
|
||||
phpstan-baseline.neon export-ignore
|
||||
psalm.xml export-ignore
|
||||
psalm-baseline.xml export-ignore
|
||||
DCO export-ignore
|
||||
.editorconfig export-ignore
|
||||
# Exclude only the following files and not all files in test/
|
||||
# This is because some packaging teams need our test files but not the CI related files
|
||||
test/doctum-config.php export-ignore
|
||||
test/bootstrap-phpstan.php export-ignore
|
||||
test/install-browserstack export-ignore
|
||||
test/start-local-server export-ignore
|
||||
test/bootstrap-static.php export-ignore
|
||||
test/config.e2e.inc.php export-ignore
|
||||
test/phpstan-constants.php export-ignore
|
||||
test/*-local-server export-ignore
|
||||
test/*.conf export-ignore
|
||||
test/*.ini export-ignore
|
||||
test/ci-* export-ignore
|
||||
test/ci-phplint export-ignore
|
||||
.browserslistrc export-ignore
|
||||
CODE_OF_CONDUCT.md export-ignore
|
||||
CONTRIBUTING.md export-ignore
|
||||
|
||||
92
.github/workflows/lint-and-analyse-php.yml
vendored
Normal file
92
.github/workflows/lint-and-analyse-php.yml
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
name: Lint and analyse php files
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- master
|
||||
- QA_**
|
||||
|
||||
jobs:
|
||||
lint-node:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: yarn cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: Install modules
|
||||
run: yarn install --non-interactive
|
||||
- name: Lint JS files
|
||||
run: yarn run js-lint --quiet
|
||||
- name: Lint CSS files
|
||||
run: yarn run css-lint
|
||||
|
||||
lint-php-files:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Lint PHP files
|
||||
run: ./test/ci-phplint
|
||||
- name: Use php 7.1
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 7.1
|
||||
extensions: mbstring, iconv, mysqli, zip, gd
|
||||
tools: composer:v2
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: composer validate
|
||||
- name: Cache module
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.composer/cache/
|
||||
key: composer-cache
|
||||
- name: Cache coding-standard
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .phpcs-cache
|
||||
key: phpcs-cache
|
||||
- name: Install dependencies
|
||||
run: composer install
|
||||
- name: Lint PHP files
|
||||
run: ./test/ci-phplint
|
||||
- name: Check coding-standard
|
||||
run: composer phpcs
|
||||
- name: Check twig templates
|
||||
run: php scripts/console lint:twig templates --show-deprecations
|
||||
|
||||
analyse-php:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use php 7.2
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 7.2
|
||||
extensions: mbstring, iconv, mysqli, zip, gd
|
||||
tools: composer:v2
|
||||
- name: Cache module
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.composer/cache/
|
||||
key: composer-cache
|
||||
- name: Install dependencies
|
||||
run: composer install
|
||||
- name: Analyse files with phpstan
|
||||
run: composer phpstan -- --memory-limit 2G
|
||||
- name: Analyse files with psalm
|
||||
run: composer psalm
|
||||
22
.github/workflows/lint-docs.yml
vendored
Normal file
22
.github/workflows/lint-docs.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
name: Lint php documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- master
|
||||
- QA_**
|
||||
|
||||
jobs:
|
||||
lint-docs:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Lint phpdoc blocks
|
||||
uses: sudo-bot/action-doctum@v5
|
||||
with:
|
||||
config-file: test/doctum-config.php
|
||||
method: "parse"
|
||||
cli-args: "--output-format=github --no-ansi --no-progress -v --ignore-parse-errors"
|
||||
15
.github/workflows/lock.yml
vendored
Normal file
15
.github/workflows/lock.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
name: 'Lock threads'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v2
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
process-only: 'issues'
|
||||
issue-lock-inactive-days: 365
|
||||
66
.github/workflows/other-tools.yml
vendored
Normal file
66
.github/workflows/other-tools.yml
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
name: Check other tools and scripts
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- master
|
||||
- QA_**
|
||||
|
||||
jobs:
|
||||
build-documentation:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.6'
|
||||
- name: Install Sphinx for the documentation build
|
||||
run: pip install 'Sphinx'
|
||||
- name: Build the documentation
|
||||
run: make -C doc html SPHINXOPTS='-n -W -a'
|
||||
|
||||
build-release:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use php 7.1
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 7.1
|
||||
extensions: mbstring, iconv, mysqli, zip, gd
|
||||
tools: composer:v2
|
||||
- name: Cache module
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.composer/cache/
|
||||
key: composer-cache
|
||||
- name: Install dependencies
|
||||
run: composer install
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: yarn cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: Install modules
|
||||
run: yarn install --non-interactive
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.6'
|
||||
- name: Install gettext
|
||||
run: sudo apt-get install -y gettext
|
||||
- name: Install Sphinx for the documentation build
|
||||
run: pip install 'Sphinx'
|
||||
- name: Build the release
|
||||
run: ./scripts/create-release.sh --ci
|
||||
129
.github/workflows/test-selenium.yml
vendored
Normal file
129
.github/workflows/test-selenium.yml
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
name: Run selenium tests
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- master
|
||||
- QA_**
|
||||
|
||||
jobs:
|
||||
test-selenium:
|
||||
name: Selenium tests on php ${{ matrix.php-version }} and ${{ matrix.os }}
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[ci selenium skip]')"
|
||||
runs-on: ${{ matrix.os }}
|
||||
services:
|
||||
database-server:
|
||||
image: ${{ matrix.db-server }}
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: testbench
|
||||
ports:
|
||||
- "3306:3306"
|
||||
options: >-
|
||||
--health-cmd="mysqladmin ping"
|
||||
--health-interval=10s
|
||||
--health-timeout=5s
|
||||
--health-retries=3
|
||||
selenium-server:
|
||||
image: selenium/standalone-chrome:3.141.59
|
||||
volumes:
|
||||
- /dev/shm:/dev/shm
|
||||
options: >-
|
||||
--health-cmd "/opt/bin/check-grid.sh"
|
||||
env:
|
||||
SCREEN_WIDTH: 1920
|
||||
SCREEN_HEIGHT: 1080
|
||||
ports:
|
||||
- "4444:4444"
|
||||
docker-host-bridge:
|
||||
# Allow accessing localhost ports from docker containers.
|
||||
# See https://github.com/qoomon/docker-host
|
||||
image: qoomon/docker-host
|
||||
options: >-
|
||||
--name docker-host-bridge
|
||||
--hostname docker-host-bridge
|
||||
--add-host docker-host-bridge:127.0.0.1
|
||||
--cap-add=NET_ADMIN
|
||||
--cap-add=NET_RAW
|
||||
--restart on-failure
|
||||
strategy:
|
||||
matrix:
|
||||
php-version: ["7.1"]
|
||||
os: [ubuntu-latest]
|
||||
db-server: ["mysql:5.7"]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install gettext
|
||||
run: sudo apt-get install -y gettext
|
||||
- name: Generate mo files
|
||||
run: ./scripts/generate-mo --quiet
|
||||
- name: Use php ${{ matrix.php-version }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-version }}
|
||||
extensions: mbstring, iconv, mysqli, zip, gd
|
||||
tools: composer:v2
|
||||
- name: Cache module
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.composer/cache/
|
||||
key: composer-cache
|
||||
- name: Install dependencies
|
||||
run: composer install --no-interaction
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: yarn cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: Install modules
|
||||
run: yarn install --non-interactive --production
|
||||
- name: Install nginx and php-fpm
|
||||
run: sudo apt-get install -y nginx php7.1-fpm
|
||||
- name: Copy the config
|
||||
run: cp test/config.e2e.inc.php config.inc.php
|
||||
- name: Start server
|
||||
env:
|
||||
CI_MODE: selenium
|
||||
FPM_PATH: php-fpm7.1
|
||||
SKIP_STANDALONE: 1
|
||||
run: |
|
||||
./test/start-local-server
|
||||
echo ::set-output name=SELENIUM_TEMPDIR::"$(cat /tmp/last_temp_dir_phpMyAdminTests)"
|
||||
id: start-local-server
|
||||
- name: Run selenium tests
|
||||
env:
|
||||
CI_MODE: selenium
|
||||
TESTSUITE_SELENIUM_BROWSER: chrome
|
||||
TESTSUITE_USER: root
|
||||
TESTSUITE_PASSWORD: testbench
|
||||
# Port defined in test/nginx.conf
|
||||
TESTSUITE_URL: http://docker-host-bridge:8000
|
||||
TESTSUITE_DATABASE_PREFIX: "selenium"
|
||||
TESTSUITE_SELENIUM_HOST: "127.0.0.1"
|
||||
TESTSUITE_SELENIUM_PORT: "4444"
|
||||
run: ./vendor/bin/phpunit --group selenium --verbose --debug --no-coverage --stop-on-skipped
|
||||
- name: Output logs and stop server
|
||||
env:
|
||||
CI_MODE: selenium
|
||||
SELENIUM_TEMPDIR: ${{ steps.start-local-server.outputs.SELENIUM_TEMPDIR }}
|
||||
if: ${{ success() || failure() }}
|
||||
run: |
|
||||
if [ -f "${SELENIUM_TEMPDIR}/php.log" ] ; then cat "${SELENIUM_TEMPDIR}/php.log" ; fi
|
||||
if [ -f "${SELENIUM_TEMPDIR}/nginx-error.log" ] ; then cat "${SELENIUM_TEMPDIR}/nginx-error.log" ; fi
|
||||
./test/stop-local-server
|
||||
- name: 'Upload screenshots'
|
||||
uses: actions/upload-artifact@v2
|
||||
if: ${{ success() || failure() }}
|
||||
with:
|
||||
name: selenium-screenshots
|
||||
path: ${{ github.workspace }}/build/selenium/**/*
|
||||
retention-days: 1
|
||||
212
.github/workflows/tests.yml
vendored
Normal file
212
.github/workflows/tests.yml
vendored
Normal file
@ -0,0 +1,212 @@
|
||||
name: Run tests
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- master
|
||||
- QA_**
|
||||
|
||||
jobs:
|
||||
test-php:
|
||||
name: Test on php ${{ matrix.php-version }} and ${{ matrix.os }}
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
php-version: ["7.1", "7.2", "7.3", "7.4", "8.0"]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install gettext
|
||||
run: sudo apt-get install -y gettext
|
||||
- name: Generate mo files
|
||||
run: ./scripts/generate-mo --quiet
|
||||
- name: Use php ${{ matrix.php-version }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-version }}
|
||||
extensions: mbstring, iconv, mysqli, zip, gd
|
||||
coverage: xdebug
|
||||
tools: composer:v2
|
||||
- name: Cache module
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.composer/cache/
|
||||
key: composer-cache
|
||||
- name: Install dependencies
|
||||
run: composer install --no-interaction
|
||||
- name: Run php tests
|
||||
run: composer run phpunit -- --exclude-group selenium
|
||||
- name: Send coverage
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
flags: unit-${{ matrix.php-version }}-${{ matrix.os }}
|
||||
name: phpunit-${{ matrix.php-version }}-${{ matrix.os }}
|
||||
- name: Send coverage to Scrutinizer
|
||||
uses: sudo-bot/action-scrutinizer@latest
|
||||
# Upload can fail on forks
|
||||
continue-on-error: true
|
||||
with:
|
||||
cli-args: "--format=php-clover build/logs/clover.xml"
|
||||
- name: Send coverage to Codacy
|
||||
# Upload can fail on forks or if the secret is missing
|
||||
continue-on-error: true
|
||||
uses: codacy/codacy-coverage-reporter-action@master
|
||||
with:
|
||||
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
||||
coverage-reports: build/logs/clover.xml
|
||||
|
||||
test-php-dbase:
|
||||
name: Test on php ${{ matrix.php-version }} and ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
strategy:
|
||||
matrix:
|
||||
php-version: ["7.1"]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install gettext
|
||||
run: sudo apt-get install -y gettext
|
||||
- name: Generate mo files
|
||||
run: ./scripts/generate-mo --quiet
|
||||
- name: Use php ${{ matrix.php-version }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-version }}
|
||||
extensions: dbase, mbstring, iconv, mysqli, zip, gd
|
||||
coverage: xdebug
|
||||
tools: composer:v2
|
||||
- name: Cache module
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.composer/cache/
|
||||
key: composer-cache
|
||||
- name: Install dependencies
|
||||
run: composer install
|
||||
- name: Run php tests
|
||||
run: composer run phpunit -- --exclude-group selenium
|
||||
- name: Send coverage
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
flags: dbase-extension
|
||||
name: php-7.1-dbase-enabled
|
||||
- name: Send coverage to Scrutinizer
|
||||
uses: sudo-bot/action-scrutinizer@latest
|
||||
# Upload can fail on forks
|
||||
continue-on-error: true
|
||||
with:
|
||||
cli-args: "--format=php-clover build/logs/clover.xml"
|
||||
- name: Send coverage to Codacy
|
||||
# Upload can fail on forks or if the secret is missing
|
||||
continue-on-error: true
|
||||
uses: codacy/codacy-coverage-reporter-action@master
|
||||
with:
|
||||
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
||||
coverage-reports: build/logs/clover.xml
|
||||
|
||||
test-php-recode:
|
||||
name: Test on php ${{ matrix.php-version }} and ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
strategy:
|
||||
matrix:
|
||||
php-version: ["7.1"]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install gettext
|
||||
run: sudo apt-get install -y gettext
|
||||
- name: Generate mo files
|
||||
run: ./scripts/generate-mo --quiet
|
||||
- name: Use php ${{ matrix.php-version }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-version }}
|
||||
extensions: recode, mbstring, iconv, mysqli, zip, gd
|
||||
coverage: xdebug
|
||||
tools: composer:v2
|
||||
- name: Cache module
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.composer/cache/
|
||||
key: composer-cache
|
||||
- name: Install dependencies
|
||||
run: composer install
|
||||
- name: Run php tests
|
||||
run: composer run phpunit -- --exclude-group selenium
|
||||
- name: Send coverage
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
flags: recode-extension
|
||||
name: php-7.1-recode-enabled
|
||||
- name: Send coverage to Scrutinizer
|
||||
uses: sudo-bot/action-scrutinizer@latest
|
||||
# Upload can fail on forks
|
||||
continue-on-error: true
|
||||
with:
|
||||
cli-args: "--format=php-clover build/logs/clover.xml"
|
||||
- name: Send coverage to Codacy
|
||||
# Upload can fail on forks or if the secret is missing
|
||||
continue-on-error: true
|
||||
uses: codacy/codacy-coverage-reporter-action@master
|
||||
with:
|
||||
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
||||
coverage-reports: build/logs/clover.xml
|
||||
|
||||
test-php-random:
|
||||
name: Test on php ${{ matrix.php-version }} and ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
strategy:
|
||||
matrix:
|
||||
php-version: ["7.4"]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install gettext
|
||||
run: sudo apt-get install -y gettext
|
||||
- name: Generate mo files
|
||||
run: ./scripts/generate-mo --quiet
|
||||
- name: Use php ${{ matrix.php-version }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-version }}
|
||||
extensions: mbstring, iconv, mysqli, zip, gd
|
||||
tools: composer:v2
|
||||
- name: Cache module
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.composer/cache/
|
||||
key: composer-cache
|
||||
- name: Install dependencies
|
||||
run: composer install
|
||||
- name: Run php tests
|
||||
# This one is allowed to fail, but we hope it will not
|
||||
continue-on-error: true
|
||||
run: composer run phpunit -- --exclude-group selenium --order-by=random --stop-on-failure
|
||||
|
||||
test-js:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: yarn cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: Install modules
|
||||
run: yarn install --non-interactive
|
||||
- name: Run tests
|
||||
run: yarn test
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -59,5 +59,4 @@ composer.lock
|
||||
# NPM
|
||||
/node_modules/
|
||||
phpstan.neon
|
||||
libraries/cache/
|
||||
js/dist/
|
||||
/setup/styles.css.map
|
||||
|
||||
@ -6,6 +6,7 @@ filter:
|
||||
excluded_paths:
|
||||
- build/
|
||||
- js/vendor/
|
||||
- js/dist/
|
||||
- node_modules/
|
||||
- tmp/
|
||||
- vendor/
|
||||
@ -13,6 +14,10 @@ filter:
|
||||
checks:
|
||||
javascript: true
|
||||
php: true
|
||||
tools:
|
||||
external_code_coverage:
|
||||
runs: 4 # php 7.x versions
|
||||
timeout: 900 # 15 min
|
||||
build:
|
||||
nodes:
|
||||
analysis:
|
||||
|
||||
@ -16,6 +16,14 @@
|
||||
],
|
||||
"ignore": ["after-comment"],
|
||||
"ignoreAtRules": ["else"]
|
||||
}]
|
||||
}],
|
||||
"value-keyword-case": [
|
||||
"lower",
|
||||
{
|
||||
"ignoreProperties": [
|
||||
"$font-family-monospace"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
207
.travis.yml
207
.travis.yml
@ -1,207 +0,0 @@
|
||||
dist: xenial
|
||||
|
||||
language: php
|
||||
|
||||
stages:
|
||||
- name: "Lint and analyse code"
|
||||
- name: "PHP Unit tests"
|
||||
- name: "Documentation"
|
||||
- name: "Other tests"
|
||||
|
||||
install:
|
||||
- nvm install 10
|
||||
- composer install --no-interaction
|
||||
- yarn install --non-interactive
|
||||
|
||||
before_script:
|
||||
- export TESTSUITE_PASSWORD=`openssl rand -base64 30`
|
||||
- export TESTSUITE_BROWSERSTACK_KEY=`echo cHlDcHJTNmZwZjVlaUR2RmV6VkU= | base64 --decode`
|
||||
- mysql -uroot -e "CREATE DATABASE IF NOT EXISTS test"
|
||||
- mysql -uroot < sql/create_tables.sql
|
||||
- mysql -uroot -e "SET PASSWORD = PASSWORD('$TESTSUITE_PASSWORD')"
|
||||
- ./test/start-local-server
|
||||
|
||||
script:
|
||||
- ./scripts/generate-mo --quiet
|
||||
- ./vendor/bin/phpunit --configuration phpunit.xml.dist --exclude-group selenium
|
||||
|
||||
after_script:
|
||||
- if [ -f php.log ] ; then cat php.log ; fi
|
||||
- if [ -f nginx-error.log ] ; then cat nginx-error.log ; fi
|
||||
- if [ -f config.inc.php ] ; then rm -rf config.inc.php; fi
|
||||
- if [ "$CI_MODE" = "selenium" ] ; then ~/browserstack/BrowserStackLocal --daemon stop; fi
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
- bash <(curl -Ls https://coverage.codacy.com/get.sh)
|
||||
|
||||
services:
|
||||
- mysql
|
||||
|
||||
cache:
|
||||
pip: true
|
||||
yarn: true
|
||||
directories:
|
||||
- $HOME/.composer/cache/
|
||||
- $HOME/browserstack
|
||||
- node_modules
|
||||
|
||||
jobs:
|
||||
allow_failures:
|
||||
- php: nightly
|
||||
- os: osx
|
||||
|
||||
include:
|
||||
- stage: "Lint and analyse code"
|
||||
name: "Lint files"
|
||||
before_install: phpenv config-rm xdebug.ini
|
||||
before_script: skip
|
||||
after_script: skip
|
||||
after_success: skip
|
||||
script:
|
||||
- ./test/ci-phplint
|
||||
- composer phpcs
|
||||
- yarn run js-lint --quiet
|
||||
- yarn run css-lint
|
||||
|
||||
- stage: "Lint and analyse code"
|
||||
name: "Run phpstan"
|
||||
before_install: phpenv config-rm xdebug.ini
|
||||
before_script: skip
|
||||
after_script: skip
|
||||
after_success: skip
|
||||
script: composer phpstan
|
||||
|
||||
- stage: "PHP Unit tests"
|
||||
php: 7.1
|
||||
name: "PHP 7.1"
|
||||
env: CI_MODE=test
|
||||
|
||||
- stage: "PHP Unit tests"
|
||||
php: 7.2
|
||||
name: "PHP 7.2"
|
||||
env: CI_MODE=test
|
||||
|
||||
- stage: "PHP Unit tests"
|
||||
php: 7.3
|
||||
name: "PHP 7.3"
|
||||
env: CI_MODE=test
|
||||
|
||||
- stage: "PHP Unit tests"
|
||||
php: 7.4
|
||||
name: "PHP 7.4"
|
||||
env: CI_MODE=test
|
||||
before_install: phpenv config-rm xdebug.ini
|
||||
|
||||
- stage: "PHP Unit tests"
|
||||
php: nightly
|
||||
name: "PHP nightly"
|
||||
env: CI_MODE=test
|
||||
install:
|
||||
- nvm install 10
|
||||
- composer install --no-interaction --ignore-platform-reqs
|
||||
- yarn install --non-interactive
|
||||
|
||||
- stage: "PHP Unit tests"
|
||||
name: "OSX"
|
||||
os: osx
|
||||
env: CI_MODE=test
|
||||
language: node_js
|
||||
node_js: 10
|
||||
before_install:
|
||||
- export PATH="/usr/local/opt/gettext/bin:$PATH"
|
||||
- echo "memory_limit=-1" > /usr/local/etc/php/7.4/conf.d/50-travis.ini
|
||||
- echo "pcre.jit=0" >> /usr/local/etc/php/7.4/conf.d/50-travis.ini
|
||||
- mysql.server start
|
||||
- sleep 5
|
||||
# Enable password access
|
||||
- mysql -e "SET PASSWORD FOR 'root'@'localhost' = PASSWORD('');"
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- php
|
||||
- composer
|
||||
- mariadb
|
||||
update: true
|
||||
|
||||
- stage: "PHP Unit tests"
|
||||
name: "Windows"
|
||||
os: windows
|
||||
language: node_js
|
||||
node_js: 10
|
||||
env:
|
||||
- CI_MODE=test
|
||||
- YARN_GPG=no
|
||||
before_install:
|
||||
- choco install php composer
|
||||
- choco install mariadb --version=10.4.8
|
||||
- export PATH=/c/tools/php74:/c/ProgramData/ComposerSetup/bin:/c/"Program Files"/"MariaDB 10.4"/bin:$PATH
|
||||
- PHP_EXTENSIONS="mysqli curl bz2 gd2 pdo_mysql"
|
||||
- for php_ext in $PHP_EXTENSIONS ; do sed -i -e "s/^;extension=${php_ext}/extension=${php_ext}/" /c/tools/php74/php.ini ; done
|
||||
- sed -i -e 's/^memory_limit = .*/memory_limit = -1/' /c/tools/php74/php.ini
|
||||
- find . -type f -name "*.php" -print0 | xargs -0 sed -i ':a;N;$!ba;s/\r//g'
|
||||
install:
|
||||
- composer install --no-interaction
|
||||
- yarn install --non-interactive
|
||||
|
||||
- stage: "PHP Unit tests"
|
||||
php: 7.1
|
||||
name: "PHP 7.1 with dbase extension"
|
||||
env: CI_MODE=test
|
||||
install:
|
||||
- nvm install 10
|
||||
- pecl channel-update pecl.php.net
|
||||
- pecl install dbase
|
||||
- php -m |grep -F 'dbase'
|
||||
- composer install --no-interaction
|
||||
- yarn install --non-interactive
|
||||
|
||||
- stage: "Documentation"
|
||||
name: "Build docs"
|
||||
before_script: skip
|
||||
after_script: skip
|
||||
after_success: skip
|
||||
install:
|
||||
- source ~/virtualenv/python3.6/bin/activate
|
||||
- pip install 'Sphinx'
|
||||
script: ./test/ci-docs
|
||||
|
||||
- stage: "Documentation"
|
||||
name: "Build API docs"
|
||||
before_install: phpenv config-rm xdebug.ini
|
||||
before_script: skip
|
||||
after_script: skip
|
||||
after_success: skip
|
||||
install: composer global require "code-lts/doctum:^5.0"
|
||||
script: $HOME/.composer/vendor/bin/doctum.php --no-interaction update ./test/doctum-config.php
|
||||
|
||||
- stage: "Other tests"
|
||||
name: "Build release"
|
||||
before_script: skip
|
||||
after_script: skip
|
||||
after_success: skip
|
||||
install:
|
||||
- nvm install 10
|
||||
- source ~/virtualenv/python3.6/bin/activate
|
||||
- pip install 'Sphinx'
|
||||
script: ./scripts/create-release.sh --ci
|
||||
|
||||
- stage: "Other tests"
|
||||
name: "Run selenium tests on Google Chrome"
|
||||
env:
|
||||
- CI_MODE=selenium
|
||||
- TESTSUITE_SELENIUM_BROWSER=chrome
|
||||
- TESTSUITE_USER=root
|
||||
- TESTSUITE_URL=http://127.0.0.1:8000
|
||||
before_install: phpenv config-rm xdebug.ini
|
||||
install:
|
||||
- nvm install 10
|
||||
- ./test/install-browserstack
|
||||
- composer install --no-interaction
|
||||
- yarn install --non-interactive
|
||||
- echo -e "<?php\n\$cfg['UploadDir'] = './test/test_data/';" > config.inc.php
|
||||
script: ./vendor/bin/phpunit --configuration phpunit.xml.nocoverage --group selenium --verbose --debug
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- nginx
|
||||
2
.weblate
2
.weblate
@ -1,3 +1,3 @@
|
||||
[weblate]
|
||||
url = https://hosted.weblate.org/api/
|
||||
translation = phpmyadmin/master
|
||||
translation = phpmyadmin/5-1
|
||||
|
||||
@ -40,7 +40,7 @@ Project maintainers who do not follow or enforce the Code of Conduct in good fai
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct/][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
[homepage]: https://www.contributor-covenant.org/
|
||||
[version]: https://www.contributor-covenant.org/version/1/4/code-of-conduct/
|
||||
|
||||
107
ChangeLog
107
ChangeLog
@ -1,6 +1,113 @@
|
||||
phpMyAdmin - ChangeLog
|
||||
======================
|
||||
|
||||
5.1.0 (2021-02-24)
|
||||
- issue #15350 Change Media (MIME) type references to Media type
|
||||
- issue #15377 Add a request router
|
||||
- issue Automatically focus input in the two-factor authentication window
|
||||
- issue #15509 Replace gender-specific pronouns with gender-neutral pronouns
|
||||
- issue #15491 Improve complexity of generated passwords
|
||||
- issue #14909 Add a configuration option to define the 1st day of week
|
||||
- issue #12726 Made user names clickable in user accounts overview
|
||||
- issue #15729 Improve virtuality dropdown for MariaDB > 10.1
|
||||
- issue #15312 Added an option to perform ALTER ONLINE (ALGORITHM=INPLACE) when editing a table structure
|
||||
- issue Added missing 'IF EXISTS' to 'DROP EVENT' when exporting databases
|
||||
- issue #15232 Improve the padding in query result tool links
|
||||
- issue #15064 Support exporting raw SQL queries
|
||||
- issue #15555 Added ip2long transformation
|
||||
- issue #15194 Fixed horizontal scroll on structure edit page
|
||||
- issue #14820 Move table hide buttons in navigation to avoid hiding a table by mistake
|
||||
- issue #14947 Use correct MySQL version if the version is 8.0 or above for documentation links
|
||||
- issue #15790 Use "MariaDB Documentation" instead of "MySQL Documentation" on a MariaDB server
|
||||
- issue #15880 Change "Show Query" link to a button
|
||||
- issue #13371 Automatically toggle the radio button to "Create a page and save it" on Designer
|
||||
- issue #12969 Tap and hold will not dismiss the error box anymore, you can now copy the error
|
||||
- issue #15582 Don't disable "Empty" table button after clicking it
|
||||
- issue #15662 Stay on the structure page after editing/adding/dropping indexes
|
||||
- issue #15663 show structure after adding a column
|
||||
- issue #16005 Remove symfony/yaml dependency
|
||||
- issue #16005 Improve performance of dependency injection system by removing yaml parsing
|
||||
- issue #15447 Disable phpMyAdmin storage database checkbox on databases list
|
||||
- issue #16001 Add autocomplete attributes on login form
|
||||
- issue #13519 Add "Preview SQL" option on Index dialog box when creating a new table
|
||||
- issue #15954 Fixed export maximal length of created query input is too small
|
||||
- issue Redesign the server status advisor page
|
||||
- issue #13124 Use same height for SQL query textarea and Columns select in SQL page
|
||||
- issue #16005 Add a new vendor constant "CACHE_DIR" that defaults to "libraries/cache/" and store routing cache into this folder
|
||||
- issue #16005 Warm-up the routing cache before building the release
|
||||
- issue #16005 Use --optimize-autoloader when installing composer vendors before building the release
|
||||
- issue #15992 Add back the table name to the printable version on "Structure" page
|
||||
- issue #14815 Allow simplifying exported view syntax to only "CREATE VIEW"
|
||||
- issue #15496 Add $cfg['CaptchaSiteVerifyURL'] for Google ReCaptcha siteVerifyUrl
|
||||
- issue #14772 Add the password_hash PHP function as an option when inserting data
|
||||
- issue #15136 Add a notice for Hex converter giving invalid results
|
||||
- issue #16139 Use a textarea for JSON columns
|
||||
- issue #16223 Make JSON input transformation editor less narrow
|
||||
- issue #14340 Add a button on Export Page to show the SQL Query
|
||||
- issue #16304 Add support for INET6 column type
|
||||
- issue #16337 Fix example insert/update query default values
|
||||
- issue #12961 Remove indexes from table relation
|
||||
- issue #13557 Use a full list of functions instead of a separated one on insert/edit page "Function" selector
|
||||
- issue #14795 Include routines in the export in a predictable order
|
||||
- issue #16227 Fixed autocomplete is not working in case the table name is quoted by "`" symbols
|
||||
- issue #15463 Force BINARY comparison when looking at privileges to avoid an SQL error on privileges tab
|
||||
- issue #16430 Fixed Windows error message uses trailing / instead of \
|
||||
- issue #16316 Added support for "SameSite=Strict" on cookies using configuration "$cfg['CookieSameSite']"
|
||||
- issue #16451 Fixed AWS RDS IAM authentication doesn't work because pma_password is truncated
|
||||
- issue #16451 Show an error message when the security limit is reached instead of silently trimming the password to avoid confusion
|
||||
- issue #15001 Add back Login Cookie Validity setting to the features form
|
||||
- issue #16457 Add config parameters to support third-party ReCaptcha v2 compatible APIs like hCaptcha
|
||||
- issue #13077 Moved tools section to left on large devices (Bootstrap xl)
|
||||
- issue #15711 Moved some buttons to left on large devices (Bootstrap xl)
|
||||
- issue #15584 Add $cfg['MysqlSslWarningSafeHosts'] to set the red text black when ssl is not used on a private network
|
||||
- issue #15652 Replace deprecated FOUND_ROWS() function call on "distinct values" feature
|
||||
- issue Export blobs as hex on JSON export
|
||||
- issue #16095 Fix leading space not shown in a CHAR column when browsing a table
|
||||
- issue Make procedures/functions SQL editor both side scrollable
|
||||
- issue #16407 Bump pragmarx/google2fa conflict to >8.0
|
||||
- issue #14953 Added a rename Button to use RENAME INDEX syntax of MySQL 5.7 (and MariaDB >= 10.5.2)
|
||||
- issue #16477 Fixed no Option to enter TABLE specific permissions when the database name contains an "_" (underscore)
|
||||
- issue #16498 Fixed empty text not appearing after deleting all Routines
|
||||
- issue #16467 Fixed a PHP notice "Trying to access array offset on value of type null" on Designer PDF export
|
||||
- issue #15658 Fixed saving UI displayed columns on a non database request fails
|
||||
- issue #16495 Fix drop tables checkbox is above the checkbox for foreign keys
|
||||
- issue #16485 Fix visual query builder missing "Build Query" button
|
||||
- issue #16565 Added 'IF EXISTS' to 'DROP EVENT' when updating events to avoid replication issues
|
||||
- issue Removed metro fonts that where Apache-2.0 files that are incompatible with GPL-2.0
|
||||
- issue #16464 Made the relation view default to the current database when creating relations
|
||||
- issue #16463 Fixed 'REFERENCES' privilege checkbox's title on new MySQL versions and on MariaDB
|
||||
- issue #16405 Added jest as a Unit Testing tool for our javascript code
|
||||
- issue #16252 Fixed the too small font size when editing rows (textareas)
|
||||
- issue #16585 Fixed BLOB to JPG transformation PHP errors
|
||||
- issue Made the console setup async to avoid blocking the page render
|
||||
- issue #16429 Use PHP 8.0 fixed version (commit) for TCPDF
|
||||
- issue #16005 Major performance improvements on browsing a lot of rows
|
||||
- issue #16595 Fixed editing columns having a `_` in their name in specific conditions
|
||||
- issue #16608 Fix "Sort by key" restore auto saved value
|
||||
- issue #16611 Fixed unable to add tables to rename aliases twice on Export
|
||||
- issue #16621 Fixed link HTML messed up in Advisor
|
||||
- issue #16622 Fixed Advisor formatting incorrect for long_query_time notice
|
||||
- issue #15389 Fixed reset current page indicator after deleting all rows to current page and not page 1
|
||||
- issue #15997 Fixed auto save query
|
||||
- issue #15997 Made auto saved query database or database+table independent
|
||||
- issue #16641 Fixed query generation that was allowing JSON to have a length
|
||||
- issue #15994 Fixed the selected value detection for "on update current_timestamp"
|
||||
- issue #16614 Fixed PHP 8.0 dataseek offset call to the MySQLI extension
|
||||
- issue #16662 Fixed Uncaught TypeError on "delete" button click of a database search results page
|
||||
- issue Fixed Undefined index: selected_usr when the user tried to delete no selected user
|
||||
- issue #16657 Fixed the QBE interface when the configuration storage is not enabled
|
||||
- issue #16479 Fix our Selenium test-suite
|
||||
- issue #16669 Fixed table search modal for BETWEEN
|
||||
- issue #16667 Fixed LIKE and TINYINT in search not working properly
|
||||
- issue #16424 Fixed numerical search in table and zoom
|
||||
- issue Improve the version handling (new Version class) and add a VERSION_SUFFIX for vendors
|
||||
- issue #14494 Fix uncaught TypeError when editing partitioning
|
||||
- issue #16525 Fix PHP 8.0 failing tests when comparing 0 to ''
|
||||
- issue #16429 Fixed PHP 8.0 errors on preg_replace and operand types
|
||||
- issue #16490 Fixed PHP 8.0 function libxml_disable_entity_loader() is deprecated
|
||||
- issue #16429 Fixed failing unit tests on PHP 8.0
|
||||
- issue #16609 Fixed Sql.rearrangeStickyColumns is not a function
|
||||
|
||||
5.0.4 (2020-10-15)
|
||||
- issue #16245 Fix failed Zoom search clears existing values
|
||||
- issue Fixed a PHP error when reporting a particular JS error
|
||||
|
||||
2
README
2
README
@ -1,7 +1,7 @@
|
||||
phpMyAdmin - Readme
|
||||
===================
|
||||
|
||||
Version 5.0.4
|
||||
Version 5.1.0
|
||||
|
||||
A web interface for MySQL and MariaDB.
|
||||
|
||||
|
||||
43
README.rst
43
README.rst
@ -8,48 +8,57 @@ https://www.phpmyadmin.net/
|
||||
Code status
|
||||
-----------
|
||||
|
||||
.. image:: https://travis-ci.org/phpmyadmin/phpmyadmin.svg?branch=QA_5_0
|
||||
:alt: Build status
|
||||
:target: https://travis-ci.org/phpmyadmin/phpmyadmin
|
||||
.. image:: https://github.com/phpmyadmin/phpmyadmin/workflows/Run%20tests/badge.svg?branch=QA_5_1
|
||||
:alt: Testsuite
|
||||
:target: https://github.com/phpmyadmin/phpmyadmin/actions
|
||||
|
||||
.. image:: https://hosted.weblate.org/widgets/phpmyadmin/-/svg-badge.svg
|
||||
.. image:: https://github.com/phpmyadmin/phpmyadmin/workflows/Run%20selenium%20tests/badge.svg?branch=QA_5_1
|
||||
:alt: Selenium tests
|
||||
:target: https://github.com/phpmyadmin/phpmyadmin/actions
|
||||
|
||||
.. image:: https://readthedocs.org/projects/phpmyadmin/badge/?version=qa_5_1
|
||||
:target: https://docs.phpmyadmin.net/en/qa_5_1/
|
||||
:alt: Documentation build status
|
||||
|
||||
.. image:: https://hosted.weblate.org/widgets/phpmyadmin/-/5-1/svg-badge.svg
|
||||
:alt: Translation status
|
||||
:target: https://hosted.weblate.org/engage/phpmyadmin/?utm_source=widget
|
||||
|
||||
.. image:: https://codecov.io/gh/phpmyadmin/phpmyadmin/branch/master/graph/badge.svg
|
||||
.. image:: https://codecov.io/gh/phpmyadmin/phpmyadmin/branch/QA_5_1/graph/badge.svg
|
||||
:alt: Coverage percentage
|
||||
:target: https://codecov.io/gh/phpmyadmin/phpmyadmin
|
||||
|
||||
.. image:: https://scrutinizer-ci.com/g/phpmyadmin/phpmyadmin/badges/quality-score.png?s=93dfde29ffa5771d9c254b7ffb11c4e673315035
|
||||
.. image:: https://scrutinizer-ci.com/g/phpmyadmin/phpmyadmin/badges/quality-score.png
|
||||
:alt: Code quality score
|
||||
:target: https://scrutinizer-ci.com/g/phpmyadmin/phpmyadmin/
|
||||
|
||||
.. image:: https://bestpractices.coreinfrastructure.org/projects/213/badge
|
||||
:alt: CII Best Practices
|
||||
:target: https://bestpractices.coreinfrastructure.org/projects/213
|
||||
|
||||
.. image:: https://www.browserstack.com/automate/badge.svg?badge_key=V1ppZHdzTThicjY4Ujk5akxYT2xYUT09LS1PVncrNCtkUW9BZXE1Q2xCQkdTMFZRPT0=--91913a0e155fda6f7c942e9dd2da64b3da571c30
|
||||
:alt: BrowserStack
|
||||
:target: https://www.browserstack.com/automate/public-build/V1ppZHdzTThicjY4Ujk5akxYT2xYUT09LS1PVncrNCtkUW9BZXE1Q2xCQkdTMFZRPT0=--91913a0e155fda6f7c942e9dd2da64b3da571c30
|
||||
|
||||
|
||||
Download
|
||||
--------
|
||||
|
||||
You can get the newest release at https://www.phpmyadmin.net/.
|
||||
|
||||
If you prefer to follow the git repository, the following branch and tag names may be of interest:
|
||||
If you prefer to follow the Git repository, the following branch and tag names may be of interest:
|
||||
|
||||
* ``STABLE`` is the current stable release.
|
||||
* ``master`` is the development branch.
|
||||
* Releases are tagged, for example version 4.0.1 was tagged as ``RELEASE_4_0_1``.
|
||||
* Releases are tagged, for example version 5.0.1 was tagged as ``RELEASE_5_0_1``.
|
||||
|
||||
Note that phpMyAdmin uses Composer to manage library dependencies, when using git
|
||||
development versions you must manually run Composer.
|
||||
Note that phpMyAdmin uses `Composer <https://getcomposer.org/>`_ to manage library dependencies, when using Git
|
||||
development versions, you must manually run Composer.
|
||||
Please see `the documentation <https://docs.phpmyadmin.net/en/latest/setup.html#installing-from-git>`_ for details.
|
||||
|
||||
More Information
|
||||
----------------
|
||||
|
||||
Please see the documentation in the doc folder or at https://docs.phpmyadmin.net/.
|
||||
Please see https://docs.phpmyadmin.net/, or browse the documentation in the doc folder.
|
||||
|
||||
For support or to learn how to contribute code or by translating to your language,
|
||||
visit https://www.phpmyadmin.net/
|
||||
For `support <https://www.phpmyadmin.net/support/>`_ or `security issues <https://www.phpmyadmin.net/security/>`_ you can visit https://www.phpmyadmin.net/
|
||||
|
||||
Translations are welcome, you can `translate phpMyAdmin to your language <https://hosted.weblate.org/projects/phpmyadmin/>`_.
|
||||
|
||||
If you would like to contribute to the phpMyAdmin's codebase, you can read the `code contribution file <CONTRIBUTING.md>`_ or browse our website's `contributing page <https://www.phpmyadmin.net/contribute/>`_.
|
||||
|
||||
74
ajax.php
74
ajax.php
@ -1,74 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Generic AJAX endpoint for getting information about database
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Controllers\AjaxController;
|
||||
use PhpMyAdmin\Core;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
$_GET['ajax_request'] = 'true';
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
$response->setAjax(true);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
/** @var AjaxController $controller */
|
||||
$controller = $containerBuilder->get(AjaxController::class);
|
||||
|
||||
if (empty($_POST['type'])) {
|
||||
Core::fatalError(__('Bad type!'));
|
||||
}
|
||||
|
||||
switch ($_POST['type']) {
|
||||
case 'list-databases':
|
||||
$response->addJSON($controller->databases());
|
||||
break;
|
||||
case 'list-tables':
|
||||
Util::checkParameters(['db'], true);
|
||||
$response->addJSON($controller->tables([
|
||||
'db' => $_POST['db'],
|
||||
]));
|
||||
break;
|
||||
case 'list-columns':
|
||||
Util::checkParameters(['db', 'table'], true);
|
||||
$response->addJSON($controller->columns([
|
||||
'db' => $_POST['db'],
|
||||
'table' => $_POST['table'],
|
||||
]));
|
||||
break;
|
||||
case 'config-get':
|
||||
Util::checkParameters(['key'], true);
|
||||
$response->addJSON($controller->getConfig([
|
||||
'key' => $_POST['key'],
|
||||
]));
|
||||
break;
|
||||
case 'config-set':
|
||||
Util::checkParameters(['key', 'value'], true);
|
||||
$result = $controller->setConfig([
|
||||
'key' => $_POST['key'],
|
||||
'value' => $_POST['value'],
|
||||
]);
|
||||
if ($result !== true) {
|
||||
$response->setRequestStatus(false);
|
||||
$response->addJSON('message', $result);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Core::fatalError(__('Bad type!'));
|
||||
}
|
||||
3
babel.config.json
Normal file
3
babel.config.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["@babel/preset-env"]
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* display selection for relational field values
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\BrowseForeigners;
|
||||
use PhpMyAdmin\Controllers\BrowseForeignersController;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Template;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
Util::checkParameters(['db', 'table', 'field'], true);
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
/** @var Template $template */
|
||||
$template = $containerBuilder->get('template');
|
||||
/* Register BrowseForeignersController dependencies */
|
||||
$containerBuilder->set(
|
||||
'browse_foreigners',
|
||||
new BrowseForeigners(
|
||||
(int) $GLOBALS['cfg']['LimitChars'],
|
||||
(int) $GLOBALS['cfg']['MaxRows'],
|
||||
(int) $GLOBALS['cfg']['RepeatCells'],
|
||||
(bool) $GLOBALS['cfg']['ShowAll'],
|
||||
$GLOBALS['pmaThemeImage'],
|
||||
$template
|
||||
)
|
||||
);
|
||||
|
||||
/** @var BrowseForeignersController $controller */
|
||||
$controller = $containerBuilder->get(BrowseForeignersController::class);
|
||||
|
||||
$response->getFooter()->setMinimal();
|
||||
$header = $response->getHeader();
|
||||
$header->disableMenuAndConsole();
|
||||
$header->setBodyId('body_browse_foreigners');
|
||||
|
||||
$response->addHTML($controller->index([
|
||||
'db' => $_POST['db'] ?? null,
|
||||
'table' => $_POST['table'] ?? null,
|
||||
'field' => $_POST['field'] ?? null,
|
||||
'fieldkey' => $_POST['fieldkey'] ?? null,
|
||||
'data' => $_POST['data'] ?? null,
|
||||
'foreign_showAll' => $_POST['foreign_showAll'] ?? null,
|
||||
'foreign_filter' => $_POST['foreign_filter'] ?? null,
|
||||
]));
|
||||
58
build.xml
58
build.xml
@ -5,8 +5,6 @@
|
||||
<property name="source_comma_sep" value="."/>
|
||||
<property environment="env"/>
|
||||
<property name="env.PHPUNIT_XML" value="phpunit.xml.dist"/>
|
||||
<property name="env.PHPUNIT_XML_NOCOVERAGE" value="phpunit.xml.nocoverage"/>
|
||||
<property name="env.PHPUNIT_XML_HHVM" value="phpunit.xml.hhvm"/>
|
||||
<property name="env.PHPUNIT_ARGS" value="--exclude-group selenium"/>
|
||||
|
||||
<target name="clean" description="Clean up and create artifact directories">
|
||||
@ -31,13 +29,7 @@
|
||||
|
||||
<target name="phpunit-nocoverage" description="Run unit tests using PHPUnit and generates junit.xml">
|
||||
<exec executable="${basedir}/vendor/bin/phpunit" failonerror="true">
|
||||
<arg line="--configuration ${env.PHPUNIT_XML_NOCOVERAGE} ${env.PHPUNIT_ARGS}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="phpunit-hhvm" description="Run unit tests using PHPUnit with HHVM specific config">
|
||||
<exec executable="${basedir}/vendor/bin/phpunit" failonerror="true">
|
||||
<arg line="--configuration ${env.PHPUNIT_XML_HHVM} ${env.PHPUNIT_ARGS}"/>
|
||||
<arg line="--configuration --no-coverage ${env.PHPUNIT_ARGS}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
@ -84,25 +76,35 @@
|
||||
|
||||
<target name="phpcs-config" description="PHPCS configuration tweaking">
|
||||
<exec executable="${basedir}/vendor/bin/phpcs">
|
||||
<arg line="--config-set installed_paths ${basedir}/vendor/phpmyadmin/coding-standard" />
|
||||
<arg line="--config-set installed_paths ${basedir}/vendor/doctrine/coding-standard/lib,${basedir}/vendor/phpmyadmin/coding-standard,${basedir}/vendor/slevomat/coding-standard" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="phpcs" description="Generate checkstyle.xml using PHP_CodeSniffer excluding third party libraries" depends="phpcs-config">
|
||||
<exec executable="${basedir}/vendor/bin/phpcs">
|
||||
<arg line="
|
||||
--ignore=*/vendor/*,*/build/*,*/tmp/*
|
||||
--report=checkstyle
|
||||
--extensions=php
|
||||
--report-file='${basedir}/build/logs/checkstyle.xml'
|
||||
--standard=PhpMyAdmin
|
||||
${source}" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="phpdoc" description="Generate API documentation using PHPDocumentor">
|
||||
<exec executable="phpdoc">
|
||||
<arg line="-d ${source} -t '${basedir}/build/api'" />
|
||||
<target name="phpstan" description="Run phpstan static code analysis">
|
||||
<exec executable="${basedir}/vendor/bin/phpstan" failonerror="true">
|
||||
<redirector error="/dev/stdout" output="${basedir}/build/logs/phpstan.xml"/>
|
||||
<arg line="analyse --error-format=checkstyle"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="phpdoc" description="Generate API documentation using Doctum">
|
||||
<!-- ant phpdoc -Denv.DOCTUM_BIN_PATH="/usr/bin/doctum" -->
|
||||
<!-- please use 5.3.0 as a minimum version -->
|
||||
<!-- Download the latest 5.x.x version -->
|
||||
<!-- curl -o /bin/doctum https://doctum.long-term.support/releases/5/doctum.phar && chmod +x /bin/doctum -->
|
||||
<property name="env.DOCTUM_BIN_PATH" value="/bin/doctum"/>
|
||||
<exec executable="${env.DOCTUM_BIN_PATH}" failonerror="true">
|
||||
<redirector error="${basedir}/build/logs/doctum.xml"/>
|
||||
<arg line="--no-interaction update ./test/doctum-config.php -v --force --no-progress --no-ansi --output-format=checkstyle" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
@ -114,24 +116,11 @@
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="jshint" description="Javascript checks">
|
||||
<apply executable="jshint" output="${basedir}/build/logs/jshint-jslint.xml" parallel="true">
|
||||
<arg line="--config ./.jshintrc --reporter=jslint" />
|
||||
<target name="eslint" description="Javascript checks">
|
||||
<apply executable="${basedir}/node_modules/.bin/eslint" output="${basedir}/build/logs/eslint.xml" parallel="true">
|
||||
<arg line="--format=checkstyle js/src" />
|
||||
<fileset dir="${basedir}">
|
||||
<include name="js/designer/*.js" />
|
||||
<include name="js/*.js" />
|
||||
<include name="setup/*.js" />
|
||||
</fileset>
|
||||
</apply>
|
||||
</target>
|
||||
|
||||
<target name="jshint-checkstyle" description="Javascript checks">
|
||||
<apply executable="jshint" output="${basedir}/build/logs/jshint-checkstyle.xml" parallel="true">
|
||||
<arg line="--config ./.jshintrc --reporter=checkstyle" />
|
||||
<fileset dir="${basedir}">
|
||||
<include name="js/designer/*.js" />
|
||||
<include name="js/*.js" />
|
||||
<include name="setup/*.js" />
|
||||
<include name="js/src/**/*.js" />
|
||||
</fileset>
|
||||
</apply>
|
||||
</target>
|
||||
@ -148,7 +137,6 @@
|
||||
|
||||
<fileset dir="${basedir}">
|
||||
<include name="libraries/**/*.php" />
|
||||
<include name="templates/**/*.phtml" />
|
||||
<include name="setup/**/*.php" />
|
||||
<include name="test/**/*.php" />
|
||||
<include name="*.php" />
|
||||
@ -157,5 +145,5 @@
|
||||
</apply>
|
||||
</target>
|
||||
|
||||
<target name="build" depends="clean,phpunit,pdepend,phpmd,phpcpd,phpcs,phpdoc,phploc,phpcb,lint,jshint,locales"/>
|
||||
<target name="build" depends="clean,phpunit,pdepend,phpmd,phpcpd,phpcs,phpdoc,phploc,phpcb,lint,eslint,locales"/>
|
||||
</project>
|
||||
|
||||
112
changelog.php
112
changelog.php
@ -1,112 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Simple script to set correct charset for changelog
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Template;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets core libraries and defines some variables
|
||||
*/
|
||||
require ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Template $template */
|
||||
$template = $containerBuilder->get('template');
|
||||
|
||||
$response = Response::getInstance();
|
||||
$response->disable();
|
||||
$response->getHeader()->sendHttpHeaders();
|
||||
|
||||
$filename = CHANGELOG_FILE;
|
||||
|
||||
/**
|
||||
* Read changelog.
|
||||
*/
|
||||
// Check if the file is available, some distributions remove these.
|
||||
if (@is_readable($filename)) {
|
||||
// Test if the if is in a compressed format
|
||||
if (substr($filename, -3) == '.gz') {
|
||||
ob_start();
|
||||
readgzfile($filename);
|
||||
$changelog = ob_get_contents();
|
||||
ob_end_clean();
|
||||
} else {
|
||||
$changelog = file_get_contents($filename);
|
||||
}
|
||||
} else {
|
||||
printf(
|
||||
__(
|
||||
'The %s file is not available on this system, please visit ' .
|
||||
'%s for more information.'
|
||||
),
|
||||
$filename,
|
||||
'<a href="https://www.phpmyadmin.net/">phpmyadmin.net</a>'
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whole changelog in variable.
|
||||
*/
|
||||
$changelog = htmlspecialchars($changelog);
|
||||
|
||||
$github_url = 'https://github.com/phpmyadmin/phpmyadmin/';
|
||||
$faq_url = 'https://docs.phpmyadmin.net/en/latest/faq.html';
|
||||
|
||||
$replaces = [
|
||||
'@(https?://[./a-zA-Z0-9.-_-]*[/a-zA-Z0-9_])@'
|
||||
=> '<a href="url.php?url=\\1">\\1</a>',
|
||||
|
||||
// mail address
|
||||
'/([0-9]{4}-[0-9]{2}-[0-9]{2}) (.+[^ ]) +<(.*@.*)>/i'
|
||||
=> '\\1 <a href="mailto:\\3">\\2</a>',
|
||||
|
||||
// FAQ entries
|
||||
'/FAQ ([0-9]+)\.([0-9a-z]+)/i'
|
||||
=> '<a href="url.php?url=' . $faq_url . '#faq\\1-\\2">FAQ \\1.\\2</a>',
|
||||
|
||||
// GitHub issues
|
||||
'/issue\s*#?([0-9]{4,5}) /i'
|
||||
=> '<a href="url.php?url=' . $github_url . 'issues/\\1">issue #\\1</a> ',
|
||||
|
||||
// CVE/CAN entries
|
||||
'/((CAN|CVE)-[0-9]+-[0-9]+)/'
|
||||
=> '<a href="url.php?url=https://cve.mitre.org/cgi-bin/cvename.cgi?name=\\1">\\1</a>',
|
||||
|
||||
// PMASAentries
|
||||
'/(PMASA-[0-9]+-[0-9]+)/'
|
||||
=> '<a href="url.php?url=https://www.phpmyadmin.net/security/\\1/">\\1</a>',
|
||||
|
||||
// Highlight releases (with links)
|
||||
'/([0-9]+)\.([0-9]+)\.([0-9]+)\.0 (\([0-9-]+\))/'
|
||||
=> '<a id="\\1_\\2_\\3"></a>'
|
||||
. '<a href="url.php?url=' . $github_url . 'commits/RELEASE_\\1_\\2_\\3">'
|
||||
. '\\1.\\2.\\3.0 \\4</a>',
|
||||
'/([0-9]+)\.([0-9]+)\.([0-9]+)\.([1-9][0-9]*) (\([0-9-]+\))/'
|
||||
=> '<a id="\\1_\\2_\\3_\\4"></a>'
|
||||
. '<a href="url.php?url=' . $github_url . 'commits/RELEASE_\\1_\\2_\\3_\\4">'
|
||||
. '\\1.\\2.\\3.\\4 \\5</a>',
|
||||
|
||||
// Highlight releases (not linkable)
|
||||
'/( ### )(.*)/'
|
||||
=> '\\1<b>\\2</b>',
|
||||
|
||||
// Links target and rel
|
||||
'/a href="/' => 'a target="_blank" rel="noopener noreferrer" href="',
|
||||
|
||||
];
|
||||
|
||||
header('Content-type: text/html; charset=utf-8');
|
||||
|
||||
echo $template->render('changelog', [
|
||||
'changelog' => preg_replace(array_keys($replaces), $replaces, $changelog),
|
||||
]);
|
||||
47
chk_rel.php
47
chk_rel.php
@ -1,47 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Displays status of phpMyAdmin configuration storage
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Relation;
|
||||
use PhpMyAdmin\Response;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
/** @var Relation $relation */
|
||||
$relation = $containerBuilder->get('relation');
|
||||
|
||||
// If request for creating the pmadb
|
||||
if (isset($_POST['create_pmadb']) && $relation->createPmaDatabase()) {
|
||||
$relation->fixPmaTables('phpmyadmin');
|
||||
}
|
||||
|
||||
// If request for creating all PMA tables.
|
||||
if (isset($_POST['fixall_pmadb'])) {
|
||||
$relation->fixPmaTables($GLOBALS['db']);
|
||||
}
|
||||
|
||||
$cfgRelation = $relation->getRelationsParam();
|
||||
// If request for creating missing PMA tables.
|
||||
if (isset($_POST['fix_pmadb'])) {
|
||||
$relation->fixPmaTables($cfgRelation['db']);
|
||||
}
|
||||
|
||||
$response->addHTML(
|
||||
$relation->getRelationsParamDiagnostic($cfgRelation)
|
||||
);
|
||||
@ -38,7 +38,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.1.3",
|
||||
"php": "^7.1.3 || ^8.0",
|
||||
"ext-hash": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-json": "*",
|
||||
@ -46,24 +46,24 @@
|
||||
"ext-pcre": "*",
|
||||
"ext-xml": "*",
|
||||
"google/recaptcha": "^1.1",
|
||||
"phpmyadmin/motranslator": "^4.0",
|
||||
"nikic/fast-route": "^1.3",
|
||||
"phpmyadmin/motranslator": "^5.0",
|
||||
"phpmyadmin/shapefile": "^2.0",
|
||||
"phpmyadmin/sql-parser": "^5.0",
|
||||
"phpmyadmin/twig-i18n-extension": "^2.0 || ^3.0",
|
||||
"phpmyadmin/twig-i18n-extension": "^3.0",
|
||||
"phpseclib/phpseclib": "^2.0",
|
||||
"symfony/config": "^4.2.8",
|
||||
"symfony/dependency-injection": "^4.2.8",
|
||||
"symfony/expression-language": "^4.2",
|
||||
"symfony/polyfill-ctype": "^1.8",
|
||||
"symfony/polyfill-mbstring": "^1.3",
|
||||
"symfony/yaml": "^4.2.8",
|
||||
"symfony/config": "^4.4.9",
|
||||
"symfony/dependency-injection": "^4.4.9",
|
||||
"symfony/expression-language": "^4.4.9",
|
||||
"symfony/polyfill-ctype": "^1.17.0",
|
||||
"symfony/polyfill-mbstring": "^1.17.0",
|
||||
"twig/twig": "^2.9 || ^3",
|
||||
"williamdes/mariadb-mysql-kbs": "^1.2"
|
||||
},
|
||||
"conflict": {
|
||||
"phpseclib/phpseclib": "2.0.8",
|
||||
"tecnickcom/tcpdf": "<6.2",
|
||||
"pragmarx/google2fa": ">=6.1",
|
||||
"pragmarx/google2fa": "<6.1.0 || >8.0",
|
||||
"pragmarx/google2fa-qrcode": "<1.0.1",
|
||||
"samyoul/u2f-php-server": "<1.1"
|
||||
},
|
||||
@ -81,32 +81,42 @@
|
||||
"samyoul/u2f-php-server": "For FIDO U2F authentication"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-webdriver/webdriver": "^1.7.1",
|
||||
"phpmyadmin/coding-standard": "^1.0",
|
||||
"phpstan/phpstan": "^0.11.5",
|
||||
"php-webdriver/webdriver": "^1.8",
|
||||
"phpmyadmin/coding-standard": "^2.1.1",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan": "^0.12.78",
|
||||
"phpstan/phpstan-phpunit": "^0.12.17",
|
||||
"phpunit/phpunit": "^7.5 || ^8.0 || ^9.0",
|
||||
"pragmarx/google2fa-qrcode": "^1.0.1",
|
||||
"samyoul/u2f-php-server": "^1.1",
|
||||
"squizlabs/php_codesniffer": "^3.0",
|
||||
"tecnickcom/tcpdf": "^6.3"
|
||||
"symfony/console": "^4.4",
|
||||
"symfony/finder": "^4.4",
|
||||
"symfony/twig-bridge": "^4.4",
|
||||
"tecnickcom/tcpdf": "dev-main#456b794f1fae9aee5c151a1ee515aae2aaa619a3",
|
||||
"vimeo/psalm": "^4.6.1"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.0.x-dev"
|
||||
"dev-master": "5.2.x-dev"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"phpcbf": "phpcbf",
|
||||
"phpcs": "phpcs",
|
||||
"phpstan": "phpstan analyse",
|
||||
"phpunit": "phpunit",
|
||||
"psalm": "psalm",
|
||||
"phpunit": "phpunit --color=always",
|
||||
"test": [
|
||||
"@phpcs",
|
||||
"@phpstan",
|
||||
"@psalm",
|
||||
"@phpunit"
|
||||
]
|
||||
],
|
||||
"update:baselines": "phpstan analyse --generate-baseline && psalm --set-baseline=psalm-baseline.xml",
|
||||
"twig-lint": "php scripts/console lint:twig templates --ansi --show-deprecations"
|
||||
},
|
||||
"config":{
|
||||
"sort-packages": true
|
||||
"sort-packages": true,
|
||||
"discard-changes": true
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* phpMyAdmin sample configuration, you can use it as base for
|
||||
* manual configuration. For easier setup you can use setup/
|
||||
*
|
||||
* All directives are explained in documentation in the doc/ folder
|
||||
* or at <https://docs.phpmyadmin.net/>.
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
|
||||
@ -1,138 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Central Columns view/edit
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
use PhpMyAdmin\CentralColumns;
|
||||
use PhpMyAdmin\Controllers\Database\CentralColumnsController;
|
||||
use PhpMyAdmin\Core;
|
||||
use PhpMyAdmin\Message;
|
||||
use PhpMyAdmin\Response;
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var CentralColumns $centralColumns */
|
||||
$centralColumns = $containerBuilder->get('central_columns');
|
||||
|
||||
/** @var CentralColumnsController $controller */
|
||||
$controller = $containerBuilder->get(CentralColumnsController::class);
|
||||
|
||||
/** @var string $db */
|
||||
$db = $containerBuilder->getParameter('db');
|
||||
|
||||
if (isset($_POST['edit_save'])) {
|
||||
echo $controller->editSave([
|
||||
'col_name' => $_POST['col_name'] ?? null,
|
||||
'orig_col_name' => $_POST['orig_col_name'] ?? null,
|
||||
'col_default' => $_POST['col_default'] ?? null,
|
||||
'col_default_sel' => $_POST['col_default_sel'] ?? null,
|
||||
'col_extra' => $_POST['col_extra'] ?? null,
|
||||
'col_isNull' => $_POST['col_isNull'] ?? null,
|
||||
'col_length' => $_POST['col_length'] ?? null,
|
||||
'col_attribute' => $_POST['col_attribute'] ?? null,
|
||||
'col_type' => $_POST['col_type'] ?? null,
|
||||
'collation' => $_POST['collation'] ?? null,
|
||||
]);
|
||||
exit;
|
||||
} elseif (isset($_POST['add_new_column'])) {
|
||||
$tmp_msg = $controller->addNewColumn([
|
||||
'col_name' => $_POST['col_name'] ?? null,
|
||||
'col_default' => $_POST['col_default'] ?? null,
|
||||
'col_default_sel' => $_POST['col_default_sel'] ?? null,
|
||||
'col_extra' => $_POST['col_extra'] ?? null,
|
||||
'col_isNull' => $_POST['col_isNull'] ?? null,
|
||||
'col_length' => $_POST['col_length'] ?? null,
|
||||
'col_attribute' => $_POST['col_attribute'] ?? null,
|
||||
'col_type' => $_POST['col_type'] ?? null,
|
||||
'collation' => $_POST['collation'] ?? null,
|
||||
]);
|
||||
}
|
||||
if (isset($_POST['populateColumns'])) {
|
||||
$response->addHTML($controller->populateColumns([
|
||||
'selectedTable' => $_POST['selectedTable'],
|
||||
]));
|
||||
exit;
|
||||
}
|
||||
if (isset($_POST['getColumnList'])) {
|
||||
$response->addJSON('message', $controller->getColumnList([
|
||||
'cur_table' => $_POST['cur_table'] ?? null,
|
||||
]));
|
||||
exit;
|
||||
}
|
||||
if (isset($_POST['add_column'])) {
|
||||
$tmp_msg = $controller->addColumn([
|
||||
'table-select' => $_POST['table-select'] ?? null,
|
||||
'column-select' => $_POST['column-select'] ?? null,
|
||||
]);
|
||||
}
|
||||
|
||||
$header = $response->getHeader();
|
||||
$scripts = $header->getScripts();
|
||||
$scripts->addFile('vendor/jquery/jquery.uitablefilter.js');
|
||||
$scripts->addFile('vendor/jquery/jquery.tablesorter.js');
|
||||
$scripts->addFile('database/central_columns.js');
|
||||
|
||||
if (isset($_POST['edit_central_columns_page'])) {
|
||||
$response->addHTML($controller->editPage([
|
||||
'selected_fld' => $_POST['selected_fld'] ?? null,
|
||||
'db' => $_POST['db'] ?? null,
|
||||
]));
|
||||
exit;
|
||||
}
|
||||
if (isset($_POST['multi_edit_central_column_save'])) {
|
||||
$message = $controller->updateMultipleColumn([
|
||||
'db' => $_POST['db'] ?? null,
|
||||
'orig_col_name' => $_POST['orig_col_name'] ?? null,
|
||||
'field_name' => $_POST['field_name'] ?? null,
|
||||
'field_default_type' => $_POST['field_default_type'] ?? null,
|
||||
'field_default_value' => $_POST['field_default_value'] ?? null,
|
||||
'field_length' => $_POST['field_length'] ?? null,
|
||||
'field_attribute' => $_POST['field_attribute'] ?? null,
|
||||
'field_type' => $_POST['field_type'] ?? null,
|
||||
'field_collation' => $_POST['field_collation'] ?? null,
|
||||
'field_null' => $_POST['field_null'] ?? null,
|
||||
'col_extra' => $_POST['col_extra'] ?? null,
|
||||
]);
|
||||
if (! is_bool($message)) {
|
||||
$response->setRequestStatus(false);
|
||||
$response->addJSON('message', $message);
|
||||
}
|
||||
}
|
||||
if (isset($_POST['delete_save'])) {
|
||||
$tmp_msg = $controller->deleteSave([
|
||||
'db' => $_POST['db'] ?? null,
|
||||
'col_name' => $_POST['col_name'] ?? null,
|
||||
]);
|
||||
}
|
||||
|
||||
$response->addHTML($controller->index([
|
||||
'pos' => $_POST['pos'] ?? null,
|
||||
'total_rows' => $_POST['total_rows'] ?? null,
|
||||
]));
|
||||
|
||||
$pos = 0;
|
||||
if (Core::isValid($_POST['pos'], 'integer')) {
|
||||
$pos = (int) $_POST['pos'];
|
||||
}
|
||||
$num_cols = $centralColumns->getColumnsCount(
|
||||
$db,
|
||||
$pos,
|
||||
(int) $GLOBALS['cfg']['MaxRows']
|
||||
);
|
||||
$message = Message::success(
|
||||
sprintf(__('Showing rows %1$s - %2$s.'), $pos + 1, $pos + $num_cols)
|
||||
);
|
||||
if (isset($tmp_msg) && $tmp_msg !== true) {
|
||||
$message = $tmp_msg;
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Renders data dictionary
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Controllers\Database\DataDictionaryController;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
Util::checkParameters(['db']);
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DataDictionaryController $controller */
|
||||
$controller = $containerBuilder->get(DataDictionaryController::class);
|
||||
|
||||
$header = $response->getHeader();
|
||||
$header->enablePrintView();
|
||||
|
||||
$response->addHTML($controller->index());
|
||||
236
db_designer.php
236
db_designer.php
@ -1,236 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* phpMyAdmin designer general code
|
||||
*
|
||||
* @package PhpMyAdmin-Designer
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Database\Designer;
|
||||
use PhpMyAdmin\Database\Designer\Common;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Response;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
global $db;
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
/** @var Designer $databaseDesigner */
|
||||
$databaseDesigner = $containerBuilder->get('designer');
|
||||
|
||||
/** @var Common $designerCommon */
|
||||
$designerCommon = $containerBuilder->get('designer_common');
|
||||
|
||||
if (isset($_POST['dialog'])) {
|
||||
if ($_POST['dialog'] == 'edit') {
|
||||
$html = $databaseDesigner->getHtmlForEditOrDeletePages($_POST['db'], 'editPage');
|
||||
} elseif ($_POST['dialog'] == 'delete') {
|
||||
$html = $databaseDesigner->getHtmlForEditOrDeletePages($_POST['db'], 'deletePage');
|
||||
} elseif ($_POST['dialog'] == 'save_as') {
|
||||
$html = $databaseDesigner->getHtmlForPageSaveAs($_POST['db']);
|
||||
} elseif ($_POST['dialog'] == 'export') {
|
||||
$html = $databaseDesigner->getHtmlForSchemaExport(
|
||||
$_POST['db'],
|
||||
$_POST['selected_page']
|
||||
);
|
||||
} elseif ($_POST['dialog'] == 'add_table') {
|
||||
// Pass the db and table to the getTablesInfo so we only have the table we asked for
|
||||
$script_display_field = $designerCommon->getTablesInfo($_POST['db'], $_POST['table']);
|
||||
$tab_column = $designerCommon->getColumnsInfo($script_display_field);
|
||||
$tables_all_keys = $designerCommon->getAllKeys($script_display_field);
|
||||
$tables_pk_or_unique_keys = $designerCommon->getPkOrUniqueKeys($script_display_field);
|
||||
|
||||
$html = $databaseDesigner->getDatabaseTables(
|
||||
$_POST['db'],
|
||||
$script_display_field,
|
||||
[],
|
||||
-1,
|
||||
$tab_column,
|
||||
$tables_all_keys,
|
||||
$tables_pk_or_unique_keys
|
||||
);
|
||||
}
|
||||
|
||||
if (! empty($html)) {
|
||||
$response->addHTML($html);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($_POST['operation'])) {
|
||||
if ($_POST['operation'] == 'deletePage') {
|
||||
$success = $designerCommon->deletePage($_POST['selected_page']);
|
||||
$response->setRequestStatus($success);
|
||||
} elseif ($_POST['operation'] == 'savePage') {
|
||||
if ($_POST['save_page'] == 'same') {
|
||||
$page = $_POST['selected_page'];
|
||||
} else { // new
|
||||
if ($designerCommon->getPageExists($_POST['selected_value'])) {
|
||||
$response->addJSON(
|
||||
'message',
|
||||
/* l10n: The user tries to save a page with an existing name in Designer */
|
||||
__(
|
||||
sprintf(
|
||||
"There already exists a page named \"%s\" please rename it to something else.",
|
||||
htmlspecialchars($_POST['selected_value'])
|
||||
)
|
||||
)
|
||||
);
|
||||
$response->setRequestStatus(false);
|
||||
return;
|
||||
} else {
|
||||
$page = $designerCommon->createNewPage($_POST['selected_value'], $_POST['db']);
|
||||
$response->addJSON('id', $page);
|
||||
}
|
||||
}
|
||||
$success = $designerCommon->saveTablePositions($page);
|
||||
$response->setRequestStatus($success);
|
||||
} elseif ($_POST['operation'] == 'setDisplayField') {
|
||||
[
|
||||
$success,
|
||||
$message,
|
||||
] = $designerCommon->saveDisplayField(
|
||||
$_POST['db'],
|
||||
$_POST['table'],
|
||||
$_POST['field']
|
||||
);
|
||||
$response->setRequestStatus($success);
|
||||
$response->addJSON('message', $message);
|
||||
} elseif ($_POST['operation'] == 'addNewRelation') {
|
||||
list($success, $message) = $designerCommon->addNewRelation(
|
||||
$_POST['db'],
|
||||
$_POST['T1'],
|
||||
$_POST['F1'],
|
||||
$_POST['T2'],
|
||||
$_POST['F2'],
|
||||
$_POST['on_delete'],
|
||||
$_POST['on_update'],
|
||||
$_POST['DB1'],
|
||||
$_POST['DB2']
|
||||
);
|
||||
$response->setRequestStatus($success);
|
||||
$response->addJSON('message', $message);
|
||||
} elseif ($_POST['operation'] == 'removeRelation') {
|
||||
list($success, $message) = $designerCommon->removeRelation(
|
||||
$_POST['T1'],
|
||||
$_POST['F1'],
|
||||
$_POST['T2'],
|
||||
$_POST['F2']
|
||||
);
|
||||
$response->setRequestStatus($success);
|
||||
$response->addJSON('message', $message);
|
||||
} elseif ($_POST['operation'] == 'save_setting_value') {
|
||||
$success = $designerCommon->saveSetting($_POST['index'], $_POST['value']);
|
||||
$response->setRequestStatus($success);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
require ROOT_PATH . 'libraries/db_common.inc.php';
|
||||
|
||||
$script_display_field = $designerCommon->getTablesInfo();
|
||||
|
||||
$display_page = -1;
|
||||
$selected_page = null;
|
||||
|
||||
if (isset($_GET['query'])) {
|
||||
$display_page = $designerCommon->getDefaultPage($_GET['db']);
|
||||
} elseif (! empty($_GET['page'])) {
|
||||
$display_page = $_GET['page'];
|
||||
} else {
|
||||
$display_page = $designerCommon->getLoadingPage($_GET['db']);
|
||||
}
|
||||
if ($display_page != -1) {
|
||||
$selected_page = $designerCommon->getPageName($display_page);
|
||||
}
|
||||
$tab_pos = $designerCommon->getTablePositions($display_page);
|
||||
|
||||
$fullTableNames = [];
|
||||
|
||||
foreach ($script_display_field as $designerTable) {
|
||||
$fullTableNames[] = $designerTable->getDbTableString();
|
||||
}
|
||||
|
||||
foreach ($tab_pos as $position) {
|
||||
if (! in_array($position['dbName'] . '.' . $position['tableName'], $fullTableNames)) {
|
||||
foreach ($designerCommon->getTablesInfo($position['dbName'], $position['tableName']) as $designerTable) {
|
||||
$script_display_field[] = $designerTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$tab_column = $designerCommon->getColumnsInfo($script_display_field);
|
||||
$script_tables = $designerCommon->getScriptTabs($script_display_field);
|
||||
$tables_pk_or_unique_keys = $designerCommon->getPkOrUniqueKeys($script_display_field);
|
||||
$tables_all_keys = $designerCommon->getAllKeys($script_display_field);
|
||||
$classes_side_menu = $databaseDesigner->returnClassNamesFromMenuButtons();
|
||||
|
||||
|
||||
$script_contr = $designerCommon->getScriptContr($script_display_field);
|
||||
|
||||
$params = ['lang' => $GLOBALS['lang']];
|
||||
if (isset($_GET['db'])) {
|
||||
$params['db'] = $_GET['db'];
|
||||
}
|
||||
|
||||
$response = Response::getInstance();
|
||||
$response->getFooter()->setMinimal();
|
||||
$header = $response->getHeader();
|
||||
$header->setBodyId('designer_body');
|
||||
|
||||
$scripts = $header->getScripts();
|
||||
$scripts->addFile('vendor/jquery/jquery.fullscreen.js');
|
||||
$scripts->addFile('designer/database.js');
|
||||
$scripts->addFile('designer/objects.js');
|
||||
$scripts->addFile('designer/page.js');
|
||||
$scripts->addFile('designer/history.js');
|
||||
$scripts->addFile('designer/move.js');
|
||||
$scripts->addFile('designer/init.js');
|
||||
|
||||
list(
|
||||
$tables,
|
||||
$num_tables,
|
||||
$total_num_tables,
|
||||
$sub_part,
|
||||
$is_show_stats,
|
||||
$db_is_system_schema,
|
||||
$tooltip_truename,
|
||||
$tooltip_aliasname,
|
||||
$pos
|
||||
) = PhpMyAdmin\Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
|
||||
|
||||
// Embed some data into HTML, later it will be read
|
||||
// by designer/init.js and converted to JS variables.
|
||||
$response->addHTML(
|
||||
$databaseDesigner->getHtmlForMain(
|
||||
$db,
|
||||
$_GET['db'],
|
||||
$script_display_field,
|
||||
$script_tables,
|
||||
$script_contr,
|
||||
$script_display_field,
|
||||
$display_page,
|
||||
isset($_GET['query']),
|
||||
$selected_page,
|
||||
$classes_side_menu,
|
||||
$tab_pos,
|
||||
$tab_column,
|
||||
$tables_all_keys,
|
||||
$tables_pk_or_unique_keys
|
||||
)
|
||||
);
|
||||
|
||||
$response->addHTML('<div id="PMA_disable_floating_menubar"></div>');
|
||||
@ -1,80 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Events management.
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Controllers\Database\EventsController;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
$_PMA_RTE = 'EVN';
|
||||
|
||||
/** @var EventsController $controller */
|
||||
$controller = $containerBuilder->get(EventsController::class);
|
||||
|
||||
/** @var string $db */
|
||||
$db = $containerBuilder->getParameter('db');
|
||||
|
||||
/** @var string $table */
|
||||
$table = $containerBuilder->getParameter('table');
|
||||
|
||||
if (! $response->isAjax()) {
|
||||
/**
|
||||
* Displays the header and tabs
|
||||
*/
|
||||
if (! empty($table) && in_array($table, $dbi->getTables($db))) {
|
||||
include_once ROOT_PATH . 'libraries/tbl_common.inc.php';
|
||||
} else {
|
||||
$table = '';
|
||||
include_once ROOT_PATH . 'libraries/db_common.inc.php';
|
||||
|
||||
list(
|
||||
$tables,
|
||||
$num_tables,
|
||||
$total_num_tables,
|
||||
$sub_part,
|
||||
$is_show_stats,
|
||||
$db_is_system_schema,
|
||||
$tooltip_truename,
|
||||
$tooltip_aliasname,
|
||||
$pos
|
||||
) = Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Since we did not include some libraries, we need
|
||||
* to manually select the required database and
|
||||
* create the missing $url_query variable
|
||||
*/
|
||||
if (strlen($db) > 0) {
|
||||
$dbi->selectDb($db);
|
||||
if (! isset($url_query)) {
|
||||
$url_query = Url::getCommon(
|
||||
[
|
||||
'db' => $db,
|
||||
'table' => $table,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$controller->index();
|
||||
173
db_export.php
173
db_export.php
@ -1,173 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* dumps a database
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Config\PageSettings;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Display\Export as DisplayExport;
|
||||
use PhpMyAdmin\Export;
|
||||
use PhpMyAdmin\Message;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
global $db, $table, $url_query, $containerBuilder;
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
PageSettings::showGroup('Export');
|
||||
|
||||
$header = $response->getHeader();
|
||||
$scripts = $header->getScripts();
|
||||
$scripts->addFile('export.js');
|
||||
|
||||
/** @var Export $export */
|
||||
$export = $containerBuilder->get('export');
|
||||
|
||||
// $sub_part is used in Util::getDbInfo() to see if we are coming from
|
||||
// db_export.php, in which case we don't obey $cfg['MaxTableList']
|
||||
$sub_part = '_export';
|
||||
require_once ROOT_PATH . 'libraries/db_common.inc.php';
|
||||
$url_query .= '&goto=db_export.php';
|
||||
|
||||
list(
|
||||
$tables,
|
||||
$num_tables,
|
||||
$total_num_tables,
|
||||
$sub_part,
|
||||
$is_show_stats,
|
||||
$db_is_system_schema,
|
||||
$tooltip_truename,
|
||||
$tooltip_aliasname,
|
||||
$pos
|
||||
) = Util::getDbInfo($db, $sub_part === null ? '' : $sub_part);
|
||||
|
||||
/**
|
||||
* Displays the form
|
||||
*/
|
||||
$export_page_title = __('View dump (schema) of database');
|
||||
|
||||
// exit if no tables in db found
|
||||
if ($num_tables < 1) {
|
||||
$response->addHTML(
|
||||
Message::error(__('No tables found in database.'))->getDisplay()
|
||||
);
|
||||
exit;
|
||||
} // end if
|
||||
|
||||
$multi_values = '<div class="export_table_list_container">';
|
||||
if (isset($_POST['structure_or_data_forced'])) {
|
||||
$force_val = htmlspecialchars($_POST['structure_or_data_forced']);
|
||||
} else {
|
||||
$force_val = 0;
|
||||
}
|
||||
$multi_values .= '<input type="hidden" name="structure_or_data_forced" value="'
|
||||
. $force_val . '">';
|
||||
$multi_values .= '<table class="export_table_select">'
|
||||
. '<thead><tr><th></th>'
|
||||
. '<th>' . __('Tables') . '</th>'
|
||||
. '<th class="export_structure">' . __('Structure') . '</th>'
|
||||
. '<th class="export_data">' . __('Data') . '</th>'
|
||||
. '</tr><tr>'
|
||||
. '<td></td>'
|
||||
. '<td class="export_table_name all">' . __('Select all') . '</td>'
|
||||
. '<td class="export_structure all">'
|
||||
. '<input type="checkbox" id="table_structure_all"></td>'
|
||||
. '<td class="export_data all"><input type="checkbox" id="table_data_all">'
|
||||
. '</td>'
|
||||
. '</tr></thead>'
|
||||
. '<tbody>';
|
||||
$multi_values .= "\n";
|
||||
|
||||
// when called by libraries/mult_submits.inc.php
|
||||
if (! empty($_POST['selected_tbl']) && empty($table_select)) {
|
||||
$table_select = $_POST['selected_tbl'];
|
||||
}
|
||||
|
||||
foreach ($tables as $each_table) {
|
||||
if (isset($_POST['table_select']) && is_array($_POST['table_select'])) {
|
||||
$is_checked = $export->getCheckedClause(
|
||||
$each_table['Name'],
|
||||
$_POST['table_select']
|
||||
);
|
||||
} elseif (isset($table_select)) {
|
||||
$is_checked = $export->getCheckedClause(
|
||||
$each_table['Name'],
|
||||
$table_select
|
||||
);
|
||||
} else {
|
||||
$is_checked = ' checked="checked"';
|
||||
}
|
||||
if (isset($_POST['table_structure']) && is_array($_POST['table_structure'])) {
|
||||
$structure_checked = $export->getCheckedClause(
|
||||
$each_table['Name'],
|
||||
$_POST['table_structure']
|
||||
);
|
||||
} else {
|
||||
$structure_checked = $is_checked;
|
||||
}
|
||||
if (isset($_POST['table_data']) && is_array($_POST['table_data'])) {
|
||||
$data_checked = $export->getCheckedClause(
|
||||
$each_table['Name'],
|
||||
$_POST['table_data']
|
||||
);
|
||||
} else {
|
||||
$data_checked = $is_checked;
|
||||
}
|
||||
$table_html = htmlspecialchars($each_table['Name']);
|
||||
$multi_values .= '<tr class="marked">';
|
||||
$multi_values .= '<td><input type="checkbox" name="table_select[]"'
|
||||
. ' value="' . $table_html . '"' . $is_checked . ' class="checkall"></td>';
|
||||
$multi_values .= '<td class="export_table_name">'
|
||||
. str_replace(' ', ' ', $table_html) . '</td>';
|
||||
$multi_values .= '<td class="export_structure">'
|
||||
. '<input type="checkbox" name="table_structure[]"'
|
||||
. ' value="' . $table_html . '"' . $structure_checked . '></td>';
|
||||
$multi_values .= '<td class="export_data">'
|
||||
. '<input type="checkbox" name="table_data[]"'
|
||||
. ' value="' . $table_html . '"' . $data_checked . '></td>';
|
||||
$multi_values .= '</tr>';
|
||||
} // end for
|
||||
|
||||
$multi_values .= "\n";
|
||||
$multi_values .= '</tbody></table></div>';
|
||||
|
||||
if (! isset($sql_query)) {
|
||||
$sql_query = '';
|
||||
}
|
||||
if (! isset($num_tables)) {
|
||||
$num_tables = 0;
|
||||
}
|
||||
if (! isset($unlim_num_rows)) {
|
||||
$unlim_num_rows = 0;
|
||||
}
|
||||
if ($multi_values === null) {
|
||||
$multi_values = '';
|
||||
}
|
||||
$response = Response::getInstance();
|
||||
$displayExport = new DisplayExport();
|
||||
$response->addHTML(
|
||||
$displayExport->getDisplay(
|
||||
'database',
|
||||
$db,
|
||||
$table,
|
||||
$sql_query,
|
||||
$num_tables,
|
||||
$unlim_num_rows,
|
||||
$multi_values
|
||||
)
|
||||
);
|
||||
@ -1,56 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Database import page
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Config\PageSettings;
|
||||
use PhpMyAdmin\Display\Import;
|
||||
use PhpMyAdmin\Response;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
global $db, $table;
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
PageSettings::showGroup('Import');
|
||||
|
||||
$response = Response::getInstance();
|
||||
$header = $response->getHeader();
|
||||
$scripts = $header->getScripts();
|
||||
$scripts->addFile('import.js');
|
||||
|
||||
$import = new Import();
|
||||
|
||||
/**
|
||||
* Gets tables information and displays top links
|
||||
*/
|
||||
require ROOT_PATH . 'libraries/db_common.inc.php';
|
||||
|
||||
list(
|
||||
$tables,
|
||||
$num_tables,
|
||||
$total_num_tables,
|
||||
$sub_part,
|
||||
$is_show_stats,
|
||||
$db_is_system_schema,
|
||||
$tooltip_truename,
|
||||
$tooltip_aliasname,
|
||||
$pos
|
||||
) = PhpMyAdmin\Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
|
||||
|
||||
$response = Response::getInstance();
|
||||
$response->addHTML(
|
||||
$import->get(
|
||||
'database',
|
||||
$db,
|
||||
$table,
|
||||
$max_upload_size
|
||||
)
|
||||
);
|
||||
@ -1,51 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Handles database multi-table querying
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Controllers\Database\MultiTableQueryController;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Template;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
/** @var MultiTableQueryController $controller */
|
||||
$controller = $containerBuilder->get(MultiTableQueryController::class);
|
||||
|
||||
/** @var Template $template */
|
||||
$template = $containerBuilder->get('template');
|
||||
|
||||
if (isset($_POST['sql_query'])) {
|
||||
$controller->displayResults([
|
||||
'sql_query' => $_POST['sql_query'],
|
||||
'db' => $_REQUEST['db'] ?? null,
|
||||
]);
|
||||
} elseif (isset($_GET['tables'])) {
|
||||
$response->addJSON($controller->table([
|
||||
'tables' => $_GET['tables'],
|
||||
'db' => $_REQUEST['db'] ?? null,
|
||||
]));
|
||||
} else {
|
||||
$header = $response->getHeader();
|
||||
$scripts = $header->getScripts();
|
||||
$scripts->addFile('vendor/jquery/jquery.md5.js');
|
||||
$scripts->addFile('database/multi_table_query.js');
|
||||
$scripts->addFile('database/query_generator.js');
|
||||
|
||||
$response->addHTML($controller->index($template));
|
||||
}
|
||||
@ -1,321 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* handles miscellaneous db operations:
|
||||
* - move/rename
|
||||
* - copy
|
||||
* - changing collation
|
||||
* - changing comment
|
||||
* - adding tables
|
||||
* - viewing PDF schemas
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\CheckUserPrivileges;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Display\CreateTable;
|
||||
use PhpMyAdmin\Message;
|
||||
use PhpMyAdmin\Operations;
|
||||
use PhpMyAdmin\Plugins;
|
||||
use PhpMyAdmin\Plugins\Export\ExportSql;
|
||||
use PhpMyAdmin\Relation;
|
||||
use PhpMyAdmin\RelationCleanup;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
global $cfg, $db, $server, $url_query;
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
$checkUserPrivileges = new CheckUserPrivileges($dbi);
|
||||
$checkUserPrivileges->getPrivileges();
|
||||
|
||||
$header = $response->getHeader();
|
||||
$scripts = $header->getScripts();
|
||||
$scripts->addFile('database/operations.js');
|
||||
|
||||
$sql_query = '';
|
||||
|
||||
/** @var Relation $relation */
|
||||
$relation = $containerBuilder->get('relation');
|
||||
$operations = new Operations($dbi, $relation);
|
||||
$relationCleanup = new RelationCleanup($dbi, $relation);
|
||||
|
||||
/**
|
||||
* Rename/move or copy database
|
||||
*/
|
||||
if (strlen($db) > 0
|
||||
&& (! empty($_POST['db_rename']) || ! empty($_POST['db_copy']))
|
||||
) {
|
||||
if (! empty($_POST['db_rename'])) {
|
||||
$move = true;
|
||||
} else {
|
||||
$move = false;
|
||||
}
|
||||
|
||||
if (! isset($_POST['newname']) || strlen($_POST['newname']) === 0) {
|
||||
$message = Message::error(__('The database name is empty!'));
|
||||
} else {
|
||||
// lower_case_table_names=1 `DB` becomes `db`
|
||||
if ($dbi->getLowerCaseNames() === '1') {
|
||||
$_POST['newname'] = mb_strtolower(
|
||||
$_POST['newname']
|
||||
);
|
||||
}
|
||||
|
||||
if ($_POST['newname'] === $_REQUEST['db']) {
|
||||
$message = Message::error(
|
||||
__('Cannot copy database to the same name. Change the name and try again.')
|
||||
);
|
||||
} else {
|
||||
$_error = false;
|
||||
if ($move || ! empty($_POST['create_database_before_copying'])) {
|
||||
$operations->createDbBeforeCopy();
|
||||
}
|
||||
|
||||
// here I don't use DELIMITER because it's not part of the
|
||||
// language; I have to send each statement one by one
|
||||
|
||||
// to avoid selecting alternatively the current and new db
|
||||
// we would need to modify the CREATE definitions to qualify
|
||||
// the db name
|
||||
$operations->runProcedureAndFunctionDefinitions($db);
|
||||
|
||||
// go back to current db, just in case
|
||||
$dbi->selectDb($db);
|
||||
|
||||
$tables_full = $dbi->getTablesFull($db);
|
||||
|
||||
// remove all foreign key constraints, otherwise we can get errors
|
||||
/** @var ExportSql $export_sql_plugin */
|
||||
$export_sql_plugin = Plugins::getPlugin(
|
||||
"export",
|
||||
"sql",
|
||||
'libraries/classes/Plugins/Export/',
|
||||
[
|
||||
'single_table' => isset($single_table),
|
||||
'export_type' => 'database',
|
||||
]
|
||||
);
|
||||
|
||||
// create stand-in tables for views
|
||||
$views = $operations->getViewsAndCreateSqlViewStandIn(
|
||||
$tables_full,
|
||||
$export_sql_plugin,
|
||||
$db
|
||||
);
|
||||
|
||||
// copy tables
|
||||
$sqlConstratints = $operations->copyTables(
|
||||
$tables_full,
|
||||
$move,
|
||||
$db
|
||||
);
|
||||
|
||||
// handle the views
|
||||
if (! $_error) {
|
||||
$operations->handleTheViews($views, $move, $db);
|
||||
}
|
||||
unset($views);
|
||||
|
||||
// now that all tables exist, create all the accumulated constraints
|
||||
if (! $_error && count($sqlConstratints) > 0) {
|
||||
$operations->createAllAccumulatedConstraints($sqlConstratints);
|
||||
}
|
||||
unset($sqlConstratints);
|
||||
|
||||
if ($dbi->getVersion() >= 50100) {
|
||||
// here DELIMITER is not used because it's not part of the
|
||||
// language; each statement is sent one by one
|
||||
|
||||
$operations->runEventDefinitionsForDb($db);
|
||||
}
|
||||
|
||||
// go back to current db, just in case
|
||||
$dbi->selectDb($db);
|
||||
|
||||
// Duplicate the bookmarks for this db (done once for each db)
|
||||
$operations->duplicateBookmarks($_error, $db);
|
||||
|
||||
if (! $_error && $move) {
|
||||
if (isset($_POST['adjust_privileges'])
|
||||
&& ! empty($_POST['adjust_privileges'])
|
||||
) {
|
||||
$operations->adjustPrivilegesMoveDb($db, $_POST['newname']);
|
||||
}
|
||||
|
||||
/**
|
||||
* cleanup pmadb stuff for this db
|
||||
*/
|
||||
$relationCleanup->database($db);
|
||||
|
||||
// if someday the RENAME DATABASE reappears, do not DROP
|
||||
$local_query = 'DROP DATABASE '
|
||||
. Util::backquote($db) . ';';
|
||||
$sql_query .= "\n" . $local_query;
|
||||
$dbi->query($local_query);
|
||||
|
||||
$message = Message::success(
|
||||
__('Database %1$s has been renamed to %2$s.')
|
||||
);
|
||||
$message->addParam($db);
|
||||
$message->addParam($_POST['newname']);
|
||||
} elseif (! $_error) {
|
||||
if (isset($_POST['adjust_privileges'])
|
||||
&& ! empty($_POST['adjust_privileges'])
|
||||
) {
|
||||
$operations->adjustPrivilegesCopyDb($db, $_POST['newname']);
|
||||
}
|
||||
|
||||
$message = Message::success(
|
||||
__('Database %1$s has been copied to %2$s.')
|
||||
);
|
||||
$message->addParam($db);
|
||||
$message->addParam($_POST['newname']);
|
||||
} else {
|
||||
$message = Message::error();
|
||||
}
|
||||
$reload = true;
|
||||
|
||||
/* Change database to be used */
|
||||
if (! $_error && $move) {
|
||||
$db = $_POST['newname'];
|
||||
} elseif (! $_error) {
|
||||
if (isset($_POST['switch_to_new'])
|
||||
&& $_POST['switch_to_new'] == 'true'
|
||||
) {
|
||||
$_SESSION['pma_switch_to_new'] = true;
|
||||
$db = $_POST['newname'];
|
||||
} else {
|
||||
$_SESSION['pma_switch_to_new'] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Database has been successfully renamed/moved. If in an Ajax request,
|
||||
* generate the output with {@link PhpMyAdmin\Response} and exit
|
||||
*/
|
||||
if ($response->isAjax()) {
|
||||
$response->setRequestStatus($message->isSuccess());
|
||||
$response->addJSON('message', $message);
|
||||
$response->addJSON('newname', $_POST['newname']);
|
||||
$response->addJSON(
|
||||
'sql_query',
|
||||
Util::getMessage(null, $sql_query)
|
||||
);
|
||||
$response->addJSON('db', $db);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings for relations stuff
|
||||
*/
|
||||
$cfgRelation = $relation->getRelationsParam();
|
||||
|
||||
/**
|
||||
* Check if comments were updated
|
||||
* (must be done before displaying the menu tabs)
|
||||
*/
|
||||
if (isset($_POST['comment'])) {
|
||||
$relation->setDbComment($db, $_POST['comment']);
|
||||
}
|
||||
|
||||
require ROOT_PATH . 'libraries/db_common.inc.php';
|
||||
$url_query .= '&goto=db_operations.php';
|
||||
|
||||
// Gets the database structure
|
||||
$sub_part = '_structure';
|
||||
|
||||
list(
|
||||
$tables,
|
||||
$num_tables,
|
||||
$total_num_tables,
|
||||
$sub_part,
|
||||
$is_show_stats,
|
||||
$db_is_system_schema,
|
||||
$tooltip_truename,
|
||||
$tooltip_aliasname,
|
||||
$pos
|
||||
) = Util::getDbInfo($db, $sub_part === null ? '' : $sub_part);
|
||||
|
||||
echo "\n";
|
||||
|
||||
if (isset($message)) {
|
||||
echo Util::getMessage($message, $sql_query);
|
||||
unset($message);
|
||||
}
|
||||
|
||||
$db_collation = $dbi->getDbCollation($db);
|
||||
$is_information_schema = $dbi->isSystemSchema($db);
|
||||
|
||||
if (! $is_information_schema) {
|
||||
if ($cfgRelation['commwork']) {
|
||||
/**
|
||||
* database comment
|
||||
*/
|
||||
$response->addHTML($operations->getHtmlForDatabaseComment($db));
|
||||
}
|
||||
|
||||
$response->addHTML('<div>');
|
||||
$response->addHTML(CreateTable::getHtml($db));
|
||||
$response->addHTML('</div>');
|
||||
|
||||
/**
|
||||
* rename database
|
||||
*/
|
||||
if ($db != 'mysql') {
|
||||
$response->addHTML($operations->getHtmlForRenameDatabase($db, $db_collation));
|
||||
}
|
||||
|
||||
// Drop link if allowed
|
||||
// Don't even try to drop information_schema.
|
||||
// You won't be able to. Believe me. You won't.
|
||||
// Don't allow to easily drop mysql database, RFE #1327514.
|
||||
if (($dbi->isSuperuser() || $cfg['AllowUserDropDatabase'])
|
||||
&& ! $db_is_system_schema
|
||||
&& $db != 'mysql'
|
||||
) {
|
||||
$response->addHTML($operations->getHtmlForDropDatabaseLink($db));
|
||||
}
|
||||
/**
|
||||
* Copy database
|
||||
*/
|
||||
$response->addHTML($operations->getHtmlForCopyDatabase($db, $db_collation));
|
||||
|
||||
/**
|
||||
* Change database charset
|
||||
*/
|
||||
$response->addHTML($operations->getHtmlForChangeDatabaseCharset($db, $db_collation));
|
||||
|
||||
if (! $cfgRelation['allworks']
|
||||
&& $cfg['PmaNoRelation_DisableWarning'] == false
|
||||
) {
|
||||
$message = Message::notice(
|
||||
__(
|
||||
'The phpMyAdmin configuration storage has been deactivated. ' .
|
||||
'%sFind out why%s.'
|
||||
)
|
||||
);
|
||||
$message->addParamHtml('<a href="./chk_rel.php" data-post="' . $url_query . '">');
|
||||
$message->addParamHtml('</a>');
|
||||
/* Show error if user has configured something, notice elsewhere */
|
||||
if (! empty($cfg['Servers'][$server]['pmadb'])) {
|
||||
$message->isError(true);
|
||||
}
|
||||
} // end if
|
||||
} // end if (!$is_information_schema)
|
||||
192
db_qbe.php
192
db_qbe.php
@ -1,192 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* query by example the whole database
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Database\Qbe;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Message;
|
||||
use PhpMyAdmin\Relation;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\SavedSearches;
|
||||
use PhpMyAdmin\Sql;
|
||||
use PhpMyAdmin\Template;
|
||||
use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
global $db, $pmaThemeImage, $url_query;
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
/** @var Relation $relation */
|
||||
$relation = $containerBuilder->get('relation');
|
||||
/** @var Template $template */
|
||||
$template = $containerBuilder->get('template');
|
||||
|
||||
// Gets the relation settings
|
||||
$cfgRelation = $relation->getRelationsParam();
|
||||
|
||||
$savedSearchList = [];
|
||||
$savedSearch = null;
|
||||
$currentSearchId = null;
|
||||
if ($cfgRelation['savedsearcheswork']) {
|
||||
$header = $response->getHeader();
|
||||
$scripts = $header->getScripts();
|
||||
$scripts->addFile('database/qbe.js');
|
||||
|
||||
//Get saved search list.
|
||||
$savedSearch = new SavedSearches($GLOBALS, $relation);
|
||||
$savedSearch->setUsername($GLOBALS['cfg']['Server']['user'])
|
||||
->setDbname($db);
|
||||
|
||||
if (! empty($_POST['searchId'])) {
|
||||
$savedSearch->setId($_POST['searchId']);
|
||||
}
|
||||
|
||||
//Action field is sent.
|
||||
if (isset($_POST['action'])) {
|
||||
$savedSearch->setSearchName($_POST['searchName']);
|
||||
if ('create' === $_POST['action']) {
|
||||
$saveResult = $savedSearch->setId(null)
|
||||
->setCriterias($_POST)
|
||||
->save();
|
||||
} elseif ('update' === $_POST['action']) {
|
||||
$saveResult = $savedSearch->setCriterias($_POST)
|
||||
->save();
|
||||
} elseif ('delete' === $_POST['action']) {
|
||||
$deleteResult = $savedSearch->delete();
|
||||
//After deletion, reset search.
|
||||
$savedSearch = new SavedSearches($GLOBALS, $relation);
|
||||
$savedSearch->setUsername($GLOBALS['cfg']['Server']['user'])
|
||||
->setDbname($db);
|
||||
$_POST = [];
|
||||
} elseif ('load' === $_POST['action']) {
|
||||
if (empty($_POST['searchId'])) {
|
||||
//when not loading a search, reset the object.
|
||||
$savedSearch = new SavedSearches($GLOBALS, $relation);
|
||||
$savedSearch->setUsername($GLOBALS['cfg']['Server']['user'])
|
||||
->setDbname($db);
|
||||
$_POST = [];
|
||||
} else {
|
||||
$loadResult = $savedSearch->load();
|
||||
}
|
||||
}
|
||||
//Else, it's an "update query"
|
||||
}
|
||||
|
||||
$savedSearchList = $savedSearch->getList();
|
||||
$currentSearchId = $savedSearch->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* A query has been submitted -> (maybe) execute it
|
||||
*/
|
||||
$message_to_display = false;
|
||||
if (isset($_POST['submit_sql']) && ! empty($sql_query)) {
|
||||
if (0 !== stripos($sql_query, "SELECT")) {
|
||||
$message_to_display = true;
|
||||
} else {
|
||||
$goto = 'db_sql.php';
|
||||
$sql = new Sql();
|
||||
$sql->executeQueryAndSendQueryResponse(
|
||||
null, // analyzed_sql_results
|
||||
false, // is_gotofile
|
||||
$_POST['db'], // db
|
||||
null, // table
|
||||
false, // find_real_end
|
||||
null, // sql_query_for_bookmark
|
||||
null, // extra_data
|
||||
null, // message_to_show
|
||||
null, // message
|
||||
null, // sql_data
|
||||
$goto, // goto
|
||||
$pmaThemeImage, // pmaThemeImage
|
||||
null, // disp_query
|
||||
null, // disp_message
|
||||
null, // query_type
|
||||
$sql_query, // sql_query
|
||||
null, // selectedTables
|
||||
null // complete_query
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$sub_part = '_qbe';
|
||||
require ROOT_PATH . 'libraries/db_common.inc.php';
|
||||
$url_query .= '&goto=db_qbe.php';
|
||||
$url_params['goto'] = 'db_qbe.php';
|
||||
|
||||
list(
|
||||
$tables,
|
||||
$num_tables,
|
||||
$total_num_tables,
|
||||
$sub_part,
|
||||
$is_show_stats,
|
||||
$db_is_system_schema,
|
||||
$tooltip_truename,
|
||||
$tooltip_aliasname,
|
||||
$pos
|
||||
) = Util::getDbInfo($db, $sub_part === null ? '' : $sub_part);
|
||||
|
||||
if ($message_to_display) {
|
||||
Message::error(
|
||||
__('You have to choose at least one column to display!')
|
||||
)
|
||||
->display();
|
||||
}
|
||||
unset($message_to_display);
|
||||
|
||||
// create new qbe search instance
|
||||
$db_qbe = new Qbe($relation, $template, $dbi, $db, $savedSearchList, $savedSearch);
|
||||
|
||||
$secondaryTabs = [
|
||||
'multi' => [
|
||||
'link' => 'db_multi_table_query.php',
|
||||
'text' => __('Multi-table query'),
|
||||
],
|
||||
'qbe' => [
|
||||
'link' => 'db_qbe.php',
|
||||
'text' => __('Query by example'),
|
||||
],
|
||||
];
|
||||
$response->addHTML(
|
||||
$template->render('secondary_tabs', [
|
||||
'url_params' => $url_params,
|
||||
'sub_tabs' => $secondaryTabs,
|
||||
])
|
||||
);
|
||||
|
||||
$url = 'db_designer.php' . Url::getCommon(
|
||||
array_merge(
|
||||
$url_params,
|
||||
['query' => 1]
|
||||
)
|
||||
);
|
||||
$response->addHTML(
|
||||
Message::notice(
|
||||
sprintf(
|
||||
__('Switch to %svisual builder%s'),
|
||||
'<a href="' . $url . '">',
|
||||
'</a>'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Displays the Query by example form
|
||||
*/
|
||||
$response->addHTML($db_qbe->getSelectionForm());
|
||||
@ -1,87 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Routines management.
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\CheckUserPrivileges;
|
||||
use PhpMyAdmin\Controllers\Database\RoutinesController;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
/** @var string $db */
|
||||
$db = $containerBuilder->getParameter('db');
|
||||
|
||||
/** @var string $table */
|
||||
$table = $containerBuilder->getParameter('table');
|
||||
|
||||
/** @var CheckUserPrivileges $checkUserPrivileges */
|
||||
$checkUserPrivileges = $containerBuilder->get('check_user_privileges');
|
||||
$checkUserPrivileges->getPrivileges();
|
||||
|
||||
$_PMA_RTE = 'RTN';
|
||||
|
||||
/** @var RoutinesController $controller */
|
||||
$controller = $containerBuilder->get(RoutinesController::class);
|
||||
|
||||
if (! $response->isAjax()) {
|
||||
/**
|
||||
* Displays the header and tabs
|
||||
*/
|
||||
if (! empty($table) && in_array($table, $dbi->getTables($db))) {
|
||||
include_once ROOT_PATH . 'libraries/tbl_common.inc.php';
|
||||
} else {
|
||||
$table = '';
|
||||
include_once ROOT_PATH . 'libraries/db_common.inc.php';
|
||||
|
||||
list(
|
||||
$tables,
|
||||
$num_tables,
|
||||
$total_num_tables,
|
||||
$sub_part,
|
||||
$is_show_stats,
|
||||
$db_is_system_schema,
|
||||
$tooltip_truename,
|
||||
$tooltip_aliasname,
|
||||
$pos
|
||||
) = Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Since we did not include some libraries, we need
|
||||
* to manually select the required database and
|
||||
* create the missing $url_query variable
|
||||
*/
|
||||
if (strlen($db) > 0) {
|
||||
$dbi->selectDb($db);
|
||||
if (! isset($url_query)) {
|
||||
$url_query = Url::getCommon(
|
||||
[
|
||||
'db' => $db,
|
||||
'table' => $table,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$controller->index([
|
||||
'type' => $_REQUEST['type'] ?? null,
|
||||
]);
|
||||
@ -1,85 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* searches the entire database
|
||||
*
|
||||
* @todo make use of UNION when searching multiple tables
|
||||
* @todo display executed query, optional?
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Database\Search;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Template;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
global $db, $url_query;
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
/** @var Template $template */
|
||||
$template = $containerBuilder->get('template');
|
||||
|
||||
$header = $response->getHeader();
|
||||
$scripts = $header->getScripts();
|
||||
$scripts->addFile('database/search.js');
|
||||
$scripts->addFile('vendor/stickyfill.min.js');
|
||||
$scripts->addFile('sql.js');
|
||||
$scripts->addFile('makegrid.js');
|
||||
|
||||
require ROOT_PATH . 'libraries/db_common.inc.php';
|
||||
|
||||
// If config variable $GLOBALS['cfg']['UseDbSearch'] is on false : exit.
|
||||
if (! $GLOBALS['cfg']['UseDbSearch']) {
|
||||
Util::mysqlDie(
|
||||
__('Access denied!'),
|
||||
'',
|
||||
false,
|
||||
$err_url
|
||||
);
|
||||
} // end if
|
||||
$url_query .= '&goto=db_search.php';
|
||||
$url_params['goto'] = 'db_search.php';
|
||||
|
||||
// Create a database search instance
|
||||
$db_search = new Search($dbi, $db, $template);
|
||||
|
||||
// Display top links if we are not in an Ajax request
|
||||
if (! $response->isAjax()) {
|
||||
list(
|
||||
$tables,
|
||||
$num_tables,
|
||||
$total_num_tables,
|
||||
$sub_part,
|
||||
$is_show_stats,
|
||||
$db_is_system_schema,
|
||||
$tooltip_truename,
|
||||
$tooltip_aliasname,
|
||||
$pos
|
||||
) = Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
|
||||
}
|
||||
|
||||
// Main search form has been submitted, get results
|
||||
if (isset($_POST['submit_search'])) {
|
||||
$response->addHTML($db_search->getSearchResults());
|
||||
}
|
||||
|
||||
// If we are in an Ajax request, we need to exit after displaying all the HTML
|
||||
if ($response->isAjax() && empty($_REQUEST['ajax_page_request'])) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Display the search form
|
||||
$response->addHTML($db_search->getMainHtml());
|
||||
49
db_sql.php
49
db_sql.php
@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Database SQL executor
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Controllers\Database\SqlController;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\SqlQueryForm;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
global $containerBuilder;
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
/** @var SqlController $controller */
|
||||
$controller = $containerBuilder->get(SqlController::class);
|
||||
|
||||
/** @var SqlQueryForm $sqlQueryForm */
|
||||
$sqlQueryForm = $containerBuilder->get('sql_query_form');
|
||||
|
||||
$header = $response->getHeader();
|
||||
$scripts = $header->getScripts();
|
||||
$scripts->addFile('makegrid.js');
|
||||
$scripts->addFile('vendor/jquery/jquery.uitablefilter.js');
|
||||
$scripts->addFile('vendor/stickyfill.min.js');
|
||||
$scripts->addFile('sql.js');
|
||||
|
||||
$response->addHTML(
|
||||
$controller->index(
|
||||
[
|
||||
'delimiter' => $_POST['delimiter'] ?? null,
|
||||
],
|
||||
$sqlQueryForm
|
||||
)
|
||||
);
|
||||
@ -1,41 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Table/Column autocomplete in SQL editors
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Response;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
if ($GLOBALS['cfg']['EnableAutocompleteForTablesAndColumns']) {
|
||||
$db = isset($_POST['db']) ? $_POST['db'] : $GLOBALS['db'];
|
||||
$sql_autocomplete = [];
|
||||
if ($db) {
|
||||
$tableNames = $dbi->getTables($db);
|
||||
foreach ($tableNames as $tableName) {
|
||||
$sql_autocomplete[$tableName] = $dbi->getColumns(
|
||||
$db,
|
||||
$tableName
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$sql_autocomplete = true;
|
||||
}
|
||||
|
||||
$response->addJSON("tables", json_encode($sql_autocomplete));
|
||||
@ -1,27 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Format SQL for SQL editors
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Response;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loading common files. Used to check for authorization, localization and to
|
||||
* load the parsing library.
|
||||
*/
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
$query = ! empty($_POST['sql']) ? $_POST['sql'] : '';
|
||||
|
||||
$query = PhpMyAdmin\SqlParser\Utils\Formatter::format($query);
|
||||
|
||||
$response = Response::getInstance();
|
||||
$response->addJSON("sql", $query);
|
||||
@ -1,62 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Database structure manipulation
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Controllers\Database\StructureController;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Response;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
require_once ROOT_PATH . 'libraries/db_common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
/** @var StructureController $controller */
|
||||
$controller = $containerBuilder->get(StructureController::class);
|
||||
|
||||
if ($response->isAjax() && ! empty($_REQUEST['favorite_table'])) {
|
||||
$json = $controller->addRemoveFavoriteTablesAction([
|
||||
'favorite_table' => $_REQUEST['favorite_table'],
|
||||
'favoriteTables' => $_REQUEST['favoriteTables'] ?? null,
|
||||
'sync_favorite_tables' => $_REQUEST['sync_favorite_tables'] ?? null,
|
||||
'add_favorite' => $_REQUEST['add_favorite'] ?? null,
|
||||
'remove_favorite' => $_REQUEST['remove_favorite'] ?? null,
|
||||
]);
|
||||
if ($json !== null) {
|
||||
$response->addJSON($json);
|
||||
}
|
||||
} elseif ($response->isAjax()
|
||||
&& isset($_REQUEST['real_row_count'])
|
||||
&& (bool) $_REQUEST['real_row_count'] === true
|
||||
) {
|
||||
$response->addJSON($controller->handleRealRowCountRequestAction([
|
||||
'real_row_count_all' => $_REQUEST['real_row_count_all'] ?? null,
|
||||
'table' => $_REQUEST['table'] ?? null,
|
||||
]));
|
||||
} else {
|
||||
$response->getHeader()->getScripts()->addFiles([
|
||||
'database/structure.js',
|
||||
'table/change.js',
|
||||
]);
|
||||
|
||||
$response->addHTML($controller->index([
|
||||
'submit_mult' => $_POST['submit_mult'] ?? null,
|
||||
'selected_tbl' => $_POST['selected_tbl'] ?? null,
|
||||
'mult_btn' => $_POST['mult_btn'] ?? null,
|
||||
'sort' => $_REQUEST['sort'] ?? null,
|
||||
'sort_order' => $_REQUEST['sort_order'] ?? null,
|
||||
]));
|
||||
}
|
||||
129
db_tracking.php
129
db_tracking.php
@ -1,129 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Tracking configuration for database
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Display\CreateTable;
|
||||
use PhpMyAdmin\Message;
|
||||
use PhpMyAdmin\Relation;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Tracker;
|
||||
use PhpMyAdmin\Tracking;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
global $db, $pmaThemeImage, $text_dir, $url_query;
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
//Get some js files needed for Ajax requests
|
||||
$response = Response::getInstance();
|
||||
$header = $response->getHeader();
|
||||
$scripts = $header->getScripts();
|
||||
$scripts->addFile('vendor/jquery/jquery.tablesorter.js');
|
||||
$scripts->addFile('database/tracking.js');
|
||||
|
||||
/** @var Tracking $tracking */
|
||||
$tracking = $containerBuilder->get('tracking');
|
||||
|
||||
/**
|
||||
* If we are not in an Ajax request, then do the common work and show the links etc.
|
||||
*/
|
||||
require ROOT_PATH . 'libraries/db_common.inc.php';
|
||||
$url_query .= '&goto=tbl_tracking.php&back=db_tracking.php';
|
||||
$url_params['goto'] = 'tbl_tracking.php';
|
||||
$url_params['back'] = 'db_tracking.php';
|
||||
|
||||
// Get the database structure
|
||||
$sub_part = '_structure';
|
||||
|
||||
list(
|
||||
$tables,
|
||||
$num_tables,
|
||||
$total_num_tables,
|
||||
$sub_part,
|
||||
$is_show_stats,
|
||||
$db_is_system_schema,
|
||||
$tooltip_truename,
|
||||
$tooltip_aliasname,
|
||||
$pos
|
||||
) = Util::getDbInfo($db, $sub_part === null ? '' : $sub_part);
|
||||
|
||||
if (isset($_POST['delete_tracking']) && isset($_POST['table'])) {
|
||||
Tracker::deleteTracking($db, $_POST['table']);
|
||||
Message::success(
|
||||
__('Tracking data deleted successfully.')
|
||||
)->display();
|
||||
} elseif (isset($_POST['submit_create_version'])) {
|
||||
$tracking->createTrackingForMultipleTables($_POST['selected']);
|
||||
Message::success(
|
||||
sprintf(
|
||||
__(
|
||||
'Version %1$s was created for selected tables,'
|
||||
. ' tracking is active for them.'
|
||||
),
|
||||
htmlspecialchars($_POST['version'])
|
||||
)
|
||||
)->display();
|
||||
} elseif (isset($_POST['submit_mult'])) {
|
||||
if (! empty($_POST['selected_tbl'])) {
|
||||
if ($_POST['submit_mult'] == 'delete_tracking') {
|
||||
foreach ($_POST['selected_tbl'] as $table) {
|
||||
Tracker::deleteTracking($db, $table);
|
||||
}
|
||||
Message::success(
|
||||
__('Tracking data deleted successfully.')
|
||||
)->display();
|
||||
} elseif ($_POST['submit_mult'] == 'track') {
|
||||
echo $tracking->getHtmlForDataDefinitionAndManipulationStatements(
|
||||
'db_tracking.php' . $url_query,
|
||||
0,
|
||||
$db,
|
||||
$_POST['selected_tbl']
|
||||
);
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
Message::notice(
|
||||
__('No tables selected.')
|
||||
)->display();
|
||||
}
|
||||
}
|
||||
|
||||
// Get tracked data about the database
|
||||
$data = Tracker::getTrackedData($db, '', '1');
|
||||
|
||||
// No tables present and no log exist
|
||||
if ($num_tables == 0 && count($data['ddlog']) === 0) {
|
||||
echo '<p>' , __('No tables found in database.') , '</p>' , "\n";
|
||||
|
||||
if (empty($db_is_system_schema)) {
|
||||
echo CreateTable::getHtml($db);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
echo $tracking->getHtmlForDbTrackingTables(
|
||||
$db,
|
||||
$url_query,
|
||||
$pmaThemeImage,
|
||||
$text_dir
|
||||
);
|
||||
|
||||
// If available print out database log
|
||||
if (count($data['ddlog']) > 0) {
|
||||
$log = '';
|
||||
foreach ($data['ddlog'] as $entry) {
|
||||
$log .= '# ' . $entry['date'] . ' ' . $entry['username'] . "\n"
|
||||
. $entry['statement'] . "\n";
|
||||
}
|
||||
echo Util::getMessage(__('Database Log'), $log);
|
||||
}
|
||||
@ -1,80 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Triggers management.
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Controllers\Database\TriggersController;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
$_PMA_RTE = 'TRI';
|
||||
|
||||
/** @var TriggersController $controller */
|
||||
$controller = $containerBuilder->get(TriggersController::class);
|
||||
|
||||
/** @var string $db */
|
||||
$db = $containerBuilder->getParameter('db');
|
||||
|
||||
/** @var string $table */
|
||||
$table = $containerBuilder->getParameter('table');
|
||||
|
||||
if (! $response->isAjax()) {
|
||||
/**
|
||||
* Displays the header and tabs
|
||||
*/
|
||||
if (! empty($table) && in_array($table, $dbi->getTables($db))) {
|
||||
include_once ROOT_PATH . 'libraries/tbl_common.inc.php';
|
||||
} else {
|
||||
$table = '';
|
||||
include_once ROOT_PATH . 'libraries/db_common.inc.php';
|
||||
|
||||
list(
|
||||
$tables,
|
||||
$num_tables,
|
||||
$total_num_tables,
|
||||
$sub_part,
|
||||
$is_show_stats,
|
||||
$db_is_system_schema,
|
||||
$tooltip_truename,
|
||||
$tooltip_aliasname,
|
||||
$pos
|
||||
) = Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Since we did not include some libraries, we need
|
||||
* to manually select the required database and
|
||||
* create the missing $url_query variable
|
||||
*/
|
||||
if (strlen($db) > 0) {
|
||||
$dbi->selectDb($db);
|
||||
if (! isset($url_query)) {
|
||||
$url_query = Url::getCommon(
|
||||
[
|
||||
'db' => $db,
|
||||
'table' => $table,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$controller->index();
|
||||
@ -44,14 +44,14 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'phpMyAdmin'
|
||||
copyright = u'2012 - 2020, The phpMyAdmin devel team'
|
||||
copyright = u'2012 - 2021, The phpMyAdmin devel team'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '5.0.4'
|
||||
version = '5.1.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = version
|
||||
|
||||
@ -315,8 +315,6 @@ linkcheck_ignore = [
|
||||
r'https://authy.com/.*',
|
||||
# Site often changes links and reverts changes (9362bde02d0535a2f8cb74a18797249cb734c4b0)
|
||||
r'https://www.yubico.com/.*',
|
||||
# 500 Server Error: Internal Server Error
|
||||
r'http://www.scriptalicious.com/.*',
|
||||
# Some timeouts and SSL issues: https://github.com/sektioneins/suhosin/issues/119
|
||||
r'https://suhosin.org/.*',
|
||||
]
|
||||
|
||||
144
doc/config.rst
144
doc/config.rst
@ -20,7 +20,7 @@ the file. This file is for over-writing the defaults; if you wish to use the
|
||||
default value there's no need to add a line here.
|
||||
|
||||
The parameters which relate to design (like colors) are placed in
|
||||
:file:`themes/themename/layout.inc.php`. You might also want to create
|
||||
:file:`themes/themename/scss/_variables.scss`. You might also want to create
|
||||
:file:`config.footer.inc.php` and :file:`config.header.inc.php` files to add
|
||||
your site specific code to be included on start and end of each page.
|
||||
|
||||
@ -29,15 +29,6 @@ your site specific code to be included on start and end of each page.
|
||||
Some distributions (eg. Debian or Ubuntu) store :file:`config.inc.php` in
|
||||
``/etc/phpmyadmin`` instead of within phpMyAdmin sources.
|
||||
|
||||
.. warning::
|
||||
|
||||
:term:`Mac` users should note that if you are on a version before
|
||||
:term:`Mac OS X`, PHP does not seem to
|
||||
like :term:`Mac` end of lines character (``\r``). So
|
||||
ensure you choose the option that allows to use the \*nix end of line
|
||||
character (``\n``) in your text editor before saving a script you have
|
||||
modified.
|
||||
|
||||
Basic settings
|
||||
--------------
|
||||
|
||||
@ -1037,6 +1028,10 @@ Server connection settings
|
||||
:type: string or false
|
||||
:default: ``''``
|
||||
|
||||
The table used by phpMyAdmin to store user name information for associating with user groups.
|
||||
See the next entry on :config:option:`$cfg['Servers'][$i]['usergroups']` for more details
|
||||
and the suggested settings.
|
||||
|
||||
.. config:option:: $cfg['Servers'][$i]['usergroups']
|
||||
|
||||
:type: string or false
|
||||
@ -1044,7 +1039,7 @@ Server connection settings
|
||||
|
||||
Since release 4.1.0 you can create different user groups with menu items
|
||||
attached to them. Users can be assigned to these groups and the logged in
|
||||
user would only see menu items configured to the usergroup he is assigned to.
|
||||
user would only see menu items configured to the usergroup they are assigned to.
|
||||
To do this it needs two tables "usergroups" (storing allowed menu items for each
|
||||
user group) and "users" (storing users and their assignments to user groups).
|
||||
|
||||
@ -1616,6 +1611,27 @@ Generic settings
|
||||
have to set :config:option:`$cfg['PmaAbsoluteUri']` for correct
|
||||
redirection.
|
||||
|
||||
.. config:option:: $cfg['MysqlSslWarningSafeHosts']
|
||||
|
||||
:type: array
|
||||
:default: ``['127.0.0.1', 'localhost']``
|
||||
|
||||
This search is case-sensitive and will match the exact string only.
|
||||
If your setup does not use SSL but is safe because you are using a
|
||||
local connection or private network, you can add your hostname or :term:`IP` to the list.
|
||||
You can also remove the default entries to only include yours.
|
||||
|
||||
This check uses the value of :config:option:`$cfg['Servers'][$i]['host']`.
|
||||
|
||||
.. versionadded:: 5.1.0
|
||||
|
||||
Example configuration
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$cfg['MysqlSslWarningSafeHosts'] = ['127.0.0.1', 'localhost', 'mariadb.local'];
|
||||
|
||||
|
||||
.. config:option:: $cfg['ExecTimeLimit']
|
||||
|
||||
:type: integer [number of seconds]
|
||||
@ -1780,6 +1796,22 @@ Cookie authentication options
|
||||
session and furthermore it makes impossible to recall user name from
|
||||
cookie.
|
||||
|
||||
.. config:option:: $cfg['CookieSameSite']
|
||||
|
||||
:type: string
|
||||
:default: ``'Strict'``
|
||||
|
||||
.. versionadded:: 5.1.0
|
||||
|
||||
It sets SameSite attribute of the Set-Cookie :term:`HTTP` response header.
|
||||
Valid values are:
|
||||
|
||||
* ``Lax``
|
||||
* ``Strict``
|
||||
* ``None``
|
||||
|
||||
.. seealso:: `rfc6265 bis <https://tools.ietf.org/id/draft-ietf-httpbis-rfc6265bis-03.html#rfc.section.5.3.7>`_
|
||||
|
||||
.. config:option:: $cfg['LoginCookieRecall']
|
||||
|
||||
:type: boolean
|
||||
@ -1884,6 +1916,43 @@ Cookie authentication options
|
||||
|
||||
.. versionadded:: 5.0.3
|
||||
|
||||
.. config:option:: $cfg['CaptchaApi']
|
||||
|
||||
:type: string
|
||||
:default: ``'https://www.google.com/recaptcha/api.js'``
|
||||
|
||||
.. versionadded:: 5.1.0
|
||||
|
||||
The URL for the reCaptcha v2 service's API, either Google's or a compatible one.
|
||||
|
||||
.. config:option:: $cfg['CaptchaCsp']
|
||||
|
||||
:type: string
|
||||
:default: ``'https://apis.google.com https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://ssl.gstatic.com/'``
|
||||
|
||||
.. versionadded:: 5.1.0
|
||||
|
||||
The Content-Security-Policy snippet (URLs from which to allow embedded content)
|
||||
for the reCaptcha v2 service, either Google's or a compatible one.
|
||||
|
||||
.. config:option:: $cfg['CaptchaRequestParam']
|
||||
|
||||
:type: string
|
||||
:default: ``'g-recaptcha'``
|
||||
|
||||
.. versionadded:: 5.1.0
|
||||
|
||||
The request parameter used for the reCaptcha v2 service.
|
||||
|
||||
.. config:option:: $cfg['CaptchaResponseParam']
|
||||
|
||||
:type: string
|
||||
:default: ``'g-recaptcha-response'``
|
||||
|
||||
.. versionadded:: 5.1.0
|
||||
|
||||
The response parameter used for the reCaptcha v2 service.
|
||||
|
||||
.. config:option:: $cfg['CaptchaLoginPublicKey']
|
||||
|
||||
:type: string
|
||||
@ -1908,6 +1977,17 @@ Cookie authentication options
|
||||
|
||||
reCaptcha will be then used in :ref:`cookie`.
|
||||
|
||||
.. config:option:: $cfg['CaptchaSiteVerifyURL']
|
||||
|
||||
:type: string
|
||||
:default: ``''``
|
||||
|
||||
The URL for the reCaptcha service to do siteverify action.
|
||||
|
||||
reCaptcha will be then used in :ref:`cookie`.
|
||||
|
||||
.. versionadded:: 5.1.0
|
||||
|
||||
Navigation panel setup
|
||||
----------------------
|
||||
|
||||
@ -2800,7 +2880,7 @@ Web server settings
|
||||
Theme settings
|
||||
--------------
|
||||
|
||||
Please directly modify :file:`themes/themename/layout.inc.php`, although
|
||||
Please directly modify :file:`themes/themename/scss/_variables.scss`, although
|
||||
your changes will be overwritten with the next update.
|
||||
|
||||
Design customization
|
||||
@ -2890,6 +2970,16 @@ Design customization
|
||||
name of the column. The comment is shown as a tool-tip for that
|
||||
column.
|
||||
|
||||
.. config:option:: $cfg['FirstDayOfCalendar']
|
||||
|
||||
:type: integer
|
||||
:default: 0
|
||||
|
||||
This will define the first day of week in the calendar. The number
|
||||
can be set from 0 to 6, which represents the seven days of the week,
|
||||
Sunday to Saturday respectively. This value can also be configured by the user
|
||||
in server settings -> features -> general -> First Day calendar field.
|
||||
|
||||
Text fields
|
||||
-----------
|
||||
|
||||
@ -3439,6 +3529,18 @@ Developer
|
||||
|
||||
These settings might have huge effect on performance or security.
|
||||
|
||||
.. config:option:: $cfg['environment']
|
||||
|
||||
:type: string
|
||||
:default: ``'production'``
|
||||
|
||||
Sets the working environment.
|
||||
|
||||
This only needs to be changed when you are developing phpMyAdmin itself.
|
||||
The ``development`` mode may display debug information in some places.
|
||||
|
||||
Possible values are ``'production'`` or ``'development'``.
|
||||
|
||||
.. config:option:: $cfg['DBG']
|
||||
|
||||
:type: array
|
||||
@ -3620,3 +3722,21 @@ server certificates and tell phpMyAdmin to use them:
|
||||
:config:option:`$cfg['Servers'][$i]['ssl_ca']`,
|
||||
:config:option:`$cfg['Servers'][$i]['ssl_verify']`,
|
||||
<https://bugs.php.net/bug.php?id=72048>
|
||||
|
||||
reCaptcha using hCaptcha
|
||||
++++++++++++++++++++++++
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$cfg['CaptchaApi'] = 'https://www.hcaptcha.com/1/api.js';
|
||||
$cfg['CaptchaCsp'] = 'https://hcaptcha.com https://*.hcaptcha.com';
|
||||
$cfg['CaptchaRequestParam'] = 'h-captcha';
|
||||
$cfg['CaptchaResponseParam'] = 'h-captcha-response';
|
||||
$cfg['CaptchaSiteVerifyURL'] = 'https://hcaptcha.com/siteverify';
|
||||
// This is the secret key from hCaptcha dashboard
|
||||
$cfg['CaptchaLoginPrivateKey'] = '0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
|
||||
// This is the site key from hCaptcha dashboard
|
||||
$cfg['CaptchaLoginPublicKey'] = 'xxx-xxx-xxx-xxx-xxxx';
|
||||
|
||||
.. seealso:: `hCaptcha website <https://www.hcaptcha.com/>`_
|
||||
.. seealso:: `hCaptcha Developer Guide <https://docs.hcaptcha.com/>`_
|
||||
|
||||
19
doc/faq.rst
19
doc/faq.rst
@ -355,7 +355,7 @@ PHP scripts. Of course you have to restart Apache.
|
||||
|
||||
This is a permission problem. Right-click on the phpmyadmin folder and
|
||||
choose properties. Under the tab Security, click on "Add" and select
|
||||
the user "IUSR\_machine" from the list. Now set his permissions and it
|
||||
the user "IUSR\_machine" from the list. Now set their permissions and it
|
||||
should work.
|
||||
|
||||
.. _faq1_27:
|
||||
@ -493,6 +493,11 @@ forget to change directory name inside of it):
|
||||
|
||||
.. seealso:: :ref:`faq4_8`
|
||||
|
||||
.. versionchanged:: 5.1.0
|
||||
|
||||
Support for using the ``target`` parameter was removed in phpMyAdmin 5.1.0.
|
||||
Use the ``route`` parameter instead.
|
||||
|
||||
.. _faq1_35:
|
||||
|
||||
1.35 Can I use HTTP authentication with Apache CGI?
|
||||
@ -1147,7 +1152,7 @@ Starting with 2.2.5, in the user management page, you can enter a
|
||||
wildcard database name for a user (for example "joe%"), and put the
|
||||
privileges you want. For example, adding ``SELECT, INSERT, UPDATE,
|
||||
DELETE, CREATE, DROP, INDEX, ALTER`` would let a user create/manage
|
||||
his/her database(s).
|
||||
their database(s).
|
||||
|
||||
.. _faq4_6:
|
||||
|
||||
@ -1306,7 +1311,7 @@ by the recent versions of the most browsers.
|
||||
5.12 Mac OS X Safari browser changes special characters to "?".
|
||||
---------------------------------------------------------------
|
||||
|
||||
This issue has been reported by a :term:`Mac OS X` user, who adds that Chimera,
|
||||
This issue has been reported by a :term:`macOS` user, who adds that Chimera,
|
||||
Netscape and Mozilla do not have this problem.
|
||||
|
||||
.. _faq5_13:
|
||||
@ -1404,7 +1409,7 @@ This is usually caused by web application firewall doing requests filtering. It
|
||||
tries to prevent SQL injection, however phpMyAdmin is tool designed to execute
|
||||
SQL queries, thus it makes it unusable.
|
||||
|
||||
Please whitelist phpMyAdmin scripts from the web application firewall settings
|
||||
Please allow phpMyAdmin scripts from the web application firewall settings
|
||||
or disable it completely for phpMyAdmin path.
|
||||
|
||||
Programs known to cause these kind of errors:
|
||||
@ -1642,7 +1647,7 @@ It means "average".
|
||||
any) will be included in backup.
|
||||
* "Enclose table and column names with backquotes" ensures that column
|
||||
and table names formed with special characters are protected.
|
||||
* "Add into comments" includes column comments, relations, and media (MIME)
|
||||
* "Add into comments" includes column comments, relations, and media
|
||||
types set in the pmadb in the dump as :term:`SQL` comments
|
||||
(*/\* xxx \*/*).
|
||||
|
||||
@ -1708,7 +1713,7 @@ user-input situation. Instead you have to initialize mimetypes using
|
||||
functions or empty mimetype definitions.
|
||||
|
||||
Plus, you have a whole overview of available mimetypes. Who knows all those
|
||||
mimetypes by heart so he/she can enter it at will?
|
||||
mimetypes by heart so they can enter it at will?
|
||||
|
||||
.. _faqbookmark:
|
||||
|
||||
@ -2230,7 +2235,7 @@ authentication to the Apache environment and it can be used in Apache
|
||||
logs. Currently there are two variables available:
|
||||
|
||||
``userID``
|
||||
User name of currently active user (he does not have to be logged in).
|
||||
User name of currently active user (they do not have to be logged in).
|
||||
``userStatus``
|
||||
Status of currently active user, one of ``ok`` (user is logged in),
|
||||
``mysql-denied`` (MySQL denied user login), ``allow-denied`` (user denied
|
||||
|
||||
103
doc/glossary.rst
103
doc/glossary.rst
@ -16,7 +16,7 @@ From Wikipedia, the free encyclopedia
|
||||
Access Control List
|
||||
|
||||
Blowfish
|
||||
a keyed, symmetric block cipher, designed in 1993 by Bruce Schneier.
|
||||
a keyed, symmetric block cipher, designed in 1993 by `Bruce Schneier <https://en.wikipedia.org/wiki/Bruce_Schneier>`_.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Blowfish_(cipher)>
|
||||
|
||||
@ -33,7 +33,7 @@ From Wikipedia, the free encyclopedia
|
||||
CGI
|
||||
Common Gateway Interface is an important World Wide Web technology that
|
||||
enables a client web browser to request data from a program executed on
|
||||
the Web server.
|
||||
the web server.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Common_Gateway_Interface>
|
||||
|
||||
@ -63,9 +63,9 @@ From Wikipedia, the free encyclopedia
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Comma-separated_values>
|
||||
|
||||
DB
|
||||
look at :term:`database`
|
||||
look at :term:`Database`
|
||||
|
||||
database
|
||||
Database
|
||||
an organized collection of data.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Database>
|
||||
@ -73,13 +73,13 @@ From Wikipedia, the free encyclopedia
|
||||
Engine
|
||||
look at :term:`Storage Engines`
|
||||
|
||||
extension
|
||||
PHP extension
|
||||
a PHP module that extends PHP with additional functionality.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Software_extension>
|
||||
|
||||
FAQ
|
||||
Frequently Asked Questions is a list of commonly asked question and there
|
||||
Frequently Asked Questions is a list of commonly asked question and their
|
||||
answers.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/FAQ>
|
||||
@ -89,7 +89,7 @@ From Wikipedia, the free encyclopedia
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Field_(computer_science)>
|
||||
|
||||
foreign key
|
||||
Foreign key
|
||||
a column or group of columns in a database row that points to a key column
|
||||
or group of columns forming a key of another database row in some
|
||||
(usually different) table.
|
||||
@ -105,14 +105,14 @@ From Wikipedia, the free encyclopedia
|
||||
look at :term:`GD`
|
||||
|
||||
GZip
|
||||
gzip is short for GNU zip, a GNU free software file compression program.
|
||||
GZip is short for GNU zip, a GNU free software file compression program.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Gzip>
|
||||
|
||||
host
|
||||
any machine connected to a computer network, a node that has a hostname.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Host>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Host_(network)>
|
||||
|
||||
hostname
|
||||
the unique name by which a network-attached device is known on a network.
|
||||
@ -120,21 +120,21 @@ From Wikipedia, the free encyclopedia
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Hostname>
|
||||
|
||||
HTTP
|
||||
HyperText Transfer Protocol is the primary method used to transfer or
|
||||
Hypertext Transfer Protocol is the primary method used to transfer or
|
||||
convey information on the World Wide Web.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/HyperText_Transfer_Protocol>
|
||||
|
||||
https
|
||||
HTTPS
|
||||
a :term:`HTTP`-connection with additional security measures.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Https:_URI_scheme>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/HTTPS>
|
||||
|
||||
IEC
|
||||
International Electrotechnical Commission
|
||||
|
||||
IIS
|
||||
Internet Information Services is a set of Internet-based services for
|
||||
Internet Information Services is a set of internet-based services for
|
||||
servers using Microsoft Windows.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Internet_Information_Services>
|
||||
@ -142,10 +142,10 @@ From Wikipedia, the free encyclopedia
|
||||
Index
|
||||
a feature that allows quick access to the rows in a table.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Index_(database)>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Database_index>
|
||||
|
||||
IP
|
||||
Internet Protocol is a data-oriented protocol used by source and
|
||||
"Internet Protocol" is a data-oriented protocol used by source and
|
||||
destination hosts for communicating data across a packet-switched
|
||||
internetwork.
|
||||
|
||||
@ -166,17 +166,20 @@ From Wikipedia, the free encyclopedia
|
||||
ISAPI
|
||||
Internet Server Application Programming Interface is the API of Internet Information Services (IIS).
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/ISAPI>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Internet_Server_Application_Programming_Interface>
|
||||
|
||||
ISP
|
||||
An Internet service provider is a business or organization that offers users
|
||||
access to the Internet and related services.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/ISP>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Internet_service_provider>
|
||||
|
||||
ISO
|
||||
International Standards Organization
|
||||
|
||||
.. seealso:: `ISO organization website <https://www.iso.org/about-us.html>`_
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/International_Organization_for_Standardization>
|
||||
|
||||
JPEG
|
||||
a most commonly used standard method of lossy compression for photographic images.
|
||||
|
||||
@ -189,19 +192,19 @@ From Wikipedia, the free encyclopedia
|
||||
look at :term:`Index`
|
||||
|
||||
LATEX
|
||||
a document preparation system for the TEX typesetting program.
|
||||
a document preparation system for the TeX typesetting program.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/LaTeX>
|
||||
|
||||
Mac
|
||||
Apple Macintosh is a line of personal computers is designed, developed, manufactured, and marketed by Apple Computer.
|
||||
Apple Macintosh is a line of personal computers designed, developed, manufactured, and marketed by Apple Inc.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Mac>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Macintosh>
|
||||
|
||||
Mac OS X
|
||||
macOS
|
||||
the operating system which is included with all currently shipping Apple Macintosh computers in the consumer and professional markets.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Mac_OS_X>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/MacOS>
|
||||
|
||||
mbstring
|
||||
The PHP `mbstring` functions provide support for languages represented by multi-byte character sets, most notably UTF-8.
|
||||
@ -223,7 +226,7 @@ From Wikipedia, the free encyclopedia
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/MIME>
|
||||
|
||||
module
|
||||
some sort of extension for the Apache Webserver.
|
||||
modular extension for the Apache HTTP Server httpd.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Apache_HTTP_Server>
|
||||
|
||||
@ -231,15 +234,18 @@ From Wikipedia, the free encyclopedia
|
||||
an Apache module implementing a Fast CGI interface; PHP can be run as a CGI module, FastCGI, or
|
||||
directly as an Apache module.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Mod_proxy>
|
||||
|
||||
MySQL
|
||||
a multithreaded, multi-user, SQL (Structured Query Language) Database Management System (DBMS).
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/MySQL>
|
||||
|
||||
mysqli
|
||||
MySQLi
|
||||
the improved MySQL client PHP extension.
|
||||
|
||||
.. seealso:: <https://www.php.net/manual/en/book.mysqli.php>
|
||||
.. seealso:: `PHP manual for MySQL Improved Extension <https://www.php.net/manual/en/book.mysqli.php>`_
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/MySQLi>
|
||||
|
||||
mysql
|
||||
the MySQL client PHP extension.
|
||||
@ -252,27 +258,30 @@ From Wikipedia, the free encyclopedia
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/OpenDocument>
|
||||
|
||||
OS X
|
||||
look at :term:`Mac OS X`.
|
||||
look at :term:`macOS`.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/OS_X>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/MacOS>
|
||||
|
||||
PDF
|
||||
Portable Document Format is a file format developed by Adobe Systems for
|
||||
representing two-dimensional documents in a device-independent and
|
||||
resolution-independent format.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Portable_Document_Format>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/PDF>
|
||||
|
||||
PEAR
|
||||
the PHP Extension and Application Repository.
|
||||
|
||||
.. seealso:: <https://pear.php.net/>
|
||||
.. seealso:: `PEAR website <https://pear.php.net/>`_
|
||||
.. seealso:: `Wikipedia page for PEAR <https://en.wikipedia.org/wiki/PEAR>`_
|
||||
|
||||
PCRE
|
||||
Perl Compatible Regular Expressions is the perl-compatible regular
|
||||
Perl-Compatible Regular Expressions is the Perl-compatible regular
|
||||
expression functions for PHP
|
||||
|
||||
.. seealso:: <https://www.php.net/pcre>
|
||||
.. seealso:: `PHP manual for Perl-Compatible Regular Expressions <https://www.php.net/pcre>`_
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions>
|
||||
|
||||
PHP
|
||||
short for "PHP: Hypertext Preprocessor", is an open-source, reflective
|
||||
@ -285,15 +294,15 @@ From Wikipedia, the free encyclopedia
|
||||
port
|
||||
a connection through which data is sent and received.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Port_(computing)>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Port_(computer_networking)>
|
||||
|
||||
primary key
|
||||
A primary key is an index over one or more fields in a table with
|
||||
unique values for every single row in this table. Every table should have
|
||||
a primary key for easier accessing/identifying data in this table. There
|
||||
a primary key for easier accessing/identifying data in this table. There
|
||||
can only be one primary key per table and it is named always **PRIMARY**.
|
||||
In fact, a primary key is just an :term:`unique key` with the name
|
||||
**PRIMARY**. If no primary key is defined MySQL will use first *unique
|
||||
**PRIMARY**. If no primary key is defined MySQL will use first *unique
|
||||
key* as primary key if there is one.
|
||||
|
||||
You can create the primary key when creating the table (in phpMyAdmin
|
||||
@ -335,7 +344,8 @@ From Wikipedia, the free encyclopedia
|
||||
Common table types are InnoDB and MyISAM, though many others exist and
|
||||
may be desirable in some situations.
|
||||
|
||||
.. seealso:: <https://dev.mysql.com/doc/refman/5.7/en/storage-engines.html>
|
||||
.. seealso:: `MySQL doc chapter about Alternative Storage Engines <https://dev.mysql.com/doc/refman/8.0/en/storage-engines.html>`_
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Database_engine>
|
||||
|
||||
socket
|
||||
a form of inter-process communication.
|
||||
@ -343,10 +353,10 @@ From Wikipedia, the free encyclopedia
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Unix_domain_socket>
|
||||
|
||||
SSL
|
||||
Secure Sockets Layer is a cryptographic protocol which provides secure
|
||||
communication on the Internet.
|
||||
Secure Sockets Layer, (now superseded by TLS) is a cryptographic protocol
|
||||
which provides secure communication on the Internet.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Secure_Sockets_Layer>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Transport_Layer_Security>
|
||||
|
||||
Stored procedure
|
||||
a subroutine available to applications accessing a relational database system
|
||||
@ -361,26 +371,27 @@ From Wikipedia, the free encyclopedia
|
||||
table
|
||||
a set of data elements (cells) that is organized, defined and stored as
|
||||
horizontal rows and vertical columns where each item can be uniquely
|
||||
identified by a label or key or by it's position in relation to other
|
||||
identified by a label or key or by its position in relation to other
|
||||
items.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Table_(database)>
|
||||
|
||||
tar
|
||||
a type of archive file format: the Tape ARchive format.
|
||||
a type of archive file format, from "Tape Archive".
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Tar_(file_format)>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Tar_(computing)>
|
||||
|
||||
TCP
|
||||
Transmission Control Protocol is one of the core protocols of the
|
||||
Internet protocol suite.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/TCP>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Internet_protocol_suite>
|
||||
|
||||
TCPDF
|
||||
PHP library to generate PDF files.
|
||||
|
||||
.. seealso:: <https://tcpdf.org/>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/TCPDF>
|
||||
|
||||
trigger
|
||||
a procedural code that is automatically executed in response to certain events on a particular table or view in a database
|
||||
@ -399,10 +410,10 @@ From Wikipedia, the free encyclopedia
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/URL>
|
||||
|
||||
Webserver
|
||||
A computer (program) that is responsible for accepting HTTP requests from clients and serving them Web pages.
|
||||
Web server
|
||||
A computer (program) that is responsible for accepting HTTP requests from clients and serving them web pages.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Webserver>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Web_server>
|
||||
|
||||
XML
|
||||
Extensible Markup Language is a W3C-recommended general-purpose markup
|
||||
@ -414,9 +425,9 @@ From Wikipedia, the free encyclopedia
|
||||
ZIP
|
||||
a popular data compression and archival format.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/ZIP_(file_format)>
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Zip_(file_format)>
|
||||
|
||||
Zlib
|
||||
an open-source, cross-platform data compression library by Jean-loup Gailly and Mark Adler.
|
||||
an open-source, cross-platform data compression library by `Jean-loup Gailly <https://en.wikipedia.org/wiki/Jean-Loup_Gailly>`_ and `Mark Adler <https://en.wikipedia.org/wiki/Mark_Adler>`_.
|
||||
|
||||
.. seealso:: <https://en.wikipedia.org/wiki/Zlib>
|
||||
|
||||
@ -324,10 +324,6 @@ negligible.
|
||||
This will significantly decrease filesize for large SQL dumps, increases the
|
||||
INSERT speed when imported, and is generally recommended.
|
||||
|
||||
.. seealso::
|
||||
|
||||
http://www.scriptalicious.com/blog/2009/04/complete-inserts-or-extended-inserts-in-phpmyadmin/
|
||||
|
||||
Texy!
|
||||
-----
|
||||
|
||||
|
||||
@ -54,13 +54,13 @@ table.
|
||||
Configurable menus and user groups
|
||||
----------------------------------
|
||||
|
||||
By enabling :config:option:`$cfg['Servers'][$i]['usergroups']` and
|
||||
By enabling :config:option:`$cfg['Servers'][$i]['users']` and
|
||||
:config:option:`$cfg['Servers'][$i]['usergroups']` you can customize what users
|
||||
will see in the phpMyAdmin navigation.
|
||||
|
||||
.. warning::
|
||||
|
||||
This feature only limits what a user sees, he is still able to use all the
|
||||
This feature only limits what a user sees, they are still able to use all the
|
||||
functions. So this can not be considered as a security limitation. Should
|
||||
you want to limit what users can do, use MySQL privileges to achieve that.
|
||||
|
||||
|
||||
@ -8,14 +8,6 @@ database server. It is still the system administrator's job to grant
|
||||
permissions on the MySQL databases properly. phpMyAdmin's :guilabel:`Users`
|
||||
page can be used for this.
|
||||
|
||||
.. warning::
|
||||
|
||||
:term:`Mac` users should note that if you are on a version before
|
||||
:term:`Mac OS X`, StuffIt unstuffs with :term:`Mac` formats. So you'll have
|
||||
to resave as in BBEdit to Unix style ALL phpMyAdmin scripts before
|
||||
uploading them to your server, as PHP seems not to like :term:`Mac`-style
|
||||
end of lines character ("``\r``").
|
||||
|
||||
Linux distributions
|
||||
+++++++++++++++++++
|
||||
|
||||
@ -28,7 +20,7 @@ distribution and you will automatically get security updates from your distribut
|
||||
Debian and Ubuntu
|
||||
-----------------
|
||||
|
||||
Debian's package repositories include a phpMyAdmin package, but be aware that
|
||||
Most Debian and Ubuntu versions include a phpMyAdmin package, but be aware that
|
||||
the configuration file is maintained in ``/etc/phpmyadmin`` and may differ in
|
||||
some ways from the official phpMyAdmin documentation. Specifically, it does:
|
||||
|
||||
@ -36,10 +28,13 @@ some ways from the official phpMyAdmin documentation. Specifically, it does:
|
||||
* Creating of :ref:`linked-tables` using dbconfig-common.
|
||||
* Securing setup script, see :ref:`debian-setup`.
|
||||
|
||||
More specific details about installing Debian or Ubuntu packages are available
|
||||
`in our wiki <https://github.com/phpmyadmin/phpmyadmin/wiki/DebianUbuntu>`_.
|
||||
|
||||
.. seealso::
|
||||
|
||||
More information can be found in `README.Debian <https://salsa.debian.org/phpmyadmin-team/phpmyadmin/blob/master/debian/README.Debian>`_
|
||||
(it is installed as :file:`/usr/share/doc/phmyadmin/README.Debian` with the package).
|
||||
More information can be found in `README.Debian <https://salsa.debian.org/phpmyadmin-team/phpmyadmin/blob/debian/latest/debian/README.Debian>`_
|
||||
(it is installed as :file:`/usr/share/doc/phpmyadmin/README.Debian` with the package).
|
||||
|
||||
OpenSUSE
|
||||
--------
|
||||
@ -95,7 +90,7 @@ In order to install from Git, you'll need a few supporting applications:
|
||||
|
||||
* `Git <https://git-scm.com/downloads>`_ to download the source, or you can download the most recent source directly from `Github <https://codeload.github.com/phpmyadmin/phpmyadmin/zip/master>`_
|
||||
* `Composer <https://getcomposer.org/download/>`__
|
||||
* `Node.js <https://nodejs.org/en/download/>`_ (version 8 or higher)
|
||||
* `Node.js <https://nodejs.org/en/download/>`_ (version 10 or higher)
|
||||
* `Yarn <https://classic.yarnpkg.com/en/docs/install>`_
|
||||
|
||||
You can clone current phpMyAdmin source from
|
||||
@ -484,6 +479,12 @@ configuration:
|
||||
- PMA_PASSWORD=
|
||||
- PMA_ABSOLUTE_URI=http://example.com/phpmyadmin/
|
||||
|
||||
IBM Cloud
|
||||
+++++++++
|
||||
|
||||
One of our users has created a helpful guide for installing phpMyAdmin on the
|
||||
`IBM Cloud platform <https://github.com/KissConsult/phpmyadmin_tutorial#readme>`_.
|
||||
|
||||
.. _quick_install:
|
||||
|
||||
Quick Install
|
||||
@ -1101,7 +1102,7 @@ are always ways to make your installation more secure:
|
||||
* If you are afraid of automated attacks, enabling Captcha by
|
||||
:config:option:`$cfg['CaptchaLoginPublicKey']` and
|
||||
:config:option:`$cfg['CaptchaLoginPrivateKey']` might be an option.
|
||||
* Failed login attemps are logged to syslog (if available, see
|
||||
* Failed login attempts are logged to syslog (if available, see
|
||||
:config:option:`$cfg['AuthLog']`). This can allow using a tool such as
|
||||
fail2ban to block brute-force attempts. Note that the log file used by syslog
|
||||
is not the same as the Apache error or access log files.
|
||||
|
||||
@ -27,7 +27,7 @@ To create a theme:
|
||||
* copy the files and directories from ``pmahomme`` to "your\_theme\_name"
|
||||
* edit the css-files in "your\_theme\_name/css"
|
||||
* put your new images in "your\_theme\_name/img"
|
||||
* edit :file:`layout.inc.php` in "your\_theme\_name"
|
||||
* edit :file:`_variables.scss` in "your\_theme\_name/scss"
|
||||
* edit :file:`theme.json` in "your\_theme\_name" to contain theme metadata (see below)
|
||||
* make a new screenshot of your theme and save it under
|
||||
"your\_theme\_name/screen.png"
|
||||
|
||||
@ -30,3 +30,20 @@ js/vendor
|
||||
vendor/
|
||||
The download kit includes various Composer packages as
|
||||
dependencies.
|
||||
|
||||
Specific files LICENSES
|
||||
-----------------------
|
||||
|
||||
phpMyAdmin distributed themes contain some content that is under licenses.
|
||||
|
||||
- `themes/*/img/b_rename.svg` Is a `Icons8 <https://thenounproject.com/Icons8/>`_, icon from the `Android L Icon Pack Collection <https://thenounproject.com/Icons8/collection/android-l-icon-pack/>`_. The icon `rename <https://thenounproject.com/term/rename/61456/>`_.
|
||||
- `themes/metro/img/user.svg` Is a IcoMoon the `user <https://github.com/Keyamoon/IcoMoon-Free/blob/master/SVG/114-user.svg>`_
|
||||
|
||||
CC BY 4.0 or GPL
|
||||
|
||||
Licenses for vendors
|
||||
--------------------
|
||||
|
||||
- `rename` from `Icons8` is under the `"public domain" <https://creativecommons.org/publicdomain/zero/1.0/>`_ (CC0 1.0) license.
|
||||
|
||||
- IcoMoon Free is under `"CC BY 4.0 or GPL" <https://github.com/Keyamoon/IcoMoon-Free/blob/master/License.txt>`_.
|
||||
|
||||
140
error_report.php
140
error_report.php
@ -1,140 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Handle error report submission
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\ErrorReport;
|
||||
use PhpMyAdmin\Message;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\UserPreferences;
|
||||
use PhpMyAdmin\Utils\HttpRequest;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
if (! isset($_POST['exception_type'])
|
||||
|| ! in_array($_POST['exception_type'], ['js', 'php'])
|
||||
) {
|
||||
die('Oops, something went wrong!!');
|
||||
}
|
||||
|
||||
$response = Response::getInstance();
|
||||
|
||||
/** @var ErrorReport $errorReport */
|
||||
$errorReport = $containerBuilder->get('error_report');
|
||||
|
||||
if (isset($_POST['send_error_report'])
|
||||
&& ($_POST['send_error_report'] == true
|
||||
|| $_POST['send_error_report'] == '1')
|
||||
) {
|
||||
if ($_POST['exception_type'] == 'php') {
|
||||
/**
|
||||
* Prevent infinite error submission.
|
||||
* Happens in case error submissions fails.
|
||||
* If reporting is done in some time interval,
|
||||
* just clear them & clear json data too.
|
||||
*/
|
||||
if (isset($_SESSION['prev_error_subm_time'])
|
||||
&& isset($_SESSION['error_subm_count'])
|
||||
&& $_SESSION['error_subm_count'] >= 3
|
||||
&& ($_SESSION['prev_error_subm_time'] - time()) <= 3000
|
||||
) {
|
||||
$_SESSION['error_subm_count'] = 0;
|
||||
$_SESSION['prev_errors'] = '';
|
||||
$response->addJSON('stopErrorReportLoop', '1');
|
||||
} else {
|
||||
$_SESSION['prev_error_subm_time'] = time();
|
||||
$_SESSION['error_subm_count'] = (
|
||||
isset($_SESSION['error_subm_count'])
|
||||
? ($_SESSION['error_subm_count'] + 1)
|
||||
: 0
|
||||
);
|
||||
}
|
||||
}
|
||||
$reportData = $errorReport->getData($_POST['exception_type']);
|
||||
// report if and only if there were 'actual' errors.
|
||||
if (count($reportData) > 0) {
|
||||
$server_response = $errorReport->send($reportData);
|
||||
if (! is_string($server_response)) {
|
||||
$success = false;
|
||||
} else {
|
||||
$decoded_response = json_decode($server_response, true);
|
||||
$success = ! empty($decoded_response) ?
|
||||
$decoded_response["success"] : false;
|
||||
}
|
||||
|
||||
/* Message to show to the user */
|
||||
if ($success) {
|
||||
if ((isset($_POST['automatic'])
|
||||
&& $_POST['automatic'] === "true")
|
||||
|| $GLOBALS['cfg']['SendErrorReports'] == 'always'
|
||||
) {
|
||||
$msg = __(
|
||||
'An error has been detected and an error report has been '
|
||||
. 'automatically submitted based on your settings.'
|
||||
);
|
||||
} else {
|
||||
$msg = __('Thank you for submitting this report.');
|
||||
}
|
||||
} else {
|
||||
$msg = __(
|
||||
'An error has been detected and an error report has been '
|
||||
. 'generated but failed to be sent.'
|
||||
)
|
||||
. ' '
|
||||
. __(
|
||||
'If you experience any '
|
||||
. 'problems please submit a bug report manually.'
|
||||
);
|
||||
}
|
||||
$msg .= ' ' . __('You may want to refresh the page.');
|
||||
|
||||
/* Create message object */
|
||||
if ($success) {
|
||||
$msg = Message::notice($msg);
|
||||
} else {
|
||||
$msg = Message::error($msg);
|
||||
}
|
||||
|
||||
/* Add message to response */
|
||||
if ($response->isAjax()) {
|
||||
if ($_POST['exception_type'] == 'js') {
|
||||
$response->addJSON('message', $msg);
|
||||
} else {
|
||||
$response->addJSON('errSubmitMsg', $msg);
|
||||
}
|
||||
} elseif ($_POST['exception_type'] == 'php') {
|
||||
$jsCode = 'Functions.ajaxShowMessage("<div class=\"error\">'
|
||||
. $msg
|
||||
. '</div>", false);';
|
||||
$response->getFooter()->getScripts()->addCode($jsCode);
|
||||
}
|
||||
|
||||
if ($_POST['exception_type'] == 'php') {
|
||||
// clear previous errors & save new ones.
|
||||
$GLOBALS['error_handler']->savePreviousErrors();
|
||||
}
|
||||
|
||||
/* Persist always send settings */
|
||||
if (isset($_POST['always_send'])
|
||||
&& $_POST['always_send'] === "true"
|
||||
) {
|
||||
$userPreferences = new UserPreferences();
|
||||
$userPreferences->persistOption("SendErrorReports", "always", "ask");
|
||||
}
|
||||
}
|
||||
} elseif (! empty($_POST['get_settings'])) {
|
||||
$response->addJSON('report_setting', $GLOBALS['cfg']['SendErrorReports']);
|
||||
} elseif ($_POST['exception_type'] == 'js') {
|
||||
$response->addHTML($errorReport->getForm());
|
||||
} else {
|
||||
// clear previous errors & save new ones.
|
||||
$GLOBALS['error_handler']->savePreviousErrors();
|
||||
}
|
||||
@ -4,18 +4,16 @@
|
||||
* many hosts that all have identical configuration otherwise. To add
|
||||
* a new host, just drop it into $hosts below. Contributed by
|
||||
* Matthew Hawkins.
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
* @subpackage Example
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$i = 0;
|
||||
$hosts = [
|
||||
"foo.example.com",
|
||||
"bar.example.com",
|
||||
"baz.example.com",
|
||||
"quux.example.com",
|
||||
'foo.example.com',
|
||||
'bar.example.com',
|
||||
'baz.example.com',
|
||||
'quux.example.com',
|
||||
];
|
||||
|
||||
foreach ($hosts as $host) {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Single signon for phpMyAdmin using OpenID
|
||||
*
|
||||
@ -11,10 +10,8 @@
|
||||
*
|
||||
* User first authenticates using OpenID and based on content of $AUTH_MAP
|
||||
* the login information is passed to phpMyAdmin in session data.
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
* @subpackage Example
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
if (false === @include_once 'OpenID/RelyingParty.php') {
|
||||
@ -34,6 +31,8 @@ $AUTH_MAP = [
|
||||
],
|
||||
];
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects,Squiz.Functions.GlobalFunction
|
||||
|
||||
/**
|
||||
* Simple function to show HTML page with given content.
|
||||
*
|
||||
@ -44,27 +43,25 @@ $AUTH_MAP = [
|
||||
function Show_page($contents)
|
||||
{
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
echo '<?xml version="1.0" encoding="utf-8"?>' , "\n";
|
||||
?>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<link rel="icon" href="../favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="../favicon.ico" type="image/x-icon">
|
||||
<meta charset="utf-8">
|
||||
<title>phpMyAdmin OpenID signon example</title>
|
||||
</head>
|
||||
<body>
|
||||
<?php
|
||||
if (isset($_SESSION) && isset($_SESSION['PMA_single_signon_error_message'])) {
|
||||
echo '<p class="error">' , $_SESSION['PMA_single_signon_message'] , '</p>';
|
||||
|
||||
echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
|
||||
echo '<!DOCTYPE HTML>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<link rel="icon" href="../favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="../favicon.ico" type="image/x-icon">
|
||||
<meta charset="utf-8">
|
||||
<title>phpMyAdmin OpenID signon example</title>
|
||||
</head>
|
||||
<body>';
|
||||
|
||||
if (isset($_SESSION['PMA_single_signon_error_message'])) {
|
||||
echo '<p class="error">' . $_SESSION['PMA_single_signon_message'] . '</p>';
|
||||
unset($_SESSION['PMA_single_signon_message']);
|
||||
}
|
||||
|
||||
echo $contents;
|
||||
?>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
echo '</body></html>';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -77,12 +74,13 @@ function Show_page($contents)
|
||||
function Die_error($e)
|
||||
{
|
||||
$contents = "<div class='relyingparty_results'>\n";
|
||||
$contents .= "<pre>" . htmlspecialchars($e->getMessage()) . "</pre>\n";
|
||||
$contents .= '<pre>' . htmlspecialchars($e->getMessage()) . "</pre>\n";
|
||||
$contents .= "</div class='relyingparty_results'>";
|
||||
Show_page($contents);
|
||||
exit;
|
||||
}
|
||||
|
||||
// phpcs:enable
|
||||
|
||||
/* Need to have cookie visible from parent directory */
|
||||
session_set_cookie_params(0, '/', '', $secure_cookie, true);
|
||||
@ -93,27 +91,25 @@ session_name($session_name);
|
||||
|
||||
// Determine realm and return_to
|
||||
$base = 'http';
|
||||
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
|
||||
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
|
||||
$base .= 's';
|
||||
}
|
||||
$base .= '://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'];
|
||||
|
||||
$realm = $base . '/';
|
||||
$returnTo = $base . dirname($_SERVER['PHP_SELF']);
|
||||
if ($returnTo[strlen($returnTo) - 1] != '/') {
|
||||
if ($returnTo[strlen($returnTo) - 1] !== '/') {
|
||||
$returnTo .= '/';
|
||||
}
|
||||
$returnTo .= 'openid.php';
|
||||
|
||||
/* Display form */
|
||||
if (! count($_GET) && ! count($_POST) || isset($_GET['phpMyAdmin'])) {
|
||||
if ((! count($_GET) && ! count($_POST)) || isset($_GET['phpMyAdmin'])) {
|
||||
/* Show simple form */
|
||||
$content = '<form action="openid.php" method="post">
|
||||
OpenID: <input type="text" name="identifier"><br>
|
||||
<input type="submit" name="start">
|
||||
</form>
|
||||
</body>
|
||||
</html>';
|
||||
</form>';
|
||||
Show_page($content);
|
||||
exit;
|
||||
}
|
||||
@ -130,7 +126,7 @@ if (isset($_POST['identifier']) && is_string($_POST['identifier'])) {
|
||||
/* Create OpenID object */
|
||||
try {
|
||||
$o = new OpenID_RelyingParty($returnTo, $realm, $identifier);
|
||||
} catch (Exception $e) {
|
||||
} catch (Throwable $e) {
|
||||
Die_error($e);
|
||||
}
|
||||
|
||||
@ -138,41 +134,41 @@ try {
|
||||
if (isset($_POST['start'])) {
|
||||
try {
|
||||
$authRequest = $o->prepare();
|
||||
} catch (Exception $e) {
|
||||
} catch (Throwable $e) {
|
||||
Die_error($e);
|
||||
}
|
||||
|
||||
$url = $authRequest->getAuthorizeURL();
|
||||
|
||||
header("Location: $url");
|
||||
header('Location: ' . $url);
|
||||
exit;
|
||||
} else {
|
||||
/* Grab query string */
|
||||
if (! count($_POST)) {
|
||||
list(, $queryString) = explode('?', $_SERVER['REQUEST_URI']);
|
||||
} else {
|
||||
// I hate php sometimes
|
||||
$queryString = file_get_contents('php://input');
|
||||
}
|
||||
|
||||
/* Check reply */
|
||||
try {
|
||||
$message = new OpenID_Message($queryString, OpenID_Message::FORMAT_HTTP);
|
||||
} catch (Exception $e) {
|
||||
Die_error($e);
|
||||
}
|
||||
|
||||
$id = $message->get('openid.claimed_id');
|
||||
|
||||
if (! empty($id) && isset($AUTH_MAP[$id])) {
|
||||
$_SESSION['PMA_single_signon_user'] = $AUTH_MAP[$id]['user'];
|
||||
$_SESSION['PMA_single_signon_password'] = $AUTH_MAP[$id]['password'];
|
||||
$_SESSION['PMA_single_signon_HMAC_secret'] = hash('sha1', uniqid(strval(rand()), true));
|
||||
session_write_close();
|
||||
/* Redirect to phpMyAdmin (should use absolute URL here!) */
|
||||
header('Location: ../index.php');
|
||||
} else {
|
||||
Show_page('<p>User not allowed!</p>');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Grab query string */
|
||||
if (! count($_POST)) {
|
||||
[, $queryString] = explode('?', $_SERVER['REQUEST_URI']);
|
||||
} else {
|
||||
// I hate php sometimes
|
||||
$queryString = file_get_contents('php://input');
|
||||
}
|
||||
|
||||
/* Check reply */
|
||||
try {
|
||||
$message = new OpenID_Message($queryString, OpenID_Message::FORMAT_HTTP);
|
||||
} catch (Throwable $e) {
|
||||
Die_error($e);
|
||||
}
|
||||
|
||||
$id = $message->get('openid.claimed_id');
|
||||
|
||||
if (empty($id) || ! isset($AUTH_MAP[$id])) {
|
||||
Show_page('<p>User not allowed!</p>');
|
||||
exit;
|
||||
}
|
||||
|
||||
$_SESSION['PMA_single_signon_user'] = $AUTH_MAP[$id]['user'];
|
||||
$_SESSION['PMA_single_signon_password'] = $AUTH_MAP[$id]['password'];
|
||||
$_SESSION['PMA_single_signon_HMAC_secret'] = hash('sha1', uniqid(strval(rand()), true));
|
||||
session_write_close();
|
||||
/* Redirect to phpMyAdmin (should use absolute URL here!) */
|
||||
header('Location: ../index.php');
|
||||
|
||||
@ -1,17 +1,16 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Single signon for phpMyAdmin
|
||||
*
|
||||
* This is just example how to use script based single signon with
|
||||
* phpMyAdmin, it is not intended to be perfect code and look, only
|
||||
* shows how you can integrate this functionality in your application.
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
* @subpackage Example
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// phpcs:disable Squiz.Functions.GlobalFunction
|
||||
|
||||
/**
|
||||
* This function returns username and password.
|
||||
*
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Single signon for phpMyAdmin
|
||||
*
|
||||
* This is just example how to use session based single signon with
|
||||
* phpMyAdmin, it is not intended to be perfect code and look, only
|
||||
* shows how you can integrate this functionality in your application.
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
* @subpackage Example
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/* Use cookies for session */
|
||||
@ -43,35 +40,33 @@ if (isset($_POST['user'])) {
|
||||
} else {
|
||||
/* Show simple form */
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
echo '<?xml version="1.0" encoding="utf-8"?>' , "\n";
|
||||
?>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<link rel="icon" href="../favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="../favicon.ico" type="image/x-icon">
|
||||
<meta charset="utf-8">
|
||||
<title>phpMyAdmin single signon example</title>
|
||||
</head>
|
||||
<body>
|
||||
<?php
|
||||
|
||||
echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
|
||||
echo '<!DOCTYPE HTML>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<link rel="icon" href="../favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="../favicon.ico" type="image/x-icon">
|
||||
<meta charset="utf-8">
|
||||
<title>phpMyAdmin single signon example</title>
|
||||
</head>
|
||||
<body>';
|
||||
|
||||
if (isset($_SESSION['PMA_single_signon_error_message'])) {
|
||||
echo '<p class="error">';
|
||||
echo $_SESSION['PMA_single_signon_error_message'];
|
||||
echo '</p>';
|
||||
}
|
||||
?>
|
||||
<form action="signon.php" method="post">
|
||||
Username: <input type="text" name="user"><br>
|
||||
Password: <input type="password" name="password"><br>
|
||||
Host: (will use the one from config.inc.php by default)
|
||||
<input type="text" name="host"><br>
|
||||
Port: (will use the one from config.inc.php by default)
|
||||
<input type="text" name="port"><br>
|
||||
<input type="submit">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
|
||||
echo '<form action="signon.php" method="post">
|
||||
Username: <input type="text" name="user" autocomplete="username"><br>
|
||||
Password: <input type="password" name="password" autocomplete="current-password"><br>
|
||||
Host: (will use the one from config.inc.php by default)
|
||||
<input type="text" name="host"><br>
|
||||
Port: (will use the one from config.inc.php by default)
|
||||
<input type="text" name="port"><br>
|
||||
<input type="submit">
|
||||
</form>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
?>
|
||||
|
||||
650
export.php
650
export.php
@ -1,650 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Main export handling code
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Core;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Encoding;
|
||||
use PhpMyAdmin\Export;
|
||||
use PhpMyAdmin\Plugins;
|
||||
use PhpMyAdmin\Plugins\ExportPlugin;
|
||||
use PhpMyAdmin\Relation;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Sanitize;
|
||||
use PhpMyAdmin\SqlParser\Parser;
|
||||
use PhpMyAdmin\SqlParser\Statements\SelectStatement;
|
||||
use PhpMyAdmin\SqlParser\Utils\Misc;
|
||||
use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
global $db, $sql_query;
|
||||
|
||||
include_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
$header = $response->getHeader();
|
||||
$scripts = $header->getScripts();
|
||||
$scripts->addFile('export_output.js');
|
||||
|
||||
/** @var Export $export */
|
||||
$export = $containerBuilder->get('export');
|
||||
|
||||
//check if it's the GET request to check export time out
|
||||
if (isset($_GET['check_time_out'])) {
|
||||
if (isset($_SESSION['pma_export_error'])) {
|
||||
$err = $_SESSION['pma_export_error'];
|
||||
unset($_SESSION['pma_export_error']);
|
||||
echo "timeout";
|
||||
} else {
|
||||
echo "success";
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets globals from $_POST
|
||||
*
|
||||
* - Please keep the parameters in order of their appearance in the form
|
||||
* - Some of these parameters are not used, as the code below directly
|
||||
* verifies from the superglobal $_POST or $_REQUEST
|
||||
* TODO: this should be removed to avoid passing user input to GLOBALS
|
||||
* without checking
|
||||
*/
|
||||
$post_params = [
|
||||
'db',
|
||||
'table',
|
||||
'what',
|
||||
'single_table',
|
||||
'export_type',
|
||||
'export_method',
|
||||
'quick_or_custom',
|
||||
'db_select',
|
||||
'table_select',
|
||||
'table_structure',
|
||||
'table_data',
|
||||
'limit_to',
|
||||
'limit_from',
|
||||
'allrows',
|
||||
'lock_tables',
|
||||
'output_format',
|
||||
'filename_template',
|
||||
'maxsize',
|
||||
'remember_template',
|
||||
'charset',
|
||||
'compression',
|
||||
'as_separate_files',
|
||||
'knjenc',
|
||||
'xkana',
|
||||
'htmlword_structure_or_data',
|
||||
'htmlword_null',
|
||||
'htmlword_columns',
|
||||
'mediawiki_headers',
|
||||
'mediawiki_structure_or_data',
|
||||
'mediawiki_caption',
|
||||
'pdf_structure_or_data',
|
||||
'odt_structure_or_data',
|
||||
'odt_relation',
|
||||
'odt_comments',
|
||||
'odt_mime',
|
||||
'odt_columns',
|
||||
'odt_null',
|
||||
'codegen_structure_or_data',
|
||||
'codegen_format',
|
||||
'excel_null',
|
||||
'excel_removeCRLF',
|
||||
'excel_columns',
|
||||
'excel_edition',
|
||||
'excel_structure_or_data',
|
||||
'yaml_structure_or_data',
|
||||
'ods_null',
|
||||
'ods_structure_or_data',
|
||||
'ods_columns',
|
||||
'json_structure_or_data',
|
||||
'json_pretty_print',
|
||||
'json_unicode',
|
||||
'xml_structure_or_data',
|
||||
'xml_export_events',
|
||||
'xml_export_functions',
|
||||
'xml_export_procedures',
|
||||
'xml_export_tables',
|
||||
'xml_export_triggers',
|
||||
'xml_export_views',
|
||||
'xml_export_contents',
|
||||
'texytext_structure_or_data',
|
||||
'texytext_columns',
|
||||
'texytext_null',
|
||||
'phparray_structure_or_data',
|
||||
'sql_include_comments',
|
||||
'sql_header_comment',
|
||||
'sql_dates',
|
||||
'sql_relation',
|
||||
'sql_mime',
|
||||
'sql_use_transaction',
|
||||
'sql_disable_fk',
|
||||
'sql_compatibility',
|
||||
'sql_structure_or_data',
|
||||
'sql_create_database',
|
||||
'sql_drop_table',
|
||||
'sql_procedure_function',
|
||||
'sql_create_table',
|
||||
'sql_create_view',
|
||||
'sql_create_trigger',
|
||||
'sql_view_current_user',
|
||||
'sql_if_not_exists',
|
||||
'sql_or_replace_view',
|
||||
'sql_auto_increment',
|
||||
'sql_backquotes',
|
||||
'sql_truncate',
|
||||
'sql_delayed',
|
||||
'sql_ignore',
|
||||
'sql_type',
|
||||
'sql_insert_syntax',
|
||||
'sql_max_query_size',
|
||||
'sql_hex_for_binary',
|
||||
'sql_utc_time',
|
||||
'sql_drop_database',
|
||||
'sql_views_as_tables',
|
||||
'sql_metadata',
|
||||
'csv_separator',
|
||||
'csv_enclosed',
|
||||
'csv_escaped',
|
||||
'csv_terminated',
|
||||
'csv_null',
|
||||
'csv_removeCRLF',
|
||||
'csv_columns',
|
||||
'csv_structure_or_data',
|
||||
// csv_replace should have been here but we use it directly from $_POST
|
||||
'latex_caption',
|
||||
'latex_structure_or_data',
|
||||
'latex_structure_caption',
|
||||
'latex_structure_continued_caption',
|
||||
'latex_structure_label',
|
||||
'latex_relation',
|
||||
'latex_comments',
|
||||
'latex_mime',
|
||||
'latex_columns',
|
||||
'latex_data_caption',
|
||||
'latex_data_continued_caption',
|
||||
'latex_data_label',
|
||||
'latex_null',
|
||||
'aliases',
|
||||
];
|
||||
|
||||
foreach ($post_params as $one_post_param) {
|
||||
if (isset($_POST[$one_post_param])) {
|
||||
$GLOBALS[$one_post_param] = $_POST[$one_post_param];
|
||||
}
|
||||
}
|
||||
|
||||
$table = $GLOBALS['table'];
|
||||
|
||||
PhpMyAdmin\Util::checkParameters(['what', 'export_type']);
|
||||
|
||||
// sanitize this parameter which will be used below in a file inclusion
|
||||
$what = Core::securePath($_POST['what']);
|
||||
|
||||
// export class instance, not array of properties, as before
|
||||
/** @var ExportPlugin $export_plugin */
|
||||
$export_plugin = Plugins::getPlugin(
|
||||
"export",
|
||||
$what,
|
||||
'libraries/classes/Plugins/Export/',
|
||||
[
|
||||
'export_type' => $export_type,
|
||||
'single_table' => isset($single_table),
|
||||
]
|
||||
);
|
||||
|
||||
// Check export type
|
||||
if (empty($export_plugin)) {
|
||||
Core::fatalError(__('Bad type!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* valid compression methods
|
||||
*/
|
||||
$compression_methods = [];
|
||||
if ($GLOBALS['cfg']['ZipDump'] && function_exists('gzcompress')) {
|
||||
$compression_methods[] = 'zip';
|
||||
}
|
||||
if ($GLOBALS['cfg']['GZipDump'] && function_exists('gzencode')) {
|
||||
$compression_methods[] = 'gzip';
|
||||
}
|
||||
|
||||
/**
|
||||
* init and variable checking
|
||||
*/
|
||||
$compression = '';
|
||||
$onserver = false;
|
||||
$save_on_server = false;
|
||||
$buffer_needed = false;
|
||||
$back_button = '';
|
||||
$refreshButton = '';
|
||||
$save_filename = '';
|
||||
$file_handle = '';
|
||||
$err_url = '';
|
||||
$filename = '';
|
||||
$separate_files = '';
|
||||
|
||||
// Is it a quick or custom export?
|
||||
if (isset($_POST['quick_or_custom'])
|
||||
&& $_POST['quick_or_custom'] == 'quick'
|
||||
) {
|
||||
$quick_export = true;
|
||||
} else {
|
||||
$quick_export = false;
|
||||
}
|
||||
|
||||
if ($_POST['output_format'] == 'astext') {
|
||||
$asfile = false;
|
||||
} else {
|
||||
$asfile = true;
|
||||
if (isset($_POST['as_separate_files'])
|
||||
&& ! empty($_POST['as_separate_files'])
|
||||
) {
|
||||
if (isset($_POST['compression'])
|
||||
&& ! empty($_POST['compression'])
|
||||
&& $_POST['compression'] == 'zip'
|
||||
) {
|
||||
$separate_files = $_POST['as_separate_files'];
|
||||
}
|
||||
}
|
||||
if (in_array($_POST['compression'], $compression_methods)) {
|
||||
$compression = $_POST['compression'];
|
||||
$buffer_needed = true;
|
||||
}
|
||||
if (($quick_export && ! empty($_POST['quick_export_onserver']))
|
||||
|| (! $quick_export && ! empty($_POST['onserver']))
|
||||
) {
|
||||
if ($quick_export) {
|
||||
$onserver = $_POST['quick_export_onserver'];
|
||||
} else {
|
||||
$onserver = $_POST['onserver'];
|
||||
}
|
||||
// Will we save dump on server?
|
||||
$save_on_server = ! empty($cfg['SaveDir']) && $onserver;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we are sending the export file (as opposed to just displaying it
|
||||
* as text), we have to bypass the usual PhpMyAdmin\Response mechanism
|
||||
*/
|
||||
if (isset($_POST['output_format']) && $_POST['output_format'] == 'sendit' && ! $save_on_server) {
|
||||
$response->disable();
|
||||
//Disable all active buffers (see: ob_get_status(true) at this point)
|
||||
do {
|
||||
if (ob_get_length() > 0 || ob_get_level() > 0) {
|
||||
$hasBuffer = ob_end_clean();
|
||||
} else {
|
||||
$hasBuffer = false;
|
||||
}
|
||||
} while ($hasBuffer);
|
||||
}
|
||||
|
||||
$tables = [];
|
||||
// Generate error url and check for needed variables
|
||||
if ($export_type == 'server') {
|
||||
$err_url = 'server_export.php' . Url::getCommon();
|
||||
} elseif ($export_type == 'database' && strlen($db) > 0) {
|
||||
$err_url = 'db_export.php' . Url::getCommon(['db' => $db]);
|
||||
// Check if we have something to export
|
||||
if (isset($table_select)) {
|
||||
$tables = $table_select;
|
||||
} else {
|
||||
$tables = [];
|
||||
}
|
||||
} elseif ($export_type == 'table' && strlen($db) > 0 && strlen($table) > 0) {
|
||||
$err_url = 'tbl_export.php' . Url::getCommon(
|
||||
[
|
||||
'db' => $db,
|
||||
'table' => $table,
|
||||
]
|
||||
);
|
||||
} else {
|
||||
Core::fatalError(__('Bad parameters!'));
|
||||
}
|
||||
|
||||
// Merge SQL Query aliases with Export aliases from
|
||||
// export page, Export page aliases are given more
|
||||
// preference over SQL Query aliases.
|
||||
$parser = new Parser($sql_query);
|
||||
$aliases = [];
|
||||
if (! empty($parser->statements[0])
|
||||
&& ($parser->statements[0] instanceof SelectStatement)
|
||||
) {
|
||||
$aliases = Misc::getAliases($parser->statements[0], $db);
|
||||
}
|
||||
if (! empty($_POST['aliases'])) {
|
||||
$aliases = $export->mergeAliases($aliases, $_POST['aliases']);
|
||||
$_SESSION['tmpval']['aliases'] = $_POST['aliases'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase time limit for script execution and initializes some variables
|
||||
*/
|
||||
Util::setTimeLimit();
|
||||
if (! empty($cfg['MemoryLimit'])) {
|
||||
ini_set('memory_limit', $cfg['MemoryLimit']);
|
||||
}
|
||||
register_shutdown_function([$export, 'shutdown']);
|
||||
// Start with empty buffer
|
||||
$dump_buffer = '';
|
||||
$dump_buffer_len = 0;
|
||||
|
||||
// Array of dump_buffers - used in separate file exports
|
||||
$dump_buffer_objects = [];
|
||||
|
||||
// We send fake headers to avoid browser timeout when buffering
|
||||
$time_start = time();
|
||||
|
||||
// Defines the default <CR><LF> format.
|
||||
// For SQL always use \n as MySQL wants this on all platforms.
|
||||
if ($what == 'sql') {
|
||||
$crlf = "\n";
|
||||
} else {
|
||||
$crlf = PHP_EOL;
|
||||
}
|
||||
|
||||
$output_kanji_conversion = Encoding::canConvertKanji();
|
||||
|
||||
// Do we need to convert charset?
|
||||
$output_charset_conversion = $asfile
|
||||
&& Encoding::isSupported()
|
||||
&& isset($charset) && $charset != 'utf-8';
|
||||
|
||||
// Use on the fly compression?
|
||||
$GLOBALS['onfly_compression'] = $GLOBALS['cfg']['CompressOnFly']
|
||||
&& $compression == 'gzip';
|
||||
if ($GLOBALS['onfly_compression']) {
|
||||
$GLOBALS['memory_limit'] = $export->getMemoryLimit();
|
||||
}
|
||||
|
||||
// Generate filename and mime type if needed
|
||||
if ($asfile) {
|
||||
if (empty($remember_template)) {
|
||||
$remember_template = '';
|
||||
}
|
||||
list($filename, $mime_type) = $export->getFilenameAndMimetype(
|
||||
$export_type,
|
||||
$remember_template,
|
||||
$export_plugin,
|
||||
$compression,
|
||||
$filename_template
|
||||
);
|
||||
} else {
|
||||
$mime_type = '';
|
||||
}
|
||||
|
||||
// Open file on server if needed
|
||||
if ($save_on_server) {
|
||||
list($save_filename, $message, $file_handle) = $export->openFile(
|
||||
$filename,
|
||||
$quick_export
|
||||
);
|
||||
|
||||
// problem opening export file on server?
|
||||
if (! empty($message)) {
|
||||
$export->showPage($db, $table, $export_type);
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Send headers depending on whether the user chose to download a dump file
|
||||
* or not
|
||||
*/
|
||||
if ($asfile) {
|
||||
// Download
|
||||
// (avoid rewriting data containing HTML with anchors and forms;
|
||||
// this was reported to happen under Plesk)
|
||||
ini_set('url_rewriter.tags', '');
|
||||
$filename = Sanitize::sanitizeFilename($filename);
|
||||
|
||||
Core::downloadHeader($filename, $mime_type);
|
||||
} else {
|
||||
// HTML
|
||||
if ($export_type == 'database') {
|
||||
$num_tables = count($tables);
|
||||
if ($num_tables === 0) {
|
||||
$message = PhpMyAdmin\Message::error(
|
||||
__('No tables found in database.')
|
||||
);
|
||||
$active_page = 'db_export.php';
|
||||
include ROOT_PATH . 'db_export.php';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
list($html, $back_button, $refreshButton) = $export->getHtmlForDisplayedExportHeader(
|
||||
$export_type,
|
||||
$db,
|
||||
$table
|
||||
);
|
||||
echo $html;
|
||||
unset($html);
|
||||
} // end download
|
||||
}
|
||||
|
||||
/** @var Relation $relation */
|
||||
$relation = $containerBuilder->get('relation');
|
||||
|
||||
// Fake loop just to allow skip of remain of this code by break, I'd really
|
||||
// need exceptions here :-)
|
||||
do {
|
||||
// Re - initialize
|
||||
$dump_buffer = '';
|
||||
$dump_buffer_len = 0;
|
||||
|
||||
// Add possibly some comments to export
|
||||
if (! $export_plugin->exportHeader()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Will we need relation & co. setup?
|
||||
$do_relation = isset($GLOBALS[$what . '_relation']);
|
||||
$do_comments = isset($GLOBALS[$what . '_include_comments'])
|
||||
|| isset($GLOBALS[$what . '_comments']);
|
||||
$do_mime = isset($GLOBALS[$what . '_mime']);
|
||||
if ($do_relation || $do_comments || $do_mime) {
|
||||
$cfgRelation = $relation->getRelationsParam();
|
||||
}
|
||||
|
||||
// Include dates in export?
|
||||
$do_dates = isset($GLOBALS[$what . '_dates']);
|
||||
|
||||
$whatStrucOrData = $GLOBALS[$what . '_structure_or_data'];
|
||||
|
||||
/**
|
||||
* Builds the dump
|
||||
*/
|
||||
if ($export_type == 'server') {
|
||||
if (! isset($db_select)) {
|
||||
$db_select = '';
|
||||
}
|
||||
$export->exportServer(
|
||||
$db_select,
|
||||
$whatStrucOrData,
|
||||
$export_plugin,
|
||||
$crlf,
|
||||
$err_url,
|
||||
$export_type,
|
||||
$do_relation,
|
||||
$do_comments,
|
||||
$do_mime,
|
||||
$do_dates,
|
||||
$aliases,
|
||||
$separate_files
|
||||
);
|
||||
} elseif ($export_type == 'database') {
|
||||
if (! isset($table_structure) || ! is_array($table_structure)) {
|
||||
$table_structure = [];
|
||||
}
|
||||
if (! isset($table_data) || ! is_array($table_data)) {
|
||||
$table_data = [];
|
||||
}
|
||||
if (! empty($_POST['structure_or_data_forced'])) {
|
||||
$table_structure = $tables;
|
||||
$table_data = $tables;
|
||||
}
|
||||
if (isset($lock_tables)) {
|
||||
$export->lockTables($db, $tables, "READ");
|
||||
try {
|
||||
$export->exportDatabase(
|
||||
$db,
|
||||
$tables,
|
||||
$whatStrucOrData,
|
||||
$table_structure,
|
||||
$table_data,
|
||||
$export_plugin,
|
||||
$crlf,
|
||||
$err_url,
|
||||
$export_type,
|
||||
$do_relation,
|
||||
$do_comments,
|
||||
$do_mime,
|
||||
$do_dates,
|
||||
$aliases,
|
||||
$separate_files
|
||||
);
|
||||
} finally {
|
||||
$export->unlockTables();
|
||||
}
|
||||
} else {
|
||||
$export->exportDatabase(
|
||||
$db,
|
||||
$tables,
|
||||
$whatStrucOrData,
|
||||
$table_structure,
|
||||
$table_data,
|
||||
$export_plugin,
|
||||
$crlf,
|
||||
$err_url,
|
||||
$export_type,
|
||||
$do_relation,
|
||||
$do_comments,
|
||||
$do_mime,
|
||||
$do_dates,
|
||||
$aliases,
|
||||
$separate_files
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// We export just one table
|
||||
// $allrows comes from the form when "Dump all rows" has been selected
|
||||
if (! isset($allrows)) {
|
||||
$allrows = '';
|
||||
}
|
||||
if (! isset($limit_to)) {
|
||||
$limit_to = '0';
|
||||
}
|
||||
if (! isset($limit_from)) {
|
||||
$limit_from = '0';
|
||||
}
|
||||
if (isset($lock_tables)) {
|
||||
try {
|
||||
$export->lockTables($db, [$table], "READ");
|
||||
$export->exportTable(
|
||||
$db,
|
||||
$table,
|
||||
$whatStrucOrData,
|
||||
$export_plugin,
|
||||
$crlf,
|
||||
$err_url,
|
||||
$export_type,
|
||||
$do_relation,
|
||||
$do_comments,
|
||||
$do_mime,
|
||||
$do_dates,
|
||||
$allrows,
|
||||
$limit_to,
|
||||
$limit_from,
|
||||
$sql_query,
|
||||
$aliases
|
||||
);
|
||||
} finally {
|
||||
$export->unlockTables();
|
||||
}
|
||||
} else {
|
||||
$export->exportTable(
|
||||
$db,
|
||||
$table,
|
||||
$whatStrucOrData,
|
||||
$export_plugin,
|
||||
$crlf,
|
||||
$err_url,
|
||||
$export_type,
|
||||
$do_relation,
|
||||
$do_comments,
|
||||
$do_mime,
|
||||
$do_dates,
|
||||
$allrows,
|
||||
$limit_to,
|
||||
$limit_from,
|
||||
$sql_query,
|
||||
$aliases
|
||||
);
|
||||
}
|
||||
}
|
||||
if (! $export_plugin->exportFooter()) {
|
||||
break;
|
||||
}
|
||||
} while (false);
|
||||
// End of fake loop
|
||||
|
||||
if ($save_on_server && ! empty($message)) {
|
||||
$export->showPage($db, $table, $export_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the dump as a file...
|
||||
*/
|
||||
if (empty($asfile)) {
|
||||
echo $export->getHtmlForDisplayedExportFooter($back_button, $refreshButton);
|
||||
return;
|
||||
} // end if
|
||||
|
||||
// Convert the charset if required.
|
||||
if ($output_charset_conversion) {
|
||||
$dump_buffer = Encoding::convertString(
|
||||
'utf-8',
|
||||
$GLOBALS['charset'],
|
||||
$dump_buffer
|
||||
);
|
||||
}
|
||||
|
||||
// Compression needed?
|
||||
if ($compression) {
|
||||
if (! empty($separate_files)) {
|
||||
$dump_buffer = $export->compress(
|
||||
$dump_buffer_objects,
|
||||
$compression,
|
||||
$filename
|
||||
);
|
||||
} else {
|
||||
$dump_buffer = $export->compress($dump_buffer, $compression, $filename);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we saved on server, we have to close file now */
|
||||
if ($save_on_server) {
|
||||
$message = $export->closeFile(
|
||||
$file_handle,
|
||||
$dump_buffer,
|
||||
$save_filename
|
||||
);
|
||||
$export->showPage($db, $table, $export_type);
|
||||
} else {
|
||||
echo $dump_buffer;
|
||||
}
|
||||
@ -1,139 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Editor for Geometry data types.
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Core;
|
||||
use PhpMyAdmin\Gis\GisFactory;
|
||||
use PhpMyAdmin\Gis\GisVisualization;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Template;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Template $template */
|
||||
$template = $containerBuilder->get('template');
|
||||
|
||||
if (! isset($_POST['field'])) {
|
||||
Util::checkParameters(['field']);
|
||||
}
|
||||
|
||||
// Get data if any posted
|
||||
$gis_data = [];
|
||||
if (Core::isValid($_POST['gis_data'], 'array')) {
|
||||
$gis_data = $_POST['gis_data'];
|
||||
}
|
||||
|
||||
$gis_types = [
|
||||
'POINT',
|
||||
'MULTIPOINT',
|
||||
'LINESTRING',
|
||||
'MULTILINESTRING',
|
||||
'POLYGON',
|
||||
'MULTIPOLYGON',
|
||||
'GEOMETRYCOLLECTION',
|
||||
];
|
||||
|
||||
// Extract type from the initial call and make sure that it's a valid one.
|
||||
// Extract from field's values if available, if not use the column type passed.
|
||||
if (! isset($gis_data['gis_type'])) {
|
||||
if (isset($_POST['type']) && $_POST['type'] != '') {
|
||||
$gis_data['gis_type'] = mb_strtoupper($_POST['type']);
|
||||
}
|
||||
if (isset($_POST['value']) && trim($_POST['value']) != '') {
|
||||
$start = (substr($_POST['value'], 0, 1) == "'") ? 1 : 0;
|
||||
$gis_data['gis_type'] = mb_substr(
|
||||
$_POST['value'],
|
||||
$start,
|
||||
mb_strpos($_POST['value'], "(") - $start
|
||||
);
|
||||
}
|
||||
if (! isset($gis_data['gis_type'])
|
||||
|| (! in_array($gis_data['gis_type'], $gis_types))
|
||||
) {
|
||||
$gis_data['gis_type'] = $gis_types[0];
|
||||
}
|
||||
}
|
||||
$geom_type = $gis_data['gis_type'];
|
||||
|
||||
// Generate parameters from value passed.
|
||||
$gis_obj = GisFactory::factory($geom_type);
|
||||
if (isset($_POST['value'])) {
|
||||
$gis_data = array_merge(
|
||||
$gis_data,
|
||||
$gis_obj->generateParams($_POST['value'])
|
||||
);
|
||||
}
|
||||
|
||||
// Generate Well Known Text
|
||||
$srid = (isset($gis_data['srid']) && $gis_data['srid'] != '') ? $gis_data['srid'] : 0;
|
||||
$wkt = $gis_obj->generateWkt($gis_data, 0);
|
||||
$wkt_with_zero = $gis_obj->generateWkt($gis_data, 0, '0');
|
||||
$result = "'" . $wkt . "'," . $srid;
|
||||
|
||||
// Generate SVG based visualization
|
||||
$visualizationSettings = [
|
||||
'width' => 450,
|
||||
'height' => 300,
|
||||
'spatialColumn' => 'wkt',
|
||||
'mysqlVersion' => $GLOBALS['dbi']->getVersion(),
|
||||
'isMariaDB' => $GLOBALS['dbi']->isMariaDB(),
|
||||
];
|
||||
$data = [
|
||||
[
|
||||
'wkt' => $wkt_with_zero,
|
||||
'srid' => $srid,
|
||||
],
|
||||
];
|
||||
$visualization = GisVisualization::getByData($data, $visualizationSettings)
|
||||
->toImage('svg');
|
||||
|
||||
$open_layers = GisVisualization::getByData($data, $visualizationSettings)
|
||||
->asOl();
|
||||
|
||||
// If the call is to update the WKT and visualization make an AJAX response
|
||||
if (isset($_POST['generate']) && $_POST['generate'] == true) {
|
||||
$extra_data = [
|
||||
'result' => $result,
|
||||
'visualization' => $visualization,
|
||||
'openLayers' => $open_layers,
|
||||
];
|
||||
$response = Response::getInstance();
|
||||
$response->addJSON($extra_data);
|
||||
exit;
|
||||
}
|
||||
|
||||
$geom_count = 1;
|
||||
if ($geom_type == 'GEOMETRYCOLLECTION') {
|
||||
$geom_count = isset($gis_data[$geom_type]['geom_count'])
|
||||
? intval($gis_data[$geom_type]['geom_count']) : 1;
|
||||
if (isset($gis_data[$geom_type]['add_geom'])) {
|
||||
$geom_count++;
|
||||
}
|
||||
}
|
||||
|
||||
$templateOutput = $template->render('gis_data_editor_form', [
|
||||
'width' => $visualizationSettings['width'],
|
||||
'height' => $visualizationSettings['height'],
|
||||
'pma_theme_image' => $GLOBALS['pmaThemeImage'],
|
||||
'field' => $_POST['field'],
|
||||
'input_name' => $_POST['input_name'],
|
||||
'srid' => $srid,
|
||||
'visualization' => $visualization,
|
||||
'open_layers' => $open_layers,
|
||||
'gis_types' => $gis_types,
|
||||
'geom_type' => $geom_type,
|
||||
'geom_count' => $geom_count,
|
||||
'gis_data' => $gis_data,
|
||||
'result' => $result,
|
||||
]);
|
||||
Response::getInstance()->addJSON('gis_editor', $templateOutput);
|
||||
809
import.php
809
import.php
@ -1,809 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Core script for import, this is just the glue around all other stuff
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Bookmark;
|
||||
use PhpMyAdmin\Core;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Encoding;
|
||||
use PhpMyAdmin\File;
|
||||
use PhpMyAdmin\Import;
|
||||
use PhpMyAdmin\ParseAnalyze;
|
||||
use PhpMyAdmin\Plugins;
|
||||
use PhpMyAdmin\Plugins\ImportPlugin;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Sql;
|
||||
use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
/* Enable LOAD DATA LOCAL INFILE for LDI plugin */
|
||||
if (isset($_POST['format']) && $_POST['format'] == 'ldi') {
|
||||
define('PMA_ENABLE_LDI', 1);
|
||||
}
|
||||
|
||||
global $db, $pmaThemeImage, $table;
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
/** @var import $import */
|
||||
$import = $containerBuilder->get('import');
|
||||
|
||||
if (isset($_POST['show_as_php'])) {
|
||||
$GLOBALS['show_as_php'] = $_POST['show_as_php'];
|
||||
}
|
||||
|
||||
// If there is a request to 'Simulate DML'.
|
||||
if (isset($_POST['simulate_dml'])) {
|
||||
$import->handleSimulateDmlRequest();
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = new Sql();
|
||||
|
||||
// If it's a refresh console bookmarks request
|
||||
if (isset($_GET['console_bookmark_refresh'])) {
|
||||
$response->addJSON(
|
||||
'console_message_bookmark',
|
||||
PhpMyAdmin\Console::getBookmarkContent()
|
||||
);
|
||||
exit;
|
||||
}
|
||||
// If it's a console bookmark add request
|
||||
if (isset($_POST['console_bookmark_add'])) {
|
||||
if (isset($_POST['label']) && isset($_POST['db'])
|
||||
&& isset($_POST['bookmark_query']) && isset($_POST['shared'])
|
||||
) {
|
||||
$cfgBookmark = Bookmark::getParams($GLOBALS['cfg']['Server']['user']);
|
||||
$bookmarkFields = [
|
||||
'bkm_database' => $_POST['db'],
|
||||
'bkm_user' => $cfgBookmark['user'],
|
||||
'bkm_sql_query' => $_POST['bookmark_query'],
|
||||
'bkm_label' => $_POST['label'],
|
||||
];
|
||||
$isShared = ($_POST['shared'] == 'true' ? true : false);
|
||||
$bookmark = Bookmark::createBookmark(
|
||||
$dbi,
|
||||
$GLOBALS['cfg']['Server']['user'],
|
||||
$bookmarkFields,
|
||||
$isShared
|
||||
);
|
||||
if ($bookmark !== false && $bookmark->save()) {
|
||||
$response->addJSON('message', __('Succeeded'));
|
||||
$response->addJSON('data', $bookmarkFields);
|
||||
$response->addJSON('isShared', $isShared);
|
||||
} else {
|
||||
$response->addJSON('message', __('Failed'));
|
||||
}
|
||||
die();
|
||||
} else {
|
||||
$response->addJSON('message', __('Incomplete params'));
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
$format = '';
|
||||
|
||||
/**
|
||||
* Sets globals from $_POST
|
||||
*/
|
||||
$post_params = [
|
||||
'charset_of_file',
|
||||
'format',
|
||||
'import_type',
|
||||
'is_js_confirmed',
|
||||
'MAX_FILE_SIZE',
|
||||
'message_to_show',
|
||||
'noplugin',
|
||||
'skip_queries',
|
||||
'local_import_file',
|
||||
];
|
||||
|
||||
foreach ($post_params as $one_post_param) {
|
||||
if (isset($_POST[$one_post_param])) {
|
||||
$GLOBALS[$one_post_param] = $_POST[$one_post_param];
|
||||
}
|
||||
}
|
||||
|
||||
// reset import messages for ajax request
|
||||
$_SESSION['Import_message']['message'] = null;
|
||||
$_SESSION['Import_message']['go_back_url'] = null;
|
||||
// default values
|
||||
$GLOBALS['reload'] = false;
|
||||
|
||||
// Use to identify current cycle is executing
|
||||
// a multiquery statement or stored routine
|
||||
if (! isset($_SESSION['is_multi_query'])) {
|
||||
$_SESSION['is_multi_query'] = false;
|
||||
}
|
||||
|
||||
$ajax_reload = [];
|
||||
$import_text = '';
|
||||
// Are we just executing plain query or sql file?
|
||||
// (eg. non import, but query box/window run)
|
||||
if (! empty($sql_query)) {
|
||||
// apply values for parameters
|
||||
if (! empty($_POST['parameterized'])
|
||||
&& ! empty($_POST['parameters'])
|
||||
&& is_array($_POST['parameters'])
|
||||
) {
|
||||
$parameters = $_POST['parameters'];
|
||||
foreach ($parameters as $parameter => $replacement) {
|
||||
$quoted = preg_quote($parameter, '/');
|
||||
// making sure that :param does not apply values to :param1
|
||||
$sql_query = preg_replace(
|
||||
'/' . $quoted . '([^a-zA-Z0-9_])/',
|
||||
$dbi->escapeString($replacement) . '${1}',
|
||||
$sql_query
|
||||
);
|
||||
// for parameters the appear at the end of the string
|
||||
$sql_query = preg_replace(
|
||||
'/' . $quoted . '$/',
|
||||
$dbi->escapeString($replacement),
|
||||
$sql_query
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// run SQL query
|
||||
$import_text = $sql_query;
|
||||
$import_type = 'query';
|
||||
$format = 'sql';
|
||||
$_SESSION['sql_from_query_box'] = true;
|
||||
|
||||
// If there is a request to ROLLBACK when finished.
|
||||
if (isset($_POST['rollback_query'])) {
|
||||
$import->handleRollbackRequest($import_text);
|
||||
}
|
||||
|
||||
// refresh navigation and main panels
|
||||
if (preg_match('/^(DROP)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i', $sql_query)) {
|
||||
$GLOBALS['reload'] = true;
|
||||
$ajax_reload['reload'] = true;
|
||||
}
|
||||
|
||||
// refresh navigation panel only
|
||||
if (preg_match(
|
||||
'/^(CREATE|ALTER)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i',
|
||||
$sql_query
|
||||
)) {
|
||||
$ajax_reload['reload'] = true;
|
||||
}
|
||||
|
||||
// do a dynamic reload if table is RENAMED
|
||||
// (by sending the instruction to the AJAX response handler)
|
||||
if (preg_match(
|
||||
'/^RENAME\s+TABLE\s+(.*?)\s+TO\s+(.*?)($|;|\s)/i',
|
||||
$sql_query,
|
||||
$rename_table_names
|
||||
)) {
|
||||
$ajax_reload['reload'] = true;
|
||||
$ajax_reload['table_name'] = PhpMyAdmin\Util::unQuote(
|
||||
$rename_table_names[2]
|
||||
);
|
||||
}
|
||||
|
||||
$sql_query = '';
|
||||
} elseif (! empty($sql_file)) {
|
||||
// run uploaded SQL file
|
||||
$import_file = $sql_file;
|
||||
$import_type = 'queryfile';
|
||||
$format = 'sql';
|
||||
unset($sql_file);
|
||||
} elseif (! empty($_POST['id_bookmark'])) {
|
||||
// run bookmark
|
||||
$import_type = 'query';
|
||||
$format = 'sql';
|
||||
}
|
||||
|
||||
// If we didn't get any parameters, either user called this directly, or
|
||||
// upload limit has been reached, let's assume the second possibility.
|
||||
if ($_POST == [] && $_GET == []) {
|
||||
$message = PhpMyAdmin\Message::error(
|
||||
__(
|
||||
'You probably tried to upload a file that is too large. Please refer ' .
|
||||
'to %sdocumentation%s for a workaround for this limit.'
|
||||
)
|
||||
);
|
||||
$message->addParam('[doc@faq1-16]');
|
||||
$message->addParam('[/doc]');
|
||||
|
||||
// so we can obtain the message
|
||||
$_SESSION['Import_message']['message'] = $message->getDisplay();
|
||||
$_SESSION['Import_message']['go_back_url'] = $GLOBALS['goto'];
|
||||
|
||||
$response->setRequestStatus(false);
|
||||
$response->addJSON('message', $message);
|
||||
|
||||
exit; // the footer is displayed automatically
|
||||
}
|
||||
|
||||
// Add console message id to response output
|
||||
if (isset($_POST['console_message_id'])) {
|
||||
$response->addJSON('console_message_id', $_POST['console_message_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets globals from $_POST patterns, for import plugins
|
||||
* We only need to load the selected plugin
|
||||
*/
|
||||
|
||||
if (! in_array(
|
||||
$format,
|
||||
[
|
||||
'csv',
|
||||
'ldi',
|
||||
'mediawiki',
|
||||
'ods',
|
||||
'shp',
|
||||
'sql',
|
||||
'xml',
|
||||
]
|
||||
)
|
||||
) {
|
||||
// this should not happen for a normal user
|
||||
// but only during an attack
|
||||
Core::fatalError('Incorrect format parameter');
|
||||
}
|
||||
|
||||
$post_patterns = [
|
||||
'/^force_file_/',
|
||||
'/^' . $format . '_/',
|
||||
];
|
||||
|
||||
Core::setPostAsGlobal($post_patterns);
|
||||
|
||||
// Check needed parameters
|
||||
PhpMyAdmin\Util::checkParameters(['import_type', 'format']);
|
||||
|
||||
// We don't want anything special in format
|
||||
$format = Core::securePath($format);
|
||||
|
||||
if (strlen($table) > 0 && strlen($db) > 0) {
|
||||
$urlparams = [
|
||||
'db' => $db,
|
||||
'table' => $table,
|
||||
];
|
||||
} elseif (strlen($db) > 0) {
|
||||
$urlparams = ['db' => $db];
|
||||
} else {
|
||||
$urlparams = [];
|
||||
}
|
||||
|
||||
// Create error and goto url
|
||||
if ($import_type == 'table') {
|
||||
$goto = 'tbl_import.php';
|
||||
} elseif ($import_type == 'database') {
|
||||
$goto = 'db_import.php';
|
||||
} elseif ($import_type == 'server') {
|
||||
$goto = 'server_import.php';
|
||||
} elseif (empty($goto) || ! preg_match('@^(server|db|tbl)(_[a-z]*)*\.php$@i', $goto)) {
|
||||
if (strlen($table) > 0 && strlen($db) > 0) {
|
||||
$goto = 'tbl_structure.php';
|
||||
} elseif (strlen($db) > 0) {
|
||||
$goto = 'db_structure.php';
|
||||
} else {
|
||||
$goto = 'server_sql.php';
|
||||
}
|
||||
}
|
||||
$err_url = $goto . Url::getCommon($urlparams);
|
||||
$_SESSION['Import_message']['go_back_url'] = $err_url;
|
||||
// Avoid setting selflink to 'import.php'
|
||||
// problem similar to bug 4276
|
||||
if (basename($_SERVER['SCRIPT_NAME']) === 'import.php') {
|
||||
$_SERVER['SCRIPT_NAME'] = $goto;
|
||||
}
|
||||
|
||||
|
||||
if (strlen($db) > 0) {
|
||||
$dbi->selectDb($db);
|
||||
}
|
||||
|
||||
Util::setTimeLimit();
|
||||
if (! empty($cfg['MemoryLimit'])) {
|
||||
ini_set('memory_limit', $cfg['MemoryLimit']);
|
||||
}
|
||||
|
||||
$timestamp = time();
|
||||
if (isset($_POST['allow_interrupt'])) {
|
||||
$maximum_time = ini_get('max_execution_time');
|
||||
} else {
|
||||
$maximum_time = 0;
|
||||
}
|
||||
|
||||
// set default values
|
||||
$timeout_passed = false;
|
||||
$error = false;
|
||||
$read_multiply = 1;
|
||||
$finished = false;
|
||||
$offset = 0;
|
||||
$max_sql_len = 0;
|
||||
$file_to_unlink = '';
|
||||
$sql_query = '';
|
||||
$sql_query_disabled = false;
|
||||
$go_sql = false;
|
||||
$executed_queries = 0;
|
||||
$run_query = true;
|
||||
$charset_conversion = false;
|
||||
$reset_charset = false;
|
||||
$bookmark_created = false;
|
||||
$result = false;
|
||||
$msg = 'Sorry an unexpected error happened!';
|
||||
|
||||
// Bookmark Support: get a query back from bookmark if required
|
||||
if (! empty($_POST['id_bookmark'])) {
|
||||
$id_bookmark = (int) $_POST['id_bookmark'];
|
||||
switch ($_POST['action_bookmark']) {
|
||||
case 0: // bookmarked query that have to be run
|
||||
$bookmark = Bookmark::get(
|
||||
$dbi,
|
||||
$GLOBALS['cfg']['Server']['user'],
|
||||
$db,
|
||||
$id_bookmark,
|
||||
'id',
|
||||
isset($_POST['action_bookmark_all'])
|
||||
);
|
||||
|
||||
if (! empty($_POST['bookmark_variable'])) {
|
||||
$import_text = $bookmark->applyVariables(
|
||||
$_POST['bookmark_variable']
|
||||
);
|
||||
} else {
|
||||
$import_text = $bookmark->getQuery();
|
||||
}
|
||||
|
||||
// refresh navigation and main panels
|
||||
if (preg_match(
|
||||
'/^(DROP)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i',
|
||||
$import_text
|
||||
)) {
|
||||
$GLOBALS['reload'] = true;
|
||||
$ajax_reload['reload'] = true;
|
||||
}
|
||||
|
||||
// refresh navigation panel only
|
||||
if (preg_match(
|
||||
'/^(CREATE|ALTER)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i',
|
||||
$import_text
|
||||
)
|
||||
) {
|
||||
$ajax_reload['reload'] = true;
|
||||
}
|
||||
break;
|
||||
case 1: // bookmarked query that have to be displayed
|
||||
$bookmark = Bookmark::get(
|
||||
$dbi,
|
||||
$GLOBALS['cfg']['Server']['user'],
|
||||
$db,
|
||||
$id_bookmark
|
||||
);
|
||||
$import_text = $bookmark->getQuery();
|
||||
if ($response->isAjax()) {
|
||||
$message = PhpMyAdmin\Message::success(__('Showing bookmark'));
|
||||
$response->setRequestStatus($message->isSuccess());
|
||||
$response->addJSON('message', $message);
|
||||
$response->addJSON('sql_query', $import_text);
|
||||
$response->addJSON('action_bookmark', $_POST['action_bookmark']);
|
||||
exit;
|
||||
} else {
|
||||
$run_query = false;
|
||||
}
|
||||
break;
|
||||
case 2: // bookmarked query that have to be deleted
|
||||
$bookmark = Bookmark::get(
|
||||
$dbi,
|
||||
$GLOBALS['cfg']['Server']['user'],
|
||||
$db,
|
||||
$id_bookmark
|
||||
);
|
||||
if (! empty($bookmark)) {
|
||||
$bookmark->delete();
|
||||
if ($response->isAjax()) {
|
||||
$message = PhpMyAdmin\Message::success(
|
||||
__('The bookmark has been deleted.')
|
||||
);
|
||||
$response->setRequestStatus($message->isSuccess());
|
||||
$response->addJSON('message', $message);
|
||||
$response->addJSON('action_bookmark', $_POST['action_bookmark']);
|
||||
$response->addJSON('id_bookmark', $id_bookmark);
|
||||
exit;
|
||||
} else {
|
||||
$run_query = false;
|
||||
$error = true; // this is kind of hack to skip processing the query
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
} // end bookmarks reading
|
||||
|
||||
// Do no run query if we show PHP code
|
||||
if (isset($GLOBALS['show_as_php'])) {
|
||||
$run_query = false;
|
||||
$go_sql = true;
|
||||
}
|
||||
|
||||
// We can not read all at once, otherwise we can run out of memory
|
||||
$memory_limit = trim(ini_get('memory_limit'));
|
||||
// 2 MB as default
|
||||
if (empty($memory_limit)) {
|
||||
$memory_limit = 2 * 1024 * 1024;
|
||||
}
|
||||
// In case no memory limit we work on 10MB chunks
|
||||
if ($memory_limit == -1) {
|
||||
$memory_limit = 10 * 1024 * 1024;
|
||||
}
|
||||
|
||||
// Calculate value of the limit
|
||||
$memoryUnit = mb_strtolower(substr((string) $memory_limit, -1));
|
||||
if ('m' == $memoryUnit) {
|
||||
$memory_limit = (int) substr((string) $memory_limit, 0, -1) * 1024 * 1024;
|
||||
} elseif ('k' == $memoryUnit) {
|
||||
$memory_limit = (int) substr((string) $memory_limit, 0, -1) * 1024;
|
||||
} elseif ('g' == $memoryUnit) {
|
||||
$memory_limit = (int) substr((string) $memory_limit, 0, -1) * 1024 * 1024 * 1024;
|
||||
} else {
|
||||
$memory_limit = (int) $memory_limit;
|
||||
}
|
||||
|
||||
// Just to be sure, there might be lot of memory needed for uncompression
|
||||
$read_limit = $memory_limit / 8;
|
||||
|
||||
// handle filenames
|
||||
if (isset($_FILES['import_file'])) {
|
||||
$import_file = $_FILES['import_file']['tmp_name'];
|
||||
$import_file_name = $_FILES['import_file']['name'];
|
||||
}
|
||||
if (! empty($local_import_file) && ! empty($cfg['UploadDir'])) {
|
||||
// sanitize $local_import_file as it comes from a POST
|
||||
$local_import_file = Core::securePath($local_import_file);
|
||||
|
||||
$import_file = PhpMyAdmin\Util::userDir($cfg['UploadDir'])
|
||||
. $local_import_file;
|
||||
|
||||
/*
|
||||
* Do not allow symlinks to avoid security issues
|
||||
* (user can create symlink to file he can not access,
|
||||
* but phpMyAdmin can).
|
||||
*/
|
||||
if (@is_link($import_file)) {
|
||||
$import_file = 'none';
|
||||
}
|
||||
} elseif (empty($import_file) || ! is_uploaded_file($import_file)) {
|
||||
$import_file = 'none';
|
||||
}
|
||||
|
||||
// Do we have file to import?
|
||||
|
||||
if ($import_file != 'none' && ! $error) {
|
||||
/**
|
||||
* Handle file compression
|
||||
*/
|
||||
$import_handle = new File($import_file);
|
||||
$import_handle->checkUploadedFile();
|
||||
if ($import_handle->isError()) {
|
||||
$import->stop($import_handle->getError());
|
||||
}
|
||||
$import_handle->setDecompressContent(true);
|
||||
$import_handle->open();
|
||||
if ($import_handle->isError()) {
|
||||
$import->stop($import_handle->getError());
|
||||
}
|
||||
} elseif (! $error) {
|
||||
if (! isset($import_text) || empty($import_text)) {
|
||||
$message = PhpMyAdmin\Message::error(
|
||||
__(
|
||||
'No data was received to import. Either no file name was ' .
|
||||
'submitted, or the file size exceeded the maximum size permitted ' .
|
||||
'by your PHP configuration. See [doc@faq1-16]FAQ 1.16[/doc].'
|
||||
)
|
||||
);
|
||||
$import->stop($message);
|
||||
}
|
||||
}
|
||||
|
||||
// so we can obtain the message
|
||||
//$_SESSION['Import_message'] = $message->getDisplay();
|
||||
|
||||
// Convert the file's charset if necessary
|
||||
if (Encoding::isSupported() && isset($charset_of_file)) {
|
||||
if ($charset_of_file != 'utf-8') {
|
||||
$charset_conversion = true;
|
||||
}
|
||||
} elseif (isset($charset_of_file) && $charset_of_file != 'utf-8') {
|
||||
$dbi->query('SET NAMES \'' . $charset_of_file . '\'');
|
||||
// We can not show query in this case, it is in different charset
|
||||
$sql_query_disabled = true;
|
||||
$reset_charset = true;
|
||||
}
|
||||
|
||||
// Something to skip? (because timeout has passed)
|
||||
if (! $error && isset($_POST['skip'])) {
|
||||
$original_skip = $skip = intval($_POST['skip']);
|
||||
while ($skip > 0 && ! $finished) {
|
||||
$import->getNextChunk($skip < $read_limit ? $skip : $read_limit);
|
||||
// Disable read progressivity, otherwise we eat all memory!
|
||||
$read_multiply = 1;
|
||||
$skip -= $read_limit;
|
||||
}
|
||||
unset($skip);
|
||||
}
|
||||
|
||||
// This array contain the data like numberof valid sql queries in the statement
|
||||
// and complete valid sql statement (which affected for rows)
|
||||
$sql_data = [
|
||||
'valid_sql' => [],
|
||||
'valid_queries' => 0,
|
||||
];
|
||||
|
||||
if (! $error) {
|
||||
/**
|
||||
* @var ImportPlugin $import_plugin
|
||||
*/
|
||||
$import_plugin = Plugins::getPlugin(
|
||||
"import",
|
||||
$format,
|
||||
'libraries/classes/Plugins/Import/',
|
||||
$import_type
|
||||
);
|
||||
if ($import_plugin == null) {
|
||||
$message = PhpMyAdmin\Message::error(
|
||||
__('Could not load import plugins, please check your installation!')
|
||||
);
|
||||
$import->stop($message);
|
||||
} else {
|
||||
// Do the real import
|
||||
$default_fk_check = PhpMyAdmin\Util::handleDisableFKCheckInit();
|
||||
try {
|
||||
$import_plugin->doImport($sql_data);
|
||||
PhpMyAdmin\Util::handleDisableFKCheckCleanup($default_fk_check);
|
||||
} catch (Exception $e) {
|
||||
PhpMyAdmin\Util::handleDisableFKCheckCleanup($default_fk_check);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($import_handle)) {
|
||||
$import_handle->close();
|
||||
}
|
||||
|
||||
// Cleanup temporary file
|
||||
if ($file_to_unlink != '') {
|
||||
unlink($file_to_unlink);
|
||||
}
|
||||
|
||||
// Reset charset back, if we did some changes
|
||||
if ($reset_charset) {
|
||||
$dbi->query('SET CHARACTER SET ' . $GLOBALS['charset_connection']);
|
||||
$dbi->setCollation($collation_connection);
|
||||
}
|
||||
|
||||
// Show correct message
|
||||
if (! empty($id_bookmark) && $_POST['action_bookmark'] == 2) {
|
||||
$message = PhpMyAdmin\Message::success(__('The bookmark has been deleted.'));
|
||||
$display_query = $import_text;
|
||||
$error = false; // unset error marker, it was used just to skip processing
|
||||
} elseif (! empty($id_bookmark) && $_POST['action_bookmark'] == 1) {
|
||||
$message = PhpMyAdmin\Message::notice(__('Showing bookmark'));
|
||||
} elseif ($bookmark_created) {
|
||||
$special_message = '[br]' . sprintf(
|
||||
__('Bookmark %s has been created.'),
|
||||
htmlspecialchars($_POST['bkm_label'])
|
||||
);
|
||||
} elseif ($finished && ! $error) {
|
||||
// Do not display the query with message, we do it separately
|
||||
$display_query = ';';
|
||||
if ($import_type != 'query') {
|
||||
$message = PhpMyAdmin\Message::success(
|
||||
'<em>'
|
||||
. _ngettext(
|
||||
'Import has been successfully finished, %d query executed.',
|
||||
'Import has been successfully finished, %d queries executed.',
|
||||
$executed_queries
|
||||
)
|
||||
. '</em>'
|
||||
);
|
||||
$message->addParam($executed_queries);
|
||||
|
||||
if (! empty($import_notice)) {
|
||||
$message->addHtml($import_notice);
|
||||
}
|
||||
if (! empty($local_import_file)) {
|
||||
$message->addText('(' . $local_import_file . ')');
|
||||
} else {
|
||||
$message->addText('(' . $_FILES['import_file']['name'] . ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Did we hit timeout? Tell it user.
|
||||
if ($timeout_passed) {
|
||||
$urlparams['timeout_passed'] = '1';
|
||||
$urlparams['offset'] = $GLOBALS['offset'];
|
||||
if (isset($local_import_file)) {
|
||||
$urlparams['local_import_file'] = $local_import_file;
|
||||
}
|
||||
|
||||
$importUrl = $err_url = $goto . Url::getCommon($urlparams);
|
||||
|
||||
$message = PhpMyAdmin\Message::error(
|
||||
__(
|
||||
'Script timeout passed, if you want to finish import,'
|
||||
. ' please %sresubmit the same file%s and import will resume.'
|
||||
)
|
||||
);
|
||||
$message->addParamHtml('<a href="' . $importUrl . '">');
|
||||
$message->addParamHtml('</a>');
|
||||
|
||||
if ($offset == 0 || (isset($original_skip) && $original_skip == $offset)) {
|
||||
$message->addText(
|
||||
__(
|
||||
'However on last run no data has been parsed,'
|
||||
. ' this usually means phpMyAdmin won\'t be able to'
|
||||
. ' finish this import unless you increase php time limits.'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// if there is any message, copy it into $_SESSION as well,
|
||||
// so we can obtain it by AJAX call
|
||||
if (isset($message)) {
|
||||
$_SESSION['Import_message']['message'] = $message->getDisplay();
|
||||
}
|
||||
// Parse and analyze the query, for correct db and table name
|
||||
// in case of a query typed in the query window
|
||||
// (but if the query is too large, in case of an imported file, the parser
|
||||
// can choke on it so avoid parsing)
|
||||
$sqlLength = mb_strlen($sql_query);
|
||||
if ($sqlLength <= $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) {
|
||||
list(
|
||||
$analyzed_sql_results,
|
||||
$db,
|
||||
$table_from_sql
|
||||
) = ParseAnalyze::sqlQuery($sql_query, $db);
|
||||
// @todo: possibly refactor
|
||||
extract($analyzed_sql_results);
|
||||
|
||||
if ($table != $table_from_sql && ! empty($table_from_sql)) {
|
||||
$table = $table_from_sql;
|
||||
}
|
||||
}
|
||||
|
||||
// There was an error?
|
||||
if (isset($my_die)) {
|
||||
foreach ($my_die as $key => $die) {
|
||||
PhpMyAdmin\Util::mysqlDie(
|
||||
$die['error'],
|
||||
$die['sql'],
|
||||
false,
|
||||
$err_url,
|
||||
$error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($go_sql) {
|
||||
if (! empty($sql_data) && ($sql_data['valid_queries'] > 1)) {
|
||||
$_SESSION['is_multi_query'] = true;
|
||||
$sql_queries = $sql_data['valid_sql'];
|
||||
} else {
|
||||
$sql_queries = [$sql_query];
|
||||
}
|
||||
|
||||
$html_output = '';
|
||||
|
||||
foreach ($sql_queries as $sql_query) {
|
||||
// parse sql query
|
||||
list(
|
||||
$analyzed_sql_results,
|
||||
$db,
|
||||
$table_from_sql
|
||||
) = ParseAnalyze::sqlQuery($sql_query, $db);
|
||||
// @todo: possibly refactor
|
||||
extract($analyzed_sql_results);
|
||||
|
||||
// Check if User is allowed to issue a 'DROP DATABASE' Statement
|
||||
if ($sql->hasNoRightsToDropDatabase(
|
||||
$analyzed_sql_results,
|
||||
$cfg['AllowUserDropDatabase'],
|
||||
$dbi->isSuperuser()
|
||||
)) {
|
||||
PhpMyAdmin\Util::mysqlDie(
|
||||
__('"DROP DATABASE" statements are disabled.'),
|
||||
'',
|
||||
false,
|
||||
$_SESSION['Import_message']['go_back_url']
|
||||
);
|
||||
return;
|
||||
} // end if
|
||||
|
||||
if ($table != $table_from_sql && ! empty($table_from_sql)) {
|
||||
$table = $table_from_sql;
|
||||
}
|
||||
|
||||
$html_output .= $sql->executeQueryAndGetQueryResponse(
|
||||
$analyzed_sql_results, // analyzed_sql_results
|
||||
false, // is_gotofile
|
||||
$db, // db
|
||||
$table, // table
|
||||
null, // find_real_end
|
||||
null, // sql_query_for_bookmark - see below
|
||||
null, // extra_data
|
||||
null, // message_to_show
|
||||
null, // message
|
||||
null, // sql_data
|
||||
$goto, // goto
|
||||
$pmaThemeImage, // pmaThemeImage
|
||||
null, // disp_query
|
||||
null, // disp_message
|
||||
null, // query_type
|
||||
$sql_query, // sql_query
|
||||
null, // selectedTables
|
||||
null // complete_query
|
||||
);
|
||||
}
|
||||
|
||||
// sql_query_for_bookmark is not included in Sql::executeQueryAndGetQueryResponse
|
||||
// since only one bookmark has to be added for all the queries submitted through
|
||||
// the SQL tab
|
||||
if (! empty($_POST['bkm_label']) && ! empty($import_text)) {
|
||||
$cfgBookmark = Bookmark::getParams($GLOBALS['cfg']['Server']['user']);
|
||||
$sql->storeTheQueryAsBookmark(
|
||||
$db,
|
||||
$cfgBookmark['user'],
|
||||
$_POST['sql_query'],
|
||||
$_POST['bkm_label'],
|
||||
isset($_POST['bkm_replace'])
|
||||
);
|
||||
}
|
||||
|
||||
$response->addJSON('ajax_reload', $ajax_reload);
|
||||
$response->addHTML($html_output);
|
||||
exit;
|
||||
} elseif ($result) {
|
||||
// Save a Bookmark with more than one queries (if Bookmark label given).
|
||||
if (! empty($_POST['bkm_label']) && ! empty($import_text)) {
|
||||
$cfgBookmark = Bookmark::getParams($GLOBALS['cfg']['Server']['user']);
|
||||
$sql->storeTheQueryAsBookmark(
|
||||
$db,
|
||||
$cfgBookmark['user'],
|
||||
$_POST['sql_query'],
|
||||
$_POST['bkm_label'],
|
||||
isset($_POST['bkm_replace'])
|
||||
);
|
||||
}
|
||||
|
||||
$response->setRequestStatus(true);
|
||||
$response->addJSON('message', PhpMyAdmin\Message::success($msg));
|
||||
$response->addJSON(
|
||||
'sql_query',
|
||||
PhpMyAdmin\Util::getMessage($msg, $sql_query, 'success')
|
||||
);
|
||||
} elseif ($result === false) {
|
||||
$response->setRequestStatus(false);
|
||||
$response->addJSON('message', PhpMyAdmin\Message::error($msg));
|
||||
} else {
|
||||
$active_page = $goto;
|
||||
include ROOT_PATH . $goto;
|
||||
}
|
||||
|
||||
// If there is request for ROLLBACK in the end.
|
||||
if (isset($_POST['rollback_query'])) {
|
||||
$dbi->query('ROLLBACK');
|
||||
}
|
||||
@ -1,129 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Import progress bar backend
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Core;
|
||||
use PhpMyAdmin\Display\ImportAjax;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
/* PHP 5.4 stores upload progress data only in the default session.
|
||||
* After calling session_name(), we won't find the progress data anymore.
|
||||
*
|
||||
* https://bugs.php.net/bug.php?id=64075
|
||||
*
|
||||
* The bug should be somewhere in
|
||||
* https://github.com/php/php-src/blob/master/ext/session/session.c#L2342
|
||||
*
|
||||
* Until this is fixed, we need to load the default session to load the data,
|
||||
* export the upload progress information from there,
|
||||
* and re-import after switching to our session.
|
||||
*
|
||||
* However, since https://github.com/phpmyadmin/phpmyadmin/commit/063a2d99
|
||||
* we have deactivated this feature, so the corresponding code is now
|
||||
* commented out.
|
||||
*/
|
||||
|
||||
/*
|
||||
if (ini_get('session.upload_progress.enabled')) {
|
||||
|
||||
$sessionupload = array();
|
||||
define('UPLOAD_PREFIX', ini_get('session.upload_progress.prefix'));
|
||||
|
||||
session_start();
|
||||
foreach ($_SESSION as $key => $value) {
|
||||
// only copy session-prefixed data
|
||||
if (substr($key, 0, strlen(UPLOAD_PREFIX))
|
||||
== UPLOAD_PREFIX) {
|
||||
$sessionupload[$key] = $value;
|
||||
}
|
||||
}
|
||||
// PMA will kill all variables, so let's use a constant
|
||||
define('SESSIONUPLOAD', serialize($sessionupload));
|
||||
session_write_close();
|
||||
|
||||
// The cookie name is not good anymore since PR #15273
|
||||
session_name('phpMyAdmin');
|
||||
session_id($_COOKIE['phpMyAdmin']);
|
||||
}
|
||||
*/
|
||||
|
||||
define('PMA_MINIMUM_COMMON', 1);
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
list(
|
||||
$SESSION_KEY,
|
||||
$upload_id,
|
||||
$plugins
|
||||
) = ImportAjax::uploadProgressSetup();
|
||||
|
||||
/*
|
||||
if (defined('SESSIONUPLOAD')) {
|
||||
// write sessionupload back into the loaded PMA session
|
||||
|
||||
$sessionupload = unserialize(SESSIONUPLOAD);
|
||||
foreach ($sessionupload as $key => $value) {
|
||||
$_SESSION[$key] = $value;
|
||||
}
|
||||
|
||||
// remove session upload data that are not set anymore
|
||||
foreach ($_SESSION as $key => $value) {
|
||||
if (substr($key, 0, strlen(UPLOAD_PREFIX))
|
||||
== UPLOAD_PREFIX
|
||||
&& ! isset($sessionupload[$key])
|
||||
) {
|
||||
unset($_SESSION[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// $_GET["message"] is used for asking for an import message
|
||||
if (isset($_GET["message"]) && $_GET["message"]) {
|
||||
// AJAX requests can't be cached!
|
||||
Core::noCacheHeader();
|
||||
|
||||
header('Content-type: text/html');
|
||||
|
||||
// wait 0.3 sec before we check for $_SESSION variable,
|
||||
// which is set inside import.php
|
||||
usleep(300000);
|
||||
|
||||
$maximumTime = ini_get('max_execution_time');
|
||||
$timestamp = time();
|
||||
// wait until message is available
|
||||
while ($_SESSION['Import_message']['message'] == null) {
|
||||
// close session before sleeping
|
||||
session_write_close();
|
||||
// sleep
|
||||
usleep(250000); // 0.25 sec
|
||||
// reopen session
|
||||
session_start();
|
||||
|
||||
if ((time() - $timestamp) > $maximumTime) {
|
||||
$_SESSION['Import_message']['message'] = PhpMyAdmin\Message::error(
|
||||
__('Could not load the progress of the import.')
|
||||
)->getDisplay();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_SESSION['Import_message']['message'])) {
|
||||
echo $_SESSION['Import_message']['message'];
|
||||
}
|
||||
if (isset($_SESSION['Import_message']['go_back_url'])) {
|
||||
echo '<fieldset class="tblFooters">' , "\n";
|
||||
echo ' [ <a href="' , $_SESSION['Import_message']['go_back_url']
|
||||
. '">' , __('Back') , '</a> ]' , "\n";
|
||||
echo '</fieldset>' , "\n";
|
||||
}
|
||||
} else {
|
||||
ImportAjax::status($_GET["id"]);
|
||||
}
|
||||
116
index.php
116
index.php
@ -1,120 +1,18 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Main loader script
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Controllers\HomeController;
|
||||
use PhpMyAdmin\Core;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Util;
|
||||
use PhpMyAdmin\Routing;
|
||||
|
||||
if (! defined('ROOT_PATH')) {
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
// phpcs:enable
|
||||
}
|
||||
|
||||
global $server;
|
||||
global $route, $containerBuilder;
|
||||
|
||||
require_once ROOT_PATH . 'libraries/common.inc.php';
|
||||
|
||||
/**
|
||||
* pass variables to child pages
|
||||
*/
|
||||
$drops = [
|
||||
'lang',
|
||||
'server',
|
||||
'collation_connection',
|
||||
'db',
|
||||
'table',
|
||||
];
|
||||
foreach ($drops as $each_drop) {
|
||||
if (array_key_exists($each_drop, $_GET)) {
|
||||
unset($_GET[$each_drop]);
|
||||
}
|
||||
}
|
||||
unset($drops, $each_drop);
|
||||
|
||||
/**
|
||||
* Black list of all scripts to which front-end must submit data.
|
||||
* Such scripts must not be loaded on home page.
|
||||
*/
|
||||
$target_blacklist = [
|
||||
'import.php',
|
||||
'export.php',
|
||||
];
|
||||
|
||||
// If we have a valid target, let's load that script instead
|
||||
if (! empty($_REQUEST['target'])
|
||||
&& is_string($_REQUEST['target'])
|
||||
&& 0 !== strpos($_REQUEST['target'], "index")
|
||||
&& ! in_array($_REQUEST['target'], $target_blacklist)
|
||||
&& Core::checkPageValidity($_REQUEST['target'], [], true)
|
||||
) {
|
||||
include ROOT_PATH . $_REQUEST['target'];
|
||||
exit;
|
||||
}
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $containerBuilder->get(Response::class);
|
||||
|
||||
/** @var DatabaseInterface $dbi */
|
||||
$dbi = $containerBuilder->get(DatabaseInterface::class);
|
||||
|
||||
/** @var HomeController $controller */
|
||||
$controller = $containerBuilder->get(HomeController::class);
|
||||
|
||||
if (isset($_REQUEST['ajax_request']) && ! empty($_REQUEST['access_time'])) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['set_theme'])) {
|
||||
$controller->setTheme([
|
||||
'set_theme' => $_POST['set_theme'],
|
||||
]);
|
||||
|
||||
header('Location: index.php' . Url::getCommonRaw());
|
||||
} elseif (isset($_POST['collation_connection'])) {
|
||||
$controller->setCollationConnection([
|
||||
'collation_connection' => $_POST['collation_connection'],
|
||||
]);
|
||||
|
||||
header('Location: index.php' . Url::getCommonRaw());
|
||||
} elseif (! empty($_REQUEST['db'])) {
|
||||
// See FAQ 1.34
|
||||
$page = null;
|
||||
if (! empty($_REQUEST['table'])) {
|
||||
$page = Util::getScriptNameForOption(
|
||||
$GLOBALS['cfg']['DefaultTabTable'],
|
||||
'table'
|
||||
);
|
||||
} else {
|
||||
$page = Util::getScriptNameForOption(
|
||||
$GLOBALS['cfg']['DefaultTabDatabase'],
|
||||
'database'
|
||||
);
|
||||
}
|
||||
include ROOT_PATH . $page;
|
||||
} elseif ($response->isAjax() && ! empty($_REQUEST['recent_table'])) {
|
||||
$response->addJSON($controller->reloadRecentTablesList());
|
||||
} elseif ($GLOBALS['PMA_Config']->isGitRevision()
|
||||
&& isset($_REQUEST['git_revision'])
|
||||
&& $response->isAjax()
|
||||
) {
|
||||
$response->addHTML($controller->gitRevision());
|
||||
} else {
|
||||
// Handles some variables that may have been sent by the calling script
|
||||
$GLOBALS['db'] = '';
|
||||
$GLOBALS['table'] = '';
|
||||
$show_query = '1';
|
||||
|
||||
if ($server > 0) {
|
||||
include ROOT_PATH . 'libraries/server_common.inc.php';
|
||||
}
|
||||
|
||||
$response->addHTML($controller->index());
|
||||
}
|
||||
$dispatcher = Routing::getDispatcher();
|
||||
Routing::callControllerForRoute($route, $dispatcher, $containerBuilder);
|
||||
|
||||
25
jest.config.js
Normal file
25
jest.config.js
Normal file
@ -0,0 +1,25 @@
|
||||
/* eslint-env node */
|
||||
|
||||
module.exports = {
|
||||
coverageDirectory: '<rootDir>/build/javascript/',
|
||||
collectCoverageFrom: ['<rootDir>/js/src/**/*.js'],
|
||||
projects: [
|
||||
{
|
||||
verbose: true,
|
||||
setupFiles: ['<rootDir>/test/jest/test-env.js'],
|
||||
coveragePathIgnorePatterns: [
|
||||
'<rootDir>/node_modules/',
|
||||
'<rootDir>/js/vendor/',
|
||||
],
|
||||
displayName: 'phpMyAdmin',
|
||||
testMatch: ['<rootDir>/test/javascript/**/*.js'],
|
||||
transform: {
|
||||
'^.+\\.js$': '<rootDir>/test/jest/file-transformer.js'
|
||||
},
|
||||
moduleNameMapper: {
|
||||
'^phpmyadmin/(.*)$': '<rootDir>/js/src/$1',
|
||||
'^@vendor/(.*)$': '<rootDir>/js/vendor/$1',
|
||||
},
|
||||
}
|
||||
]
|
||||
};
|
||||
2
js/dist/.gitignore
vendored
Normal file
2
js/dist/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/*
|
||||
!/.gitignore
|
||||
1015
js/messages.php
1015
js/messages.php
File diff suppressed because it is too large
Load Diff
@ -1,100 +0,0 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Server Status Advisor
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Unbind all event handlers before tearing down a page
|
||||
*/
|
||||
AJAX.registerTeardown('server/status/advisor.js', function () {
|
||||
$('a[href="#openAdvisorInstructions"]').off('click');
|
||||
$('#statustabs_advisor').html('');
|
||||
$('#advisorDialog').remove();
|
||||
$('#instructionsDialog').remove();
|
||||
});
|
||||
|
||||
AJAX.registerOnload('server/status/advisor.js', function () {
|
||||
// if no advisor is loaded
|
||||
if ($('#advisorData').length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** ** Server config advisor ****/
|
||||
var $dialog = $('<div></div>').attr('id', 'advisorDialog');
|
||||
var $instructionsDialog = $('<div></div>')
|
||||
.attr('id', 'instructionsDialog')
|
||||
.html($('#advisorInstructionsDialog').html());
|
||||
|
||||
$('a[href="#openAdvisorInstructions"]').on('click', function () {
|
||||
var dlgBtns = {};
|
||||
dlgBtns[Messages.strClose] = function () {
|
||||
$(this).dialog('close');
|
||||
};
|
||||
$instructionsDialog.dialog({
|
||||
title: Messages.strAdvisorSystem,
|
||||
width: '60%',
|
||||
buttons: dlgBtns
|
||||
});
|
||||
});
|
||||
|
||||
var $cnt = $('#statustabs_advisor');
|
||||
var $tbody;
|
||||
var $tr;
|
||||
var even = true;
|
||||
|
||||
var data = JSON.parse($('#advisorData').text());
|
||||
$cnt.html('');
|
||||
|
||||
if (data.parse.errors.length > 0) {
|
||||
$cnt.append('<b>Rules file not well formed, following errors were found:</b><br>- ');
|
||||
$cnt.append(data.parse.errors.join('<br>- '));
|
||||
$cnt.append('<p></p>');
|
||||
}
|
||||
|
||||
if (data.run.errors.length > 0) {
|
||||
$cnt.append('<b>Errors occurred while executing rule expressions:</b><br>- ');
|
||||
$cnt.append(data.run.errors.join('<br>- '));
|
||||
$cnt.append('<p></p>');
|
||||
}
|
||||
|
||||
if (data.run.fired.length > 0) {
|
||||
$cnt.append('<p><b>' + Messages.strPerformanceIssues + '</b></p>');
|
||||
$cnt.append('<table class="data" id="rulesFired" border="0"><thead><tr>' +
|
||||
'<th>' + Messages.strIssuse + '</th><th>' + Messages.strRecommendation +
|
||||
'</th></tr></thead><tbody></tbody></table>');
|
||||
$tbody = $cnt.find('table#rulesFired');
|
||||
|
||||
var rcStripped;
|
||||
|
||||
$.each(data.run.fired, function (key, value) {
|
||||
// recommendation may contain links, don't show those in overview table (clicking on them redirects the user)
|
||||
rcStripped = $.trim($('<div>').html(value.recommendation).text());
|
||||
$tbody.append($tr = $('<tr class="linkElem noclick"><td>' +
|
||||
value.issue + '</td><td>' + rcStripped + ' </td></tr>'));
|
||||
even = !even;
|
||||
$tr.data('rule', value);
|
||||
|
||||
$tr.on('click', function () {
|
||||
var rule = $(this).data('rule');
|
||||
$dialog
|
||||
.dialog({ title: Messages.strRuleDetails })
|
||||
.html(
|
||||
'<p><b>' + Messages.strIssuse + ':</b><br>' + rule.issue + '</p>' +
|
||||
'<p><b>' + Messages.strRecommendation + ':</b><br>' + rule.recommendation + '</p>' +
|
||||
'<p><b>' + Messages.strJustification + ':</b><br>' + rule.justification + '</p>' +
|
||||
'<p><b>' + Messages.strFormula + ':</b><br>' + rule.formula + '</p>' +
|
||||
'<p><b>' + Messages.strTest + ':</b><br>' + rule.test + '</p>'
|
||||
);
|
||||
|
||||
var dlgBtns = {};
|
||||
dlgBtns[Messages.strClose] = function () {
|
||||
$(this).dialog('close');
|
||||
};
|
||||
|
||||
$dialog.dialog({ width: 600, buttons: dlgBtns });
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,12 +1,12 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
/* global isStorageSupported */ // js/config.js
|
||||
/* global ErrorReport */ // js/error_report.js
|
||||
/* global MicroHistory */ // js/microhistory.js
|
||||
|
||||
/**
|
||||
* This object handles ajax requests for pages. It also
|
||||
* handles the reloading of the main menu and scripts.
|
||||
*
|
||||
* @test-module AJAX
|
||||
*/
|
||||
var AJAX = {
|
||||
/**
|
||||
@ -49,7 +49,7 @@ var AJAX = {
|
||||
*/
|
||||
hash: function (key) {
|
||||
var newKey = key;
|
||||
/* http://burtleburtle.net/bob/hash/doobs.html#one */
|
||||
/* https://burtleburtle.net/bob/hash/doobs.html#one */
|
||||
newKey += '';
|
||||
var len = newKey.length;
|
||||
var hash = 0;
|
||||
@ -262,17 +262,10 @@ var AJAX = {
|
||||
// the click event is not triggered by script
|
||||
if (typeof event !== 'undefined' && event.type === 'click' &&
|
||||
event.isTrigger !== true &&
|
||||
!jQuery.isEmptyObject(AJAX.lockedTargets)
|
||||
!jQuery.isEmptyObject(AJAX.lockedTargets) &&
|
||||
confirm(Messages.strConfirmNavigation) === false
|
||||
) {
|
||||
if (confirm(Messages.strConfirmNavigation) === false) {
|
||||
return false;
|
||||
} else {
|
||||
if (isStorageSupported('localStorage')) {
|
||||
window.localStorage.removeItem('autoSavedSql');
|
||||
} else {
|
||||
Cookies.set('autoSavedSql', '');
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
AJAX.resetLock();
|
||||
var isLink = !! href || false;
|
||||
@ -550,9 +543,9 @@ var AJAX = {
|
||||
var source = data.selflink.split('?')[0];
|
||||
// Check for faulty links
|
||||
var $selflinkReplace = {
|
||||
'import.php': 'tbl_sql.php',
|
||||
'tbl_chart.php': 'sql.php',
|
||||
'tbl_gis_visualization.php': 'sql.php'
|
||||
'index.php?route=/import': 'index.php?route=/table/sql',
|
||||
'index.php?route=/table/chart': 'index.php?route=/sql',
|
||||
'index.php?route=/table/gis-visualization': 'index.php?route=/sql'
|
||||
};
|
||||
if ($selflinkReplace[source]) {
|
||||
var replacement = $selflinkReplace[source];
|
||||
@ -770,7 +763,8 @@ var AJAX = {
|
||||
var self = this;
|
||||
|
||||
script.type = 'text/javascript';
|
||||
script.src = 'js/' + name + '?' + 'v=' + encodeURIComponent(CommonParams.get('PMA_VERSION'));
|
||||
var file = name.indexOf('vendor/') !== -1 ? name : 'dist/' + name;
|
||||
script.src = 'js/' + file + '?' + 'v=' + encodeURIComponent(CommonParams.get('PMA_VERSION'));
|
||||
script.async = false;
|
||||
script.onload = function () {
|
||||
self.done(name, callback);
|
||||
@ -873,7 +867,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
*/
|
||||
$(function () {
|
||||
var menuContent = $('<div></div>')
|
||||
.append($('#serverinfo').clone())
|
||||
.append($('#server-breadcrumb').clone())
|
||||
.append($('#topmenucontainer').clone())
|
||||
.html();
|
||||
if (history && history.pushState) {
|
||||
@ -943,7 +937,7 @@ $(document).on('submit', 'form', AJAX.requestHandler);
|
||||
* Gracefully handle fatal server errors
|
||||
* (e.g: 500 - Internal server error)
|
||||
*/
|
||||
$(document).ajaxError(function (event, request) {
|
||||
$(document).on('ajaxError', function (event, request) {
|
||||
if (AJAX.debug) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('AJAX error: status=' + request.status + ', text=' + request.statusText);
|
||||
@ -961,7 +955,7 @@ $(document).ajaxError(function (event, request) {
|
||||
details += '<div>' + Functions.escapeHtml(Messages.strErrorConnection) + '</div>';
|
||||
}
|
||||
Functions.ajaxShowMessage(
|
||||
'<div class="error">' +
|
||||
'<div class="alert alert-danger" role="alert">' +
|
||||
Messages.strErrorProcessingRequest +
|
||||
details +
|
||||
'</div>',
|
||||
@ -27,7 +27,7 @@ CodeMirror.sqlLint = function (text, updateLinting, options, cm) {
|
||||
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: 'lint.php',
|
||||
url: 'index.php?route=/lint',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
'sql_query': text,
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
$(function () {
|
||||
Functions.checkNumberOfFields();
|
||||
@ -9,6 +8,8 @@ $(function () {
|
||||
*
|
||||
* The content for this is normally loaded from Header.php or
|
||||
* Response.php and executed by ajax.js
|
||||
*
|
||||
* @test-module CommonParams
|
||||
*/
|
||||
var CommonParams = (function () {
|
||||
/**
|
||||
@ -79,19 +80,24 @@ var CommonParams = (function () {
|
||||
/**
|
||||
* Returns the url query string using the saved parameters
|
||||
*
|
||||
* @param {string} separator New separator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
getUrlQuery: function () {
|
||||
getUrlQuery: function (separator) {
|
||||
var sep = (typeof separator !== 'undefined') ? separator : '?';
|
||||
var common = this.get('common_query');
|
||||
var separator = '?';
|
||||
var argsep = CommonParams.get('arg_separator');
|
||||
if (common.length > 0) {
|
||||
separator = argsep;
|
||||
if (typeof common === 'string') {
|
||||
// If the last char is the separator, do not add it
|
||||
// Else add it
|
||||
common = common.substr(common.length - 1, common.length) === argsep ? common : common + argsep;
|
||||
}
|
||||
|
||||
return Functions.sprintf(
|
||||
'%s%sserver=%s' + argsep + 'db=%s' + argsep + 'table=%s',
|
||||
this.get('common_query'),
|
||||
separator,
|
||||
sep,
|
||||
common,
|
||||
encodeURIComponent(this.get('server')),
|
||||
encodeURIComponent(this.get('db')),
|
||||
encodeURIComponent(this.get('table'))
|
||||
@ -150,7 +156,11 @@ var CommonActions = {
|
||||
newUrl = $('#selflink').find('a').attr('href') || window.location.pathname;
|
||||
newUrl = newUrl.substring(0, newUrl.indexOf('?'));
|
||||
}
|
||||
newUrl += CommonParams.getUrlQuery();
|
||||
if (newUrl.indexOf('?') !== -1) {
|
||||
newUrl += CommonParams.getUrlQuery(CommonParams.get('arg_separator'));
|
||||
} else {
|
||||
newUrl += CommonParams.getUrlQuery('?');
|
||||
}
|
||||
$('<a></a>', { href: newUrl })
|
||||
.appendTo('body')
|
||||
.trigger('click')
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Functions used in configuration forms and on user preferences pages
|
||||
*/
|
||||
@ -45,9 +44,9 @@ AJAX.registerTeardown('config.js', function () {
|
||||
});
|
||||
|
||||
AJAX.registerOnload('config.js', function () {
|
||||
var $topmenuUpt = $('#topmenu2.user_prefs_tabs');
|
||||
$topmenuUpt.find('li.active a').attr('rel', 'samepage');
|
||||
$topmenuUpt.find('li:not(.active) a').attr('rel', 'newpage');
|
||||
var $topmenuUpt = $('#user_prefs_tabs');
|
||||
$topmenuUpt.find('a.active').attr('rel', 'samepage');
|
||||
$topmenuUpt.find('a:not(.active)').attr('rel', 'newpage');
|
||||
});
|
||||
|
||||
// default values for fields
|
||||
@ -616,10 +615,10 @@ function setupConfigTabs () {
|
||||
e.preventDefault();
|
||||
setTab($(this).attr('href').substr(1));
|
||||
})
|
||||
.filter(':first')
|
||||
.first()
|
||||
.parent()
|
||||
.addClass('active');
|
||||
$this.find('div.tabs_contents fieldset').hide().filter(':first').show();
|
||||
$this.find('div.tabs_contents fieldset').hide().first().show();
|
||||
});
|
||||
}
|
||||
|
||||
@ -637,23 +636,18 @@ AJAX.registerOnload('config.js', function () {
|
||||
setupConfigTabs();
|
||||
adjustPrefsNotification();
|
||||
|
||||
// tab links handling, check each 200ms
|
||||
// tab links handling
|
||||
// (works with history in FF, further browser support here would be an overkill)
|
||||
var prevHash;
|
||||
var tabCheckFnc = function () {
|
||||
if (location.hash !== prevHash) {
|
||||
prevHash = location.hash;
|
||||
if (prevHash.match(/^#tab_[a-zA-Z0-9_]+$/)) {
|
||||
// session ID is sometimes appended here
|
||||
var hash = prevHash.substr(5).split('&')[0];
|
||||
if ($('#' + hash).length) {
|
||||
setTab(hash);
|
||||
}
|
||||
window.onhashchange = function () {
|
||||
if (location.hash.match(/^#tab_[a-zA-Z0-9_]+$/)) {
|
||||
// session ID is sometimes appended here
|
||||
var hash = location.hash.substr(5).split('&')[0];
|
||||
if ($('#' + hash).length) {
|
||||
setTab(hash);
|
||||
}
|
||||
}
|
||||
};
|
||||
tabCheckFnc();
|
||||
setInterval(tabCheckFnc, 200);
|
||||
window.onhashchange();
|
||||
});
|
||||
|
||||
//
|
||||
@ -776,7 +770,7 @@ AJAX.registerOnload('config.js', function () {
|
||||
disabled = true;
|
||||
}
|
||||
$form.find('input[type=submit]').prop('disabled', disabled);
|
||||
}).submit(function (e) {
|
||||
}).on('submit', function (e) {
|
||||
var $form = $(this);
|
||||
if ($form.attr('name') === 'prefs_export' && $('#export_local_storage')[0].checked) {
|
||||
e.preventDefault();
|
||||
@ -791,7 +785,7 @@ AJAX.registerOnload('config.js', function () {
|
||||
$(document).on('click', 'div.click-hide-message', function () {
|
||||
$(this)
|
||||
.hide()
|
||||
.parent('.group')
|
||||
.parent('.card-body')
|
||||
.css('height', '')
|
||||
.next('form')
|
||||
.show();
|
||||
@ -808,7 +802,7 @@ function savePrefsToLocalStorage (form) {
|
||||
var submit = $form.find('input[type=submit]');
|
||||
submit.prop('disabled', true);
|
||||
$.ajax({
|
||||
url: 'prefs_manage.php',
|
||||
url: 'index.php?route=/preferences/manage',
|
||||
cache: false,
|
||||
type: 'POST',
|
||||
data: {
|
||||
@ -824,7 +818,7 @@ function savePrefsToLocalStorage (form) {
|
||||
updatePrefsDate();
|
||||
$('div.localStorage-empty').hide();
|
||||
$('div.localStorage-exists').show();
|
||||
var group = $form.parent('.group');
|
||||
var group = $form.parent('.card-body');
|
||||
group.css('height', group.height() + 'px');
|
||||
$form.hide('fast');
|
||||
$form.prev('.click-hide-message').show('fast');
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Used in or for console
|
||||
*
|
||||
@ -62,8 +61,16 @@ var Console = {
|
||||
return;
|
||||
}
|
||||
|
||||
Console.config = Functions.configGet('Console', false);
|
||||
Functions.configGet('Console', false, (data) => {
|
||||
Console.config = data;
|
||||
Console.setupAfterInit();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup the console after the config has been set at initialize stage
|
||||
*/
|
||||
setupAfterInit: function () {
|
||||
Console.isEnabled = true;
|
||||
|
||||
// Vars init
|
||||
@ -73,7 +80,7 @@ var Console = {
|
||||
Console.$consoleTemplates = $('#pma_console').find('>.templates');
|
||||
|
||||
// Generate a from for post
|
||||
Console.$requestForm = $('<form method="post" action="import.php">' +
|
||||
Console.$requestForm = $('<form method="post" action="index.php?route=/import">' +
|
||||
'<input name="is_js_confirmed" value="0">' +
|
||||
'<textarea name="sql_query"></textarea>' +
|
||||
'<input name="console_message_id" value="0">' +
|
||||
@ -171,7 +178,7 @@ var Console = {
|
||||
ConsoleMessages.showInstructions(Console.config.EnterExecutes);
|
||||
});
|
||||
|
||||
$(document).ajaxComplete(function (event, xhr, ajaxOptions) {
|
||||
$(document).on('ajaxComplete', function (event, xhr, ajaxOptions) {
|
||||
if (ajaxOptions.dataType && ajaxOptions.dataType.indexOf('json') !== -1) {
|
||||
return;
|
||||
}
|
||||
@ -182,7 +189,7 @@ var Console = {
|
||||
var data = JSON.parse(xhr.responseText);
|
||||
Console.ajaxCallback(data);
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
// eslint-disable-next-line no-console, compat/compat
|
||||
console.trace();
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed to parse JSON: ' + e.message);
|
||||
@ -209,6 +216,7 @@ var Console = {
|
||||
Console.info();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Execute query and show results in console
|
||||
*
|
||||
@ -913,7 +921,7 @@ var ConsoleMessages = {
|
||||
$targetMessage.find('.action.delete_bookmark').on('click', function () {
|
||||
var $message = $(this).closest('.message');
|
||||
if (confirm(Messages.strConsoleDeleteBookmarkConfirm + '\n' + $message.find('.bookmark_label').text())) {
|
||||
$.post('import.php',
|
||||
$.post('index.php?route=/import',
|
||||
{
|
||||
'server': CommonParams.get('server'),
|
||||
'action_bookmark': 2,
|
||||
@ -1048,7 +1056,7 @@ var ConsoleBookmarks = {
|
||||
}
|
||||
},
|
||||
refresh: function () {
|
||||
$.get('import.php',
|
||||
$.get('index.php?route=/import',
|
||||
{
|
||||
'ajax_request': true,
|
||||
'server': CommonParams.get('server'),
|
||||
@ -1084,7 +1092,7 @@ var ConsoleBookmarks = {
|
||||
return;
|
||||
}
|
||||
$(this).prop('disabled', true);
|
||||
$.post('import.php',
|
||||
$.post('index.php?route=/import',
|
||||
{
|
||||
'ajax_request': true,
|
||||
'console_bookmark_add': 'true',
|
||||
@ -1118,7 +1126,7 @@ var ConsoleDebug = {
|
||||
},
|
||||
initialize: function () {
|
||||
// Try to get debug info after every AJAX request
|
||||
$(document).ajaxSuccess(function (event, xhr, settings, data) {
|
||||
$(document).on('ajaxSuccess', function (event, xhr, settings, data) {
|
||||
if (data.debug) {
|
||||
ConsoleDebug.showLog(data.debug, settings.url);
|
||||
}
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Conditionally included if framing is not allowed
|
||||
*/
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @fileoverview events handling from central columns page
|
||||
* @name Central columns
|
||||
@ -7,7 +6,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* AJAX scripts for db_central_columns.php
|
||||
* AJAX scripts for /database/central-columns
|
||||
*
|
||||
* Actions ajaxified here:
|
||||
* Inline Edit and save of a result row
|
||||
@ -68,20 +67,20 @@ AJAX.registerOnload('database/central_columns.js', function () {
|
||||
var editColumnData = editColumnList + '' + argsep + 'edit_central_columns_page=true' + argsep + 'ajax_request=true' + argsep + 'ajax_page_request=true' + argsep + 'db=' + encodeURIComponent(CommonParams.get('db'));
|
||||
Functions.ajaxShowMessage();
|
||||
AJAX.source = $(this);
|
||||
$.post('db_central_columns.php', editColumnData, AJAX.responseHandler);
|
||||
$.post('index.php?route=/database/central-columns', editColumnData, AJAX.responseHandler);
|
||||
});
|
||||
$('#multi_edit_central_columns').submit(function (event) {
|
||||
$('#multi_edit_central_columns').on('submit', function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
var argsep = CommonParams.get('arg_separator');
|
||||
var multiColumnEditData = $('#multi_edit_central_columns').serialize() + argsep + 'multi_edit_central_column_save=true' + argsep + 'ajax_request=true' + argsep + 'ajax_page_request=true' + argsep + 'db=' + encodeURIComponent(CommonParams.get('db'));
|
||||
Functions.ajaxShowMessage();
|
||||
AJAX.source = $(this);
|
||||
$.post('db_central_columns.php', multiColumnEditData, AJAX.responseHandler);
|
||||
$.post('index.php?route=/database/central-columns', multiColumnEditData, AJAX.responseHandler);
|
||||
});
|
||||
$('#add_new').find('td').each(function () {
|
||||
if ($(this).attr('name') !== 'undefined') {
|
||||
$(this).find('input,select:first').attr('name', $(this).attr('name'));
|
||||
$(this).find('input,select').first().attr('name', $(this).attr('name'));
|
||||
}
|
||||
});
|
||||
$('#field_0_0').attr('required','required');
|
||||
@ -94,7 +93,7 @@ AJAX.registerOnload('database/central_columns.js', function () {
|
||||
$(document).on('keyup', '.filter_rows', function () {
|
||||
// get the column names
|
||||
var cols = $('th.column_heading').map(function () {
|
||||
return $.trim($(this).text());
|
||||
return $(this).text().trim();
|
||||
}).get();
|
||||
$.uiTableFilter($('#table_columns'), $(this).val(), cols, null, 'td span');
|
||||
});
|
||||
@ -139,7 +138,7 @@ AJAX.registerOnload('database/central_columns.js', function () {
|
||||
var rownum = $(this).data('rownum');
|
||||
$('#f_' + rownum + ' td').each(function () {
|
||||
if ($(this).attr('name') !== 'undefined') {
|
||||
$(this).find(':input[type!="hidden"],select:first')
|
||||
$(this).find(':input[type!="hidden"],select').first()
|
||||
.attr('name', $(this).attr('name'));
|
||||
}
|
||||
});
|
||||
@ -153,13 +152,13 @@ AJAX.registerOnload('database/central_columns.js', function () {
|
||||
var datastring = $('#f_' + rownum + ' :input').serialize();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: 'db_central_columns.php',
|
||||
url: 'index.php?route=/database/central-columns',
|
||||
data: datastring + CommonParams.get('arg_separator') + 'ajax_request=true',
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
if (data.message !== '1') {
|
||||
Functions.ajaxShowMessage(
|
||||
'<div class="error">' +
|
||||
'<div class="alert alert-danger" role="alert">' +
|
||||
data.message +
|
||||
'</div>',
|
||||
false
|
||||
@ -183,7 +182,7 @@ AJAX.registerOnload('database/central_columns.js', function () {
|
||||
},
|
||||
error: function () {
|
||||
Functions.ajaxShowMessage(
|
||||
'<div class="error">' +
|
||||
'<div class="alert alert-danger" role="alert">' +
|
||||
Messages.strErrorProcessingRequest +
|
||||
'</div>',
|
||||
false
|
||||
@ -193,14 +192,13 @@ AJAX.registerOnload('database/central_columns.js', function () {
|
||||
});
|
||||
$('#table-select').on('change', function () {
|
||||
var selectValue = $(this).val();
|
||||
var defaultColumnSelect = $('#column-select').find('option:first');
|
||||
var href = 'db_central_columns.php';
|
||||
var defaultColumnSelect = $('#column-select').find('option').first();
|
||||
var href = 'index.php?route=/database/central-columns/populate';
|
||||
var params = {
|
||||
'ajax_request' : true,
|
||||
'server' : CommonParams.get('server'),
|
||||
'db' : CommonParams.get('db'),
|
||||
'selectedTable' : selectValue,
|
||||
'populateColumns' : true
|
||||
'selectedTable' : selectValue
|
||||
};
|
||||
$('#column-select').html('<option value="">' + Messages.strLoading + '</option>');
|
||||
if (selectValue !== '') {
|
||||
@ -210,7 +208,7 @@ AJAX.registerOnload('database/central_columns.js', function () {
|
||||
});
|
||||
}
|
||||
});
|
||||
$('#add_column').submit(function (e) {
|
||||
$('#add_column').on('submit', function (e) {
|
||||
var selectvalue = $('#column-select').val();
|
||||
if (selectvalue === '') {
|
||||
e.preventDefault();
|
||||
@ -226,7 +224,7 @@ AJAX.registerOnload('database/central_columns.js', function () {
|
||||
$addColDivLinkSpan.html('+');
|
||||
}
|
||||
});
|
||||
$('#add_new').submit(function () {
|
||||
$('#add_new').on('submit', function () {
|
||||
$('#add_new').toggle();
|
||||
});
|
||||
$('#tableslistcontainer').find('select.default_type').on('change', function () {
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @fileoverview function used in QBE for DB
|
||||
* @name Database Operations
|
||||
@ -11,9 +10,10 @@
|
||||
*/
|
||||
|
||||
/* global generateFromBlock, generateWhereBlock */ // js/database/query_generator.js
|
||||
/* global md5 */ // js/vendor/jquery/jquery.md5.js
|
||||
|
||||
/**
|
||||
* js file for handling AJAX and other events in db_multi_table_query.php
|
||||
* js file for handling AJAX and other events in /database/multi-table-query
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -71,7 +71,7 @@ AJAX.registerOnload('database/multi_table_query.js', function () {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
async: false,
|
||||
url: 'db_multi_table_query.php',
|
||||
url: 'index.php?route=/database/multi-table-query/tables',
|
||||
data: {
|
||||
'server': sessionStorage.server,
|
||||
'db': $('#db_name').val(),
|
||||
@ -133,7 +133,7 @@ AJAX.registerOnload('database/multi_table_query.js', function () {
|
||||
};
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: 'db_multi_table_query.php',
|
||||
url: 'index.php?route=/database/multi-table-query/query',
|
||||
data: data,
|
||||
success: function (data) {
|
||||
var $resultsDom = $(data.message);
|
||||
@ -172,7 +172,7 @@ AJAX.registerOnload('database/multi_table_query.js', function () {
|
||||
if ($sibs.length === 0) {
|
||||
$sibs = $(this).parent().parent().find('.columnNameSelect');
|
||||
}
|
||||
$sibs.first().html($('#' + $.md5($(this).val())).html());
|
||||
$sibs.first().html($('#' + md5($(this).val())).html());
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @fileoverview function used in server privilege pages
|
||||
* @name Database Operations
|
||||
@ -10,7 +9,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ajax event handlers here for db_operations.php
|
||||
* Ajax event handlers here for /database/operations
|
||||
*
|
||||
* Actions Ajaxified here:
|
||||
* Rename Database
|
||||
@ -36,6 +35,11 @@ AJAX.registerOnload('database/operations.js', function () {
|
||||
$(document).on('submit', '#rename_db_form.ajax', function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (Functions.emptyCheckTheField(this, 'newname')) {
|
||||
Functions.ajaxShowMessage(Messages.strFormEmpty, false, 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
var oldDbName = CommonParams.get('db');
|
||||
var newDbName = $('#new_db_name').val();
|
||||
|
||||
@ -81,12 +85,18 @@ AJAX.registerOnload('database/operations.js', function () {
|
||||
*/
|
||||
$(document).on('submit', '#copy_db_form.ajax', function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (Functions.emptyCheckTheField(this, 'newname')) {
|
||||
Functions.ajaxShowMessage(Messages.strFormEmpty, false, 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
Functions.ajaxShowMessage(Messages.strCopyingDatabase, false);
|
||||
var $form = $(this);
|
||||
Functions.prepareForAjaxRequest($form);
|
||||
$.post($form.attr('action'), $form.serialize(), function (data) {
|
||||
// use messages that stay on screen
|
||||
$('div.success, div.error').fadeOut();
|
||||
$('.alert-success, .alert-danger').fadeOut();
|
||||
if (typeof data !== 'undefined' && data.success === true) {
|
||||
if ($('#checkbox_switch').is(':checked')) {
|
||||
CommonParams.set('db', data.newname);
|
||||
@ -120,7 +130,7 @@ AJAX.registerOnload('database/operations.js', function () {
|
||||
var $form = $(this);
|
||||
Functions.prepareForAjaxRequest($form);
|
||||
Functions.ajaxShowMessage(Messages.strChangingCharset);
|
||||
$.post($form.attr('action'), $form.serialize() + CommonParams.get('arg_separator') + 'submitcollation=1', function (data) {
|
||||
$.post($form.attr('action'), $form.serialize(), function (data) {
|
||||
if (typeof data !== 'undefined' && data.success === true) {
|
||||
Functions.ajaxShowMessage(data.message);
|
||||
} else {
|
||||
@ -153,7 +163,7 @@ AJAX.registerOnload('database/operations.js', function () {
|
||||
Navigation.reload();
|
||||
CommonParams.set('db', '');
|
||||
CommonActions.refreshMain(
|
||||
'server_databases.php',
|
||||
'index.php?route=/server/databases',
|
||||
function () {
|
||||
Functions.ajaxShowMessage(data.message);
|
||||
}
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @fileoverview function used in QBE for DB
|
||||
* @name Database Operations
|
||||
@ -10,7 +9,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ajax event handlers here for db_qbe.php
|
||||
* Ajax event handlers here for /database/qbe
|
||||
*
|
||||
* Actions Ajaxified here:
|
||||
* Select saved search
|
||||
@ -32,7 +31,7 @@ AJAX.registerOnload('database/qbe.js', function () {
|
||||
|
||||
$('#tblQbe').width($('#tblQbe').parent().width());
|
||||
$('#tblQbeFooters').width($('#tblQbeFooters').parent().width());
|
||||
$('#tblQbe').resize(function () {
|
||||
$('#tblQbe').on('resize', function () {
|
||||
var newWidthTblQbe = $('#textSqlquery').next().width();
|
||||
$('#tblQbe').width(newWidthTblQbe);
|
||||
$('#tblQbeFooters').width(newWidthTblQbe);
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @fileoverview function used in QBE for DB
|
||||
* @name Database Operations
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* JavaScript functions used on Database Search page
|
||||
*
|
||||
@ -185,7 +184,7 @@ AJAX.registerOnload('database/search.js', function () {
|
||||
|
||||
$('#sqlqueryform').html(data.sql_query);
|
||||
/** Refresh the search results after the deletion */
|
||||
document.getElementById('buttonGo').trigger('click');
|
||||
$('#buttonGo').trigger('click');
|
||||
$('#togglequerybox').html(Messages.strHideQueryBox);
|
||||
/** Show the results of the deletion option */
|
||||
$('#browse-results').hide();
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @fileoverview functions used on the database structure page
|
||||
* @name Database Structure
|
||||
@ -11,7 +10,7 @@
|
||||
var DatabaseStructure = {};
|
||||
|
||||
/**
|
||||
* AJAX scripts for db_structure.php
|
||||
* AJAX scripts for /database/structure
|
||||
*
|
||||
* Actions ajaxified here:
|
||||
* Drop Database
|
||||
@ -51,7 +50,7 @@ DatabaseStructure.adjustTotals = function () {
|
||||
/**
|
||||
* @var $allTr jQuery object that references all the rows in the list of tables
|
||||
*/
|
||||
var $allTr = $('#tablesForm').find('table.data tbody:first tr');
|
||||
var $allTr = $('#tablesForm').find('table.data tbody').first().find('tr');
|
||||
// New summary values for the table
|
||||
var tableSum = $allTr.length;
|
||||
var rowsSum = 0;
|
||||
@ -79,10 +78,10 @@ DatabaseStructure.adjustTotals = function () {
|
||||
// Extract the size and overhead
|
||||
var valSize = 0;
|
||||
var valOverhead = 0;
|
||||
var strSize = $.trim($this.find('.tbl_size span:not(.unit)').text());
|
||||
var strSizeUnit = $.trim($this.find('.tbl_size span.unit').text());
|
||||
var strOverhead = $.trim($this.find('.tbl_overhead span:not(.unit)').text());
|
||||
var strOverheadUnit = $.trim($this.find('.tbl_overhead span.unit').text());
|
||||
var strSize = $this.find('.tbl_size span:not(.unit)').text().trim();
|
||||
var strSizeUnit = $this.find('.tbl_size span.unit').text().trim();
|
||||
var strOverhead = $this.find('.tbl_overhead span:not(.unit)').text().trim();
|
||||
var strOverheadUnit = $this.find('.tbl_overhead span.unit').text().trim();
|
||||
// Given a value and a unit, such as 100 and KiB, for the table size
|
||||
// and overhead calculate their numeric values in bytes, such as 102400
|
||||
for (i = 0; i < byteUnits.length; i++) {
|
||||
@ -217,16 +216,37 @@ AJAX.registerOnload('database/structure.js', function () {
|
||||
* Event handler on select of "Make consistent with central list"
|
||||
*/
|
||||
$('select[name=submit_mult]').on('change', function (event) {
|
||||
if ($(this).val() === 'make_consistent_with_central_list') {
|
||||
var url = 'index.php?route=/database/structure';
|
||||
var action = $(this).val();
|
||||
|
||||
if (action === 'make_consistent_with_central_list') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
jqConfirm(
|
||||
Messages.makeConsistentMessage, function () {
|
||||
$('#tablesForm').trigger('submit');
|
||||
Messages.makeConsistentMessage,
|
||||
function () {
|
||||
var $form = $('#tablesForm');
|
||||
var argsep = CommonParams.get('arg_separator');
|
||||
var data = $form.serialize() + argsep + 'ajax_request=true' + argsep + 'ajax_page_request=true';
|
||||
|
||||
Functions.ajaxShowMessage();
|
||||
AJAX.source = $form;
|
||||
|
||||
$.post(
|
||||
'index.php?route=/database/structure/central-columns-make-consistent',
|
||||
data,
|
||||
AJAX.responseHandler
|
||||
);
|
||||
}
|
||||
);
|
||||
return false;
|
||||
} else if ($(this).val() === 'copy_tbl' || $(this).val() === 'add_prefix_tbl' || $(this).val() === 'replace_prefix_tbl' || $(this).val() === 'copy_tbl_change_prefix') {
|
||||
}
|
||||
|
||||
if (action === 'copy_tbl' ||
|
||||
action === 'add_prefix_tbl' ||
|
||||
action === 'replace_prefix_tbl' ||
|
||||
action === 'copy_tbl_change_prefix'
|
||||
) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if ($('input[name="selected_tbl[]"]:checked').length === 0) {
|
||||
@ -234,18 +254,22 @@ AJAX.registerOnload('database/structure.js', function () {
|
||||
}
|
||||
var formData = $('#tablesForm').serialize();
|
||||
var modalTitle = '';
|
||||
if ($(this).val() === 'copy_tbl') {
|
||||
if (action === 'copy_tbl') {
|
||||
url = 'index.php?route=/database/structure/copy-form';
|
||||
modalTitle = Messages.strCopyTablesTo;
|
||||
} else if ($(this).val() === 'add_prefix_tbl') {
|
||||
} else if (action === 'add_prefix_tbl') {
|
||||
url = 'index.php?route=/database/structure/add-prefix';
|
||||
modalTitle = Messages.strAddPrefix;
|
||||
} else if ($(this).val() === 'replace_prefix_tbl') {
|
||||
} else if (action === 'replace_prefix_tbl') {
|
||||
url = 'index.php?route=/database/structure/change-prefix-form';
|
||||
modalTitle = Messages.strReplacePrefix;
|
||||
} else if ($(this).val() === 'copy_tbl_change_prefix') {
|
||||
} else if (action === 'copy_tbl_change_prefix') {
|
||||
url = 'index.php?route=/database/structure/change-prefix-form';
|
||||
modalTitle = Messages.strCopyPrefix;
|
||||
}
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: 'db_structure.php',
|
||||
url: url,
|
||||
dataType: 'html',
|
||||
data: formData
|
||||
|
||||
@ -269,9 +293,46 @@ AJAX.registerOnload('database/structure.js', function () {
|
||||
buttons: buttonOptions
|
||||
});
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (action === 'analyze_tbl') {
|
||||
url = 'index.php?route=/table/maintenance/analyze';
|
||||
} else if (action === 'sync_unique_columns_central_list') {
|
||||
url = 'index.php?route=/database/structure/central-columns-add';
|
||||
} else if (action === 'delete_unique_columns_central_list') {
|
||||
url = 'index.php?route=/database/structure/central-columns-remove';
|
||||
} else if (action === 'check_tbl') {
|
||||
url = 'index.php?route=/table/maintenance/check';
|
||||
} else if (action === 'checksum_tbl') {
|
||||
url = 'index.php?route=/table/maintenance/checksum';
|
||||
} else if (action === 'drop_tbl') {
|
||||
url = 'index.php?route=/database/structure/drop-form';
|
||||
} else if (action === 'empty_tbl') {
|
||||
url = 'index.php?route=/database/structure/empty-form';
|
||||
} else if (action === 'export') {
|
||||
url = 'index.php?route=/export/tables';
|
||||
} else if (action === 'optimize_tbl') {
|
||||
url = 'index.php?route=/table/maintenance/optimize';
|
||||
} else if (action === 'repair_tbl') {
|
||||
url = 'index.php?route=/table/maintenance/repair';
|
||||
} else if (action === 'show_create') {
|
||||
url = 'index.php?route=/database/structure/show-create';
|
||||
} else {
|
||||
$('#tablesForm').trigger('submit');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var $form = $(this).parents('form');
|
||||
var argsep = CommonParams.get('arg_separator');
|
||||
var data = $form.serialize() + argsep + 'ajax_request=true' + argsep + 'ajax_page_request=true';
|
||||
|
||||
Functions.ajaxShowMessage();
|
||||
AJAX.source = $form;
|
||||
|
||||
$.post(url, data, AJAX.responseHandler);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -309,14 +370,6 @@ AJAX.registerOnload('database/structure.js', function () {
|
||||
var $tr = $thisAnchor.closest('tr');
|
||||
$tr.find('.tbl_rows').text('0');
|
||||
$tr.find('.tbl_size, .tbl_overhead').text('-');
|
||||
// Fetch inner span of this anchor
|
||||
// and replace the icon with its disabled version
|
||||
var span = $thisAnchor.html().replace(/b_empty/, 'bd_empty');
|
||||
// To disable further attempts to truncate the table,
|
||||
// replace the a element with its inner span (modified)
|
||||
$thisAnchor
|
||||
.replaceWith(span)
|
||||
.removeClass('truncate_table_anchor');
|
||||
DatabaseStructure.adjustTotals();
|
||||
} else {
|
||||
Functions.ajaxShowMessage(Messages.strErrorProcessingRequest + ' : ' + data.error, false);
|
||||
@ -12,7 +12,7 @@ AJAX.registerTeardown('database/tracking.js', function () {
|
||||
*/
|
||||
AJAX.registerOnload('database/tracking.js', function () {
|
||||
var $versions = $('#versions');
|
||||
$versions.find('tr:first th').append($('<div class="sorticon"></div>'));
|
||||
$versions.find('tr').first().find('th').append($('<div class="sorticon"></div>'));
|
||||
$versions.tablesorter({
|
||||
sortList: [[1, 0]],
|
||||
headers: {
|
||||
@ -25,7 +25,7 @@ AJAX.registerOnload('database/tracking.js', function () {
|
||||
});
|
||||
|
||||
var $noVersions = $('#noversions');
|
||||
$noVersions.find('tr:first th').append($('<div class="sorticon"></div>'));
|
||||
$noVersions.find('tr').first().find('th').append($('<div class="sorticon"></div>'));
|
||||
$noVersions.tablesorter({
|
||||
sortList: [[1, 0]],
|
||||
headers: {
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @fileoverview function used in this file builds history tab and generates query.
|
||||
*
|
||||
@ -9,7 +8,7 @@
|
||||
|
||||
/* global contr */ // js/designer/init.js
|
||||
/* global fromArray:writable */ // js/designer/move.js
|
||||
/* global pmaThemeImage */ // js/messages.php
|
||||
/* global themeImagePath */ // templates/javascript/variables.twig
|
||||
|
||||
var DesignerHistory = {};
|
||||
|
||||
@ -89,35 +88,36 @@ DesignerHistory.display = function (init, finit) {
|
||||
}
|
||||
// this part generates HTML code for history tab.adds delete,edit,and/or and detail features with objects.
|
||||
str = ''; // string to store Html code for history tab
|
||||
for (i = 0; i < historyArray.length; i++) {
|
||||
var historyArrayLength = historyArray.length;
|
||||
for (i = 0; i < historyArrayLength; i++) {
|
||||
temp = historyArray[i].getTab(); // + '.' + historyArray[i].getObjNo(); for Self JOIN
|
||||
str += '<h3 class="tiger"><a href="#">' + temp + '</a></h3>';
|
||||
str += '<div class="toggle_container">\n';
|
||||
while ((historyArray[i].getTab()) === temp) { // + '.' + historyArray[i].getObjNo()) === temp) {
|
||||
str += '<div class="block"> <table width ="250">';
|
||||
str += '<div class="block"> <table class="pma-table" width ="250">';
|
||||
str += '<thead><tr><td>';
|
||||
if (historyArray[i].getAndOr()) {
|
||||
str += '<img src="' + pmaThemeImage + 'designer/or_icon.png" onclick="DesignerHistory.andOr(' + i + ')" title="OR"></td>';
|
||||
str += '<img src="' + themeImagePath + 'designer/or_icon.png" onclick="DesignerHistory.andOr(' + i + ')" title="OR"></td>';
|
||||
} else {
|
||||
str += '<img src="' + pmaThemeImage + 'designer/and_icon.png" onclick="DesignerHistory.andOr(' + i + ')" title="AND"></td>';
|
||||
str += '<img src="' + themeImagePath + 'designer/and_icon.png" onclick="DesignerHistory.andOr(' + i + ')" title="AND"></td>';
|
||||
}
|
||||
str += '<td style="padding-left: 5px;" class="right">' + Functions.getImage('b_sbrowse', Messages.strColumnName) + '</td>' +
|
||||
'<td width="175" style="padding-left: 5px">' + $('<div/>').text(historyArray[i].getColumnName()).html() + '<td>';
|
||||
if (historyArray[i].getType() === 'GroupBy' || historyArray[i].getType() === 'OrderBy') {
|
||||
var detailDescGroupBy = $('<div/>').text(DesignerHistory.detail(i)).html();
|
||||
str += '<td class="center">' + Functions.getImage('s_info', DesignerHistory.detail(i)) + '</td>' +
|
||||
str += '<td class="text-center">' + Functions.getImage('s_info', DesignerHistory.detail(i)) + '</td>' +
|
||||
'<td title="' + detailDescGroupBy + '">' + historyArray[i].getType() + '</td>' +
|
||||
'<td onclick=DesignerHistory.historyDelete(' + i + ')>' + Functions.getImage('b_drop', Messages.strDelete) + '</td>';
|
||||
} else {
|
||||
var detailDesc = $('<div/>').text(DesignerHistory.detail(i)).html();
|
||||
str += '<td class="center">' + Functions.getImage('s_info', DesignerHistory.detail(i)) + '</td>' +
|
||||
str += '<td class="text-center">' + Functions.getImage('s_info', DesignerHistory.detail(i)) + '</td>' +
|
||||
'<td title="' + detailDesc + '">' + historyArray[i].getType() + '</td>' +
|
||||
'<td onclick=DesignerHistory.historyEdit(' + i + ')>' + Functions.getImage('b_edit', Messages.strEdit) + '</td>' +
|
||||
'<td onclick=DesignerHistory.historyDelete(' + i + ')>' + Functions.getImage('b_drop', Messages.strDelete) + '</td>';
|
||||
}
|
||||
str += '</tr></thead>';
|
||||
i++;
|
||||
if (i >= historyArray.length) {
|
||||
if (i >= historyArrayLength) {
|
||||
break;
|
||||
}
|
||||
str += '</table></div>';
|
||||
@ -155,7 +155,8 @@ DesignerHistory.andOr = function (index) {
|
||||
**/
|
||||
|
||||
DesignerHistory.historyDelete = function (index) {
|
||||
for (var k = 0; k < fromArray.length; k++) {
|
||||
var fromArrayLength = fromArray.length;
|
||||
for (var k = 0; k < fromArrayLength; k++) {
|
||||
if (fromArray[k] === historyArray[index].getTab()) {
|
||||
fromArray.splice(k, 1);
|
||||
break;
|
||||
@ -451,12 +452,13 @@ DesignerHistory.unique = function (arrayName) {
|
||||
var newArray = [];
|
||||
uniquetop:
|
||||
for (var i = 0; i < arrayName.length; i++) {
|
||||
for (var j = 0; j < newArray.length; j++) {
|
||||
var newArrayLength = newArray.length;
|
||||
for (var j = 0; j < newArrayLength; j++) {
|
||||
if (newArray[j] === arrayName[i]) {
|
||||
continue uniquetop;
|
||||
}
|
||||
}
|
||||
newArray[newArray.length] = arrayName[i];
|
||||
newArray[newArrayLength] = arrayName[i];
|
||||
}
|
||||
return newArray;
|
||||
};
|
||||
@ -470,7 +472,8 @@ DesignerHistory.unique = function (arrayName) {
|
||||
*/
|
||||
|
||||
DesignerHistory.found = function (arrayName, value) {
|
||||
for (var i = 0; i < arrayName.length; i++) {
|
||||
var arrayNameLength = arrayName.length;
|
||||
for (var i = 0; i < arrayNameLength; i++) {
|
||||
if (arrayName[i] === value) {
|
||||
return 1;
|
||||
}
|
||||
@ -485,7 +488,8 @@ DesignerHistory.found = function (arrayName, value) {
|
||||
* @params arr array in which elements are added
|
||||
*/
|
||||
DesignerHistory.addArray = function (add, arr) {
|
||||
for (var i = 0; i < add.length; i++) {
|
||||
var addLength = add.length;
|
||||
for (var i = 0; i < addLength; i++) {
|
||||
arr.push(add[i]);
|
||||
}
|
||||
return arr;
|
||||
@ -499,8 +503,10 @@ DesignerHistory.addArray = function (add, arr) {
|
||||
*
|
||||
*/
|
||||
DesignerHistory.removeArray = function (rem, arr) {
|
||||
for (var i = 0; i < rem.length; i++) {
|
||||
for (var j = 0; j < arr.length; j++) {
|
||||
var remLength = rem.length;
|
||||
for (var i = 0; i < remLength; i++) {
|
||||
var arrLength = arr.length;
|
||||
for (var j = 0; j < arrLength; j++) {
|
||||
if (rem[i] === arr[j]) {
|
||||
arr.splice(j, 1);
|
||||
}
|
||||
@ -517,7 +523,8 @@ DesignerHistory.removeArray = function (rem, arr) {
|
||||
DesignerHistory.queryGroupBy = function () {
|
||||
var i;
|
||||
var str = '';
|
||||
for (i = 0; i < historyArray.length; i++) {
|
||||
var historyArrayLength = historyArray.length;
|
||||
for (i = 0; i < historyArrayLength; i++) {
|
||||
if (historyArray[i].getType() === 'GroupBy') {
|
||||
str += '`' + historyArray[i].getColumnName() + '`, ';
|
||||
}
|
||||
@ -534,7 +541,8 @@ DesignerHistory.queryGroupBy = function () {
|
||||
DesignerHistory.queryHaving = function () {
|
||||
var i;
|
||||
var and = '(';
|
||||
for (i = 0; i < historyArray.length; i++) {
|
||||
var historyArrayLength = historyArray.length;
|
||||
for (i = 0; i < historyArrayLength; i++) {
|
||||
if (historyArray[i].getType() === 'Having') {
|
||||
if (historyArray[i].getObj().getOperator() !== 'None') {
|
||||
and += historyArray[i].getObj().getOperator() + '(`' + historyArray[i].getColumnName() + '`) ' + historyArray[i].getObj().getRelationOperator();
|
||||
@ -561,7 +569,8 @@ DesignerHistory.queryHaving = function () {
|
||||
DesignerHistory.queryOrderBy = function () {
|
||||
var i;
|
||||
var str = '';
|
||||
for (i = 0; i < historyArray.length; i++) {
|
||||
var historyArrayLength = historyArray.length;
|
||||
for (i = 0; i < historyArrayLength; i++) {
|
||||
if (historyArray[i].getType() === 'OrderBy') {
|
||||
str += '`' + historyArray[i].getColumnName() + '` ' +
|
||||
historyArray[i].getObj().getOrder() + ', ';
|
||||
@ -581,7 +590,8 @@ DesignerHistory.queryWhere = function () {
|
||||
var i;
|
||||
var and = '(';
|
||||
var or = '(';
|
||||
for (i = 0; i < historyArray.length; i++) {
|
||||
var historyArrayLength = historyArray.length;
|
||||
for (i = 0; i < historyArrayLength; i++) {
|
||||
if (historyArray[i].getType() === 'Where') {
|
||||
if (historyArray[i].getAndOr() === 0) {
|
||||
and += '( `' + historyArray[i].getColumnName() + '` ' + historyArray[i].getObj().getRelationOperator() + ' ' + historyArray[i].getObj().getQuery() + ')';
|
||||
@ -610,7 +620,8 @@ DesignerHistory.queryWhere = function () {
|
||||
|
||||
DesignerHistory.checkAggregate = function (idThis) {
|
||||
var i;
|
||||
for (i = 0; i < historyArray.length; i++) {
|
||||
var historyArrayLength = historyArray.length;
|
||||
for (i = 0; i < historyArrayLength; i++) {
|
||||
var temp = '`' + historyArray[i].getTab() + '`.`' + historyArray[i].getColumnName() + '`';
|
||||
if (temp === idThis && historyArray[i].getType() === 'Aggregate') {
|
||||
return historyArray[i].getObj().getOperator() + '(' + idThis + ')';
|
||||
@ -621,7 +632,8 @@ DesignerHistory.checkAggregate = function (idThis) {
|
||||
|
||||
DesignerHistory.checkRename = function (idThis) {
|
||||
var i;
|
||||
for (i = 0; i < historyArray.length; i++) {
|
||||
var historyArrayLength = historyArray.length;
|
||||
for (i = 0; i < historyArrayLength; i++) {
|
||||
var temp = '`' + historyArray[i].getTab() + '`.`' + historyArray[i].getColumnName() + '`';
|
||||
if (temp === idThis && historyArray[i].getType() === 'Rename') {
|
||||
return ' AS `' + historyArray[i].getObj().getRenameTo() + '`';
|
||||
@ -657,7 +669,8 @@ DesignerHistory.queryFrom = function () {
|
||||
// the constraints that have been used in the LEFT JOIN
|
||||
var constraintsAdded = [];
|
||||
|
||||
for (i = 0; i < historyArray.length; i++) {
|
||||
var historyArrayLength = historyArray.length;
|
||||
for (i = 0; i < historyArrayLength; i++) {
|
||||
fromArray.push(historyArray[i].getTab());
|
||||
}
|
||||
fromArray = DesignerHistory.unique(fromArray);
|
||||
@ -751,8 +764,9 @@ DesignerHistory.queryFrom = function () {
|
||||
DesignerHistory.buildQuery = function () {
|
||||
var qSelect = 'SELECT ';
|
||||
var temp;
|
||||
if (selectField.length > 0) {
|
||||
for (var i = 0; i < selectField.length; i++) {
|
||||
var selectFieldLength = selectField.length;
|
||||
if (selectFieldLength > 0) {
|
||||
for (var i = 0; i < selectFieldLength; i++) {
|
||||
temp = DesignerHistory.checkAggregate(selectField[i]);
|
||||
if (temp !== '') {
|
||||
qSelect += temp;
|
||||
@ -1,6 +1,5 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Initialises the data required to run Designer, then fires it up.
|
||||
* Initializes the data required to run Designer, then fires it up.
|
||||
*/
|
||||
|
||||
/* global DesignerOfflineDB */ // js/designer/database.js
|
||||
@ -9,14 +8,12 @@
|
||||
/* global DesignerPage */ // js/designer/page.js
|
||||
/* global designerConfig */ // templates/database/designer/main.twig
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
var jTabs;
|
||||
var hTabs;
|
||||
var contr;
|
||||
var displayField;
|
||||
var server;
|
||||
var selectedPage;
|
||||
/* eslint-enable no-unused-vars */
|
||||
|
||||
var db;
|
||||
var designerTablesEnabled;
|
||||
@ -33,14 +30,16 @@ AJAX.registerOnload('designer/init.js', function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
jTabs = designerConfig.scriptTables.j_tabs;
|
||||
hTabs = designerConfig.scriptTables.h_tabs;
|
||||
contr = designerConfig.scriptContr;
|
||||
displayField = designerConfig.scriptDisplayField;
|
||||
|
||||
server = designerConfig.server;
|
||||
db = designerConfig.db;
|
||||
selectedPage = designerConfig.displayPage;
|
||||
/* eslint-enable no-unused-vars */
|
||||
|
||||
db = designerConfig.db;
|
||||
designerTablesEnabled = designerConfig.tablesEnabled;
|
||||
|
||||
DesignerMove.main();
|
||||
@ -54,15 +53,15 @@ AJAX.registerOnload('designer/init.js', function () {
|
||||
}
|
||||
|
||||
$('#query_Aggregate_Button').on('click', function () {
|
||||
document.getElementById('query_Aggregate').style.display = 'none';
|
||||
$('#query_Aggregate').style.display = 'none';
|
||||
});
|
||||
|
||||
$('#query_having_button').on('click', function () {
|
||||
document.getElementById('query_having').style.display = 'none';
|
||||
$('#query_having').style.display = 'none';
|
||||
});
|
||||
|
||||
$('#query_rename_to_button').on('click', function () {
|
||||
document.getElementById('query_rename_to').style.display = 'none';
|
||||
$('#query_rename_to').style.display = 'none';
|
||||
});
|
||||
|
||||
$('#build_query_button').on('click', function () {
|
||||
@ -70,6 +69,6 @@ AJAX.registerOnload('designer/init.js', function () {
|
||||
});
|
||||
|
||||
$('#query_where_button').on('click', function () {
|
||||
document.getElementById('query_where').style.display = 'none';
|
||||
$('#query_where').style.display = 'none';
|
||||
});
|
||||
});
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @package PhpMyAdmin-Designer
|
||||
*/
|
||||
@ -7,7 +6,7 @@
|
||||
/* global DesignerHistory, historyArray, selectField */ // js/designer/history.js
|
||||
/* global contr, db, designerTablesEnabled, displayField, hTabs, jTabs, selectedPage:writable, server */ // js/designer/init.js
|
||||
/* global DesignerPage */ // js/designer/page.js
|
||||
/* global pmaThemeImage */ // js/messages.php
|
||||
/* global themeImagePath */ // templates/javascript/variables.twig
|
||||
|
||||
var DesignerMove = {};
|
||||
|
||||
@ -551,7 +550,7 @@ DesignerMove.addTableToTablesList = function (index, tableDom) {
|
||||
' db="' + dbEncoded + '"' +
|
||||
' table_name="' + tableEncoded + '"' +
|
||||
' class="scroll_tab_struct"' +
|
||||
' src="' + pmaThemeImage + 'designer/exec.png"/>' +
|
||||
' src="' + themeImagePath + 'designer/exec.png"/>' +
|
||||
' </td>' +
|
||||
' <td width="1px">' +
|
||||
' <input class="scroll_tab_checkbox"' +
|
||||
@ -566,13 +565,13 @@ DesignerMove.addTableToTablesList = function (index, tableDom) {
|
||||
' designer_url_table_name="' + dbEncoded + '.' + tableEncoded + '">' + $('<div/>').text(db + '.' + table).html() + '</td>' +
|
||||
'</tr>');
|
||||
$('#id_scroll_tab table').first().append($newTableLine);
|
||||
$($newTableLine).find('.scroll_tab_struct').click(function () {
|
||||
$($newTableLine).find('.scroll_tab_struct').on('click', function () {
|
||||
DesignerMove.startTabUpd(db, table);
|
||||
});
|
||||
$($newTableLine).on('click', '.designer_Tabs2,.designer_Tabs', function () {
|
||||
DesignerMove.selectTab($(this).attr('designer_url_table_name'));
|
||||
});
|
||||
$($newTableLine).find('.scroll_tab_checkbox').click(function () {
|
||||
$($newTableLine).find('.scroll_tab_checkbox').on('click', function () {
|
||||
$(this).attr('title', function (i, currentvalue) {
|
||||
return currentvalue === Messages.strHide ? Messages.strShow : Messages.strHide;
|
||||
});
|
||||
@ -599,7 +598,7 @@ DesignerMove.addOtherDbTables = function () {
|
||||
return;
|
||||
}
|
||||
|
||||
$.post('db_designer.php', {
|
||||
$.post('index.php?route=/database/designer', {
|
||||
'ajax_request' : true,
|
||||
'dialog' : 'add_table',
|
||||
'db' : db,
|
||||
@ -632,7 +631,7 @@ DesignerMove.addOtherDbTables = function () {
|
||||
var $selectTable = $('<select id="add_table"></select>');
|
||||
$selectTable.append('<option value="">' + Messages.strNone + '</option>');
|
||||
|
||||
$.post('sql.php', {
|
||||
$.post('index.php?route=/sql', {
|
||||
'ajax_request' : true,
|
||||
'sql_query' : 'SHOW databases;',
|
||||
'server': CommonParams.get('server')
|
||||
@ -662,7 +661,7 @@ DesignerMove.addOtherDbTables = function () {
|
||||
if ($(this).val()) {
|
||||
var dbName = $(this).val();
|
||||
var sqlQuery = 'SHOW tables;';
|
||||
$.post('sql.php', {
|
||||
$.post('index.php?route=/sql', {
|
||||
'ajax_request' : true,
|
||||
'sql_query': sqlQuery,
|
||||
'db' : dbName,
|
||||
@ -699,7 +698,7 @@ DesignerMove.save = function (url) {
|
||||
document.getElementById('t_h_' + key + '_').value = document.getElementById('check_vis_' + key).checked ? 1 : 0;
|
||||
}
|
||||
document.getElementById('container-form').action = url;
|
||||
$('#container-form').submit();
|
||||
$('#container-form').trigger('submit');
|
||||
};
|
||||
|
||||
DesignerMove.getUrlPos = function (forceString) {
|
||||
@ -743,7 +742,7 @@ DesignerMove.save2 = function (callback) {
|
||||
poststr += DesignerMove.getUrlPos();
|
||||
|
||||
var $msgbox = Functions.ajaxShowMessage(Messages.strProcessingRequest);
|
||||
$.post('db_designer.php', poststr, function (data) {
|
||||
$.post('index.php?route=/database/designer', poststr, function (data) {
|
||||
if (data.success === false) {
|
||||
Functions.ajaxShowMessage(data.error, false);
|
||||
} else {
|
||||
@ -820,7 +819,7 @@ DesignerMove.save3 = function (callback) {
|
||||
$(this).dialog('close');
|
||||
};
|
||||
|
||||
var $form = $('<form action="db_designer.php" method="post" name="save_page" id="save_page" class="ajax"></form>')
|
||||
var $form = $('<form action="index.php?route=/database/designer" method="post" name="save_page" id="save_page" class="ajax"></form>')
|
||||
.append('<input type="hidden" name="server" value="' + server + '">')
|
||||
.append($('<input type="hidden" name="db" />').val(db))
|
||||
.append('<input type="hidden" name="operation" value="savePage">')
|
||||
@ -865,7 +864,7 @@ DesignerMove.editPages = function () {
|
||||
};
|
||||
|
||||
var $msgbox = Functions.ajaxShowMessage();
|
||||
$.post('db_designer.php', {
|
||||
$.post('index.php?route=/database/designer', {
|
||||
'ajax_request': true,
|
||||
'server': server,
|
||||
'db': db,
|
||||
@ -948,7 +947,7 @@ DesignerMove.deletePages = function () {
|
||||
};
|
||||
|
||||
var $msgbox = Functions.ajaxShowMessage();
|
||||
$.post('db_designer.php', {
|
||||
$.post('index.php?route=/database/designer', {
|
||||
'ajax_request': true,
|
||||
'server': server,
|
||||
'db': db,
|
||||
@ -1050,7 +1049,7 @@ DesignerMove.saveAs = function () {
|
||||
};
|
||||
|
||||
var $msgbox = Functions.ajaxShowMessage();
|
||||
$.post('db_designer.php', {
|
||||
$.post('index.php?route=/database/designer', {
|
||||
'ajax_request': true,
|
||||
'server': server,
|
||||
'db': db,
|
||||
@ -1131,7 +1130,7 @@ DesignerMove.exportPages = function () {
|
||||
var $msgbox = Functions.ajaxShowMessage();
|
||||
var argsep = CommonParams.get('arg_separator');
|
||||
|
||||
$.post('db_designer.php', {
|
||||
$.post('index.php?route=/database/designer', {
|
||||
'ajax_request': true,
|
||||
'server': server,
|
||||
'db': db,
|
||||
@ -1184,7 +1183,7 @@ DesignerMove.loadPage = function (page) {
|
||||
if (page !== null) {
|
||||
paramPage = argsep + 'page=' + page;
|
||||
}
|
||||
$('<a href="db_designer.php?server=' + server + argsep + 'db=' + encodeURIComponent(db) + paramPage + '"></a>')
|
||||
$('<a href="index.php?route=/database/designer&server=' + server + argsep + 'db=' + encodeURIComponent(db) + paramPage + '"></a>')
|
||||
.appendTo($('#page_content'))
|
||||
.trigger('click');
|
||||
} else {
|
||||
@ -1229,7 +1228,7 @@ DesignerMove.angularDirect = function () {
|
||||
};
|
||||
|
||||
DesignerMove.saveValueInConfig = function (indexSent, valueSent) {
|
||||
$.post('db_designer.php',
|
||||
$.post('index.php?route=/database/designer',
|
||||
{
|
||||
'operation': 'save_setting_value',
|
||||
'index': indexSent,
|
||||
@ -1332,7 +1331,7 @@ DesignerMove.clickField = function (db, T, f, pk) {
|
||||
document.getElementById('display_field_button').className = 'M_butt';
|
||||
|
||||
var $msgbox = Functions.ajaxShowMessage(Messages.strProcessingRequest);
|
||||
$.post('db_designer.php',
|
||||
$.post('index.php?route=/database/designer',
|
||||
{
|
||||
'operation': 'setDisplayField',
|
||||
'ajax_request': true,
|
||||
@ -1360,7 +1359,7 @@ DesignerMove.newRelation = function () {
|
||||
linkRelation += argsep + 'operation=addNewRelation' + argsep + 'ajax_request=true';
|
||||
|
||||
var $msgbox = Functions.ajaxShowMessage(Messages.strProcessingRequest);
|
||||
$.post('db_designer.php', linkRelation, function (data) {
|
||||
$.post('index.php?route=/database/designer', linkRelation, function (data) {
|
||||
if (data.success === false) {
|
||||
Functions.ajaxShowMessage(data.error, false);
|
||||
} else {
|
||||
@ -1373,13 +1372,13 @@ DesignerMove.newRelation = function () {
|
||||
// -------------------------- create tables -------------------------------------
|
||||
DesignerMove.startTableNew = function () {
|
||||
CommonParams.set('table', '');
|
||||
CommonActions.refreshMain('tbl_create.php');
|
||||
CommonActions.refreshMain('index.php?route=/table/create');
|
||||
};
|
||||
|
||||
DesignerMove.startTabUpd = function (db, table) {
|
||||
CommonParams.set('db', db);
|
||||
CommonParams.set('table', table);
|
||||
CommonActions.refreshMain('tbl_structure.php');
|
||||
CommonActions.refreshMain('index.php?route=/table/structure');
|
||||
};
|
||||
|
||||
// --------------------------- hide tables --------------------------------------
|
||||
@ -1589,7 +1588,7 @@ DesignerMove.updRelation = function () {
|
||||
linkRelation += argsep + 'operation=removeRelation' + argsep + 'ajax_request=true';
|
||||
|
||||
var $msgbox = Functions.ajaxShowMessage(Messages.strProcessingRequest);
|
||||
$.post('db_designer.php', linkRelation, function (data) {
|
||||
$.post('index.php?route=/database/designer', linkRelation, function (data) {
|
||||
if (data.success === false) {
|
||||
Functions.ajaxShowMessage(data.error, false);
|
||||
} else {
|
||||
@ -1619,7 +1618,8 @@ DesignerMove.hideTabAll = function (idThis) {
|
||||
idThis.src = idThis.dataset.down;
|
||||
}
|
||||
var E = document.getElementById('container-form');
|
||||
for (var i = 0; i < E.elements.length; i++) {
|
||||
var EelementsLength = E.elements.length;
|
||||
for (var i = 0; i < EelementsLength; i++) {
|
||||
if (E.elements[i].type === 'checkbox' && E.elements[i].id.substring(0, 10) === 'check_vis_') {
|
||||
if (idThis.alt === 'v') {
|
||||
E.elements[i].checked = true;
|
||||
@ -1671,7 +1671,8 @@ DesignerMove.noHaveConstr = function (idThis) {
|
||||
idThis.src = idThis.dataset.down;
|
||||
}
|
||||
var E = document.getElementById('container-form');
|
||||
for (var i = 0; i < E.elements.length; i++) {
|
||||
var EelementsLength = E.elements.length;
|
||||
for (var i = 0; i < EelementsLength; i++) {
|
||||
if (E.elements[i].type === 'checkbox' && E.elements[i].id.substring(0, 10) === 'check_vis_') {
|
||||
if (!DesignerMove.inArrayK(E.elements[i].value, a)) {
|
||||
if (idThis.alt === 'v') {
|
||||
@ -2034,16 +2035,16 @@ DesignerMove.enableTableEvents = function (index, element) {
|
||||
DesignerMove.clickField(params[3], params[0], params[1], params[2]);
|
||||
});
|
||||
|
||||
$(element).find('.tab_zag_noquery').mouseover(function () {
|
||||
$(element).find('.tab_zag_noquery').on('mouseover', function () {
|
||||
DesignerMove.tableOnOver($(this).attr('table_name'),0, $(this).attr('query_set'));
|
||||
});
|
||||
$(element).find('.tab_zag_noquery').mouseout(function () {
|
||||
$(element).find('.tab_zag_noquery').on('mouseout', function () {
|
||||
DesignerMove.tableOnOver($(this).attr('table_name'),1, $(this).attr('query_set'));
|
||||
});
|
||||
$(element).find('.tab_zag_query').mouseover(function () {
|
||||
$(element).find('.tab_zag_query').on('mouseover', function () {
|
||||
DesignerMove.tableOnOver($(this).attr('table_name'),0, 1);
|
||||
});
|
||||
$(element).find('.tab_zag_query').mouseout(function () {
|
||||
$(element).find('.tab_zag_query').on('mouseout', function () {
|
||||
DesignerMove.tableOnOver($(this).attr('table_name'),1, 1);
|
||||
});
|
||||
|
||||
@ -2127,6 +2128,11 @@ AJAX.registerOnload('designer/move.js', function () {
|
||||
});
|
||||
$('#SaveAs').on('click', function () {
|
||||
DesignerMove.saveAs();
|
||||
$(document).on('ajaxStop', function () {
|
||||
$('#selected_value').on('click', function () {
|
||||
$('#savePageNewRadio').prop('checked', true);
|
||||
});
|
||||
});
|
||||
return false;
|
||||
});
|
||||
$('#delPages').on('click', function () {
|
||||
@ -2179,10 +2185,11 @@ AJAX.registerOnload('designer/move.js', function () {
|
||||
DesignerMove.sideMenuRight(this);
|
||||
return false;
|
||||
});
|
||||
$('#side_menu').hover(function () {
|
||||
$('#side_menu').on('mouseenter', function () {
|
||||
DesignerMove.showText();
|
||||
return false;
|
||||
}, function () {
|
||||
});
|
||||
$('#side_menu').on('mouseleave', function () {
|
||||
DesignerMove.hideText();
|
||||
return false;
|
||||
});
|
||||
@ -2205,7 +2212,7 @@ AJAX.registerOnload('designer/move.js', function () {
|
||||
$('.designer_tab').each(DesignerMove.enableTableEvents);
|
||||
$('.designer_tab').each(DesignerMove.addTableToTablesList);
|
||||
|
||||
$('input#del_button').click(function () {
|
||||
$('input#del_button').on('click', function () {
|
||||
DesignerMove.updRelation();
|
||||
});
|
||||
$('input#cancel_button').on('click', function () {
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
/* This script handles PMA Drag Drop Import, loaded only when configuration is enabled.*/
|
||||
|
||||
@ -16,15 +15,15 @@ var DragDropImport = {
|
||||
*/
|
||||
liveUploadCount: 0,
|
||||
/**
|
||||
* @var string array, allowed extensions
|
||||
* @var string array, allowed extensions
|
||||
*/
|
||||
allowedExtensions: ['sql', 'xml', 'ldi', 'mediawiki', 'shp'],
|
||||
/**
|
||||
* @var string array, allowed extensions for compressed files
|
||||
* @var string array, allowed extensions for compressed files
|
||||
*/
|
||||
allowedCompressedExtensions: ['gz', 'bz2', 'zip'],
|
||||
/**
|
||||
* @var obj array to store message returned by import_status.php
|
||||
* @var obj array to store message returned by /import-status
|
||||
*/
|
||||
importStatus: [],
|
||||
/**
|
||||
@ -72,7 +71,6 @@ var DragDropImport = {
|
||||
* @return void
|
||||
*/
|
||||
sendFileToServer: function (formData, hash) {
|
||||
var uploadURL = './import.php'; // Upload URL
|
||||
var jqXHR = $.ajax({
|
||||
xhr: function () {
|
||||
var xhrobj = $.ajaxSettings.xhr();
|
||||
@ -90,7 +88,7 @@ var DragDropImport = {
|
||||
}
|
||||
return xhrobj;
|
||||
},
|
||||
url: uploadURL,
|
||||
url: 'index.php?route=/import',
|
||||
type: 'POST',
|
||||
contentType:false,
|
||||
processData: false,
|
||||
@ -365,7 +363,7 @@ $(document).on('dragleave', '.pma_drop_handler', DragDropImport.dragLeave);
|
||||
// when file is dropped to PMA UI
|
||||
$(document).on('drop', 'body', DragDropImport.drop);
|
||||
|
||||
// minimizing-maximising the sql ajax upload status
|
||||
// minimizing-maximizing the sql ajax upload status
|
||||
$(document).on('click', '.pma_sql_import_status h2 .minimize', function () {
|
||||
if ($(this).attr('toggle') === 'off') {
|
||||
$('.pma_sql_import_status div').css('height','270px');
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
/* global TraceKit */ // js/vendor/tracekit.js
|
||||
|
||||
@ -25,7 +24,7 @@ var ErrorReport = {
|
||||
exception.name = ErrorReport.extractExceptionName(exception);
|
||||
}
|
||||
ErrorReport.lastException = exception;
|
||||
$.post('error_report.php', {
|
||||
$.post('index.php?route=/error-report', {
|
||||
'ajax_request': true,
|
||||
'server': CommonParams.get('server'),
|
||||
'get_settings': true,
|
||||
@ -43,7 +42,7 @@ var ErrorReport = {
|
||||
'send_error_report': true,
|
||||
'automatic': true
|
||||
});
|
||||
$.post('error_report.php', postData, function (data) {
|
||||
$.post('index.php?route=/error-report', postData, function (data) {
|
||||
if (data.success === false) {
|
||||
// in the case of an error, show the error message returned.
|
||||
Functions.ajaxShowMessage(data.error, false);
|
||||
@ -80,7 +79,7 @@ var ErrorReport = {
|
||||
'description': $('#report_description').val(),
|
||||
'always_send': $('#always_send_checkbox')[0].checked
|
||||
});
|
||||
$.post('error_report.php', postData, function (data) {
|
||||
$.post('index.php?route=/error-report', postData, function (data) {
|
||||
$dialog.dialog('close');
|
||||
if (data.success === false) {
|
||||
// in the case of an error, show the error message returned.
|
||||
@ -95,7 +94,7 @@ var ErrorReport = {
|
||||
$(this).dialog('close');
|
||||
};
|
||||
|
||||
$.post('error_report.php', reportData, function (data) {
|
||||
$.post('index.php?route=/error-report', reportData, function (data) {
|
||||
if (data.success === false) {
|
||||
// in the case of an error, show the error message returned.
|
||||
Functions.ajaxShowMessage(data.error, false);
|
||||
@ -124,8 +123,7 @@ var ErrorReport = {
|
||||
ErrorReport.removeErrorNotification();
|
||||
|
||||
var $div = $(
|
||||
'<div style="position:fixed;bottom:0;left:0;right:0;margin:0;' +
|
||||
'z-index:1000" class="error" id="error_notification"></div>'
|
||||
'<div class="alert alert-danger userPermissionModal" role="alert" id="error_notification"></div>'
|
||||
).append(
|
||||
Functions.getImage('s_error') + Messages.strErrorOccurred
|
||||
);
|
||||
@ -200,7 +198,7 @@ var ErrorReport = {
|
||||
* @return void
|
||||
*/
|
||||
redirectToSettings: function () {
|
||||
window.location.href = 'prefs_forms.php';
|
||||
window.location.href = 'index.php?route=/preferences/features';
|
||||
},
|
||||
/**
|
||||
* Returns the report data to send to the server
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Functions used in the export tab
|
||||
*
|
||||
@ -33,12 +32,12 @@ Export.enableDumpSomeRowsSubOptions = function () {
|
||||
*/
|
||||
Export.getTemplateData = function () {
|
||||
var $form = $('form[name="dump"]');
|
||||
var blacklist = ['token', 'server', 'db', 'table', 'single_table',
|
||||
var excludeList = ['token', 'server', 'db', 'table', 'single_table',
|
||||
'export_type', 'export_method', 'sql_query', 'template_id'];
|
||||
var obj = {};
|
||||
var arr = $form.serializeArray();
|
||||
$.each(arr, function () {
|
||||
if ($.inArray(this.name, blacklist) < 0) {
|
||||
if ($.inArray(this.name, excludeList) < 0) {
|
||||
if (obj[this.name] !== undefined) {
|
||||
if (! obj[this.name].push) {
|
||||
obj[this.name] = [obj[this.name]];
|
||||
@ -49,7 +48,7 @@ Export.getTemplateData = function () {
|
||||
}
|
||||
}
|
||||
});
|
||||
// include unchecked checboxes (which are ignored by serializeArray()) with null
|
||||
// include unchecked checkboxes (which are ignored by serializeArray()) with null
|
||||
// to uncheck them when loading the template
|
||||
$form.find('input[type="checkbox"]:not(:checked)').each(function () {
|
||||
if (obj[this.name] === undefined) {
|
||||
@ -79,13 +78,12 @@ Export.createTemplate = function (name) {
|
||||
'db': CommonParams.get('db'),
|
||||
'table': CommonParams.get('table'),
|
||||
'exportType': $('input[name="export_type"]').val(),
|
||||
'templateAction': 'create',
|
||||
'templateName': name,
|
||||
'templateData': JSON.stringify(templateData)
|
||||
};
|
||||
|
||||
Functions.ajaxShowMessage();
|
||||
$.post('tbl_export.php', params, function (response) {
|
||||
$.post('index.php?route=/export/template/create', params, function (response) {
|
||||
if (response.success === true) {
|
||||
$('#templateName').val('');
|
||||
$('#template').html(response.data);
|
||||
@ -113,12 +111,11 @@ Export.loadTemplate = function (id) {
|
||||
'db': CommonParams.get('db'),
|
||||
'table': CommonParams.get('table'),
|
||||
'exportType': $('input[name="export_type"]').val(),
|
||||
'templateAction': 'load',
|
||||
'templateId': id,
|
||||
};
|
||||
|
||||
Functions.ajaxShowMessage();
|
||||
$.post('tbl_export.php', params, function (response) {
|
||||
$.post('index.php?route=/export/template/load', params, function (response) {
|
||||
if (response.success === true) {
|
||||
var $form = $('form[name="dump"]');
|
||||
var options = JSON.parse(response.data);
|
||||
@ -163,13 +160,12 @@ Export.updateTemplate = function (id) {
|
||||
'db': CommonParams.get('db'),
|
||||
'table': CommonParams.get('table'),
|
||||
'exportType': $('input[name="export_type"]').val(),
|
||||
'templateAction': 'update',
|
||||
'templateId': id,
|
||||
'templateData': JSON.stringify(templateData)
|
||||
};
|
||||
|
||||
Functions.ajaxShowMessage();
|
||||
$.post('tbl_export.php', params, function (response) {
|
||||
$.post('index.php?route=/export/template/update', params, function (response) {
|
||||
if (response.success === true) {
|
||||
Functions.ajaxShowMessage(Messages.strTemplateUpdated);
|
||||
} else {
|
||||
@ -190,12 +186,11 @@ Export.deleteTemplate = function (id) {
|
||||
'db': CommonParams.get('db'),
|
||||
'table': CommonParams.get('table'),
|
||||
'exportType': $('input[name="export_type"]').val(),
|
||||
'templateAction': 'delete',
|
||||
'templateId': id,
|
||||
};
|
||||
|
||||
Functions.ajaxShowMessage();
|
||||
$.post('tbl_export.php', params, function (response) {
|
||||
$.post('index.php?route=/export/template/delete', params, function (response) {
|
||||
if (response.success === true) {
|
||||
$('#template').find('option[value="' + id + '"]').remove();
|
||||
Functions.ajaxShowMessage(Messages.strTemplateDeleted);
|
||||
@ -233,6 +228,27 @@ AJAX.registerTeardown('export.js', function () {
|
||||
});
|
||||
|
||||
AJAX.registerOnload('export.js', function () {
|
||||
$('#showsqlquery').on('click', function () {
|
||||
// Creating a dialog box similar to preview sql container to show sql query
|
||||
var modalOptions = {};
|
||||
modalOptions[Messages.strClose] = function () {
|
||||
$(this).dialog('close');
|
||||
};
|
||||
$('#export_sql_modal_content').clone().dialog({
|
||||
minWidth: 550,
|
||||
maxHeight: 400,
|
||||
modal: true,
|
||||
buttons: modalOptions,
|
||||
title: Messages.strQuery,
|
||||
close: function () {
|
||||
$(this).remove();
|
||||
}, open: function () {
|
||||
// Pretty SQL printing.
|
||||
Functions.highlightSql($(this));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Export template handling code
|
||||
*/
|
||||
@ -254,7 +270,7 @@ AJAX.registerOnload('export.js', function () {
|
||||
}
|
||||
});
|
||||
|
||||
// udpate an existing template with new criteria
|
||||
// update an existing template with new criteria
|
||||
$('input[name="updateTemplate"]').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
var id = $('select[name="template"]').val();
|
||||
@ -312,7 +328,7 @@ AJAX.registerOnload('export.js', function () {
|
||||
});
|
||||
|
||||
// When MS Excel is selected as the Format automatically Switch to Character Set as windows-1252
|
||||
$('#plugins').change(function () {
|
||||
$('#plugins').on('change', function () {
|
||||
var selectedPluginName = $('#plugins').find('option:selected').val();
|
||||
if (selectedPluginName === 'excel') {
|
||||
$('#select_charset').val('windows-1252');
|
||||
@ -382,7 +398,7 @@ Export.setupTableStructureOrData = function () {
|
||||
|
||||
Export.checkSelectedTables();
|
||||
Export.checkTableSelectAll();
|
||||
Export.checkTableSelectStrutureOrData();
|
||||
Export.checkTableSelectStructureOrData();
|
||||
}
|
||||
};
|
||||
|
||||
@ -489,7 +505,7 @@ Export.checkTableSelectAll = function () {
|
||||
}
|
||||
};
|
||||
|
||||
Export.checkTableSelectStrutureOrData = function () {
|
||||
Export.checkTableSelectStructureOrData = function () {
|
||||
var strChecked = $('input[name="table_structure[]"]:checked').length;
|
||||
var dataChecked = $('input[name="table_data[]"]:checked').length;
|
||||
var autoIncrement = $('#checkbox_sql_auto_increment');
|
||||
@ -621,35 +637,35 @@ AJAX.registerOnload('export.js', function () {
|
||||
Export.toggleTableSelect($(this).closest('tr'));
|
||||
Export.checkTableSelectAll();
|
||||
Export.handleAddProcCheckbox();
|
||||
Export.checkTableSelectStrutureOrData();
|
||||
Export.checkTableSelectStructureOrData();
|
||||
});
|
||||
|
||||
$('input[name="table_structure[]"]').on('change', function () {
|
||||
Export.checkTableSelected($(this).closest('tr'));
|
||||
Export.checkTableSelectAll();
|
||||
Export.handleAddProcCheckbox();
|
||||
Export.checkTableSelectStrutureOrData();
|
||||
Export.checkTableSelectStructureOrData();
|
||||
});
|
||||
|
||||
$('input[name="table_data[]"]').on('change', function () {
|
||||
Export.checkTableSelected($(this).closest('tr'));
|
||||
Export.checkTableSelectAll();
|
||||
Export.handleAddProcCheckbox();
|
||||
Export.checkTableSelectStrutureOrData();
|
||||
Export.checkTableSelectStructureOrData();
|
||||
});
|
||||
|
||||
$('#table_structure_all').on('change', function () {
|
||||
Export.toggleTableSelectAllStr();
|
||||
Export.checkSelectedTables();
|
||||
Export.handleAddProcCheckbox();
|
||||
Export.checkTableSelectStrutureOrData();
|
||||
Export.checkTableSelectStructureOrData();
|
||||
});
|
||||
|
||||
$('#table_data_all').on('change', function () {
|
||||
Export.toggleTableSelectAllData();
|
||||
Export.checkSelectedTables();
|
||||
Export.handleAddProcCheckbox();
|
||||
Export.checkTableSelectStrutureOrData();
|
||||
Export.checkTableSelectStructureOrData();
|
||||
});
|
||||
|
||||
if ($('input[name=\'export_type\']').val() === 'database') {
|
||||
@ -728,17 +744,12 @@ Export.checkTimeOut = function (timeLimit) {
|
||||
}
|
||||
// margin of one second to avoid race condition to set/access session variable
|
||||
limit = limit + 1;
|
||||
var href = 'export.php';
|
||||
var params = {
|
||||
'ajax_request' : true,
|
||||
'check_time_out' : true
|
||||
};
|
||||
clearTimeout(timeOut);
|
||||
timeOut = setTimeout(function () {
|
||||
$.get(href, params, function (data) {
|
||||
$.get('index.php?route=/export/check-time-out', { 'ajax_request': true }, function (data) {
|
||||
if (data.message === 'timeout') {
|
||||
Functions.ajaxShowMessage(
|
||||
'<div class="error">' +
|
||||
'<div class="alert alert-danger" role="alert">' +
|
||||
Messages.strTimeOutError +
|
||||
'</div>',
|
||||
false
|
||||
@ -816,10 +827,9 @@ Export.createAliasModal = function (event) {
|
||||
} else {
|
||||
var params = {
|
||||
'ajax_request': true,
|
||||
'server': CommonParams.get('server'),
|
||||
'type': 'list-databases'
|
||||
'server': CommonParams.get('server')
|
||||
};
|
||||
$.post('ajax.php', params, function (response) {
|
||||
$.post('index.php?route=/databases', params, function (response) {
|
||||
if (response.success === true) {
|
||||
$.each(response.databases, function (idx, value) {
|
||||
var option = $('<option></option>');
|
||||
@ -859,14 +869,19 @@ Export.aliasToggleRow = function (elm) {
|
||||
}
|
||||
};
|
||||
|
||||
Export.aliasRow = null;
|
||||
|
||||
Export.addAlias = function (type, name, field, value) {
|
||||
if (value === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
var row = $('#alias_data tfoot tr').clone();
|
||||
if (Export.aliasRow === null) {
|
||||
Export.aliasRow = $('#alias_data tfoot tr');
|
||||
}
|
||||
var row = Export.aliasRow.clone();
|
||||
row.find('th').text(type);
|
||||
row.find('td:first').text(name);
|
||||
row.find('td').first().text(name);
|
||||
row.find('input').attr('name', field);
|
||||
row.find('input').val(value);
|
||||
row.find('.alias_remove').on('click', function () {
|
||||
@ -930,13 +945,14 @@ AJAX.registerOnload('export.js', function () {
|
||||
option.attr('value', table);
|
||||
$('#table_alias_select').append(option).val(table).trigger('change');
|
||||
} else {
|
||||
var database = $(this).val();
|
||||
var params = {
|
||||
'ajax_request': true,
|
||||
'server': CommonParams.get('server'),
|
||||
'db': $(this).val(),
|
||||
'type': 'list-tables'
|
||||
'db': database,
|
||||
};
|
||||
$.post('ajax.php', params, function (response) {
|
||||
var url = 'index.php?route=/tables';
|
||||
$.post(url, params, function (response) {
|
||||
if (response.success === true) {
|
||||
$.each(response.tables, function (idx, value) {
|
||||
var option = $('<option></option>');
|
||||
@ -952,14 +968,16 @@ AJAX.registerOnload('export.js', function () {
|
||||
});
|
||||
$('#table_alias_select').on('change', function () {
|
||||
Export.aliasToggleRow($(this));
|
||||
var database = $('#db_alias_select').val();
|
||||
var table = $(this).val();
|
||||
var params = {
|
||||
'ajax_request': true,
|
||||
'server': CommonParams.get('server'),
|
||||
'db': $('#db_alias_select').val(),
|
||||
'table': $(this).val(),
|
||||
'type': 'list-columns'
|
||||
'db': database,
|
||||
'table': table,
|
||||
};
|
||||
$.post('ajax.php', params, function (response) {
|
||||
var url = 'index.php?route=/columns';
|
||||
$.post(url, params, function (response) {
|
||||
if (response.success === true) {
|
||||
$.each(response.columns, function (idx, value) {
|
||||
var option = $('<option></option>');
|
||||
@ -1011,4 +1029,28 @@ AJAX.registerOnload('export.js', function () {
|
||||
);
|
||||
$('#column_alias_name').val('');
|
||||
});
|
||||
|
||||
var setSelectOptions = function (doCheck) {
|
||||
Functions.setSelectOptions('dump', 'db_select[]', doCheck);
|
||||
};
|
||||
|
||||
$('#db_select_all').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
setSelectOptions(true);
|
||||
});
|
||||
|
||||
$('#db_unselect_all').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
setSelectOptions(false);
|
||||
});
|
||||
|
||||
$('#buttonGo').on('click', function () {
|
||||
var timeLimit = parseInt($(this).attr('data-exec-time-limit'));
|
||||
|
||||
// If the time limit set is zero,
|
||||
// then time out won't occur so no need to check for time out.
|
||||
if (timeLimit > 0) {
|
||||
Export.checkTimeOut(timeLimit);
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
AJAX.registerOnload('export_output.js', function () {
|
||||
$(document).on('keydown', function (e) {
|
||||
if ((e.which || e.keyCode) === 116) {
|
||||
@ -6,4 +5,9 @@ AJAX.registerOnload('export_output.js', function () {
|
||||
$('#export_refresh_form').trigger('submit');
|
||||
}
|
||||
});
|
||||
|
||||
$('#export_refresh_btn').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$('#export_refresh_form').trigger('submit');
|
||||
});
|
||||
});
|
||||
@ -1,15 +1,13 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
/* global isStorageSupported */ // js/config.js
|
||||
/* global ChartType, ColumnType, DataTable, JQPlotChartFactory */ // js/chart.js
|
||||
/* global DatabaseStructure */ // js/database/structure.js
|
||||
/* global mysqlDocBuiltin, mysqlDocKeyword */ // js/doclinks.js
|
||||
/* global Indexes */ // js/indexes.js
|
||||
/* global maxInputVars, mysqlDocTemplate, pmaThemeImage */ // js/messages.php
|
||||
/* global firstDayOfCalendar, maxInputVars, mysqlDocTemplate, themeImagePath */ // templates/javascript/variables.twig
|
||||
/* global MicroHistory */ // js/microhistory.js
|
||||
/* global checkPasswordStrength */ // js/server/privileges.js
|
||||
/* global sprintf */ // js/vendor/sprintf.js
|
||||
/* global Int32Array */ // ES6
|
||||
/* global zxcvbn */ // js/vendor/zxcvbn.js
|
||||
|
||||
/**
|
||||
* general function, usually for data manipulation pages
|
||||
@ -20,7 +18,6 @@ var Functions = {};
|
||||
/**
|
||||
* @var sqlBoxLocked lock for the sqlbox textarea in the querybox
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
var sqlBoxLocked = false;
|
||||
|
||||
/**
|
||||
@ -130,7 +127,7 @@ Functions.addDatepicker = function ($thisElement, type, options) {
|
||||
minute: currentDateTime.getMinutes(),
|
||||
second: currentDateTime.getSeconds(),
|
||||
showOn: 'button',
|
||||
buttonImage: pmaThemeImage + 'b_calendar.png',
|
||||
buttonImage: themeImagePath + 'b_calendar.png',
|
||||
buttonImageOnly: true,
|
||||
stepMinutes: 1,
|
||||
stepHours: 1,
|
||||
@ -139,6 +136,7 @@ Functions.addDatepicker = function ($thisElement, type, options) {
|
||||
showMicrosec: true,
|
||||
showTimepicker: showTimepicker,
|
||||
showButtonPanel: false,
|
||||
changeYear: true,
|
||||
dateFormat: 'yy-mm-dd', // yy means year with four digits
|
||||
timeFormat: 'HH:mm:ss.lc',
|
||||
constrainInput: false,
|
||||
@ -226,7 +224,8 @@ Functions.addDateTimePicker = function () {
|
||||
showMillisec: showMillisec,
|
||||
showMicrosec: showMicrosec,
|
||||
timeFormat: timeFormat,
|
||||
hourMax: hourMax
|
||||
hourMax: hourMax,
|
||||
firstDay: firstDayOfCalendar
|
||||
});
|
||||
// Add a tip regarding entering MySQL allowed-values
|
||||
// for TIME and DATE data-type
|
||||
@ -431,7 +430,7 @@ Functions.sprintf = function () {
|
||||
*/
|
||||
Functions.hideShowDefaultValue = function ($defaultType) {
|
||||
if ($defaultType.val() === 'USER_DEFINED') {
|
||||
$defaultType.siblings('.default_value').show().focus();
|
||||
$defaultType.siblings('.default_value').show().trigger('focus');
|
||||
} else {
|
||||
$defaultType.siblings('.default_value').hide();
|
||||
if ($defaultType.val() === 'NULL') {
|
||||
@ -483,6 +482,36 @@ Functions.prepareForAjaxRequest = function ($form) {
|
||||
}
|
||||
};
|
||||
|
||||
Functions.checkPasswordStrength = function (value, meterObject, meterObjectLabel, username) {
|
||||
// List of words we don't want to appear in the password
|
||||
var customDict = [
|
||||
'phpmyadmin',
|
||||
'mariadb',
|
||||
'mysql',
|
||||
'php',
|
||||
'my',
|
||||
'admin',
|
||||
];
|
||||
if (username !== null) {
|
||||
customDict.push(username);
|
||||
}
|
||||
var zxcvbnObject = zxcvbn(value, customDict);
|
||||
var strength = zxcvbnObject.score;
|
||||
strength = parseInt(strength);
|
||||
meterObject.val(strength);
|
||||
switch (strength) {
|
||||
case 0: meterObjectLabel.html(Messages.strExtrWeak);
|
||||
break;
|
||||
case 1: meterObjectLabel.html(Messages.strVeryWeak);
|
||||
break;
|
||||
case 2: meterObjectLabel.html(Messages.strWeak);
|
||||
break;
|
||||
case 3: meterObjectLabel.html(Messages.strGood);
|
||||
break;
|
||||
case 4: meterObjectLabel.html(Messages.strStrong);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a new password and copy it to the password input areas
|
||||
*
|
||||
@ -494,9 +523,10 @@ Functions.suggestPassword = function (passwordForm) {
|
||||
// restrict the password to just letters and numbers to avoid problems:
|
||||
// "editors and viewers regard the password as multiple words and
|
||||
// things like double click no longer work"
|
||||
var pwchars = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWYXZ';
|
||||
var pwchars = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWYXZ@!_.*/()[]-';
|
||||
var passwordlength = 16; // do we want that to be dynamic? no, keep it simple :)
|
||||
var passwd = passwordForm.generated_pw;
|
||||
// eslint-disable-next-line compat/compat
|
||||
var randomWords = new Int32Array(passwordlength);
|
||||
|
||||
passwd.value = '';
|
||||
@ -504,7 +534,9 @@ Functions.suggestPassword = function (passwordForm) {
|
||||
var i;
|
||||
|
||||
// First we're going to try to use a built-in CSPRNG
|
||||
// eslint-disable-next-line compat/compat
|
||||
if (window.crypto && window.crypto.getRandomValues) {
|
||||
// eslint-disable-next-line compat/compat
|
||||
window.crypto.getRandomValues(randomWords);
|
||||
} else if (window.msCrypto && window.msCrypto.getRandomValues) {
|
||||
// Because of course IE calls it msCrypto instead of being standard
|
||||
@ -526,7 +558,7 @@ Functions.suggestPassword = function (passwordForm) {
|
||||
passwordForm.elements.pma_pw2.value = passwd.value;
|
||||
var meterObj = $jQueryPasswordForm.find('meter[name="pw_meter"]').first();
|
||||
var meterObjLabel = $jQueryPasswordForm.find('span[name="pw_strength"]').first();
|
||||
checkPasswordStrength(passwd.value, meterObj, meterObjLabel);
|
||||
Functions.checkPasswordStrength(passwd.value, meterObj, meterObjLabel);
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -559,7 +591,7 @@ Functions.parseVersionString = function (str) {
|
||||
var min = parseInt(x[1], 10) || 0;
|
||||
var pat = parseInt(x[2], 10) || 0;
|
||||
var hotfix = parseInt(x[3], 10) || 0;
|
||||
return maj * 100000000 + min * 1000000 + pat * 10000 + hotfix * 100 + add;
|
||||
return maj * 100000000 + min * 1000000 + pat * 10000 + hotfix * 100 + add;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -586,10 +618,10 @@ Functions.currentVersion = function (data) {
|
||||
Functions.escapeHtml(data.version),
|
||||
Functions.escapeHtml(data.date)
|
||||
);
|
||||
var htmlClass = 'notice';
|
||||
var htmlClass = 'alert alert-primary';
|
||||
if (Math.floor(latest / 10000) === Math.floor(current / 10000)) {
|
||||
/* Security update */
|
||||
htmlClass = 'error';
|
||||
htmlClass = 'alert alert-danger';
|
||||
}
|
||||
$('#newer_version_notice').remove();
|
||||
var mainContainerDiv = document.createElement('div');
|
||||
@ -609,7 +641,7 @@ Functions.currentVersion = function (data) {
|
||||
/* Remove extra whitespace */
|
||||
var versionInfo = $('#li_pma_version').contents().get(2);
|
||||
if (typeof versionInfo !== 'undefined') {
|
||||
versionInfo.textContent = $.trim(versionInfo.textContent);
|
||||
versionInfo.textContent = versionInfo.textContent.trim();
|
||||
}
|
||||
var $liPmaVersion = $('#li_pma_version');
|
||||
$liPmaVersion.find('span.latest').remove();
|
||||
@ -624,10 +656,9 @@ Functions.displayGitRevision = function () {
|
||||
$('#is_git_revision').remove();
|
||||
$('#li_pma_version_git').remove();
|
||||
$.get(
|
||||
'index.php',
|
||||
'index.php?route=/git-revision',
|
||||
{
|
||||
'server': CommonParams.get('server'),
|
||||
'git_revision': true,
|
||||
'ajax_request': true,
|
||||
'no_debug': true
|
||||
},
|
||||
@ -640,9 +671,7 @@ Functions.displayGitRevision = function () {
|
||||
};
|
||||
|
||||
/**
|
||||
* for PhpMyAdmin\Display\ChangePassword
|
||||
* libraries/user_password.php
|
||||
*
|
||||
* for PhpMyAdmin\Display\ChangePassword and /user-password
|
||||
*/
|
||||
Functions.displayPasswordGenerateButton = function () {
|
||||
var generatePwdRow = $('<tr></tr>').addClass('vmiddle');
|
||||
@ -857,14 +886,14 @@ Functions.emptyCheckTheField = function (theForm, theFieldName) {
|
||||
Functions.checkFormElementInRange = function (theForm, theFieldName, message, minimum, maximum) {
|
||||
var theField = theForm.elements[theFieldName];
|
||||
var val = parseInt(theField.value, 10);
|
||||
var min = minimum;
|
||||
var max = maximum;
|
||||
var min = 0;
|
||||
var max = Number.MAX_VALUE;
|
||||
|
||||
if (typeof(min) === 'undefined') {
|
||||
min = 0;
|
||||
if (typeof(minimum) !== 'undefined') {
|
||||
min = minimum;
|
||||
}
|
||||
if (typeof(max) === 'undefined') {
|
||||
max = Number.MAX_VALUE;
|
||||
if (typeof(maximum) !== 'undefined' && maximum !== null) {
|
||||
max = maximum;
|
||||
}
|
||||
|
||||
if (isNaN(val)) {
|
||||
@ -929,7 +958,7 @@ Functions.checkTableEditForm = function (theForm, fieldsCnt) {
|
||||
var $input = $('input.textfield[name=\'table\']');
|
||||
if ($input.val() === '') {
|
||||
alert(Messages.strFormEmpty);
|
||||
$input.focus();
|
||||
$input.trigger('focus');
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -985,7 +1014,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
idleSecondsCounter++;
|
||||
}
|
||||
function UpdateIdleTime () {
|
||||
var href = 'index.php';
|
||||
var href = 'index.php?route=/';
|
||||
var guid = 'default';
|
||||
if (isStorageSupported('sessionStorage')) {
|
||||
guid = window.sessionStorage.guid;
|
||||
@ -1085,9 +1114,9 @@ AJAX.registerOnload('functions.js', function () {
|
||||
var checked = $this.prop('checked');
|
||||
$checkbox.prop('checked', checked).trigger('change');
|
||||
if (checked) {
|
||||
$tr.addClass('marked');
|
||||
$tr.addClass('marked table-active');
|
||||
} else {
|
||||
$tr.removeClass('marked');
|
||||
$tr.removeClass('marked table-active');
|
||||
}
|
||||
lastClickChecked = checked;
|
||||
|
||||
@ -1111,7 +1140,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
}
|
||||
$tr.parent().find('tr:not(.noclick)')
|
||||
.slice(start, end + 1)
|
||||
.removeClass('marked')
|
||||
.removeClass('marked table-active')
|
||||
.find(':checkbox')
|
||||
.prop('checked', false)
|
||||
.trigger('change');
|
||||
@ -1128,7 +1157,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
}
|
||||
$tr.parent().find('tr:not(.noclick)')
|
||||
.slice(start, end + 1)
|
||||
.addClass('marked')
|
||||
.addClass('marked table-active')
|
||||
.find(':checkbox')
|
||||
.prop('checked', true)
|
||||
.trigger('change');
|
||||
@ -1212,6 +1241,7 @@ Functions.handleSimulateQueryButton = function () {
|
||||
*
|
||||
*/
|
||||
Functions.insertQuery = function (queryType) {
|
||||
var table;
|
||||
if (queryType === 'clear') {
|
||||
Functions.setQuery('');
|
||||
return;
|
||||
@ -1219,8 +1249,7 @@ Functions.insertQuery = function (queryType) {
|
||||
if (codeMirrorEditor) {
|
||||
$('#querymessage').html(Messages.strFormatting +
|
||||
' <img class="ajaxIcon" src="' +
|
||||
pmaThemeImage + 'ajax_clock_small.gif" alt="">');
|
||||
var href = 'db_sql_format.php';
|
||||
themeImagePath + 'ajax_clock_small.gif" alt="">');
|
||||
var params = {
|
||||
'ajax_request': true,
|
||||
'sql': codeMirrorEditor.getValue(),
|
||||
@ -1228,7 +1257,7 @@ Functions.insertQuery = function (queryType) {
|
||||
};
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: href,
|
||||
url: 'index.php?route=/database/sql/format',
|
||||
data: params,
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
@ -1240,10 +1269,18 @@ Functions.insertQuery = function (queryType) {
|
||||
}
|
||||
return;
|
||||
} else if (queryType === 'saved') {
|
||||
if (isStorageSupported('localStorage') && typeof window.localStorage.autoSavedSql !== 'undefined') {
|
||||
Functions.setQuery(window.localStorage.autoSavedSql);
|
||||
} else if (Cookies.get('autoSavedSql')) {
|
||||
Functions.setQuery(Cookies.get('autoSavedSql'));
|
||||
var db = $('input[name="db"]').val();
|
||||
table = $('input[name="table"]').val();
|
||||
var key = db;
|
||||
if (table !== undefined) {
|
||||
key += '.' + table;
|
||||
}
|
||||
key = 'autoSavedSql_' + key;
|
||||
if (isStorageSupported('localStorage') &&
|
||||
typeof window.localStorage.getItem(key) === 'string') {
|
||||
Functions.setQuery(window.localStorage.getItem(key));
|
||||
} else if (Cookies.get(key)) {
|
||||
Functions.setQuery(Cookies.get(key));
|
||||
} else {
|
||||
Functions.ajaxShowMessage(Messages.strNoAutoSavedQuery);
|
||||
}
|
||||
@ -1252,7 +1289,7 @@ Functions.insertQuery = function (queryType) {
|
||||
|
||||
var query = '';
|
||||
var myListBox = document.sqlform.dummy;
|
||||
var table = document.sqlform.table.value;
|
||||
table = document.sqlform.table.value;
|
||||
|
||||
if (myListBox.options.length > 0) {
|
||||
sqlBoxLocked = true;
|
||||
@ -1268,8 +1305,8 @@ Functions.insertQuery = function (queryType) {
|
||||
editDis += ',';
|
||||
}
|
||||
columnsList += myListBox.options[i].value;
|
||||
valDis += '[value-' + NbSelect + ']';
|
||||
editDis += myListBox.options[i].value + '=[value-' + NbSelect + ']';
|
||||
valDis += '\'[value-' + NbSelect + ']\'';
|
||||
editDis += myListBox.options[i].value + '=\'[value-' + NbSelect + ']\'';
|
||||
}
|
||||
if (queryType === 'selectall') {
|
||||
query = 'SELECT * FROM `' + table + '` WHERE 1';
|
||||
@ -1329,6 +1366,8 @@ Functions.insertValueQuery = function () {
|
||||
} else {
|
||||
myQuery.value += columnsList;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
sqlBoxLocked = false;
|
||||
}
|
||||
};
|
||||
@ -1743,9 +1782,8 @@ Functions.loadForeignKeyCheckbox = function () {
|
||||
var params = {
|
||||
'ajax_request': true,
|
||||
'server': CommonParams.get('server'),
|
||||
'get_default_fk_check_value': true
|
||||
};
|
||||
$.get('sql.php', params, function (data) {
|
||||
$.get('index.php?route=/sql/get-default-fk-check-value', params, function (data) {
|
||||
var html = '<input type="hidden" name="fk_checks" value="0">' +
|
||||
'<input type="checkbox" name="fk_checks" id="fk_checks"' +
|
||||
(data.default_fk_check_value ? ' checked="checked"' : '') + '>' +
|
||||
@ -1848,7 +1886,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
var fkCheck = $(this).parent().find('#fk_checks').is(':checked');
|
||||
|
||||
var $form = $('a.inline_edit_sql').prev('form');
|
||||
var $fakeForm = $('<form>', { action: 'import.php', method: 'post' })
|
||||
var $fakeForm = $('<form>', { action: 'index.php?route=/import', method: 'post' })
|
||||
.append($form.find('input[name=server], input[name=db], input[name=table], input[name=token]').clone())
|
||||
.append($('<input>', { type: 'hidden', name: 'show_query', value: 1 }))
|
||||
.append($('<input>', { type: 'hidden', name: 'is_js_confirmed', value: 0 }))
|
||||
@ -1857,7 +1895,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
if (! Functions.checkSqlQuery($fakeForm[0])) {
|
||||
return false;
|
||||
}
|
||||
$('.success').hide();
|
||||
$('.alert-success').hide();
|
||||
$fakeForm.appendTo($('body')).trigger('submit');
|
||||
});
|
||||
|
||||
@ -1898,7 +1936,6 @@ Functions.codeMirrorAutoCompleteOnInputRead = function (instance) {
|
||||
|
||||
sqlAutoCompleteInProgress = true;
|
||||
|
||||
var href = 'db_sql_autocomplete.php';
|
||||
var params = {
|
||||
'ajax_request': true,
|
||||
'server': CommonParams.get('server'),
|
||||
@ -1917,7 +1954,7 @@ Functions.codeMirrorAutoCompleteOnInputRead = function (instance) {
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: href,
|
||||
url: 'index.php?route=/database/sql/autocomplete',
|
||||
data: params,
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
@ -2177,7 +2214,7 @@ Functions.updateCode = function ($base, htmlValue, rawValue) {
|
||||
*
|
||||
* 4) var $msg = Functions.ajaxShowMessage('Some error', false);
|
||||
* This will show a message that will not disappear automatically, but it
|
||||
* can be dismissed by the user after he has finished reading it.
|
||||
* can be dismissed by the user after they have finished reading it.
|
||||
*
|
||||
* @param string message string containing the message to be shown.
|
||||
* optional, defaults to 'Loading...'
|
||||
@ -2228,9 +2265,9 @@ Functions.ajaxShowMessage = function (message, timeout, type) {
|
||||
}
|
||||
// Determine type of message, add styling as required
|
||||
if (type === 'error') {
|
||||
msg = '<div class="error">' + msg + '</div>';
|
||||
msg = '<div class="alert alert-danger" role="alert">' + msg + '</div>';
|
||||
} else if (type === 'success') {
|
||||
msg = '<div class="success">' + msg + '</div>';
|
||||
msg = '<div class="alert alert-success" role="alert">' + msg + '</div>';
|
||||
}
|
||||
// Create a parent element for the AJAX messages, if necessary
|
||||
if ($('#loading_parent').length === 0) {
|
||||
@ -2242,8 +2279,8 @@ Functions.ajaxShowMessage = function (message, timeout, type) {
|
||||
// Remove all old messages, if any
|
||||
$('span.ajax_notification[id^=ajax_message_num]').remove();
|
||||
/**
|
||||
* @var $retval a jQuery object containing the reference
|
||||
* to the created AJAX message
|
||||
* @var $retval a jQuery object containing the reference
|
||||
* to the created AJAX message
|
||||
*/
|
||||
var $retval = $(
|
||||
'<span class="ajax_notification" id="ajax_message_num_' +
|
||||
@ -2271,7 +2308,7 @@ Functions.ajaxShowMessage = function (message, timeout, type) {
|
||||
if (dismissable) {
|
||||
$retval.addClass('dismissable').css('cursor', 'pointer');
|
||||
/**
|
||||
* Add a tooltip to the notification to let the user know that (s)he
|
||||
* Add a tooltip to the notification to let the user know that they
|
||||
* can dismiss the ajax notification by clicking on it.
|
||||
*/
|
||||
Functions.tooltip(
|
||||
@ -2424,8 +2461,8 @@ Functions.checkReservedWordColumns = function ($form) {
|
||||
var isConfirmed = true;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: 'tbl_structure.php',
|
||||
data: $form.serialize() + CommonParams.get('arg_separator') + 'reserved_word_check=1',
|
||||
url: 'index.php?route=/table/structure/reserved-word-check',
|
||||
data: $form.serialize(),
|
||||
success: function (data) {
|
||||
if (typeof data.success !== 'undefined' && data.success === true) {
|
||||
isConfirmed = confirm(data.message);
|
||||
@ -2442,8 +2479,18 @@ $(function () {
|
||||
* Allows the user to dismiss a notification
|
||||
* created with Functions.ajaxShowMessage()
|
||||
*/
|
||||
$(document).on('click', 'span.ajax_notification.dismissable', function () {
|
||||
Functions.ajaxRemoveMessage($(this));
|
||||
var holdStarter = null;
|
||||
$(document).on('mousedown', 'span.ajax_notification.dismissable', function () {
|
||||
holdStarter = setTimeout(function () {
|
||||
holdStarter = null;
|
||||
}, 250);
|
||||
});
|
||||
|
||||
$(document).on('mouseup', 'span.ajax_notification.dismissable', function () {
|
||||
if (holdStarter && event.which === 1) {
|
||||
clearTimeout(holdStarter);
|
||||
Functions.ajaxRemoveMessage($(this));
|
||||
}
|
||||
});
|
||||
/**
|
||||
* The below two functions hide the "Dismiss notification" tooltip when a user
|
||||
@ -2551,7 +2598,7 @@ Functions.createProfilingChart = function (target, data) {
|
||||
numberColumns: 2
|
||||
}
|
||||
},
|
||||
// from http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines#Color_Palette
|
||||
// from https://web.archive.org/web/20190321233412/http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines
|
||||
seriesColors: [
|
||||
'#fce94f',
|
||||
'#fcaf3e',
|
||||
@ -2825,7 +2872,7 @@ Functions.sortTable = function (textSelector) {
|
||||
|
||||
// get the text of the field that we will sort by
|
||||
$.each(rows, function (index, row) {
|
||||
row.sortKey = $.trim($(row).find(textSelector).text().toLowerCase());
|
||||
row.sortKey = $(row).find(textSelector).text().toLowerCase().trim();
|
||||
});
|
||||
|
||||
// get the sorted order
|
||||
@ -2860,8 +2907,8 @@ AJAX.registerTeardown('functions.js', function () {
|
||||
});
|
||||
|
||||
/**
|
||||
* jQuery coding for 'Create Table'. Used on db_operations.php,
|
||||
* db_structure.php and db_tracking.php (i.e., wherever
|
||||
* jQuery coding for 'Create Table'. Used on /database/operations,
|
||||
* /database/structure and /database/tracking (i.e., wherever
|
||||
* PhpMyAdmin\Display\CreateTable is used)
|
||||
*
|
||||
* Attach Ajax Event handlers for Create Table
|
||||
@ -2894,7 +2941,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
$.post($form.attr('action'), $form.serialize() + CommonParams.get('arg_separator') + 'do_save_data=1', function (data) {
|
||||
if (typeof data !== 'undefined' && data.success === true) {
|
||||
$('#properties_message')
|
||||
.removeClass('error')
|
||||
.removeClass('alert-danger')
|
||||
.html('');
|
||||
Functions.ajaxShowMessage(data.message);
|
||||
// Only if the create table dialog (distinct panel) exists
|
||||
@ -2917,7 +2964,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
/**
|
||||
* @var curr_last_row Object referring to the last <tr> element in {@link tablesTable}
|
||||
*/
|
||||
var currLastRow = $(tablesTable).find('tr:last');
|
||||
var currLastRow = $(tablesTable).find('tr').last();
|
||||
/**
|
||||
* @var curr_last_row_index_string String containing the index of {@link currLastRow}
|
||||
*/
|
||||
@ -2955,13 +3002,13 @@ AJAX.registerOnload('functions.js', function () {
|
||||
if (! (history && history.pushState)) {
|
||||
params12 += MicroHistory.menus.getRequestParam();
|
||||
}
|
||||
var tableStructureUrl = 'tbl_structure.php?server=' + data.params.server +
|
||||
var tableStructureUrl = 'index.php?route=/table/structure' + argsep + 'server=' + data.params.server +
|
||||
argsep + 'db=' + data.params.db + argsep + 'token=' + data.params.token +
|
||||
argsep + 'goto=db_structure.php' + argsep + 'table=' + data.params.table + '';
|
||||
argsep + 'goto=' + encodeURIComponent('index.php?route=/database/structure') + argsep + 'table=' + data.params.table + '';
|
||||
$.get(tableStructureUrl, params12, AJAX.responseHandler);
|
||||
} else {
|
||||
Functions.ajaxShowMessage(
|
||||
'<div class="error">' + data.error + '</div>',
|
||||
'<div class="alert alert-danger" role="alert">' + data.error + '</div>',
|
||||
false
|
||||
);
|
||||
}
|
||||
@ -3026,7 +3073,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
if ($form.is('.create_table_form.ajax')) {
|
||||
submitChangesInCreateTableForm('submit_partition_change=1');
|
||||
} else {
|
||||
$form.submit();
|
||||
$form.trigger('submit');
|
||||
}
|
||||
});
|
||||
|
||||
@ -3054,7 +3101,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
*
|
||||
* @see Messages.strPasswordEmpty
|
||||
* @see Messages.strPasswordNotSame
|
||||
* @param object $the_form The form to be validated
|
||||
* @param {object} $theForm The form to be validated
|
||||
* @return bool
|
||||
*/
|
||||
Functions.checkPassword = function ($theForm) {
|
||||
@ -3120,7 +3167,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
$('#pma_username').val('').prop('required', false);
|
||||
$('#user_exists_warning').css('display', 'none');
|
||||
} else if (this.value === 'userdefined') {
|
||||
$('#pma_username').trigger('focus').select().prop('required', true);
|
||||
$('#pma_username').trigger('focus').trigger('select').prop('required', true);
|
||||
}
|
||||
});
|
||||
|
||||
@ -3137,7 +3184,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
$('#text_pma_pw').prop('required', false).val('');
|
||||
} else if (this.value === 'userdefined') {
|
||||
$('#text_pma_pw2').prop('required', true);
|
||||
$('#text_pma_pw').prop('required', true).trigger('focus').select();
|
||||
$('#text_pma_pw').prop('required', true).trigger('focus').trigger('select');
|
||||
} else {
|
||||
$('#text_pma_pw2').prop('required', false);
|
||||
$('#text_pma_pw').prop('required', false);
|
||||
@ -3294,8 +3341,8 @@ AJAX.registerOnload('functions.js', function () {
|
||||
*/
|
||||
Functions.hideShowConnection = function ($engineSelector) {
|
||||
var $connection = $('.create_table_form input[name=connection]');
|
||||
var index = $connection.parent('td').index() + 1;
|
||||
var $labelTh = $connection.parents('tr').prev('tr').children('th:nth-child(' + index + ')');
|
||||
var index = $connection.parent('td').index();
|
||||
var $labelTh = $connection.parents('tr').prev('tr').children('th').eq(index);
|
||||
if ($engineSelector.val() !== 'FEDERATED') {
|
||||
$connection
|
||||
.prop('disabled', true)
|
||||
@ -3391,7 +3438,7 @@ var $enumEditorDialog = null;
|
||||
AJAX.registerOnload('functions.js', function () {
|
||||
$(document).on('click', 'a.open_enum_editor', function () {
|
||||
// Get the name of the column that is being edited
|
||||
var colname = $(this).closest('tr').find('input:first').val();
|
||||
var colname = $(this).closest('tr').find('input').first().val();
|
||||
var title;
|
||||
var i;
|
||||
// And use it to make up a title for the page
|
||||
@ -3444,7 +3491,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
}
|
||||
var fields = '';
|
||||
// If there are no values, maybe the user is about to make a
|
||||
// new list so we add a few for him/her to get started with.
|
||||
// new list so we add a few for them to get started with.
|
||||
if (values.length === 0) {
|
||||
values.push('', '', '', '');
|
||||
}
|
||||
@ -3465,9 +3512,9 @@ AJAX.registerOnload('functions.js', function () {
|
||||
'<legend>' + title + '</legend>' +
|
||||
'<p>' + Functions.getImage('s_notice') +
|
||||
Messages.enum_hint + '</p>' +
|
||||
'<table class=\'values\'>' + fields + '</table>' +
|
||||
'<table class=\'pma-table values\'>' + fields + '</table>' +
|
||||
'</fieldset><fieldset class=\'tblFooters\'>' +
|
||||
'<table class=\'add\'><tr><td>' +
|
||||
'<table class=\'pma-table add\'><tr><td>' +
|
||||
'<div class=\'slider\'></div>' +
|
||||
'</td><td>' +
|
||||
'<form><div><input type=\'submit\' class=\'add_value btn btn-primary\' value=\'' +
|
||||
@ -3480,7 +3527,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
'</fieldset>' +
|
||||
'</div>';
|
||||
/**
|
||||
* @var Defines functions to be called when the buttons in
|
||||
* @var {object} buttonOptions Defines functions to be called when the buttons in
|
||||
* the buttonOptions jQuery dialog bar are pressed
|
||||
*/
|
||||
var buttonOptions = {};
|
||||
@ -3516,7 +3563,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
buttons: buttonOptions,
|
||||
open: function () {
|
||||
// Focus the "Go" button after opening the dialog
|
||||
$(this).closest('.ui-dialog').find('.ui-dialog-buttonpane button:first').trigger('focus');
|
||||
$(this).closest('.ui-dialog').find('.ui-dialog-buttonpane button').first().trigger('focus');
|
||||
},
|
||||
close: function () {
|
||||
$(this).remove();
|
||||
@ -3541,7 +3588,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
});
|
||||
|
||||
$(document).on('click', 'a.central_columns_dialog', function () {
|
||||
var href = 'db_central_columns.php';
|
||||
var href = 'index.php?route=/database/central-columns';
|
||||
var db = CommonParams.get('db');
|
||||
var table = CommonParams.get('table');
|
||||
var maxRows = $(this).data('maxrows');
|
||||
@ -3587,7 +3634,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
fields += Functions.escapeHtml(centralColumnList[db + '_' + table][i].col_extra) + '</span>' +
|
||||
'</div></td>';
|
||||
if (pick) {
|
||||
fields += '<td><input class="btn btn-secondary pick all100" type="submit" value="' +
|
||||
fields += '<td><input class="btn btn-secondary pick w-100" type="submit" value="' +
|
||||
Messages.pickColumn + '" onclick="Functions.autoPopulate(\'' + colid + '\',' + i + ')"></td>';
|
||||
}
|
||||
fields += '</tr>';
|
||||
@ -3600,13 +3647,13 @@ AJAX.registerOnload('functions.js', function () {
|
||||
}
|
||||
var seeMore = '';
|
||||
if (listSize > maxRows) {
|
||||
seeMore = '<fieldset class=\'tblFooters center font_weight_bold\'>' +
|
||||
seeMore = '<fieldset class="tblFooters text-center font_weight_bold">' +
|
||||
'<a href=\'#\' id=\'seeMore\'>' + Messages.seeMore + '</a></fieldset>';
|
||||
}
|
||||
var centralColumnsDialog = '<div class=\'max_height_400\'>' +
|
||||
'<fieldset>' +
|
||||
searchIn +
|
||||
'<table id=\'col_list\' class=\'values all100\'>' + fields + '</table>' +
|
||||
'<table id=\'col_list\' class=\'pma-table values w-100\'>' + fields + '</table>' +
|
||||
'</fieldset>' +
|
||||
seeMore +
|
||||
'</div>';
|
||||
@ -3650,7 +3697,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
fields += centralColumnList[db + '_' + table][i].col_extra + '</span>' +
|
||||
'</div></td>';
|
||||
if (pick) {
|
||||
fields += '<td><input class="btn btn-secondary pick all100" type="submit" value="' +
|
||||
fields += '<td><input class="btn btn-secondary pick w-100" type="submit" value="' +
|
||||
Messages.pickColumn + '" onclick="Functions.autoPopulate(\'' + colid + '\',' + i + ')"></td>';
|
||||
}
|
||||
fields += '</tr>';
|
||||
@ -3662,7 +3709,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$(this).closest('.ui-dialog').find('.ui-dialog-buttonpane button:first').trigger('focus');
|
||||
$(this).closest('.ui-dialog').find('.ui-dialog-buttonpane button').first().trigger('focus');
|
||||
},
|
||||
close: function () {
|
||||
$('#col_list').off('click', '.pick');
|
||||
@ -3689,7 +3736,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
Functions.getImage('b_drop') +
|
||||
'</td></tr>'
|
||||
)
|
||||
.find('tr:last')
|
||||
.find('tr').last()
|
||||
.show('fast');
|
||||
}
|
||||
});
|
||||
@ -3762,7 +3809,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
while (rowsToAdd--) {
|
||||
var $indexColumns = $('#index_columns');
|
||||
var $newrow = $indexColumns
|
||||
.find('tbody > tr:first')
|
||||
.find('tbody > tr').first()
|
||||
.clone()
|
||||
.appendTo(
|
||||
$indexColumns.find('tbody')
|
||||
@ -3774,8 +3821,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Functions.indexEditorDialog = function (url, title, callbackSuccess, callbackFailure) {
|
||||
Functions.indexDialogModal = function (routeUrl, url, title, callbackSuccess, callbackFailure) {
|
||||
/* Remove the hidden dialogs if there are*/
|
||||
var $editIndexDialog = $('#edit_index_dialog');
|
||||
if ($editIndexDialog.length !== 0) {
|
||||
@ -3790,7 +3836,7 @@ Functions.indexEditorDialog = function (url, title, callbackSuccess, callbackFai
|
||||
var buttonOptions = {};
|
||||
buttonOptions[Messages.strGo] = function () {
|
||||
/**
|
||||
* @var the_form object referring to the export form
|
||||
* @var the_form object referring to the export form
|
||||
*/
|
||||
var $form = $('#index_frm');
|
||||
Functions.ajaxShowMessage(Messages.strProcessingRequest);
|
||||
@ -3804,7 +3850,7 @@ Functions.indexEditorDialog = function (url, title, callbackSuccess, callbackFai
|
||||
if (typeof data !== 'undefined' && data.success === true) {
|
||||
Functions.ajaxShowMessage(data.message);
|
||||
Functions.highlightSql($('.result_query'));
|
||||
$('.result_query .notice').remove();
|
||||
$('.result_query .alert').remove();
|
||||
/* Reload the field form*/
|
||||
$('#table_index').remove();
|
||||
$('<div id=\'temp_div\'><div>')
|
||||
@ -3817,7 +3863,7 @@ Functions.indexEditorDialog = function (url, title, callbackSuccess, callbackFai
|
||||
}
|
||||
$('div.no_indexes_defined').hide();
|
||||
if (callbackSuccess) {
|
||||
callbackSuccess();
|
||||
callbackSuccess(data);
|
||||
}
|
||||
Navigation.reload();
|
||||
} else {
|
||||
@ -3844,7 +3890,7 @@ Functions.indexEditorDialog = function (url, title, callbackSuccess, callbackFai
|
||||
$(this).dialog('close');
|
||||
};
|
||||
var $msgbox = Functions.ajaxShowMessage();
|
||||
$.post('tbl_indexes.php', url, function (data) {
|
||||
$.post(routeUrl, url, function (data) {
|
||||
if (typeof data !== 'undefined' && data.success === false) {
|
||||
// in the case of an error, show the error message returned.
|
||||
Functions.ajaxShowMessage(data.error, false);
|
||||
@ -3869,6 +3915,14 @@ Functions.indexEditorDialog = function (url, title, callbackSuccess, callbackFai
|
||||
}); // end $.get()
|
||||
};
|
||||
|
||||
Functions.indexEditorDialog = function (url, title, callbackSuccess, callbackFailure) {
|
||||
Functions.indexDialogModal('index.php?route=/table/indexes', url, title, callbackSuccess, callbackFailure);
|
||||
};
|
||||
|
||||
Functions.indexRenameDialog = function (url, title, callbackSuccess, callbackFailure) {
|
||||
Functions.indexDialogModal('index.php?route=/table/indexes/rename', url, title, callbackSuccess, callbackFailure);
|
||||
};
|
||||
|
||||
Functions.showIndexEditDialog = function ($outer) {
|
||||
Indexes.checkIndexType();
|
||||
Functions.checkIndexName('index_frm');
|
||||
@ -4004,7 +4058,7 @@ Functions.toggleButton = function ($obj) {
|
||||
var w = parseInt(($('img', $obj).height() / 16) * 22, 10);
|
||||
// Resize the central part of the switch on the top
|
||||
// layer to match the background
|
||||
$('table td:nth-child(2) > div', $obj).width(w);
|
||||
$($obj).find('table td').eq(1).children('div').width(w);
|
||||
/**
|
||||
* var imgw Width of the background image
|
||||
* var tblw Width of the foreground layer
|
||||
@ -4021,7 +4075,7 @@ Functions.toggleButton = function ($obj) {
|
||||
* var btnw Outer width of the central part of the switch
|
||||
*/
|
||||
var offw = $('td.toggleOff', $obj).outerWidth();
|
||||
var btnw = $('table td:nth-child(2)', $obj).outerWidth();
|
||||
var btnw = $($obj).find('table td').eq(1).outerWidth();
|
||||
// Resize the main div so that exactly one side of
|
||||
// the switch plus the central part fit into it.
|
||||
$obj.width(offw + btnw + 2);
|
||||
@ -4032,15 +4086,15 @@ Functions.toggleButton = function ($obj) {
|
||||
var move = $('td.toggleOff', $obj).outerWidth();
|
||||
// If the switch is initialized to the
|
||||
// OFF state we need to move it now.
|
||||
if ($('div.container', $obj).hasClass('off')) {
|
||||
if ($('div.toggle-container', $obj).hasClass('off')) {
|
||||
if (right === 'right') {
|
||||
$('div.container', $obj).animate({ 'left': '-=' + move + 'px' }, 0);
|
||||
$('div.toggle-container', $obj).animate({ 'left': '-=' + move + 'px' }, 0);
|
||||
} else {
|
||||
$('div.container', $obj).animate({ 'left': '+=' + move + 'px' }, 0);
|
||||
$('div.toggle-container', $obj).animate({ 'left': '+=' + move + 'px' }, 0);
|
||||
}
|
||||
}
|
||||
// Attach an 'onclick' event to the switch
|
||||
$('div.container', $obj).on('click', function () {
|
||||
$('div.toggle-container', $obj).on('click', function () {
|
||||
if ($(this).hasClass('isActive')) {
|
||||
return false;
|
||||
} else {
|
||||
@ -4098,7 +4152,7 @@ Functions.toggleButton = function ($obj) {
|
||||
* Unbind all event handlers before tearing down a page
|
||||
*/
|
||||
AJAX.registerTeardown('functions.js', function () {
|
||||
$('div.container').off('click');
|
||||
$('div.toggle-container').off('click');
|
||||
});
|
||||
/**
|
||||
* Initialise all toggle buttons
|
||||
@ -4136,7 +4190,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
// Check where to load the new content
|
||||
if ($(this).closest('#pma_navigation').length === 0) {
|
||||
// For the main page we don't need to do anything,
|
||||
$(this).closest('form').submit();
|
||||
$(this).closest('form').trigger('submit');
|
||||
} else {
|
||||
// but for the navigation we need to manually replace the content
|
||||
Navigation.treePagination($(this));
|
||||
@ -4149,7 +4203,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
if ($('li.jsversioncheck').length > 0) {
|
||||
$.ajax({
|
||||
dataType: 'json',
|
||||
url: 'version_check.php',
|
||||
url: 'index.php?route=/version-check',
|
||||
method: 'POST',
|
||||
data: {
|
||||
'server': CommonParams.get('server')
|
||||
@ -4464,12 +4518,14 @@ AJAX.registerOnload('functions.js', function () {
|
||||
*/
|
||||
$('a.take_theme').on('click', function () {
|
||||
var what = this.name;
|
||||
/* eslint-disable compat/compat */
|
||||
if (window.opener && window.opener.document.forms.setTheme.elements.set_theme) {
|
||||
window.opener.document.forms.setTheme.elements.set_theme.value = what;
|
||||
window.opener.document.forms.setTheme.submit();
|
||||
window.close();
|
||||
return false;
|
||||
}
|
||||
/* eslint-enable compat/compat */
|
||||
return true;
|
||||
});
|
||||
});
|
||||
@ -4489,7 +4545,7 @@ Functions.createPrintAndBackButtons = function () {
|
||||
var backButton = $('<input>',{
|
||||
type: 'button',
|
||||
value: Messages.back,
|
||||
class: 'btn btn-primary',
|
||||
class: 'btn btn-secondary',
|
||||
id: 'back_button_print_view'
|
||||
});
|
||||
backButton.on('click', Functions.removePrintAndBackButton);
|
||||
@ -4565,7 +4621,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
// was also prevented in IE
|
||||
$(this).trigger('blur');
|
||||
|
||||
$(this).closest('.ui-dialog').find('.ui-button:first').trigger('click');
|
||||
$(this).closest('.ui-dialog').find('.ui-button').first().trigger('click');
|
||||
}
|
||||
}); // end $(document).on()
|
||||
}
|
||||
@ -4589,7 +4645,7 @@ Functions.createViewDialog = function ($this) {
|
||||
codeMirrorEditor.save();
|
||||
}
|
||||
$msg = Functions.ajaxShowMessage();
|
||||
$.post('view_create.php', $('#createViewDialog').find('form').serialize(), function (data) {
|
||||
$.post('index.php?route=/view/create', $('#createViewDialog').find('form').serialize(), function (data) {
|
||||
Functions.ajaxRemoveMessage($msg);
|
||||
if (typeof data !== 'undefined' && data.success === true) {
|
||||
$('#createViewDialog').dialog('close');
|
||||
@ -4637,7 +4693,7 @@ $(function () {
|
||||
'width': '100%',
|
||||
'z-index': 99
|
||||
})
|
||||
.append($('#serverinfo'))
|
||||
.append($('#server-breadcrumb'))
|
||||
.append($('#topmenucontainer'));
|
||||
// Allow the DOM to render, then adjust the padding on the body
|
||||
setTimeout(function () {
|
||||
@ -4651,16 +4707,17 @@ $(function () {
|
||||
});
|
||||
|
||||
/**
|
||||
* Scrolls the page to the top if clicking the serverinfo bar
|
||||
* Scrolls the page to the top if clicking the server-breadcrumb bar
|
||||
*/
|
||||
$(function () {
|
||||
$(document).on('click', '#serverinfo, #goto_pagetop', function (event) {
|
||||
$(document).on('click', '#server-breadcrumb, #goto_pagetop', function (event) {
|
||||
event.preventDefault();
|
||||
$('html, body').animate({ scrollTop: 0 }, 'fast');
|
||||
});
|
||||
});
|
||||
|
||||
var checkboxesSel = 'input.checkall:checkbox:enabled';
|
||||
Functions.checkboxesSel = checkboxesSel;
|
||||
|
||||
/**
|
||||
* Watches checkboxes in a form to set the checkall box accordingly
|
||||
@ -4686,7 +4743,7 @@ $(document).on('change', checkboxesSel, Functions.checkboxesChanged);
|
||||
$(document).on('change', 'input.checkall_box', function () {
|
||||
var isChecked = $(this).is(':checked');
|
||||
$(this.form).find(checkboxesSel).not('.row-hidden').prop('checked', isChecked)
|
||||
.parents('tr').toggleClass('marked', isChecked);
|
||||
.parents('tr').toggleClass('marked table-active', isChecked);
|
||||
});
|
||||
|
||||
$(document).on('click', '.checkall-filter', function () {
|
||||
@ -4760,7 +4817,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
/* Trigger filtering of the list based on incoming database name */
|
||||
var $filter = $('#filterText');
|
||||
if ($filter.val()) {
|
||||
$filter.trigger('keyup').select();
|
||||
$filter.trigger('keyup').trigger('select');
|
||||
}
|
||||
});
|
||||
|
||||
@ -4869,12 +4926,12 @@ Functions.ignorePhpErrors = function (clearPrevErrors) {
|
||||
) {
|
||||
clearPrevious = false;
|
||||
}
|
||||
// send AJAX request to error_report.php with send_error_report=0, exception_type=php & token.
|
||||
// send AJAX request to /error-report with send_error_report=0, exception_type=php & token.
|
||||
// It clears the prev_errors stored in session.
|
||||
if (clearPrevious) {
|
||||
var $pmaReportErrorsForm = $('#pma_report_errors_form');
|
||||
$pmaReportErrorsForm.find('input[name="send_error_report"]').val(0); // change send_error_report to '0'
|
||||
$pmaReportErrorsForm.submit();
|
||||
$pmaReportErrorsForm.trigger('submit');
|
||||
}
|
||||
|
||||
// remove displayed errors
|
||||
@ -4933,8 +4990,8 @@ AJAX.registerOnload('functions.js', function () {
|
||||
|
||||
// There could be multiple submit buttons on the same form,
|
||||
// we assume all of them behave identical and just click one.
|
||||
if (! $form.find('input[type="submit"]:first') ||
|
||||
! $form.find('input[type="submit"]:first').trigger('click')
|
||||
if (! $form.find('input[type="submit"]').first() ||
|
||||
! $form.find('input[type="submit"]').first().trigger('click')
|
||||
) {
|
||||
$form.trigger('submit');
|
||||
}
|
||||
@ -4955,7 +5012,7 @@ AJAX.registerOnload('functions.js', function () {
|
||||
/*
|
||||
* Display warning regarding SSL when sha256_password
|
||||
* method is selected
|
||||
* Used in user_password.php (Change Password link on index.php)
|
||||
* Used in /user-password (Change Password link on index.php)
|
||||
*/
|
||||
$(document).on('change', 'select#select_authentication_plugin_cp', function () {
|
||||
if (this.value === 'sha256_password') {
|
||||
@ -5043,7 +5100,7 @@ Functions.getImage = function (image, alternate, attributes) {
|
||||
}
|
||||
// set css classes
|
||||
retval.attr('class', 'icon ic_' + image);
|
||||
// set all other attrubutes
|
||||
// set all other attributes
|
||||
for (var i in attr) {
|
||||
if (i === 'src') {
|
||||
// do not allow to override the 'src' attribute
|
||||
@ -5065,19 +5122,19 @@ Functions.getImage = function (image, alternate, attributes) {
|
||||
* NOTE: Depending on server's configuration, the configuration table may be or
|
||||
* not persistent.
|
||||
*
|
||||
* @param {string} key Configuration key.
|
||||
* @param {object} value Configuration value.
|
||||
* @param {string} key Configuration key.
|
||||
* @param {object} value Configuration value.
|
||||
*/
|
||||
Functions.configSet = function (key, value) {
|
||||
var serialized = JSON.stringify(value);
|
||||
localStorage.setItem(key, serialized);
|
||||
$.ajax({
|
||||
url: 'ajax.php',
|
||||
url: 'index.php?route=/config/set',
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
'ajax_request': true,
|
||||
key: key,
|
||||
type: 'config-set',
|
||||
server: CommonParams.get('server'),
|
||||
value: serialized,
|
||||
},
|
||||
@ -5103,12 +5160,13 @@ Functions.configSet = function (key, value) {
|
||||
* If value should not be cached and the up-to-date configuration value from
|
||||
* right from the server is required, the third parameter should be `false`.
|
||||
*
|
||||
* @param {string} key Configuration key.
|
||||
* @param {boolean} cached Configuration type.
|
||||
* @param {string} key Configuration key.
|
||||
* @param {boolean} cached Configuration type.
|
||||
* @param {Function} successCallback The callback to call after the value is received
|
||||
*
|
||||
* @return {object} Configuration value.
|
||||
* @return {object} Configuration value.
|
||||
*/
|
||||
Functions.configGet = function (key, cached) {
|
||||
Functions.configGet = function (key, cached, successCallback) {
|
||||
var isCached = (typeof cached !== 'undefined') ? cached : true;
|
||||
var value = localStorage.getItem(key);
|
||||
if (isCached && value !== undefined && value !== null) {
|
||||
@ -5118,15 +5176,13 @@ Functions.configGet = function (key, cached) {
|
||||
// Result not found in local storage or ignored.
|
||||
// Hitting the server.
|
||||
$.ajax({
|
||||
// TODO: This is ugly, but usually when a configuration is needed,
|
||||
// processing cannot continue until that value is found.
|
||||
// Another solution is to provide a callback as a parameter.
|
||||
async: false,
|
||||
url: 'ajax.php',
|
||||
// Value at false to be synchronous (then ignore the callback on success)
|
||||
async: typeof successCallback === 'function',
|
||||
url: 'index.php?route=/config/get',
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
type: 'config-get',
|
||||
'ajax_request': true,
|
||||
server: CommonParams.get('server'),
|
||||
key: key
|
||||
},
|
||||
@ -5137,14 +5193,18 @@ Functions.configGet = function (key, cached) {
|
||||
} else {
|
||||
Functions.ajaxShowMessage(data.message);
|
||||
}
|
||||
// Eventually, call callback.
|
||||
// Call the callback if it is defined
|
||||
if (typeof successCallback === 'function') {
|
||||
// Feed it the value previously saved like on async mode
|
||||
successCallback(JSON.parse(localStorage.getItem(key)));
|
||||
}
|
||||
}
|
||||
});
|
||||
return JSON.parse(localStorage.getItem(key));
|
||||
};
|
||||
|
||||
/**
|
||||
* Return POST data as stored by Util::linkOrButton
|
||||
* Return POST data as stored by Generator::linkOrButton
|
||||
*/
|
||||
Functions.getPostData = function () {
|
||||
var dataPost = this.attr('data-post');
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @fileoverview functions used in GIS data editor
|
||||
*
|
||||
@ -7,9 +6,8 @@
|
||||
*/
|
||||
|
||||
/* global addZoomPanControllers, loadSVG, selectVisualization, styleOSM, zoomAndPan */ // js/table/gis_visualization.js
|
||||
/* global pmaThemeImage */ // js/messages.php
|
||||
/* global themeImagePath */ // templates/javascript/variables.twig
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
var gisEditorLoaded = false;
|
||||
|
||||
/**
|
||||
@ -75,7 +73,7 @@ function addDataPoint (pointNumber, prefix) {
|
||||
function initGISEditorVisualization () {
|
||||
// Loads either SVG or OSM visualization based on the choice
|
||||
selectVisualization();
|
||||
// Adds necessary styles to the div that coontains the openStreetMap
|
||||
// Adds necessary styles to the div that contains the openStreetMap
|
||||
styleOSM();
|
||||
// Loads the SVG element and make a reference to it
|
||||
loadSVG();
|
||||
@ -102,7 +100,7 @@ function loadJSAndGISEditor (value, field, type, inputName) {
|
||||
var smallScripts = ['js/vendor/jquery/jquery.svg.js',
|
||||
'js/vendor/jquery/jquery.mousewheel.js',
|
||||
'js/vendor/jquery/jquery.event.drag-2.2.js',
|
||||
'js/table/gis_visualization.js'];
|
||||
'js/dist/table/gis_visualization.js'];
|
||||
|
||||
for (var i = 0; i < smallScripts.length; i++) {
|
||||
script = document.createElement('script');
|
||||
@ -131,6 +129,7 @@ function loadJSAndGISEditor (value, field, type, inputName) {
|
||||
script.src = 'js/vendor/openlayers/OpenLayers.js';
|
||||
head.appendChild(script);
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
gisEditorLoaded = true;
|
||||
}
|
||||
|
||||
@ -144,7 +143,7 @@ function loadJSAndGISEditor (value, field, type, inputName) {
|
||||
*/
|
||||
function loadGISEditor (value, field, type, inputName) {
|
||||
var $gisEditor = $('#gis_editor');
|
||||
$.post('gis_data_editor.php', {
|
||||
$.post('index.php?route=/gis-data-editor', {
|
||||
'field' : field,
|
||||
'value' : value,
|
||||
'type' : type,
|
||||
@ -177,20 +176,20 @@ function openGISEditor () {
|
||||
var popupOffsetLeft = windowWidth / 2 - popupWidth / 2;
|
||||
|
||||
var $gisEditor = $('#gis_editor');
|
||||
var $backgrouond = $('#popup_background');
|
||||
var $background = $('#popup_background');
|
||||
|
||||
$gisEditor.css({ 'top': popupOffsetTop, 'left': popupOffsetLeft, 'width': popupWidth, 'height': popupHeight });
|
||||
$backgrouond.css({ 'opacity' : '0.7' });
|
||||
$background.css({ 'opacity' : '0.7' });
|
||||
|
||||
$gisEditor.append(
|
||||
'<div id="gis_data_editor">' +
|
||||
'<img class="ajaxIcon" id="loadingMonitorIcon" src="' +
|
||||
pmaThemeImage + 'ajax_clock_small.gif" alt="">' +
|
||||
themeImagePath + 'ajax_clock_small.gif" alt="">' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Make it appear
|
||||
$backgrouond.fadeIn('fast');
|
||||
$background.fadeIn('fast');
|
||||
$gisEditor.fadeIn('fast');
|
||||
}
|
||||
|
||||
@ -203,7 +202,7 @@ function insertDataAndClose () {
|
||||
var inputName = $form.find('input[name=\'input_name\']').val();
|
||||
|
||||
var argsep = CommonParams.get('arg_separator');
|
||||
$.post('gis_data_editor.php', $form.serialize() + argsep + 'generate=true' + argsep + 'ajax_request=true', function (data) {
|
||||
$.post('index.php?route=/gis-data-editor', $form.serialize() + argsep + 'generate=true' + argsep + 'ajax_request=true', function (data) {
|
||||
if (typeof data !== 'undefined' && data.success === true) {
|
||||
$('input[name=\'' + inputName + '\']').val(data.result);
|
||||
} else {
|
||||
@ -251,7 +250,7 @@ AJAX.registerOnload('gis_data_editor.js', function () {
|
||||
$(document).on('change', '#gis_editor input[type=\'text\']', function () {
|
||||
var $form = $('form#gis_data_editor_form');
|
||||
var argsep = CommonParams.get('arg_separator');
|
||||
$.post('gis_data_editor.php', $form.serialize() + argsep + 'generate=true' + argsep + 'ajax_request=true', function (data) {
|
||||
$.post('index.php?route=/gis-data-editor', $form.serialize() + argsep + 'generate=true' + argsep + 'ajax_request=true', function (data) {
|
||||
if (typeof data !== 'undefined' && data.success === true) {
|
||||
$('#gis_data_textarea').val(data.result);
|
||||
$('#placeholder').empty().removeClass('hasSVG').html(data.visualization);
|
||||
@ -274,7 +273,7 @@ AJAX.registerOnload('gis_data_editor.js', function () {
|
||||
var $form = $('form#gis_data_editor_form');
|
||||
|
||||
var argsep = CommonParams.get('arg_separator');
|
||||
$.post('gis_data_editor.php', $form.serialize() + argsep + 'get_gis_editor=true' + argsep + 'ajax_request=true', function (data) {
|
||||
$.post('index.php?route=/gis-data-editor', $form.serialize() + argsep + 'get_gis_editor=true' + argsep + 'ajax_request=true', function (data) {
|
||||
if (typeof data !== 'undefined' && data.success === true) {
|
||||
$gisEditor.html(data.gis_editor);
|
||||
initGISEditorVisualization();
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Functions used in the import tab
|
||||
*
|
||||
@ -59,9 +58,9 @@ AJAX.registerOnload('import.js', function () {
|
||||
$(document).on('submit', '#import_file_form', function () {
|
||||
var radioLocalImport = $('#radio_local_import_file');
|
||||
var radioImport = $('#radio_import_file');
|
||||
var fileMsg = '<div class="error"><img src="themes/dot.gif" title="" alt="" class="icon ic_s_error"> ' + Messages.strImportDialogMessage + '</div>';
|
||||
var wrongTblNameMsg = '<div class="error"><img src="themes/dot.gif" title="" alt="" class="icon ic_s_error">' + Messages.strTableNameDialogMessage + '</div>';
|
||||
var wrongDBNameMsg = '<div class="error"><img src="themes/dot.gif" title="" alt="" class="icon ic_s_error">' + Messages.strDBNameDialogMessage + '</div>';
|
||||
var fileMsg = '<div class="alert alert-danger" role="alert"><img src="themes/dot.gif" title="" alt="" class="icon ic_s_error"> ' + Messages.strImportDialogMessage + '</div>';
|
||||
var wrongTblNameMsg = '<div class="alert alert-danger" role="alert"><img src="themes/dot.gif" title="" alt="" class="icon ic_s_error">' + Messages.strTableNameDialogMessage + '</div>';
|
||||
var wrongDBNameMsg = '<div class="alert alert-danger" role="alert"><img src="themes/dot.gif" title="" alt="" class="icon ic_s_error">' + Messages.strDBNameDialogMessage + '</div>';
|
||||
|
||||
if (radioLocalImport.length !== 0) {
|
||||
// remote upload.
|
||||
@ -74,7 +73,7 @@ AJAX.registerOnload('import.js', function () {
|
||||
|
||||
if (radioLocalImport.is(':checked')) {
|
||||
if ($('#select_local_import_file').length === 0) {
|
||||
Functions.ajaxShowMessage('<div class="error"><img src="themes/dot.gif" title="" alt="" class="icon ic_s_error"> ' + Messages.strNoImportFile + ' </div>', false);
|
||||
Functions.ajaxShowMessage('<div class="alert alert-danger" role="alert"><img src="themes/dot.gif" title="" alt="" class="icon ic_s_error"> ' + Messages.strNoImportFile + ' </div>', false);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -93,14 +92,14 @@ AJAX.registerOnload('import.js', function () {
|
||||
}
|
||||
if ($('#text_csv_new_tbl_name').length > 0) {
|
||||
var newTblName = $('#text_csv_new_tbl_name').val();
|
||||
if (newTblName.length > 0 && $.trim(newTblName).length === 0) {
|
||||
if (newTblName.length > 0 && newTblName.trim().length === 0) {
|
||||
Functions.ajaxShowMessage(wrongTblNameMsg, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ($('#text_csv_new_db_name').length > 0) {
|
||||
var newDBName = $('#text_csv_new_db_name').val();
|
||||
if (newDBName.length > 0 && $.trim(newDBName).length === 0) {
|
||||
if (newDBName.length > 0 && newDBName.trim().length === 0) {
|
||||
Functions.ajaxShowMessage(wrongDBNameMsg, false);
|
||||
return false;
|
||||
}
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @fileoverview function used for index manipulation pages
|
||||
* @name Table Structure
|
||||
@ -58,7 +57,7 @@ Indexes.checkIndexType = function () {
|
||||
/**
|
||||
* @var Object Table header for the size column.
|
||||
*/
|
||||
var $sizeHeader = $('#index_columns').find('thead tr th:nth-child(2)');
|
||||
var $sizeHeader = $('#index_columns').find('thead tr').children('th').eq(1);
|
||||
/**
|
||||
* @var Object Inputs to specify the columns for the index.
|
||||
*/
|
||||
@ -68,7 +67,7 @@ Indexes.checkIndexType = function () {
|
||||
*/
|
||||
var $sizeInputs = $('input[name="index[columns][sub_parts][]"]');
|
||||
/**
|
||||
* @var Object Footer containg the controllers to add more columns
|
||||
* @var Object Footer containing the controllers to add more columns
|
||||
*/
|
||||
var $addMore = $('#index_frm').find('.add_more');
|
||||
|
||||
@ -291,7 +290,7 @@ Indexes.getCompositeIndexList = function (sourceArray, colIndex) {
|
||||
(alreadyPresent ? 'checked="checked"' : '') +
|
||||
' id="composite_index_' + i + '" value="' + i + '">' +
|
||||
'<label for="composite_index_' + i + '">' + columnNames.join(', ') +
|
||||
'</lablel>' +
|
||||
'</label>' +
|
||||
'</li>'
|
||||
);
|
||||
}
|
||||
@ -302,7 +301,7 @@ Indexes.getCompositeIndexList = function (sourceArray, colIndex) {
|
||||
/**
|
||||
* Shows 'Add Index' dialog.
|
||||
*
|
||||
* @param array source_array Array holding particluar index
|
||||
* @param array source_array Array holding particular index
|
||||
* @param string array_index Index of an INDEX in array
|
||||
* @param array target_columns Columns for an INDEX
|
||||
* @param string col_index Index of column on form
|
||||
@ -351,7 +350,7 @@ Indexes.showAddIndexDialog = function (sourceArray, arrayIndex, targetColumns, c
|
||||
);
|
||||
} else {
|
||||
Functions.ajaxShowMessage(
|
||||
'<div class="error"><img src="themes/dot.gif" title="" alt=""' +
|
||||
'<div class="alert alert-danger" role="alert"><img src="themes/dot.gif" title="" alt=""' +
|
||||
' class="icon ic_s_error"> ' + Messages.strMissingColumn +
|
||||
' </div>', false
|
||||
);
|
||||
@ -376,7 +375,7 @@ Indexes.showAddIndexDialog = function (sourceArray, arrayIndex, targetColumns, c
|
||||
$(this).dialog('close');
|
||||
};
|
||||
var $msgbox = Functions.ajaxShowMessage();
|
||||
$.post('tbl_indexes.php', postData, function (data) {
|
||||
$.post('index.php?route=/table/indexes', postData, function (data) {
|
||||
if (data.success === false) {
|
||||
// in the case of an error, show the error message returned.
|
||||
Functions.ajaxShowMessage(data.error, false);
|
||||
@ -395,7 +394,7 @@ Indexes.showAddIndexDialog = function (sourceArray, arrayIndex, targetColumns, c
|
||||
width: 450,
|
||||
minHeight: 250,
|
||||
create: function () {
|
||||
$(this).keypress(function (e) {
|
||||
$(this).on('keypress', function (e) {
|
||||
if (e.which === 13 || e.keyCode === 13 || window.event.keyCode === 13) {
|
||||
e.preventDefault();
|
||||
buttonOptions[Messages.strGo]();
|
||||
@ -415,8 +414,6 @@ Indexes.showAddIndexDialog = function (sourceArray, arrayIndex, targetColumns, c
|
||||
containment: $('#index_columns').find('tbody'),
|
||||
tolerance: 'pointer'
|
||||
});
|
||||
// We dont need the slider at this moment.
|
||||
$(this).find('fieldset.tblFooters').remove();
|
||||
},
|
||||
modal: true,
|
||||
buttons: buttonOptions,
|
||||
@ -446,7 +443,7 @@ Indexes.showAddIndexDialog = function (sourceArray, arrayIndex, targetColumns, c
|
||||
);
|
||||
} else {
|
||||
Functions.ajaxShowMessage(
|
||||
'<div class="error"><img src="themes/dot.gif" title="" alt=""' +
|
||||
'<div class="alert alert-danger" role="alert"><img src="themes/dot.gif" title="" alt=""' +
|
||||
' class="icon ic_s_error"> ' + Messages.strMissingColumn +
|
||||
' </div>', false
|
||||
);
|
||||
@ -497,7 +494,7 @@ Indexes.indexTypeSelectionDialog = function (sourceArray, indexChoice, colIndex)
|
||||
if ($('input[name="composite_with"]').length !== 0 && $('input[name="composite_with"]:checked').length === 0
|
||||
) {
|
||||
Functions.ajaxShowMessage(
|
||||
'<div class="error"><img src="themes/dot.gif" title=""' +
|
||||
'<div class="alert alert-danger" role="alert"><img src="themes/dot.gif" title=""' +
|
||||
' alt="" class="icon ic_s_error"> ' +
|
||||
Messages.strFormEmpty +
|
||||
' </div>',
|
||||
@ -570,6 +567,7 @@ AJAX.registerTeardown('indexes.js', function () {
|
||||
$(document).off('change', '#select_index_choice');
|
||||
$(document).off('click', 'a.drop_primary_key_index_anchor.ajax');
|
||||
$(document).off('click', '#table_index tbody tr td.edit_index.ajax, #index_div .add_index.ajax');
|
||||
$(document).off('click', '#table_index tbody tr td.rename_index.ajax');
|
||||
$(document).off('click', '#index_frm input[type=submit]');
|
||||
$('body').off('change', 'select[name*="field_key"]');
|
||||
$(document).off('click', '.show_index_dialog');
|
||||
@ -634,9 +632,9 @@ AJAX.registerOnload('indexes.js', function () {
|
||||
* @var $currRow Object containing reference to the current field's row
|
||||
*/
|
||||
var $currRow = $anchor.parents('tr');
|
||||
/** @var Number of columns in the key */
|
||||
/** @var {number} rows Number of columns in the key */
|
||||
var rows = $anchor.parents('td').attr('rowspan') || 1;
|
||||
/** @var Rows that should be hidden */
|
||||
/** @var {number} $rowsToHide Rows that should be hidden */
|
||||
var $rowsToHide = $currRow;
|
||||
for (var i = 1, $lastRow = $currRow.next(); i < rows; i++, $lastRow = $lastRow.next()) {
|
||||
$rowsToHide = $rowsToHide.add($lastRow);
|
||||
@ -661,7 +659,7 @@ AJAX.registerOnload('indexes.js', function () {
|
||||
$('div.no_indexes_defined').show('medium');
|
||||
$rowsToHide.remove();
|
||||
});
|
||||
$tableRef.siblings('div.notice').hide('medium');
|
||||
$tableRef.siblings('.alert-primary').hide('medium');
|
||||
} else {
|
||||
// We are removing some of the rows only
|
||||
$rowsToHide.hide('medium', function () {
|
||||
@ -677,10 +675,8 @@ AJAX.registerOnload('indexes.js', function () {
|
||||
.prependTo('#structure_content');
|
||||
Functions.highlightSql($('#page_content'));
|
||||
}
|
||||
CommonActions.refreshMain(false, function () {
|
||||
$('a.ajax[href^=#indexes]').trigger('click');
|
||||
});
|
||||
Navigation.reload();
|
||||
CommonActions.refreshMain('index.php?route=/table/structure');
|
||||
} else {
|
||||
Functions.ajaxShowMessage(Messages.strErrorProcessingRequest + ' : ' + data.error, false);
|
||||
}
|
||||
@ -689,8 +685,8 @@ AJAX.registerOnload('indexes.js', function () {
|
||||
}); // end Drop Primary Key/Index
|
||||
|
||||
/**
|
||||
*Ajax event handler for index edit
|
||||
**/
|
||||
* Ajax event handler for index edit
|
||||
**/
|
||||
$(document).on('click', '#table_index tbody tr td.edit_index.ajax, #index_div .add_index.ajax', function (event) {
|
||||
event.preventDefault();
|
||||
var url;
|
||||
@ -713,11 +709,25 @@ AJAX.registerOnload('indexes.js', function () {
|
||||
title = Messages.strEditIndex;
|
||||
}
|
||||
url += CommonParams.get('arg_separator') + 'ajax_request=true';
|
||||
Functions.indexEditorDialog(url, title, function () {
|
||||
// refresh the page using ajax
|
||||
CommonActions.refreshMain(false, function () {
|
||||
$('a.ajax[href^=#indexes]').trigger('click');
|
||||
});
|
||||
Functions.indexEditorDialog(url, title, function (data) {
|
||||
CommonParams.set('db', data.params.db);
|
||||
CommonParams.set('table', data.params.table);
|
||||
CommonActions.refreshMain('index.php?route=/table/structure');
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Ajax event handler for index rename
|
||||
**/
|
||||
$(document).on('click', '#table_index tbody tr td.rename_index.ajax', function (event) {
|
||||
event.preventDefault();
|
||||
var url = $(this).find('a').getPostData();
|
||||
var title = Messages.strRenameIndex;
|
||||
url += CommonParams.get('arg_separator') + 'ajax_request=true';
|
||||
Functions.indexRenameDialog(url, title, function (data) {
|
||||
CommonParams.set('db', data.params.db);
|
||||
CommonParams.set('table', data.params.table);
|
||||
CommonActions.refreshMain('index.php?route=/table/structure');
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* jqplot formatter for byte values
|
||||
*
|
||||
293
js/src/jquery.sortable-table.js
Normal file
293
js/src/jquery.sortable-table.js
Normal file
@ -0,0 +1,293 @@
|
||||
/**
|
||||
* This file is internal to phpMyAdmin.
|
||||
* @license see the main phpMyAdmin license.
|
||||
*
|
||||
* @fileoverview A jquery plugin that allows drag&drop sorting in tables.
|
||||
* Coded because JQuery UI sortable doesn't support tables. Also it has no animation
|
||||
*
|
||||
* @name Sortable Table JQuery plugin
|
||||
*
|
||||
* @requires jQuery
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options:
|
||||
*
|
||||
* $('table').sortableTable({
|
||||
* ignoreRect: { top, left, width, height } - Relative coordinates on each element. If the user clicks
|
||||
* in this area, it is not seen as a drag&drop request. Useful for toolbars etc.
|
||||
* events: {
|
||||
* start: callback function when the user starts dragging
|
||||
* drop: callback function after an element has been dropped
|
||||
* }
|
||||
* })
|
||||
*/
|
||||
|
||||
/**
|
||||
* Commands:
|
||||
*
|
||||
* $('table').sortableTable('init') - equivalent to $('table').sortableTable()
|
||||
* $('table').sortableTable('refresh') - if the table has been changed, refresh correctly assigns all events again
|
||||
* $('table').sortableTable('destroy') - removes all events from the table
|
||||
*/
|
||||
|
||||
/**
|
||||
* Setup:
|
||||
*
|
||||
* Can be applied on any table, there is just one convention.
|
||||
* Each cell (<td>) has to contain one and only one element (preferably div or span)
|
||||
* which is the actually draggable element.
|
||||
*/
|
||||
(function ($) {
|
||||
jQuery.fn.sortableTable = function (method) {
|
||||
var methods = {
|
||||
init: function (options) {
|
||||
var tb = new SortableTableInstance(this, options);
|
||||
tb.init();
|
||||
$(this).data('sortableTable', tb);
|
||||
},
|
||||
refresh: function () {
|
||||
$(this).data('sortableTable').refresh();
|
||||
},
|
||||
destroy: function () {
|
||||
$(this).data('sortableTable').destroy();
|
||||
}
|
||||
};
|
||||
|
||||
if (methods[method]) {
|
||||
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
|
||||
} else if (typeof method === 'object' || !method) {
|
||||
return methods.init.apply(this, arguments);
|
||||
} else {
|
||||
$.error('Method ' + method + ' does not exist on jQuery.sortableTable');
|
||||
}
|
||||
|
||||
function SortableTableInstance (table, options = {}) {
|
||||
var down = false;
|
||||
var $draggedEl;
|
||||
var oldCell;
|
||||
var previewMove;
|
||||
var id;
|
||||
|
||||
/* Mouse handlers on the child elements */
|
||||
var onMouseUp = function (e) {
|
||||
dropAt(e.pageX, e.pageY);
|
||||
};
|
||||
|
||||
var onMouseDown = function (e) {
|
||||
$draggedEl = $(this).children();
|
||||
if ($draggedEl.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (options.ignoreRect && insideRect({ x: e.pageX - $draggedEl.offset().left, y: e.pageY - $draggedEl.offset().top }, options.ignoreRect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
down = true;
|
||||
oldCell = this;
|
||||
|
||||
if (options.events && options.events.start) {
|
||||
options.events.start(this);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
var globalMouseMove = function (e) {
|
||||
if (down) {
|
||||
move(e.pageX, e.pageY);
|
||||
|
||||
if (inside($(oldCell), e.pageX, e.pageY)) {
|
||||
if (previewMove !== null) {
|
||||
moveTo(previewMove);
|
||||
previewMove = null;
|
||||
}
|
||||
} else {
|
||||
$(table).find('td').each(function () {
|
||||
if (inside($(this), e.pageX, e.pageY)) {
|
||||
if ($(previewMove).attr('class') !== $(this).children().first().attr('class')) {
|
||||
if (previewMove !== null) {
|
||||
moveTo(previewMove);
|
||||
}
|
||||
previewMove = $(this).children().first();
|
||||
if (previewMove.length > 0) {
|
||||
moveTo($(previewMove), {
|
||||
pos: {
|
||||
top: $(oldCell).offset().top - $(previewMove).parent().offset().top,
|
||||
left: $(oldCell).offset().left - $(previewMove).parent().offset().left
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
var globalMouseOut = function () {
|
||||
if (down) {
|
||||
down = false;
|
||||
if (previewMove) {
|
||||
moveTo(previewMove);
|
||||
}
|
||||
moveTo($draggedEl);
|
||||
previewMove = null;
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize sortable table
|
||||
this.init = function () {
|
||||
id = 1;
|
||||
// Add some required css to each child element in the <td>s
|
||||
$(table).find('td').children().each(function () {
|
||||
// Remove any old occurrences of our added draggable-num class
|
||||
$(this).attr('class', $(this).attr('class').replace(/\s*draggable-\d+/g, ''));
|
||||
$(this).addClass('draggable-' + (id++));
|
||||
});
|
||||
|
||||
// Mouse events
|
||||
$(table).find('td').on('mouseup', onMouseUp);
|
||||
$(table).find('td').on('mousedown', onMouseDown);
|
||||
|
||||
$(document).on('mousemove', globalMouseMove);
|
||||
$(document).on('mouseleave', globalMouseOut);
|
||||
};
|
||||
|
||||
// Call this when the table has been updated
|
||||
this.refresh = function () {
|
||||
this.destroy();
|
||||
this.init();
|
||||
};
|
||||
|
||||
this.destroy = function () {
|
||||
// Add some required css to each child element in the <td>s
|
||||
$(table).find('td').children().each(function () {
|
||||
// Remove any old occurrences of our added draggable-num class
|
||||
$(this).attr('class', $(this).attr('class').replace(/\s*draggable-\d+/g, ''));
|
||||
});
|
||||
|
||||
// Mouse events
|
||||
$(table).find('td').off('mouseup', onMouseUp);
|
||||
$(table).find('td').off('mousedown', onMouseDown);
|
||||
|
||||
$(document).off('mousemove', globalMouseMove);
|
||||
$(document).off('mouseleave', globalMouseOut);
|
||||
};
|
||||
|
||||
function switchElement (drag, dropTo) {
|
||||
var dragPosDiff = {
|
||||
left: $(drag).children().first().offset().left - $(dropTo).offset().left,
|
||||
top: $(drag).children().first().offset().top - $(dropTo).offset().top
|
||||
};
|
||||
|
||||
var dropPosDiff = null;
|
||||
if ($(dropTo).children().length > 0) {
|
||||
dropPosDiff = {
|
||||
left: $(dropTo).children().first().offset().left - $(drag).offset().left,
|
||||
top: $(dropTo).children().first().offset().top - $(drag).offset().top
|
||||
};
|
||||
}
|
||||
|
||||
/* I love you append(). It moves the DOM Elements so gracefully <3 */
|
||||
// Put the element in the way to old place
|
||||
$(drag).append($(dropTo).children().first()).children()
|
||||
.stop(true, true)
|
||||
.on('mouseup', onMouseUp);
|
||||
|
||||
if (dropPosDiff) {
|
||||
$(drag).append($(dropTo).children().first()).children()
|
||||
.css('left', dropPosDiff.left + 'px')
|
||||
.css('top', dropPosDiff.top + 'px');
|
||||
}
|
||||
|
||||
// Put our dragged element into the space we just freed up
|
||||
$(dropTo).append($(drag).children().first()).children()
|
||||
.on('mouseup', onMouseUp)
|
||||
.css('left', dragPosDiff.left + 'px')
|
||||
.css('top', dragPosDiff.top + 'px');
|
||||
|
||||
moveTo($(dropTo).children().first(), { duration: 100 });
|
||||
moveTo($(drag).children().first(), { duration: 100 });
|
||||
|
||||
if (options.events && options.events.drop) {
|
||||
// Drop event. The drag child element is moved into the drop element
|
||||
// and vice versa. So the parameters are switched.
|
||||
|
||||
// Calculate row and column index
|
||||
const colIdx = $(dropTo).prevAll().length;
|
||||
const rowIdx = $(dropTo).parent().prevAll().length;
|
||||
|
||||
options.events.drop(drag, dropTo, { col: colIdx, row: rowIdx });
|
||||
}
|
||||
}
|
||||
|
||||
function move (x, y) {
|
||||
$draggedEl.offset({
|
||||
top: Math.min($(document).height(), Math.max(0, y - $draggedEl.height() / 2)),
|
||||
left: Math.min($(document).width(), Math.max(0, x - $draggedEl.width() / 2))
|
||||
});
|
||||
}
|
||||
|
||||
function inside ($el, x, y) {
|
||||
var off = $el.offset();
|
||||
return y >= off.top && x >= off.left && x < off.left + $el.width() && y < off.top + $el.height();
|
||||
}
|
||||
|
||||
function insideRect (pos, r) {
|
||||
return pos.y > r.top && pos.x > r.left && pos.y < r.top + r.height && pos.x < r.left + r.width;
|
||||
}
|
||||
|
||||
function dropAt (x, y) {
|
||||
if (!down) {
|
||||
return;
|
||||
}
|
||||
down = false;
|
||||
|
||||
var switched = false;
|
||||
|
||||
$(table).find('td').each(function () {
|
||||
if ($(this).children().first().attr('class') !== $(oldCell).children().first().attr('class') && inside($(this), x, y)) {
|
||||
switchElement(oldCell, this);
|
||||
switched = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!switched) {
|
||||
if (previewMove) {
|
||||
moveTo(previewMove);
|
||||
}
|
||||
moveTo($draggedEl);
|
||||
}
|
||||
|
||||
previewMove = null;
|
||||
}
|
||||
|
||||
function moveTo (elem, opts = {}) {
|
||||
if (!opts.pos) {
|
||||
opts.pos = { left: 0, top: 0 };
|
||||
}
|
||||
if (!opts.duration) {
|
||||
opts.duration = 200;
|
||||
}
|
||||
|
||||
$(elem).css('position', 'relative');
|
||||
$(elem).animate({ top: opts.pos.top, left: opts.pos.left }, {
|
||||
duration: opts.duration,
|
||||
complete: function () {
|
||||
if (opts.pos.left === 0 && opts.pos.top === 0) {
|
||||
$(elem)
|
||||
.css('position', '')
|
||||
.css('left', '')
|
||||
.css('top', '');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}(jQuery));
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user