Merge branch 'QA_5_1' into STABLE

This commit is contained in:
Isaac Bennetch 2021-02-24 01:11:24 -05:00
commit 81ca97b26b
2161 changed files with 1147947 additions and 1153598 deletions

13
.browserslistrc Normal file
View 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

View File

@ -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

View File

@ -1,3 +1,4 @@
js/vendor/
js/dist/
tmp/
vendor/

View File

@ -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
View File

@ -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

View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -59,5 +59,4 @@ composer.lock
# NPM
/node_modules/
phpstan.neon
libraries/cache/
js/dist/
/setup/styles.css.map

View File

@ -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:

View File

@ -16,6 +16,14 @@
],
"ignore": ["after-comment"],
"ignoreAtRules": ["else"]
}]
}],
"value-keyword-case": [
"lower",
{
"ignoreProperties": [
"$font-family-monospace"
]
}
]
}
}

View File

@ -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

View File

@ -1,3 +1,3 @@
[weblate]
url = https://hosted.weblate.org/api/
translation = phpmyadmin/master
translation = phpmyadmin/5-1

View File

@ -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
View File

@ -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
View File

@ -1,7 +1,7 @@
phpMyAdmin - Readme
===================
Version 5.0.4
Version 5.1.0
A web interface for MySQL and MariaDB.

View File

@ -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/>`_.

View File

@ -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
View File

@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-env"]
}

View File

@ -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,
]));

View File

@ -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>

View File

@ -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}) (.+[^ ]) +&lt;(.*@.*)&gt;/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),
]);

View File

@ -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)
);

View File

@ -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
}
}

View File

@ -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);
/**

View File

@ -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;
}

View File

@ -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());

View File

@ -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>');

View File

@ -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();

View File

@ -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 .= '&amp;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(' ', '&nbsp;', $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
)
);

View File

@ -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
)
);

View File

@ -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));
}

View File

@ -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 .= '&amp;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)

View File

@ -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 .= '&amp;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());

View File

@ -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,
]);

View File

@ -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 .= '&amp;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());

View File

@ -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
)
);

View File

@ -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));

View File

@ -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);

View File

@ -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,
]));
}

View File

@ -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 .= '&amp;goto=tbl_tracking.php&amp;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);
}

View File

@ -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();

View File

@ -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/.*',
]

View File

@ -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/>`_

View File

@ -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

View File

@ -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>

View File

@ -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!
-----

View File

@ -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.

View File

@ -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.

View File

@ -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"

View File

@ -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>`_.

View File

@ -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();
}

View File

@ -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) {

View File

@ -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');

View File

@ -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.
*

View File

@ -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>';
}
?>

View File

@ -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;
}

View File

@ -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);

View File

@ -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');
}

View File

@ -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
View File

@ -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
View 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
View File

@ -0,0 +1,2 @@
/*
!/.gitignore

File diff suppressed because it is too large Load Diff

View File

@ -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 });
});
});
}
});

View File

@ -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>',

View File

@ -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,

View File

@ -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')

View File

@ -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');

View File

@ -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);
}

View File

@ -1,4 +1,3 @@
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Conditionally included if framing is not allowed
*/

View File

@ -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 () {

View File

@ -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());
});
});

View File

@ -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);
}

View File

@ -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);

View File

@ -1,4 +1,3 @@
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* @fileoverview function used in QBE for DB
* @name Database Operations

View File

@ -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();

View File

@ -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);

View File

@ -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: {

View File

@ -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;

View File

@ -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';
});
});

View File

@ -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 () {

View File

@ -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');

View File

@ -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

View File

@ -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);
}
});
});

View File

@ -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');
});
});

View File

@ -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 +
'&nbsp;<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');

View File

@ -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();

View File

@ -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;
}

View File

@ -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');
});
});

View File

@ -1,4 +1,3 @@
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* jqplot formatter for byte values
*

View 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