Merge branch 'QA_4_7' into STABLE

This commit is contained in:
Isaac Bennetch 2017-03-29 08:45:02 -04:00
commit 6519211304
1220 changed files with 391128 additions and 529657 deletions

26
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,26 @@
### Steps to reproduce
1.
2.
3.
### Expected behaviour
Tell us what should happen
### Actual behaviour
Tell us what happens instead
### Server configuration
**Operating system**:
**Web server:**
**Database:**
**PHP version:**
**phpMyAdmin version:**
### Client configuration
**Browser:**
**Operating system:**

6
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,6 @@
Before submitting pull request, please check that every commit:
- [ ] Has proper Signed-Off-By
- [ ] Has commit message which describes it
- [ ] Is needed on it's own, if you have just minor fixes to previous commits, you can squash them
- [ ] Any new functionality is covered by tests

2
.gitignore vendored
View File

@ -34,6 +34,7 @@ web.config
/js/line_counts.php
# API documentation
/apidoc/
/doc/linkcheck/
# Demo server
revision-info.php
# PHPUnit
@ -48,5 +49,4 @@ phpunit.xml
# Ant cache
cache.properties
# Composer
composer.lock
/vendor/

View File

@ -3,8 +3,16 @@ imports:
- javascript
- php
filter:
excluded_paths: [libraries/php-gettext/*, libraries/tcpdf/*, libraries/bfShapeFiles/*, libraries/phpseclib/*, libraries/plugins/auth/recaptchalib.php, libraries/sql-formatter/*, js/jquery/*, js/jqplot/*, js/openlayers/*, js/codemirror/*, js/canvg/*, js/tracekit/*, js/OpenStreetMap.js, js/sprintf.js, test/libraries/php-gettext/*, test/libraries/sql-formatter/*]
tools:
php_code_sniffer:
config:
standard: "PMAStandard"
excluded_paths: [js/jquery/*, js/jqplot/*, js/openlayers/*, js/codemirror/*, js/canvg/*, js/tracekit/*, js/sprintf.js]
build:
dependencies:
before:
- composer install
- ./vendor/bin/phpcs --config-set installed_paths `pwd`/vendor/phpmyadmin/coding-standard
tests:
override:
-
command: './vendor/bin/phpcs --standard=PMAStandard ./ --report=checkstyle --report-file=cs-data --ignore=*/vendor/*,*/canvg/*,*/codemirror/*,*/openlayers/*,*/jquery/*,*/jqplot/*,*/build/*'
analysis:
file: 'cs-data' # The reporter filename
format: 'php-cs-checkstyle' # The supported format by Scrutinizer

View File

@ -3,66 +3,92 @@
# - run lint for every PHP version
# - run Selenium for single PHP version
dist: trusty
language: php
services:
- mysql
php:
- "7.1"
- "7.0"
- "5.6"
- "5.5"
- hhvm
- hhvm-3.3
- hhvm-3.12
- hhvm-3.18
sudo: false
sudo: required
env:
matrix:
- PHPUNIT_ARGS="--exclude-group selenium"
- CI_MODE=test
global:
- TESTSUITE_USER=root
- TESTSUITE_PASSWORD=root
- TESTSUITE_URL=http://127.0.0.1:8000
install:
- pip install --user codecov
- ./test/install-runkit
- ./test/install-browserstack
- composer install --dev --no-interaction
- ./test/ci-install-$CI_MODE
- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then case "$TRAVIS_PHP_VERSION" in hhvm*) ;; *) phpenv config-add test/php-noprofile.ini ;; esac ; fi
before_script:
- if [ $TRAVIS_PHP_VERSION != "hhvm" ] ; then phpenv config-add test/php-noprofile.ini ; fi
- export PATH=~/.composer/vendor/bin/:$PATH
- mysql -uroot -e "CREATE DATABASE test"
- 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:
- ant clean
- ant locales
- ant lint
- set -e;
if [ $TRAVIS_PHP_VERSION == "hhvm" ] ; then
ant phpunit-hhvm ;
else
if [ ! -z "$SELENIUM" ] ; then
ant phpunit-nocoverage ;
else
ant phpunit ;
fi ;
fi
- ./scripts/generate-mo --quiet
- if [ $CI_MODE = test ] ; then ./test/ci-lint ; fi
- ./test/ci-$CI_MODE
after_script:
- if [ -f vendor/bin/coveralls ] ; then php vendor/bin/coveralls -v || true ; fi
- if [ -f vendor/bin/codacycoverage ] ; then php vendor/bin/codacycoverage clover || true ; fi
- codecov
- if [ -f php.log ] ; then cat php.log ; fi
- if [ -f build/logs/phpunit.json ] ; then ./scripts/phpunit-top-tests build/logs/phpunit.json ; fi
after_success:
- bash <(curl -s https://codecov.io/bash)
matrix:
allow_failures:
- php: "7.0"
env: CI_MODE=selenium
fast_finish: true
include:
- php: "7.0"
env: CI_MODE=selenium
- php: "7.0"
env: CI_MODE=release
- php: "7.0"
env: CI_MODE=docs
- os: osx
language: generic
env: CI_MODE=test
before_install:
- brew tap homebrew/php
- brew update
- brew install gettext php70 mariadb
- brew link --force gettext
- curl https://getcomposer.org/installer | php
- ln -s "`pwd`/composer.phar" /usr/local/bin/composer
- mysql.server start
cache:
pip: true
directories:
- $HOME/.composer/cache/
- $HOME/browserstack
- $HOME/runkit
# trigger Buildtime Trend Service to parse Travis CI log
notifications:
webhooks:
- https://buildtimetrend.herokuapp.com/travis
# Install APT packages
# - git > 2.5.1 needed for worktrees
# - mysql server does not seem to be always present on Travis Trusty environment
addons:
apt:
packages:
- git
- mysql-server-5.6

View File

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

View File

@ -20,9 +20,10 @@ Please report [bugs on GitHub][1].
## Patches submission
Patches are welcome as [pull requests on GitHub][2]. Please include a
Signed-off-by tag. Note that by submitting patches with the Signed-off-by
tag, you are giving permission to license the patch as GPLv2-or-later. See
[the DCO file][3] for details.
Signed-off-by tag in the commit message (you can do this by passing `--signoff`
parameter to Git). Note that by submitting patches with the Signed-off-by tag,
you are giving permission to license the patch as GPLv2-or-later. See [the DCO
file][3] for details.
[2]: https://github.com/phpmyadmin/phpmyadmin/pulls
[3]: https://github.com/phpmyadmin/phpmyadmin/blob/master/DCO

515
ChangeLog
View File

@ -1,6 +1,115 @@
phpMyAdmin - ChangeLog
======================
4.7.0 (2017-03-28)
- patch #12233 [Display] Improve message when renaming database to same name
- issue #6146 Log authentication attempts to syslog
- issue #11981 Remove support for Swekey authentication
- issue #11987 Remove code for no longer supported MSIE versions
+ issue #11962 Remove embedded PHP libraries, use composer to install them
+ issue #12017 Cannot easily select multiple tables when exporting
+ issue #12047 Add javascript filtering for databases
- issue #12166 More compact rendering of navigation tree
+ issue #12129 Improve performance with SkipLockedTables
- issue #12173 Do not hide indexes under a slider
- issue Improve performance of zip file import
- issue #12196 Removed $cfg['ThemePath']
- issue #6274 Add support for export user settings as config.inc.php snippet
- issue #5555 Better report query errors while generating SQL exports
- issue #12307 Produce valid JSON on export
- issue #12325 Setup script icons broken
- issue #12378 Support IPv6 proxies
- issue Removed MySQL connection retry without password
- issue #12218 Allow to specify further parameters for control connection
- issue #12162 Show charset for each table on Database structure page
- issue #12463 Incorrect link in the href of icon at Hide/Show unhide links
- issue #12330 Shortcut for closing console
- issue #12465 Improved handling of http requests
- issue #12474 Broken links in Setup forms Navigation
- issue #12494 Can't add a new User
- issue #12523 Add 'token' Parameter in all POST requests (Fix 'Token mismatch' errors)
- issue #12302 Improved usage of number_format
- issue #12656 Server selection not working
- issue #12543 NULL results in dataset are colored grey
- issue #12664 Create Bookmark broken
- issue #12688 Use unsigned int for storing bookmark ID
- issue #12352 Added password strength indicator
- issue #12713 Correctly handle HTTP status when doing requests
- issue #12247 Add option to delete settings from browser storage
- issue #12783 Remove unused PMA_addJSCode function
- issue #12069 Add table filtering to database structure
- issue #12799 Allow to configure signon session parameters
- issue #12854 Drop database is broken
- issue #12863 Can't toggle Event Scheduler on
- issue #12742 Finish removing dead code references to xls/xlsx import and export, which was removed some time ago.
- issue #12536 Rename "Relations" to "Relationships" in many places as it's the more proper term
- issue #12834 Fixed margins in central columns feature
- issue #12903 Document more export configuration options
- issue #12897 Use consistent numeric format for table overhead
- issue #12901 Use server returned table name on renaming table
- issue #12918 Always use \r\n as newline when editing fields
- issue #12923 Fixed server side search in navigation panel
- issue #12929 Undefined index warning with ssl_ca_paths
- issue #12924 Do not show errors from OpenSSL cookie encryption/decryption
- issue #12945 Fixed hint rendering on adding new user
- issue #12941 Fixed sorting of tables in relation view
- issue #12936 Fixed tables pagination in navigation panel
- issue #12904 Do not collapse add form for central columns if there are none
- issue #12955 Fixed database renaming
- issue #12954 Fixed export of tracking data
- issue #12960 Enclose exports in transaction by default
- issue #12966 After adding a column ADD INDEX option won't be displayed when enabling AI
- issue #12972 Better error message when Composer has not been run
- issue #12988 Do not show language selector without choices
- issue #12993 Fixed external links to php documentation
- issue #12990 Fixed error when loading favorite tables to console
- issue #12981 Improved rendering of new version information
- issue #12922 Fixed bookmarks ordering
- issue #12964 Fixed table search in navigation
- issue #12985 Fixed rendering of foreign key browsing
- issue #12957 Fixed manipulation with GIS data having zero coordinates
- issue #12804 Fixed various designer javascript errors
- issue #12934 Fixed possible javascript error on server status page
- issue #12927 Fixed javascript error on 3NF normalization
- issue #12996 List all databses in navigation panel database dropdown
- issue #12980 Better defaults when creating multi field foreign key
- issue #12976 Improved foreign key editor behavior
- issue #12958 Always show error reporting dialog on top
- issue #12693 Improved support for TokuDB
- issue #11231 Try harder to honor LoginCookieValidity setting
- issue #13016 and #13017 Slight improvements to the table layout of Relation view
- issue #12345 Correctly show affected rows for LOAD DATA queries
- issue #13010 Copy database: SQL error for copying PMADB metadata
- issue #13002 Fixed OpenDocument exports
- issue #13000 Align NULL values according to the column alignment
- issue #13021 Show phpMyAdmin errors even with error_reporting set to 0
- issue #13020 Removed warning about client and server versions mismatch
- issue Hide comments on table Structure tab when no comment is set
- issue Fixed submission of error reports
- issue #13033 Use Referrer-Policy header to specify referrer policy
- issue Fixed javascript confirmation of dangerous queries
- issue #13040 Compatibility with hhvm 3.18
- issue #13031 Fixed displaying of all rows
- issue #12967 Fixed related field selection for native relations
- issue #13045 Properly escape MIME transformatoin names
- issue #13028 Always show 100% in font selector
- issue #13047 Fix query simulating for more servers
- issue #12846 Fix new version check for sites with wrongly configured curl
- issue #12951 When exporting to Excel, the default is now to include column names in the first row
- issue #13059 Removed debugging code
- issue #13029 Fixed table tracking for nested table groups
- issue #13053 Fixed broken links in setup
- issue #12708 Removed phpMyAdmin version from User-Agent header
- issue #13084 Do not point users to setup when it is disabled
- issue #12660 Delete only phpMyAdmin cookies on upgrade
- issue #13088 Fixed editing of rows with text primary key
- issue #13092 Do not try to sync favorite tables if configuration storage is not enabled
- issue #13105 Fixed changing attribute for virtual field
- issue #12757 Fixed setting password on recent MariaDB with non working plugins
- issue #12349 Fixed undefined variable on import from some formats
- issue #13103 Do not offer default names for copying/renaming databases
- issue [security] Possible to bypass $cfg['Servers'][$i]['AllowNoPassword'], see PMASA-2017-08
4.6.6 (2017-01-23)
- issue #12759 Fix Notice regarding 'Undefined index: old_usergroup'
- issue #12760 Fix Notice regarding 'Undefined index: users'
@ -48,412 +157,6 @@ phpMyAdmin - ChangeLog
- issue [security] SSRF in replication, see PMASA-2017-6.
- issue [security] DOS in replication status, see PMASA-2017-7.
4.6.5.2 (2016-12-05)
- issue #12765 Fixed SQL export with newlines
4.6.5.1 (2016-11-25)
- issue #12735 Incorrect parameters to escapeString in Node.php
- issue #12734 Fix PHP error when mbstring is not installed
- issue #12736 Don't force partition count to be specified when creating a new table
4.6.5 (2016-11-24)
- issue Remove potentionally license problematic sRGB profile
- issue #12459 Display read only fields as read only when editing
- issue #12384 Fix expanding of navigation pane when clicking on database
- issue #12430 Impove partitioning support
- issue #12374 Reintroduced simplified PmaAbsoluteUri configuration directive
- issue Always use UTC time in HTTP headers
- issue #12479 Simplified validation of external links
- issue #12483 Fix browsing tables with built in transformations
- issue #12485 Do not show warning about short blowfish_secret if none is set
- issue #12251 Fixed random logouts due to wrong cookie path
- issue #12480 Fixed editing of ENUM/SET/DECIMAL fields structure
- issue #12497 Missing escaping of configuration used in SQL (hide_db and only_db)
- issue #12476 Add error checking in reading advisory rules file
- issue #12477 Add checking missing elements and confirming element types from json_decode
- issue #12251 Automatically save SQL query in browser local storage rather than in cookie
- issue #12292 Unable to edit transformations
- issue #12502 Remove unused paramenter when connecting to MySQLi
- issue #12303 Fix number formatting with different settings of precision in PHP
- issue #12405 Use single quotes in PHP code
- issue #12534 Option for the dropped column is not removed from 'after_field' select, after the column is dropped
- issue #12531 Properly detect DROP DATABASE queries
- issue #12470 Fix possible race condition in setting URL hash
- issue #11924 Remove caching of server information
- issue #11628 Proper parsing of INSERT ... ON DUPLICATE KEY queries
- issue #12545 Proper parsing of CREATE TABLE ... PARTITION queries
- issue #12473 Code can throw unhandled exception
- issue #12550 Do not try to keep alive session even after expiry
- issue #12512 Fixed rendering BBCode links in setup
- issue #12518 Fixed copy of table with generated columns
- issue #12221 Fixed export of table with generated columns
- issue #12320 Copying a user does not copy usergroup
- issue #12272 Adding a new row with default enum goes to no selection when you want to add more then 2 rows
- issue #12487 Drag and drop import prevents file dropping to blob column file selector on the insert tab
- issue #12554 Absence of scrolling makes it impossible to read longer text values in grid editing
- issue #12530 "Edit routine" crashes when the current user is not the definer, even if privileges are adequate
- issue #12300 Export selective tables by-default dumps Events also
- issue #12298 Fixed export of view definitions
- issue #12242 Edit routine detail dialog does not fill "Return length" field in mysql functions
- issue #12575 New index Confirm adds whitespace around the field name
- issue #12382 Bug in zoom search
- issue #12321 Assign LIMIT clause only to syntactically correct queries
- issue #12461 Can't Execute SQL With Sub-Query Due To "LIMIT 0,25" Inserted At Wrong Place
- issue #12511 Clarify documentation on ArbitraryServerRegexp
- issue #12508 Remove duplicate code in SQL escaping
- issue #12475 Cleanup code for getting table information
- issue #12579 phpMyAdmin's export of a Select statment without a FROM clause generates Wrong SQL
- issue #12316 Correct export of complex SELECT statements
- issue #12080 Fixed parsing of subselect queries
- issue #11740 Fixed handling DELETE ... USING queries
- issue #12100 Fixed handling of CASE operator
- issue #12455 Query history stores separate entry for every letter typed
- issue #12327 Create PHP code no longer works
- issue #12179 Fixed bookmarking of query with multiple statements
- issue #12419 Wrong description on GRANT OPTION
- issue #12615 Fixed regexp for matching browser versions
- issue #12569 Avoid showing import errors twice
- issue #12362 prefs_manage.php can leave an orphaned temporary file
- issue #12619 Unable to export csv when using union select
- issue #12625 Broken Edit links in query results of JOIN query
- issue #12634 Drop DB error in import if DB doesn't exist
- issue #12338 Designer reverts to first saved ER after EACH relation create or delete
- issue #12639 'Show trace' in Console generates JS error for functions in query's trace called without any arguments
- issue #12366 Fix user creation with certain MariaDB setups
- issue #12616 Refuse to work with mbstring.func_overload enabled
- issue #12472 Properly report connection without password in setup
- issue #12365 Fix records count for large tables
- issue #12533 Fix records count for complex queries
- issue #12454 Query history not updated in console until page refresh
- issue #12344 Fixed parsing of labels in loop
- issue #12228 Fixed parsing of BEGIN labels
- issue #12637 Fixed editing some timestamp values
- issue #12622 Fixed javascript error in designer
- issue #12334 Missing page indicator or VIEWs
- issue #12610 Export of tables with Timestamp/Datetime/Time columns defined with ON UPDATE clause with precision fails
- issue #12661 Error inserting into pma__history after timeout
- issue #12195 Row_format = fixed not visible
- issue #12665 Cannot add a foreign key - non-indexed fields not listed in InnoDB tables
- issue #12674 Allow for proper MySQL-allowed strings as identifiers
- issue #12651 Allow for partial dates on table insert page
- issue #12681 Fixed designer with tables using special chars
- issue #12652 Fixed visual query builder for foreign keys with more fields
- issue #12257 Improved search page performance
- issue #12322 Avoid selecting default function for foreign keys
- issue #12453 Fixed escaping of SQL parts in some corner cases
- issue #12542 Missing table name in account privileges editor
- issue #12691 Remove ksort call on empty array in PMA_getPlugins function
- issue #12443 Check parameter type before processing
- issue #12299 Avoid generating too long URLs in search
- issue #12361 Fix self SQL injection in table-specific privileges
- issue #12698 Add link to release notes and download on new version notification
- issue #12712 Error when trying to setup replication (fatal error in call to an old PMA_DBI_connect function)
- issue [security] Unsafe generation of $cfg['blowfish_secret'], see PMASA-2016-58
- issue [security] phpMyAdmin's phpinfo functionality is removed, see PMASA-2016-59
- issue [security] AllowRoot and allow/deny rule bypass with specially-crafted username, see PMASA-2016-60
- issue [security] Username matching weaknesses with allow/deny rules, see PMASA-2016-61
- issue [security] Possible to bypass logout timeout, see PMASA-2016-62
- issue [security] Full path disclosure (FPD) weaknesses, see PMASA-2016-63
- issue [security] Multiple XSS weaknesses, see PMASA-2016-64
- issue [security] Multiple denial-of-service (DOS) vulnerabilities, see PMASA-2016-65
- issue [security] Possible to bypass white-list protection for URL redirection, see PMASA-2016-66
- issue [security] BBCode injection to login page, see PMASA-2016-67
- issue [security] Denial-of-service (DOS) vulnerability in table partitioning, see PMASA-2016-68
- issue [security] Multiple SQL injection vulnerabilities, see PMASA-2016-69
- issue [security] Incorrect serialized string parsing, see PMASA-2016-70
- issue [security] CSRF token not stripped from the URL, see PMASA-2016-71
4.6.4 (2016-08-16)
- issue [security] Weaknesses with cookie encryption, see PMASA-2016-29
- issue [security] Improve session cookie code for openid.php and signon.php example files
- issue [security] Full path disclosure in openid.php and signon.php example files
- issue [security] Multiple XSS vulnerabilities, see PMASA-2016-30
- issue [security] Multiple XSS vulnerabilities, see PMASA-2016-31
- issue [security] Unsafe generation of BlowfishSecret (when not supplied by the user)
- issue [security] Referrer leak when phpinfo is enabled
- issue [security] PHP code injection, see PMASA-2016-32
- issue [security] Full path disclosure, see PMASA-2016-33
- issue [security] SQL injection attack, see PMASA-2016-34
- issue [security] Local file exposure through LOAD DATA LOCAL INFILE, see PMASA-2016-35
- issue [security] Local file exposure through symlinks with UploadDir, see PMASA-2016-36
- issue [security] Path traversal with SaveDir and UploadDir, see PMASA-2016-37
- issue [security] Multiple XSS vulnerabilities, see PMASA-2016-38
- issue [security] SQL injection vulnerability as control user, see PMASA-2016-39
- issue [security] SQL injection vulnerability, see PMASA-2016-40
- issue [security] Denial-of-service attack through transformation feature, see PMASA-2016-41
- issue [security] SQL injection vulnerability as control user, see PMASA-2016-42
- issue [security] Verify data before unserializing, see PMASA-2016-43
- issue [security] Use HTTPS for wiki links
- issue Remove Swekey support
- issue [security] Denial-of-service attack with $cfg['AllowArbitraryServer'] = true and persistent connections, see PMASA-2016-45
- issue [security] Improve SSL certificate handling
- issue [security] Fix full path disclosure in debugging code
- issue [security] Possible circumvention of IP-based allow/deny rules with IPv6 and proxy server, see PMASA-2016-47
- issue [security] Detect if user is logged in, see PMASA-2016-48
- issue [security] Bypass URL redirection protection, see PMASA-2016-49
- issue [security] Referrer leak, see PMASA-2016-50
- issue [security] Reflected File Download, see PMASA-2016-51
- issue [security] ArbitraryServerRegexp bypass, see PMASA-2016-52
- issue [security] Denial-of-service attack by entering long password, see PMASA-2016-53
- issue [security] Remote code execution vulnerability when running as CGI, see PMASA-2016-054
- issue [security] Administrators could trigger SQL injection attack against users
- issue [security] Denial-of-service attack when PHP uses dbase extension, see PMASA-2016-55
- issue [security] Remove tode execution vulnerability when PHP uses dbase extension, see PMASA-2016-56
- issue [security] Denial-of-service attack by using for loops, see PMASA-2016-46
- issue Include X-Robots-Tag header in responses
- issue Enforce numeric field length when creating table
- issue Fixed invalid Content-Length in some HTTP responses
- issue #12394 Create view should require a view name
- issue #12391 Message with 'Change password successfully' displayed, but does not take effect
- issue Tighten control on PHP sessions and session cookies
- issue #12409 Re-enable overhead on server databases view
- issue #12414 Fixed rendering of Original theme
- issue #12413 Fixed deleting users in non English locales
- issue #12416 Fixed replication status output in Databases listing
- issue #12303 Avoid typecasting to float when not needed
- issue #12425 Duplicate message variable names in messages.inc.php
- issue #12399 Adding index to table shows wrong top navigation
- issue #12424 Fixed password change on MariaDB without auth plugin
- issue #12339 Do not error on unset server port
- issue #12422 Improvements to the original theme
- issue #12395 Do not try to load old transformation plugins
- issue #12423 Fixed replication status in database listing
- issue #12433 Copy table with prefix does not copy the indexes
- issue #12375 Search in database: Window content is not scrolling down when clicking first time on Browse link
- issue #12346 SQL Editor textareas can have their size increased from the top, distorting the page view
4.6.3 (2016-06-23)
- issue #12249 Fixed cookie path on Windows
- issue #12279 Fixed error reporting on connect problems
- issue #12290 Fixed export of tables without explicitly set engine
- issue #12285 Designer JavaScript error: Show/Hide tables list
- issue #12293 Fix MySQL SSL connection with some PHP versions
- issue #12279 Fix MySQL connection error on version mismatch
- issue #12281 Keep user attributes (privileges, authentication mode, etc) when copying a user
- issue #12308 Fix division by zero in case of misconfigured MySQL server
- issue #12317 Fix editing server variables
- issue #12303 Fix table size calculation in some circumstances
- issue #12310 Fix listing routines for non privileged user
- issue Escape generated query in exporting a database
- issue Setup script doesn't use input type 'password' in all relevant locations
- issue [security] BBCode injection in setup script, see PMASA-2016-17
- issue [security] Cookie attribute injection attack, see PMASA-2016-18
- issue Redirect loop when directly calling url.php
- issue [security] SQL injection attack, see PMASA-2016-19
- issue [security] XSS attack in Table Structure page, see PMASA-2016-20
- issue [security] XSS attack in Server Privileges page, see PMASA-2016-21
- issue [security] DOS attack vulnerability, see PMASA-2016-22
- issue [security] Multiple full path disclosure vulnerabilities, see PMASA-2016-23
- issue [security] Full path disclosure when running in debug mode
- issue [security] XSS attack with partition range and table structure, see PMASA-2016-25
- issue [security] XSS attack when checking database privileges, see PMASA-2016-26
- issue [security] XSS attack when MySQL server is using a specific payload log_bin directive, see PMASA-2016-26
- issue [security] XSS vulnerabilities in Transformation feature, see PMASA-2016-26
4.6.2 (2016-05-25)
- issue [security] User SQL queries can be revealed through URL GET parameters, see PMASA-2016-14
- issue [security] Self XSS vulneratbility, see PMASA-2016-16
- issue #12225 Use https for documentation links
- issue #12234 Fix schema export with too many tables
- issue #12240 Avoid parsing non JSON responses as JSON
- issue #12244 Avoid using too log URLs when getting javascripts
- issue #12118 Fixed setting mixed case languages
- issue #12229 Avoid storing objects in session when debugging SQL
- issue #12249 Fix cookie path on IIS
- issue #11705 Fix occassional 200 errors on Windows
- issue #12219 Fix locking issues when importing SQL
- issue #12231 Avoid confusing warning when mysql extension is missing
- issue Improve handling of logout
- issue Safer handling of sessions during authentication
- issue #12209 Fix server selection on main page
- issue #12192 Avoid storing full error data in session
- issue #12082 Fixed export of ARCHIVE tables with keys
- issue #11565 Add session reload for config authentication
- issue #12229 Do not fail on errors stored in session
- issue #12248 Fix loading of APC based upload progress bar
4.6.1 (2016-05-02)
- issue #12120 PMA_Util not found in insert_edit.lib.php
- issue #12118 Fixed activation of some languages
- issue #12121 Fixed error in 3NF step of normalization
- issue #12135 Fix offering JSON datatype in incompatible MySQL versions
- issue #12132 Can not open table with JSON field
- issue #12125 Cannot highlight a column if I scroll down from the top of the table
- issue #12154 Fixed possible PHP error in SQL parser
- issue #12029 Fixed SQL quoting in SQL export
- issue #12129 Improve performance of database structure page
- issue #12159 Fix PHP error if user did unpack new version over old one
- issue #12165 Fix parsing of expression 0
- issue #12146 Document setup with Google Cloud SQL
- issue #12197 Fix parsing of queries with double \
- issue #12202 Fixed setting of language from user configuration
- issue #12200 Fixed check for ndb version
- issue #12206 Fixed loading of configuration file
- issue #12204 Check if sessions are working and report failures
- issue #12211 non-clickable initial letter for users / and can't modify users with MySQL 5.7.12
- issue #12215 Fixed config tab persistence errors
- issue #12217 Fixed javascript erros on user creation
- issue #12144 Fixed parsing of some AS clauses
- issue #12205 Fixed parsing of FULL OUTER JOIN queries
- issue #12171 Fixed editing of VIEW structure
- issue #12208 Avoid printing executed queries on import
4.6.0.0 (2016-03-22)
+ issue #11456 Disabled storage engines
+ issue #11479 Allow setting routine wise privileges
- issue Hide Insert tab for non-updatable views
+ issue #11490 UI for defining partitioning in create table window
+ issue #11438 Support JSON data type
+ issue Editing partitions in table Structure
- issue Tracking does not make sense for information_schema
- issue #11550 Regression in Find and replace
+ issue #11619 TokuDB Tables Show Size as "unknown"
+ issue #11654 Use a slider for Internal relations
+ issue #11641 Ability to disable the navigationhiding Feature
- issue #11647 Restrict configuration NavigationTreeDbSeparator to strings
- issue #11667 Disable the tooltip in the navigation panel's filter box
+ issue Copy results to clipboard
+ issue #11504 Reactivate cut&paste possibility in print view
- issue #11702 Extraneous message after edit + grid-edit
- issue #11668 Table header is empty with browsing an empty table
+ issue #11701 Allow changing parameter order of routines
- issue #11708 Remove no password warning
+ issue #11711 Clarify the meaning of "Stand-in structure for view" in SQL export
- issue HTML line break shown after a MySQL connection error message
- issue #11728 CSV import skip row count after
- issue Fixed displaying of SQL query on table operations
- issue #6321 Display binary strings as text if they are valid UTF-8
+ issue #11743 Display routine specific privileges
+ issue #11538 Copy multiple tables to database
+ issue Support Cloudflare Flexible SSL
- issue Handle empty TABLE_COMMENT
+ issue #11833 Drop support for old Internet Explorer versions
+ issue #11796 Use modals for displaying forms in db structure page
+ issue #11789 Show MySQL error messages in user language
+ issue Add 'ssl_verify' configuration directive for self-signed certificates with mysqlnd and PHP >= 5.6
+ issue #11874 Show more used PHP extensions
- issue #11874 Report when version check and error reporting are disabled
- issue #11849 Fix PDF schema export
- issue #11412 Remove ForceSSL configuration directive
- issue Remove support for Mozilla Prism
- issue #11412 Remove PmaAbsoluteUri configuration directive
- issue #11914 Fix autoloading of phpseclib
- issue #11880 Fixed rendering of missing extension error
- issue #11923 Errors on Structure tab when user only has select access on certain columns
- issue #11972 Missing documentation for $cfg['Servers'][$i]['favorite'] and $cfg['NumFavoriteTables']
- issue #11907 Avoid displaying UPDATE query twice
- issue #11850 Fixed CSV import
- issue Fix SQL syntax highlighting in database search page
- issue #12056 Fix error when we can not generate random string
- issue #12055 Fixed PHP syntax error in templates
- issue #12054 Fixed processing of queries with escaped quotes
- issue #12041 Fixed exporting tables with fields DEFAULT and COMMENT
- issue #12073 Hide edit and delete buttons when the results are not related to a table
- issue #12083 Fixed parsing of field definition
- issue #12081 Fixed rendering of table stats
- issue #11705 Fixed problems with PHP on Windows on table structure
- issue #12085 Like search strings being escaped incorrectly
- issue #12092 Rename exported databases/tables doesn't seem to work
- issue #12099 Undefined index: controllink
- issue #12094 PHP Fatal error: Call to undefined function __()
- issue #12098 Fix login after logout with http authentication
- issue #12074 Fixed possible invalid SQL export
- issue #12026 Fixed parsing of UNION SELECT with brackets
- issue #12109 Fixed parsing of CREATE TABLE [AS] SELECT
- issue #12105 Multi-server drap-and-drop import always fails
- issue #12116 Fulltext indexes are not copied when using copy database function
4.5.5.1 (2016-02-29)
- issue #11971 CREATE UNIQUE INDEX index type is not recognized by parser.
- issue #11982 Row count wrong when grouping joined tables.
- issue #12012 Column definition with default value and comment in CREATE TABLE expoerted faulty.
- issue #12020 New statement but no delimiter and unexpected token with REPLACE.
- issue #12029 Fixed incorrect usage of SQL parser context in SQL export
- issue [security] XSS vulnerability in SQL parser, see PMASA-2016-10.
- issue [security] Multiple XSS vulnerabilities, see PMASA-2016-11.
- issue [security] Multiple XSS vulnerabilities, see PMASA-2016-12.
- issue [security] Vulnerability allowing man-in-the-middle attack on API call to GitHub, see PMASA-2016-13.
- issue #12048 Fixed inclusion of gettext library from SQL parser
4.5.5.0 (2016-02-22)
- issue Undefined index: is_ajax_request
- issue #11855 Fix password change on MariaDB 10.1 and newer
- issue #11874 Validate version information before further processing it
- issue #11881 Full processlist lost on refresh
- issue #11834 Adjust privileges fails if database name contains underscores
- issue #11906 'Loading...' banner shows on login screen
- issue #11930 Fixed changing of table parameters, eg. AUTO_INCREMENT
- issue #11885 Call to undefined function SqlParser\ctype_alnum()
- issue #11879 4.5.3.1 - NOW() function not recognized by parser
- issue #11867 Gracefully handle the DESC statement
- issue #11843 Fractional timestamp causes corrupted SQL export
- issue #11836 Static analysis error for valid WHERE condition with IF keyword
- issue #11800 Syntax Verifier error using REGEXP in SQL statement
- issue #11799 Backslashes in comments are being interpreted as escape characters
- issue #11909 Can't insert row into table that contains generated column
- issue #11677 sql-parser and php-gettext collide.
- issue #11920 Can't disable backquotes in export
- issue #11911 Inserts via tbl_change.php in VARBINARY columns does not allow using HEX() and MD5()
- issue #11939 Correct content type for uploaded error reports
- issue #11940 Silent errors from checking local documentation
- issue #11944 Fixed error on servers with disabled php_uname
- issue #11946 Correctly store and report file upload errors
- issue #11948 Avoid javascript errors on invalid location hash
- issue #11950 Fix PHP warning on configuration errors
- issue #11951 Silent errors on checking for writable folders
- issue #11952 Silent warning on invalid file upload
- issue #11953 Do not fail getting filename with open_basedir limitations
- issue #11956 unrecognized keyword interval
- issue Field names and aliases are being correctly parsed now.
- issue #11959 Fix javascript error in setup
- issue #11964 Undefined index: TABLE_COMMENT in database structure page
- issue #11967 Fix PHP error on loading invalid XML or ODS file
- issue #11969 Missing confirmation while dropping a view in view_operations.php
- issue #11968 Fix export of index comments in SQL
- issue #11979 DECLARE not accepted as valid SQL
4.5.4.1 (2016-01-29)
- issue #11892 Error with PMA 4.4.15.3
- issue #11896 Remove hard dependency on phpseclib
4.5.4.0 (2016-01-28)
- issue #11724 live data edit of big sets is not working
- issue Table list not saved in db QBE bookmarked search
- issue #11777 While 'changing a column', query fails with a syntax error after the 'CHARSET=' keyword
- issue #11783 Avoid syntax error in javascript messages on invalid PHP setting for max_input_vars
- issue #11784 Properly handle errors in upacking zip archive
- issue #11785 Set PHP's internal encoding to UTF-8
- issue #11786 Fixed Kanji encoding in some specific cases
- issue #11787 Check whether iconv works before using it
- issue #11788 Avoid conversion of MySQL error messages
- issue #11792 Undefined index: parameters
- issue #11802 Undefined index: field_name_orig
- issue Undefined index: host
- issue #11810 'Add to central columns' (per column button) does nothing
- issue #11727 SQL duplicate entry error trying to INSERT in designer_settings table
- issue #11798 Fix handling of databases with dot in a name
- issue #11820 Fix hiding of page content behind menu
- issue #11780 FROM clause not generated after loading search bookmark
- issue #11826 Fix creating/editing VIEW with DEFINER containing special chars
- issue #11828 Do not invoke FLUSH PRIVILEGES when server in --skip-grant-tables
- issue #11804 Misleading message for configuration storage
- issue #11772 Table pagination does nothing when session expired
- issue #11840 Index comments not working properly
- issue #11791 Better handle local storage errors
- issue #11752 Improve detection of privileges for privilege adjusting
- issue #11854 Undefined property: stdClass::$releases at version check when disabled in config
- issue #11814 SQL comment and variable stripped from bookmark on save
- issue Gracefully handle errors in regex based javascript search
- issue [security] Multiple full path disclosure vulnerabilities, see PMASA-2016-1
- issue [security] Unsafe generation of CSRF token, see PMASA-2016-2
- issue [security] Multiple XSS vulnerabilities, see PMASA-2016-3
- issue [security] Insecure password generation in JavaScript, see PMASA-2016-4
- issue [security] Unsafe comparison of CSRF token, see PMASA-2016-5
- issue [security] Multiple full path disclosure vulnerabilities, see PMASA-2016-6
- issue [security] XSS vulnerability in normalization page, see PMASA-2016-7
- issue [security] Full path disclosure vulnerability in SQL parser, see PMASA-2016-8
- issue [security] XSS vulnerability in SQL editor, see PMASA-2016-9
--- Older ChangeLogs can be found on our project website ---
https://www.phpmyadmin.net/old-stuff/ChangeLogs/

2
README
View File

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

View File

@ -8,7 +8,7 @@ https://www.phpmyadmin.net/
Code status
-----------
.. image:: https://secure.travis-ci.org/phpmyadmin/phpmyadmin.png?branch=master
.. image:: https://travis-ci.org/phpmyadmin/phpmyadmin.svg?branch=master
:alt: Build status
:target: https://travis-ci.org/phpmyadmin/phpmyadmin
@ -22,14 +22,11 @@ Code status
.. image:: https://scrutinizer-ci.com/g/phpmyadmin/phpmyadmin/badges/quality-score.png?s=93dfde29ffa5771d9c254b7ffb11c4e673315035
:target: https://scrutinizer-ci.com/g/phpmyadmin/phpmyadmin/
.. image:: https://buildtimetrend.herokuapp.com/badge/phpmyadmin/phpmyadmin
:alt: Buildtime Trend badge
:target: https://buildtimetrend.herokuapp.com/dashboard/phpmyadmin/phpmyadmin
.. image:: https://bestpractices.coreinfrastructure.org/projects/213/badge
:alt: CII Best Practices
:target: https://bestpractices.coreinfrastructure.org/projects/213
Download
--------
@ -41,6 +38,10 @@ If you prefer to follow the git repository, the following branch and tag names m
* ``master`` is the development branch.
* Releases are tagged, for example version 4.0.1 was tagged as ``RELEASE_4_0_1``.
Note that phpMyAdmin uses Composer 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
----------------

View File

@ -5,6 +5,7 @@
*
* @package PhpMyAdmin
*/
use PMA\libraries\Response;
require_once 'libraries/common.inc.php';
require_once 'libraries/transformations.lib.php';
@ -26,7 +27,7 @@ foreach ($request_params as $one_request_param) {
PMA\libraries\Util::checkParameters(array('db', 'table', 'field'));
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$response->getFooter()->setMinimal();
$header = $response->getHeader();
$header->disableMenuAndConsole();
@ -36,8 +37,7 @@ $header->setBodyId('body_browse_foreigners');
* Displays the frame
*/
$cfgRelation = PMA_getRelationsParam();
$foreigners = ($cfgRelation['relwork'] ? PMA_getForeigners($db, $table) : false);
$foreigners = PMA_getForeigners($db, $table);
$foreign_limit = PMA_getForeignLimit(
isset($_REQUEST['foreign_showAll']) ? $_REQUEST['foreign_showAll'] : null
);

View File

@ -55,7 +55,7 @@
<arg line="${source_comma_sep}
xml
codesize,design,naming,unusedcode
--exclude test,build,tcpdf,php-gettext,bfShapeFiles,phpseclib,recaptchalib.php,vendor,sql-parser
--exclude test,build,vendor
--reportfile '${basedir}/build/logs/pmd.xml'" />
</exec>
</target>
@ -66,12 +66,6 @@
--exclude test
--exclude build
--exclude vendor
--exclude libraries/tcpdf
--exclude libraries/php-gettext
--exclude libraries/bfShapeFiles
--exclude libraries/phpseclib
--exclude libraries/plugins/auth/recaptcha/recaptchalib.php
--exclude libraries/sql-parser
${source}" />
</exec>
</target>
@ -82,12 +76,6 @@
--exclude test
--exclude build
--exclude vendor
--exclude libraries/tcpdf
--exclude libraries/php-gettext
--exclude libraries/bfShapeFiles
--exclude libraries/phpseclib
--exclude libraries/plugins/auth/recaptcha/recaptchalib.php
--exclude libraries/sql-parser
${source}" />
</exec>
</target>
@ -101,7 +89,7 @@
<target name="phpcs" description="Generate checkstyle.xml using PHP_CodeSniffer excluding third party libraries" depends="phpcs-config">
<exec executable="phpcs">
<arg line="
--ignore=*/php-gettext/*,*/vendor/*,*/tcpdf/*,*/canvg/*,*/codemirror/*,*/openlayers/*,*/jquery/*,*/jqplot/*,*/build/*,*/bfShapeFiles/*,*/phpseclib/*,*/recaptcha/*,*/sql-parser/*
--ignore=*/vendor/*,*/canvg/*,*/codemirror/*,*/openlayers/*,*/jquery/*,*/jqplot/*,*/build/*
--report=checkstyle
--extensions=php
--report-file='${basedir}/build/logs/checkstyle.xml'

View File

@ -5,13 +5,14 @@
*
* @package PhpMyAdmin
*/
use PMA\libraries\Response;
/**
* Gets core libraries and defines some variables
*/
require 'libraries/common.inc.php';
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$response->disable();
$response->getHeader()->sendHttpHeaders();
@ -35,10 +36,11 @@ if (@is_readable($filename)) {
} else {
printf(
__(
'The %s file is not available on this system, please visit '
. 'www.phpmyadmin.net for more information.'
'The %s file is not available on this system, please visit ' .
'%s for more information.'
),
$filename
$filename,
'<a href="https://www.phpmyadmin.net/">phpmyadmin.net</a>'
);
exit;
}
@ -132,6 +134,9 @@ $replaces = array(
'/( ### )(.*)/'
=> '\\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');
@ -151,12 +156,5 @@ echo '<pre>';
echo preg_replace(array_keys($replaces), $replaces, $changelog);
echo '</pre>';
?>
<script type="text/javascript">
var links = document.getElementsByTagName("a");
for(var i = 0; i < links.length; i++) {
links[i].target = "_blank";
links[i].rel = "noopener noreferrer";
}
</script>
</body>
</html>

View File

@ -5,6 +5,7 @@
*
* @package PhpMyAdmin
*/
use PMA\libraries\Response;
require_once 'libraries/common.inc.php';
@ -26,7 +27,7 @@ if (isset($_REQUEST['fix_pmadb'])) {
PMA_fixPMATables($cfgRelation['db']);
}
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$response->addHTML(
PMA_getRelationsParamDiagnostic($cfgRelation)
);

3
codecov.yml Normal file
View File

@ -0,0 +1,3 @@
comment:
layout: header, changes, diff
coverage: {}

View File

@ -20,13 +20,24 @@
"source": "https://github.com/phpmyadmin/phpmyadmin"
},
"non-feature-branches": ["RELEASE_.*"],
"autoload": {
"psr-4": {
"PMA\\": "./"
}
},
"require": {
"php": ">=5.5.0",
"ext-mbstring": "*",
"ext-mysqli": "*",
"ext-xml": "*",
"ext-pcre": "*",
"ext-json": "*"
"ext-json": "*",
"phpmyadmin/sql-parser": "^4.1.2",
"phpmyadmin/motranslator": "^3.0",
"phpmyadmin/shapefile": "^2.0",
"tecnickcom/tcpdf": "^6.2",
"phpseclib/phpseclib": "^2.0",
"google/recaptcha": "^1.1"
},
"suggest": {
"ext-openssl": "Cookie encryption",
@ -35,10 +46,11 @@
"ext-zlib": "For gz import and export",
"ext-bz2": "For bzip2 import and export",
"ext-zip": "For zip import and export",
"ext-gd2": "For image transformations"
"ext-gd2": "For image transformations",
"tecnickcom/tcpdf": "For PDF support"
},
"require-dev": {
"satooshi/php-coveralls": "~0.6",
"satooshi/php-coveralls": "^1.0",
"phpunit/phpunit": "~4.1",
"codacy/coverage": "dev-master",
"phpunit/phpunit-selenium": "~1.2",

2580
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,6 @@ $i++;
$cfg['Servers'][$i]['auth_type'] = 'cookie';
/* Server parameters */
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['connect_type'] = 'tcp';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;

View File

@ -6,6 +6,9 @@
*
* @package PhpMyAdmin
*/
use PMA\libraries\URL;
use PMA\libraries\Response;
/**
* Gets some core libraries
*/
@ -55,7 +58,7 @@ if (isset($_POST['add_column'])) {
$selected_col[] = $_POST['column-select'];
$tmp_msg = PMA_syncUniqueColumns($selected_col, false, $selected_tbl);
}
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$header = $response->getHeader();
$scripts = $header->getScripts();
$scripts->addFile('jquery/jquery.uitablefilter.js');
@ -97,7 +100,7 @@ if (PMA_isValid($_REQUEST['pos'], 'integer')) {
} else {
$pos = 0;
}
$addNewColumn = PMA_getHTMLforAddNewColumn($db);
$addNewColumn = PMA_getHTMLforAddNewColumn($db, $total_rows);
$response->addHTML($addNewColumn);
if ($total_rows <= 0) {
$response->addHTML(
@ -114,7 +117,7 @@ $response->addHTML($table_navigation_html);
$columnAdd = PMA_getHTMLforAddCentralColumn($total_rows, $pos, $db);
$response->addHTML($columnAdd);
$deleteRowForm = '<form method="post" id="del_form" action="db_central_columns.php">'
. PMA_URL_getHiddenInputs(
. URL::getHiddenInputs(
$db
)
. '<input id="del_col_name" type="hidden" name="col_name" value="">'
@ -131,14 +134,12 @@ $tableheader = PMA_getCentralColumnsTableHeader(
);
$response->addHTML($tableheader);
$result = PMA_getColumnsList($db, $pos, $max_rows);
$odd_row = true;
$row_num = 0;
foreach ($result as $row) {
$tableHtmlRow = PMA_getHTMLforCentralColumnsTableRow(
$row, $odd_row, $row_num, $db
$row, $row_num, $db
);
$response->addHTML($tableHtmlRow);
$odd_row = !$odd_row;
$row_num++;
}
$response->addHTML('</table>');

View File

@ -5,6 +5,8 @@
*
* @package PhpMyAdmin
*/
use PMA\libraries\URL;
use PMA\libraries\Response;
/**
* Gets the variables sent or posted to this script, then displays headers
@ -26,7 +28,7 @@ if (! isset($selected_tbl)) {
) = PMA\libraries\Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
}
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$header = $response->getHeader();
$header->enablePrintView();
@ -45,7 +47,7 @@ PMA\libraries\Util::checkParameters(array('db'));
/**
* Defines the url to return to in case of error in a sql statement
*/
$err_url = 'db_sql.php' . PMA_URL_getCommon(array('db' => $db));
$err_url = 'db_sql.php' . URL::getCommon(array('db' => $db));
if ($cfgRelation['commwork']) {
$comment = PMA_getDbComment($db);
@ -122,7 +124,6 @@ foreach ($tables as $table) {
echo ' <th>MIME</th>' , "\n";
}
echo '</tr>';
$odd_row = true;
foreach ($columns as $row) {
if ($row['Null'] == '') {
@ -145,9 +146,7 @@ foreach ($tables as $table) {
}
$column_name = $row['Field'];
echo '<tr class="';
echo $odd_row ? 'odd' : 'even'; $odd_row = ! $odd_row;
echo '">';
echo '<tr>';
echo '<td class="nowrap">';
echo htmlspecialchars($column_name);

View File

@ -5,12 +5,13 @@
*
* @package PhpMyAdmin-Designer
*/
use PMA\libraries\Response;
require_once 'libraries/common.inc.php';
require_once 'libraries/pmd_common.php';
require_once 'libraries/db_designer.lib.php';
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
if (isset($_REQUEST['dialog'])) {
@ -113,7 +114,7 @@ if (isset($_GET['db'])) {
$params['db'] = $_GET['db'];
}
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$response->getFooter()->setMinimal();
$header = $response->getHeader();
$header->setBodyId('pmd_body');

View File

@ -117,9 +117,9 @@ foreach ($tables as $each_table) {
$data_checked = $is_checked;
}
$table_html = htmlspecialchars($each_table['Name']);
$multi_values .= '<tr>';
$multi_values .= '<tr class="marked">';
$multi_values .= '<td><input type="checkbox" name="table_select[]"'
. ' value="' . $table_html . '"' . $is_checked . ' /></td>';
. ' 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">'

View File

@ -6,6 +6,7 @@
* @package PhpMyAdmin
*/
use PMA\libraries\Response;
use PMA\libraries\config\PageSettings;
require_once 'libraries/common.inc.php';
@ -14,7 +15,7 @@ require_once 'libraries/config/page_settings.forms.php';
PageSettings::showGroup('Import');
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$header = $response->getHeader();
$scripts = $header->getScripts();
$scripts->addFile('import.js');
@ -37,7 +38,7 @@ list(
) = PMA\libraries\Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
require 'libraries/display_import.lib.php';
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$response->addHTML(
PMA_getImportDisplay(
'database', $db, $table, $max_upload_size

View File

@ -11,13 +11,13 @@
*
* @package PhpMyAdmin
*/
use PMA\libraries\Response;
use PMA\libraries\plugins\export\ExportSql;
/**
* requirements
*/
require_once 'libraries/common.inc.php';
require_once 'libraries/mysql_charsets.inc.php';
require_once 'libraries/display_create_table.lib.php';
/**
@ -27,7 +27,7 @@ require_once 'libraries/check_user_privileges.lib.php';
require_once 'libraries/operations.lib.php';
// add a javascript file for jQuery functions to handle Ajax actions
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$header = $response->getHeader();
$scripts = $header->getScripts();
$scripts->addFile('db_operations.js');
@ -37,7 +37,7 @@ $sql_query = '';
/**
* Rename/move or copy database
*/
if (mb_strlen($GLOBALS['db'])
if (strlen($GLOBALS['db']) > 0
&& (! empty($_REQUEST['db_rename']) || ! empty($_REQUEST['db_copy']))
) {
if (! empty($_REQUEST['db_rename'])) {
@ -46,9 +46,7 @@ if (mb_strlen($GLOBALS['db'])
$move = false;
}
if (! isset($_REQUEST['newname'])
|| ! mb_strlen($_REQUEST['newname'])
) {
if (! isset($_REQUEST['newname']) || strlen($_REQUEST['newname']) === 0) {
$message = PMA\libraries\Message::error(__('The database name is empty!'));
} else {
$_error = false;
@ -177,8 +175,7 @@ if (mb_strlen($GLOBALS['db'])
* Database has been successfully renamed/moved. If in an Ajax request,
* generate the output with {@link PMA\libraries\Response} and exit
*/
if ($GLOBALS['is_ajax_request'] == true) {
$response = PMA\libraries\Response::getInstance();
if ($response->isAjax()) {
$response->setRequestStatus($message->isSuccess());
$response->addJSON('message', $message);
$response->addJSON('newname', $_REQUEST['newname']);
@ -230,7 +227,7 @@ if (isset($message)) {
unset($message);
}
$_REQUEST['db_collation'] = PMA_getDbCollation($GLOBALS['db']);
$_REQUEST['db_collation'] = $GLOBALS['dbi']->getDbCollation($GLOBALS['db']);
$is_information_schema = $GLOBALS['dbi']->isSystemSchema($GLOBALS['db']);
$response->addHTML('<div id="boxContainer" data-box-width="300">');
@ -283,12 +280,8 @@ if (!$is_information_schema) {
'%sFind out why%s.'
)
);
$message->addParam(
'<a href="'
. './chk_rel.php' . $url_query . '">',
false
);
$message->addParam('</a>', false);
$message->addParamHtml('<a href="./chk_rel.php' . $url_query . '">');
$message->addParamHtml('</a>');
/* Show error if user has configured something, notice elsewhere */
if (!empty($cfg['Servers'][$server]['pmadb'])) {
$message->isError(true);

View File

@ -6,15 +6,16 @@
* @package PhpMyAdmin
*/
use PMA\libraries\SavedSearches;
use PMA\libraries\URL;
use PMA\libraries\Response;
/**
* requirements
*/
require_once 'libraries/common.inc.php';
require_once 'libraries/bookmark.lib.php';
require_once 'libraries/sql.lib.php';
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
// Gets the relation settings
$cfgRelation = PMA_getRelationsParam();
@ -131,7 +132,7 @@ unset($message_to_display);
// create new qbe search instance
$db_qbe = new PMA\libraries\DbQbe($GLOBALS['db'], $savedSearchList, $savedSearch);
$url = 'db_designer.php' . PMA_URL_getCommon(
$url = 'db_designer.php' . URL::getCommon(
array_merge(
$url_params,
array('query' => 1)

View File

@ -10,7 +10,6 @@
* Include required files
*/
require_once 'libraries/common.inc.php';
require_once 'libraries/mysql_charsets.inc.php';
/**
* Include all other files

View File

@ -13,9 +13,10 @@
*/
require_once 'libraries/common.inc.php';
use PMA\libraries\Response;
use PMA\libraries\DbSearch;
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$header = $response->getHeader();
$scripts = $header->getScripts();
$scripts->addFile('db_search.js');
@ -38,7 +39,7 @@ $url_params['goto'] = 'db_search.php';
$db_search = new DbSearch($GLOBALS['db']);
// Display top links if we are not in an Ajax request
if ($GLOBALS['is_ajax_request'] != true) {
if (! $response->isAjax()) {
list(
$tables,
$num_tables,
@ -55,19 +56,18 @@ if ($GLOBALS['is_ajax_request'] != true) {
// Main search form has been submitted, get results
if (isset($_REQUEST['submit_search'])) {
$response->addHTML($db_search->getSearchResults());
} else {
$response->addHTML('<div id="searchresults"></div>');
}
// If we are in an Ajax request, we need to exit after displaying all the HTML
if ($GLOBALS['is_ajax_request'] == true && empty($_REQUEST['ajax_page_request'])) {
if ($response->isAjax() && empty($_REQUEST['ajax_page_request'])) {
exit;
}
// Display the search form
$response->addHTML($db_search->getSelectionForm());
$response->addHTML('<div id="searchresults"></div>');
$response->addHTML(
'<div id="togglesearchresultsdiv"><a id="togglesearchresultlink"></a></div>'
. '<br class="clearfloat" />'
);
$response->addHTML($db_search->getSelectionForm());
$response->addHTML('<br class="clearfloat" />');
$response->addHTML($db_search->getResultDivs());

View File

@ -6,6 +6,7 @@
* @package PhpMyAdmin
*/
use PMA\libraries\config\PageSettings;
use PMA\libraries\Response;
/**
*
@ -19,7 +20,7 @@ PageSettings::showGroup('Sql_queries');
/**
* Runs common work
*/
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$header = $response->getHeader();
$scripts = $header->getScripts();
$scripts->addFile('makegrid.js');

View File

@ -6,6 +6,7 @@
* @package PhpMyAdmin
*/
use PMA\libraries\Response;
require_once 'libraries/common.inc.php';
if ($GLOBALS['cfg']['EnableAutocompleteForTablesAndColumns']) {
@ -22,5 +23,5 @@ if ($GLOBALS['cfg']['EnableAutocompleteForTablesAndColumns']) {
} else {
$sql_autocomplete = true;
}
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$response->addJSON("tables", json_encode($sql_autocomplete));

View File

@ -5,6 +5,7 @@
*
* @package PhpMyAdmin
*/
use PMA\libraries\Response;
/**
* Loading common files. Used to check for authorization, localization and to
@ -14,7 +15,7 @@ require_once 'libraries/common.inc.php';
$query = !empty($_POST['sql']) ? $_POST['sql'] : '';
$query = SqlParser\Utils\Formatter::format($query);
$query = PhpMyAdmin\SqlParser\Utils\Formatter::format($query);
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$response->addJSON("sql", $query);

View File

@ -16,7 +16,9 @@ require_once 'libraries/common.inc.php';
require_once 'libraries/db_common.inc.php';
$container = libraries\di\Container::getDefaultContainer();
$container->factory('PMA\libraries\controllers\database\DatabaseStructureController');
$container->factory(
'PMA\libraries\controllers\database\DatabaseStructureController'
);
$container->alias(
'DatabaseStructureController',
'PMA\libraries\controllers\database\DatabaseStructureController'

View File

@ -5,6 +5,7 @@
*
* @package PhpMyAdmin
*/
use PMA\libraries\Response;
use PMA\libraries\Tracker;
/**
@ -16,7 +17,7 @@ require_once './libraries/tracking.lib.php';
require_once 'libraries/display_create_table.lib.php';
//Get some js files needed for Ajax requests
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$header = $response->getHeader();
$scripts = $header->getScripts();
$scripts->addFile('jquery/jquery.tablesorter.js');

View File

@ -52,21 +52,21 @@ class ConfigOption(ObjectDescription):
# Generic index entries
indexentry = self.indextemplate % (name,)
self.indexnode['entries'].append((indextype, indexentry,
targetname, targetname))
targetname, targetname, None))
self.indexnode['entries'].append((indextype, name,
targetname, targetname))
targetname, targetname, None))
# Server section
if targetparts[0] == 'Servers' and len(targetparts) > 1:
indexname = ', '.join(targetparts[1:])
self.indexnode['entries'].append((indextype, 'server configuration; %s' % indexname,
targetname, targetname))
targetname, targetname, None))
self.indexnode['entries'].append((indextype, indexname,
targetname, targetname))
targetname, targetname, None))
else:
indexname = ', '.join(targetparts)
self.indexnode['entries'].append((indextype, indexname,
targetname, targetname))
targetname, targetname, None))
self.env.domaindata['config']['objects'][self.objtype, name] = \
self.env.docname, targetname
@ -84,8 +84,8 @@ class ConfigSectionXRefRole(XRefRole):
tgtid = 'index-%s' % env.new_serialno('index')
indexnode = addnodes.index()
indexnode['entries'] = [
('single', varname, tgtid, varname),
('single', 'configuration section; %s' % varname, tgtid, varname)
('single', varname, tgtid, varname, None),
('single', 'configuration section; %s' % varname, tgtid, varname, None)
]
targetnode = nodes.target('', '', ids=[tgtid])
document.note_explicit_target(targetnode)
@ -118,7 +118,7 @@ class ConfigSection(ObjectDescription):
indextype = 'single'
indexentry = self.indextemplate % (name,)
self.indexnode['entries'].append((indextype, indexentry,
targetname, targetname))
targetname, targetname, None))
self.env.domaindata['config']['objects'][self.objtype, name] = \
self.env.docname, targetname
@ -135,8 +135,8 @@ class ConfigOptionXRefRole(XRefRole):
tgtid = 'index-%s' % env.new_serialno('index')
indexnode = addnodes.index()
indexnode['entries'] = [
('single', varname, tgtid, varname),
('single', 'configuration option; %s' % varname, tgtid, varname)
('single', varname, tgtid, varname, None),
('single', 'configuration option; %s' % varname, tgtid, varname, None)
]
targetnode = nodes.target('', '', ids=[tgtid])
document.note_explicit_target(targetnode)
@ -165,9 +165,12 @@ class ConfigFileDomain(Domain):
}
def clear_doc(self, docname):
toremove = []
for key, (fn, _) in self.data['objects'].items():
if fn == docname:
del self.data['objects'][key]
toremove.append(key)
for key in toremove:
del self.data['objects'][key]
def resolve_xref(self, env, fromdocname, builder,
typ, target, node, contnode):
@ -185,4 +188,3 @@ class ConfigFileDomain(Domain):
def setup(app):
app.add_domain(ConfigFileDomain)

78
doc/bookmarks.rst Normal file
View File

@ -0,0 +1,78 @@
.. _bookmarks:
Bookmarks
=========
.. note::
You need to have configured the :ref:`linked-tables` for using bookmarks
feature.
Storing bookmarks
-----------------
Any query you have executed can be stored as a bookmark on the page
where the results are displayed. You will find a button labeled
:guilabel:`Bookmark this query` just at the end of the page. As soon as you have
stored a bookmark, it is related to the database you run the query on.
You can now access a bookmark dropdown on each page, the query box
appears on for that database.
Variables inside bookmarks
--------------------------
You can also have, inside the query, placeholders for variables.
This is done by inserting into the query SQL comments between ``/*`` and
``*/``. Inside the comments, the special strings ``[VARIABLE{variable-number}]`` is used.
Be aware that the whole query minus the SQL comments must be
valid by itself, otherwise you won't be able to store it as a bookmark.
When you execute the bookmark, everything typed into the *Variables*
input boxes on the query box page will replace the strings ``/*[VARIABLE{variable-number}]*/`` in
your stored query.
Also remember, that everything else inside the ``/*[VARIABLE{variable-number}]*/`` string for
your query will remain the way it is, but will be stripped of the ``/**/``
chars. So you can use:
.. code-block:: mysql
/*, [VARIABLE1] AS myname */
which will be expanded to
.. code-block:: mysql
, VARIABLE1 as myname
in your query, where VARIABLE1 is the string you entered in the Variable 1 input box.
A more complex example. Say you have stored
this query:
.. code-block:: mysql
SELECT Name, Address FROM addresses WHERE 1 /* AND Name LIKE '%[VARIABLE1]%' */
Say, you now enter "phpMyAdmin" as the variable for the stored query, the full
query will be:
.. code-block:: mysql
SELECT Name, Address FROM addresses WHERE 1 AND Name LIKE '%phpMyAdmin%'
**NOTE THE ABSENCE OF SPACES** inside the ``/**/`` construct. Any spaces
inserted there will be later also inserted as spaces in your query and may lead
to unexpected results especially when using the variable expansion inside of a
"LIKE ''" expression.
Browsing table using bookmark
-----------------------------
When bookmark is named same as table, it will be used as query when browsing
this table.
.. seealso::
:ref:`faqbookmark`,
:ref:`faq6_22`

143
doc/charts.rst Normal file
View File

@ -0,0 +1,143 @@
.. _charts:
Charts
======
.. versionadded:: 3.4.0
Since phpMyAdmin version 3.4.0, you can easily generate charts from a SQL query
by clicking the "Display chart" link in the "Query results operations" area.
.. image:: images/query_result_operations.png
A window layer "Display chart" is shown in which you can customize the chart with the following options.
- Chart type: Allows you choose the type of the chart. Supported types are bar charts, column charts, line charts, spline charts, area charts, pie charts and timeline charts (only the chart types applicable for current series selection are offered).
- X-axis: Allows to choose the field for the main axis.
- Series: Allows to choose series for the chart. You can choose multiple series.
- Title: Allows specifying a title for the chart which is displayed above the chart.
- X-axis and Y-axis labels: Allows specifying labels for axes.
- Start row and number of rows: Allows generating charts only for a specified number of rows of the results set.
.. image:: images/chart.png
Chart implementation
--------------------
Charts in phpMyAdmin are drawn using `jqPlot <http://www.jqplot.com/>`_ jQuery library.
Examples
--------
Pie chart
+++++++++
Query results for a simple pie chart can be generated with:
.. code-block:: mysql
SELECT 'Food' AS 'expense',
1250 AS 'amount' UNION
SELECT 'Accommodation', 500 UNION
SELECT 'Travel', 720 UNION
SELECT 'Misc', 220
And the result of this query is:
+---------------+--------+
| expense | anount |
+===============+========+
| Food | 1250 |
+---------------+--------+
| Accommodation | 500 |
+---------------+--------+
| Travel | 720 |
+---------------+--------+
| Misc | 220 |
+---------------+--------+
Choosing expense as the X-axis and amount in series:
.. image:: images/pie_chart.png
Bar and column chart
++++++++++++++++++++
Both bar charts and column chats support stacking. Upon selecting one of these types a checkbox is displayed to select stacking.
Query results for a simple bar or column chart can be generated with:
.. code-block:: mysql
SELECT
'ACADEMY DINOSAUR' AS 'title',
0.99 AS 'rental_rate',
20.99 AS 'replacement_cost' UNION
SELECT 'ACE GOLDFINGER', 4.99, 12.99 UNION
SELECT 'ADAPTATION HOLES', 2.99, 18.99 UNION
SELECT 'AFFAIR PREJUDICE', 2.99, 26.99 UNION
SELECT 'AFRICAN EGG', 2.99, 22.99
And the result of this query is:
+------------------+--------------+-------------------+
| title | rental_rate | replacement_cost |
+==================+==============+===================+
| ACADEMY DINOSAUR | 0.99 | 20.99 |
+------------------+--------------+-------------------+
| ACE GOLDFINGER | 4.99 | 12.99 |
+------------------+--------------+-------------------+
| ADAPTATION HOLES | 2.99 | 18.99 |
+------------------+--------------+-------------------+
| AFFAIR PREJUDICE | 2.99 | 26.99 |
+------------------+--------------+-------------------+
| AFRICAN EGG | 2.99 | 22.99 |
+------------------+--------------+-------------------+
Choosing title as the X-axis and rental_rate and replacement_cost as series:
.. image:: images/column_chart.png
Scatter chart
+++++++++++++
Scatter charts are useful in identifying the movement of one or more variable(s) compared to another variable.
Using the same data set from bar and column charts section and choosing replacement_cost as the X-axis and rental_rate in series:
.. image:: images/scatter_chart.png
Line, spline and timeline charts
++++++++++++++++++++++++++++++++
These charts can be used to illustrate trends in underlying data. Spline charts draw smooth lines while timeline charts draw X-axis taking the distances between the dates/time into consideration.
Query results for a simple line, spline or timeline chart can be generated with:
.. code-block:: mysql
SELECT
DATE('2006-01-08') AS 'date',
2056 AS 'revenue',
1378 AS 'cost' UNION
SELECT DATE('2006-01-09'), 1898, 2301 UNION
SELECT DATE('2006-01-15'), 1560, 600 UNION
SELECT DATE('2006-01-17'), 3457, 1565
And the result of this query is:
+------------+---------+------+
| date | revenue | cost |
+============+=========+======+
| 2016-01-08 | 2056 | 1378 |
+------------+---------+------+
| 2006-01-09 | 1898 | 2301 |
+------------+---------+------+
| 2006-01-15 | 1560 | 600 |
+------------+---------+------+
| 2006-01-17 | 3457 | 1565 |
+------------+---------+------+
.. image:: images/line_chart.png
.. image:: images/spline_chart.png
.. image:: images/timeline_chart.png

View File

@ -44,14 +44,14 @@ master_doc = 'index'
# General information about the project.
project = u'phpMyAdmin'
copyright = u'2012 - 2016, The phpMyAdmin devel team'
copyright = u'2012 - 2017, 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 = '4.6.6'
version = '4.7.0'
# The full version, including alpha/beta/rc tags.
release = version
@ -302,3 +302,8 @@ from sphinx.highlighting import lexers
from pygments.lexers.web import PhpLexer
lexers['php'] = PhpLexer(startinline=True)
# Number of retries and timeout for linkcheck
linkcheck_retries = 10
linkcheck_timeout = 10
linkcheck_anchors = False

View File

@ -5,10 +5,15 @@
Configuration
=============
Almost all configurable data is placed in :file:`config.inc.php`. If this file
does not exist, please refer to the :ref:`setup` section to create one. This
file only needs to contain the parameters you want to change from their
corresponding default value in :file:`libraries/config.default.php`.
All configurable data is placed in :file:`config.inc.php` in phpMyAdmin's
toplevel directory. If this file does not exist, please refer to the
:ref:`setup` section to create one. This file only needs to contain the
parameters you want to change from their corresponding default value in
:file:`libraries/config.default.php` (this file is not inteded for changes).
.. seealso::
:ref:`config-examples` for examples of configurations
If a directive is missing from your file, you can just add another line with
the file. This file is for over-writing the defaults; if you wish to use the
@ -48,13 +53,12 @@ Basic settings
Sets here the complete :term:`URL` (with full path) to your phpMyAdmin
installation's directory. E.g.
``https://www.example.net/path_to_your_phpMyAdmin_directory/``. Note also
that the :term:`URL` on most of web servers are casesensitive. Dont
forget the trailing slash at the end.
that the :term:`URL` on most of web servers are case sensitive (even on
Windows). Dont forget the trailing slash at the end.
Starting with version 2.3.0, it is advisable to try leaving this blank. In
most cases phpMyAdmin automatically detects the proper setting. Users of
port forwarding will need to set :config:option:`$cfg['PmaAbsoluteUri']`
(`more info <https://sourceforge.net/p/phpmyadmin/support-requests/795/>`_).
port forwarding or complex reverse proxy setup might need to set this.
A good test is to browse a table, edit a row and save it. There should be
an error message if phpMyAdmin is having trouble autodetecting the correct
@ -104,6 +108,10 @@ Basic settings
:type: boolean
:default: false
.. deprecated:: 4.7.0
This setting was removed as the warning has been removed as well.
A warning is displayed on the main page if there is a difference
between the MySQL library and server version.
@ -208,13 +216,22 @@ Server connection settings
* hostname, e.g., ``'localhost'`` or ``'mydb.example.org'``
* IP address, e.g., ``'127.0.0.1'`` or ``'192.168.10.1'``
* IPv6 address, e.g. ``2001:cdba:0000:0000:0000:0000:3257:9652``
* dot - ``'.'``, i.e., use named pipes on windows systems
* empty - ``''``, disables this server
.. note::
phpMyAdmin supports connecting to MySQL servers reachable via IPv6 only.
To connect to an IPv6 MySQL server, enter its IPv6 address in this field.
The hostname ``localhost`` is handled specially by MySQL and it uses
the socket based connection protocol. To use TCP/IP networking, use an
IP address or hostname such as ``127.0.0.1`` or ``db.example.com``. You
can configure the path to the socket with
:config:option:`$cfg['Servers'][$i]['socket']`.
.. seealso::
:config:option:`$cfg['Servers'][$i]['port']`,
<https://dev.mysql.com/doc/refman/5.7/en/connecting.html>
.. config:option:: $cfg['Servers'][$i]['port']
@ -231,6 +248,11 @@ Server connection settings
different from the default port, use ``127.0.0.1`` or the real hostname
in :config:option:`$cfg['Servers'][$i]['host']`.
.. seealso::
:config:option:`$cfg['Servers'][$i]['host']`,
<https://dev.mysql.com/doc/refman/5.7/en/connecting.html>
.. config:option:: $cfg['Servers'][$i]['socket']
:type: string
@ -241,19 +263,38 @@ Server connection settings
:command:`mysql` commandline client, issue the ``status`` command. Among the
resulting information displayed will be the socket used.
.. note::
This takes effect only if :config:option:`$cfg['Servers'][$i]['host']` is set
to ``localhost``.
.. seealso::
:config:option:`$cfg['Servers'][$i]['host']`,
<https://dev.mysql.com/doc/refman/5.7/en/connecting.html>
.. config:option:: $cfg['Servers'][$i]['ssl']
:type: boolean
:default: false
Whether to enable SSL for the connection between phpMyAdmin and the MySQL server.
Whether to enable SSL for the connection between phpMyAdmin and the MySQL
server to secure the connection.
When using the ``'mysql'`` extension,
none of the remaining ``'ssl...'`` configuration options apply.
We strongly recommend the ``'mysqli'`` extension when using this option.
.. seealso:: :ref:`example-google-ssl`
.. seealso::
:ref:`example-google-ssl`
:config:option:`$cfg['Servers'][$i]['ssl_key']`,
:config:option:`$cfg['Servers'][$i]['ssl_cert']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca_path']`,
:config:option:`$cfg['Servers'][$i]['ssl_ciphers']`,
:config:option:`$cfg['Servers'][$i]['ssl_verify']`
.. config:option:: $cfg['Servers'][$i]['ssl_key']
@ -268,7 +309,15 @@ Server connection settings
$cfg['Servers'][$i]['ssl_key'] = '/etc/mysql/server-key.pem';
.. seealso:: :ref:`example-google-ssl`
.. seealso::
:ref:`example-google-ssl`
:config:option:`$cfg['Servers'][$i]['ssl']`,
:config:option:`$cfg['Servers'][$i]['ssl_cert']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca_path']`,
:config:option:`$cfg['Servers'][$i]['ssl_ciphers']`,
:config:option:`$cfg['Servers'][$i]['ssl_verify']`
.. config:option:: $cfg['Servers'][$i]['ssl_cert']
@ -277,7 +326,15 @@ Server connection settings
Path to the cert file when using SSL for connecting to the MySQL server.
.. seealso:: :ref:`example-google-ssl`
.. seealso::
:ref:`example-google-ssl`
:config:option:`$cfg['Servers'][$i]['ssl']`,
:config:option:`$cfg['Servers'][$i]['ssl_key']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca_path']`,
:config:option:`$cfg['Servers'][$i]['ssl_ciphers']`,
:config:option:`$cfg['Servers'][$i]['ssl_verify']`
.. config:option:: $cfg['Servers'][$i]['ssl_ca']
@ -286,7 +343,15 @@ Server connection settings
Path to the CA file when using SSL for connecting to the MySQL server.
.. seealso:: :ref:`example-google-ssl`
.. seealso::
:ref:`example-google-ssl`
:config:option:`$cfg['Servers'][$i]['ssl']`,
:config:option:`$cfg['Servers'][$i]['ssl_key']`,
:config:option:`$cfg['Servers'][$i]['ssl_cert']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca_path']`,
:config:option:`$cfg['Servers'][$i]['ssl_ciphers']`,
:config:option:`$cfg['Servers'][$i]['ssl_verify']`
.. config:option:: $cfg['Servers'][$i]['ssl_ca_path']
@ -295,6 +360,16 @@ Server connection settings
Directory containing trusted SSL CA certificates in PEM format.
.. seealso::
:ref:`example-google-ssl`
:config:option:`$cfg['Servers'][$i]['ssl']`,
:config:option:`$cfg['Servers'][$i]['ssl_key']`,
:config:option:`$cfg['Servers'][$i]['ssl_cert']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca']`,
:config:option:`$cfg['Servers'][$i]['ssl_ciphers']`,
:config:option:`$cfg['Servers'][$i]['ssl_verify']`
.. config:option:: $cfg['Servers'][$i]['ssl_ciphers']
:type: string
@ -302,6 +377,16 @@ Server connection settings
List of allowable ciphers for SSL connections to the MySQL server.
.. seealso::
:config:option:`$cfg['Servers'][$i]['ssl']`,
:config:option:`$cfg['Servers'][$i]['ssl_key']`,
:config:option:`$cfg['Servers'][$i]['ssl_cert']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca_path']`,
:config:option:`$cfg['Servers'][$i]['ssl_verify']`
.. config:option:: $cfg['Servers'][$i]['ssl_verify']
:type: boolean
@ -319,18 +404,39 @@ Server connection settings
Since PHP 5.6.0 it also verifies whether server name matches CN of it's
certificate. There is currently no way to disable just this check without
disabling complete SSL verification.
.. warning::
Disabling the certificate verification defeats purpose of using SSL.
This will make the connection vulnerable to man in the middle attacks.
.. note::
This flag only works with PHP 5.6.16 or later.
.. seealso:: :ref:`example-google-ssl`
.. seealso::
:ref:`example-google-ssl`
:config:option:`$cfg['Servers'][$i]['ssl']`,
:config:option:`$cfg['Servers'][$i]['ssl_key']`,
:config:option:`$cfg['Servers'][$i]['ssl_cert']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca_path']`,
:config:option:`$cfg['Servers'][$i]['ssl_ciphers']`,
:config:option:`$cfg['Servers'][$i]['ssl_verify']`
.. config:option:: $cfg['Servers'][$i]['connect_type']
:type: string
:default: ``'tcp'``
.. deprecated:: 4.7.0
This setting is no longer used as of 4.7.0, since MySQL decides the
connection type based on host, so it could lead to unexpected results.
Please set :config:option:`$cfg['Servers'][$i]['host']` accordingly
instead.
What type connection to use with the MySQL server. Your options are
``'socket'`` and ``'tcp'``. It defaults to tcp as that is nearly guaranteed
to be available on all MySQL servers, while sockets are not supported on
@ -354,6 +460,10 @@ Server connection settings
Permits to use an alternate host to hold the configuration storage
data.
.. seealso::
:config:option:`$cfg['Servers'][$i]['control_*']`
.. _controlport:
.. config:option:: $cfg['Servers'][$i]['controlport']
@ -363,6 +473,10 @@ Server connection settings
Permits to use an alternate port to connect to the host that
holds the configuration storage.
.. seealso::
:config:option:`$cfg['Servers'][$i]['control_*']`
.. _controluser:
.. config:option:: $cfg['Servers'][$i]['controluser']
@ -374,13 +488,59 @@ Server connection settings
:type: string
:default: ``''``
This special account is used for 2 distinct purposes: to make possible all
relational features (see :config:option:`$cfg['Servers'][$i]['pmadb']`).
This special account is used to access :ref:`linked-tables`.
You don't need it in single user case, but if phpMyAdmin is shared it
is recommended to give access to :ref:`linked-tables` only to this user
and configure phpMyAdmin to use it. All users will then be able to use
the features without need to have direct access to :ref:`linked-tables`.
.. versionchanged:: 2.2.5
those were called ``stduser`` and ``stdpass``
.. seealso:: :ref:`setup`, :ref:`authentication_modes`, :ref:`linked-tables`
.. seealso::
:ref:`setup`,
:ref:`authentication_modes`,
:ref:`linked-tables`,
:config:option:`$cfg['Servers'][$i]['pmadb']`,
:config:option:`$cfg['Servers'][$i]['controlhost']`,
:config:option:`$cfg['Servers'][$i]['controlport']`,
:config:option:`$cfg['Servers'][$i]['control_*']`
.. config:option:: $cfg['Servers'][$i]['control_*']
:type: mixed
.. versionadded:: 4.7.0
You can change any MySQL connection setting for control link (used to
access :ref:`linked-tables`) using configuration prefixed with ``control_``.
This can be used to change any aspect of the control connection, which by
default uses same parameters as the user one.
For example you can configure SSL for the control connection:
.. code-block:: php
// Enable SSL
$cfg['Servers'][$i]['control_ssl'] = true;
// Client secret key
$cfg['Servers'][$i]['control_ssl_key'] = '../client-key.pem';
// Client certificate
$cfg['Servers'][$i]['control_ssl_cert'] = '../client-cert.pem';
// Server certification authority
$cfg['Servers'][$i]['control_ssl_ca'] = '../server-ca.pem';
.. seealso::
:config:option:`$cfg['Servers'][$i]['ssl']`,
:config:option:`$cfg['Servers'][$i]['ssl_key']`,
:config:option:`$cfg['Servers'][$i]['ssl_cert']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca_path']`,
:config:option:`$cfg['Servers'][$i]['ssl_ciphers']`,
:config:option:`$cfg['Servers'][$i]['ssl_verify']`
.. config:option:: $cfg['Servers'][$i]['auth_type']
@ -390,13 +550,13 @@ Server connection settings
Whether config or cookie or :term:`HTTP` or signon authentication should be
used for this server.
* 'config' authentication (``$auth_type = 'config'``) is the plain old
* 'config' authentication (``$auth_type = 'config'``) is the plain old
way: username and password are stored in :file:`config.inc.php`.
* 'cookie' authentication mode (``$auth_type = 'cookie'``) allows you to
* 'cookie' authentication mode (``$auth_type = 'cookie'``) allows you to
log in as any valid MySQL user with the help of cookies.
* 'http' authentication allows you to log in as any
valid MySQL user via HTTP-Auth.
* 'signon' authentication mode (``$auth_type = 'signon'``) allows you to
* 'signon' authentication mode (``$auth_type = 'signon'``) allows you to
log in from prepared PHP session data or using supplied PHP script.
.. seealso:: :ref:`authentication_modes`
@ -436,6 +596,10 @@ Server connection settings
:type: boolean
:default: false
.. deprecated:: 4.7.0
This setting was removed as it can produce unexpected results.
Allow attempt to log in without password when a login with password
fails. This can be used together with http authentication, when
authentication is done some other way and phpMyAdmin gets user name
@ -494,7 +658,7 @@ Server connection settings
More information on regular expressions can be found in the `PCRE
pattern syntax
<https://php.net/manual/en/reference.pcre.pattern.syntax.php>`_ portion
<https://secure.php.net/manual/en/reference.pcre.pattern.syntax.php>`_ portion
of the PHP reference manual.
.. config:option:: $cfg['Servers'][$i]['verbose']
@ -508,6 +672,15 @@ Server connection settings
show only certain databases on your system, for example. For HTTP
auth, all non-US-ASCII characters will be stripped.
.. config:option:: $cfg['Servers'][$i]['extension']
:type: string
:default: ``'mysqli'``
The PHP MySQL extension to use (``mysql`` or ``mysqli``).
It is recommended to use ``mysqli`` in all installations.
.. config:option:: $cfg['Servers'][$i]['pmadb']
:type: string
@ -611,6 +784,12 @@ Server connection settings
:type: string or false
:default: ``''``
The designer feature can save your page layout; by pressing the "Save page" or "Save page as"
button in the expanding designer menu, you can customize the layout and have it loaded the next
time you use the designer. That layout is stored in this table. Furthermore, this table is also
required for using the PDF relation export feature, see
:config:option:`$cfg['Servers'][$i]['pdf\_pages']` for additional details.
.. config:option:: $cfg['Servers'][$i]['pdf_pages']
:type: string or false
@ -673,7 +852,7 @@ Server connection settings
``pma__column_info``)
* to update your PRE-2.5.0 Column\_comments table use this: and
remember that the Variable in :file:`config.inc.php` has been renamed from
:config:option:`$cfg['Servers'][$i]['column\_comments']` to
:samp:`$cfg['Servers'][$i]['column\_comments']` to
:config:option:`$cfg['Servers'][$i]['column\_info']`
.. code-block:: mysql
@ -1153,8 +1332,12 @@ Server connection settings
Disable using ``INFORMATION_SCHEMA`` to retrieve information (use
``SHOW`` commands instead), because of speed issues when many
databases are present. Currently used in some parts of the code, more
to come.
databases are present.
.. note::
Enabling this option might give you big performance boost on older
MySQL servers.
.. config:option:: $cfg['Servers'][$i]['SignonScript']
@ -1185,6 +1368,23 @@ Server connection settings
.. seealso:: :ref:`auth_signon`
.. config:option:: $cfg['Servers'][$i]['SignonCookieParams']
:type: array
:default: ``array()``
.. versionadded:: 4.7.0
An associative array of session cookie parameters of other authentication system.
It is not needed if the other system doesn't use session_set_cookie_params().
Keys should include 'lifetime', 'path', 'domain', 'secure' or 'httponly'.
Valid values are mentioned in `session_get_cookie_params <https://php.net/manual/en/
function.session-get-cookie-params.php>`_, they should be set to same values as the
other application uses. Takes effect only if
:config:option:`$cfg['Servers'][$i]['SignonScript']` is not configured.
.. seealso:: :ref:`auth_signon`
.. config:option:: $cfg['Servers'][$i]['SignonURL']
:type: string
@ -1208,6 +1408,13 @@ Server connection settings
Generic settings
----------------
.. config:option:: $cfg['DisableShortcutKeys']
:type: boolean
:default: false
You can disable phpMyAdmin shortcut keys by setting :config:option:`$cfg['DisableShortcutKeys']` to false.
.. config:option:: $cfg['ServerDefault']
:type: integer
@ -1301,14 +1508,14 @@ Generic settings
:type: boolean
:default: false
Whether `persistent connections <https://php.net/manual/en/features
Whether `persistent connections <https://secure.php.net/manual/en/features
.persistent-connections.php>`_ should be used or not. Works with
following extensions:
* mysql (`mysql\_pconnect <https://php.net/manual/en/function.mysql-
* mysql (`mysql\_pconnect <https://secure.php.net/manual/en/function.mysql-
pconnect.php>`_),
* mysqli (requires PHP 5.3.0 or newer, `more information
<https://php.net/manual/en/mysqli.persistconns.php>`_).
<https://secure.php.net/manual/en/mysqli.persistconns.php>`_).
.. config:option:: $cfg['ForceSSL']
@ -1345,7 +1552,7 @@ Generic settings
:default: ``''``
Path for storing session data (`session\_save\_path PHP parameter
<https://php.net/session_save_path>`_).
<https://secure.php.net/session_save_path>`_).
.. config:option:: $cfg['MemoryLimit']
@ -1497,7 +1704,7 @@ Cookie authentication options
Define how long a login cookie is valid. Please note that php
configuration option `session.gc\_maxlifetime
<https://php.net/manual/en/session.configuration.php#ini.session.gc-
<https://secure.php.net/manual/en/session.configuration.php#ini.session.gc-
maxlifetime>`_ might limit session validity and if the session is lost,
the login cookie is also invalidated. So it is a good idea to set
``session.gc_maxlifetime`` at least to the same value of
@ -1855,20 +2062,8 @@ Main panel
:type: boolean
:default: false
.. config:option:: $cfg['ShowChgPassword']
:type: boolean
:default: true
.. config:option:: $cfg['ShowCreateDb']
:type: boolean
:default: true
Defines whether to display the :guilabel:`PHP information` and
:guilabel:`Change password` links and form for creating database or not at
the starting main (right) frame. This setting does not check MySQL commands
entered directly.
Defines whether to display the :guilabel:`PHP information` or not at
the starting main (right) frame.
Please note that to block the usage of ``phpinfo()`` in scripts, you have to
put this in your :file:`php.ini`:
@ -1885,11 +2080,29 @@ Main panel
This might also make easier some remote attacks on your installations,
so enable this only when needed.
Also note that enabling the :guilabel:`Change password` link has no effect
.. config:option:: $cfg['ShowChgPassword']
:type: boolean
:default: true
Defines whether to display the :guilabel:`Change password` link or not at
the starting main (right) frame. This setting does not check MySQL commands
entered directly.
Please note that enabling the :guilabel:`Change password` link has no effect
with config authentication mode: because of the hard coded password value
in the configuration file, end users can't be allowed to change their
passwords.
.. config:option:: $cfg['ShowCreateDb']
:type: boolean
:default: true
Defines whether to display the form for creating database or not at the
starting main (right) frame. This setting does not check MySQL commands
entered directly.
.. config:option:: $cfg['ShowGitRevision']
:type: boolean
@ -1999,6 +2212,9 @@ Browse mode
descending order for columns of type TIME, DATE, DATETIME and
TIMESTAMP, ascending order else- by default.
.. versionchanged:: 3.4.0
Since phpMyAdmin 3.4.0 the default value is ``'SMART'``.
.. config:option:: $cfg['GridEditing']
:type: string
@ -2124,6 +2340,13 @@ Export and import settings
items are similar to texts seen on export page, so you can easily
identify what they mean.
.. config:option:: $cfg['Export']['format']
:type: string
:default: ``'sql'``
Default export format.
.. config:option:: $cfg['Export']['method']
:type: string
@ -2137,7 +2360,40 @@ Export and import settings
* ``custom-no-form`` same as ``custom`` but does not display the option
of using quick export
.. config:option:: $cfg['Export']['charset']
:type: string
:default: ``''``
Defines charset for generated export. By default no charset conversion is
done assuming UTF-8.
.. config:option:: $cfg['Export']['file_template_table']
:type: string
:default: ``'@TABLE@'``
Default filename template for table exports.
.. seealso:: :ref:`faq6_27`
.. config:option:: $cfg['Export']['file_template_database']
:type: string
:default: ``'@DATABASE@'``
Default filename template for database exports.
.. seealso:: :ref:`faq6_27`
.. config:option:: $cfg['Export']['file_template_server']
:type: string
:default: ``'@SERVER@'``
Default filename template for server exports.
.. seealso:: :ref:`faq6_27`
.. config:option:: $cfg['Import']
@ -2148,6 +2404,13 @@ Export and import settings
items are similar to texts seen on import page, so you can easily
identify what they mean.
.. config:option:: $cfg['Import']['charset']
:type: string
:default: ``''``
Defines charset for import. By default no charset conversion is done
assuming UTF-8.
Tabs display settings
---------------------
@ -2280,7 +2543,7 @@ Languages
recode)
* iconv - use iconv or libiconv functions
* recode - use recode\_string function
* mb - use mbstring extension
* mb - use :term:`mbstring` extension
* none - disable encoding conversion
Enabled charset conversion activates a pull-down menu in the Export
@ -2464,7 +2727,7 @@ Design customization
:default: false
Defines whether to show row links (Edit, Copy, Delete) and checkboxes
for multiple row operations even when the selection does not have a unique key.
for multiple row operations even when the selection does not have a :term:`unique key`.
Using row actions in the absence of a unique key may result in different/more
rows being affected since there is no guaranteed way to select the exact row(s).
@ -2480,7 +2743,7 @@ Design customization
:type: string
:default: ``'NONE'``
This defines the default sort order for the tables, having a primary key,
This defines the default sort order for the tables, having a :term:`primary key`,
when there is no sort order defines externally.
Acceptable values : ['NONE', 'ASC', 'DESC']
@ -2788,6 +3051,8 @@ Various display setting
``SELECT COUNT`` will be used, otherwise the approximate count will be
used.
.. seealso:: :ref:`faq3_11`
.. config:option:: $cfg['MaxExactCountViews']
:type: integer
@ -2861,14 +3126,6 @@ Page titles
Theme manager settings
----------------------
.. config:option:: $cfg['ThemePath']
:type: string
:default: ``'./themes'``
If theme manager is active, use this as the path of the subdirectory
containing all the themes.
.. config:option:: $cfg['ThemeManager']
:type: boolean
@ -2881,7 +3138,7 @@ Theme manager settings
:type: string
:default: ``'pmahomme'``
The default theme (a subdirectory under :config:option:`$cfg['ThemePath']`).
The default theme (a subdirectory under :file:`./themes/`).
.. config:option:: $cfg['ThemePerServer']
@ -2941,6 +3198,14 @@ Developer
Enable logging queries and execution times to be
displayed in the console's Debug SQL tab.
.. config:option:: $cfg['DBG']['sqllog']
:type: boolean
:default: false
Enable logging of queries and execution times to the syslog.
Requires :config:option:`$cfg['DBG']['sql']` to be enabled.
.. config:option:: $cfg['DBG']['demo']
:type: boolean
@ -2949,11 +3214,103 @@ Developer
Enable to let server present itself as demo server.
This is used for `phpMyAdmin demo server <https://www.phpmyadmin.net/try/>`_.
.. _config-examples:
Examples
--------
See following configuration snippets for usual setups of phpMyAdmin.
See following configuration snippets for typical setups of phpMyAdmin.
Basic example
+++++++++++++
Example configuration file, which can be copied to :file:`config.inc.php` to
get some core configuration layout; it is distributed with phpMyAdmin as
:file:`config.sample.inc.php`. Please note that it does not contain all
configuration options, only the most frequently used ones.
.. literalinclude:: ../config.sample.inc.php
:language: php
.. warning::
Don't use the controluser 'pma' if it does not yet exist and don't use 'pmapass'
as password.
.. _example-signon:
Example for signon authentication
+++++++++++++++++++++++++++++++++
This example uses :file:`examples/signon.php` to demonstrate usage of :ref:`auth_signon`:
.. code-block:: php
<?php
$i = 0;
$i++;
$cfg['Servers'][$i]['extension'] = 'mysqli';
$cfg['Servers'][$i]['auth_type'] = 'signon';
$cfg['Servers'][$i]['SignonSession'] = 'SignonSession';
$cfg['Servers'][$i]['SignonURL'] = 'examples/signon.php';
?>`
Example for IP address limited autologin
++++++++++++++++++++++++++++++++++++++++
If you want to automatically login when accessing phpMyAdmin locally while asking
for a password when accessing remotely, you can achieve it using following snippet:
.. code-block:: php
if ($_SERVER["REMOTE_ADDR"] == "127.0.0.1") {
$cfg['Servers'][$i]['auth_type'] = 'config';
$cfg['Servers'][$i]['user'] = 'root';
$cfg['Servers'][$i]['password'] = 'yourpassword';
} else {
$cfg['Servers'][$i]['auth_type'] = 'cookie';
}
.. note::
Filtering based on IP addresses isn't reliable over the internet, use it
only for local address.
Example for using multiple MySQL servers
++++++++++++++++++++++++++++++++++++++++
You can configure any number of servers using :config:option:`$cfg['Servers']`,
following example shows two of them:
.. code-block:: php
<?php
$cfg['blowfish_secret']='multiServerExample70518';
//any string of your choice
$i = 0;
$i++; // server 1 :
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['verbose'] = 'no1';
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['extension'] = 'mysqli';
// more options for #1 ...
$i++; // server 2 :
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['verbose'] = 'no2';
$cfg['Servers'][$i]['host'] = 'remote.host.addr';//or ip:'10.9.8.1'
// this server must allow remote clients, e.g., host 10.9.8.%
// not only in mysql.host but also in the startup configuration
$cfg['Servers'][$i]['extension'] = 'mysqli';
// more options for #2 ...
// end of server sections
$cfg['ServerDefault'] = 0; // to choose the server on startup
// further general options ...
?>
.. _example-google-ssl:
@ -2963,7 +3320,9 @@ Google Cloud SQL with SSL
To connect to Google Could SQL, you currently need to disable certificate
verification. This is caused by the certficate being issued for CN matching
your instance name, but you connect to an IP address and PHP tries to match
these two. With verfication you end up with error message like::
these two. With verfication you end up with error message like:
.. code-block:: text
Peer certificate CN=`api-project-851612429544:pmatest' did not match expected CN=`8.8.8.8'
@ -2978,7 +3337,7 @@ server certificates and tell phpMyAdmin to use them:
.. code-block:: php
// IP address of your instance
$cfg['Servers'][2]['host'] = '8.8.8.8';
$cfg['Servers'][$i]['host'] = '8.8.8.8';
// Use SSL for connection
$cfg['Servers'][$i]['ssl'] = true;
// Client secret key
@ -2996,4 +3355,5 @@ server certificates and tell phpMyAdmin to use them:
:config:option:`$cfg['Servers'][$i]['ssl_key']`,
:config:option:`$cfg['Servers'][$i]['ssl_cert']`,
:config:option:`$cfg['Servers'][$i]['ssl_ca']`,
:config:option:`$cfg['Servers'][$i]['ssl_verify']`
:config:option:`$cfg['Servers'][$i]['ssl_verify']`,
<https://bugs.php.net/bug.php?id=72048>

View File

@ -6,7 +6,7 @@ Copyright
.. code-block:: none
Copyright (C) 1998-2000 Tobias Ratschiller <tobias_at_ratschiller.com>
Copyright (C) 2001-2014 Marc Delisle <marc_at_infomarc.info>
Copyright (C) 2001-2017 Marc Delisle <marc_at_infomarc.info>
Olivier Müller <om_at_omnis.ch>
Robin Johnson <robbat2_at_users.sourceforge.net>
Alexander M. Turek <me_at_derrabus.de>
@ -38,12 +38,5 @@ jQuery's license, which is where we got the files under js/jquery/ is
(MIT|GPL), a copy of each license is available in this repository (GPL
is available as LICENSE, MIT as js/jquery/MIT-LICENSE.txt).
TCPDF which is located under libraries/tcpdf is released under GPL
version 3 and the license is available as libraries/tcpdf/LICENSE.TXT.
DejaVu fonts which are located under libraries/tcpdf/fonts/ and their
license is documented in
libraries/tcpdf/fonts/dejavu-fonts-ttf-2.33/LICENSE.
PHP-gettext which is located under libraries/php-gettext/ is released
under GPL version 2 license which is available in the LICENSE file.
The download kit additionally includes several composer libraries. See their
licensing information in the vendor/ directory.

View File

@ -183,7 +183,7 @@ Credits, in chronological order
* :term:`PDF` schema output, thanks also to
Olivier Plathey for the "FPDF" library (see <http://www.fpdf.org/>), Steven
Wittens for the "UFPDF" library (see <https://acko.net/blog/ufpdf-unicode-utf-8-extension-for-fpdf/>) and
Nicola Asuni for the "TCPDF" library (see <https://www.tcpdf.org/>).
Nicola Asuni for the "TCPDF" library (see <https://tcpdf.org/>).
* Olof Edlund <olof.edlund\_at\_upright.se>
@ -563,7 +563,7 @@ Following people have contributed to translation of phpMyAdmin:
* Finnish
* Juha <jremes\_at\_outlook.com>
* Juha Remes <jremes\_at\_outlook.com>
* Lari Oesch <lari\_at\_oesch.me>

View File

@ -68,7 +68,7 @@ and :file:`index.php`.
.. _faq1_7:
1.7 How can I GZip a dump or a CSV export? It does not seem to work.
1.7 How can I gzip a dump or a CSV export? It does not seem to work.
--------------------------------------------------------------------
This feature is based on the ``gzencode()``
@ -115,8 +115,8 @@ It seems to clear up many problems between Internet Explorer and SSL.
.. _faq1_11:
1.11 I get an 'open\_basedir restriction' while uploading a file from the query box.
------------------------------------------------------------------------------------
1.11 I get an 'open\_basedir restriction' while uploading a file from the import tab.
-------------------------------------------------------------------------------------
Since version 2.2.4, phpMyAdmin supports servers with open\_basedir
restrictions. However you need to create temporary directory and configure it
@ -128,9 +128,15 @@ and after execution of your :term:`SQL` commands, removed.
1.12 I have lost my MySQL root password, what can I do?
-------------------------------------------------------
phpMyAdmin does authenticate against MySQL server you're using, so to recover
from phpMyAdmin password loss, you need to recover at MySQL level.
The MySQL manual explains how to `reset the permissions
<https://dev.mysql.com/doc/refman/5.7/en/resetting-permissions.html>`_.
If you are using MySQL server installed by your hosting provider, please
contact their support to recover the password for you.
.. _faq1_13:
1.13 (withdrawn).
@ -159,14 +165,13 @@ Starting with version 2.7.0, the import engine has been rewritten and
these problems should not occur. If possible, upgrade your phpMyAdmin
to the latest version to take advantage of the new import features.
The first things to check (or ask your host provider to check) are the
values of ``upload_max_filesize``, ``memory_limit`` and
``post_max_size`` in the :file:`php.ini` configuration file. All of these
three settings limit the maximum size of data that can be submitted
and handled by PHP. One user also said that ``post_max_size`` and
``memory_limit`` need to be larger than ``upload_max_filesize``.
There exist several workarounds if your upload is too big or your
hosting provider is unwilling to change the settings:
The first things to check (or ask your host provider to check) are the values
of ``max_execution_time``, ``upload_max_filesize``, ``memory_limit`` and
``post_max_size`` in the :file:`php.ini` configuration file. All of these three
settings limit the maximum size of data that can be submitted and handled by
PHP. Please note that ``post_max_size`` needs to be larger than
``upload_max_filesize``. There exist several workarounds if your upload is too
big or your hosting provider is unwilling to change the settings:
* Look at the :config:option:`$cfg['UploadDir']` feature. This allows one to upload a file to the server
via scp, ftp, or your favorite file transfer method. PhpMyAdmin is
@ -207,7 +212,7 @@ your server - as mentioned in :ref:`faq1_17`. This problem is
generally caused by using MySQL version 4.1 or newer. MySQL changed
the authentication hash and your PHP is trying to use the old method.
The proper solution is to use the `mysqli extension
<https://www.php.net/mysqli>`_ with the proper client library to match
<https://secure.php.net/mysqli>`_ with the proper client library to match
your MySQL installation. More
information (and several workarounds) are located in the `MySQL
Documentation <https://dev.mysql.com/doc/refman/5.7/en/old-client.html>`_.
@ -242,6 +247,41 @@ or something similar.
There are currently two interfaces PHP provides as MySQL extensions - ``mysql``
and ``mysqli``. The ``mysqli`` is tried first, because it's the best one.
This problem can be also caused by wrong paths in the :file:`php.ini` or using
wrong :file:`php.ini`.
Make sure that the extension files do exist in the folder which the
``extension_dir`` points to and that the corresponding lines in your
:file:`php.ini` are not commented out (you can use ``phpinfo()`` to check
current setup):
.. code-block:: ini
[PHP]
; Directory in which the loadable extensions (modules) reside.
extension_dir = "C:/Apache2/modules/php/ext"
The :file:`php.ini` can be loaded from several locations (especially on
Windows), so please check you're updating the correct one. If using Apache, you
can tell it to use specific path for this file using ``PHPIniDir`` directive:
.. code-block:: apache
LoadFile "C:/php/php5ts.dll"
LoadModule php5_module "C:/php/php5apache2_2.dll"
<IfModule php5_module>
PHPIniDir "C:/PHP"
<Location>
AddType text/html .php
AddHandler application/x-httpd-php .php
</Location>
</IfModule>
In some rare cases this problem can be also caused by other extensions loaded
in PHP which prevent MySQL extensions to be loaded. If anything else fails, you
can try commenting out extensions for other databses from :file:`php.ini`.
.. _faq1_21:
1.21 I am running the CGI version of PHP under Unix, and I cannot log in using cookie auth.
@ -272,6 +312,12 @@ directory and add the following line to the group [mysqld]:
set-variable = lower_case_table_names=0
.. note::
Forcing this variable to 0 with --lower-case-table-names=0 on a
case-insensitive filesystem and access MyISAM tablenames using different
lettercases, index corruption may result.
Next, save the file and restart the MySQL service. You can always
check the value of this directive using the query
@ -279,6 +325,8 @@ check the value of this directive using the query
SHOW VARIABLES LIKE 'lower_case_table_names';
.. seealso:: `Identifier Case Sensitivity in the MySQL Reference Manual <https://dev.mysql.com/doc/refman/5.7/en/identifier-case-sensitivity.html>`_
.. _faq1_24:
1.24 (withdrawn).
@ -330,7 +378,7 @@ This can happen due to a MySQL bug when having database / table names
with upper case characters although ``lower_case_table_names`` is
set to 1. To fix this, turn off this directive, convert all database
and table names to lower case and turn it on again. Alternatively,
there's a bug-fix available starting with MySQL 3.23.56 /
there's a bug-fix available starting with MySQL 3.23.56 /
4.0.11-gamma.
.. _faq1_29:
@ -378,12 +426,16 @@ MMCache but upgrading MMCache to version 2.3.21 solves the problem.
.. _faq1_31:
1.31 Does phpMyAdmin support PHP 5?
-----------------------------------
1.31 Which PHP versions does phpMyAdmin support?
------------------------------------------------
Yes.
Since release 4.5, phpMyAdmin supports only PHP 5.5 and newer. Since release
4.1 phpMyAdmin supports only PHP 5.3 and newer. For PHP 5.2 you can use 4.0.x
releases.
Since release 4.5, phpMyAdmin supports only PHP 5.5 and newer. Since release 4.1 phpMyAdmin supports only PHP 5.3 and newer. For PHP 5.2 you can use 4.0.x releases.
PHP 7 is supported since phpMyAdmin 4.6, PHP 7.1 is supported since 4.6.5.
phpMyAdmin also works fine with HHVM.
.. _faq1_32:
@ -415,12 +467,12 @@ Yes. This procedure was tested with phpMyAdmin 2.6.1, PHP 4.3.9 in
------------------------------------------------------
Yes. Out of the box, you can use :term:`URL` like
https://example.com/phpMyAdmin/index.php?server=X&db=database&table=table&target=script.
``http://server/phpMyAdmin/index.php?server=X&db=database&table=table&target=script``.
For ``server`` you use the server number
which refers to the order of the server paragraph in
:file:`config.inc.php`. Table and script parts are optional. If you want
https://example.com/phpMyAdmin/database[/table][/script] :term:`URL`, you need to do some configuration. Following
lines apply only for `Apache <https://httpd.apache.org/>`_ web server.
``http://server/phpMyAdmin/database[/table][/script]`` :term:`URL`, you need to do some configuration. Following
lines apply only for `Apache <https://httpd.apache.org>`_ web server.
First make sure, that you have enabled some features within global
configuration. You need ``Options SymLinksIfOwnerMatch`` and ``AllowOverride
FileInfo`` enabled for directory where phpMyAdmin is installed and you
@ -477,7 +529,7 @@ extension which works fine in this case.
Yes but the default configuration values of Suhosin are known to cause
problems with some operations, for example editing a table with many
columns and no primary key or with textual primary key.
columns and no :term:`primary key` or with textual :term:`primary key`.
Suhosin configuration might lead to malfunction in some cases and it
can not be fully avoided as phpMyAdmin is kind of application which
@ -537,10 +589,14 @@ You can also disable the warning using the :config:option:`$cfg['SuhosinDisableW
1.39 When I try to connect via https, I can log in, but then my connection is redirected back to http. What can cause this behavior?
------------------------------------------------------------------------------------------------------------------------------------
Be sure that you have enabled ``SSLOptions`` and ``StdEnvVars`` in
your Apache configuration.
This is caused by the fact that PHP scripts have no knowledge that the site is
using https. Depending on used webserver, you should configure it to let PHP
know about URL and scheme used to access it.
.. seealso:: <http://httpd.apache.org/docs/2.0/mod/mod_ssl.html#ssloptions>
For example in Apache ensure that you have enabled ``SSLOptions`` and
``StdEnvVars`` in the configuration.
.. seealso:: <https://httpd.apache.org/docs/2.4/mod/mod_ssl.html>
.. _faq1_40:
@ -558,7 +614,7 @@ the set-cookie headers. Example from the Apache 2.2 documentation:
ProxyPassReverseCookieDomain backend.example.com public.example.com
ProxyPassReverseCookiePath / /mirror/foo/
Note: if the backend url looks like https://example.com/~user/phpmyadmin, the
Note: if the backend url looks like ``http://server/~user/phpmyadmin``, the
tilde (~) must be url encoded as %7E in the ProxyPassReverse\* lines.
This is not specific to phpmyadmin, it's just the behavior of Apache.
@ -626,7 +682,7 @@ Some users have requested to be able to reduce the size of the phpMyAdmin instal
This is not recommended and could lead to confusion over missing features, but can be done.
A list of files and corresponding functionality which degrade gracefully when removed include:
* :file:`./libraries/tcpdf` folder (exporting to PDF)
* :file:`./vendor/tecnickcom/tcpdf` folder (exporting to PDF)
* :file:`./locale/` folder, or unused subfolders (interface translations)
* Any unused themes in :file:`./themes/`
* :file:`./js/jquery/src/` (included for licensing reasons)
@ -635,6 +691,7 @@ A list of files and corresponding functionality which degrade gracefully when re
* :file:`./setup/` (setup script)
* :file:`./examples/`
* :file:`./sql/` (SQL scripts to configure advanced functionality)
* :file:`./js/openlayers/` (GIS visualization)
.. _faqconfig:
@ -650,7 +707,7 @@ Edit your :file:`config.inc.php` file and ensure there is nothing (I.E. no
blank lines, no spaces, no characters...) neither before the ``<?php`` tag at
the beginning, neither after the ``?>`` tag at the end. We also got a report
from a user under :term:`IIS`, that used a zipped distribution kit: the file
:file:`libraries/Config.class.php` contained an end-of-line character (hex 0A)
:file:`libraries/Config.php` contained an end-of-line character (hex 0A)
at the end; removing this character cleared his errors.
.. _faq2_2:
@ -668,7 +725,22 @@ support into PHP.
2.3 The error message "Warning: MySQL Connection Failed: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (111) ..." is displayed. What can I do?
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
For RedHat users, Harald Legner suggests this on the mailing list:
The error message can also be: :guilabel:`Error #2002 - The server is not
responding (or the local MySQL server's socket is not correctly configured)`.
First, you need to determine what socket is being used by MySQL. To do this,
connect to your server and go to the MySQL bin directory. In this directory
there should be a file named *mysqladmin*. Type ``./mysqladmin variables``, and
this should give you a bunch of info about your MySQL server, including the
socket (*/tmp/mysql.sock*, for example). You can also ask your ISP for the
connection info or, if you're hosting your own, connect from the 'mysql'
command-line client and type 'status' to get the connection type and socket or
port number.
Then, you need to tell PHP to use this socket. You can do this for all PHP in
the :file:`php.ini` or for phpMyAdmin only in the :file:`config.inc.php`. For
example: :config:option:`$cfg['Servers'][$i]['socket']` Please also make sure
that the permissions of this file allow to be readable by your webserver.
On my RedHat-Box the socket of MySQL is */var/lib/mysql/mysql.sock*.
In your :file:`php.ini` you will find a line
@ -685,24 +757,8 @@ change it to
Then restart apache and it will work.
Here is a fix suggested by Brad Ummer:
* First, you need to determine what socket is being used by MySQL. To do
this, telnet to your server and go to the MySQL bin directory. In this
directory there should be a file named *mysqladmin*. Type
``./mysqladmin variables``, and this should give you a bunch of info
about your MySQL server, including the socket (*/tmp/mysql.sock*, for
example).
* Then, you need to tell PHP to use this socket. To do this in
phpMyAdmin, you need to complete the socket information in the
:file:`config.inc.php`. For example:
:config:option:`$cfg['Servers'][$i]['socket']` Please also make sure that
the permissions of this file allow to be readable by your webserver (i.e.
'0755').
Have also a look at the `corresponding section of the MySQL
documentation <https://dev.mysql.com/doc/en/can-not-connect-to-
server.html>`_.
documentation <https://dev.mysql.com/doc/refman/5.7/en/can-not-connect-to-server.html>`_.
.. _faq2_4:
@ -745,20 +801,18 @@ doesn't work in this configuration with port forwarding. If you enter
2.7 Using and creating themes
-----------------------------
Themes are configured with :config:option:`$cfg['ThemePath']`,
:config:option:`$cfg['ThemeManager']` and :config:option:`$cfg['ThemeDefault']`.
Under :config:option:`$cfg['ThemePath']`, you should not delete the
directory ``pmahomme`` or its underlying structure, because this is the
system theme used by phpMyAdmin. ``pmahomme`` contains all images and
styles, for backwards compatibility and for all themes that would not
include images or css-files. If :config:option:`$cfg['ThemeManager']`
is enabled, you can select your favorite theme on the main page. Your selected
theme will be stored in a cookie.
Themes are configured with :config:option:`$cfg['ThemeManager']` and
:config:option:`$cfg['ThemeDefault']`. Under :file:`./themes/`, you should not
delete the directory ``pmahomme`` or its underlying structure, because this is
the system theme used by phpMyAdmin. ``pmahomme`` contains all images and
styles, for backwards compatibility and for all themes that would not include
images or css-files. If :config:option:`$cfg['ThemeManager']` is enabled, you
can select your favorite theme on the main page. Your selected theme will be
stored in a cookie.
To create a theme:
* make a new subdirectory (for example "your\_theme\_name") under :config:option:`$cfg['ThemePath']` (by
default ``themes``)
* make a new subdirectory (for example "your\_theme\_name") under :file:`./themes/`.
* 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"
@ -798,11 +852,11 @@ Here are a few points to check:
Dorninger for the hint).
* In the :file:`php.ini` directive ``arg_separator.input``, a value of ";"
will cause this error. Replace it with "&;".
* If you are using `Hardened-PHP <http://www.hardened-php.net/>`_, you
might want to increase `request limits <http://www.hardened-
php.net/hphp/troubleshooting.html>`_.
* If you are using `Suhosin <https://suhosin.org/stories/index.html>`_, you
might want to increase `request limits <https://suhosin.org/stories/faq.html>`_.
* The directory specified in the :file:`php.ini` directive
``session.save_path`` does not exist or is read-only.
``session.save_path`` does not exist or is read-only (this can be caused
by `bug in the PHP installer <https://bugs.php.net/bug.php?id=39842>`_).
.. _faq2_9:
@ -810,7 +864,7 @@ Here are a few points to check:
---------------------------------
To be able to see a progress bar during your uploads, your server must
have the `APC <https://php.net/manual/en/book.apc.php>`_ extension, the
have the `APC <https://secure.php.net/manual/en/book.apc.php>`_ extension, the
`uploadprogress <https://pecl.php.net/package/uploadprogress>`_ one, or
you must be running PHP 5.4.0 or higher. Moreover, the JSON extension
has to be enabled in your PHP.
@ -845,9 +899,9 @@ again.
----------------------------------------------------------------------------------------------------
Compressed dumps are built in memory and because of this are limited
to php's memory limit. For GZip/BZip2 exports this can be overcome
to php's memory limit. For gzip/bzip2 exports this can be overcome
since 2.5.4 using :config:option:`$cfg['CompressOnFly']` (enabled by default).
Zip exports can not be handled this way, so if you need Zip files for larger
zip exports can not be handled this way, so if you need zip files for larger
dump, you have to use another way.
.. _faq3_3:
@ -903,10 +957,10 @@ TableSeparator or disabling that feature.
3.7 I have table with many (100+) columns and when I try to browse table I get series of errors like "Warning: unable to parse url". How can this be fixed?
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Your table neither have a primary key nor an unique one, so we must
Your table neither have a :term:`primary key` nor an :term:`unique key`, so we must
use a long expression to identify this row. This causes problems to
parse\_url function. The workaround is to create a primary or unique
key.
parse\_url function. The workaround is to create a :term:`primary key`
or :term:`unique key`.
.. _faq3_8:
@ -931,19 +985,19 @@ official phpMyAdmin-homepage.
When MySQL is running in ANSI-compatibility mode, there are some major
differences in how :term:`SQL` is structured (see
<https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_ansi>). Most important of all, the
<https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html>). Most important of all, the
quote-character (") is interpreted as an identifier quote character and not as
a string quote character, which makes many internal phpMyAdmin operations into
invalid :term:`SQL` statements. There is no
workaround to this behaviour. News to this item will be posted in `Bug report
#1013 <https://sourceforge.net/p/phpmyadmin/bugs/1013/>`_.
workaround to this behaviour. News to this item will be posted in `issue
#7383 <https://github.com/phpmyadmin/phpmyadmin/issues/7383>`_.
.. _faq3_10:
3.10 Homonyms and no primary key: When the results of a SELECT display more that one column with the same value (for example ``SELECT lastname from employees where firstname like 'A%'`` and two "Smith" values are displayed), if I click Edit I cannot be sure that I am editing the intended row.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Please make sure that your table has a primary key, so that phpMyAdmin
Please make sure that your table has a :term:`primary key`, so that phpMyAdmin
can use it for the Edit and Delete links.
.. _faq3_11:
@ -959,6 +1013,8 @@ However, one can easily replace the approximate row count with exact count by
simply clicking on the approximate count. This can also be done for all tables
at once by clicking on the rows sum displayed at the bottom.
.. seealso:: :config:option:`$cfg['MaxExactCount']`
.. _faq3_12:
3.12 (withdrawn).
@ -1026,6 +1082,20 @@ accordingly. This is done for the sake of efficiency.
At some point, the character set used to store bookmark content has changed.
It's better to recreate your bookmark from the newer phpMyAdmin version.
.. _faq3_21:
3.21 I am unable to log in with a username containing unicode characters such as á.
-----------------------------------------------------------------------------------
This can happen if MySQL server is not configured to use utf-8 as default
charset. This is a limitation of how PHP and the MySQL server interact; there
is no way for PHP to set the charset before authenticating.
.. seealso::
`phpMyAdmin issue 12232 <https://github.com/phpmyadmin/phpmyadmin/issues/12232>`_,
`MySQL documentation note <https://secure.php.net/manual/en/mysqli.real-connect.php#refsect1-mysqli.real-connect-notes>`_
.. _faqmultiuser:
ISPs, multi-user installations
@ -1176,12 +1246,12 @@ Xitami server.
5.3 I have problems dumping tables with Konqueror (phpMyAdmin 2.2.2).
---------------------------------------------------------------------
With Konqueror 2.1.1: plain dumps, zip and GZip dumps work ok, except
With Konqueror 2.1.1: plain dumps, zip and gzip dumps work ok, except
that the proposed file name for the dump is always 'tbl\_dump.php'.
Bzip2 dumps don't seem to work. With Konqueror 2.2.1: plain dumps
The bzip2 dumps don't seem to work. With Konqueror 2.2.1: plain dumps
work; zip dumps are placed into the user's temporary directory, so
they must be moved before closing Konqueror, or else they disappear.
GZip dumps give an error message. Testing needs to be done for
gzip dumps give an error message. Testing needs to be done for
Konqueror 2.2.2.
.. _faq5_4:
@ -1194,21 +1264,14 @@ till version 6.
.. _faq5_5:
5.5 In Internet Explorer 5.0, I get JavaScript errors when browsing my rows.
5.5 (withdrawn).
----------------------------------------------------------------------------
Upgrade to at least Internet Explorer 5.5 SP2.
.. _faq5_6:
5.6 In Internet Explorer 5.0, 5.5 or 6.0, I get an error (like "Page not found") when trying to modify a row in a table with many columns, or with a text column.
5.6 (withdrawn).
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Your table neither have a primary key nor an unique one, so we must use a long
:term:`URL` to identify this row. There is a limit on the length of the
:term:`URL` in those browsers, and this not happen in Netscape, for example.
The workaround is to create a primary or unique key, or use another browser.
.. _faq5_7:
5.7 I refresh (reload) my browser, and come back to the welcome page.
@ -1235,13 +1298,9 @@ This is a Mozilla bug (see bug #26882 at `BugZilla
.. _faq5_10:
5.10 With Netscape 4.75 I get empty rows between each row of data in a CSV exported file.
5.10 (withdrawn).
-----------------------------------------------------------------------------------------
This is a known Netscape 4.75 bug: it adds some line feeds when
exporting data in octet-stream mode. Since we can't detect the
specific Netscape version, we cannot workaround this bug.
.. _faq5_11:
5.11 Extended-ASCII characters like German umlauts are displayed wrong.
@ -1262,26 +1321,19 @@ Netscape and Mozilla do not have this problem.
.. _faq5_13:
5.13 With Internet Explorer 5.5 or 6, and HTTP authentication type, I cannot manage two servers: I log in to the first one, then the other one, but if I switch back to the first, I have to log in on each operation.
5.13 (withdrawn)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
This is a bug in Internet Explorer, other browsers do not behave this
way.
.. _faq5_14:
5.14 Using Opera6, I can manage to get to the authentication, but nothing happens after that, only a blank screen.
5.14 (withdrawn)
------------------------------------------------------------------------------------------------------------------
Please upgrade to Opera7 at least.
.. _faq5_15:
5.15 I have display problems with Safari.
5.15 (withdrawn)
-----------------------------------------
Please upgrade to at least version 1.2.3.
.. _faq5_16:
5.16 With Internet Explorer, I get "Access is denied" Javascript errors. Or I cannot make phpMyAdmin work under Windows.
@ -1308,14 +1360,9 @@ installed in their Firefox is causing the problem.
.. _faq5_18:
5.18 With Konqueror 4.2.x an invalid ``LIMIT`` clause is generated when I browse a table.
5.18 (withdrawn)
-----------------------------------------------------------------------------------------
This happens only when both of these conditions are met: using the
``http`` authentication mode and ``register_globals`` being set to
``On`` on the server. It seems to be a browser-specific problem;
meanwhile use the ``cookie`` authentication mode.
.. _faq5_19:
5.19 I get JavaScript errors in my browser.
@ -1325,6 +1372,55 @@ Issues have been reported with some combinations of browser
extensions. To troubleshoot, disable all extensions then clear your
browser cache to see if the problem goes away.
.. _faq5_20:
5.20 I get errors about violating Content Security Policy.
----------------------------------------------------------
If you see errors like:
.. code-block:: text
Refused to apply inline style because it violates the following Content Security Policy directive
This is usually caused by some software, which wrongly rewrites
:mailheader:`Content Security Policy` headers. Usually this is caused by
antivirus proxy or browser addons which are causing such errors.
If you see these errors, try disabling the HTTP proxy in antivirus or disable
the :mailheader:`Content Security Policy` rewriting in it. If that doesn't
help, try disabling browser extensions.
Alternatively it can be also server configuration issue (if the webserver is
configured to emit :mailheader:`Content Security Policy` headers, they can
override the ones from phpMyAdmin).
Programs known to cause these kind of errors:
* Kaspersky Internet Security
.. _faq5_21:
5.21 I get errors about potentially unsafe operation when browsing table or executing SQL query.
------------------------------------------------------------------------------------------------
If you see errors like:
.. code-block:: text
A potentially unsafe operation has been detected in your request to this site.
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
or disable it completely for phpMyAdmin path.
Programs known to cause these kind of errors:
* Wordfence Web Application Firewall
.. _faqusing:
Using phpMyAdmin
@ -1509,13 +1605,17 @@ schema layout. Which tables will go on which pages?
Browsers on other operating systems, and other browsers on Windows, do
not have this problem.
.. seealso::
:ref:`relations`
.. _faq6_9:
6.9 phpMyAdmin is changing the type of one of my columns!
---------------------------------------------------------
No, it's MySQL that is doing `silent column type changing
<https://dev.mysql.com/doc/en/silent-column-changes.html>`_.
<https://dev.mysql.com/doc/refman/5.7/en/silent-column-changes.html>`_.
.. _underscore:
@ -1543,7 +1643,7 @@ It means "average".
**Structure:**
* "Add DROP TABLE" will add a line telling MySQL to `drop the table
<https://dev.mysql.com/doc/mysql/en/drop-table.html>`_, if it already
<https://dev.mysql.com/doc/refman/5.7/en/drop-table.html>`_, if it already
exists during the import. It does NOT drop the table after your
export, it only affects the import file.
* "If Not Exists" will only create the table if it doesn't exist.
@ -1564,10 +1664,10 @@ It means "average".
* "Extended inserts" provides a shorter dump file by using only once the
INSERT verb and the table name.
* "Delayed inserts" are best explained in the `MySQL manual - INSERT DELAYED Syntax
<https://dev.mysql.com/doc/mysql/en/insert-delayed.html>`_.
<https://dev.mysql.com/doc/refman/5.7/en/insert-delayed.html>`_.
* "Ignore inserts" treats errors as a warning instead. Again, more info
is provided in the `MySQL manual - INSERT Syntax
<https://dev.mysql.com/doc/mysql/en/insert.html>`_, but basically with
<https://dev.mysql.com/doc/refman/5.7/en/insert.html>`_, but basically with
this selected, invalid values are adjusted and inserted rather than
causing the entire statement to fail.
@ -1608,10 +1708,10 @@ etc.).
.. _faq6_17:
6.17 Transformations: I can't enter my own mimetype! WTF is this feature then useful for?
-----------------------------------------------------------------------------------------
6.17 Transformations: I can't enter my own mimetype! What is this feature then useful for?
------------------------------------------------------------------------------------------
Slow down :). Defining mimetypes is of no use, if you can't put
Defining mimetypes is of no use if you can't put
transformations on them. Otherwise you could just put a comment on the
column. Because entering your own mimetype will cause serious syntax
checking issues and validation, this introduces a high-risk false-
@ -1626,57 +1726,10 @@ mimetypes by heart so he/she can enter it at will?
6.18 Bookmarks: Where can I store bookmarks? Why can't I see any bookmarks below the query box? What are these variables for?
-----------------------------------------------------------------------------------------------------------------------------
Any query you have executed can be stored as a bookmark on the page
where the results are displayed. You will find a button labeled
'Bookmark this query' just at the end of the page. As soon as you have
stored a bookmark, it is related to the database you run the query on.
You can now access a bookmark dropdown on each page, the query box
appears on for that database.
You need to have configured the :ref:`linked-tables` for using bookmarks
feature. Once you have done that, you can use bookmarks in the :guilabel:`SQL` tab.
You can also have, inside the query, placeholders for variables.
This is done by inserting into the query SQL comments between ``/*`` and
``*/``. Inside the comments, the special strings ``[VARIABLE{variable-number}]`` is used.
Be aware that the whole query minus the SQL comments must be
valid by itself, otherwise you won't be able to store it as a bookmark.
When you execute the bookmark, everything typed into the *Variables*
input boxes on the query box page will replace the strings ``/*[VARIABLE{variable-number}]*/`` in
your stored query.
Also remember, that everything else inside the ``/*[VARIABLE{variable-number}]*/`` string for
your query will remain the way it is, but will be stripped of the ``/**/``
chars. So you can use:
.. code-block:: mysql
/*, [VARIABLE1] AS myname */
which will be expanded to
.. code-block:: mysql
, VARIABLE1 as myname
in your query, where VARIABLE1 is the string you entered in the Variable 1 input box.
A more complex example. Say you have stored
this query:
.. code-block:: mysql
SELECT Name, Address FROM addresses WHERE 1 /* AND Name LIKE '%[VARIABLE1]%' */
Say, you now enter "phpMyAdmin" as the variable for the stored query, the full
query will be:
.. code-block:: mysql
SELECT Name, Address FROM addresses WHERE 1 AND Name LIKE '%phpMyAdmin%'
**NOTE THE ABSENCE OF SPACES** inside the ``/**/`` construct. Any spaces
inserted there will be later also inserted as spaces in your query and may lead
to unexpected results especially when using the variable expansion inside of a
"LIKE ''" expression.
.. seealso:: :ref:`bookmarks`
.. _faq6_19:
@ -1706,7 +1759,7 @@ DATABASES, LOCK TABLES. Those privileges also enable users to see all the
database names. So if your users do not need those privileges, you can remove
them and their databases list will shorten.
.. seealso:: <https://bugs.mysql.com/179>
.. seealso:: <https://bugs.mysql.com/bug.php?id=179>
.. _faq6_21:
@ -1733,6 +1786,8 @@ limit of 100, see :config:option:`$cfg['ForeignKeyMaxLimit']`.
Yes. If a bookmark has the same label as a table name and it's not a
public bookmark, it will be executed.
.. seealso:: :ref:`bookmarks`
.. _faq6_23:
6.23 Export: I heard phpMyAdmin can export Microsoft Excel files?
@ -1773,7 +1828,7 @@ in Browse mode or on the Structure page.
-----------------------------------
In all places where phpMyAdmin accepts format strings, you can use
``@VARIABLE@`` expansion and `strftime <https://php.net/strftime>`_
``@VARIABLE@`` expansion and `strftime <https://secure.php.net/strftime>`_
format strings. The expanded variables depend on a context (for
example, if you haven't chosen a table, you can not get the table
name), but the following variables can be used:
@ -1829,8 +1884,7 @@ other.
Not every table can be put to the chart. Only tables with one, two or
three columns can be visualised as a chart. Moreover the table must be
in a special format for chart script to understand it. Currently
supported formats can be found in the `wiki <https://wiki.phpmyadmin.ne
t/pma/Charts#Data_formats_for_query_results_chart>`_.
supported formats can be found in :ref:`charts`.
.. _faq6_30:
@ -1849,7 +1903,7 @@ methods:
Configure upload directory with :config:option:`$cfg['UploadDir']`, upload both .shp and .dbf files with
the same filename and chose the .shp file from the import page.
Create a Zip archive with .shp and .dbf files and import it. For this
Create a zip archive with .shp and .dbf files and import it. For this
to work, you need to set :config:option:`$cfg['TempDir']` to a place where the web server user can
write (for example ``'./tmp'``).
@ -1966,7 +2020,7 @@ Note: The Range search feature will work only `Numeric` and `Date` data type col
.. _faq6_36:
6.36 What is Central columns and How can I use this feature?
6.36 What is Central columns and how can I use this feature?
------------------------------------------------------------
As the name suggests, the Central columns feature enables to maintain a central list of
@ -2018,8 +2072,8 @@ Third Normal Form.
`ownerEmail` varchar(64) NOT NULL,
);
The above table is not in First normal Form as no primary key exists. Primary key
is supposed to be (`petName`,`ownerLastName`,`ownerFirstName`) . If the primary key
The above table is not in First normal Form as no :term:`primary key` exists. Primary key
is supposed to be (`petName`,`ownerLastName`,`ownerFirstName`) . If the :term:`primary key`
is chosen as suggested the resultant table won't be in Second as well as Third Normal
form as the following dependencies exists.
@ -2046,7 +2100,7 @@ involve a manual verification at one point.
* Ensure that you have exclusive access to the table to rearrange
* On your primary key column (i.e. id), remove the AUTO_INCREMENT setting
* On your :term:`primary key` column (i.e. id), remove the AUTO_INCREMENT setting
* Delete your primary key in Structure > indexes
@ -2113,7 +2167,7 @@ Values entered in these field will be substituted in the query before being exec
If you get errors like *#1031 - Table storage engine for 'table_name' doesn't have this option*
while importing the dumps exported from pre-5.7.7 MySQL servers into new MySQL server versions 5.7.7+,
it might be because ROW_FORMAT=FIXED is not supported with InnoDB tables. Moreover, the value of
`innodb_strict_mode <http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_strict_mode>`_ would define if this would be reported as a warning or as an error.
`innodb_strict_mode <https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_strict_mode>`_ would define if this would be reported as a warning or as an error.
Since MySQL version 5.7.9, the default value for `innodb_strict_mode` is `ON` and thus would generate
an error when such a CREATE TABLE or ALTER TABLE statement is encountered.
@ -2141,6 +2195,8 @@ phpMyAdmin project
---------------------------------------------------
Our issues tracker is located at <https://github.com/phpmyadmin/phpmyadmin/issues>.
For security issues, please refer to the instructions at <https://www.phpmyadmin.net/security> to email
the developers directly.
.. _faq7_2:
@ -2211,6 +2267,22 @@ attempts.
This is a server configuration problem. Never enable ``display_errors`` on a production site.
.. _faq8_4:
8.4 CSV files exported from phpMyAdmin could allow a formula injection attack.
------------------------------------------------------------------------------
It is possible to generate a :term:`CSV` file that, when imported to a spreadsheet program such as Microsoft Excel,
could potentially allow the execution of arbitrary commands.
The CSV files generated by phpMyAdmin could potentially contain text that would be interpreted by a spreadsheet program as
a formula, but we do not believe escaping those fields is the proper behavior. There is no means to properly escape and
differentiate between a desired text output and a formula that should be escaped, and CSV is a text format where function
definitions should not be interpreted anyway. We have discussed this at length and feel it is the responsibility of the
spreadsheet program to properly parse and sanitize such data on input instead.
Google also has a `similar view <https://sites.google.com/site/bughunteruniversity/nonvuln/csv-excel-formula-injection>`_.
.. _faqsynchronization:
Synchronization

View File

@ -10,7 +10,7 @@ From Wikipedia, the free encyclopedia
.htaccess
the default name of Apache's directory-level configuration file.
.. seealso:: <https://www.wikipedia.org/wiki/.htaccess>
.. seealso:: <https://en.wikipedia.org/wiki/.htaccess>
ACL
Access Contol List
@ -18,7 +18,7 @@ From Wikipedia, the free encyclopedia
Blowfish
a keyed, symmetric block cipher, designed in 1993 by Bruce Schneier.
.. seealso:: <https://www.wikipedia.org/wiki/Blowfish_(cipher)>
.. seealso:: <https://en.wikipedia.org/wiki/Blowfish_(cipher)>
Browser
a software application that enables a user to display and interact with text, images, and other information typically located on a web page at a website on the World Wide Web.
@ -28,39 +28,39 @@ From Wikipedia, the free encyclopedia
bzip2
a free software/open source data compression algorithm and program developed by Julian Seward.
.. seealso:: <https://www.wikipedia.org/wiki/Bzip2>
.. seealso:: <https://en.wikipedia.org/wiki/Bzip2>
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.
.. seealso:: <https://www.wikipedia.org/wiki/CGI>
.. seealso:: <https://en.wikipedia.org/wiki/CGI>
Changelog
a log or record of changes made to a project.
.. seealso:: <https://www.wikipedia.org/wiki/Changelog>
.. seealso:: <https://en.wikipedia.org/wiki/Changelog>
Client
a computer system that accesses a (remote) service on another computer by some kind of network.
.. seealso:: <https://www.wikipedia.org/wiki/Client_(computing)>
.. seealso:: <https://en.wikipedia.org/wiki/Client_(computing)>
column
a set of data values of a particular simple type, one for each row of the table.
.. seealso:: <https://www.wikipedia.org/wiki/Column_(database)>
.. seealso:: <https://en.wikipedia.org/wiki/Column_(database)>
Cookie
a packet of information sent by a server to a World Wide Web browser and then sent back by the browser each time it accesses that server.
.. seealso:: <https://www.wikipedia.org/wiki/HTTP_cookie>
.. seealso:: <https://en.wikipedia.org/wiki/HTTP_cookie>
CSV
Comma- separated values
.. seealso:: <https://www.wikipedia.org/wiki/Comma-separated_values>
.. seealso:: <https://en.wikipedia.org/wiki/Comma-separated_values>
DB
look at :term:`database`
@ -68,7 +68,7 @@ From Wikipedia, the free encyclopedia
database
an organized collection of data.
.. seealso:: <https://www.wikipedia.org/wiki/Database>
.. seealso:: <https://en.wikipedia.org/wiki/Database>
Engine
look at :term:`storage engines`
@ -76,25 +76,25 @@ From Wikipedia, the free encyclopedia
extension
a PHP module that extends PHP with additional functionality.
.. seealso:: <https://www.wikipedia.org/wiki/extension>
.. seealso:: <https://en.wikipedia.org/wiki/Software_extension>
FAQ
Frequently Asked Questions is a list of commonly asked question and there
answers.
.. seealso:: <https://www.wikipedia.org/wiki/FAQ>
.. seealso:: <https://en.wikipedia.org/wiki/FAQ>
Field
one part of divided data/columns.
.. seealso:: <https://www.wikipedia.org/wiki/Field_(computer_science)>
.. seealso:: <https://en.wikipedia.org/wiki/Field_(computer_science)>
foreign key
a column or group of columns in a database row that point to a key column
or group of columns forming a key of another database row in some
(usually different) table.
.. seealso:: <https://www.wikipedia.org/wiki/Foreign_key>
.. seealso:: <https://en.wikipedia.org/wiki/Foreign_key>
FPDF
the free :term:`PDF` library
@ -104,7 +104,7 @@ From Wikipedia, the free encyclopedia
GD
Graphics Library by Thomas Boutell and others for dynamically manipulating images.
.. seealso:: <https://www.wikipedia.org/wiki/GD_Graphics_Library>
.. seealso:: <https://en.wikipedia.org/wiki/GD_Graphics_Library>
GD2
look at :term:`gd`
@ -112,28 +112,28 @@ From Wikipedia, the free encyclopedia
gzip
gzip is short for GNU zip, a GNU free software file compression program.
.. seealso:: <https://www.wikipedia.org/wiki/Gzip>
.. seealso:: <https://en.wikipedia.org/wiki/Gzip>
host
any machine connected to a computer network, a node that has a hostname.
.. seealso:: <https://www.wikipedia.org/wiki/Host>
.. seealso:: <https://en.wikipedia.org/wiki/Host>
hostname
the unique name by which a network attached device is known on a network.
.. seealso:: <https://www.wikipedia.org/wiki/Hostname>
.. seealso:: <https://en.wikipedia.org/wiki/Hostname>
HTTP
HyperText Transfer Protocol is the primary method used to transfer or
convey information on the World Wide Web.
.. seealso:: <https://www.wikipedia.org/wiki/HyperText_Transfer_Protocol>
.. seealso:: <https://en.wikipedia.org/wiki/HyperText_Transfer_Protocol>
https
a :term:`HTTP`-connection with additional security measures.
.. seealso:: <https://www.wikipedia.org/wiki/Https:_URI_scheme>
.. seealso:: <https://en.wikipedia.org/wiki/Https:_URI_scheme>
IEC
International Electrotechnical Commission
@ -142,42 +142,42 @@ From Wikipedia, the free encyclopedia
Internet Information Services is a set of Internet-based services for
servers using Microsoft Windows.
.. seealso:: <https://www.wikipedia.org/wiki/Internet_Information_Services>
.. seealso:: <https://en.wikipedia.org/wiki/Internet_Information_Services>
Index
a feature that allows quick access to the rows in a table.
.. seealso:: <https://www.wikipedia.org/wiki/Index_(database)>
.. seealso:: <https://en.wikipedia.org/wiki/Index_(database)>
IP
Internet Protocol is a data-oriented protocol used by source and
destination hosts for communicating data across a packet-switched
internetwork.
.. seealso:: <https://www.wikipedia.org/wiki/Internet_Protocol>
.. seealso:: <https://en.wikipedia.org/wiki/Internet_Protocol>
IP Address
a unique number that devices use in order to identify and communicate with each other on a network utilizing the Internet Protocol standard.
.. seealso:: <https://www.wikipedia.org/wiki/IP_Address>
.. seealso:: <https://en.wikipedia.org/wiki/IP_Address>
IPv6
IPv6 (Internet Protocol version 6) is the latest revision of the
Internet Protocol (:term:`IP`), designed to deal with the
long-anticipated problem of its precedessor IPv4 running out of addresses.
.. seealso:: <https://www.wikipedia.org/wiki/IPv6>
.. seealso:: <https://en.wikipedia.org/wiki/IPv6>
ISAPI
Internet Server Application Programming Interface is the API of Internet Information Services (IIS).
.. seealso:: <https://www.wikipedia.org/wiki/ISAPI>
.. seealso:: <https://en.wikipedia.org/wiki/ISAPI>
ISP
Internet service provider is a business or organization that offers users
access to the Internet and related services.
.. seealso:: <https://www.wikipedia.org/wiki/ISP>
.. seealso:: <https://en.wikipedia.org/wiki/ISP>
ISO
International Standards Organisation
@ -185,7 +185,7 @@ From Wikipedia, the free encyclopedia
JPEG
a most commonly used standard method of lossy compression for photographic images.
.. seealso:: <https://www.wikipedia.org/wiki/JPEG>
.. seealso:: <https://en.wikipedia.org/wiki/JPEG>
JPG
look at :term:`jpeg`
@ -196,38 +196,45 @@ From Wikipedia, the free encyclopedia
LATEX
a document preparation system for the TEX typesetting program.
.. seealso:: <https://www.wikipedia.org/wiki/LaTeX>
.. seealso:: <https://en.wikipedia.org/wiki/LaTeX>
Mac
Apple Macintosh is line of personal computers is designed, developed, manufactured, and marketed by Apple Computer.
.. seealso:: <https://www.wikipedia.org/wiki/Mac>
.. seealso:: <https://en.wikipedia.org/wiki/Mac>
Mac OS X
the operating system which is included with all currently shipping Apple Macintosh computers in the consumer and professional markets.
.. seealso:: <https://www.wikipedia.org/wiki/Mac_OS_X>
.. seealso:: <https://en.wikipedia.org/wiki/Mac_OS_X>
mbstring
The PHP `mbstring` functions provide support for languages represented by multi-byte character sets, most notably UTF-8.
If you have troubles installing this extension, please follow :ref:`faqmysql`, it provides useful hints.
.. seealso:: <https://secure.php.net/manual/en/book.mbstring.php>
MCrypt
a cryptographic library.
.. seealso:: <https://www.wikipedia.org/wiki/MCrypt>
.. seealso:: <https://en.wikipedia.org/wiki/MCrypt>
mcrypt
the MCrypt PHP extension.
.. seealso:: <https://php.net/mcrypt>
.. seealso:: <https://secure.php.net/mcrypt>
MIME
Multipurpose Internet Mail Extensions is
an Internet Standard for the format of e-mail.
.. seealso:: <https://www.wikipedia.org/wiki/MIME>
.. seealso:: <https://en.wikipedia.org/wiki/MIME>
module
some sort of extension for the Apache Webserver.
.. seealso:: <https://www.wikipedia.org/wiki/module>
.. seealso:: <https://en.wikipedia.org/wiki/Apache_HTTP_Server>
mod_proxy_fcgi
an Apache module implmenting a Fast CGI interface; PHP can be run as a CGI module, FastCGI, or
@ -236,34 +243,34 @@ From Wikipedia, the free encyclopedia
MySQL
a multithreaded, multi-user, SQL (Structured Query Language) Database Management System (DBMS).
.. seealso:: <https://www.wikipedia.org/wiki/MySQL>
.. seealso:: <https://en.wikipedia.org/wiki/MySQL>
mysqli
the improved MySQL client PHP extension.
.. seealso:: <https://php.net/mysqli>
.. seealso:: <https://secure.php.net/manual/en/book.mysqli.php>
mysql
the MySQL client PHP extension.
.. seealso:: <https://php.net/mysql>
.. seealso:: <https://secure.php.net/manual/en/book.mysql.php>
OpenDocument
open standard for office documents.
.. seealso:: <https://www.wikipedia.org/wiki/OpenDocument>
.. seealso:: <https://en.wikipedia.org/wiki/OpenDocument>
OS X
look at :term:`Mac OS X`.
.. seealso:: <https://www.wikipedia.org/wiki/OS_X>
.. seealso:: <https://en.wikipedia.org/wiki/OS_X>
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://www.wikipedia.org/wiki/Portable_Document_Format>
.. seealso:: <https://en.wikipedia.org/wiki/Portable_Document_Format>
PEAR
the PHP Extension and Application Repository.
@ -274,7 +281,7 @@ From Wikipedia, the free encyclopedia
Perl Compatible Regular Expressions is the perl-compatible regular
expression functions for PHP
.. seealso:: <https://php.net/pcre>
.. seealso:: <https://secure.php.net/pcre>
PHP
short for "PHP: Hypertext Preprocessor", is an open-source, reflective
@ -282,19 +289,36 @@ From Wikipedia, the free encyclopedia
and dynamic web content, and more recently, a broader range of software
applications.
.. seealso:: <https://www.wikipedia.org/wiki/PHP>
.. seealso:: <https://en.wikipedia.org/wiki/PHP>
port
a connection through which data is sent and received.
.. seealso:: <https://www.wikipedia.org/wiki/Port_(computing)>
.. seealso:: <https://en.wikipedia.org/wiki/Port_(computing)>
primary key
A primary key is an index over one or more fields in a table with
unique values for each single row in this table. Every table should have
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
key* as primary key if there is one.
You can create the primary key when creating the table (in phpMyAdmin
just check the primary key radio buttons for each field you wish to be
part of the primary key).
You can also add a primary key to an existing table with `ALTER` `TABLE`
or `CREATE` `INDEX` (in phpMyAdmin you can just click on 'add index' on
the table structure page below the listed fields).
RFC
Request for Comments (RFC) documents are a series of memoranda
encompassing new research, innovations, and methodologies applicable to
Internet technologies.
.. seealso:: <https://www.wikipedia.org/wiki/Request_for_Comments>
.. seealso:: <https://en.wikipedia.org/wiki/Request_for_Comments>
RFC 1952
GZIP file format specification version 4.3
@ -304,17 +328,23 @@ From Wikipedia, the free encyclopedia
Row (record, tuple)
represents a single, implicitly structured data item in a table.
.. seealso:: <https://www.wikipedia.org/wiki/Row_(database)>
.. seealso:: <https://en.wikipedia.org/wiki/Row_(database)>
Server
a computer system that provides services to other computing systems over a network.
.. seealso:: <https://www.wikipedia.org/wiki/Server_(computing)>
.. seealso:: <https://en.wikipedia.org/wiki/Server_(computing)>
Storage Engines
handlers for different table types
MySQL can use several different formats for storing data on disk, these
are called storage engines or table types. phpMyAdmin allows a user to
change their storage engine for a particular table through the operations
tab.
.. seealso:: <https://dev.mysql.com/doc/en/storage-engines.html>
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>
socket
a form of inter-process communication.
@ -325,7 +355,7 @@ From Wikipedia, the free encyclopedia
Secure Sockets Layer is a cryptographic protocol which provides secure
communication on the Internet.
.. seealso:: <https://www.wikipedia.org/wiki/Secure_Sockets_Layer>
.. seealso:: <https://en.wikipedia.org/wiki/Secure_Sockets_Layer>
Stored procedure
a subroutine available to applications accessing a relational database system
@ -335,7 +365,7 @@ From Wikipedia, the free encyclopedia
SQL
Structured Query Language
.. seealso:: <https://www.wikipedia.org/wiki/SQL>
.. seealso:: <https://en.wikipedia.org/wiki/SQL>
table
a set of data elements (cells) that is organized, defined and stored as
@ -343,18 +373,18 @@ From Wikipedia, the free encyclopedia
identified by a label or key or by it?s position in relation to other
items.
.. seealso:: <https://www.wikipedia.org/wiki/Table_(database)>
.. seealso:: <https://en.wikipedia.org/wiki/Table_(database)>
tar
a type of archive file format: the Tape ARchive format.
.. seealso:: <https://www.wikipedia.org/wiki/Tar_(file_format)>
.. seealso:: <https://en.wikipedia.org/wiki/Tar_(file_format)>
TCP
Transmission Control Protocol is one of the core protocols of the
Internet protocol suite.
.. seealso:: <https://www.wikipedia.org/wiki/TCP>
.. seealso:: <https://en.wikipedia.org/wiki/TCP>
TCPDF
Rewrite of :term:`UFPDF` with various improvements.
@ -366,6 +396,11 @@ From Wikipedia, the free encyclopedia
.. seealso:: <https://en.wikipedia.org/wiki/Database_trigger>
unique key
An unique key is an index over one or more fields in a table which has a
unique value for each row. The first unique key will be treated as
:term:`primary key` if there is no *primary key* defined.
UFPDF
Unicode/UTF-8 extension for :term:`FPDF`
@ -376,28 +411,28 @@ From Wikipedia, the free encyclopedia
standardized format, that is used for referring to resources, such as
documents and images on the Internet, by their location.
.. seealso:: <https://www.wikipedia.org/wiki/URL>
.. 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.
.. seealso:: <https://www.wikipedia.org/wiki/Webserver>
.. seealso:: <https://en.wikipedia.org/wiki/Webserver>
XML
Extensible Markup Language is a W3C-recommended general- purpose markup
language for creating special-purpose markup languages, capable of
describing many different kinds of data.
.. seealso:: <https://www.wikipedia.org/wiki/XML>
.. seealso:: <https://en.wikipedia.org/wiki/XML>
ZIP
a popular data compression and archival format.
.. seealso:: <https://www.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.
.. seealso:: <https://www.wikipedia.org/wiki/Zlib>
.. seealso:: <https://en.wikipedia.org/wiki/Zlib>

BIN
doc/images/bar_chart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
doc/images/chart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
doc/images/column_chart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
doc/images/line_chart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
doc/images/pie_chart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
doc/images/spline_chart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,11 +1,77 @@
Import and export
=================
In addition to the standard Import and Export tab, you can also import an SQL file directly by dragging and dropping
it from your local file manager to the phpMyAdmin interface in your web browser.
Import
++++++
Open Document Spreadsheet
-------------------------
To import data, go to the "Import" tab in phpMyAdmin. To import data into a
specific database or table, open the database or table before going to the
"Import" tab.
In addition to the standard Import and Export tab, you can also import an SQL
file directly by dragging and dropping it from your local file manager to the
phpMyAdmin interface in your web browser.
If you are having troubles importing big files, please consult :ref:`faq1_16`.
You can import using following methods:
Form based upload
Can be used with any supported format, also (b|g)zipped files, e.g., mydump.sql.gz .
Form based SQL Query
Can be used with valid SQL dumps.
Using upload directory
You can specify an upload directory on your web server where phpMyAdmin is installed, after uploading your file into this directory you can select this file in the import dialog of phpMyAdmin, see :config:option:`$cfg['UploadDir']`.
phpMyAdmin can import from several various commonly used formats.
CSV
---
Comma separated values format which is often used by spreadsheets or various other programs for export/import.
.. note::
When importing data into a table from a CSV file where the table has an
'auto_increment' field, make the 'auto_increment' value for each record in
the CSV field to be '0' (zero). This allows the 'auto_increment' field to
populate correctly.
It is now possible to import a CSV file at the server or database level.
Instead of having to create a table to import the CSV file into, a best-fit
structure will be determined for you and the data imported into it, instead.
All other features, requirements, and limitations are as before.
CSV using LOAD DATA
-------------------
Similar to CSV, only using the internal MySQL parser and not the phpMyAdmin one.
ESRI Shape File
---------------
The ESRI shapefile or simply a shapefile is a popular geospatial vector data
format for geographic information systems software. It is developed and
regulated by Esri as a (mostly) open specification for data interoperability
among Esri and other software products.
MediaWiki
---------
MediaWiki files, which can be exported by phpMyAdmin (version 4.0 or later),
can now also be imported. This is the format used by Wikipedia to display
tables.
Open Document Spreadsheet (ODS)
-------------------------------
OpenDocument workbooks containing one or more spreadsheets can now be directly imported.
When importing an ODS speadsheet, the spreadsheet must be named in a specific way in order to make the
import as simple as possible.
@ -25,3 +91,267 @@ accomplished by inserting a new row at the top of your spreadsheet). When on the
checkbox for "The first line of the file contains the table column names;" this way your newly imported
data will go to the proper columns.
.. note::
Formulas and calculations will NOT be evaluated, rather, their value from
the most recent save will be loaded. Please ensure that all values in the
spreadsheet are as needed before importing it.
SQL
---
SQL can be used to make any manipulation on data, it is also useful for restoring backed up data.
XML
---
XML files exported by phpMyAdmin (version 3.3.0 or later) can now be imported.
Structures (databases, tables, views, triggers, etc.) and/or data will be
created depending on the contents of the file.
The supported xml schemas are not yet documented in this wiki.
Export
++++++
phpMyAdmin can export into text files (even compressed) on your local disk (or
a special the webserver :config:option:`$cfg['SaveDir']` folder) in various
commonly used formats:
CodeGen
-------
`NHibernate <https://en.wikipedia.org/wiki/NHibernate>`_ file format. Planned
versions: Java, Hibernate, PHP PDO, JSON, etc. So the preliminary name is
codegen.
CSV
---
Comma separated values format which is often used by spreadsheets or various
other programs for export/import.
CSV for Microsoft Excel
-----------------------
This is just preconfigured version of CSV export which can be imported into
most English versions of Microsoft Excel. Some localised versions (like
"Danish") are expecting ";" instead of "," as field separator.
Microsoft Word 2000
-------------------
If you're using Microsoft Word 2000 or newer (or compatible such as
OpenOffice.org), you can use this export.
JSON
----
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It
is easy for humans to read and write and it is easy for machines to parse and
generate.
.. versionchanged:: 4.7.0
The generated JSON structure has been changed in phpMyAdmin 4.7.0 to
produce valid JSON data.
The generated JSON is list of objects with following attributes:
.. js:data:: type
Type of given object, can be one of:
``header``
Export header containing comment and phpMyAdmin version.
``database``
Start of a database marker, containing name of database.
``table``
Table data export.
.. js:data:: version
Used in ``header`` :js:data:`type` and indicates phpMyAdmin version.
.. js:data:: comment
Optional textual comment.
.. js:data:: name
Object name - either table or database based on :js:data:`type`.
.. js:data:: database
Database name for ``table`` :js:data:`type`.
.. js:data:: data
Table content for ``table`` :js:data:`type`.
Sample output:
.. code-block:: json
[
{
"comment": "Export to JSON plugin for PHPMyAdmin",
"type": "header",
"version": "4.7.0-dev"
},
{
"name": "cars",
"type": "database"
},
{
"data": [
{
"car_id": "1",
"description": "Green Chrysler 300",
"make_id": "5",
"mileage": "113688",
"price": "13545.00",
"transmission": "automatic",
"yearmade": "2007"
}
],
"database": "cars",
"name": "cars",
"type": "table"
},
{
"data": [
{
"make": "Chrysler",
"make_id": "5"
}
],
"database": "cars",
"name": "makes",
"type": "table"
}
]
LaTeX
-----
If you want to embed table data or structure in LaTeX, this is right choice for you.
LaTeX is a typesetting system that is very suitable for producing scientific
and mathematical documents of high typographical quality. It is also suitable
for producing all sorts of other documents, from simple letters to complete
books. LaTeX uses TeX as its formatting engine. Learn more about TeX and
LaTeX on `the Comprehensive TeX Archive Network <https://www.ctan.org/>`_
also see the `short description od TeX <https://www.ctan.org/tex/>`_.
The output needs to be embedded into a LaTeX document before it can be
rendered, for example in following document:
.. code-block:: latex
\documentclass{article}
\title{phpMyAdmin SQL output}
\author{}
\usepackage{longtable,lscape}
\date{}
\setlength{\parindent}{0pt}
\usepackage[left=2cm,top=2cm,right=2cm,nohead,nofoot]{geometry}
\pdfpagewidth 210mm
\pdfpageheight 297mm
\begin{document}
\maketitle
% insert phpMyAdmin LaTeX Dump here
\end{document}
MediaWiki
---------
Both tables and databases can be exported in the MediaWiki format, which is
used by Wikipedia to display tables. It can export structure, data or both,
including table names or headers.
OpenDocument Spreadsheet
------------------------
Open standard for spreadsheet data, which is being widely adopted. Many recent
spreadsheet programs, such as LibreOffice, OpenOffice or Google Docs can handle
this format. Additionally, some versions of Microsoft Excel can be adapted to
use the OpenDocument Formats through helpers like
<http://odf-converter.sourceforge.net/>.
OpenDocument Text
-----------------
New standard for text data which is being widely addopted. Most recent word
processors (such as OpenOffice.org, AbiWord or KWord) can handle this.
PDF
---
For presentation purposes, non editable PDF might be best choice for you.
PHP Array
---------
You can generate a php file which will declare a multidimensional array with
the contents of the selected table or database.
SQL
---
Export in SQL can be used to restore your database, thus it is useful for
backing up.
The option 'Maximal length of created query' seems to be undocumented. But
experiments has shown that it splits large extended INSERTS so each one is no
bigger than the given number of bytes (or characters?). Thus when importing the
file, for large tables you avoid the error "Got a packet bigger than
'max_allowed_packet' bytes".
.. seealso::
https://dev.mysql.com/doc/refman/5.7/en/packet-too-large.html
Data Options
~~~~~~~~~~~~
**Complete inserts** adds the column names to the SQL dump. This parameter
improves the readability and reliability of the dump. Adding the column names
increases the size of the dump, but when combined with Extended inserts it's
negligible.
**Extended inserts** combines multiple rows of data into a single INSERT query.
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!
-----
`Texy! <https://texy.info/>`_ markup format. You can see example on `Texy! demo
<https://texy.info/en/try/4q5we>`_.
XML
---
Easily parsable export for use with custom scripts.
.. versionchanged:: 3.3.0
The XML schema used has changed as of version 3.3.0
YAML
----
YAML is a data serialization format which is both human readable and
computationally powerful ( <http://www.yaml.org> ).

View File

@ -48,6 +48,21 @@ Currently phpMyAdmin can:
<https://www.phpmyadmin.net/translations/>`_
Shortcut keys
-------------
Currently phpMyAdmin supports following shortcuts:
* k - Toggle console
* h - Go to home page
* s - Open settings
* d + s - Go to database structure (Provided you are in database related page)
* d + f - Search database (Provided you are in database related page)
* t + s - Go to table structure (Provided you are in table related page)
* t + f - Search table (Provided you are in table related page)
* backspace - Takes you to older page.
A word about users
------------------

View File

@ -13,6 +13,21 @@ book and other officially endorsed `books at the phpMyAdmin site`_.
Tutorials
---------
Third party tutorials and articles are listed on our `wiki page`_.
Third party tutorials and articles which you might find interesting:
.. _wiki page: https://wiki.phpmyadmin.net/pma/Articles
Česky (Czech)
+++++++++++++
- `Seriál o phpMyAdminovi <https://cihar.com/publications/linuxsoft/>`_
English
+++++++
- `Having fun with phpMyAdmin's MIME-transformations & PDF-features <http://garv.in/tops/texte/mimetutorial>`_
- `Learning SQL Using phpMyAdmin (old tutorial) <http://www.php-editors.com/articles/sql_phpmyadmin.php>`_
- `Install and configure phpMyAdmin on IIS <http://www.iis-aid.com/articles/how_to_guides/install_and_configure_phpmyadmin_iis>`_
Русский (Russian)
+++++++++++++++++
* `Russian server about phpMyAdmin <http://php-myadmin.ru/>`_

85
doc/relations.rst Normal file
View File

@ -0,0 +1,85 @@
.. _relations:
Relations
=========
phpMyAdmin allows relationships (similar to foreign keys) using MySQL-native
(InnoDB) methods when available and falling back on special phpMyAdmin-only
features when needed. There are two ways of editing these relations, with the
*relation view* and the drag-and-drop *designer* -- both of which are explained
on this page.
.. note::
You need to have configured the :ref:`linked-tables` for using phpMyAdmin
only relations.
Technical info
--------------
Currently the only MySQL table type that natively supports relationships is
InnoDB. When using an InnoDB table, phpMyAdmin will create real InnoDB
relations which will be enforced by MySQL no matter which application accesses
the database. In the case of any other table type, phpMyAdmin enforces the
relations internally and those relations are not applied to any other
application.
Relation view
-------------
In order to get it working, you first have to properly create the
[[pmadb|pmadb]]. Once that is setup, select a table's "Structure" page. Below
the table definition, a link called "Relation view" is shown. If you click that
link, a page will be shown that offers you to create a link to another table
for any (most) fields. Only PRIMARY KEYS are shown there, so if the field you
are referring to is not shown, you most likely are doing something wrong. The
drop-down at the bottom is the field which will be used as the name for a
record.
Relation view example
+++++++++++++++++++++
.. image:: images/pma-relations-relation-view-link.png
.. image:: images/pma-relations-relation-link.png
Let's say you have categories and links and one category can contain several links. Your table structure would be something like this:
- `category.category_id` (must be unique)
- `category.name`
- `link.link_id`
- `link.category_id`
- `link.uri`.
Open the relation view (below the table structure) page for the `link` table and for `category_id` field, you select `category.category_id` as master record.
If you now browse the link table, the `category_id` field will be a clickable hyperlink to the proper category record. But all you see is just the `category_id`, not the name of the category.
.. image:: images/pma-relations-relation-name.png
To fix this, open the relation view of the `category` table and in the drop down at the bottom, select "name". If you now browse the link table again and hover the mouse over the `category_id` hyperlink, the value from the related category will be shown as tooltip.
.. image:: images/pma-relations-links.png
Designer
--------
The Designer feature is a graphical way of creating, editing, and displaying
phpMyAdmin relations. These relations are compatible with those created in
phpMyAdmin's relation view.
To use this feature, you need a properly configured :ref:`linked-tables` and
must have the :config:option:`$cfg['Servers'][$i]['table_coords']` configured.
To use the designer, select a database's structure page, then look for the
:guilabel:`Designer` tab.
To export the view into PDF, you have to create PDF pages first. The Designer
creates the layout, how the tables shall be displayed. To finally export the
view, you have to create this with a PDF page and select your layout, which you
have created with the designer.
.. seealso::
:ref:`faqpdf`

View File

@ -13,7 +13,7 @@ PHP
---
* You need PHP 5.5.0 or newer, with ``session`` support, the Standard PHP Library
(SPL) extension, JSON support, and the ``mbstring`` extension.
(SPL) extension, JSON support, and the ``mbstring`` extension (see :term:`mbstring`).
* To support uploading of ZIP files, you need the PHP ``zip`` extension.
@ -21,19 +21,19 @@ PHP
("image/jpeg: inline") with their original aspect ratio.
* When using the cookie authentication (the default), the `openssl
<https://www.php.net/openssl>`_ extension is strongly suggested.
<https://secure.php.net/openssl>`_ extension is strongly suggested.
* To support upload progress bars, see :ref:`faq2_9`.
* To support XML and Open Document Spreadsheet importing, you need the
`libxml <https://www.php.net/libxml>`_ extension.
`libxml <https://secure.php.net/libxml>`_ extension.
* To support reCAPTCHA on the login page, you need the
`openssl <https://www.php.net/openssl>`_ extension.
`openssl <https://secure.php.net/openssl>`_ extension.
* To support displaying phpMyAdmin's latest version, you need to enable
``allow_url_open`` in your :file:`php.ini` or to have the
`curl <https://www.php.net/curl>`_ extension.
`curl <https://secure.php.net/curl>`_ extension.
.. seealso:: :ref:`faq1_31`, :ref:`authentication_modes`

View File

@ -23,13 +23,23 @@ phpMyAdmin is included in most Linux distributions. It is recommended to use
distribution packages when possible - they usually provide integration to your
distribution and you will automatically get security updates from your distribution.
.. _debian-package:
Debian
------
Debian's package repositories 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.
some ways from the official phpMyAdmin documentation. Specifically it does:
* Configuration of web server (works for Apache and lighttpd).
* Creating of :ref:`linked-tables` using dbconfig-common.
* Securing setup script, see :ref:`debian-setup`.
.. seealso::
More information can be found in `README.Debian <https://anonscm.debian.org/cgit/collab-maint/phpmyadmin.git/tree/debian/README.Debian>`_
(it is installed as :file:`/usr/share/doc/phmyadmin/README.Debian` with the package).
OpenSUSE
--------
@ -42,7 +52,12 @@ Ubuntu
Ubuntu ships phpMyAdmin package, however if you want to use recent version, you
can use packages from
`PPA for Michal Čihař <https://launchpad.net/~nijel/+archive/phpmyadmin>`_.
`phpMyAdmin PPA <https://launchpad.net/~nijel/+archive/ubuntu/phpmyadmin>`_.
.. seealso::
The packages are same as in :ref:`debian-package` please check the documentation
there for more details.
Gentoo
------
@ -86,13 +101,37 @@ which include phpMyAdmin together with a database and web server such as
You can find more of such options at `Wikipedia <https://en.wikipedia.org/wiki/List_of_AMP_packages>`_.
Installing from Git
+++++++++++++++++++
You can clone current phpMyAdmin source from
``https://github.com/phpmyadmin/phpmyadmin.git``:
.. code-block:: sh
git clone https://github.com/phpmyadmin/phpmyadmin.git
Additionally you need to install dependencies using `Composer tool`_:
.. code-block:: sh
composer update
If you do not intend to develop, you can skip installation of developer tools
by invoking:
.. code-block:: sh
composer update --no-dev
.. _composer:
Installing using Composer
+++++++++++++++++++++++++
You can install phpMyAdmin using `Composer <https://getcomposer.org/>`_,
however it's currently not available in the default
`Packagist <https://packagist.org/>`_ repository due to its technical
You can install phpMyAdmin using `Composer tool`_, however it's currently not
available in the default `Packagist`_ repository due to its technical
limitations.
The installation is possible by adding our own repository
@ -107,7 +146,7 @@ The installation is possible by adding our own repository
Installing using Docker
+++++++++++++++++++++++
phpMyAdmin comes with a Docker image, which you can easily deploy. You can
phpMyAdmin comes with a `Docker image`_, which you can easily deploy. You can
download it using:
.. code-block:: sh
@ -115,22 +154,49 @@ download it using:
docker pull phpmyadmin/phpmyadmin
The phpMyAdmin server will be executed on port 80. It supports several ways of
configuring the link to the database server, which you can manage using
environment variables:
configuring the link to the database server, either by Docker's link feature
by linking your database container to ``db`` for phpMyAdmin (by specifying
``--link your_db_host:db``) or by environment variables (in this case it's up
to you to setup networking in Docker to allow phpMyAdmin container to access
the database container over network).
.. _docker-vars:
Docker environment variables
----------------------------
You can configure several phpMyAdmin features using environment variables:
.. envvar:: PMA_ARBITRARY
Allows you to enter database server hostname on login form (see
:config:option:`$cfg['AllowArbitraryServer']`).
Allows you to enter database server hostname on login form.
.. seealso:: :config:option:`$cfg['AllowArbitraryServer']`
.. envvar:: PMA_HOST
Host name or IP address of the database server to use.
.. seealso:: :config:option:`$cfg['Servers'][$i]['host']`
.. envvar:: PMA_HOSTS
Comma separated host names or IP addresses of the database servers to use.
.. note:: Used only if :envvar:`PMA_HOST` is empty.
.. envvar:: PMA_VERBOSE
Verbose name the database server.
.. seealso:: :config:option:`$cfg['Servers'][$i]['verbose']`
.. envvar:: PMA_VERBOSES
Comma separated verbose name the database servers.
.. note:: Used only if :envvar:`PMA_VERBOSE` is empty.
.. envvar:: PMA_USER
User name to use for :ref:`auth_config`.
@ -148,6 +214,8 @@ environment variables:
The fully-qualified path (``https://pma.example.net/``) where the reverse
proxy makes phpMyAdmin available.
.. seealso:: :config:option:`$cfg['PmaAbsoluteUri']`
By default, :ref:`cookie` is used, but if :envvar:`PMA_USER` and
:envvar:`PMA_PASSWORD` are set, it is switched to :ref:`auth_config`.
@ -155,16 +223,33 @@ By default, :ref:`cookie` is used, but if :envvar:`PMA_USER` and
The credentials you need to login are stored in the MySQL server, in case
of Docker image there are various ways to set it (for example
:envvar:`MYSQL_ROOT_PASSWORD` when starting MySQL container). Please check
:samp:`MYSQL_ROOT_PASSWORD` when starting MySQL container). Please check
documentation for `MariaDB container <https://hub.docker.com/r/_/mariadb/>`_
or `MySQL container <https://hub.docker.com/r/_/mysql/>`_.
.. _docker-custom:
Customizing configuration
-------------------------
Additionally configuration can be tweaked by :file:`/etc/phpmyadmin/config.user.inc.php`. If
this file exists, it will be loaded after configuration generated from above
environment variables, so you can override any configuration variable. This
configuraiton can be added as a volume when invoking docker using
`-v /some/local/directory/config.user.inc.php:/etc/phpmyadmin/config.user.inc.php` parameters.
Note that the supplied configuration file is applied after :ref:`docker-vars`,
but you can override any of the values.
For example to change default behaviour of CSV export you can use following
configuration file:
.. code-block:: php
<?php
$cfg['Export']['csv_columns'] = true;
.. seealso::
See :ref:`config` for detailed description of configuration options.
@ -227,6 +312,80 @@ arbitrary server - allowing you to specify MySQL/MariaDB server on login page.
docker-compose up -d
Customizing configuration file using docker-compose
---------------------------------------------------
You can use external file to customize phpMyAdmin configuration and pass it
using volumes directive:
.. code-block:: yaml
phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: phpmyadmin
environment:
- PMA_ARBITRARY=1
restart: always
ports:
- 8080:80
volumes:
- /sessions
- ~/docker/phpmyadmin/config.user.inc.php:/etc/phpmyadmin/config.user.inc.php
.. seealso:: :ref:`docker-custom`
Running behind haproxy in a subdirectory
----------------------------------------
When you want to expose phpMyAdmin running in a Docker container in a
subdirectory, you need to rewrite the request path in the server proxying the
requests. For example using haproxy it can be done as:
.. code-block:: text
frontend http
bind *:80
option forwardfor
option http-server-close
### NETWORK restriction
acl LOCALNET src 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12
# /phpmyadmin
acl phpmyadmin path_dir /phpmyadmin
use_backend phpmyadmin if phpmyadmin LOCALNET
backend phpmyadmin
mode http
reqirep ^(GET|POST|HEAD)\ /phpmyadmin/(.*) \1\ /\2
# phpMyAdmin container IP
server localhost 172.30.21.21:80
You then should specify :envvar:`PMA_ABSOLUTE_URI` in the docker-compose
configuration:
.. code-block:: yaml
version: '2'
services:
phpmyadmin:
restart: always
image: phpmyadmin/phpmyadmin
container_name: phpmyadmin
hostname: phpmyadmin
domainname: example.com
ports:
- 8000:80
environment:
- PMA_HOSTS=172.26.36.7,172.26.36.8,172.26.36.9,172.26.36.10
- PMA_VERBOSES=production-db1,production-db2,dev-db1,dev-db2
- PMA_USER=root
- PMA_PASSWORD=
- PMA_ABSOLUTE_URI=http://example.com/phpmyadmin/
.. _quick_install:
Quick Install
@ -278,6 +437,8 @@ simple configuration may look like this:
$i=0;
$i++;
$cfg['Servers'][$i]['auth_type'] = 'cookie';
// if you insist on "root" having no password:
// $cfg['Servers'][$i]['AllowNoPassword'] = true; `
?>
Or, if you prefer to not be prompted every time you log in:
@ -294,6 +455,11 @@ Or, if you prefer to not be prompted every time you log in:
$cfg['Servers'][$i]['auth_type'] = 'config';
?>
.. warning::
Storing passwords in the configuration is insecure as anybody can then
manipulate with your database.
For a full explanation of possible configuration values, see the
:ref:`config` of this document.
@ -324,21 +490,38 @@ options which the setup script does not provide.
recommended, for example with HTTPAUTH in a :term:`.htaccess` file or switch to using
``auth_type`` cookie or http. See the :ref:`faqmultiuser`
for additional information, especially :ref:`faq4_4`.
#. Open the `main phpMyAdmin directory <index.php>`_ in your browser.
#. Open the main phpMyAdmin directory in your browser.
phpMyAdmin should now display a welcome screen and your databases, or
a login dialog if using :term:`HTTP` or
cookie authentication mode.
#. You should deny access to the ``./libraries`` and ``./setup/lib``
subfolders in your webserver configuration.
Such configuration prevents from possible
path exposure and cross side scripting vulnerabilities that might
happen to be found in that code. For the Apache webserver, this is
often accomplished with a :term:`.htaccess` file in those directories.
#. It is generally a good idea to protect a public phpMyAdmin installation
against access by robots as they usually can not do anything good
there. You can do this using ``robots.txt`` file in root of your
webserver or limit access by web server configuration, see
:ref:`faq1_42`.
.. _debian-setup:
Setup script on Debian, Ubuntu and derivatives
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Debian and Ubuntu have changed way how setup is enabled and disabled, in a way
that single command has to be executed for either of these.
To allow editing configuration invoke:
.. code-block:: sh
/usr/sbin/pma-configure
To block editing configuration invoke:
.. code-block:: sh
/usr/sbin/pma-secure
Setup script on openSUSE
~~~~~~~~~~~~~~~~~~~~~~~~
Some openSUSE releases do not include setup script in the package. In case you
want to generate configuration on these you can either download original
package from <https://www.phpmyadmin.net/> or use setup script on our demo
server: <https://demo.phpmyadmin.net/STABLE/setup/>.
.. _verify:
@ -374,9 +557,10 @@ Some additional downloads (for example themes) might be signed by Michal Čihař
and you can get more identification information from <https://keybase.io/nijel>.
You should verify that the signature matches
the archive you have downloaded. This way you can be sure that you are using
the same code that was released.
You should verify that the signature matches the archive you have downloaded.
This way you can be sure that you are using the same code that was released.
You should also verify the date of the signature to make sure that you
downloaded the latest version.
Each archive is accompanied with ``.asc`` files which contains the PGP signature
for it. Once you have both of them in the same folder, you can verify the signature:
@ -462,8 +646,13 @@ clear error regardless of the fact that the key is trusted or not:
phpMyAdmin configuration storage
++++++++++++++++++++++++++++++++
For a whole set of additional features (bookmarks, comments, :term:`SQL`-history,
tracking mechanism, :term:`PDF`-generation, column contents transformation,
.. versionchanged:: 3.4.0
Prior to phpMyAdmin 3.4.0 this was called Linked Tables Infrastructure, but
the name was changed due to extended scope of the storage.
For a whole set of additional features (:ref:`bookmarks`, comments, :term:`SQL`-history,
tracking mechanism, :term:`PDF`-generation, :ref:`transformations`, :ref:`relations`
etc.) you need to create a set of special tables. Those tables can be located
in your own database, or in a central database for a multi-user installation
(this database would then be accessed by the controluser, so no other user
@ -507,6 +696,8 @@ If you already had this infrastructure and:
:file:`sql/upgrade_tables_mysql_4_1_2+.sql`.
* upgraded to phpMyAdmin 4.3.0 or newer from 2.5.0 or newer (<= 4.2.x),
please use :file:`sql/upgrade_column_info_4_3_0+.sql`.
* upgraded to phpMyAdmin 4.7.0 or newer from 4.3.0 or newer,
please use :file:`sql/upgrade_tables_4_7_0+.sql`.
and then create new tables by importing :file:`sql/create_tables.sql`.
@ -543,7 +734,6 @@ Upgrading from an older version
This way you will not leave old no longer working code in the directory,
which can have severe security implications or can cause various breakages.
Simply copy :file:`config.inc.php` from your previous installation into
the newly unpacked one. Configuration files from old versions may
require some tweaking as some options have been changed or removed.
@ -555,6 +745,15 @@ You should **not** copy :file:`libraries/config.default.php` over
:file:`config.inc.php` because the default configuration file is version-
specific.
The complete upgrade can be performed in few simple steps:
1. Download the latest phpMyAdmin version from <https://www.phpmyadmin.net/downloads/>.
2. Rename existing phpMyAdmin folder (for example to ``phpmyadmin-old``).
3. Unpack freshly donwloaded phpMyAdmin to desired location (for example ``phpmyadmin``).
4. Copy :file:`config.inc.php`` from old location (``phpmyadmin-old``) to new one (``phpmyadmin``).
5. Test that everything works properly.
6. Remove backup of previous version (``phpmyadmin-old``).
If you have upgraded your MySQL server from a version previous to 4.1.2 to
version 5.x or newer and if you use the phpMyAdmin configuration storage, you
should run the :term:`SQL` script found in
@ -607,8 +806,18 @@ What the user may now do is controlled entirely by the MySQL user management
system. With HTTP or cookie authentication mode, you don't need to fill the
user/password fields inside the :config:option:`$cfg['Servers']`.
.. seealso::
:ref:`faq1_32`,
:ref:`faq1_35`,
:ref:`faq4_1`,
:ref:`faq4_2`,
:ref:`faq4_3`
.. index:: pair: HTTP; Authentication mode
.. _auth_http:
HTTP authentication mode
------------------------
@ -629,6 +838,13 @@ HTTP authentication mode
* See also :ref:`faq4_4` about not using the :term:`.htaccess` mechanism along with
':term:`HTTP`' authentication mode.
.. note::
There is no way to do proper logout in HTTP authentication, most browsers
will remember credentials until there is no different successful
authentication. Because of this this method has limitation that you can not
login with same user after logout.
.. index:: pair: Cookie; Authentication mode
.. _cookie:
@ -639,12 +855,12 @@ Cookie authentication mode
* Username and password are stored in cookies during the session and password
is deleted when it ends.
* With this mode, the user can truly log out of phpMyAdmin and log
back in with the same username.
back in with the same username (this is not possible with :ref:`auth_http`).
* If you want to allow users to enter any hostname to connect (rather than only
servers that are configured in :file:`config.inc.php`),
see the :config:option:`$cfg['AllowArbitraryServer']` directive.
* As mentioned in the :ref:`require` section, having the ``mcrypt`` extension will
speed up access considerably, but is not required.
* As mentioned in the :ref:`require` section, having the ``openssl`` extension
will speed up access considerably, but is not required.
.. index:: pair: Signon; Authentication mode
@ -657,7 +873,8 @@ Signon authentication mode
application to authenticate to phpMyAdmin to implement single signon
solution.
* The other application has to store login information into session
data (see :config:option:`$cfg['Servers'][$i]['SignonSession']`) or you
data (see :config:option:`$cfg['Servers'][$i]['SignonSession']` and
:config:option:`$cfg['Servers'][$i]['SignonCookieParams']`) or you
need to implement script to return the credentials (see
:config:option:`$cfg['Servers'][$i]['SignonScript']`).
* When no credentials are available, the user is being redirected to
@ -687,8 +904,10 @@ in :file:`examples/signon-script.php`:
.. seealso::
:config:option:`$cfg['Servers'][$i]['auth_type']`,
:config:option:`$cfg['Servers'][$i]['SignonSession']`,
:config:option:`$cfg['Servers'][$i]['SignonCookieParams']`,
:config:option:`$cfg['Servers'][$i]['SignonScript']`,
:config:option:`$cfg['Servers'][$i]['SignonURL']`
:config:option:`$cfg['Servers'][$i]['SignonURL']`,
:ref:`example-signon`
.. index:: pair: Config; Authentication mode
@ -716,22 +935,37 @@ Config authentication mode
of which are beyond the scope of this manual but easily searchable
with Google).
Securing your phpMyAdmin installation
+++++++++++++++++++++++++++++++++++++
The phpMyAdmin team tries hard to make the application secure, however there
are always ways to make your installation more secure:
* Follow our `Security announcements <https://www.phpmyadmin.net/security/>`_ and upgrade
phpMyAdmin whenever new vulnerability is published.
* Serve phpMyAdmin on HTTPS only. Preferably, you should use HSTS as well, so that
you're protected from protocol downgrade attacks.
* Ensure your PHP setup follows recommendations for production sites, for example
`display_errors <https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors>`_
should be disabled.
* Remove the ``test`` directory from phpMyAdmin, unless you are developing and need test suite.
* Remove the ``setup`` directory from phpMyAdmin, you will probably not
use it after the initial setup.
* Properly choose an authentication method - :ref:`cookie`
is probably the best choice for shared hosting.
* Deny access to auxiliary files in :file:`./libraries/` or
:file:`./templates/` subfolders in your webserver configuration.
Such configuration prevents from possible path exposure and cross side
scripting vulnerabilities that might happen to be found in that code. For the
Apache webserver, this is often accomplished with a :term:`.htaccess` file in
those directories.
* It is generally a good idea to protect a public phpMyAdmin installation
against access by robots as they usually can not do anything good there. You
can do this using ``robots.txt`` file in root of your webserver or limit
access by web server configuration, see :ref:`faq1_42`.
* In case you don't want all MySQL users to be able to access
phpMyAdmin, you can use :config:option:`$cfg['Servers'][$i]['AllowDeny']['rules']` to limit them.
phpMyAdmin, you can use :config:option:`$cfg['Servers'][$i]['AllowDeny']['rules']` to limit them
or :config:option:`$cfg['Servers'][$i]['AllowRoot']` to deny root user access.
* Consider hiding phpMyAdmin behind an authentication proxy, so that
users need to authenticate prior to providing MySQL credentials
to phpMyAdmin. You can achieve this by configuring your web server to request
@ -754,6 +988,9 @@ 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). 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.
Known issues
++++++++++++
@ -772,3 +1009,8 @@ Trouble logging back in after logging out using 'http' authentication
When using the 'http' ``auth_type``, it can be impossible to log back in (when the logout comes
manually or after a period of inactivity). `Issue 11898 <https://github.com/phpmyadmin/phpmyadmin/issues/11898>`_.
.. _Composer tool: https://getcomposer.org/
.. _Packagist: https://packagist.org/
.. _Docker image: https://hub.docker.com/r/phpmyadmin/phpmyadmin/

View File

@ -3,6 +3,11 @@
Transformations
===============
.. note::
You need to have configured the :ref:`linked-tables` for using transformations
feature.
.. _transformationsintro:
Introduction
@ -29,7 +34,7 @@ options, you can consult your *<www.your-host.com>/<your-install-
dir>/transformation\_overview.php* installation.
For a tutorial on how to effectively use transformations, see our
`Link section <https://www.phpmyadmin.net/home_page/docs.php>`_ on the
`Link section <https://www.phpmyadmin.net/docs/>`_ on the
official phpMyAdmin homepage.
.. _transformationshowto:
@ -128,9 +133,9 @@ The applyTransformation() method always gets passed three variables:
function as an array.
#. **$meta** - Contains an object with information about your column. The
data is drawn from the output of the `mysql\_fetch\_field()
<https://www.php.net/mysql_fetch_field>`_ function. This means, all
<https://secure.php.net/mysql_fetch_field>`_ function. This means, all
object properties described on the `manual page
<https://www.php.net/mysql_fetch_field>`_ are available in this
<https://secure.php.net/mysql_fetch_field>`_ are available in this
variable and can be used to transform a column accordingly to
unsigned/zerofill/not\_null/... properties. The $meta->mimetype
variable contains the original MIME-type of the column (i.e.

View File

@ -5,6 +5,9 @@ User Guide
:maxdepth: 2
transformations
bookmarks
privileges
other
relations
charts
import_export
other

View File

@ -27,9 +27,6 @@ Currently known list of external libraries:
js/jquery
jQuery js framework and various jQuery based libraries.
libraries/php-gettext
php-gettext library
libraries/tcpdf
tcpdf library, stripped down of not needed files
libraries/phpseclib
portions of phpseclib library
vendor/
The download kit includes various Composer packages as
dependencies.

View File

@ -5,6 +5,7 @@
*
* @package PhpMyAdmin
*/
use PMA\libraries\Response;
require_once 'libraries/common.inc.php';
require_once 'libraries/error_report.lib.php';
require_once 'libraries/user_preferences.lib.php';
@ -15,7 +16,7 @@ if (!isset($_REQUEST['exception_type'])
die('Oops, something went wrong!!');
}
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
if (isset($_REQUEST['send_error_report'])
&& ($_REQUEST['send_error_report'] == true
@ -35,7 +36,6 @@ if (isset($_REQUEST['send_error_report'])
) {
$_SESSION['error_subm_count'] = 0;
$_SESSION['prev_errors'] = '';
$response = PMA\libraries\Response::getInstance();
$response->addJSON('_stopErrorReportLoop', '1');
} else {
$_SESSION['prev_error_subm_time'] = time();

View File

@ -22,7 +22,6 @@ foreach ($hosts as $host) {
$cfg['Servers'][$i]['host'] = $host;
$cfg['Servers'][$i]['port'] = '';
$cfg['Servers'][$i]['socket'] = '';
$cfg['Servers'][$i]['connect_type'] = 'tcp';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['controluser'] = 'pma';
$cfg['Servers'][$i]['controlpass'] = 'pmapass';

View File

@ -89,7 +89,7 @@ $base .= '://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'];
$realm = $base . '/';
$returnTo = $base . dirname($_SERVER['PHP_SELF']);
if ($returnTo[mb_strlen($returnTo) - 1] != '/') {
if ($returnTo[strlen($returnTo) - 1] != '/') {
$returnTo .= '/';
}
$returnTo .= 'openid.php';

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* "Echo" service to allow force downloading of exported charts (png or svg)
* and server status monitor settings
*
* @package PhpMyAdmin
*/
define('PMA_MINIMUM_COMMON', true);
require_once 'libraries/common.inc.php';
if (isset($_REQUEST['monitorconfig'])) {
/* For monitor chart config export */
PMA_downloadHeader('monitor.cfg', 'application/json; charset=UTF-8');
header('X-Content-Type-Options: nosniff');
echo urldecode($_REQUEST['monitorconfig']);
} else if (isset($_REQUEST['import'])) {
/* For monitor chart config import */
header('Content-Type: application/json; charset=UTF-8');
header('X-Content-Type-Options: nosniff');
if (!file_exists($_FILES['file']['tmp_name'])) {
exit();
}
echo file_get_contents($_FILES['file']['tmp_name']);
}

View File

@ -5,8 +5,10 @@
*
* @package PhpMyAdmin
*/
use PMA\libraries\Response;
use PMA\libraries\gis\GISFactory;
use PMA\libraries\gis\GISVisualization;
use PMA\libraries\URL;
/**
* Escapes special characters if the variable is set.
@ -100,7 +102,7 @@ if (isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) {
'visualization' => $visualization,
'openLayers' => $open_layers,
);
$response = PMA\libraries\Response::getInstance();
$response = Response::getInstance();
$response->addJSON($extra_data);
exit;
}
@ -127,7 +129,7 @@ if (isset($_REQUEST['input_name'])) {
echo '<input type="hidden" name="input_name" value="'
, htmlspecialchars($_REQUEST['input_name']) , '" />';
}
echo PMA_URL_getHiddenInputs();
echo URL::getHiddenInputs();
echo '<!-- Visualization section -->';
echo '<div id="placeholder" style="width:450px;height:300px;'
@ -426,5 +428,5 @@ echo '</div>';
echo '</div>';
echo '</form>';
PMA\libraries\Response::getInstance()->addJSON('gis_editor', ob_get_contents());
Response::getInstance()->addJSON('gis_editor', ob_get_contents());
ob_end_clean();

View File

@ -5,7 +5,12 @@
*
* @package PhpMyAdmin
*/
use PMA\libraries\Response;
use PMA\libraries\Encoding;
use PMA\libraries\plugins\ImportPlugin;
use PMA\libraries\File;
use PMA\libraries\URL;
use PMA\libraries\Bookmark;
/* Enable LOAD DATA LOCAL INFILE for LDI plugin */
if (isset($_POST['format']) && $_POST['format'] == 'ldi') {
@ -17,7 +22,6 @@ if (isset($_POST['format']) && $_POST['format'] == 'ldi') {
*/
require_once 'libraries/common.inc.php';
require_once 'libraries/sql.lib.php';
require_once 'libraries/bookmark.lib.php';
//require_once 'libraries/display_import_functions.lib.php';
if (isset($_REQUEST['show_as_php'])) {
@ -33,9 +37,10 @@ if (isset($_REQUEST['simulate_dml'])) {
exit;
}
$response = Response::getInstance();
// If it's a refresh console bookmarks request
if (isset($_REQUEST['console_bookmark_refresh'])) {
$response = PMA\libraries\Response::getInstance();
$response->addJSON(
'console_message_bookmark', PMA\libraries\Console::getBookmarkContent()
);
@ -43,11 +48,10 @@ if (isset($_REQUEST['console_bookmark_refresh'])) {
}
// If it's a console bookmark add request
if (isset($_REQUEST['console_bookmark_add'])) {
$response = PMA\libraries\Response::getInstance();
if (isset($_REQUEST['label']) && isset($_REQUEST['db'])
&& isset($_REQUEST['bookmark_query']) && isset($_REQUEST['shared'])
) {
$cfgBookmark = PMA_Bookmark_getParams();
$cfgBookmark = Bookmark::getParams();
$bookmarkFields = array(
'bkm_database' => $_REQUEST['db'],
'bkm_user' => $cfgBookmark['user'],
@ -55,7 +59,8 @@ if (isset($_REQUEST['console_bookmark_add'])) {
'bkm_label' => $_REQUEST['label']
);
$isShared = ($_REQUEST['shared'] == 'true' ? true : false);
if (PMA_Bookmark_save($bookmarkFields, $isShared)) {
$bookmark = Bookmark::createBookmark($bookmarkFields, $isShared);
if ($bookmark !== false && $bookmark->save()) {
$response->addJSON('message', __('Succeeded'));
$response->addJSON('data', $bookmarkFields);
$response->addJSON('isShared', $isShared);
@ -86,7 +91,6 @@ $post_params = array(
'local_import_file'
);
// TODO: adapt full list of allowed parameters, as in export.php
foreach ($post_params as $one_post_param) {
if (isset($_POST[$one_post_param])) {
$GLOBALS[$one_post_param] = $_POST[$one_post_param];
@ -113,7 +117,8 @@ if (! empty($sql_query)) {
// apply values for parameters
if (! empty($_REQUEST['parameterized'])
&& ! empty($_REQUEST['parameters'])
&& is_array($_REQUEST['parameters'])) {
&& is_array($_REQUEST['parameters'])
) {
$parameters = $_REQUEST['parameters'];
foreach ($parameters as $parameter => $replacement) {
$quoted = preg_quote($parameter, '/');
@ -199,7 +204,6 @@ if ($_POST == array() && $_GET == array()) {
$_SESSION['Import_message']['message'] = $message->getDisplay();
$_SESSION['Import_message']['go_back_url'] = $GLOBALS['goto'];
$response = PMA\libraries\Response::getInstance();
$response->setRequestStatus(false);
$response->addJSON('message', $message);
@ -208,7 +212,6 @@ if ($_POST == array() && $_GET == array()) {
// Add console message id to response output
if (isset($_POST['console_message_id'])) {
$response = PMA\libraries\Response::getInstance();
$response->addJSON('console_message_id', $_POST['console_message_id']);
}
@ -250,7 +253,7 @@ $format = PMA_securePath($format);
// Create error and goto url
if ($import_type == 'table') {
$err_url = 'tbl_import.php' . PMA_URL_getCommon(
$err_url = 'tbl_import.php' . URL::getCommon(
array(
'db' => $db, 'table' => $table
)
@ -258,29 +261,29 @@ if ($import_type == 'table') {
$_SESSION['Import_message']['go_back_url'] = $err_url;
$goto = 'tbl_import.php';
} elseif ($import_type == 'database') {
$err_url = 'db_import.php' . PMA_URL_getCommon(array('db' => $db));
$err_url = 'db_import.php' . URL::getCommon(array('db' => $db));
$_SESSION['Import_message']['go_back_url'] = $err_url;
$goto = 'db_import.php';
} elseif ($import_type == 'server') {
$err_url = 'server_import.php' . PMA_URL_getCommon();
$err_url = 'server_import.php' . URL::getCommon();
$_SESSION['Import_message']['go_back_url'] = $err_url;
$goto = 'server_import.php';
} else {
if (empty($goto) || !preg_match('@^(server|db|tbl)(_[a-z]*)*\.php$@i', $goto)) {
if (mb_strlen($table) && mb_strlen($db)) {
if (strlen($table) > 0 && strlen($db) > 0) {
$goto = 'tbl_structure.php';
} elseif (mb_strlen($db)) {
} elseif (strlen($db) > 0) {
$goto = 'db_structure.php';
} else {
$goto = 'server_sql.php';
}
}
if (mb_strlen($table) && mb_strlen($db)) {
$common = PMA_URL_getCommon(array('db' => $db, 'table' => $table));
} elseif (mb_strlen($db)) {
$common = PMA_URL_getCommon(array('db' => $db));
if (strlen($table) > 0 && strlen($db) > 0) {
$common = URL::getCommon(array('db' => $db, 'table' => $table));
} elseif (strlen($db) > 0) {
$common = URL::getCommon(array('db' => $db));
} else {
$common = PMA_URL_getCommon();
$common = URL::getCommon();
}
$err_url = $goto . $common
. (preg_match('@^tbl_[a-z]*\.php$@', $goto)
@ -295,7 +298,7 @@ if (basename($_SERVER['SCRIPT_NAME']) === 'import.php') {
}
if (mb_strlen($db)) {
if (strlen($db) > 0) {
$GLOBALS['dbi']->selectDb($db);
}
@ -327,23 +330,27 @@ $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($_REQUEST['id_bookmark'])) {
$id_bookmark = (int)$_REQUEST['id_bookmark'];
include_once 'libraries/bookmark.lib.php';
switch ($_REQUEST['action_bookmark']) {
case 0: // bookmarked query that have to be run
$import_text = PMA_Bookmark_get(
$bookmark = Bookmark::get(
$db,
$id_bookmark,
'id',
isset($_REQUEST['action_bookmark_all'])
);
if (! empty($_REQUEST['bookmark_variable'])) {
$import_text = PMA_Bookmark_applyVariables(
$import_text
$import_text = $bookmark->applyVariables(
$_REQUEST['bookmark_variable']
);
} else {
$import_text = $bookmark->getQuery();
}
// refresh navigation and main panels
@ -365,10 +372,10 @@ if (! empty($_REQUEST['id_bookmark'])) {
}
break;
case 1: // bookmarked query that have to be displayed
$import_text = PMA_Bookmark_get($db, $id_bookmark);
if ($GLOBALS['is_ajax_request'] == true) {
$bookmark = Bookmark::get($db, $id_bookmark);
$import_text = $bookmark->getQuery();
if ($response->isAjax()) {
$message = PMA\libraries\Message::success(__('Showing bookmark'));
$response = PMA\libraries\Response::getInstance();
$response->setRequestStatus($message->isSuccess());
$response->addJSON('message', $message);
$response->addJSON('sql_query', $import_text);
@ -379,22 +386,24 @@ if (! empty($_REQUEST['id_bookmark'])) {
}
break;
case 2: // bookmarked query that have to be deleted
$import_text = PMA_Bookmark_get($db, $id_bookmark);
PMA_Bookmark_delete($id_bookmark);
if ($GLOBALS['is_ajax_request'] == true) {
$message = PMA\libraries\Message::success(
__('The bookmark has been deleted.')
);
$response = PMA\libraries\Response::getInstance();
$response->setRequestStatus($message->isSuccess());
$response->addJSON('message', $message);
$response->addJSON('action_bookmark', $_REQUEST['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
$bookmark = Bookmark::get($db, $id_bookmark);
if (! empty($bookmark)) {
$bookmark->delete();
if ($response->isAjax()) {
$message = PMA\libraries\Message::success(
__('The bookmark has been deleted.')
);
$response->setRequestStatus($message->isSuccess());
$response->addJSON('message', $message);
$response->addJSON('action_bookmark', $_REQUEST['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
@ -459,132 +468,18 @@ if (! empty($local_import_file) && ! empty($cfg['UploadDir'])) {
// Do we have file to import?
if ($import_file != 'none' && ! $error) {
// work around open_basedir and other limitations
$open_basedir = @ini_get('open_basedir');
// If we are on a server with open_basedir, we must move the file
// before opening it.
if (! empty($open_basedir)) {
$tmp_subdir = ini_get('upload_tmp_dir');
if (empty($tmp_subdir)) {
$tmp_subdir = sys_get_temp_dir();
}
$tmp_subdir = rtrim($tmp_subdir, DIRECTORY_SEPARATOR);
if (@is_writable($tmp_subdir)) {
$import_file_new = $tmp_subdir . DIRECTORY_SEPARATOR
. basename($import_file) . uniqid();
if (move_uploaded_file($import_file, $import_file_new)) {
$import_file = $import_file_new;
$file_to_unlink = $import_file_new;
}
$size = filesize($import_file);
} else {
// If the php.ini is misconfigured (eg. there is no /tmp access defined
// with open_basedir), $tmp_subdir won't be writable and the user gets
// a 'File could not be read!' error (at PMA_detectCompression), which
// is not too meaningful. Show a meaningful error message to the user
// instead.
$message = PMA\libraries\Message::error(
__(
'Uploaded file cannot be moved, because the server has ' .
'open_basedir enabled without access to the %s directory ' .
'(for temporary files).'
)
);
$message->addParam($tmp_subdir);
PMA_stopImport($message);
}
}
/**
* Handle file compression
* @todo duplicate code exists in File.php
*/
$compression = PMA_detectCompression($import_file);
if ($compression === false) {
$message = PMA\libraries\Message::error(__('File could not be read!'));
PMA_stopImport($message); //Contains an 'exit'
$import_handle = new File($import_file);
$import_handle->checkUploadedFile();
if ($import_handle->isError()) {
PMA_stopImport($import_handle->getError());
}
switch ($compression) {
case 'application/bzip2':
if ($cfg['BZipDump'] && @function_exists('bzopen')) {
$import_handle = @bzopen($import_file, 'r');
} else {
$message = PMA\libraries\Message::error(
__(
'You attempted to load file with unsupported compression ' .
'(%s). Either support for it is not implemented or disabled ' .
'by your configuration.'
)
);
$message->addParam($compression);
PMA_stopImport($message);
}
break;
case 'application/gzip':
if ($cfg['GZipDump'] && @function_exists('gzopen')) {
$import_handle = @gzopen($import_file, 'r');
} else {
$message = PMA\libraries\Message::error(
__(
'You attempted to load file with unsupported compression ' .
'(%s). Either support for it is not implemented or disabled ' .
'by your configuration.'
)
);
$message->addParam($compression);
PMA_stopImport($message);
}
break;
case 'application/zip':
if ($cfg['ZipDump'] && @function_exists('zip_open')) {
/**
* Load interface for zip extension.
*/
include_once 'libraries/zip_extension.lib.php';
$zipResult = PMA_getZipContents($import_file);
if (! empty($zipResult['error'])) {
$message = PMA\libraries\Message::rawError($zipResult['error']);
PMA_stopImport($message);
} else {
$import_text = $zipResult['data'];
}
} else {
$message = PMA\libraries\Message::error(
__(
'You attempted to load file with unsupported compression ' .
'(%s). Either support for it is not implemented or disabled ' .
'by your configuration.'
)
);
$message->addParam($compression);
PMA_stopImport($message);
}
break;
case 'none':
$import_handle = @fopen($import_file, 'r');
break;
default:
$message = PMA\libraries\Message::error(
__(
'You attempted to load file with unsupported compression (%s). ' .
'Either support for it is not implemented or disabled by your ' .
'configuration.'
)
);
$message->addParam($compression);
PMA_stopImport($message);
// the previous function exits
}
// use isset() because zip compression type does not use a handle
if (! $error && isset($import_handle) && $import_handle === false) {
$message = PMA\libraries\Message::error(__('File could not be read!'));
PMA_stopImport($message);
$import_handle->setDecompressContent(true);
$import_handle->open();
if ($import_handle->isError()) {
PMA_stopImport($import_handle->getError());
}
} elseif (! $error) {
if (! isset($import_text) || empty($import_text)) {
@ -603,7 +498,7 @@ if ($import_file != 'none' && ! $error) {
//$_SESSION['Import_message'] = $message->getDisplay();
// Convert the file's charset if necessary
if ($GLOBALS['PMA_recoding_engine'] != PMA_CHARSET_NONE && isset($charset_of_file)) {
if (Encoding::isSupported() && isset($charset_of_file)) {
if ($charset_of_file != 'utf-8') {
$charset_conversion = true;
}
@ -658,8 +553,8 @@ if (! $error) {
}
}
if (! empty($import_handle)) {
fclose($import_handle);
if (isset($import_handle)) {
$import_handle->close();
}
// Cleanup temporary file
@ -703,14 +598,12 @@ if (! empty($id_bookmark) && $_REQUEST['action_bookmark'] == 2) {
$message->addParam($executed_queries);
if ($import_notice) {
$message->addString($import_notice);
$message->addHtml($import_notice);
}
if (! empty($local_import_file)) {
$message->addString('(' . htmlspecialchars($local_import_file) . ')');
$message->addText('(' . $local_import_file . ')');
} else {
$message->addString(
'(' . htmlspecialchars($_FILES['import_file']['name']) . ')'
);
$message->addText('(' . $_FILES['import_file']['name'] . ')');
}
}
}
@ -729,11 +622,11 @@ if ($timeout_passed) {
. ' please %sresubmit the same file%s and import will resume.'
)
);
$message->addParam('<a href="' . $importUrl . '">', false);
$message->addParam('</a>', false);
$message->addParamHtml('<a href="' . $importUrl . '">');
$message->addParamHtml('</a>');
if ($offset == 0 || (isset($original_skip) && $original_skip == $offset)) {
$message->addString(
$message->addText(
__(
'However on last run no data has been parsed,'
. ' this usually means phpMyAdmin won\'t be able to'
@ -844,7 +737,7 @@ if ($go_sql) {
// 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 = PMA_Bookmark_getParams();
$cfgBookmark = Bookmark::getParams();
PMA_storeTheQueryAsBookmark(
$db, $cfgBookmark['user'],
$_REQUEST['sql_query'], $_POST['bkm_label'],
@ -852,7 +745,6 @@ if ($go_sql) {
);
}
$response = PMA\libraries\Response::getInstance();
$response->addJSON('ajax_reload', $ajax_reload);
$response->addHTML($html_output);
exit();
@ -860,7 +752,7 @@ if ($go_sql) {
} else if ($result) {
// Save a Bookmark with more than one queries (if Bookmark label given).
if (! empty($_POST['bkm_label']) && ! empty($import_text)) {
$cfgBookmark = PMA_Bookmark_getParams();
$cfgBookmark = Bookmark::getParams();
PMA_storeTheQueryAsBookmark(
$db, $cfgBookmark['user'],
$_REQUEST['sql_query'], $_POST['bkm_label'],
@ -868,7 +760,6 @@ if ($go_sql) {
);
}
$response = PMA\libraries\Response::getInstance();
$response->setRequestStatus(true);
$response->addJSON('message', PMA\libraries\Message::success($msg));
$response->addJSON(
@ -876,7 +767,6 @@ if ($go_sql) {
PMA\libraries\Util::getMessage($msg, $sql_query, 'success')
);
} else if ($result == false) {
$response = PMA\libraries\Response::getInstance();
$response->setRequestStatus(false);
$response->addJSON('message', PMA\libraries\Message::error($msg));
} else {

View File

@ -24,9 +24,7 @@
*/
/*
if (version_compare(PHP_VERSION, '5.4.0', '>=')
&& ini_get('session.upload_progress.enabled')
) {
if (ini_get('session.upload_progress.enabled')) {
$sessionupload = array();
define('UPLOAD_PREFIX', ini_get('session.upload_progress.prefix'));
@ -34,7 +32,7 @@ if (version_compare(PHP_VERSION, '5.4.0', '>=')
session_start();
foreach ($_SESSION as $key => $value) {
// only copy session-prefixed data
if (mb_substr($key, 0, mb_strlen(UPLOAD_PREFIX))
if (substr($key, 0, strlen(UPLOAD_PREFIX))
== UPLOAD_PREFIX) {
$sessionupload[$key] = $value;
}
@ -69,7 +67,7 @@ if (defined('SESSIONUPLOAD')) {
// remove session upload data that are not set anymore
foreach ($_SESSION as $key => $value) {
if (mb_substr($key, 0, mb_strlen(UPLOAD_PREFIX))
if (substr($key, 0, strlen(UPLOAD_PREFIX))
== UPLOAD_PREFIX
&& ! isset($sessionupload[$key])
) {

View File

@ -5,7 +5,13 @@
*
* @package PhpMyAdmin
*/
use PMA\libraries\Response;
use PMA\libraries\RecentFavoriteTable;
use PMA\libraries\URL;
use PMA\libraries\Sanitize;
use PMA\libraries\Charsets;
use PMA\libraries\ThemeManager;
use PMA\libraries\LanguageManager;
/**
* Gets some core libraries and displays a top message if required
@ -74,11 +80,11 @@ if (! empty($_REQUEST['db'])) {
exit;
}
$response = Response::getInstance();
/**
* Check if it is an ajax request to reload the recent tables list.
*/
if ($GLOBALS['is_ajax_request'] && ! empty($_REQUEST['recent_table'])) {
$response = PMA\libraries\Response::getInstance();
if ($response->isAjax() && ! empty($_REQUEST['recent_table'])) {
$response->addJSON(
'list',
RecentFavoriteTable::getInstance('recent')->getHtmlList()
@ -87,7 +93,7 @@ if ($GLOBALS['is_ajax_request'] && ! empty($_REQUEST['recent_table'])) {
}
if ($GLOBALS['PMA_Config']->isGitRevision()) {
if (isset($_REQUEST['git_revision']) && $GLOBALS['is_ajax_request'] == true) {
if (isset($_REQUEST['git_revision']) && $response->isAjax()) {
PMA_printGitRevision();
exit;
}
@ -105,7 +111,7 @@ if (! empty($message)) {
unset($message);
}
$common_url_query = PMA_URL_getCommon();
$common_url_query = URL::getCommon();
$mysql_cur_user_and_host = '';
// when $server > 0, a server has been chosen so we can display
@ -202,7 +208,7 @@ if ($server > 0 || count($cfg['Servers']) > 1
} // end if
echo ' <li id="li_select_mysql_collation" class="no_bullets" >';
echo ' <form method="post" action="index.php">' , "\n"
. PMA_URL_getHiddenInputs(null, null, 4, 'collation_connection')
. URL::getHiddenInputs(null, null, 4, 'collation_connection')
. ' <label for="select_collation_connection">' . "\n"
. ' ' . PMA\libraries\Util::getImage('s_asci.png')
. "&nbsp;" . __('Server connection collation') . "\n"
@ -211,8 +217,7 @@ if ($server > 0 || count($cfg['Servers']) > 1
. ': ' . "\n"
. ' </label>' . "\n"
. PMA_generateCharsetDropdownBox(
PMA_CSDROPDOWN_COLLATION,
. Charsets::getCollationDropdownBox(
'collation_connection',
'select_collation_connection',
$collation_connection,
@ -231,11 +236,12 @@ echo '<h2>' , __('Appearance settings') , '</h2>';
echo ' <ul>';
// Displays language selection combo
if (empty($cfg['Lang'])) {
$language_manager = LanguageManager::getInstance();
if (empty($cfg['Lang']) && $language_manager->hasChoice()) {
echo '<li id="li_select_lang" class="no_bullets">';
include_once 'libraries/display_select_lang.lib.php';
echo PMA\libraries\Util::getImage('s_lang.png') , " "
, PMA_getLanguageSelectorHtml();
, $language_manager->getSelectorDisplay();
echo '</li>';
}
@ -244,7 +250,7 @@ if (empty($cfg['Lang'])) {
if ($GLOBALS['cfg']['ThemeManager']) {
echo '<li id="li_select_theme" class="no_bullets">';
echo PMA\libraries\Util::getImage('s_theme.png') , " "
, $_SESSION['PMA_Theme_Manager']->getHtmlSelectBox();
, ThemeManager::getInstance()->getHtmlSelectBox();
echo '</li>';
}
echo '<li id="li_select_fontsize">';
@ -309,9 +315,10 @@ if ($server > 0 && $GLOBALS['cfg']['ShowServerInfo']) {
echo ' <li id="li_select_mysql_charset">';
echo ' ' , __('Server charset:') , ' '
. ' <span lang="en" dir="ltr">';
echo ' ' , $mysql_charsets_descriptions[$mysql_charset_map['utf-8']];
echo ' (' , $mysql_charset_map['utf-8'] , ')'
. ' </span>'
$unicode = Charsets::$mysql_charset_map['utf-8'];
$charsets = Charsets::getMySQLCharsetsDescriptions();
echo ' ' , $charsets[$unicode], ' (' . $unicode, ')';
echo ' </span>'
. ' </li>'
. ' </ul>'
. ' </div>';
@ -419,14 +426,14 @@ PMA_printListItem(
PMA_printListItem(
__('List of changes'),
'li_pma_changes',
'changelog.php' . PMA_URL_getCommon(),
'changelog.php' . URL::getCommon(),
null,
'_blank'
);
PMA_printListItem(
__('License'),
'li_pma_license',
'license.php' . PMA_URL_getCommon(),
'license.php' . URL::getCommon(),
null,
'_blank'
);
@ -474,7 +481,7 @@ if ($cfg['LoginCookieValidityDisableWarning'] == false) {
if ($gc_time < $GLOBALS['cfg']['LoginCookieValidity'] ) {
trigger_error(
__(
'Your PHP parameter [a@https://php.net/manual/en/session.' .
'Your PHP parameter [a@https://secure.php.net/manual/en/session.' .
'configuration.php#ini.session.gc-maxlifetime@_blank]session.' .
'gc_maxlifetime[/a] is lower than cookie validity configured ' .
'in phpMyAdmin, because of this, your login might expire sooner ' .
@ -557,12 +564,8 @@ if ($server > 0) {
);
}
$msg = PMA\libraries\Message::notice($msg_text);
$msg->addParam(
'<a href="./chk_rel.php'
. $common_url_query . '">',
false
);
$msg->addParam('</a>', false);
$msg->addParamHtml('<a href="./chk_rel.php' . $common_url_query . '">');
$msg->addParamHtml('</a>');
/* Show error if user has configured something, notice elsewhere */
if (!empty($cfg['Servers'][$server]['pmadb'])) {
$msg->isError(true);
@ -571,48 +574,6 @@ if ($server > 0) {
} // end if
}
/**
* Warning about different MySQL library and server version
* (a difference on the third digit does not count).
* If someday there is a constant that we can check about mysqlnd,
* we can use it instead of strpos().
* If no default server is set, $GLOBALS['dbi'] is not defined yet.
* We also do not warn if MariaDB is detected, as it has its own version
* numbering.
*/
if (isset($GLOBALS['dbi'])
&& $cfg['ServerLibraryDifference_DisableWarning'] == false
) {
$_client_info = $GLOBALS['dbi']->getClientInfo();
if ($server > 0
&& mb_strpos($_client_info, 'mysqlnd') === false
&& mb_strpos(PMA_MYSQL_STR_VERSION, 'MariaDB') === false
&& substr(PMA_MYSQL_CLIENT_API, 0, 3) != substr(
PMA_MYSQL_INT_VERSION, 0, 3
)
) {
trigger_error(
PMA_sanitize(
sprintf(
__(
'Your PHP MySQL library version %s differs from your ' .
'MySQL server version %s. This may cause unpredictable ' .
'behavior.'
),
$_client_info,
substr(
PMA_MYSQL_STR_VERSION,
0,
strpos(PMA_MYSQL_STR_VERSION . '-', '-')
)
)
),
E_USER_NOTICE
);
}
unset($_client_info);
}
/**
* Warning about Suhosin only if its simulation mode is not enabled
*/

View File

@ -1,67 +0,0 @@
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* phpMyAdmin's BigInts library
*/
/**
* @var BigInts object to handle big integers (in string)
* as JS can handle upto 53 bits of precision only.
*/
var BigInts = {
/**
* Compares two integer strings
*
* @param int1 the string representation of 1st integer
* @param int2 the string representation of 2nd integer
*
* @return int 0 if equal, < 0 if int1 < int2, else > 0
*/
compare: function(int1, int2) {
// trim integers
int1 = int1.trim();
int2 = int2.trim();
// length of integer strings
var len1 = int1.length;
var len2 = int2.length;
// integer is -ve or not
var isNeg1 = (int1[0] === '-');
var isNeg2 = (int2[0] === '-');
// Sign of int1 != int2 then no actual comparison
// is needed we can return result directly
if (isNeg1 !== isNeg2) {
return (isNeg1 === true ? -1 : 1);
}
// replace - sign with 0
int1[0] = isNeg1 ? '0' : int1[0];
int2[0] = isNeg2 ? '0' : int2[0];
// pad integers with 0 to make them
// equal length
int1 = BigInts.lpad(int1, len2);
int2 = BigInts.lpad(int2, len1);
// Now they are good to compare as strings
if (int1 !== int2) {
return (int1 < int2 ? -1 : 1);
}
return 0;
},
/**
* Adds leading zeros to a integer given a total length
*
* @param int the string representation of the integer
* @param total the total length required
*
* @return int the integer of length given with added leading
* zeros if necessary
*/
lpad: function(int, total){
var len = int.length;
var pad = '';
while(len < total) {
pad += '0';
len++;
}
return (pad + int);
}
};

View File

@ -1,4 +1,4 @@
Copyright (C) 2015 by Marijn Haverbeke <marijnh@gmail.com> and others
Copyright (C) 2016 by Marijn Haverbeke <marijnh@gmail.com> and others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -25,8 +25,6 @@
margin: 0;
padding: 0 4px;
border-radius: 2px;
max-width: 19em;
overflow: hidden;
white-space: pre;
color: black;
cursor: pointer;

View File

@ -25,8 +25,18 @@
};
CodeMirror.defineExtension("showHint", function(options) {
// We want a single cursor position.
if (this.listSelections().length > 1 || this.somethingSelected()) return;
options = parseOptions(this, this.getCursor("start"), options);
var selections = this.listSelections()
if (selections.length > 1) return;
// By default, don't allow completion when something is selected.
// A hint function can have a `supportsSelection` property to
// indicate that it can handle selections.
if (this.somethingSelected()) {
if (!options.hint.supportsSelection) return;
// Don't try with cross-line selections
for (var i = 0; i < selections.length; i++)
if (selections[i].head.line != selections[i].anchor.line) return;
}
if (this.state.completionActive) this.state.completionActive.close();
var completion = this.state.completionActive = new Completion(this, options);
@ -38,12 +48,12 @@
function Completion(cm, options) {
this.cm = cm;
this.options = this.buildOptions(options);
this.options = options;
this.widget = null;
this.debounce = 0;
this.tick = 0;
this.startPos = this.cm.getCursor();
this.startLen = this.cm.getLine(this.startPos.line).length;
this.startPos = this.cm.getCursor("start");
this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
var self = this;
cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
@ -98,23 +108,22 @@
},
update: function(first) {
if (this.tick == null) return;
if (this.data) CodeMirror.signal(this.data, "update");
if (!this.options.hint.async) {
this.finishUpdate(this.options.hint(this.cm, this.options), first);
} else {
var myTick = ++this.tick, self = this;
this.options.hint(this.cm, function(data) {
if (self.tick == myTick) self.finishUpdate(data, first);
}, this.options);
}
if (this.tick == null) return
var self = this, myTick = ++this.tick
fetchHints(this.options.hint, this.cm, this.options, function(data) {
if (self.tick == myTick) self.finishUpdate(data, first)
})
},
finishUpdate: function(data, first) {
this.data = data;
if (this.data) CodeMirror.signal(this.data, "update");
var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
if (this.widget) this.widget.close();
if (data && this.data && isNewCompletion(this.data, data)) return;
this.data = data;
if (data && data.list.length) {
if (picked && data.list.length == 1) {
this.pick(data, 0);
@ -123,20 +132,26 @@
CodeMirror.signal(data, "shown");
}
}
},
buildOptions: function(options) {
var editor = this.cm.options.hintOptions;
var out = {};
for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
if (editor) for (var prop in editor)
if (editor[prop] !== undefined) out[prop] = editor[prop];
if (options) for (var prop in options)
if (options[prop] !== undefined) out[prop] = options[prop];
return out;
}
};
function isNewCompletion(old, nw) {
var moved = CodeMirror.cmpPos(nw.from, old.from)
return moved > 0 && old.to.ch - old.from.ch != nw.to.ch - nw.from.ch
}
function parseOptions(cm, pos, options) {
var editor = cm.options.hintOptions;
var out = {};
for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
if (editor) for (var prop in editor)
if (editor[prop] !== undefined) out[prop] = editor[prop];
if (options) for (var prop in options)
if (options[prop] !== undefined) out[prop] = options[prop];
if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
return out;
}
function getText(completion) {
if (typeof completion == "string") return completion;
else return completion.text;
@ -214,6 +229,9 @@
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
(completion.options.container || document.body).appendChild(hints);
var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
var scrolls = hints.scrollHeight > hints.clientHeight + 1
var startScroll = cm.getScrollInfo();
if (overlapY > 0) {
var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
if (curTop - height > 0) { // Fits above cursor
@ -238,6 +256,8 @@
}
hints.style.left = (left = pos.left - overlapX) + "px";
}
if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
node.style.paddingRight = cm.display.nativeBarWidth + "px"
cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
@ -255,7 +275,6 @@
cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
}
var startScroll = cm.getScrollInfo();
cm.on("scroll", this.onScroll = function() {
var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
var newTop = top + startScroll.top - curScroll.top;
@ -335,34 +354,70 @@
}
};
CodeMirror.registerHelper("hint", "auto", function(cm, options) {
var helpers = cm.getHelpers(cm.getCursor(), "hint"), words;
if (helpers.length) {
for (var i = 0; i < helpers.length; i++) {
var cur = helpers[i](cm, options);
if (cur && cur.list.length) return cur;
}
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
if (words) return CodeMirror.hint.fromList(cm, {words: words});
} else if (CodeMirror.hint.anyword) {
return CodeMirror.hint.anyword(cm, options);
function applicableHelpers(cm, helpers) {
if (!cm.somethingSelected()) return helpers
var result = []
for (var i = 0; i < helpers.length; i++)
if (helpers[i].supportsSelection) result.push(helpers[i])
return result
}
function fetchHints(hint, cm, options, callback) {
if (hint.async) {
hint(cm, callback, options)
} else {
var result = hint(cm, options)
if (result && result.then) result.then(callback)
else callback(result)
}
}
function resolveAutoHints(cm, pos) {
var helpers = cm.getHelpers(pos, "hint"), words
if (helpers.length) {
var resolved = function(cm, callback, options) {
var app = applicableHelpers(cm, helpers);
function run(i) {
if (i == app.length) return callback(null)
fetchHints(app[i], cm, options, function(result) {
if (result && result.list.length > 0) callback(result)
else run(i + 1)
})
}
run(0)
}
resolved.async = true
resolved.supportsSelection = true
return resolved
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
} else if (CodeMirror.hint.anyword) {
return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
} else {
return function() {}
}
}
CodeMirror.registerHelper("hint", "auto", {
resolve: resolveAutoHints
});
CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
var to = CodeMirror.Pos(cur.line, token.end);
if (token.string && /\w/.test(token.string[token.string.length - 1])) {
var term = token.string, from = CodeMirror.Pos(cur.line, token.start);
} else {
var term = "", from = to;
}
var found = [];
for (var i = 0; i < options.words.length; i++) {
var word = options.words[i];
if (word.slice(0, token.string.length) == token.string)
if (word.slice(0, term.length) == term)
found.push(word);
}
if (found.length) return {
list: found,
from: CodeMirror.Pos(cur.line, token.start),
to: CodeMirror.Pos(cur.line, token.end)
};
if (found.length) return {list: found, from: from, to: to};
});
CodeMirror.commands.autocomplete = CodeMirror.showHint;
@ -373,7 +428,7 @@
alignWithWord: true,
closeCharacters: /[\s()\[\]{};:>,]/,
closeOnUnfocus: true,
completeOnSingleClick: false,
completeOnSingleClick: true,
container: null,
customKeys: null,
extraKeys: null

View File

@ -18,7 +18,9 @@
QUERY_DIV: ";",
ALIAS_KEYWORD: "AS"
};
var Pos = CodeMirror.Pos;
var Pos = CodeMirror.Pos, cmpPos = CodeMirror.cmpPos;
function isArray(val) { return Object.prototype.toString.call(val) == "[object Array]" }
function getKeywords(editor) {
var mode = editor.doc.modeOption;
@ -30,10 +32,28 @@
return typeof item == "string" ? item : item.text;
}
function getItem(list, item) {
if (!list.slice) return list[item];
for (var i = list.length - 1; i >= 0; i--) if (getText(list[i]) == item)
return list[i];
function wrapTable(name, value) {
if (isArray(value)) value = {columns: value}
if (!value.text) value.text = name
return value
}
function parseTables(input) {
var result = {}
if (isArray(input)) {
for (var i = input.length - 1; i >= 0; i--) {
var item = input[i]
result[getText(item).toUpperCase()] = wrapTable(getText(item), item)
}
} else if (input) {
for (var name in input)
result[name.toUpperCase()] = wrapTable(name, input[name])
}
return result
}
function getTable(name) {
return tables[name.toUpperCase()]
}
function shallowClone(object) {
@ -50,11 +70,18 @@
}
function addMatches(result, search, wordlist, formatter) {
for (var word in wordlist) {
if (!wordlist.hasOwnProperty(word)) continue;
if (wordlist.slice) word = wordlist[word];
if (match(search, word)) result.push(formatter(word));
if (isArray(wordlist)) {
for (var i = 0; i < wordlist.length; i++)
if (match(search, wordlist[i])) result.push(formatter(wordlist[i]))
} else {
for (var word in wordlist) if (wordlist.hasOwnProperty(word)) {
var val = wordlist[word]
if (!val || val === true)
val = word
else
val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text
if (match(search, val)) result.push(formatter(val))
}
}
}
@ -78,7 +105,7 @@
}
function nameCompletion(cur, token, result, editor) {
// Try to complete table, colunm names and return start position of completion
// Try to complete table, column names and return start position of completion
var useBacktick = false;
var nameParts = [];
var start = token.start;
@ -115,13 +142,13 @@
var alias = false;
var aliasTable = table;
// Check if table is available. If not, find table by Alias
if (!getItem(tables, table)) {
if (!getTable(table)) {
var oldTable = table;
table = findTableByAlias(table, editor);
if (table !== oldTable) alias = true;
}
var columns = getItem(tables, table);
var columns = getTable(table);
if (columns && columns.columns)
columns = columns.columns;
@ -151,15 +178,6 @@
}
}
function convertCurToNumber(cur) {
// max characters of a line is 999,999.
return cur.line + cur.ch / Math.pow(10, 6);
}
function convertNumberToCur(num) {
return Pos(Math.floor(num), +num.toString().split('.').pop());
}
function findTableByAlias(alias, editor) {
var doc = editor.doc;
var fullQuery = doc.getValue();
@ -182,15 +200,14 @@
separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
//find valid range
var prevItem = 0;
var current = convertCurToNumber(editor.getCursor());
for (var i=0; i< separator.length; i++) {
var _v = convertCurToNumber(separator[i]);
if (current > prevItem && current <= _v) {
validRange = { start: convertNumberToCur(prevItem), end: convertNumberToCur(_v) };
var prevItem = null;
var current = editor.getCursor()
for (var i = 0; i < separator.length; i++) {
if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) {
validRange = {start: prevItem, end: separator[i]};
break;
}
prevItem = _v;
prevItem = separator[i];
}
var query = doc.getRange(validRange.start, validRange.end, false);
@ -199,7 +216,7 @@
var lineText = query[i];
eachWord(lineText, function(word) {
var wordUpperCase = word.toUpperCase();
if (wordUpperCase === aliasUpperCase && getItem(tables, previousWord))
if (wordUpperCase === aliasUpperCase && getTable(previousWord))
table = previousWord;
if (wordUpperCase !== CONS.ALIAS_KEYWORD)
previousWord = word;
@ -210,11 +227,11 @@
}
CodeMirror.registerHelper("hint", "sql", function(editor, options) {
tables = (options && options.tables) || {};
tables = parseTables(options && options.tables)
var defaultTableName = options && options.defaultTable;
var disableKeywords = options && options.disableKeywords;
defaultTable = defaultTableName && getItem(tables, defaultTableName);
keywords = keywords || getKeywords(editor);
defaultTable = defaultTableName && getTable(defaultTableName);
keywords = getKeywords(editor);
if (defaultTableName && !defaultTable)
defaultTable = findTableByAlias(defaultTableName, editor);

View File

@ -4,10 +4,11 @@
}
.CodeMirror-lint-tooltip {
background-color: infobackground;
background-color: #ffd;
border: 1px solid black;
border-radius: 4px 4px 4px 4px;
color: infotext;
color: black;
font-family: monospace;
font-size: 10pt;
overflow: hidden;
padding: 2px 5px;
@ -24,11 +25,6 @@
-ms-transition: opacity .4s;
}
.CodeMirror-lint-tooltip code {
font-family: monospace;
font-weight: bold;
}
.CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning {
background-position: left bottom;
background-repeat: repeat-x;

View File

@ -1,5 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
@ -60,6 +61,7 @@
this.timeout = null;
this.hasGutter = hasGutter;
this.onMouseOver = function(e) { onMouseOver(cm, e); };
this.waitingFor = 0
}
function parseOptions(_cm, options) {
@ -111,21 +113,35 @@
var tip = document.createElement("div");
tip.className = "CodeMirror-lint-message-" + severity;
tip.appendChild(document.createTextNode(ann.message));
// Unescaping only the <code> tag.
tip.innerHTML = tip.innerHTML.replace("&lt;code&gt;", "<code>")
.replace("&lt;/code&gt;", "</code>");
return tip;
}
function lintAsync(cm, getAnnotations, passOptions) {
var state = cm.state.lint
var id = ++state.waitingFor
function abort() {
id = -1
cm.off("change", abort)
}
cm.on("change", abort)
getAnnotations(cm.getValue(), function(annotations, arg2) {
cm.off("change", abort)
if (state.waitingFor != id) return
if (arg2 && annotations instanceof CodeMirror) annotations = arg2
updateLinting(cm, annotations)
}, passOptions, cm);
}
function startLinting(cm) {
var state = cm.state.lint, options = state.options;
var passOptions = options.options || options; // Support deprecated passing of `options` property in options
var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), "lint");
if (!getAnnotations) return;
if (options.async || getAnnotations.async)
getAnnotations(cm.getValue(), updateLinting, passOptions, cm);
else
if (options.async || getAnnotations.async) {
lintAsync(cm, getAnnotations, passOptions)
} else {
updateLinting(cm, getAnnotations(cm.getValue(), passOptions, cm));
}
}
function updateLinting(cm, annotationsNotSorted) {
@ -170,9 +186,14 @@
state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
}
function popupSpanTooltip(ann, e) {
function popupTooltips(annotations, e) {
var target = e.target || e.srcElement;
showTooltipFor(e, annotationTooltip(ann), target);
var tooltip = document.createDocumentFragment();
for (var i = 0; i < annotations.length; i++) {
var ann = annotations[i];
tooltip.appendChild(annotationTooltip(ann));
}
showTooltipFor(e, tooltip, target);
}
function onMouseOver(cm, e) {
@ -180,16 +201,20 @@
if (!/\bCodeMirror-lint-mark-/.test(target.className)) return;
var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2;
var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client"));
var annotations = [];
for (var i = 0; i < spans.length; ++i) {
var ann = spans[i].__annotation;
if (ann) return popupSpanTooltip(ann, e);
if (ann) annotations.push(ann);
}
if (annotations.length) popupTooltips(annotations, e);
}
CodeMirror.defineOption("lint", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
clearMarks(cm);
cm.off("change", onChange);
if (cm.state.lint.options.lintOnChange !== false)
cm.off("change", onChange);
CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver);
clearTimeout(cm.state.lint.timeout);
delete cm.state.lint;
@ -199,11 +224,16 @@
var gutters = cm.getOption("gutters"), hasLintGutter = false;
for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true;
var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter);
cm.on("change", onChange);
if (state.options.tooltips != false)
if (state.options.lintOnChange !== false)
cm.on("change", onChange);
if (state.options.tooltips != false && state.options.tooltips != "gutter")
CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
startLinting(cm);
}
});
CodeMirror.defineExtension("performLint", function() {
if (this.state.lint) startLinting(this);
});
});

View File

@ -16,7 +16,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) {
var ie = /MSIE \d/.test(navigator.userAgent);
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
if (callback.nodeType == 1) {
if (callback.appendChild) {
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
var node = callback, col = 0;
node.innerHTML = "";

View File

@ -41,19 +41,21 @@
/* CURSOR */
.CodeMirror div.CodeMirror-cursor {
.CodeMirror-cursor {
border-left: 1px solid black;
border-right: none;
width: 0;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
.cm-fat-cursor .CodeMirror-cursor {
width: auto;
border: 0;
border: 0 !important;
background: #7e7;
}
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
@ -63,30 +65,37 @@
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
background-color: #7e7;
}
@-moz-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
0% {}
50% { background-color: transparent; }
100% {}
}
@-webkit-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
0% {}
50% { background-color: transparent; }
100% {}
}
@keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
0% {}
50% { background-color: transparent; }
100% {}
}
/* Can style cursor different in overwrite (non-insert) mode */
div.CodeMirror-overwrite div.CodeMirror-cursor {}
.CodeMirror-overwrite .CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-rulers {
position: absolute;
left: 0; right: 0; top: -50px; bottom: -20px;
overflow: hidden;
}
.CodeMirror-ruler {
border-left: 1px solid #ccc;
top: 0; bottom: 0;
position: absolute;
}
@ -162,7 +171,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actuall scrolling happens, thus preventing shaking and
before actual scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
@ -188,21 +197,26 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
min-height: 100%;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
display: inline-block;
vertical-align: top;
margin-bottom: -30px;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
height: 100%;
background: none !important;
border: none !important;
}
.CodeMirror-gutter-background {
position: absolute;
top: 0; bottom: 0;
z-index: 4;
}
.CodeMirror-gutter-elt {
position: absolute;
@ -235,6 +249,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
-webkit-font-variant-ligatures: contextual;
font-variant-ligatures: contextual;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
@ -277,19 +293,22 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
overflow: hidden;
visibility: hidden;
}
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor {
.CodeMirror-cursor {
position: absolute;
border-right: none;
width: 0;
pointer-events: none;
}
.CodeMirror-measure pre { position: static; }
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
div.CodeMirror-dragcursors {
visibility: visible;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
@ -297,17 +316,14 @@ div.CodeMirror-cursors {
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.CodeMirror ::selection { background: #d7d4f0; }
.CodeMirror ::-moz-selection { background: #d7d4f0; }
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
.cm-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// TODO actually recognize syntax of TypeScript constructs
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
@ -13,6 +11,11 @@
})(function(CodeMirror) {
"use strict";
function expressionAllowed(stream, state, backUp) {
return /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
(state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
}
CodeMirror.defineMode("javascript", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var statementIndent = parserConfig.statementIndent;
@ -30,14 +33,15 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
var jsKeywords = {
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
"return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C,
"var": kw("var"), "const": kw("var"), "let": kw("var"),
"function": kw("function"), "catch": kw("catch"),
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
"in": operator, "typeof": operator, "instanceof": operator,
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
"this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C
"this": kw("this"), "class": kw("class"), "super": kw("atom"),
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
"await": C, "async": kw("async")
};
// Extend the 'normal' keywords with the TypeScript language extensions
@ -45,18 +49,24 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
var type = {type: "variable", style: "variable-3"};
var tsKeywords = {
// object-like things
"interface": kw("interface"),
"extends": kw("extends"),
"constructor": kw("constructor"),
"interface": kw("class"),
"implements": C,
"namespace": C,
"module": kw("module"),
"enum": kw("module"),
"type": kw("type"),
// scope modifiers
"public": kw("public"),
"private": kw("private"),
"protected": kw("protected"),
"static": kw("static"),
"public": kw("modifier"),
"private": kw("modifier"),
"protected": kw("modifier"),
"abstract": kw("modifier"),
// operators
"as": operator,
// types
"string": type, "number": type, "bool": type, "any": type
"string": type, "number": type, "boolean": type, "any": type
};
for (var attr in tsKeywords) {
@ -105,6 +115,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
} else if (ch == "0" && stream.eat(/x/i)) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
} else if (ch == "0" && stream.eat(/o/i)) {
stream.eatWhile(/[0-7]/i);
return ret("number", "number");
} else if (ch == "0" && stream.eat(/b/i)) {
stream.eatWhile(/[01]/i);
return ret("number", "number");
} else if (/\d/.test(ch)) {
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
return ret("number", "number");
@ -115,8 +131,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
} else if (stream.eat("/")) {
stream.skipToEnd();
return ret("comment", "comment");
} else if (state.lastType == "operator" || state.lastType == "keyword c" ||
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
} else if (expressionAllowed(stream, state, 1)) {
readRegexp(stream);
stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
return ret("regexp", "string-2");
@ -131,7 +146,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
stream.skipToEnd();
return ret("error", "error");
} else if (isOperatorChar.test(ch)) {
stream.eatWhile(isOperatorChar);
if (ch != ">" || !state.lexical || state.lexical.type != ">")
stream.eatWhile(isOperatorChar);
return ret("operator", "operator", stream.current());
} else if (wordRE.test(ch)) {
stream.eatWhile(wordRE);
@ -194,13 +210,18 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
var arrow = stream.string.indexOf("=>", stream.start);
if (arrow < 0) return;
if (isTS) { // Try to skip TypeScript return type declarations after the arguments
var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow))
if (m) arrow = m.index
}
var depth = 0, sawSomething = false;
for (var pos = arrow - 1; pos >= 0; --pos) {
var ch = stream.string.charAt(pos);
var bracket = brackets.indexOf(ch);
if (bracket >= 0 && bracket < 3) {
if (!depth) { ++pos; break; }
if (--depth == 0) break;
if (--depth == 0) { if (ch == "(") sawSomething = true; break; }
} else if (bracket >= 3 && bracket < 6) {
++depth;
} else if (wordRE.test(ch)) {
@ -275,8 +296,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return false;
}
var state = cx.state;
cx.marked = "def";
if (state.context) {
cx.marked = "def";
if (inList(state.localVars)) return;
state.localVars = {name: varname, next: state.localVars};
} else {
@ -329,28 +350,30 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function statement(type, value) {
if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
if (type == "{") return cont(pushlex("}"), block, poplex);
if (type == ";") return cont();
if (type == "if") {
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
cx.state.cc.pop()();
return cont(pushlex("form"), expression, statement, poplex, maybeelse);
return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
}
if (type == "function") return cont(functiondef);
if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
if (type == "variable") return cont(pushlex("stat"), maybelabel);
if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
if (type == "switch") return cont(pushlex("form"), parenExpr, pushlex("}", "switch"), expect("{"),
block, poplex, poplex);
if (type == "case") return cont(expression, expect(":"));
if (type == "default") return cont(expect(":"));
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
statement, poplex, popcontext);
if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
if (type == "class") return cont(pushlex("form"), className, poplex);
if (type == "export") return cont(pushlex("form"), afterExport, poplex);
if (type == "import") return cont(pushlex("form"), afterImport, poplex);
if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
if (type == "module") return cont(pushlex("form"), pattern, pushlex("}"), expect("{"), block, poplex, poplex)
if (type == "type") return cont(typeexpr, expect("operator"), typeexpr, expect(";"));
if (type == "async") return cont(statement)
return pass(pushlex("stat"), expression, expect(";"), poplex);
}
function expression(type) {
@ -359,6 +382,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function expressionNoComma(type) {
return expressionInner(type, true);
}
function parenExpr(type) {
if (type != "(") return pass()
return cont(pushlex(")"), expression, expect(")"), poplex)
}
function expressionInner(type, noComma) {
if (cx.state.fatArrowAt == cx.stream.start) {
var body = noComma ? arrowBodyNoComma : arrowBody;
@ -369,12 +396,14 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
if (type == "function") return cont(functiondef, maybeop);
if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
if (type == "class") return cont(pushlex("form"), classExpression, poplex);
if (type == "keyword c" || type == "async") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
if (type == "quasi") { return pass(quasi, maybeop); }
if (type == "quasi") return pass(quasi, maybeop);
if (type == "new") return cont(maybeTarget(noComma));
return cont();
}
function maybeexpression(type) {
@ -425,6 +454,18 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
findFatArrow(cx.stream, cx.state);
return pass(type == "{" ? statement : expressionNoComma);
}
function maybeTarget(noComma) {
return function(type) {
if (type == ".") return cont(noComma ? targetNoComma : target);
else return pass(noComma ? expressionNoComma : expression);
};
}
function target(_, value) {
if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
}
function targetNoComma(_, value) {
if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
}
function maybelabel(type) {
if (type == ":") return cont(poplex, statement);
return pass(maybeoperatorComma, expect(";"), poplex);
@ -433,7 +474,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "variable") {cx.marked = "property"; return cont();}
}
function objprop(type, value) {
if (type == "variable" || cx.style == "keyword") {
if (type == "async") {
cx.marked = "property";
return cont(objprop);
} else if (type == "variable" || cx.style == "keyword") {
cx.marked = "property";
if (value == "get" || value == "set") return cont(getterSetter);
return cont(afterprop);
@ -442,8 +486,14 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return cont(afterprop);
} else if (type == "jsonld-keyword") {
return cont(afterprop);
} else if (type == "modifier") {
return cont(objprop)
} else if (type == "[") {
return cont(expression, expect("]"), afterprop);
} else if (type == "spread") {
return cont(expression);
} else if (type == ":") {
return pass(afterprop)
}
}
function getterSetter(type) {
@ -456,17 +506,20 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "(") return pass(functiondef);
}
function commasep(what, end) {
function proceed(type) {
function proceed(type, value) {
if (type == ",") {
var lex = cx.state.lexical;
if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
return cont(what, proceed);
return cont(function(type, value) {
if (type == end || value == end) return pass()
return pass(what)
}, proceed);
}
if (type == end) return cont();
if (type == end || value == end) return cont();
return cont(expect(end));
}
return function(type) {
if (type == end) return cont();
return function(type, value) {
if (type == end || value == end) return cont();
return pass(what, proceed);
};
}
@ -479,20 +532,45 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "}") return cont();
return pass(statement, block);
}
function maybetype(type) {
if (isTS && type == ":") return cont(typedef);
function maybetype(type, value) {
if (isTS) {
if (type == ":") return cont(typeexpr);
if (value == "?") return cont(maybetype);
}
}
function maybedefault(_, value) {
if (value == "=") return cont(expressionNoComma);
function typeexpr(type) {
if (type == "variable") {cx.marked = "variable-3"; return cont(afterType);}
if (type == "string" || type == "number" || type == "atom") return cont(afterType);
if (type == "{") return cont(commasep(typeprop, "}"))
if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType)
}
function typedef(type) {
if (type == "variable") {cx.marked = "variable-3"; return cont();}
function maybeReturnType(type) {
if (type == "=>") return cont(typeexpr)
}
function typeprop(type) {
if (type == "variable" || cx.style == "keyword") {
cx.marked = "property"
return cont(typeprop)
} else if (type == ":") {
return cont(typeexpr)
}
}
function typearg(type) {
if (type == "variable") return cont(typearg)
else if (type == ":") return cont(typeexpr)
}
function afterType(type, value) {
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
if (value == "|" || type == ".") return cont(typeexpr)
if (type == "[") return cont(expect("]"), afterType)
}
function vardef() {
return pass(pattern, maybetype, maybeAssign, vardefCont);
}
function pattern(type, value) {
if (type == "modifier") return cont(pattern)
if (type == "variable") { register(value); return cont(); }
if (type == "spread") return cont(pattern);
if (type == "[") return contCommasep(pattern, "]");
if (type == "{") return contCommasep(proppattern, "}");
}
@ -502,6 +580,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return cont(maybeAssign);
}
if (type == "variable") cx.marked = "property";
if (type == "spread") return cont(pattern);
if (type == "}") return pass();
return cont(expect(":"), pattern, maybeAssign);
}
function maybeAssign(_type, value) {
@ -537,28 +617,34 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function functiondef(type, value) {
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
if (type == "variable") {register(value); return cont(functiondef);}
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, maybetype, statement, popcontext);
}
function funarg(type) {
if (type == "spread") return cont(funarg);
return pass(pattern, maybetype, maybedefault);
return pass(pattern, maybetype, maybeAssign);
}
function classExpression(type, value) {
// Class expressions may have an optional name.
if (type == "variable") return className(type, value);
return classNameAfter(type, value);
}
function className(type, value) {
if (type == "variable") {register(value); return cont(classNameAfter);}
}
function classNameAfter(type, value) {
if (value == "extends") return cont(expression, classNameAfter);
if (value == "extends" || value == "implements") return cont(isTS ? typeexpr : expression, classNameAfter);
if (type == "{") return cont(pushlex("}"), classBody, poplex);
}
function classBody(type, value) {
if (type == "variable" || cx.style == "keyword") {
if (value == "static") {
if ((value == "static" || value == "get" || value == "set" ||
(isTS && (value == "public" || value == "private" || value == "protected" || value == "readonly" || value == "abstract"))) &&
cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false)) {
cx.marked = "keyword";
return cont(classBody);
}
cx.marked = "property";
if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);
return cont(functiondef, classBody);
return cont(isTS ? classfield : functiondef, classBody);
}
if (value == "*") {
cx.marked = "keyword";
@ -567,23 +653,24 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == ";") return cont(classBody);
if (type == "}") return cont();
}
function classGetterSetter(type) {
if (type != "variable") return pass();
cx.marked = "property";
return cont();
function classfield(type, value) {
if (value == "?") return cont(classfield)
if (type == ":") return cont(typeexpr, maybeAssign)
return pass(functiondef)
}
function afterModule(type, value) {
if (type == "string") return cont(statement);
if (type == "variable") { register(value); return cont(maybeFrom); }
}
function afterExport(_type, value) {
function afterExport(type, value) {
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
return pass(statement);
}
function exportField(type, value) {
if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); }
if (type == "variable") return pass(expressionNoComma, exportField);
}
function afterImport(type) {
if (type == "string") return cont();
return pass(importSpec, maybeFrom);
return pass(importSpec, maybeMoreImports, maybeFrom);
}
function importSpec(type, value) {
if (type == "{") return contCommasep(importSpec, "}");
@ -591,6 +678,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (value == "*") cx.marked = "keyword";
return cont(maybeAs);
}
function maybeMoreImports(type) {
if (type == ",") return cont(importSpec, maybeMoreImports)
}
function maybeAs(_type, value) {
if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
}
@ -599,17 +689,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function arrayLiteral(type) {
if (type == "]") return cont();
return pass(expressionNoComma, maybeArrayComprehension);
}
function maybeArrayComprehension(type) {
if (type == "for") return pass(comprehension, expect("]"));
if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
return pass(commasep(expressionNoComma, "]"));
}
function comprehension(type) {
if (type == "for") return cont(forspec, comprehension);
if (type == "if") return cont(expression, comprehension);
}
function isContinuedStatement(state, textAfter) {
return state.lastType == "operator" || state.lastType == "," ||
@ -628,7 +709,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
localVars: parserConfig.localVars,
context: parserConfig.localVars && {vars: parserConfig.localVars},
indented: 0
indented: basecolumn || 0
};
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
state.globalVars = parserConfig.globalVars;
@ -652,14 +733,18 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
indent: function(state, textAfter) {
if (state.tokenize == tokenComment) return CodeMirror.Pass;
if (state.tokenize != tokenBase) return 0;
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top
// Kludge to prevent 'maybelse' from blocking lexical scope pops
if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
var c = state.cc[i];
if (c == poplex) lexical = lexical.prev;
else if (c != maybeelse) break;
}
if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
while ((lexical.type == "stat" || lexical.type == "form") &&
(firstChar == "}" || ((top = state.cc[state.cc.length - 1]) &&
(top == maybeoperatorComma || top == maybeoperatorNoComma) &&
!/^[,\.=+\-*:?[\(]/.test(textAfter))))
lexical = lexical.prev;
if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
lexical = lexical.prev;
var type = lexical.type, closing = firstChar == type;
@ -684,7 +769,13 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
helperType: jsonMode ? "json" : "javascript",
jsonldMode: jsonldMode,
jsonMode: jsonMode
jsonMode: jsonMode,
expressionAllowed: expressionAllowed,
skipExpression: function(state) {
var top = state.cc[state.cc.length - 1]
if (top == expression || top == expressionNoComma) state.cc.pop()
}
};
});

File diff suppressed because one or more lines are too long

View File

@ -11,54 +11,56 @@
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("xml", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;
if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
var htmlConfig = {
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
'track': true, 'wbr': true, 'menuitem': true},
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
'th': true, 'tr': true},
contextGrabbers: {
'dd': {'dd': true, 'dt': true},
'dt': {'dd': true, 'dt': true},
'li': {'li': true},
'option': {'option': true, 'optgroup': true},
'optgroup': {'optgroup': true},
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
'rp': {'rp': true, 'rt': true},
'rt': {'rp': true, 'rt': true},
'tbody': {'tbody': true, 'tfoot': true},
'td': {'td': true, 'th': true},
'tfoot': {'tbody': true},
'th': {'td': true, 'th': true},
'thead': {'tbody': true, 'tfoot': true},
'tr': {'tr': true}
},
doNotIndent: {"pre": true},
allowUnquoted: true,
allowMissing: true,
caseFold: true
}
var Kludges = parserConfig.htmlMode ? {
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
'track': true, 'wbr': true, 'menuitem': true},
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
'th': true, 'tr': true},
contextGrabbers: {
'dd': {'dd': true, 'dt': true},
'dt': {'dd': true, 'dt': true},
'li': {'li': true},
'option': {'option': true, 'optgroup': true},
'optgroup': {'optgroup': true},
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
'rp': {'rp': true, 'rt': true},
'rt': {'rp': true, 'rt': true},
'tbody': {'tbody': true, 'tfoot': true},
'td': {'td': true, 'th': true},
'tfoot': {'tbody': true},
'th': {'td': true, 'th': true},
'thead': {'tbody': true, 'tfoot': true},
'tr': {'tr': true}
},
doNotIndent: {"pre": true},
allowUnquoted: true,
allowMissing: true,
caseFold: true
} : {
autoSelfClosers: {},
implicitlyClosed: {},
contextGrabbers: {},
doNotIndent: {},
allowUnquoted: false,
allowMissing: false,
caseFold: false
};
var alignCDATA = parserConfig.alignCDATA;
var xmlConfig = {
autoSelfClosers: {},
implicitlyClosed: {},
contextGrabbers: {},
doNotIndent: {},
allowUnquoted: false,
allowMissing: false,
caseFold: false
}
CodeMirror.defineMode("xml", function(editorConf, config_) {
var indentUnit = editorConf.indentUnit
var config = {}
var defaults = config_.htmlMode ? htmlConfig : xmlConfig
for (var prop in defaults) config[prop] = defaults[prop]
for (var prop in config_) config[prop] = config_[prop]
// Return variables for tokenizers
var type, setStyle;
@ -109,6 +111,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
return null;
}
}
inText.isInText = true;
function inTag(stream, state) {
var ch = stream.next();
@ -187,7 +190,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
this.tagName = tagName;
this.indent = state.indented;
this.startOfLine = startOfLine;
if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
this.noIndent = true;
}
function popContext(state) {
@ -200,8 +203,8 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
return;
}
parentTagName = state.context.tagName;
if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
if (!config.contextGrabbers.hasOwnProperty(parentTagName) ||
!config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
return;
}
popContext(state);
@ -232,9 +235,9 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
if (type == "word") {
var tagName = stream.current();
if (state.context && state.context.tagName != tagName &&
Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
config.implicitlyClosed.hasOwnProperty(state.context.tagName))
popContext(state);
if (state.context && state.context.tagName == tagName) {
if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) {
setStyle = "tag";
return closeState;
} else {
@ -268,7 +271,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
var tagName = state.tagName, tagStart = state.tagStart;
state.tagName = state.tagStart = null;
if (type == "selfcloseTag" ||
Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
config.autoSelfClosers.hasOwnProperty(tagName)) {
maybePopContext(state, tagName);
} else {
maybePopContext(state, tagName);
@ -281,12 +284,12 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
}
function attrEqState(type, stream, state) {
if (type == "equals") return attrValueState;
if (!Kludges.allowMissing) setStyle = "error";
if (!config.allowMissing) setStyle = "error";
return attrState(type, stream, state);
}
function attrValueState(type, stream, state) {
if (type == "string") return attrContinuedState;
if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;}
setStyle = "error";
return attrState(type, stream, state);
}
@ -296,12 +299,14 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
}
return {
startState: function() {
return {tokenize: inText,
state: baseState,
indented: 0,
tagName: null, tagStart: null,
context: null};
startState: function(baseIndent) {
var state = {tokenize: inText,
state: baseState,
indented: baseIndent || 0,
tagName: null, tagStart: null,
context: null}
if (baseIndent != null) state.baseIndent = baseIndent
return state
},
token: function(stream, state) {
@ -334,19 +339,19 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
// Indent the starts of attribute names.
if (state.tagName) {
if (multilineTagIndentPastTag)
if (config.multilineTagIndentPastTag !== false)
return state.tagStart + state.tagName.length + 2;
else
return state.tagStart + indentUnit * multilineTagIndentFactor;
return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1);
}
if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
if (config.alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
if (tagAfter && tagAfter[1]) { // Closing tag spotted
while (context) {
if (context.tagName == tagAfter[2]) {
context = context.prev;
break;
} else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
} else if (config.implicitlyClosed.hasOwnProperty(context.tagName)) {
context = context.prev;
} else {
break;
@ -354,25 +359,30 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
}
} else if (tagAfter) { // Opening tag spotted
while (context) {
var grabbers = Kludges.contextGrabbers[context.tagName];
var grabbers = config.contextGrabbers[context.tagName];
if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
context = context.prev;
else
break;
}
}
while (context && !context.startOfLine)
while (context && context.prev && !context.startOfLine)
context = context.prev;
if (context) return context.indent + indentUnit;
else return 0;
else return state.baseIndent || 0;
},
electricInput: /<\/[\s\w:]+>$/,
blockCommentStart: "<!--",
blockCommentEnd: "-->",
configuration: parserConfig.htmlMode ? "html" : "xml",
helperType: parserConfig.htmlMode ? "html" : "xml"
configuration: config.htmlMode ? "html" : "xml",
helperType: config.htmlMode ? "html" : "xml",
skipAttribute: function(state) {
if (state.state == attrValueState)
state.state = attrState
}
};
});

View File

@ -84,9 +84,15 @@ var PMA_commonParams = (function () {
* @return string
*/
getUrlQuery: function () {
var common = this.get('common_query');
var separator = '?';
if (common.length > 0) {
separator = '&';
}
return PMA_sprintf(
'%s&server=%s&db=%s&table=%s',
'%s%sserver=%s&db=%s&table=%s',
this.get('common_query'),
separator,
encodeURIComponent(this.get('server')),
encodeURIComponent(this.get('db')),
encodeURIComponent(this.get('table'))

View File

@ -585,10 +585,10 @@ function setTab(tab_id)
{
$('ul.tabs').each(function() {
var $this = $(this);
if (!$this.find('li a[href=#' + tab_id + ']').length) {
if (!$this.find('li a[href="#' + tab_id + '"]').length) {
return;
}
$this.find('li').removeClass('active').find('a[href=#' + tab_id + ']').parent().addClass('active');
$this.find('li').removeClass('active').find('a[href="#' + tab_id + '"]').parent().addClass('active');
$this.parent().find('div.tabs_contents fieldset').hide().filter('#' + tab_id).show();
var hashValue = 'tab_' + tab_id;
location.hash = hashValue;
@ -798,8 +798,8 @@ function savePrefsToLocalStorage(form)
type: 'POST',
data: {
ajax_request: true,
server: $form.find('input[name=server]').val(),
token: $form.find('input[name=token]').val(),
server: PMA_commonParams.get('server'),
token: PMA_commonParams.get('token'),
submit_get_json: true
},
success: function (data) {
@ -838,7 +838,7 @@ function updatePrefsDate()
}
/**
* Prepares message which informs that localStorage preferences are available and can be imported
* Prepares message which informs that localStorage preferences are available and can be imported or deleted
*/
function offerPrefsAutoimport()
{
@ -853,7 +853,17 @@ function offerPrefsAutoimport()
if ($a.attr('href') == '#no') {
$cnt.remove();
$.post('index.php', {
token: $cnt.find('input[name=token]').val(),
token: PMA_commonParams.get('token'),
server: PMA_commonParams.get('server'),
prefs_autoload: 'hide'
}, null, 'html');
return;
} else if ($a.attr('href') == '#delete') {
$cnt.remove();
localStorage.clear();
$.post('index.php', {
token: PMA_commonParams.get('token'),
server: PMA_commonParams.get('server'),
prefs_autoload: 'hide'
}, null, 'html');
return;

View File

@ -127,12 +127,6 @@ var PMA_console = {
PMA_consoleDebug.initialize();
PMA_console.$consoleToolbar.children('.console_switch').click(PMA_console.toggle);
$(document).keydown(function(event) {
// Ctrl + Alt + C
if (event.ctrlKey && event.altKey && event.keyCode === 67) {
PMA_console.toggle();
}
});
$('#pma_console').find('.toolbar').children().mousedown(function(event) {
event.preventDefault();
@ -196,9 +190,10 @@ var PMA_console = {
return;
}
try {
var data = $.parseJSON(xhr.responseText);
var data = JSON.parse(xhr.responseText);
PMA_console.ajaxCallback(data);
} catch (e) {
console.trace();
console.log("Invalid JSON!" + e.message);
if (AJAX.xhr && AJAX.xhr.status === 0 && AJAX.xhr.statusText !== 'abort') {
PMA_ajaxShowMessage($('<div />',{'class':'error','html':PMA_messages.strRequestFailed+' ( '+escapeHtml(AJAX.xhr.statusText)+' )'}));
@ -255,7 +250,7 @@ var PMA_console = {
if (options && options.profiling === true) {
PMA_console.$requestForm.append('<input name="profiling" value="on">');
}
if (! confirmQuery(PMA_console.$requestForm[0], PMA_console.$requestForm.children('textarea')[0])) {
if (! confirmQuery(PMA_console.$requestForm[0], PMA_console.$requestForm.children('textarea')[0].value)) {
return;
}
PMA_console.$requestForm.children('[name=console_message_id]')

View File

@ -132,7 +132,6 @@ AJAX.registerOnload('db_central_columns.js', function () {
$('#tableslistcontainer').find('.checkall').show();
});
$('.edit_save_form').click(function(event) {
//alert(1);
event.preventDefault();
event.stopPropagation();
var rownum = $(this).data('rownum');
@ -142,14 +141,14 @@ AJAX.registerOnload('db_central_columns.js', function () {
.attr('name', $(this).attr('name'));
}
});
if($('#f_' + rownum + ' .default_type').val() === 'USER_DEFINED') {
$('#f_' + rownum + ' .default_type').attr('name','col_default_sel');
} else {
$('#f_' + rownum + ' .default_value').attr('name','col_default_val');
}
// alert(rownum);
var datastring = $('#f_' + rownum + ' :input').serialize();
//console.log(datastring);
$.ajax({
type: "POST",
url: "db_central_columns.php",

View File

@ -41,7 +41,7 @@ AJAX.registerOnload('db_operations.js', function () {
var new_db_name = $('#new_db_name').val();
if (new_db_name == old_db_name) {
PMA_ajaxShowMessage(PMA_messages.strDropDatabaseStrongWarning);
PMA_ajaxShowMessage(PMA_messages.strDatabaseRenameToSameName, false, "error");
return false;
}
@ -133,11 +133,16 @@ AJAX.registerOnload('db_operations.js', function () {
var question = PMA_messages.strDropDatabaseStrongWarning + ' ';
question += PMA_sprintf(
PMA_messages.strDoYouReally,
'DROP DATABASE ' + escapeHtml(PMA_commonParams.get('db'))
'DROP DATABASE `' + escapeHtml(PMA_commonParams.get('db') + '`')
);
var params = {
'is_js_confirmed': '1',
'ajax_request': true,
'token': PMA_commonParams.get('token')
};
$(this).PMA_confirm(question, $(this).attr('href'), function (url) {
PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
$.post(url, {'is_js_confirmed': '1', 'ajax_request': true}, function (data) {
$.post(url, params, function (data) {
if (typeof data !== 'undefined' && data.success) {
//Database deleted successfully, refresh both the frames
PMA_reloadNavigation();

View File

@ -129,7 +129,8 @@ AJAX.registerOnload('db_search.js', function () {
var params = {
'ajax_request': true,
'is_js_confirmed': true,
'sql_query' : browse_sql
'sql_query' : browse_sql,
'token' : PMA_commonParams.get('token')
};
$.post(url, params, function (data) {
if (typeof data !== 'undefined' && data.success) {
@ -171,7 +172,8 @@ AJAX.registerOnload('db_search.js', function () {
var params = {
'ajax_request': true,
'is_js_confirmed': true,
'sql_query': $(this).data('delete-sql')
'sql_query': $(this).data('delete-sql'),
'token' : PMA_commonParams.get('token')
};
var url = $(this).attr('href');

View File

@ -30,6 +30,7 @@ AJAX.registerTeardown('db_structure.js', function () {
$('a.real_row_count').off('click');
$('a.row_count_sum').off('click');
$('select[name=submit_mult]').unbind('change');
$("#filterText").unbind('keyup');
});
/**
@ -210,6 +211,26 @@ AJAX.registerOnload('db_structure.js', function () {
});
};
/**
* Filtering tables on table listing of particular database
*
*/
$("#filterText").keyup(function() {
var filterInput = $(this).val().toUpperCase();
var structureTable = $('#structureTable')[0];
$('#structureTable tbody tr').each(function() {
var tr = $(this);
var a = tr.find('a')[0];
if (a) {
if (a.text.trim().toUpperCase().indexOf(filterInput) > -1) {
tr[0].style.display = "";
} else {
tr[0].style.display = "none";
}
}
});
});
/**
* Event handler on select of "Make consistent with central list"
*/
@ -217,9 +238,11 @@ AJAX.registerOnload('db_structure.js', function () {
if ($(this).val() === 'make_consistent_with_central_list') {
event.preventDefault();
event.stopPropagation();
jqConfirm(PMA_messages.makeConsistentMessage, function(){
$('#tablesForm').submit();
});
jqConfirm(
PMA_messages.makeConsistentMessage, function(){
$('#tablesForm').submit();
}
);
return false;
}
else if ($(this).val() === 'copy_tbl' || $(this).val() === 'add_prefix_tbl' || $(this).val() === 'replace_prefix_tbl' || $(this).val() === 'copy_tbl_change_prefix') {
@ -295,7 +318,7 @@ AJAX.registerOnload('db_structure.js', function () {
* @var question String containing the question to be asked for confirmation
*/
var question = PMA_messages.strTruncateTableStrongWarning + ' ' +
PMA_sprintf(PMA_messages.strDoYouReally, 'TRUNCATE ' + escapeHtml(curr_table_name)) +
PMA_sprintf(PMA_messages.strDoYouReally, 'TRUNCATE `' + escapeHtml(curr_table_name) + '`') +
getForeignKeyCheckboxLoader();
$this_anchor.PMA_confirm(question, $this_anchor.attr('href'), function (url) {
@ -303,6 +326,7 @@ AJAX.registerOnload('db_structure.js', function () {
PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
var params = getJSConfirmCommonParam(this);
params.token = PMA_commonParams.get('token');
$.post(url, params, function (data) {
if (typeof data !== 'undefined' && data.success === true) {
@ -354,10 +378,10 @@ AJAX.registerOnload('db_structure.js', function () {
var question;
if (! is_view) {
question = PMA_messages.strDropTableStrongWarning + ' ' +
PMA_sprintf(PMA_messages.strDoYouReally, 'DROP TABLE ' + escapeHtml(curr_table_name));
PMA_sprintf(PMA_messages.strDoYouReally, 'DROP TABLE `' + escapeHtml(curr_table_name) + '`');
} else {
question =
PMA_sprintf(PMA_messages.strDoYouReally, 'DROP VIEW ' + escapeHtml(curr_table_name));
PMA_sprintf(PMA_messages.strDoYouReally, 'DROP VIEW `' + escapeHtml(curr_table_name) + '`');
}
question += getForeignKeyCheckboxLoader();
@ -366,11 +390,11 @@ AJAX.registerOnload('db_structure.js', function () {
var $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
var params = getJSConfirmCommonParam(this);
params.token = PMA_commonParams.get('token');
$.post(url, params, function (data) {
if (typeof data !== 'undefined' && data.success === true) {
PMA_ajaxShowMessage(data.message);
toggleRowColors($curr_row.next());
$curr_row.hide("medium").remove();
PMA_adjustTotals();
PMA_reloadNavigation();

View File

@ -83,7 +83,12 @@ AJAX.registerOnload('db_tracking.js', function () {
$anchor.PMA_confirm(question, $anchor.attr('href'), function (url) {
PMA_ajaxShowMessage(PMA_messages.strDeletingTrackingData);
AJAX.source = $anchor;
$.post(url, {'ajax_page_request': true, 'ajax_request': true}, AJAX.responseHandler);
var params = {
'ajax_page_request': true,
'ajax_request': true,
'token': PMA_commonParams.get('token')
};
$.post(url, params, AJAX.responseHandler);
});
});
});

View File

@ -64,6 +64,7 @@ var ErrorReport = {
$('#error_report_dialog').remove();
}
var $div = $('<div id="error_report_dialog"></div>');
$div.css('z-index', '1000');
var button_options = {};
@ -303,8 +304,8 @@ var ErrorReport = {
};
TraceKit.report.subscribe(ErrorReport.error_handler);
ErrorReport.set_up_error_reporting();
$(function () {
AJAX.registerOnload('error_report.js', function(){
TraceKit.report.subscribe(ErrorReport.error_handler);
ErrorReport.set_up_error_reporting();
ErrorReport.wrap_global_functions();
});

View File

@ -126,7 +126,7 @@ function loadTemplate(id)
$.post('tbl_export.php', params, function (response) {
if (response.success === true) {
var $form = $('form[name="dump"]');
var options = $.parseJSON(response.data);
var options = JSON.parse(response.data);
$.each(options, function (key, value) {
var $element = $form.find('[name="' + key + '"]');
if ($element.length) {
@ -522,10 +522,13 @@ function check_table_selected(row) {
if (data && structure) {
table_select.prop({checked: true, indeterminate: false});
$row.addClass('marked');
} else if (data || structure) {
table_select.prop({checked: true, indeterminate: true});
$row.removeClass('marked');
} else {
table_select.prop({checked: false, indeterminate: false});
$row.removeClass('marked');
}
}
@ -535,8 +538,10 @@ function toggle_table_select(row) {
if (table_selected) {
$row.find('input[type="checkbox"]:not(:disabled)').prop('checked', true);
$row.addClass('marked');
} else {
$row.find('input[type="checkbox"]:not(:disabled)').prop('checked', false);
$row.removeClass('marked');
}
}

View File

@ -471,8 +471,13 @@ function suggestPassword(passwd_form)
passwd.value += pwchars.charAt(Math.abs(randomWords[i]) % pwchars.length);
}
passwd_form.text_pma_pw.value = passwd.value;
passwd_form.text_pma_pw2.value = passwd.value;
$jquery_passwd_form = $(passwd_form);
passwd_form.elements['pma_pw'].value = passwd.value;
passwd_form.elements['pma_pw2'].value = passwd.value;
meter_obj = $jquery_passwd_form.find('meter[name="pw_meter"]').first();
meter_obj_label = $jquery_passwd_form.find('span[name="pw_strength"]').first();
checkPasswordStrength(passwd.value, meter_obj, meter_obj_label);
return true;
}
@ -516,10 +521,16 @@ function PMA_current_version(data)
var current = parseVersionString($('span.version').text());
var latest = parseVersionString(data.version);
var url = 'https://web.phpmyadmin.net/files/' + escapeHtml(encodeURIComponent(data.version)) + '/';
var version_information_message = '<span class="latest">' +
PMA_messages.strLatestAvailable +
' <a href="' + url + '" class="disableAjax">' + escapeHtml(data.version) + '</a>' +
'</span>';
var version_information_message = document.createElement('span');
version_information_message.className = 'latest';
var version_information_message_link = document.createElement('a');
version_information_message_link.href = url;
version_information_message_link.className = 'disableAjax';
version_information_message_link_text = document.createTextNode(data.version);
version_information_message_link.appendChild(version_information_message_link_text);
var prefix_message = document.createTextNode(PMA_messages.strLatestAvailable + ' ');
version_information_message.appendChild(prefix_message);
version_information_message.appendChild(version_information_message_link);
if (latest > current) {
var message = PMA_sprintf(
PMA_messages.strNewerVersion,
@ -532,14 +543,26 @@ function PMA_current_version(data)
htmlClass = 'error';
}
$('#newer_version_notice').remove();
$('#maincontainer').after('<div id="newer_version_notice" class="' + htmlClass + '"><a href="' + url + '" class="disableAjax">' + message + '</a></div>');
var maincontainer_div = document.createElement('div');
maincontainer_div.id = 'newer_version_notice';
maincontainer_div.className = htmlClass;
var maincontainer_div_link = document.createElement('a');
maincontainer_div_link.href = url;
maincontainer_div_link.className = 'disableAjax';
maincontainer_div_link_text = document.createTextNode(message);
maincontainer_div_link.appendChild(maincontainer_div_link_text);
maincontainer_div.appendChild(maincontainer_div_link);
$('#maincontainer').append($(maincontainer_div));
}
if (latest === current) {
version_information_message = ' (' + PMA_messages.strUpToDate + ')';
version_information_message = document.createTextNode(' (' + PMA_messages.strUpToDate + ')');
}
/* Remove extra whitespace */
var version_info = $('#li_pma_version').contents().get(2);
version_info.textContent = $.trim(version_info.textContent);
var $liPmaVersion = $('#li_pma_version');
$liPmaVersion.find('span.latest').remove();
$liPmaVersion.append(version_information_message);
$liPmaVersion.append($(version_information_message));
}
}
@ -649,7 +672,7 @@ function confirmLink(theLink, theSqlQuery)
* This function is called by the 'checkSqlQuery()' js function.
*
* @param theForm1 object the form
* @param sqlQuery1 object the sql query textarea
* @param sqlQuery1 string the sql query string
*
* @return boolean whether to run the query or not
*
@ -674,15 +697,15 @@ function confirmQuery(theForm1, sqlQuery1)
var do_confirm_re_2 = new RegExp('^\\s*DELETE\\s+FROM\\s', 'i');
var do_confirm_re_3 = new RegExp('^\\s*TRUNCATE\\s', 'i');
if (do_confirm_re_0.test(sqlQuery1.value) ||
do_confirm_re_1.test(sqlQuery1.value) ||
do_confirm_re_2.test(sqlQuery1.value) ||
do_confirm_re_3.test(sqlQuery1.value)) {
if (do_confirm_re_0.test(sqlQuery1) ||
do_confirm_re_1.test(sqlQuery1) ||
do_confirm_re_2.test(sqlQuery1) ||
do_confirm_re_3.test(sqlQuery1)) {
var message;
if (sqlQuery1.value.length > 100) {
message = sqlQuery1.value.substr(0, 100) + '\n ...';
if (sqlQuery1.length > 100) {
message = sqlQuery1.substr(0, 100) + '\n ...';
} else {
message = sqlQuery1.value;
message = sqlQuery1;
}
var is_confirmed = confirm(PMA_sprintf(PMA_messages.strDoYouReally, message));
// statement is confirmed -> update the
@ -695,7 +718,6 @@ function confirmQuery(theForm1, sqlQuery1)
// statement is rejected -> do not submit the form
else {
window.focus();
sqlQuery1.focus();
return false;
} // end if (handle confirm box result)
} // end if (display confirm box)
@ -723,31 +745,30 @@ function checkSqlQuery(theForm)
} else {
sqlQuery = theForm.elements.sql_query.value;
}
var isEmpty = 1;
var space_re = new RegExp('\\s+');
if (typeof(theForm.elements.sql_file) != 'undefined' &&
theForm.elements.sql_file.value.replace(space_re, '') !== '') {
return true;
}
if (isEmpty && typeof(theForm.elements.id_bookmark) != 'undefined' &&
if (typeof(theForm.elements.id_bookmark) != 'undefined' &&
(theForm.elements.id_bookmark.value !== null || theForm.elements.id_bookmark.value !== '') &&
theForm.elements.id_bookmark.selectedIndex !== 0) {
return true;
}
var result = false;
// Checks for "DROP/DELETE/ALTER" statements
if (sqlQuery.replace(space_re, '') !== '') {
return confirmQuery(theForm, sqlQuery);
}
theForm.reset();
isEmpty = 1;
if (isEmpty) {
result = confirmQuery(theForm, sqlQuery);
} else {
alert(PMA_messages.strFormEmpty);
codemirror_editor.focus();
return false;
}
return true;
if (codemirror_editor) {
codemirror_editor.focus();
} else if (codemirror_inline_editor) {
codemirror_inline_editor.focus();
}
return result;
} // end of the 'checkSqlQuery()' function
/**
@ -895,17 +916,31 @@ AJAX.registerOnload('functions.js', function () {
document.onkeypress = function() {
_idleSecondsCounter = 0;
};
function guid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
function SetIdleTime() {
_idleSecondsCounter++;
}
function UpdateIdleTime() {
var href = 'index.php';
var guid = 'default';
if (isStorageSupported('sessionStorage')) {
guid = window.sessionStorage.guid;
}
var params = {
'ajax_request' : true,
'token' : PMA_commonParams.get('token'),
'server' : PMA_commonParams.get('server'),
'db' : PMA_commonParams.get('db'),
'guid': guid,
'access_time':_idleSecondsCounter
};
$.ajax({
@ -914,28 +949,42 @@ AJAX.registerOnload('functions.js', function () {
data: params,
success: function (data) {
if (data.success) {
var remaining = PMA_commonParams.get('LoginCookieValidity') - _idleSecondsCounter;
if (PMA_commonParams.get('LoginCookieValidity') - _idleSecondsCounter < 0) {
/* There is other active window, let's reset counter */
_idleSecondsCounter = 0;
}
var remaining = Math.min(
/* Remaining login validity */
PMA_commonParams.get('LoginCookieValidity') - _idleSecondsCounter,
/* Remaining time till session GC */
PMA_commonParams.get('session_gc_maxlifetime')
);
var interval = 1000;
if (remaining > 5) {
// max value for setInterval() function
var interval = Math.min(remaining * 1000, Math.pow(2, 31) - 1);
updateTimeout = window.setTimeout(UpdateIdleTime, interval);
} else if (remaining > 0) {
// We're close to session expiry
updateTimeout = window.setTimeout(UpdateIdleTime, 2000);
interval = Math.min((remaining - 1) * 1000, Math.pow(2, 31) - 1);
}
updateTimeout = window.setTimeout(UpdateIdleTime, interval);
} else { //timeout occurred
if(isStorageSupported('sessionStorage')){
clearInterval(IncInterval);
if (isStorageSupported('sessionStorage')){
window.sessionStorage.clear();
}
window.location.reload(true);
clearInterval(IncInterval);
}
}
});
}
if (PMA_commonParams.get('logged_in') && PMA_commonParams.get('auth_type') == 'cookie') {
if (PMA_commonParams.get('logged_in')) {
IncInterval = window.setInterval(SetIdleTime, 1000);
var interval = (PMA_commonParams.get('LoginCookieValidity') - 5) * 1000;
var session_timeout = Math.min(
PMA_commonParams.get('LoginCookieValidity'),
PMA_commonParams.get('session_gc_maxlifetime')
);
if (isStorageSupported('sessionStorage')) {
window.sessionStorage.setItem('guid', guid());
}
var interval = (session_timeout - 5) * 1000;
if (interval > Math.pow(2, 31) - 1) { // max value for setInterval() function
interval = Math.pow(2, 31) - 1;
}
@ -974,7 +1023,7 @@ AJAX.registerOnload('functions.js', function () {
last_click_checked = checked;
// remember the last clicked row
last_clicked_row = last_click_checked ? $table.find('tr.odd:not(.noclick), tr.even:not(.noclick)').index($tr) : -1;
last_clicked_row = last_click_checked ? $table.find('tr:not(.noclick)').index($tr) : -1;
last_shift_clicked_row = -1;
} else {
// handle the shift click
@ -990,7 +1039,7 @@ AJAX.registerOnload('functions.js', function () {
start = last_shift_clicked_row;
end = last_clicked_row;
}
$tr.parent().find('tr.odd:not(.noclick), tr.even:not(.noclick)')
$tr.parent().find('tr:not(.noclick)')
.slice(start, end + 1)
.removeClass('marked')
.find(':checkbox')
@ -999,7 +1048,7 @@ AJAX.registerOnload('functions.js', function () {
}
// handle new shift click
var curr_row = $table.find('tr.odd:not(.noclick), tr.even:not(.noclick)').index($tr);
var curr_row = $table.find('tr:not(.noclick)').index($tr);
if (curr_row >= last_clicked_row) {
start = last_clicked_row;
end = curr_row;
@ -1007,7 +1056,7 @@ AJAX.registerOnload('functions.js', function () {
start = curr_row;
end = last_clicked_row;
}
$tr.parent().find('tr.odd:not(.noclick), tr.even:not(.noclick)')
$tr.parent().find('tr:not(.noclick)')
.slice(start, end + 1)
.addClass('marked')
.find(':checkbox')
@ -1034,7 +1083,7 @@ AJAX.registerOnload('functions.js', function () {
* so that it works also for pages reached via AJAX)
*/
/*AJAX.registerOnload('functions.js', function () {
$(document).on('hover', 'tr.odd, tr.even',function (event) {
$(document).on('hover', 'tr',function (event) {
var $tr = $(this);
$tr.toggleClass('hover',event.type=='mouseover');
$tr.children().toggleClass('hover',event.type=='mouseover');
@ -1860,7 +1909,6 @@ AJAX.registerOnload('functions.js', function () {
});
$(document).on('click', "input#sql_query_edit_save", function () {
$(".success").hide();
//hide already existing success message
var sql_query;
if (codemirror_inline_editor) {
@ -1881,6 +1929,7 @@ AJAX.registerOnload('functions.js', function () {
if (! checkSqlQuery($fake_form[0])) {
return false;
}
$(".success").hide();
$fake_form.appendTo($('body')).submit();
});
@ -1946,7 +1995,7 @@ function codemirrorAutocompleteOnInputRead(instance) {
data: params,
success: function (data) {
if (data.success) {
var tables = $.parseJSON(data.tables);
var tables = JSON.parse(data.tables);
sql_autocomplete_default_table = PMA_commonParams.get('table');
sql_autocomplete = [];
for (var table in tables) {
@ -2036,7 +2085,7 @@ function bindCodeMirrorToInlineEditor() {
function catchKeypressesFromSqlInlineEdit(event) {
// ctrl-enter is 10 in chrome and ie, but 13 in ff
if (event.ctrlKey && (event.keyCode == 13 || event.keyCode == 10)) {
if ((event.ctrlKey || event.metaKey) && (event.keyCode == 13 || event.keyCode == 10)) {
$("#sql_query_edit_save").trigger('click');
}
}
@ -2214,11 +2263,17 @@ function PMA_updateCode($base, htmlValue, rawValue)
* @param mixed timeout number of milliseconds for the message to be visible
* optional, defaults to 5000. If set to 'false', the
* notification will never disappear
* @param string type string to dictate the type of message shown.
* optional, defaults to normal notification.
* If set to 'error', the notification will show message
* with red background.
* If set to 'success', the notification will show with
* a green background.
* @return jQuery object jQuery Element that holds the message div
* this object can be passed to PMA_ajaxRemoveMessage()
* to remove the notification
*/
function PMA_ajaxShowMessage(message, timeout)
function PMA_ajaxShowMessage(message, timeout, type)
{
/**
* @var self_closing Whether the notification will automatically disappear
@ -2249,6 +2304,12 @@ function PMA_ajaxShowMessage(message, timeout)
} else if (timeout === false) {
self_closing = false;
}
// Determine type of message, add styling as required
if (type === "error") {
message = "<div class=\"error\">" + message + "</div>";
} else if (type === "success") {
message = "<div class=\"success\">" + message + "</div>";
}
// Create a parent element for the AJAX messages, if necessary
if ($('#loading_parent').length === 0) {
$('<div id="loading_parent"></div>')
@ -2738,7 +2799,6 @@ jQuery.fn.PMA_confirm = function (question, url, callbackFn, openCallback) {
/**
* jQuery function to sort a table's body after a new row has been appended to it.
* Also fixes the even/odd classes of the table rows at the end.
*
* @param string text_selector string to select the sortKey's text
*
@ -2777,13 +2837,6 @@ jQuery.fn.PMA_sort_table = function (text_selector) {
$(table_body).append(row);
row.sortKey = null;
});
//Re-check the classes of each row
$(this).find('tr:odd')
.removeClass('even').addClass('odd')
.end()
.find('tr:even')
.removeClass('odd').addClass('even');
});
};
@ -2974,7 +3027,7 @@ AJAX.registerOnload('functions.js', function () {
}
});
$("input[value=AUTO_INCREMENT]").change(function(){
$(document).on('change', "input[value=AUTO_INCREMENT]", function() {
if (this.checked) {
var col = /\d/.exec($(this).attr('name'));
col = col[0];
@ -3162,6 +3215,10 @@ AJAX.registerOnload('functions.js', function () {
return;
}
if (data._scripts) {
AJAX.scriptHandler.load(data._scripts);
}
$('<div id="change_password_dialog"></div>')
.dialog({
title: PMA_messages.strChangePassword,
@ -3178,7 +3235,6 @@ AJAX.registerOnload('functions.js', function () {
.find("legend").remove().end()
.find("table.noclick").unwrap().addClass("some-margin")
.find("input#text_pma_pw").focus();
displayPasswordGenerateButton();
$('#fieldset_change_password_footer').hide();
PMA_ajaxRemoveMessage($msgbox);
$('#change_password_form').bind('submit', function (e) {
@ -3508,7 +3564,7 @@ AJAX.registerOnload('functions.js', function () {
url: href,
data: params,
success: function (data) {
central_column_list[db + '_' + table] = $.parseJSON(data.message);
central_column_list[db + '_' + table] = JSON.parse(data.message);
},
async:false
});
@ -4037,7 +4093,9 @@ var toggleButton = function ($obj) {
removeClass = 'off';
addClass = 'on';
}
$.post(url, {'ajax_request': true}, function (data) {
var params = {'ajax_request': true, 'token': PMA_commonParams.get('token')};
$.post(url, params, function (data) {
if (typeof data !== 'undefined' && data.success === true) {
PMA_ajaxRemoveMessage($msg);
$container
@ -4164,6 +4222,8 @@ AJAX.registerOnload('functions.js', function () {
favorite_tables: (isStorageSupported('localStorage') && typeof window.localStorage.favorite_tables !== 'undefined')
? window.localStorage.favorite_tables
: '',
token: PMA_commonParams.get('token'),
server: PMA_commonParams.get('server'),
no_debug: true
},
success: function (data) {
@ -4581,7 +4641,7 @@ function copyToClipboard()
});
textArea.value += '\n';
elementList = $('tbody .odd,tbody .even');
elementList = $('tbody tr');
elementList.each(function() {
var childElementList = $(this).find('.data span');
childElementList.each(function(){
@ -4615,6 +4675,16 @@ AJAX.registerTeardown('functions.js', function () {
AJAX.registerOnload('functions.js', function () {
$('input#print').click(printPage);
$('.logout').click(function() {
var form = $(
'<form method="POST" action="' + $(this).attr('href') + '" class="disableAjax">' +
'<input type="hidden" name="token" value="' + PMA_commonParams.get('token') + '"/>' +
'</form>'
);
$('body').append(form);
form.submit();
return false;
});
/**
* Ajaxification for the "Create View" action
*/
@ -4786,22 +4856,6 @@ $(document).on("change", "input.sub_checkall_box", function () {
.parents("tr").toggleClass("marked", is_checked);
});
/**
* Toggles row colors of a set of 'tr' elements starting from a given element
*
* @param $start Starting element
*/
function toggleRowColors($start)
{
for (var $curr_row = $start; $curr_row.length > 0; $curr_row = $curr_row.next()) {
if ($curr_row.hasClass('odd')) {
$curr_row.removeClass('odd').addClass('even');
} else if ($curr_row.hasClass('even')) {
$curr_row.removeClass('even').addClass('odd');
}
}
}
/**
* Formats a byte number to human-readable form
*

View File

@ -6,34 +6,34 @@
*
* @package PhpMyAdmin
*/
chdir('..');
// Send correct type:
header('Content-Type: text/javascript; charset=UTF-8');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT');
if (!defined('TESTSUITE')) {
chdir('..');
// Avoid loading the full common.inc.php because this would add many
// non-js-compatible stuff like DOCTYPE
define('PMA_MINIMUM_COMMON', true);
define('PMA_PATH_TO_BASEDIR', '../');
require_once './libraries/common.inc.php';
// Send correct type:
header('Content-Type: text/javascript; charset=UTF-8');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT');
// Avoid loading the full common.inc.php because this would add many
// non-js-compatible stuff like DOCTYPE
define('PMA_MINIMUM_COMMON', true);
define('PMA_PATH_TO_BASEDIR', '../');
require_once './libraries/common.inc.php';
}
$buffer = PMA\libraries\OutputBuffering::getInstance();
$buffer->start();
register_shutdown_function(
function () {
echo PMA\libraries\OutputBuffering::getInstance()->getContents();
}
);
if (!defined('TESTSUITE')) {
register_shutdown_function(
function () {
echo PMA\libraries\OutputBuffering::getInstance()->getContents();
}
);
}
// Get the data for the sprites, if it's available
if (is_readable($_SESSION['PMA_Theme']->getPath() . '/sprites.lib.php')) {
include $_SESSION['PMA_Theme']->getPath() . '/sprites.lib.php';
}
$sprites = array();
if (function_exists('PMA_sprites')) {
$sprites = PMA_sprites();
}
$sprites = $_SESSION['PMA_Theme']->getSpriteData();
// We only need the keys from the array of sprites data,
// since they contain the (partial) class names
$keys = array();

View File

@ -7,33 +7,37 @@
* @package PhpMyAdmin
*/
chdir('..');
if (!defined('TESTSUITE')) {
chdir('..');
// Close session early as we won't write anything there
session_write_close();
// Close session early as we won't write anything there
session_write_close();
// Send correct type
header('Content-Type: text/javascript; charset=UTF-8');
// Enable browser cache for 1 hour
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT');
// Send correct type
header('Content-Type: text/javascript; charset=UTF-8');
// Enable browser cache for 1 hour
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT');
// When a token is not presented, even though whitelisted arrays are removed
// in PMA_removeRequestVars(). This is a workaround for that.
$_GET['scripts'] = json_encode($_GET['scripts']);
// When a token is not presented, even though whitelisted arrays are removed
// in PMA_removeRequestVars(). This is a workaround for that.
$_GET['scripts'] = json_encode($_GET['scripts']);
// Avoid loading the full common.inc.php because this would add many
// non-js-compatible stuff like DOCTYPE
define('PMA_MINIMUM_COMMON', true);
define('PMA_PATH_TO_BASEDIR', '../');
require_once './libraries/common.inc.php';
// Avoid loading the full common.inc.php because this would add many
// non-js-compatible stuff like DOCTYPE
define('PMA_MINIMUM_COMMON', true);
define('PMA_PATH_TO_BASEDIR', '../');
require_once './libraries/common.inc.php';
}
$buffer = PMA\libraries\OutputBuffering::getInstance();
$buffer->start();
register_shutdown_function(
function () {
echo PMA\libraries\OutputBuffering::getInstance()->getContents();
}
);
if (!defined('TESTSUITE')) {
register_shutdown_function(
function () {
echo PMA\libraries\OutputBuffering::getInstance()->getContents();
}
);
}
$_GET['scripts'] = json_decode($_GET['scripts']);
if (! empty($_GET['scripts']) && is_array($_GET['scripts'])) {
@ -43,7 +47,7 @@ if (! empty($_GET['scripts']) && is_array($_GET['scripts'])) {
$script_name = 'js';
$path = explode("/", $script);
foreach ($path as $index => $filename) {
foreach ($path as $filename) {
// Allow alphanumeric, "." and "-" chars only, no files starting
// with .
if (preg_match("@^[\w][\w\.-]+$@", $filename)) {

Some files were not shown because too many files have changed in this diff Show More