[Phpmyadmin-git] [SCM] phpMyAdmin branch, master, updated. RELEASE_3_3_5_1-7256-g82acbb2

Marc Delisle lem9 at users.sourceforge.net
Sat Aug 21 13:54:00 CEST 2010


The branch, master has been updated
       via  82acbb2ba3c9aed9f934650575666920e2fd9bab (commit)
       via  a5417a0ce7ebc603871360d0b391881280c8536d (commit)
       via  e3446960163f00125b516712c720a178093f46f2 (commit)
       via  b8cee3086bb34bc231b62c6884bb3192c2046595 (commit)
       via  98cbab04113cac9de1aa8aea07dd92d8ae7f03b7 (commit)
       via  97c939f8df0ae8e2ccd1357c78e2dfeda2383fad (commit)
       via  e6170b2dc211a19d43ff4e4f6d17f8598b2d6905 (commit)
       via  bcaec734418959fb0ce5e60a25ccddfa7cc75cb6 (commit)
       via  4c39f5012e14f3c08e8da67dc05ca445d7a6b2f9 (commit)
       via  60329f14cbc865e5c312602529966e128a0402da (commit)
       via  f7c3ea158aaad28aea233fb859403d3db27812c3 (commit)
       via  9d4c5409c608af3900dd4f8889b69e17666dfbd5 (commit)
       via  5dc9f17d39e9766333dc11bf3208678abce18080 (commit)
       via  a6b34a5977fd68e7da5e4703dbff487fbb579e5b (commit)
       via  8b78fcec2696efa1fc0dbf2f501e8fea02b79c71 (commit)
       via  1d265c58936ba3cbf2378566182104f6340a458b (commit)
       via  4c430acc7175165a82f31a8051e493bd1da4a690 (commit)
       via  4a5ffa7a12c687b46346be9052a3d2fdaeecebee (commit)
       via  e3f6715c44cf5923a8b9e6e68c8c362c69feaeef (commit)
       via  53e8d75c0f9a2713cdee01d7075930a045b6dde5 (commit)
       via  279724d6f85f0fe3eb4bb59665e7f01ce8d1b593 (commit)
       via  9a733070032a5f00f368c85450e8000fa5e02aca (commit)
       via  30413def3ef24a4ce11d1426030ad1f14f2fbca7 (commit)
       via  e76b4f8721528b3530e92e025845a6557bb94b06 (commit)
       via  23d74c9996853164f2f7b707336e70dd334599a0 (commit)
       via  dcc352a9dce00acc50b919521deaae314c048fd4 (commit)
       via  7f75e7515fbd03a031ffcd35167147f2f51adc0b (commit)
       via  157c4fb775783486b980075aba0982b69a77eab3 (commit)
       via  9adc2597c5e94c42979c45aef46700b318ef0384 (commit)
       via  5a3ec082d80402d96f0288697b700f5ff9f19b7b (commit)
       via  ac3e9e323b3f33ec5804862943e63ab2e10f4a93 (commit)
       via  65e0676ab4836603343951cf6b455e4d7756cfb5 (commit)
       via  9d62971e110d26d15909b91d02c066435699dbcd (commit)
       via  edaf7ce86c10bafdf1eb554ed03910ec7b7be691 (commit)
       via  b2674e9d59c6670feb26be1ecb0d9b51f3889a3d (commit)
       via  812748a50d622ef30aca0d44cb022d4676708698 (commit)
       via  7db978de3fd4ae2543190dd3f61eb58beeaaa21e (commit)
       via  8d24baad94ce2b358d62e6ebb57296192b90af04 (commit)
       via  b39567f38183b05c9a1c7511782ea148ba1c892e (commit)
       via  5afd385f307759f6e7d5e4460ecf630390ff5d63 (commit)
       via  2d67cb58c42193308ace1cace3e463ff19c5714f (commit)
       via  2e55d85ab5adff22e6c766b2c857fd60a62416cd (commit)
       via  c8b6acdf59b9c18d94abcbb58af216683bf23658 (commit)
       via  7399ce3e6137742af746cbc08389a3e29e186a13 (commit)
       via  7ac7e24d8cc97cb3c0234b0058661770c0d0f44c (commit)
       via  7b0135ed6a4dea645c5c18859cb6f08906504153 (commit)
       via  600bdbd57ea7fd974381323c99d5a5abd92a50df (commit)
       via  cc9b5c9028d04234b033377631b0bdcf4695f09a (commit)
       via  43a7629da9bdc90910833915aac5df92d1ddea32 (commit)
       via  a8ed8e61233ff0b6517b901160e99689ad7a92fd (commit)
       via  c0ba57f040b78736a351701a549a3f7b33157020 (commit)
       via  fab6eb09ea605c6be550a80a49f9f1aee87820de (commit)
       via  52550eff13b6dca702539946fbdd1ac12e80f107 (commit)
       via  c67340d023eaeb147e0b28155a55db64c8e1598a (commit)
       via  8c28b69aba4d630feff0ba2e8c291bdcea158251 (commit)
       via  4376f6ce14cf264a8cfd5ef529d8dc6b7947a31f (commit)
       via  cf99d6511ffd6abe85c77b64b0182b23f2a8bf59 (commit)
       via  b71edb53806b7bb2867db6ab391a11a7e91ccade (commit)
       via  a7fe3f362c3cb81ca04922049725af6242921438 (commit)
       via  afca401bc8677482585b6eca60e7ceda0804c68b (commit)
       via  c5bef4d2dafb5535a83c9aad4dad7cc933a3e7dc (commit)
       via  0b30a339fa24a2f03db8f9f4149f01019f74ce82 (commit)
       via  995fcba961442a209a7b087c3e532aeb8f0720b3 (commit)
       via  7a5fd6281078b234c665e64cea968641c4aceec0 (commit)
       via  60285cd6650e055b999c05e23cdca101b829036d (commit)
       via  030abc511430327aedd764e1486e9c5bb24efbda (commit)
       via  e7dd9a7c678f5b680dcaa93f7bf337e058df4677 (commit)
       via  57a8d902f4016b8b4e6d5f8cf866c54a4ba93f96 (commit)
       via  b3ae73f2aa53072a85fccd24f0debcc094ab0813 (commit)
       via  74eb921e68335c1a4a928251767814d6b478b6b3 (commit)
       via  625b9edca8c8451e5aa4ed7f532af217f800065c (commit)
       via  956315e0b2e06a90544f721763894708b427bb66 (commit)
       via  e6b551dc7176e94989291647ab728218ea71c5f1 (commit)
       via  3137cc2f1d1e18a14c0dce9b63d34472f781dd49 (commit)
       via  bcaecbf10a4cf84b38b14a776ce02911c6e13725 (commit)
       via  5717683ef16e7d35a0991e93bbf0459b0f1dfa4f (commit)
       via  104ac11c1d2184a15a5cd7ae2a521728fe73b5b2 (commit)
       via  104b40cb11ff09d3cf65e2848c61606863448a34 (commit)
       via  54c322544cbd774ff7858cdff0644f6f7b3250f1 (commit)
       via  a9f39a92e7331a0a71e6da1b60987fd4d964375a (commit)
       via  93d49e8ca860cd92b643e5257fc7e41075558cee (commit)
       via  68d9c401138e184575ad30bb4cae9f5e5be9d11a (commit)
       via  d63fa35c0f4147859370adbda34fbb27c811634d (commit)
       via  9dc47ecc41865486a595cbc300451600137fb255 (commit)
       via  7c5a298f271260e47ee690c11eec3c37c1f08b43 (commit)
       via  47cd7c9a20071fe527b5dd06f9ab69340593fe5e (commit)
       via  a3d46e16e2891fc766cda9dd85aff6df8c5746ca (commit)
       via  2fab9fbf28a26cb59ecd8d14a0181ab4773bd245 (commit)
       via  9130ebb7b64f0a5d010e8af92b04a8cf006cccbf (commit)
       via  49c2562eaeb563b4cb2fe156f9ddc17211036d3c (commit)
       via  b13dee72f389bfda1eb3769e8d0abb54239fc057 (commit)
       via  83f1397f0f612191759bfe9f82b8b9369be15a5a (commit)
       via  c91c105da82609b81c28e002ae278d61ce019b24 (commit)
       via  e842432c7ec268f9cf1780995281a8db7de5490e (commit)
       via  e5238f384573ffe1e96a36314b811bf03822c665 (commit)
       via  d09c35f5a83da6753f6cb9efcbea453b6933ed55 (commit)
       via  0dc5d2e2b19bce4efd325c76544cef38d3d179f8 (commit)
       via  3a8de5a7162edde4c3dee33f1cb63bcb14137d25 (commit)
       via  b68ba42f9f3a9017b25d7ac6668543c4ccde108c (commit)
       via  9f44d864b6763682b858f6d9ff03401d8c236a28 (commit)
       via  f920e44af4f640a3170759adcfadc62d167c7f3c (commit)
       via  d68f2db90463d3d93be96a8531505706aae5618e (commit)
       via  114869eb7a3d8b74f0c3ad4827dac6807335ab34 (commit)
       via  3ff76ffcf52b07a788f081f3f1f12f59d5e64bcb (commit)
       via  b2e232b582c4245da4ac76b9b4cd853a8b899500 (commit)
       via  02bb83cad3121b9ce9f9e66f3b11e9e3ca950e4a (commit)
       via  c7b304b6e62cdcd331c0cdc8aa4f884644f0f085 (commit)
       via  eb31291dcaa405c93089e4d11f0d644aadf7bd9c (commit)
       via  ca9c13c80cfed1cd96d27076c76f0fc2fac0b7ad (commit)
       via  3b3f8bff6978d05d01afb79eb0fbad6b2b41ea97 (commit)
       via  a90b0a21f242bb552451118e5f0101345d1cdb15 (commit)
       via  2e1fd2677fffa08315e277bd39626531d0701931 (commit)
       via  b2ecf178038524b7b245e6c507118eb6ad432a31 (commit)
       via  082604eed3c0241c68ef157f5f2379826585f1b5 (commit)
       via  4572e3ec8220b53a62a40e0d90747baaac013135 (commit)
       via  03e66cd0d419947f3fcd617e4412e2e53179472b (commit)
       via  3ed35399589e18a6b3bec155d4f7bd74047a9c7a (commit)
       via  65911c57e1cfffefbbdd2e86b3f0d2e1204c80b4 (commit)
       via  6b2f774ba83a856eb39040059a1d2ed78645aa4b (commit)
       via  65863ae2292b6a6cb16d82516a3922f2b00e9dfe (commit)
       via  101bbeefb60f8eb4bee5a9a692cab305ecc8336f (commit)
       via  0f540aca0404a43094f552ccbc576db21749c9b2 (commit)
       via  7661627a76c721ab2ab39f6a4ca03227b41841b8 (commit)
      from  7be82362080f862de054c85646fb54b3bf6402b9 (commit)


- Log -----------------------------------------------------------------
commit 82acbb2ba3c9aed9f934650575666920e2fd9bab
Merge: 7be82362080f862de054c85646fb54b3bf6402b9 a5417a0ce7ebc603871360d0b391881280c8536d
Author: Marc Delisle <marc at infomarc.info>
Date:   Sat Aug 21 07:46:57 2010 -0400

    fix merge conflicts

commit a5417a0ce7ebc603871360d0b391881280c8536d
Author: Crack <piotrprz at gmail.com>
Date:   Thu Aug 19 20:35:49 2010 +0200

    add custom-no-form to Export/method

commit e3446960163f00125b516712c720a178093f46f2
Author: Crack <piotrprz at gmail.com>
Date:   Thu Aug 19 16:36:41 2010 +0200

    account for changes introduced when merging lori/gsoc branch

commit b8cee3086bb34bc231b62c6884bb3192c2046595
Merge: 98cbab04113cac9de1aa8aea07dd92d8ae7f03b7 772d80787ddead09cb5f00a45738ef48693ba5b4
Author: Crack <piotrprz at gmail.com>
Date:   Thu Aug 19 14:45:18 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin
    
    Conflicts:
    	js/functions.js
    	js/tooltip.js
    	libraries/config.default.php
    	libraries/config.values.php
    	libraries/display_export.lib.php
    	setup/lib/forms.inc.php
    	setup/lib/messages.inc.php
    	themes/darkblue_orange/css/theme_right.css.php
    	themes/original/css/theme_right.css.php

commit 98cbab04113cac9de1aa8aea07dd92d8ae7f03b7
Author: Crack <piotrprz at gmail.com>
Date:   Sun Aug 8 22:10:48 2010 +0200

    second part of error message display changes

commit 97c939f8df0ae8e2ccd1357c78e2dfeda2383fad
Merge: e6170b2dc211a19d43ff4e4f6d17f8598b2d6905 c24571f826c39dc7ff623d6392d0a49e7dfe02e3
Author: Crack <piotrprz at gmail.com>
Date:   Fri Aug 6 15:24:15 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin

commit e6170b2dc211a19d43ff4e4f6d17f8598b2d6905
Author: Crack <piotrprz at gmail.com>
Date:   Fri Aug 6 15:17:53 2010 +0200

    comments
    output escaping

commit bcaec734418959fb0ce5e60a25ccddfa7cc75cb6
Author: Crack <piotrprz at gmail.com>
Date:   Fri Aug 6 14:56:52 2010 +0200

    sort messages

commit 4c39f5012e14f3c08e8da67dc05ca445d7a6b2f9
Author: Crack <piotrprz at gmail.com>
Date:   Fri Aug 6 14:46:01 2010 +0200

    restore cache'ing in phpmyadmin.css.php

commit 60329f14cbc865e5c312602529966e128a0402da
Author: Crack <piotrprz at gmail.com>
Date:   Fri Aug 6 14:36:26 2010 +0200

    blacklist and settings debug code shown if $cfg['DBG']['php'] is true

commit f7c3ea158aaad28aea233fb859403d3db27812c3
Author: Crack <piotrprz at gmail.com>
Date:   Fri Aug 6 13:57:59 2010 +0200

    info about setup script in "manage your settings", it seems many people still don't know it exists

commit 9d4c5409c608af3900dd4f8889b69e17666dfbd5
Author: Crack <piotrprz at gmail.com>
Date:   Thu Aug 5 21:01:59 2010 +0200

    fix import merge
    fix <select> handling (hopefully this time for real)

commit 5dc9f17d39e9766333dc11bf3208678abce18080
Author: Crack <piotrprz at gmail.com>
Date:   Wed Aug 4 16:02:54 2010 +0200

    fix <select> value setting

commit a6b34a5977fd68e7da5e4703dbff487fbb579e5b
Author: Crack <piotrprz at gmail.com>
Date:   Wed Aug 4 15:27:47 2010 +0200

    fix generation of theme unique value
    refresh session cache for config after save

commit 8b78fcec2696efa1fc0dbf2f501e8fea02b79c71
Author: Crack <piotrprz at gmail.com>
Date:   Wed Aug 4 14:35:09 2010 +0200

    remove unneeded file

commit 1d265c58936ba3cbf2378566182104f6340a458b
Author: Crack <piotrprz at gmail.com>
Date:   Wed Aug 4 00:57:11 2010 +0200

    fix regular expression validation when phpMyAdmin custom error handler is set

commit 4c430acc7175165a82f31a8051e493bd1da4a690
Author: Crack <piotrprz at gmail.com>
Date:   Tue Aug 3 00:57:14 2010 +0200

    add missing .htaccess

commit 4a5ffa7a12c687b46346be9052a3d2fdaeecebee
Author: Crack <piotrprz at gmail.com>
Date:   Tue Aug 3 00:55:57 2010 +0200

    File comments:
    - remove @license and @version from comments
    - add vim settings
    - change descriptions in form definition files

commit e3f6715c44cf5923a8b9e6e68c8c362c69feaeef
Author: Crack <piotrprz at gmail.com>
Date:   Tue Aug 3 00:37:39 2010 +0200

    bugfix: use true/false for boolean values read from <select>s instead of 1/0

commit 53e8d75c0f9a2713cdee01d7075930a045b6dde5
Merge: 279724d6f85f0fe3eb4bb59665e7f01ce8d1b593 887e2be664f04827fe164d724d233598a251bcb9
Author: Crack <piotrprz at gmail.com>
Date:   Sun Aug 1 23:19:21 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin
    
    Conflicts:
    	libraries/db_links.inc.php
    	libraries/tbl_links.inc.php

commit 279724d6f85f0fe3eb4bb59665e7f01ce8d1b593
Author: Crack <piotrprz at gmail.com>
Date:   Sun Aug 1 22:52:15 2010 +0200

    bugfix: user preferences don't work correctly without output buffering

commit 9a733070032a5f00f368c85450e8000fa5e02aca
Author: Crack <piotrprz at gmail.com>
Date:   Sun Aug 1 21:55:04 2010 +0200

    allow users to set only_db and hide_db

commit 30413def3ef24a4ce11d1426030ad1f14f2fbca7
Author: Crack <piotrprz at gmail.com>
Date:   Sun Aug 1 21:46:33 2010 +0200

    bugfix: removed superfluous ob_end_clean() which caused page rendering to fail when OBGzip was enabled

commit e76b4f8721528b3530e92e025845a6557bb94b06
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 31 21:54:38 2010 +0200

    fix array definition code

commit 23d74c9996853164f2f7b707336e70dd334599a0
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jul 30 20:31:47 2010 +0200

    fix config download from index.php in setup script

commit dcc352a9dce00acc50b919521deaae314c048fd4
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jul 30 20:25:22 2010 +0200

    refactor config file generation out of ConfigFile class

commit 7f75e7515fbd03a031ffcd35167147f2f51adc0b
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jul 30 19:45:53 2010 +0200

    improve formatting in generated config file

commit 157c4fb775783486b980075aba0982b69a77eab3
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jul 30 19:44:59 2010 +0200

    fixed some fields not saving due to equality conversions (eg. 0 == 'auto')
    fix user preferences menu display when tabs don't fit on screen

commit 9adc2597c5e94c42979c45aef46700b318ef0384
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jul 30 00:47:20 2010 +0200

    short comments for inputs:
    - information whether SQL validator is enabled for Validate link
    - information about required extensions (SOAP, compression)
    - information for constrained values (eg. MaxDbList)

commit 5a3ec082d80402d96f0288697b700f5ff9f19b7b
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jul 27 23:15:23 2010 +0200

    fix user preferences in phpmyadmin.css.php
    fix css for LightTabs
    fix values in <select> lists

commit ac3e9e323b3f33ec5804862943e63ab2e10f4a93
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jul 27 22:12:53 2010 +0200

    keep selected tab after save
    change pmadb to phpMyAdmin configuration storage in warning string

commit 65e0676ab4836603343951cf6b455e4d7756cfb5
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jul 27 19:45:01 2010 +0200

    remove SQL Validator from user preferences

commit 9d62971e110d26d15909b91d02c066435699dbcd
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jul 26 22:34:13 2010 +0200

    clean up config JavaScript

commit edaf7ce86c10bafdf1eb554ed03910ec7b7be691
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jul 26 21:30:57 2010 +0200

    translate "More" tab
    cleanup code

commit b2674e9d59c6670feb26be1ecb0d9b51f3889a3d
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jul 26 20:56:19 2010 +0200

    change tab order in server, db and table menus

commit 812748a50d622ef30aca0d44cb022d4676708698
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jul 26 20:34:31 2010 +0200

    Changes to conform to latest merge:
    - use require instead if require_once for footer.inc.php
    - rename pmadb to phpMyAdmin configuration storage

commit 7db978de3fd4ae2543190dd3f61eb58beeaaa21e
Merge: 8d24baad94ce2b358d62e6ebb57296192b90af04 41bc587ed4494d21e7b69647a1235d2ca405c8ea
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jul 26 20:24:57 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin
    
    Conflicts:
    	libraries/config.values.php

commit 8d24baad94ce2b358d62e6ebb57296192b90af04
Author: Crack <piotrprz at gmail.com>
Date:   Sun Jul 25 22:58:52 2010 +0200

    run submenu code only when #topmenu is present
    todo update

commit b39567f38183b05c9a1c7511782ea148ba1c892e
Author: Crack <piotrprz at gmail.com>
Date:   Sun Jul 25 22:58:14 2010 +0200

    revert disable/* options

commit 5afd385f307759f6e7d5e4460ecf630390ff5d63
Author: Crack <piotrprz at gmail.com>
Date:   Sun Jul 25 22:10:38 2010 +0200

    create menu for menu tabs which don't fit in one line
    fix tooltip.js error when not in pma frame

commit 2d67cb58c42193308ace1cace3e463ff19c5714f
Merge: 2e55d85ab5adff22e6c766b2c857fd60a62416cd 084c0dbcf51dea488d99b7bfffffa23832ace4f3
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 24 18:34:52 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin
    
    Conflicts:
    	libraries/relation.lib.php

commit 2e55d85ab5adff22e6c766b2c857fd60a62416cd
Author: Crack <piotrprz at gmail.com>
Date:   Thu Jul 22 20:04:16 2010 +0200

    Developers tab no longer depends on UserprefsDisallow, introduced UserprefsDeveloperTab setting

commit c8b6acdf59b9c18d94abcbb58af216683bf23658
Author: Crack <piotrprz at gmail.com>
Date:   Thu Jul 22 17:02:17 2010 +0200

    remove debug
    use proper function to cancel event

commit 7399ce3e6137742af746cbc08389a3e29e186a13
Author: Crack <piotrprz at gmail.com>
Date:   Thu Jul 22 12:37:51 2010 +0200

    a few changes on preferences manage page
    fix JS date generation on preferences export to localStorage

commit 7ac7e24d8cc97cb3c0234b0058661770c0d0f44c
Author: Crack <piotrprz at gmail.com>
Date:   Thu Jul 22 01:29:36 2010 +0200

    more styling for disabled options
    new "Developer" tab (by default all options are disabled, users can't modify them)
    fixed UserprefsDisallow export in setup script

commit 7b0135ed6a4dea645c5c18859cb6f08906504153
Author: Crack <piotrprz at gmail.com>
Date:   Wed Jul 21 16:11:02 2010 +0200

    fix port number validation
    correct naming mistake (authentication != authorization)
    setup script: move server authentication settings to new tab

commit 600bdbd57ea7fd974381323c99d5a5abd92a50df
Author: Crack <piotrprz at gmail.com>
Date:   Wed Jul 21 14:01:53 2010 +0200

    Setup script: AllowThirdPartyFraming
    User preferences and setup script: new tab - Warnings, with options to disable mcrypt, Suhosin and pmadb warnings

commit cc9b5c9028d04234b033377631b0bdcf4695f09a
Author: Crack <piotrprz at gmail.com>
Date:   Wed Jul 21 01:21:32 2010 +0200

    mark fields that user can disable in setup script

commit 43a7629da9bdc90910833915aac5df92d1ddea32
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jul 20 21:57:05 2010 +0200

    Users can disable: AllowUserDropDatabase, UseDbSearch, QueryHistoryDB, ShowPhpInfo, ShowChgPassword
    Users can change: QueryHistoryMax (must be lower than value from file config)

commit a8ed8e61233ff0b6517b901160e99689ad7a92fd
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jul 20 16:36:22 2010 +0200

    SQL Validator forms

commit c0ba57f040b78736a351701a549a3f7b33157020
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jul 20 12:42:18 2010 +0200

    add config options for charset in Import and Export

commit fab6eb09ea605c6be550a80a49f9f1aee87820de
Merge: 52550eff13b6dca702539946fbdd1ac12e80f107 79a23fcd01ee2bd7ca2f5e5cb89bc993492597fa
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jul 20 12:30:03 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin

commit 52550eff13b6dca702539946fbdd1ac12e80f107
Merge: c67340d023eaeb147e0b28155a55db64c8e1598a d7192b3a95bbaef2fccbd34ab57accb077085b4d
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jul 20 12:19:21 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin
    
    Resolved conflicts:
    	setup/lib/forms.inc.php
    	setup/lib/messages.inc.php

commit c67340d023eaeb147e0b28155a55db64c8e1598a
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jul 19 23:57:12 2010 +0200

    save lang and collation_connection to user preferences

commit 8c28b69aba4d630feff0ba2e8c291bdcea158251
Merge: 4376f6ce14cf264a8cfd5ef529d8dc6b7947a31f d0106c29edc5eba444c984f74fabad51639b9315
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jul 19 16:16:12 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin

commit 4376f6ce14cf264a8cfd5ef529d8dc6b7947a31f
Merge: cf99d6511ffd6abe85c77b64b0182b23f2a8bf59 e0d1e92336a43b0b2997ff11f15957156cbb35f4
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jul 19 16:04:50 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin

commit cf99d6511ffd6abe85c77b64b0182b23f2a8bf59
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 17 22:43:38 2010 +0200

    fix restore-default not showing after page load
    setup script comments for fields that set constraints on user preferences (MaxDbLost, MaxTableList)

commit b71edb53806b7bb2867db6ab391a11a7e91ccade
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 17 14:23:15 2010 +0200

    add missing @uses comments

commit a7fe3f362c3cb81ca04922049725af6242921438
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 17 14:02:19 2010 +0200

    allow multiple validators for one field
    users can set MaxDbList and MaxTableList, values are bounded by the original value

commit afca401bc8677482585b6eca60e7ceda0804c68b
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 17 11:39:30 2010 +0200

    parametrized validators
    valdiation by regular expressions
    shorter text fields for numeric inputs

commit c5bef4d2dafb5535a83c9aad4dad7cc933a3e7dc
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jul 16 20:28:11 2010 +0200

    fix "restore default" button, should be visible only when field has custom value
    added missing validations for setup script
    added two field descriptions
    added SkipLockedTables to user preferences

commit 0b30a339fa24a2f03db8f9f4149f01019f74ce82
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jul 16 11:30:51 2010 +0200

    css for Darkblue/orange

commit 995fcba961442a209a7b087c3e532aeb8f0720b3
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jul 16 11:30:21 2010 +0200

    fix theme changing

commit 7a5fd6281078b234c665e64cea968641c4aceec0
Author: Crack <piotrprz at gmail.com>
Date:   Wed Jul 14 21:28:24 2010 +0200

    allow users to easily work with preferences stored in session (when pmadb is disabled): after logging in, user is presented with a message asking whether settings from localStorage should be loaded

commit 60285cd6650e055b999c05e23cdca101b829036d
Author: Crack <piotrprz at gmail.com>
Date:   Wed Jul 14 17:07:19 2010 +0200

    add missing string escapes
    don't create <a> tag if LeftLogoLink is empty

commit 030abc511430327aedd764e1486e9c5bb24efbda
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jul 13 23:15:22 2010 +0200

    add missing validation for TextareaRows
    fix warning in FormDisplay while importing settings

commit e7dd9a7c678f5b680dcaa93f7bf337e058df4677
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jul 13 22:59:21 2010 +0200

    allow to partially import broken configs - show message with error list and import only correct values

commit 57a8d902f4016b8b4e6d5f8cf866c54a4ba93f96
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jul 13 22:17:19 2010 +0200

    fix ThemeDefault and fontsize export

commit b3ae73f2aa53072a85fccd24f0debcc094ab0813
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jul 12 19:24:07 2010 +0200

    ui fixes

commit 74eb921e68335c1a4a928251767814d6b478b6b3
Merge: 625b9edca8c8451e5aa4ed7f532af217f800065c ce2cad288666f2bfd71dc21ae8e0277288834657
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jul 12 14:04:16 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin

commit 625b9edca8c8451e5aa4ed7f532af217f800065c
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jul 12 14:02:45 2010 +0200

    show message when preferences are saved to localStorage

commit 956315e0b2e06a90544f721763894708b427bb66
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 10 21:51:54 2010 +0200

    bugfix: show warning only when pmadb is unavailable

commit e6b551dc7176e94989291647ab728218ea71c5f1
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 10 12:09:34 2010 +0200

    bugfixes: allow to work with multiple servers, fix boolean values in select fields

commit 3137cc2f1d1e18a14c0dce9b63d34472f781dd49
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 10 00:06:50 2010 +0200

    add date information when importing from localStorage

commit bcaecbf10a4cf84b38b14a776ce02911c6e13725
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jul 9 20:37:04 2010 +0200

    allow user preferences to work without pmadb, but warn users about that

commit 5717683ef16e7d35a0991e93bbf0459b0f1dfa4f
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jul 9 19:37:49 2010 +0200

    basic import/export for localStorage, needs to be polished

commit 104ac11c1d2184a15a5cd7ae2a521728fe73b5b2
Author: Crack <piotrprz at gmail.com>
Date:   Thu Jul 8 19:01:09 2010 +0200

    import and export for user preferences (currently JSON file only)
    add preferences reset

commit 104b40cb11ff09d3cf65e2848c61606863448a34
Author: Crack <piotrprz at gmail.com>
Date:   Thu Jul 8 12:36:09 2010 +0200

    rename file

commit 54c322544cbd774ff7858cdff0644f6f7b3250f1
Author: Crack <piotrprz at gmail.com>
Date:   Wed Jul 7 01:27:05 2010 +0200

    move user preferences to top level server menu

commit a9f39a92e7331a0a71e6da1b60987fd4d964375a
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jul 6 18:20:33 2010 +0200

    saving of theme and font size

commit 93d49e8ca860cd92b643e5257fc7e41075558cee
Merge: 68d9c401138e184575ad30bb4cae9f5e5be9d11a 3e9e18aebb5d551f260e178f2f311384c2653b28
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jul 5 19:37:03 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin

commit 68d9c401138e184575ad30bb4cae9f5e5be9d11a
Author: Crack <piotrprz at gmail.com>
Date:   Sun Jul 4 21:56:46 2010 +0200

    moved Import by LOAD DATA settings to CSV category
    moved PMA_array_* functions to core.lib.php
    moved PMA_read_userprefs_fieldnames() to user_preferences.lib.php
    server/database/table filename templates are saved to pmadb when "remember template" is checked

commit d63fa35c0f4147859370adbda34fbb27c811634d
Author: Crack <piotrprz at gmail.com>
Date:   Sun Jul 4 00:18:04 2010 +0200

    finished messages.inc.php cleanup

commit 9dc47ecc41865486a595cbc300451600137fb255
Author: Crack <piotrprz at gmail.com>
Date:   Sun Jul 4 00:04:55 2010 +0200

    rename $strSetup* variables to $strConfig*

commit 7c5a298f271260e47ee690c11eec3c37c1f08b43
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 3 23:27:02 2010 +0200

    moved validate.lib.php

commit 47cd7c9a20071fe527b5dd06f9ab69340593fe5e
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 3 23:22:20 2010 +0200

    styling
    moved some options (SQL Queries and SQL Box forms)

commit a3d46e16e2891fc766cda9dd85aff6df8c5746ca
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 3 22:50:06 2010 +0200

    sort messages

commit 2fab9fbf28a26cb59ecd8d14a0181ab4773bd245
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 3 22:45:14 2010 +0200

    Export options

commit 9130ebb7b64f0a5d010e8af92b04a8cf006cccbf
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 3 19:02:54 2010 +0200

    allow to group fields in forms

commit 49c2562eaeb563b4cb2fe156f9ddc17211036d3c
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jul 3 13:45:48 2010 +0200

    more flexible <select> declaration
    fix array export in ConfigFile

commit b13dee72f389bfda1eb3769e8d0abb54239fc057
Author: Crack <piotrprz at gmail.com>
Date:   Thu Jul 1 22:24:18 2010 +0200

    Import settings

commit 83f1397f0f612191759bfe9f82b8b9369be15a5a
Merge: c91c105da82609b81c28e002ae278d61ce019b24 4986ee01742944b1c648cdcac0360cff653c12f8
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jun 28 16:42:29 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin

commit c91c105da82609b81c28e002ae278d61ce019b24
Author: Crack <piotrprz at gmail.com>
Date:   Sun Jun 27 12:43:54 2010 +0200

    added missing file

commit e842432c7ec268f9cf1780995281a8db7de5490e
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jun 26 01:04:17 2010 +0200

    User preferences:
    - add icons to category tabs
    - user overrides were unavailable in CSS files
    - apply saved configuration immediately after save, reload navigation frame if it's affected
    - disabled overrides marked in user preferences forms

commit e5238f384573ffe1e96a36314b811bf03822c665
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jun 21 19:12:25 2010 +0200

    add $cfg['UserprefsDisallow'] and allow setting it in setup script
    correct IE opacity issue for "restore default value" button
    fix regressions introduced in previous commit

commit d09c35f5a83da6753f6cb9efcbea453b6933ed55
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jun 21 18:46:23 2010 +0200

    setup script - better config file generation

commit 0dc5d2e2b19bce4efd325c76544cef38d3d179f8
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jun 21 16:24:34 2010 +0200

    markers for field errors

commit 3a8de5a7162edde4c3dee33f1cb63bcb14137d25
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jun 21 15:24:07 2010 +0200

    make form definition structure the same for setup script and user preferences

commit b68ba42f9f3a9017b25d7ac6668543c4ccde108c
Author: Crack <piotrprz at gmail.com>
Date:   Mon Jun 21 01:05:45 2010 +0200

    Better error handling

commit 9f44d864b6763682b858f6d9ff03401d8c236a28
Author: Crack <piotrprz at gmail.com>
Date:   Sun Jun 20 21:34:13 2010 +0200

    user preferences saving and integration

commit f920e44af4f640a3170759adcfadc62d167c7f3c
Merge: d68f2db90463d3d93be96a8531505706aae5618e 7f77f618d9effc18e1563e5be56a22a206a8a436
Author: Crack <piotrprz at gmail.com>
Date:   Sun Jun 20 18:45:41 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin

commit d68f2db90463d3d93be96a8531505706aae5618e
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jun 18 20:22:34 2010 +0200

    add warnings if pma_userconfig is not present

commit 114869eb7a3d8b74f0c3ad4827dac6807335ab34
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jun 18 19:36:00 2010 +0200

    updated paths

commit 3ff76ffcf52b07a788f081f3f1f12f59d5e64bcb
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jun 18 19:33:24 2010 +0200

    moved forms definition files

commit b2e232b582c4245da4ac76b9b4cd853a8b899500
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jun 18 17:53:53 2010 +0200

    Added pmadb table for preferences storage
    Removed some messages from messages.inc.php

commit 02bb83cad3121b9ce9f9e66f3b11e9e3ca950e4a
Author: Crack <piotrprz at gmail.com>
Date:   Wed Jun 16 23:54:57 2010 +0200

    add new settings to setup script

commit c7b304b6e62cdcd331c0cdc8aa4f884644f0f085
Author: Crack <piotrprz at gmail.com>
Date:   Wed Jun 16 23:54:35 2010 +0200

    improve js validators
    add missing validations and language strings

commit eb31291dcaa405c93089e4d11f0d644aadf7bd9c
Author: Crack <piotrprz at gmail.com>
Date:   Wed Jun 16 23:50:44 2010 +0200

    docs typo

commit ca9c13c80cfed1cd96d27076c76f0fc2fac0b7ad
Merge: 3b3f8bff6978d05d01afb79eb0fbad6b2b41ea97 0963eb36edc3e902ae12899ca306b5ce057136f3
Author: Crack <piotrprz at gmail.com>
Date:   Wed Jun 16 13:02:14 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin

commit 3b3f8bff6978d05d01afb79eb0fbad6b2b41ea97
Merge: a90b0a21f242bb552451118e5f0101345d1cdb15 f1d89536703373c41b888b68414a55ec9642e9ef
Author: Crack <piotrprz at gmail.com>
Date:   Sun Jun 13 15:03:58 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin

commit a90b0a21f242bb552451118e5f0101345d1cdb15
Author: Crack <piotrprz at gmail.com>
Date:   Sun Jun 13 15:01:37 2010 +0200

    removed some messages from messages.inc.php (validation, some other error messages)
    
    User preferences:
    added translations and values for some fields
    validation for DefaultPropDisplay

commit 2e1fd2677fffa08315e277bd39626531d0701931
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jun 12 23:48:07 2010 +0200

    Configuration forms styling

commit b2ecf178038524b7b245e6c507118eb6ad432a31
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jun 12 12:42:29 2010 +0200

    Split setup/scripts.js into generic and setup script specific parts

commit 082604eed3c0241c68ef157f5f2379826585f1b5
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jun 11 23:42:36 2010 +0200

    Fixed JSDoc

commit 4572e3ec8220b53a62a40e0d90747baaac013135
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jun 11 22:00:52 2010 +0200

    Fix paths in config templates

commit 03e66cd0d419947f3fcd617e4412e2e53179472b
Author: Crack <piotrprz at gmail.com>
Date:   Fri Jun 11 17:11:15 2010 +0200

    Display forms

commit 3ed35399589e18a6b3bec155d4f7bd74047a9c7a
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jun 5 19:25:54 2010 +0200

    Setup script refactoring: moved ConfigFile, Form, FormDisplay
    Config db overrides and validation info stored in config.values.php

commit 65911c57e1cfffefbbdd2e86b3f0d2e1204c80b4
Merge: 6b2f774ba83a856eb39040059a1d2ed78645aa4b f50d6694e79bb1f8268e44123e8b6935f10a365a
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jun 5 16:59:16 2010 +0200

    Merge branch 'master' of ssh://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin

commit 6b2f774ba83a856eb39040059a1d2ed78645aa4b
Author: Crack <piotrprz at gmail.com>
Date:   Sat Jun 5 15:42:55 2010 +0200

    Add category tabs to preferences page
    Setup script refactoring

commit 65863ae2292b6a6cb16d82516a3922f2b00e9dfe
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jun 1 14:33:02 2010 +0200

    List of fields to add, divided into categories

commit 101bbeefb60f8eb4bee5a9a692cab305ecc8336f
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jun 1 14:32:10 2010 +0200

    link to user preferences on main page (not working yet)

commit 0f540aca0404a43094f552ccbc576db21749c9b2
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jun 1 14:31:11 2010 +0200

    Setup script: moved LeftDefaultTabTable, added MainPageIconic

commit 7661627a76c721ab2ab39f6a4ca03227b41841b8
Author: Crack <piotrprz at gmail.com>
Date:   Tue Jun 1 14:24:15 2010 +0200

    doc fix

-----------------------------------------------------------------------

Summary of changes:
 .gitignore                                         |    1 +
 Documentation.html                                 |   31 +-
 config.sample.inc.php                              |    1 +
 export.php                                         |    9 +-
 setup/scripts.js => js/config.js                   |  559 ++++++++++---------
 js/functions.js                                    |   98 ++++-
 js/messages.php                                    |    3 +
 libraries/Config.class.php                         |  187 ++++++-
 libraries/common.inc.php                           |    3 +
 libraries/common.lib.php                           |    4 +-
 libraries/config.default.php                       |   77 +++-
 libraries/config.values.php                        |  189 +++++++
 libraries/config/ConfigFile.class.php              |  486 ++++++++++++++++
 {setup/lib => libraries/config}/Form.class.php     |   80 ++-
 .../lib => libraries/config}/FormDisplay.class.php |  305 +++++++++--
 libraries/config/FormDisplay.tpl.php               |  429 ++++++++++++++
 libraries/config/config_functions.lib.php          |  100 ++++
 libraries/config/messages.inc.php                  |  498 +++++++++++++++++
 libraries/config/setup.forms.php                   |  368 ++++++++++++
 libraries/config/user_preferences.forms.php        |  268 +++++++++
 {setup/lib => libraries/config}/validate.lib.php   |  177 +++++--
 libraries/core.lib.php                             |   85 +++
 libraries/db_links.inc.php                         |   14 +-
 libraries/display_export.lib.php                   |   26 +-
 libraries/export/sql.php                           |    2 +-
 libraries/footer.inc.php                           |    8 +
 libraries/header.inc.php                           |   14 +
 libraries/header_meta_style.inc.php                |    2 +-
 libraries/header_scripts.inc.php                   |    2 +-
 libraries/navigation_header.inc.php                |   34 +-
 libraries/relation.lib.php                         |   13 +-
 libraries/server_links.inc.php                     |   50 +-
 libraries/tbl_links.inc.php                        |   14 +-
 libraries/user_preferences.inc.php                 |   72 +++
 libraries/user_preferences.lib.php                 |  316 +++++++++++
 main.php                                           |    8 +
 prefs_forms.php                                    |   89 +++
 prefs_manage.php                                   |  337 +++++++++++
 scripts/create_tables.sql                          |   15 +
 scripts/find_unused_messages.sh                    |    2 +-
 setup/config.php                                   |   22 +-
 {libraries => setup/frames}/.htaccess              |    0
 setup/frames/config.inc.php                        |   10 +-
 setup/frames/form.inc.php                          |   35 +-
 setup/frames/index.inc.php                         |   21 +-
 setup/frames/menu.inc.php                          |   15 +-
 setup/frames/servers.inc.php                       |   20 +-
 setup/index.php                                    |    2 +-
 setup/lib/ConfigFile.class.php                     |  322 -----------
 setup/lib/ConfigGenerator.class.php                |  151 +++++
 setup/lib/FormDisplay.tpl.php                      |  293 ----------
 setup/lib/common.inc.php                           |  220 +-------
 setup/lib/config_info.inc.php                      |  144 -----
 setup/lib/form_processing.lib.php                  |   13 +-
 setup/lib/forms.inc.php                            |  183 ------
 setup/lib/index.lib.php                            |  147 +++---
 setup/lib/messages.inc.php                         |  381 -------------
 setup/scripts.js                                   |  586 +-------------------
 setup/styles.css                                   |   66 ++-
 setup/validate.php                                 |   10 +-
 themes/darkblue_orange/css/theme_right.css.php     |  334 +++++++++++-
 themes/darkblue_orange/img/b_more.png              |  Bin 0 -> 963 bytes
 themes/original/css/theme_right.css.php            |  343 +++++++++++-
 themes/original/img/b_more.png                     |  Bin 0 -> 1005 bytes
 64 files changed, 5521 insertions(+), 2773 deletions(-)
 copy setup/scripts.js => js/config.js (57%)
 create mode 100644 libraries/config.values.php
 create mode 100644 libraries/config/ConfigFile.class.php
 rename {setup/lib => libraries/config}/Form.class.php (67%)
 rename {setup/lib => libraries/config}/FormDisplay.class.php (61%)
 create mode 100644 libraries/config/FormDisplay.tpl.php
 create mode 100644 libraries/config/config_functions.lib.php
 create mode 100644 libraries/config/messages.inc.php
 create mode 100644 libraries/config/setup.forms.php
 create mode 100644 libraries/config/user_preferences.forms.php
 rename {setup/lib => libraries/config}/validate.lib.php (62%)
 create mode 100644 libraries/user_preferences.inc.php
 create mode 100644 libraries/user_preferences.lib.php
 create mode 100644 prefs_forms.php
 create mode 100644 prefs_manage.php
 copy {libraries => setup/frames}/.htaccess (100%)
 delete mode 100644 setup/lib/ConfigFile.class.php
 create mode 100644 setup/lib/ConfigGenerator.class.php
 delete mode 100644 setup/lib/FormDisplay.tpl.php
 delete mode 100644 setup/lib/config_info.inc.php
 delete mode 100644 setup/lib/forms.inc.php
 delete mode 100644 setup/lib/messages.inc.php
 create mode 100644 themes/darkblue_orange/img/b_more.png
 create mode 100644 themes/original/img/b_more.png

diff --git a/.gitignore b/.gitignore
index 3e12f7d..a773f8e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,7 @@ phpmyadmin.wpj
 .settings
 .buildpath
 .cache
+.idea
 *.sw[op]
 # Locales
 locale
diff --git a/Documentation.html b/Documentation.html
index a782847..7077d2a 100644
--- a/Documentation.html
+++ b/Documentation.html
@@ -1139,6 +1139,26 @@ CREATE DATABASE,ALTER DATABASE,DROP DATABASE</pre>
         <br/><br/>
     </dd>
 
+    <dt id="userconfig">
+        <span id="cfg_Servers_userconfig">$cfg['Servers'][$i]['userconfig']</span> string
+    </dt>
+    <dd>
+        Since release 3.4.x phpMyAdmin allows users to set most preferences by themselves
+        and store them in the database.
+        <br /><br />
+
+        If you don't allow for storing preferences in <a href="#pmadb">pmadb</a>, users can
+        still personalize phpMyAdmin, but settings will be saved in browser's local storage,
+        or, it is is unavailable, until the end of session.
+        <br /><br />
+
+        To allow the usage of this functionality:
+
+        <ul>
+            <li>set up <a href="#pmadb">pmadb</a> and the linked-tables infrastructure</li>
+            <li>put the table name in <tt>$cfg['Servers'][$i]['userconfig']</tt></li>
+        </ul>
+    </dd>
 
     <dt id="designer_coords">
         <span id="cfg_Servers_designer_coords">$cfg['Servers'][$i]['designer_coords']</span> string
@@ -1183,7 +1203,7 @@ CREATE DATABASE,ALTER DATABASE,DROP DATABASE</pre>
         <span id="cfg_Servers_AllowDeny_order">$cfg['Servers'][$i]['AllowDeny']['order']</span> string
     </dt>
     <dd>If your rule order is empty, then <abbr title="Internet Protocol">IP</abbr>
-        authentication is disabled.<br /><br />
+        authorization is disabled.<br /><br />
 
         If your rule order is set to <tt>'deny,allow'</tt> then the system applies
         all deny rules followed by allow rules. Access is allowed by default. Any
@@ -1195,7 +1215,7 @@ CREATE DATABASE,ALTER DATABASE,DROP DATABASE</pre>
         default.  Any client which does not match an Allow directive or does
         match a Deny directive will be denied access to the server.<br /><br />
 
-        If your rule order is set to 'explicit', the authentication is
+        If your rule order is set to 'explicit', authorization is
         performed in a similar fashion to rule order 'deny,allow', with the
         added restriction that your host/username combination <b>must</b> be
         listed in the <i>allow</i> rules, and not listed in the <i>deny</i>
@@ -2153,6 +2173,11 @@ setfacl -d -m "g:www-data:rwx" tmp
     closed state. A value of <tt>'open'</tt> does the reverse. To completely 
     disable all visual sliders, use <tt>'disabled'</tt>.</dd>
 
+    <dt id="cfg_UserprefsDisallow">$cfg['UserprefsDisallow'] array</dt>
+    <dd>Contains names of configuration options (keys in <tt>$cfg</tt> array)
+        that users can't set through user preferences. For possible values, refer
+        to <tt>libraries/config/user_preferences.forms.php</tt>.</dd>
+
     <dt id="cfg_TitleTable">$cfg['TitleTable'] string</dt>
     <dt id="cfg_TitleDatabase">$cfg['TitleDatabase'] string</dt>
     <dt id="cfg_TitleServer">$cfg['TitleServer'] string</dt>
@@ -3483,7 +3508,7 @@ have either the <a href="http://pecl.php.net/package/APC">APC</a> extension
 <h4 id="faq3_15">
     <a href="#faq3_15">3.15 When I import an Excel spreadsheet, some cells with calculations do not display correctly.</a></h4>
 <p>
-    phpMyAdmin uses the <a href="http://www.codeplex.com/PHPExcel/" target="_blank">PHPExcel</a> library to parse Excel XLS and XLSX spreadsheets. 
+    phpMyAdmin uses the <a href="http://www.codeplex.com/PHPExcel/">PHPExcel</a> library to parse Excel XLS and XLSX spreadsheets. 
     Therefore, any limitations that are listed on their page regarding Excel calculations will also apply here.
     <br /><br />
     PHPExcel will be kept up to date so as to make all improvements available to phpMyAdmin users.
diff --git a/config.sample.inc.php b/config.sample.inc.php
index da403fd..41f6466 100644
--- a/config.sample.inc.php
+++ b/config.sample.inc.php
@@ -49,6 +49,7 @@ $cfg['Servers'][$i]['AllowNoPassword'] = false;
 // $cfg['Servers'][$i]['history'] = 'pma_history';
 // $cfg['Servers'][$i]['tracking'] = 'pma_tracking';
 // $cfg['Servers'][$i]['designer_coords'] = 'pma_designer_coords';
+// $cfg['Servers'][$i]['userconfig'] = 'pma_userconfig';
 /* Contrib / Swekey authentication */
 // $cfg['Servers'][$i]['auth_swekey_config'] = '/etc/swekey-pma.conf';
 
diff --git a/export.php b/export.php
index 1a5d6e6..2615496 100644
--- a/export.php
+++ b/export.php
@@ -256,15 +256,18 @@ if ($asfile) {
     $pma_uri_parts = parse_url($cfg['PmaAbsoluteUri']);
     if ($export_type == 'server') {
         if (isset($remember_template)) {
-            $GLOBALS['PMA_Config']->setCookie('pma_server_filename_template', $filename_template);
+            $GLOBALS['PMA_Config']->setUserValue('pma_server_filename_template',
+                'Export/file_template_server', $filename_template);
         }
     } elseif ($export_type == 'database') {
         if (isset($remember_template)) {
-            $GLOBALS['PMA_Config']->setCookie('pma_db_filename_template', $filename_template);
+            $GLOBALS['PMA_Config']->setUserValue('pma_db_filename_template',
+                'Export/file_template_database', $filename_template);
         }
     } else {
         if (isset($remember_template)) {
-            $GLOBALS['PMA_Config']->setCookie('pma_table_filename_template', $filename_template);
+            $GLOBALS['PMA_Config']->setUserValue('pma_table_filename_template',
+                'Export/file_template_table', $filename_template);
         }
     }
     $filename = PMA_expandUserString($filename_template);
diff --git a/setup/scripts.js b/js/config.js
similarity index 57%
copy from setup/scripts.js
copy to js/config.js
index 7298e63..1b0cedd 100644
--- a/setup/scripts.js
+++ b/js/config.js
@@ -1,14 +1,7 @@
 /**
- * functions used in setup script
- * 
- * @version $Id$
+ * Functions used in configuration forms and on user preferences pages
  */
 
-// show this window in top frame
-if (top != self) {
-    window.top.location.href = location;
-}
-
 // default values for fields
 var defaultValues = {};
 
@@ -18,7 +11,7 @@ var PMA_messages = {};
 /**
  * Returns field type
  *
- * @param Element field
+ * @param {Element} field
  */
 function getFieldType(field) {
 	field = $(field);
@@ -42,9 +35,9 @@ function getFieldType(field) {
  * o boolean - if field_type is 'checkbox'
  * o Array of values - if field_type is 'select'
  *
- * @param Element field
- * @param String  field_type  see getFieldType
- * @param mixed   value
+ * @param {Element} field
+ * @param {String}  field_type  see {@link #getFieldType}
+ * @param {String|Boolean}  [value]
  */
 function setFieldValue(field, field_type, value) {
 	field = $(field);
@@ -80,9 +73,9 @@ function setFieldValue(field, field_type, value) {
  * o boolean - if type is 'checkbox'
  * o Array of values - if type is 'select'
  *
- * @param Element field
- * @param String  field_type  see getFieldType
- * @return mixed
+ * @param {Element} field
+ * @param {String}  field_type returned by {@link #getFieldType}
+ * @type Boolean|String|String[]
  */
 function getFieldValue(field, field_type) {
 	field = $(field);
@@ -101,6 +94,7 @@ function getFieldValue(field, field_type) {
             }
             return items;
     }
+    return null;
 }
 
 /**
@@ -127,8 +121,8 @@ function getAllValues() {
 /**
  * Checks whether field has its default value
  *
- * @param Element field
- * @param String  type
+ * @param {Element} field
+ * @param {String}  type
  * @return boolean
  */
 function checkFieldDefault(field, type) {
@@ -160,43 +154,13 @@ function checkFieldDefault(field, type) {
 
 /**
  * Returns element's id prefix
- * @param Element element
+ * @param {Element} element
  */
 function getIdPrefix(element) {
     return $(element).attr('id').replace(/[^-]+$/, '');
 }
 
 // ------------------------------------------------------------------
-// Messages
-//
-
-// stores hidden message ids
-var hiddenMessages = [];
-
-$(function() {
-    var hidden = hiddenMessages.length;
-    for (var i = 0; i < hidden; i++) {
-        $('#'+hiddenMessages[i]).css('display', 'none');
-    }
-    if (hidden > 0) {
-        var link = $('#show_hidden_messages');
-        link.click(function(e) {
-            e.preventDefault();
-            for (var i = 0; i < hidden; i++) {
-                $('#'+hiddenMessages[i]).show(500);
-            }
-            $(this).remove();
-        });
-        link.html(link.html().replace('#MSG_COUNT', hidden));
-        link.css('display', '');
-    }
-});
-
-//
-// END: Messages
-// ------------------------------------------------------------------
-
-// ------------------------------------------------------------------
 // Form validation and field operations
 //
 
@@ -206,171 +170,88 @@ var validate = {};
 // form validator list
 var validators = {
     // regexp: numeric value
-    _regexp_numeric: new RegExp('^[0-9]*$'),
+    _regexp_numeric: /^[0-9]+$/,
+    // regexp: extract parts from PCRE expression
+    _regexp_pcre_extract: /(.)(.*)\1(.*)?/,
     /**
      * Validates positive number
      *
-     * @param boolean isKeyUp
+     * @param {boolean} isKeyUp
      */
     validate_positive_number: function (isKeyUp) {
+        if (isKeyUp && this.value == '') {
+            return true;
+        }
         var result = this.value != '0' && validators._regexp_numeric.test(this.value);
         return result ? true : PMA_messages['error_nan_p'];
     },
     /**
      * Validates non-negative number
      *
-     * @param boolean isKeyUp
+     * @param {boolean} isKeyUp
      */
     validate_non_negative_number: function (isKeyUp) {
+        if (isKeyUp && this.value == '') {
+            return true;
+        }
         var result = validators._regexp_numeric.test(this.value);
         return result ? true : PMA_messages['error_nan_nneg'];
     },
     /**
      * Validates port number
      *
-     * @param boolean isKeyUp
+     * @param {boolean} isKeyUp
      */
     validate_port_number: function(isKeyUp) {
-        var result = validators._regexp_numeric.test(this.value) && this.value != '0';
-        if (!result || this.value > 65536) {
-            result = PMA_messages['error_incorrect_port'];
+        if (this.value == '') {
+            return true;
         }
-        return result;
+        var result = validators._regexp_numeric.test(this.value) && this.value != '0';
+        return result && this.value <= 65535 ? true : PMA_messages['error_incorrect_port'];
     },
-    // field validators
-    _field: {
-        /**
-         * hide_db field
-         *
-         * @param boolean isKeyUp
-         */
-        hide_db: function(isKeyUp) {
-            if (!isKeyUp && this.value != '') {
-                var data = {};
-                data[this.id] = this.value;
-                ajaxValidate(this, 'Servers/1/hide_db', data);
-            }
+    /**
+     * Validates value according to given regular expression
+     *
+     * @param {boolean} isKeyUp
+     * @param {string}  regexp
+     */
+    validate_by_regex: function(isKeyUp, regexp) {
+        if (isKeyUp && this.value == '') {
             return true;
-        },
-		/**
-         * TrustedProxies field
-         *
-         * @param boolean isKeyUp
-         */
-        TrustedProxies: function(isKeyUp) {
-            if (!isKeyUp && this.value != '') {
-                var data = {};
-                data[this.id] = this.value;
-                ajaxValidate(this, 'TrustedProxies', data);
-            }
+        }
+        // convert PCRE regexp
+        var parts = regexp.match(validators._regexp_pcre_extract);
+        var valid = this.value.match(new RegExp(parts[2], parts[3])) != null;
+        return valid ? true : PMA_messages['error_invalid_value'];
+    },
+    /**
+     * Validates upper bound for numeric inputs
+     *
+     * @param {boolean} isKeyUp
+     * @param {int} max_value
+     */
+    validate_upper_bound: function(isKeyUp, max_value) {
+        var val = parseInt(this.value);
+        if (isNaN(val)) {
             return true;
         }
+        return val <= max_value ? true : PMA_messages['error_value_lte'].replace('%s', max_value);
+    },
+    // field validators
+    _field: {
     },
     // fieldset validators
     _fieldset: {
-        /**
-         * Validates Server fieldset
-         *
-         * @param boolean isKeyUp
-         */
-        Server: function(isKeyUp) {
-            if (!isKeyUp) {
-                ajaxValidate(this, 'Server', getAllValues());
-            }
-            return true;
-        },
-        /**
-         * Validates Server_login_options fieldset
-         *
-         * @param boolean isKeyUp
-         */
-        Server_login_options: function(isKeyUp) {
-            return validators._fieldset.Server.apply(this, [isKeyUp]);
-        },
-        /**
-         * Validates Server_pmadb fieldset
-         *
-         * @param boolean isKeyUp
-         */
-        Server_pmadb: function(isKeyUp) {
-            if (isKeyUp) {
-                return true;
-            }
-
-            var prefix = getIdPrefix($(this).find('input'));
-            var pmadb_active = $('#' + prefix + 'pmadb').val() != '';
-            if (pmadb_active) {
-                ajaxValidate(this, 'Server_pmadb', getAllValues());
-            }
-
-            return true;
-        }
     }
 };
 
 /**
- * Calls server-side validation procedures
- *
- * @param Element parent  input field in <fieldset> or <fieldset>
- * @param String id       validator id
- * @param Object values   values hash (element_id: value)
- */
-function ajaxValidate(parent, id, values) {
-	parent = $(parent);
-    // ensure that parent is a fieldset
-    if (parent.attr('tagName') != 'FIELDSET') {
-        parent = parent.closest('fieldset');
-        if (parent.length == 0) {
-            return false;
-        }
-    }
- 
-    if (parent.data('ajax') != null) {
-    	parent.data('ajax').abort();
-    }
-
-    parent.data('ajax', $.ajax({
-        url: 'validate.php',
-        cache: false,
-        type: 'POST',
-        data: {
-            token: parent.closest('form').find('input[name=token]').val(),
-            id: id,
-            values: $.toJSON(values)
-        },
-        success: function(response) {
-            if (response == null) {
-                return;
-            }
-
-            var error = {};
-            if (typeof response != 'object') {
-                error[parent.id] = [response];
-            } else if (typeof response['error'] != 'undefined') {
-                error[parent.id] = [response['error']];
-            } else {
-                for (key in response) {
-                	var value = response[key];
-                    error[key] = jQuery.isArray(value) ? value : [value];
-                }
-            }
-            displayErrors(error);
-        },
-        complete: function() {
-            parent.removeData('ajax');
-        }
-    }));
-
-    return true;
-}
-
-/**
  * Registers validator for given field
  *
- * @param String  id       field id
- * @param String  type     validator (key in validators object)
- * @param boolean onKeyUp  whether fire on key up
- * @param mixed   params   validation function parameters
+ * @param {String}  id       field id
+ * @param {String}  type     validator (key in validators object)
+ * @param {boolean} onKeyUp  whether fire on key up
+ * @param {Array}   params   validation function parameters
  */
 function validateField(id, type, onKeyUp, params) {
     if (typeof validators[type] == 'undefined') {
@@ -385,9 +266,10 @@ function validateField(id, type, onKeyUp, params) {
 /**
  * Returns valdiation functions associated with form field
  *
- * @param  String  field_id     form field id
- * @param  boolean onKeyUpOnly  see validateField
- * @return Array  array of [function, paramseters to be passed to function]
+ * @param  {String}  field_id     form field id
+ * @param  {boolean} onKeyUpOnly  see validateField
+ * @type Array
+ * @return array of [function, paramseters to be passed to function]
  */
 function getFieldValidators(field_id, onKeyUpOnly) {
     // look for field bound validator
@@ -417,10 +299,10 @@ function getFieldValidators(field_id, onKeyUpOnly) {
  * WARNING: created DOM elements must be identical with the ones made by
  * display_input() in FormDisplay.tpl.php!
  *
- * @param Object  error list (key: field id, value: error array)
+ * @param {Object} error_list list of errors in the form {field id: error array}
  */
 function displayErrors(error_list) {
-    for (field_id in error_list) {
+    for (var field_id in error_list) {
         var errors = error_list[field_id];
         var field = $('#'+field_id);
         var isFieldset = field.attr('tagName') == 'FIELDSET';
@@ -433,6 +315,13 @@ function displayErrors(error_list) {
             return item != '';
         });
 
+        // CSS error class
+        if (!isFieldset) {
+            // checkboxes uses parent <span> for marking
+            var fieldMarker = (field.attr('type') == 'checkbox') ? field.parent() : field;
+            fieldMarker[errors.length ? 'addClass' : 'removeClass']('field-error');
+        }
+
         if (errors.length) {
             // if error container doesn't exist, create it
             if (errorCnt.length == 0) {
@@ -460,15 +349,15 @@ function displayErrors(error_list) {
 /**
  * Validates fieldset and puts errors in 'errors' object
  *
- * @param Element field
- * @param boolean isKeyUp
- * @param Object  errors
+ * @param {Element} fieldset
+ * @param {boolean} isKeyUp
+ * @param {Object}  errors
  */
 function validate_fieldset(fieldset, isKeyUp, errors) {
 	fieldset = $(fieldset);
     if (fieldset.length && typeof validators._fieldset[fieldset.attr('id')] != 'undefined') {
         var fieldset_errors = validators._fieldset[fieldset.attr('id')].apply(fieldset[0], [isKeyUp]);
-        for (field_id in fieldset_errors) {
+        for (var field_id in fieldset_errors) {
             if (typeof errors[field_id] == 'undefined') {
                 errors[field_id] = [];
             }
@@ -483,9 +372,9 @@ function validate_fieldset(fieldset, isKeyUp, errors) {
 /**
  * Validates form field and puts errors in 'errors' object
  *
- * @param Element field
- * @param boolean isKeyUp
- * @param Object  errors
+ * @param {Element} field
+ * @param {boolean} isKeyUp
+ * @param {Object}  errors
  */
 function validate_field(field, isKeyUp, errors) {
 	field = $(field);
@@ -493,7 +382,11 @@ function validate_field(field, isKeyUp, errors) {
     errors[field_id] = [];
     var functions = getFieldValidators(field_id, isKeyUp);
     for (var i = 0; i < functions.length; i++) {
-        var result = functions[i][0].apply(field[0], [isKeyUp, functions[i][1]]);
+        var args = functions[i][1] != null
+            ? functions[i][1].slice(0)
+            : [];
+        args.unshift(isKeyUp);
+        var result = functions[i][0].apply(field[0], args);
         if (result !== true) {
             if (typeof result == 'string') {
             	result = [result];
@@ -506,8 +399,8 @@ function validate_field(field, isKeyUp, errors) {
 /**
  * Validates form field and parent fieldset
  *
- * @param Element field
- * @param boolean isKeyUp
+ * @param {Element} field
+ * @param {boolean} isKeyUp
  */
 function validate_field_and_fieldset(field, isKeyUp) {
 	field = $(field);
@@ -520,7 +413,7 @@ function validate_field_and_fieldset(field, isKeyUp) {
 /**
  * Marks field depending on its value (system default or custom)
  *
- * @param Element field
+ * @param {Element} field
  */
 function markField(field) {
 	field = $(field);
@@ -536,12 +429,12 @@ function markField(field) {
 /**
  * Enables or disables the "restore default value" button
  *
- * @param Element field
- * @param bool    display
+ * @param {Element} field
+ * @param {boolean} display
  */
 function setRestoreDefaultBtn(field, display) {
-    var el = $(field).closest('td').find('.restore-default');
-    el.css('display', (el.css('display') ? '' : 'none'));
+    var el = $(field).closest('td').find('.restore-default img');
+    el[display ? 'show' : 'hide']();
 }
 
 $(function() {
@@ -565,7 +458,7 @@ $(function() {
         // disable textarea spellcheck
         if (tagName == 'TEXTAREA') {
         	el.attr('spellcheck', false);
-        }    	
+        }
     });
 
 	// check whether we've refreshed a page and browser remembered modified
@@ -581,7 +474,7 @@ $(function() {
 		$('fieldset').each(function(){
 			validate_fieldset(this, false, errors);
 		});
-		
+
 		displayErrors(errors);
 	} else if (check_page_refresh) {
 		check_page_refresh.val('1');
@@ -599,62 +492,43 @@ $(function() {
 /**
  * Sets active tab
  *
- * @param Element tab_link
+ * @param {String} tab_id
  */
-function setTab(tab_link) {
-    var tabs_menu = $(tab_link).closest('.tabs');
-
-    var links = tabs_menu.find('a');
-    var contents, link;
-    for (var i = 0, imax = links.length; i < imax; i++) {
-    	link = $(links[i]);
-        contents = $(link.attr('href'));
-        if (links[i] == tab_link) {
-        	link.addClass('active');
-            contents.css('display', 'block');
-        } else {
-            link.removeClass('active');
-            contents.css('display', 'none');
-        }
-    }
-    location.hash = 'tab_' + $(tab_link).attr('href').substr(1);
+function setTab(tab_id) {
+    $('.tabs a').removeClass('active').filter('[href=' + tab_id + ']').addClass('active');
+    $('.tabs_contents fieldset').hide().filter(tab_id).show();
+    location.hash = 'tab_' + tab_id.substr(1);
+    $('.config-form input[name=tab_hash]').val(location.hash);
 }
 
 $(function() {
     var tabs = $('.tabs');
-    var url_tab = location.hash.match(/^#tab_.+/)
-        ? $('a[href$="' + location.hash.substr(5) + '"]') : null;
-    if (url_tab) {
-        url_tab = url_tab[0];
+    if (!tabs.length) {
+        return;
     }
     // add tabs events and activate one tab (the first one or indicated by location hash)
-    for (var i = 0, imax = tabs.length; i < imax; i++) {
-        var links = $(tabs[i]).find('a');
-        var selected_tab = links[0];
-        for (var j = 0, jmax = links.length; j < jmax; j++) {
-            $(links[j]).click(function(e) {
-                e.preventDefault();
-                setTab(this);
-            });
-            if (links[j] == url_tab) {
-                selected_tab = links[j];
-            }
-        }
-        setTab(selected_tab);
-    }
+    tabs.find('a')
+        .click(function(e) {
+            e.preventDefault();
+            setTab($(this).attr('href'));
+        })
+        .filter(':first')
+        .addClass('active');
+    $('.tabs_contents fieldset').hide().filter(':first').show();
+
     // tab links handling, check each 200ms
     // (works with history in FF, further browser support here would be an overkill)
-    var prev_hash = location.hash;
-    setInterval(function() {
+    var prev_hash;
+    var tab_check_fnc = function() {
         if (location.hash != prev_hash) {
             prev_hash = location.hash;
-            var url_tab = location.hash.match(/^#tab_.+/)
-                ? $('a[href$="' + location.hash.substr(5) + '"]') : null;
-            if (url_tab) {
-                setTab(url_tab[0]);
+            if (location.hash.match(/^#tab_.+/) && $('#' + location.hash.substr(5)).length) {
+                setTab('#' + location.hash.substr(5));
             }
         }
-    }, 200);
+    };
+    tab_check_fnc();
+    setInterval(tab_check_fnc, 200);
 });
 
 //
@@ -666,7 +540,7 @@ $(function() {
 //
 
 $(function() {
-    $('input[type=button]').click(function(e) {
+    $('input[type=button][name=submit_reset]').click(function() {
         var fields = $(this).closest('fieldset').find('input, select, textarea');
         for (var i = 0, imax = fields.length; i < imax; i++) {
             setFieldValue(fields[i], getFieldType(fields[i]));
@@ -685,7 +559,7 @@ $(function() {
 /**
  * Restores field's default value
  *
- * @param String field_id
+ * @param {String} field_id
  */
 function restoreField(field_id) {
     var field = $('#'+field_id);
@@ -696,34 +570,179 @@ function restoreField(field_id) {
 }
 
 $(function() {
-    $('.restore-default, .set-value').each(function() {
-        var link = $(this);
-        link.css('opacity', 0.25);
-        if (!link.hasClass('restore-default')) {
-            // restore-default is handled by markField
-        	link.css('display', '');
-        }
-        link.bind({
-            mouseenter: function() {$(this).css('opacity', 1);},
-            mouseleave: function() {$(this).css('opacity', 0.25);},
-            click: function(e) {
-                e.preventDefault();
-                var href = $(this).attr('href').substr(1);
-                var field_id;
-                if ($(this).hasClass('restore-default')) {
-                    field_id = href;
-                    restoreField(field_id);
-                } else {
-                    field_id = href.match(/^[^=]+/)[0];
-                    var value = href.match(/=(.+)$/)[1];
-                    setFieldValue($('#'+field_id), 'text', value);
-                }
-                $('#'+field_id).trigger('change');
+    $('.tabs_contents')
+        .delegate('.restore-default, .set-value', 'mouseenter', function(){$(this).css('opacity', 1)})
+        .delegate('.restore-default, .set-value', 'mouseleave', function(){$(this).css('opacity', 0.25)})
+        .delegate('.restore-default, .set-value', 'click', function(e) {
+            e.preventDefault();
+            var href = $(this).attr('href');
+            var field_sel;
+            if ($(this).hasClass('restore-default')) {
+                field_sel = href;
+                restoreField(field_sel.substr(1));
+            } else {
+                field_sel = href.match(/^[^=]+/)[0];
+                var value = href.match(/=(.+)$/)[1];
+                setFieldValue($(field_sel), 'text', value);
             }
-        });
-    });
+            $(field_sel).trigger('change');
+        })
+        .find('.restore-default, .set-value')
+        // inline-block for IE so opacity inheritance works
+        .css({display: 'inline-block', opacity: 0.25});
 });
 
 //
 // END: "Restore default" and "set value" buttons
 // ------------------------------------------------------------------
+
+// ------------------------------------------------------------------
+// User preferences import/export
+//
+
+$(function() {
+    offerPrefsAutoimport();
+    var radios = $('#import_local_storage, #export_local_storage');
+    if (!radios.length) {
+        return;
+    }
+
+    // enable JavaScript dependent fields
+    radios
+        .attr('disabled', false)
+        .add('#export_text_file, #import_text_file')
+        .click(function(){
+            var enable_id = $(this).attr('id');
+            var disable_id = enable_id.match(/local_storage$/)
+                ? enable_id.replace(/local_storage$/, 'text_file')
+                : enable_id.replace(/text_file$/, 'local_storage');
+            $('#opts_'+disable_id).addClass('disabled').find('input').attr('disabled', true);
+            $('#opts_'+enable_id).removeClass('disabled').find('input').attr('disabled', false);
+        });
+
+    // detect localStorage state
+    var ls_supported = window.localStorage || false;
+    var ls_exists = ls_supported ? (window.localStorage['config'] || false) : false;
+    $('.localStorage-'+(ls_supported ? 'un' : '')+'supported').hide();
+    $('.localStorage-'+(ls_exists ? 'empty' : 'exists')).hide();
+    if (ls_exists) {
+        updatePrefsDate();
+    }
+    $('form.prefs-form').change(function(){
+        var form = $(this);
+        var disabled = false;
+        if (!ls_supported) {
+            disabled = form.find('input[type=radio][value$=local_storage]').attr('checked');
+        } else if (!ls_exists && form.attr('name') == 'prefs_import'
+                && $('#import_local_storage')[0].checked) {
+            disabled = true;
+        }
+        form.find('input[type=submit]').attr('disabled', disabled);
+    }).submit(function(e) {
+        var form = $(this);
+        if (form.attr('name') == 'prefs_export' && $('#export_local_storage')[0].checked) {
+            e.preventDefault();
+            // use AJAX to read JSON settings and save them
+            savePrefsToLocalStorage(form);
+        } else if (form.attr('name') == 'prefs_import' && $('#import_local_storage')[0].checked) {
+            // set 'json' input and submit form
+            form.find('input[name=json]').val(window.localStorage['config']);
+        }
+    });
+
+    $('.click-hide-message').live('click', function(){
+        var div = $(this);
+        div.hide().parent('.group').css('height', '');
+        div.next('form').show();
+    });
+});
+
+/**
+ * Saves user preferences to localStorage
+ *
+ * @param {Element} form
+ */
+function savePrefsToLocalStorage(form)
+{
+    form = $(form);
+    var submit = form.find('input[type=submit]');
+    submit.attr('disabled', true);
+    $.ajax({
+        url: 'prefs_manage.php',
+        cache: false,
+        type: 'POST',
+        data: {
+            token: form.find('input[name=token]').val(),
+            submit_get_json: true
+        },
+        success: function(response) {
+            window.localStorage['config'] = response.prefs;
+            window.localStorage['config_mtime'] = response.mtime;
+            window.localStorage['config_mtime_local'] = (new Date()).toUTCString();
+            updatePrefsDate();
+            $('.localStorage-empty').hide();
+            $('.localStorage-exists').show();
+            var group = form.parent('.group');
+            group.css('height', group.height() + 'px');
+            form.hide('fast');
+            form.prev('.click-hide-message').show('fast');
+        },
+        complete: function() {
+            submit.attr('disabled', false);
+        }
+    });
+}
+
+/**
+ * Updates preferences timestamp in Import form
+ */
+function updatePrefsDate()
+{
+    var d = new Date(window.localStorage['config_mtime_local']);
+    var msg = PMA_messages['strSavedOn'].replace('__DATE__', formatDate(d));
+    $('#opts_import_local_storage .localStorage-exists').html(msg);
+}
+
+/**
+ * Returns date formatted as YYYY-MM-DD HH:II
+ *
+ * @param {Date} d
+ */
+function formatDate(d)
+{
+    return d.getFullYear() + '-'
+        + (d.getMonth() < 10 ? '0'+d.getMonth() : d.getMonth())
+        + '-' + (d.getDate() < 10 ? '0'+d.getDate() : d.getDate())
+        + ' ' + (d.getHours() < 10 ? '0'+d.getHours() : d.getHours())
+        + ':' + (d.getMinutes() < 10 ? '0'+d.getMinutes() : d.getMinutes());
+}
+
+/**
+ * Prepares message which informs that localStorage preferences are available and can be imported
+ */
+function offerPrefsAutoimport()
+{
+    var has_config = (window.localStorage || false) && (window.localStorage['config'] || false);
+    var cnt = $('#prefs_autoload');
+    if (!cnt.length || !has_config) {
+        return;
+    }
+    cnt.find('a').click(function(e) {
+        e.preventDefault();
+        var a = $(this);
+        if (a.attr('href') == '#no') {
+            cnt.remove();
+            $.post('main.php', {
+                token: cnt.find('input[name=token]').val(),
+                prefs_autoload: 'hide'});
+            return;
+        }
+        cnt.find('input[name=json]').val(window.localStorage['config']);
+        cnt.find('form').submit();
+    });
+    cnt.show();
+}
+
+//
+// END: User preferences import/export
+// ------------------------------------------------------------------
\ No newline at end of file
diff --git a/js/functions.js b/js/functions.js
index 2d57f3b..75ffee5 100644
--- a/js/functions.js
+++ b/js/functions.js
@@ -1893,4 +1893,100 @@ $(document).ready(function() {
             style: { background: '#ffffcc' }
         });
     });
-});
\ No newline at end of file
+});
+
+function menuResize()
+{
+    var cnt = $('#topmenu');
+    var wmax = cnt.width() - 5; // 5 px margin for jumping menu in Chrome
+    var submenu = cnt.find('.submenu');
+    var submenu_w = submenu.outerWidth(true);
+    var submenu_ul = submenu.find('ul');
+    var li = cnt.find('> li');
+    var li2 = submenu_ul.find('li');
+    var more_shown = li2.length > 0;
+    var w = more_shown ? submenu_w : 0;
+
+    // hide menu items
+    var hide_start = 0;
+    for (var i = 0; i < li.length-1; i++) { // li.length-1: skip .submenu element
+        var el = $(li[i]);
+        var el_width = el.outerWidth(true);
+        el.data('width', el_width);
+        w += el_width;
+        if (w > wmax) {
+            w -= el_width;
+            if (w + submenu_w < wmax) {
+                hide_start = i;
+            } else {
+                hide_start = i-1;
+                w -= $(li[i-1]).data('width');
+            }
+            break;
+        }
+    }
+
+    if (hide_start > 0) {
+        for (var i = hide_start; i < li.length-1; i++) {
+            $(li[i])[more_shown ? 'prependTo' : 'appendTo'](submenu_ul);
+        }
+        submenu.show();
+    } else if (more_shown) {
+        w -= submenu_w;
+        // nothing hidden, maybe something can be restored
+        for (var i = 0; i < li2.length; i++) {
+            //console.log(li2[i], submenu_w);
+            w += $(li2[i]).data('width');
+            // item fits or (it is the last item and it would fit if More got removed)
+            if (w+submenu_w < wmax || (i == li2.length-1 && w < wmax)) {
+                $(li2[i]).insertBefore(submenu);
+                if (i == li2.length-1) {
+                    submenu.hide();
+                }
+                continue;
+            }
+            break;
+        }
+    }
+    if (submenu.find('.tabactive').length) {
+        submenu.addClass('active').find('> a').removeClass('tab').addClass('tabactive');
+    } else {
+        submenu.removeClass('active').find('> a').addClass('tab').removeClass('tabactive');
+    }
+}
+
+$(function() {
+    var topmenu = $('#topmenu');
+    if (topmenu.length == 0) {
+        return;
+    }
+    // create submenu container
+    var link = $('<a />', {href: '#', 'class': 'tab'})
+        .text(PMA_messages['strMore'])
+        .click(function(e) {
+            e.preventDefault();
+        });
+    var img = topmenu.find('li:first-child img');
+    if (img.length) {
+        img.clone().attr('src', img.attr('src').replace(/\/[^\/]+$/, '/b_more.png')).prependTo(link);
+    }
+    var submenu = $('<li />', {'class': 'submenu'})
+        .append(link)
+        .append($('<ul />'))
+        .mouseenter(function() {
+            if ($(this).find('ul .tabactive').length == 0) {
+                $(this).addClass('submenuhover').find('> a').addClass('tabactive');
+            }
+        })
+        .mouseleave(function() {
+            if ($(this).find('ul .tabactive').length == 0) {
+                $(this).removeClass('submenuhover').find('> a').removeClass('tabactive');
+            }
+        })
+        .hide();
+    topmenu.append(submenu);
+
+    // populate submenu and register resize event
+    $(window).resize(menuResize);
+    menuResize();
+});
diff --git a/js/messages.php b/js/messages.php
index 4999002..94e1e67 100644
--- a/js/messages.php
+++ b/js/messages.php
@@ -66,6 +66,9 @@ $js_messages['strChangeDisplay'] = __('Choose column to display');
 $js_messages['strGeneratePassword'] = __('Generate password');
 $js_messages['strGenerate'] = __('Generate');
 
+/* navigation tabs */
+$js_messages['strMore'] = __('More');
+
 echo "var PMA_messages = new Array();\n";
 foreach ($js_messages as $name => $js_message) {
     PMA_printJsValue("PMA_messages['" . $name . "']", $js_message);
diff --git a/libraries/Config.class.php b/libraries/Config.class.php
index 7389b9f..16fe5a1 100644
--- a/libraries/Config.class.php
+++ b/libraries/Config.class.php
@@ -24,6 +24,11 @@ class PMA_Config
     var $default_source = './libraries/config.default.php';
 
     /**
+     * @var array   default configuration settings
+     */
+    var $default = array();
+
+    /**
      * @var array   configuration settings
      */
     var $settings = array();
@@ -320,6 +325,7 @@ class PMA_Config
         $this->default_server = $cfg['Servers'][1];
         unset($cfg['Servers']);
 
+        $this->default = $cfg;
         $this->settings = PMA_array_merge_recursive($this->settings, $cfg);
 
         $this->error_config_default_file = false;
@@ -409,6 +415,176 @@ class PMA_Config
     }
 
     /**
+     * Loads user preferences and merges them with current config
+     * must be called after control connection has been estabilished
+     *
+     * @uses $GLOBALS['cfg']
+     * @uses $GLOBALS['collation_connection']
+     * @uses $GLOBALS['lang']
+     * @uses $_SESSION['cache']['server_$server']['config_mtime']
+     * @uses $_SESSION['cache']['server_$server']['userprefs']
+     * @uses $_SESSION['cache']['server_$server']['userprefs_mtime']
+     * @uses $_SESSION['PMA_Theme_Manager']
+     * @uses PMA_apply_userprefs()
+     * @uses PMA_array_merge_recursive()
+     * @uses PMA_load_userprefs()
+     * @return boolean
+     */
+    function loadUserPreferences()
+    {
+        // index.php should load these settings, so that phpmyadmin.css.php
+        // will have everything avaiable in session cache
+        $server = isset($GLOBALS['server'])
+            ? $GLOBALS['server']
+            : (!empty($GLOBALS['cfg']['ServerDefault']) ? $GLOBALS['cfg']['ServerDefault'] : 0);
+        $cache_key = 'server_' . $server;
+        if ($server > 0 && !defined('PMA_MINIMUM_COMMON')) {
+            $config_mtime = max($this->default_source_mtime, $this->source_mtime);
+            // cache user preferences, use database only when needed
+            if (!isset($_SESSION['cache'][$cache_key]['userprefs'])
+                    || $_SESSION['cache'][$cache_key]['config_mtime'] < $config_mtime) {
+                // load required libraries
+                require_once './libraries/user_preferences.lib.php';
+                $prefs = PMA_load_userprefs();
+                $_SESSION['cache'][$cache_key]['userprefs'] = PMA_apply_userprefs($prefs['config_data']);
+                $_SESSION['cache'][$cache_key]['userprefs_mtime'] = $prefs['mtime'];
+                $_SESSION['cache'][$cache_key]['userprefs_type'] = $prefs['type'];
+                $_SESSION['cache'][$cache_key]['config_mtime'] = $config_mtime;
+            }
+        } else if ($server == 0 || !isset($_SESSION['cache'][$cache_key]['userprefs'])) {
+            $this->set('user_preferences', false);
+            return;
+        }
+        $config_data = $_SESSION['cache'][$cache_key]['userprefs'];
+        // type is 'db' or 'session'
+        $this->set('user_preferences', $_SESSION['cache'][$cache_key]['userprefs_type']);
+        $this->set('user_preferences_mtime', $_SESSION['cache'][$cache_key]['userprefs_mtime']);
+
+        // backup some settings
+        $org_fontsize = $this->settings['fontsize'];
+        // load config array
+        $this->settings = PMA_array_merge_recursive($this->settings, $config_data);
+        $GLOBALS['cfg'] = PMA_array_merge_recursive($GLOBALS['cfg'], $config_data);
+        if (defined('PMA_MINIMUM_COMMON')) {
+            return;
+        }
+
+        // settings below start really working on next page load, but
+        // changes are made only in index.php so everything is set when
+        // in frames
+
+        // save theme
+        $tmanager = $_SESSION['PMA_Theme_Manager'];
+        if ($tmanager->getThemeCookie() || isset($_REQUEST['set_theme'])) {
+            if ((!isset($config_data['ThemeDefault']) && $tmanager->theme->getId() != 'original')
+                    || isset($config_data['ThemeDefault']) && $config_data['ThemeDefault'] != $tmanager->theme->getId()) {
+                // new theme was set in common.inc.php
+                $this->setUserValue(null, 'ThemeDefault', $tmanager->theme->getId(), 'original');
+            }
+        } else {
+            // no cookie - read default from settings
+            if ($this->settings['ThemeDefault'] != $tmanager->theme->getId()
+                    && $tmanager->checkTheme($this->settings['ThemeDefault'])) {
+                $tmanager->setActiveTheme($this->settings['ThemeDefault']);
+                $tmanager->setThemeCookie();
+            }
+        }
+
+        // save font size
+        if ((!isset($config_data['fontsize']) && $org_fontsize != '82%')
+                || isset($config_data['fontsize']) && $org_fontsize != $config_data['fontsize']) {
+            $this->setUserValue(null, 'fontsize', $org_fontsize, '82%');
+        }
+
+        // save language
+        if (isset($_COOKIE['pma_lang']) || isset($_POST['lang'])) {
+            if ((!isset($config_data['lang']) && $GLOBALS['lang'] != 'en')
+                    || isset($config_data['lang']) && $GLOBALS['lang'] != $config_data['lang']) {
+                $this->setUserValue(null, 'lang', $GLOBALS['lang'], 'en');
+            }
+        } else {
+            // read language from settings
+            if (isset($config_data['lang']) && PMA_langSet($config_data['lang'])) {
+                $this->setCookie('pma_lang', $GLOBALS['lang']);
+            }
+        }
+
+        // save connection collation
+        if (isset($_COOKIE['pma_collation_connection']) || isset($_POST['collation_connection'])) {
+            if ((!isset($config_data['collation_connection']) && $GLOBALS['collation_connection'] != 'utf8_general_ci')
+                    || isset($config_data['collation_connection']) && $GLOBALS['collation_connection'] != $config_data['collation_connection']) {
+                $this->setUserValue(null, 'collation_connection', $GLOBALS['collation_connection'], 'utf8_general_ci');
+            }
+        } else {
+            // read collation from settings
+            if (isset($config_data['collation_connection'])) {
+                $GLOBALS['collation_connection'] = $config_data['collation_connection'];
+                $this->setCookie('pma_collation_connection', $GLOBALS['collation_connection']);
+            }
+        }
+    }
+
+    /**
+     * Sets config value which is stored in user preferences (if available) or in a cookie.
+     *
+     * If user preferences are not yet initialized, option is applied to global config and
+     * added to a update queue, which is processed by {@link loadUserPreferences()}
+     *
+     * @uses $GLOBALS['cfg']
+     * @uses PMA_array_read()
+     * @uses PMA_array_write()
+     * @uses PMA_persist_option()
+     * @param string $cookie_name can be null
+     * @param string $cfg_path
+     * @param mixed  $new_cfg_value
+     * @param mixed  $default_value
+     */
+    function setUserValue($cookie_name, $cfg_path, $new_cfg_value, $default_value = null)
+    {
+        // use permanent user preferences if possible
+        $prefs_type = $this->get('user_preferences');
+        if ($prefs_type) {
+            require_once './libraries/user_preferences.lib.php';
+            if ($default_value === null) {
+                $default_value = PMA_array_read($cfg_path, $this->default);
+            }
+            PMA_persist_option($cfg_path, $new_cfg_value, $default_value);
+        }
+        if ($prefs_type != 'db' && $cookie_name) {
+            // fall back to cookies
+            if ($default_value === null) {
+                $default_value = PMA_array_read($cfg_path, $this->settings);
+            }
+            $this->setCookie($cookie_name, $new_cfg_value, $default_value);
+        }
+        PMA_array_write($cfg_path, $GLOBALS['cfg'], $new_cfg_value);
+        PMA_array_write($cfg_path, $this->settings, $new_cfg_value);
+    }
+
+    /**
+     * Reads value stored by {@link setUserValue()}
+     *
+     * @param string $cookie_name
+     * @param mixed $cfg_value
+     * @return mixed
+     */
+    function getUserValue($cookie_name, $cfg_value)
+    {
+        $cookie_exists = isset($_COOKIE) && !empty($_COOKIE[$cookie_name]);
+        $prefs_type = $this->get('user_preferences');
+        if ($prefs_type == 'db') {
+            // permanent user preferences value exists, remove cookie
+            if ($cookie_exists) {
+                $this->removeCookie($cookie_name);
+            }
+        } else if ($cookie_exists) {
+            return $_COOKIE[$cookie_name];
+        }
+        // return value from $cfg array
+        return $cfg_value;
+    }
+
+    /**
      * set source
      * @param   string  $source
      */
@@ -537,6 +713,7 @@ class PMA_Config
             $fontsize +
             $this->source_mtime +
             $this->default_source_mtime +
+            $this->get('user_preferences_mtime') +
             $_SESSION['PMA_Theme']->mtime_info +
             $_SESSION['PMA_Theme']->filesize_info)
             . (isset($_SESSION['tmp_user_values']['custom_color']) ? substr($_SESSION['tmp_user_values']['custom_color'],1,6) : '');
@@ -726,10 +903,10 @@ class PMA_Config
     {
         $new_fontsize = '';
 
-        if (isset($_GET['fontsize'])) {
-            $new_fontsize = $_GET['fontsize'];
-        } elseif (isset($_POST['fontsize'])) {
-            $new_fontsize = $_POST['fontsize'];
+        if (isset($_GET['set_fontsize'])) {
+            $new_fontsize = $_GET['set_fontsize'];
+        } elseif (isset($_POST['set_fontsize'])) {
+            $new_fontsize = $_POST['set_fontsize'];
         } elseif (isset($_COOKIE['pma_fontsize'])) {
             $new_fontsize = $_COOKIE['pma_fontsize'];
         }
@@ -1011,7 +1188,7 @@ class PMA_Config
         $options = PMA_Config::_getFontsizeOptions($current_size);
 
         $return = '<label for="select_fontsize">' . __('Font size') . ':</label>' . "\n";
-        $return .= '<select name="fontsize" id="select_fontsize" onchange="this.form.submit();">' . "\n";
+        $return .= '<select name="set_fontsize" id="select_fontsize" onchange="this.form.submit();">' . "\n";
         foreach ($options as $option) {
             $return .= '<option value="' . $option . '"';
             if ($option == $current_size) {
diff --git a/libraries/common.inc.php b/libraries/common.inc.php
index a728c5a..ab22f17 100644
--- a/libraries/common.inc.php
+++ b/libraries/common.inc.php
@@ -956,6 +956,9 @@ if (! defined('PMA_MINIMUM_COMMON')) {
 
 } // end if !defined('PMA_MINIMUM_COMMON')
 
+// load user preferences
+$GLOBALS['PMA_Config']->loadUserPreferences();
+
 // remove sensitive values from session
 $GLOBALS['PMA_Config']->set('blowfish_secret', '');
 $GLOBALS['PMA_Config']->set('Servers', '');
diff --git a/libraries/common.lib.php b/libraries/common.lib.php
index 23b3eee..741d8cb 100644
--- a/libraries/common.lib.php
+++ b/libraries/common.lib.php
@@ -1576,7 +1576,7 @@ function PMA_generate_html_tab($tab, $url_params = array())
     $defaults = array(
         'text'      => '',
         'class'     => '',
-        'active'    => false,
+        'active'    => null,
         'link'      => '',
         'sep'       => '?',
         'attr'      => '',
@@ -1595,7 +1595,7 @@ function PMA_generate_html_tab($tab, $url_params = array())
         } elseif (! empty($tab['active'])
          || PMA_isValid($GLOBALS['active_page'], 'identical', $tab['link'])) {
             $tab['class'] = 'active';
-        } elseif (empty($GLOBALS['active_page'])
+        } elseif (is_null($tab['active']) && empty($GLOBALS['active_page'])
           && basename($GLOBALS['PMA_PHP_SELF']) == $tab['link']
           && empty($tab['warning'])) {
             $tab['class'] = 'active';
diff --git a/libraries/config.default.php b/libraries/config.default.php
index 691a0f7..9c5ea62 100644
--- a/libraries/config.default.php
+++ b/libraries/config.default.php
@@ -341,6 +341,15 @@ $cfg['Servers'][$i]['designer_coords'] = '';
 $cfg['Servers'][$i]['tracking'] = '';
 
 /**
+ * table to store user preferences
+ *   - leave blank to disable server storage
+ *     SUGGESTED: 'pma_userconfig'
+ *
+ * @global string $cfg['Servers'][$i]['userconfig']
+ */
+$cfg['Servers'][$i]['userconfig'] = '';
+
+/**
  * set to false if you know that your pma_* tables are up to date.
  * This prevents compatibility checks and thereby increases performance.
  *
@@ -1064,6 +1073,13 @@ $cfg['Export'] = array();
 $cfg['Export']['format'] = 'sql';
 
 /**
+ * quick/custom/custom-no-form
+ *
+ * @global string $cfg['Export']['format']
+ */
+$cfg['Export']['method'] = 'quick';
+
+/**
  * none/zip/gzip/bzip2
  *
  * @global string $cfg['Export']['compression']
@@ -1148,6 +1164,13 @@ $cfg['Export']['file_template_server'] = '@SERVER@';
 $cfg['Export']['codegen_structure_or_data'] = 'data';
 
 /**
+ * 
+ *
+ * @global $cfg['Export']['codegen_format']
+ */
+$cfg['Export']['codegen_format'] = 0;
+
+/**
  *
  *
  * @global boolean $cfg['Export']['ods_columns']
@@ -1339,6 +1362,13 @@ $cfg['Export']['csv_terminated'] = 'AUTO';
 /**
  *
  *
+ * @global string $cfg['Export']['csv_removeCRLF']
+ */
+$cfg['Export']['csv_removeCRLF'] = false;
+
+/**
+ *
+ *
  * @global boolean $cfg['Export']['excel_columns']
  */
 $cfg['Export']['excel_columns'] = false;
@@ -1360,6 +1390,13 @@ $cfg['Export']['excel_edition'] = 'win';
 /**
  *
  *
+ * @global string $cfg['Export']['excel_removeCRLF']
+ */
+$cfg['Export']['excel_removeCRLF'] = false;
+
+/**
+ *
+ *
  * @global string $cfg['Export']['excel_structure_or_data']
  */
 $cfg['Export']['excel_structure_or_data'] = 'data';
@@ -1616,7 +1653,7 @@ $cfg['Export']['sql_hex_for_blob'] = true;
  *
  * @global string $cfg['Export']['sql_type']
  */
-$cfg['Export']['sql_type'] = 'insert';
+$cfg['Export']['sql_type'] = 'INSERT';
 
 /**
  *
@@ -1673,6 +1710,7 @@ $cfg['Export']['pdf_report_title'] = '';
  *@global string $cfg['Export']['xml_structure_or_data']
  */
 $cfg['Export']['xml_structure_or_data'] = 'data';
+
 /**
  * Export schema for each structure
  *
@@ -1728,6 +1766,7 @@ $cfg['Export']['xml_export_contents'] = true;
  * @global string $cfg['Export']['yaml_structure_or_data']
  */
 $cfg['Export']['yaml_structure_or_data'] = 'data';
+
 /*******************************************************************************
  * Import defaults
  */
@@ -1759,7 +1798,7 @@ $cfg['Import']['allow_interrupt'] = true;
  *
  * @global integer $cfg['Import']['skip_queries']
  */
-$cfg['Import']['skip_queries'] = '0';
+$cfg['Import']['skip_queries'] = 0;
 
 /**
  *
@@ -1785,6 +1824,13 @@ $cfg['Import']['csv_replace'] = false;
 /**
  *
  *
+ * @global boolean $cfg['Import']['csv_ignore']
+ */
+$cfg['Import']['csv_ignore'] = false;
+
+/**
+ *
+ *
  * @global string $cfg['Import']['csv_terminated']
  */
 $cfg['Import']['csv_terminated'] = ',';
@@ -1834,6 +1880,13 @@ $cfg['Import']['ldi_replace'] = false;
 /**
  *
  *
+ * @global boolean $cfg['Import']['ldi_ignore']
+ */
+$cfg['Import']['ldi_ignore'] = false;
+
+/**
+ *
+ *
  * @global string $cfg['Import']['ldi_terminated']
  */
 $cfg['Import']['ldi_terminated'] = ';';
@@ -1916,6 +1969,13 @@ $cfg['Import']['xls_col_names'] = false;
 $cfg['Import']['xls_empty_rows'] = true;
 
 /**
+ *
+ *
+ * @global string $cfg['Import']['xlsx_col_names']
+ */
+$cfg['Import']['xlsx_col_names'] = false;
+
+/**
  * Link to the official MySQL documentation.
  * Be sure to include no trailing slash on the path.
  * See http://dev.mysql.com/doc/ for more information
@@ -2171,7 +2231,7 @@ $cfg['DefaultDisplay'] = 'horizontal';
 /**
  * default display direction for altering/creating columns (tbl_properties)
  * (horizontal|vertical|<number>)
- * number indicates maximal number for which vertical model is used
+ * number indicates maximum number for which vertical model is used
  *
  * @global integer $cfg['DefaultPropDisplay']
  */
@@ -2295,7 +2355,18 @@ $cfg['NaturalOrder'] = true;
  */
 $cfg['InitialSlidersState'] = 'closed';
 
+/**
+ * User preferences: disallow these settings
+ * For possible setting names look in libraries/config/user_preferences.forms.php
+ *
+ * @global array $cfg['UserprefsDisallow']
+ */
+$cfg['UserprefsDisallow'] = array();
 
+/**
+ * User preferences: enable the Developer tab
+ */
+$cfg['UserprefsDeveloperTab'] = false;
 
 /*******************************************************************************
  * Window title settings
diff --git a/libraries/config.values.php b/libraries/config.values.php
new file mode 100644
index 0000000..dea8a23
--- /dev/null
+++ b/libraries/config.values.php
@@ -0,0 +1,189 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Database with allowed values for configuration stored in the $cfg array,
+ * used by setup script and user preferences to generate forms.
+ *
+ * @package phpMyAdmin
+ */
+
+if (!defined('PHPMYADMIN')) {
+    exit;
+}
+
+/**
+ * Value meaning:
+ * o array - select field, array contains allowed values
+ * o string - type override
+ *
+ * Use normal array, paths won't be expanded
+ */
+$cfg_db = array();
+
+$cfg_db['Servers'] = array(1 => array(
+    'port'         => 'integer',
+    'connect_type' => array('tcp', 'socket'),
+    'extension'    => array('mysql', 'mysqli'),
+    'auth_type'    => array('config', 'http', 'signon', 'cookie'),
+    'AllowDeny'    => array(
+        'order'    => array('', 'deny,allow', 'allow,deny', 'explicit')),
+    'only_db'      => 'array'));
+$cfg_db['RecodingEngine'] = array('auto', 'iconv', 'recode', 'none');
+$cfg_db['OBGzip'] = array('auto', true, false);
+$cfg_db['MemoryLimit'] = 'short_string';
+$cfg_db['ShowTooltipAliasTB'] = array('nested', true, false);
+$cfg_db['DisplayDatabasesList'] = array('auto', true, false);
+$cfg_db['LeftLogoLinkWindow'] = array('main', 'new');
+$cfg_db['LeftDefaultTabTable'] = array(
+    'tbl_structure.php', // fields list
+    'tbl_sql.php',       // SQL form
+    'tbl_select.php',    // search page
+    'tbl_change.php',    // insert row page
+    'sql.php');          // browse page
+$cfg_db['LeftFrameDBSeparator'] = 'short_string';
+$cfg_db['LeftFrameTableSeparator'] = 'short_string';
+$cfg_db['NavigationBarIconic'] = array(true, false, 'both');
+$cfg_db['Order'] = array('ASC', 'DESC', 'SMART');
+$cfg_db['ProtectBinary'] = array(false, 'blob', 'all');
+$cfg_db['DefaultDisplay'] = array('horizontal', 'vertical', 'horizontalflipped');
+$cfg_db['CharEditing'] = array('input', 'textarea');
+$cfg_db['PropertiesIconic'] = array(true, false, 'both');
+$cfg_db['DefaultTabServer'] = array(
+    'main.php',                // the welcome page (recommended for multiuser setups)
+    'server_databases.php',    // list of databases
+    'server_status.php',       // runtime information
+    'server_variables.php',    // MySQL server variables
+    'server_privileges.php',   // user management
+    'server_processlist.php'); // process list
+$cfg_db['DefaultTabDatabase'] = array(
+    'db_structure.php',   // tables list
+    'db_sql.php',         // SQL form
+    'db_search.php',      // search query
+    'db_operations.php'); // operations on database
+$cfg_db['DefaultTabTable'] = array(
+    'tbl_structure.php', // fields list
+    'tbl_sql.php',       // SQL form
+    'tbl_select.php',    // search page
+    'tbl_change.php',    // insert row page
+    'sql.php');          // browse page
+$cfg_db['QueryWindowDefTab'] = array(
+	'sql',     // SQL
+	'files',   // Import files
+	'history', // SQL history
+	'full');   // All (SQL and SQL history)
+$cfg_db['InitialSlidersState'] = array('open', 'closed');
+$cfg_db['Import']['format'] = array(
+    'csv',    // CSV
+    'docsql', // DocSQL
+    'ldi',    // CSV using LOAD DATA
+    'sql');   // SQL
+$cfg_db['Import']['charset'] = array_merge(array(''), $GLOBALS['cfg']['AvailableCharsets']);
+$cfg_db['Import']['sql_compatibility'] = $cfg_db['Export']['sql_compatibility'] = array(
+    'NONE', 'ANSI', 'DB2', 'MAXDB', 'MYSQL323', 'MYSQL40', 'MSSQL', 'ORACLE',
+    // removed; in MySQL 5.0.33, this produces exports that
+    // can't be read by POSTGRESQL (see our bug #1596328)
+    //'POSTGRESQL',
+    'TRADITIONAL');
+$cfg_db['Import']['csv_terminated'] = 'short_string';
+$cfg_db['Import']['csv_enclosed'] = 'short_string';
+$cfg_db['Import']['csv_escaped'] = 'short_string';
+$cfg_db['Import']['ldi_terminated'] = 'short_string';
+$cfg_db['Import']['ldi_enclosed'] = 'short_string';
+$cfg_db['Import']['ldi_escaped'] = 'short_string';
+$cfg_db['Import']['ldi_local_option'] = array('auto', true, false);
+$cfg_db['Export']['_sod_select'] = array(
+    'structure' => __('structure'),
+    'data' => __('data'),
+    'structure_and_data' => __('structure and data'));
+$cfg_db['Export']['method'] = array(
+    'quick' => __('Quick - display only the minimal options to configure'),
+    'custom' => __('Custom - display all possible options to configure'),
+    'custom-no-form' => __('Custom - like above, but without the quick/custom choice'));
+$cfg_db['Export']['format'] = array('codegen', 'csv', 'excel', 'htmlexcel',
+    'htmlword', 'latex', 'ods', 'odt', 'pdf', 'sql', 'texytext', 'xls', 'xml',
+    'yaml');
+$cfg_db['Export']['compression'] = array('none', 'zip', 'gzip', 'bzip2');
+$cfg_db['Export']['charset'] = array_merge(array(''), $GLOBALS['cfg']['AvailableCharsets']);
+$cfg_db['Export']['codegen_format'] = array('#', 'NHibernate C# DO', 'NHibernate XML');
+$cfg_db['Export']['csv_separator'] = 'short_string';
+$cfg_db['Export']['csv_terminated'] = 'short_string';
+$cfg_db['Export']['csv_enclosed'] = 'short_string';
+$cfg_db['Export']['csv_escaped'] = 'short_string';
+$cfg_db['Export']['csv_null'] = 'short_string';
+$cfg_db['Export']['excel_null'] = 'short_string';
+$cfg_db['Export']['excel_edition'] = array('win' => 'Windows',
+    'mac_excel2003' => 'Excel 2003 / Macintosh', 'mac_excel2008' => 'Excel 2008 / Macintosh');
+$cfg_db['Export']['sql_structure_or_data'] = $cfg_db['Export']['_sod_select'];
+$cfg_db['Export']['sql_type'] = array('INSERT', 'UPDATE', 'REPLACE');
+$cfg_db['Export']['sql_insert_syntax'] = array(
+    'complete' => __('complete inserts'),
+    'extended' => __('extended inserts'),
+    'both' => __('both of the above'),
+    'none' => __('neither of the above'));
+$cfg_db['Export']['xls_null'] = 'short_string';
+$cfg_db['Export']['xlsx_null'] = 'short_string';
+$cfg_db['Export']['htmlword_structure_or_data'] = $cfg_db['Export']['_sod_select'];
+$cfg_db['Export']['htmlword_null'] = 'short_string';
+$cfg_db['Export']['ods_null'] = 'short_string';
+$cfg_db['Export']['odt_null'] = 'short_string';
+$cfg_db['Export']['odt_structure_or_data'] = $cfg_db['Export']['_sod_select'];
+$cfg_db['Export']['texytext_structure_or_data'] = $cfg_db['Export']['_sod_select'];
+$cfg_db['Export']['texytext_null'] = 'short_string';
+
+/**
+ * Default values overrides
+ * Use only full paths
+ */
+$cfg_db['_overrides'] = array();
+$cfg_db['_overrides']['Servers/1/extension'] = extension_loaded('mysqli')
+    ? 'mysqli' : 'mysql';
+
+/**
+ * Basic validator assignments (functions from libraries/config/validate.lib.php and 'validators'
+ * object in js/config.js)
+ * Use only full paths and form ids
+ */
+$cfg_db['_validators'] = array(
+    'CharTextareaCols' => 'validate_positive_number',
+    'CharTextareaRows' => 'validate_positive_number',
+    'DefaultPropDisplay' => array(array('validate_by_regex', '/^(?:horizontal|vertical|\d+)$/')),
+    'ExecTimeLimit' => 'validate_non_negative_number',
+    'Export/sql_max_query_size' => 'validate_positive_number',
+    'ForeignKeyMaxLimit' => 'validate_positive_number',
+    'Import/csv_enclosed' => array(array('validate_by_regex', '/^.?$/')),
+    'Import/csv_escaped' => array(array('validate_by_regex', '/^.$/')),
+    'Import/csv_terminated' => array(array('validate_by_regex', '/^.$/')),
+    'Import/ldi_enclosed' => array(array('validate_by_regex', '/^.?$/')),
+    'Import/ldi_escaped' => array(array('validate_by_regex', '/^.$/')),
+    'Import/ldi_terminated' => array(array('validate_by_regex', '/^.$/')),
+    'Import/skip_queries' => 'validate_non_negative_number',
+    'InsertRows' => 'validate_positive_number',
+    'LeftFrameTableLevel' => 'validate_positive_number',
+    'LimitChars' => 'validate_positive_number',
+    'LoginCookieValidity' => 'validate_positive_number',
+    'LoginCookieStore' => 'validate_non_negative_number',
+    'MaxDbList' => 'validate_positive_number',
+    'MaxCharactersInDisplayedSQL' => 'validate_positive_number',
+    'MaxRows' => 'validate_positive_number',
+    'MaxTableList' => 'validate_positive_number',
+    'MemoryLimit' => array(array('validate_by_regex', '/^\d+(?:[kmg])?$/i')),
+    'QueryHistoryMax' => 'validate_positive_number',
+    'QueryWindowWidth' => 'validate_positive_number',
+    'QueryWindowHeight' => 'validate_positive_number',
+    'RepeatCells' => 'validate_non_negative_number',
+    'Server' => 'validate_server',
+    'Server_pmadb' => 'validate_pmadb',
+    'Servers/1/port' => 'validate_port_number',
+    'Servers/1/hide_db' => 'validate_regex',
+    'TextareaCols' => 'validate_positive_number',
+    'TextareaRows' => 'validate_positive_number',
+    'TrustedProxies' => 'validate_trusted_proxies');
+
+/**
+ * Additional validators used for user preferences
+ */
+$cfg_db['_userValidators'] = array(
+    'MaxDbList' => array(array('validate_upper_bound', 'value:MaxDbList')),
+    'MaxTableList' => array(array('validate_upper_bound', 'value:MaxTableList')),
+    'QueryHistoryMax' => array(array('validate_upper_bound', 'value:QueryHistoryMax')),);
+?>
\ No newline at end of file
diff --git a/libraries/config/ConfigFile.class.php b/libraries/config/ConfigFile.class.php
new file mode 100644
index 0000000..41ffe4b
--- /dev/null
+++ b/libraries/config/ConfigFile.class.php
@@ -0,0 +1,486 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Config file management
+ *
+ * @package phpMyAdmin
+ */
+
+/**
+ * Config file management class.
+ * Stores its data in $_SESSION
+ *
+ * @package    phpMyAdmin
+ */
+class ConfigFile
+{
+    /**
+     * Stores default PMA config from config.default.php
+     * @var array
+     */
+    private $cfg;
+
+    /**
+     * Stores allowed values for non-standard fields
+     * @var array
+     */
+    private $cfgDb;
+
+    /**
+     * Keys which will be always written to config file
+     * @var array
+     */
+    private $persistKeys = array();
+
+    /**
+     * Changes keys while updating config in {@link updateWithGlobalConfig()} or reading
+     * by {@link getConfig()} or {@link getConfigArray()}
+     * @var array
+     */
+    private $cfgUpdateReadMapping = array();
+
+    /**
+     * Key filter for {@link set()}
+     * @var array|null
+     */
+    private $setFilter;
+
+    /**
+     * Instance id (key in $_SESSION array, separate for each server - ConfigFile{server id})
+     * @var string
+     */
+    private $id;
+
+    /**
+     * Result for {@link _flattenArray()}
+     * @var array
+     */
+    private $_flattenArrayResult;
+
+    /**
+     * ConfigFile instance
+     * @var ConfigFile
+     */
+    private static $_instance;
+
+    /**
+     * Private constructor, use {@link getInstance()}
+     *
+     * @uses PMA_array_write()
+     */
+    private function __construct()
+    {
+        // load default config values
+        $cfg = &$this->cfg;
+        require './libraries/config.default.php';
+        $cfg['fontsize'] = '82%';
+
+        // load additional config information
+        $cfg_db = &$this->cfgDb;
+        require './libraries/config.values.php';
+
+        // apply default values overrides
+        if (count($cfg_db['_overrides'])) {
+            foreach ($cfg_db['_overrides'] as $path => $value) {
+                PMA_array_write($path, $cfg, $value);
+            }
+        }
+
+        $this->id = 'ConfigFile' . $GLOBALS['server'];
+        if (!isset($_SESSION[$this->id])) {
+            $_SESSION[$this->id] = array();
+        }
+    }
+
+    /**
+     * Returns class instance
+     *
+     * @return ConfigFile
+     */
+    public static function getInstance()
+    {
+        if (is_null(self::$_instance)) {
+            self::$_instance = new ConfigFile();
+        }
+        return self::$_instance;
+    }
+
+    /**
+     * Sets names of config options which will be placed in config file even if they are set
+     * to their default values (use only full paths)
+     *
+     * @param array $keys
+     */
+    public function setPersistKeys($keys)
+    {
+        // checking key presence is much faster than searching so move values to keys
+        $this->persistKeys = array_flip($keys);
+    }
+
+    /**
+     * Returns flipped array set by {@link setPersistKeys()}
+     *
+     * @return array
+     */
+    public function getPersistKeysMap()
+    {
+        return $this->persistKeys;
+    }
+
+    /**
+     * By default ConfigFile allows setting of all configuration keys, use this method
+     * to set up a filter on {@link set()} method
+     *
+     * @param array|null $keys array of allowed keys or null to remove filter
+     */
+    public function setAllowedKeys($keys)
+    {
+        if ($keys === null) {
+            $this->setFilter = null;
+            return;
+        }
+        // checking key presence is much faster than searching so move values to keys
+        $this->setFilter = array_flip($keys);
+    }
+
+    /**
+     * Sets path mapping for updating config in {@link updateWithGlobalConfig()} or reading
+     * by {@link getConfig()} or {@link getConfigArray()}
+     * @var array
+     */
+    public function setCfgUpdateReadMapping(array $mapping)
+    {
+        $this->cfgUpdateReadMapping = $mapping;
+    }
+
+    /**
+     * Resets configuration data
+     */
+    public function resetConfigData()
+    {
+        $_SESSION[$this->id] = array();
+    }
+
+    /**
+     * Sets configuration data (overrides old data)
+     *
+     * @param array $cfg
+     */
+    public function setConfigData(array $cfg)
+    {
+        $_SESSION[$this->id] = $cfg;
+    }
+
+    /**
+     * Sets config value
+     *
+     * @uses PMA_array_remove()
+     * @uses PMA_array_write()
+     * @param string $path
+     * @param mixed  $value
+     * @param string $canonical_path
+     */
+    public function set($path, $value, $canonical_path = null)
+    {
+        if ($canonical_path === null) {
+            $canonical_path = $this->getCanonicalPath($path);
+        }
+        // apply key whitelist
+        if ($this->setFilter !== null && !isset($this->setFilter[$canonical_path])) {
+            return;
+        }
+        // remove if the path isn't protected and it's empty or has a default value
+        $default_value = $this->getDefault($canonical_path);
+        if (!isset($this->persistKeys[$canonical_path])
+                && (($value === $default_value) || (empty($value) && empty($default_value)))) {
+            PMA_array_remove($path, $_SESSION[$this->id]);
+        } else {
+            PMA_array_write($path, $_SESSION[$this->id], $value);
+        }
+    }
+
+    /**
+     * Flattens multidimensional array, changes indices to paths (eg. 'key/subkey').
+     * Used as array_walk() callback.
+     *
+     * @param mixed $value
+     * @param mixed $key
+     * @param mixed $prefix
+     */
+    private function _flattenArray($value, $key, $prefix)
+    {
+        // no recursion for numeric arrays
+        if (is_array($value) && !isset($value[0])) {
+            $prefix .= $key . '/';
+            array_walk($value, array($this, '_flattenArray'), $prefix);
+        } else {
+            $this->_flattenArrayResult[$prefix . $key] = $value;
+        }
+    }
+
+    /**
+     * Returns default config in a flattened array
+     *
+     * @return array
+     */
+    public function getFlatDefaultConfig()
+    {
+        $this->_flattenArrayResult = array();
+        array_walk($this->cfg, array($this, '_flattenArray'), '');
+        $flat_cfg = $this->_flattenArrayResult;
+        $this->_flattenArrayResult = null;
+        return $flat_cfg;
+    }
+
+    /**
+     * Updates config with values read from given array
+     * (config will contain differences to defaults from config.defaults.php).
+     *
+     * @param array $cfg
+     */
+    public function updateWithGlobalConfig(array $cfg)
+    {
+        // load config array and flatten it
+        $this->_flattenArrayResult = array();
+        array_walk($cfg, array($this, '_flattenArray'), '');
+        $flat_cfg = $this->_flattenArrayResult;
+        $this->_flattenArrayResult = null;
+
+        // save values
+        // map for translating a few user preferences paths, should be complemented
+        // by code reading from generated config to perform inverse mapping
+        foreach ($flat_cfg as $path => $value) {
+            if (isset($this->cfgUpdateReadMapping[$path])) {
+                $path = $this->cfgUpdateReadMapping[$path];
+            }
+            $this->set($path, $value, $path);
+        }
+    }
+
+    /**
+     * Returns config value or $default if it's not set
+     *
+     * @uses PMA_array_read()
+     * @param  string $path
+     * @param  mixed  $default
+     * @return mixed
+     */
+    public function get($path, $default = null)
+    {
+        return PMA_array_read($path, $_SESSION[$this->id], $default);
+    }
+
+    /**
+     * Returns default config value or $default it it's not set ie. it doesn't
+     * exist in config.default.php ($cfg) and config.values.php
+     * ($_cfg_db['_overrides'])
+     *
+     * @uses PMA_array_read()
+     * @param  string $canonical_path
+     * @param  mixed  $default
+     * @return mixed
+     */
+    public function getDefault($canonical_path, $default = null)
+    {
+        return PMA_array_read($canonical_path, $this->cfg, $default);
+    }
+
+    /**
+     * Returns config value, if it's not set uses the default one; returns
+     * $default if the path isn't set and doesn't contain a default value
+     *
+     * @uses PMA_array_read()
+     * @param  string $path
+     * @param  mixed  $default
+     * @return mixed
+     */
+    public function getValue($path, $default = null)
+    {
+        $v = PMA_array_read($path, $_SESSION[$this->id], null);
+        if ($v !== null) {
+            return $v;
+        }
+        $path = $this->getCanonicalPath($path);
+        return $this->getDefault($path, $default);
+    }
+
+    /**
+     * Returns canonical path
+     *
+     * @param string $path
+     * @return string
+     */
+    public function getCanonicalPath($path) {
+        return preg_replace('#^Servers/([\d]+)/#', 'Servers/1/', $path);
+    }
+
+    /**
+     * Returns config database entry for $path ($cfg_db in config_info.php)
+     *
+     * @uses PMA_array_read()
+     * @param  string $path
+     * @param  mixed  $default
+     * @return mixed
+     */
+    public function getDbEntry($path, $default = null)
+    {
+        return PMA_array_read($path, $this->cfgDb, $default);
+    }
+
+    /**
+     * Returns server count
+     *
+     * @return int
+     */
+    public function getServerCount()
+    {
+        return isset($_SESSION[$this->id]['Servers'])
+            ? count($_SESSION[$this->id]['Servers'])
+            : 0;
+    }
+
+    /**
+     * Returns server list
+     *
+     * @return array|null
+     */
+    public function getServers()
+    {
+      return isset($_SESSION[$this->id]['Servers'])
+          ? $_SESSION[$this->id]['Servers']
+          : null;
+    }
+
+    /**
+     * Returns DSN of given server
+     *
+     * @param integer $server
+     * @return string
+     */
+    function getServerDSN($server)
+    {
+        if (!isset($_SESSION[$this->id]['Servers'][$server])) {
+            return '';
+        }
+
+        $path = 'Servers/' . $server;
+        $dsn = $this->getValue("$path/extension") . '://';
+        if ($this->getValue("$path/auth_type") == 'config') {
+            $dsn .= $this->getValue("$path/user");
+            if (!$this->getValue("$path/nopassword")) {
+                $dsn .= ':***';
+            }
+            $dsn .= '@';
+        }
+        if ($this->getValue("$path/connect_type") == 'tcp') {
+            $dsn .= $this->getValue("$path/host");
+            $port = $this->getValue("$path/port");
+            if ($port) {
+                $dsn .= ':' . $port;
+            }
+        } else {
+            $dsn .= $this->getValue("$path/socket");
+        }
+        return $dsn;
+    }
+
+    /**
+     * Returns server name
+     *
+     * @param int $id
+     * @return string
+     */
+    public function getServerName($id)
+    {
+        if (!isset($_SESSION[$this->id]['Servers'][$id])) {
+            return '';
+        }
+        $verbose = $this->get("Servers/$id/verbose");
+        if (!empty($verbose)) {
+            return $verbose;
+        }
+        $host = $this->get("Servers/$id/host");
+        return empty($host) ? 'localhost' : $host;
+    }
+
+    /**
+     * Removes server
+     *
+     * @param int $server
+     */
+    public function removeServer($server)
+    {
+        if (!isset($_SESSION[$this->id]['Servers'][$server])) {
+            return;
+        }
+        $last_server = $this->getServerCount();
+
+        for ($i = $server; $i < $last_server; $i++) {
+            $_SESSION[$this->id]['Servers'][$i] = $_SESSION[$this->id]['Servers'][$i+1];
+        }
+        unset($_SESSION[$this->id]['Servers'][$last_server]);
+
+        if (isset($_SESSION[$this->id]['ServerDefault'])
+            && $_SESSION[$this->id]['ServerDefault'] >= 0) {
+            unset($_SESSION[$this->id]['ServerDefault']);
+        }
+    }
+
+    /**
+     * Returns config file path, relative to phpMyAdmin's root path
+     *
+     * @return string
+     */
+    public function getFilePath()
+    {
+        // Load paths
+        if (!defined('SETUP_CONFIG_FILE')) {
+            require_once './libraries/vendor_config.php';
+        }
+
+        return SETUP_CONFIG_FILE;
+    }
+
+    /**
+     * Returns configuration array (full, multidimensional format)
+     *
+     * @return array
+     */
+    public function getConfig()
+    {
+        $c = $_SESSION[$this->id];
+        foreach ($this->cfgUpdateReadMapping as $map_to => $map_from) {
+            PMA_array_write($map_to, $c, PMA_array_read($map_from, $c));
+            PMA_array_remove($map_from, $c);
+        }
+        return $c;
+    }
+
+    /**
+     * Returns configuration array (flat format)
+     *
+     * @return array
+     */
+    public function getConfigArray()
+    {
+        $this->_flattenArrayResult = array();
+        array_walk($_SESSION[$this->id], array($this, '_flattenArray'), '');
+        $c = $this->_flattenArrayResult;
+        $this->_flattenArrayResult = null;
+
+        $persistKeys = array_diff(array_keys($this->persistKeys), array_keys($c));
+        foreach ($persistKeys as $k) {
+            $c[$k] = $this->getDefault($k);
+        }
+
+        foreach ($this->cfgUpdateReadMapping as $map_to => $map_from) {
+            if (!isset($c[$map_from])) {
+                continue;
+            }
+            $c[$map_to] = $c[$map_from];
+            unset($c[$map_from]);
+        }
+        return $c;
+    }
+}
+?>
\ No newline at end of file
diff --git a/setup/lib/Form.class.php b/libraries/config/Form.class.php
similarity index 67%
rename from setup/lib/Form.class.php
rename to libraries/config/Form.class.php
index 1e1fad4..b53d86f 100644
--- a/setup/lib/Form.class.php
+++ b/libraries/config/Form.class.php
@@ -1,17 +1,16 @@
 <?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
 /**
  * Form handling code.
  *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin
  */
 
 /**
  * Base class for forms, loads default configuration options, checks allowed
  * values etc.
  *
- * @package    phpMyAdmin-setup
+ * @package    phpMyAdmin
  */
 class Form
 {
@@ -46,21 +45,16 @@ class Form
     private $fieldsTypes;
 
     /**
-     * Cached forms
-     * @var array
-     */
-    private static $_forms;
-
-    /**
      * Constructor, reads default config values
      *
      * @param string  $form_name
+     * @param array   $form
      * @param int     $index      arbitrary index, stored in Form::$index
      */
-    public function __construct($form_name, $index = null)
+    public function __construct($form_name, array $form, $index = null)
     {
         $this->index = $index;
-        $this->loadForm($form_name);
+        $this->loadForm($form_name, $form);
     }
 
     /**
@@ -80,6 +74,8 @@ class Form
     /**
      * Returns allowed values for select fields
      *
+     * @uses ConfigFile::getDbEntry()
+     * @uses ConfigFile::getInstance()
      * @param   string  $option_path
      * @return  array
      */
@@ -94,12 +90,33 @@ class Form
             trigger_error("$option_path - not a static value list", E_USER_ERROR);
             return array();
         }
+        // convert array('#', 'a', 'b') to array('a', 'b')
+        if (isset($value[0]) && $value[0] === '#') {
+            // remove first element ('#')
+            array_shift($value);
+        } else {
+            // convert value list array('a', 'b') to array('a' => 'a', 'b' => 'b')
+            $has_string_keys = false;
+            $keys = array();
+            for ($i = 0; $i < count($value); $i++) {
+                if (!isset($value[$i])) {
+                    $has_string_keys = true;
+                    break;
+                }
+                $keys[] = is_bool($value[$i]) ? (int)$value[$i] : $value[$i];
+            }
+            if (!$has_string_keys) {
+                $value = array_combine($keys, $value);
+            }
+        }
+
+        // $value has keys and value names, return it
         return $value;
     }
 
     /**
      * array_walk callback function, reads path of form fields from
-     * array (see file comment in forms.inc.php)
+     * array (see file comment in setup.forms.php or user_preferences.forms.inc)
      *
      * @param   mixed   $value
      * @param   mixed   $key
@@ -108,41 +125,33 @@ class Form
     private function _readFormPathsCallback($value, $key, $prefix)
     {
         if (is_array($value)) {
-            $prefix .= (empty($prefix) ? '' : '/') . $key;
+            $prefix .= $key . '/';
             array_walk($value, array($this, '_readFormPathsCallback'), $prefix);
         } else {
             if (!is_int($key)) {
-                $this->default[$prefix . '/' . $key] = $value;
+                $this->default[$prefix . $key] = $value;
                 $value = $key;
             }
-            $this->fields[] = $prefix . '/' . $value;
+            $this->fields[] = $prefix . $value;
         }
     }
 
     /**
      * Reads form paths to {@link $fields}
+     *
+     * @param array $form
      */
-    protected function readFormPaths()
+    protected function readFormPaths($form)
     {
-        if (is_null(self::$_forms)) {
-            $forms =& self::$_forms;
-            require './setup/lib/forms.inc.php';
-        }
-
-        if (!isset(self::$_forms[$this->name])) {
-            return;
-        }
-
         // flatten form fields' paths and save them to $fields
         $this->fields = array();
-        array_walk(self::$_forms[$this->name], array($this, '_readFormPathsCallback'), '');
+        array_walk($form, array($this, '_readFormPathsCallback'), '');
 
         // $this->fields is an array of the form: [0..n] => 'field path'
         // change numeric indexes to contain field names (last part of the path)
         $paths = $this->fields;
         $this->fields = array();
         foreach ($paths as $path) {
-            $path = ltrim($path, '/');
             $key = ltrim(substr($path, strrpos($path, '/')), '/');
             $this->fields[$key] = $path;
         }
@@ -151,11 +160,19 @@ class Form
 
     /**
      * Reads fields' types to $this->fieldsTypes
+     *
+     * @uses ConfigFile::getDbEntry()
+     * @uses ConfigFile::getDefault()
+     * @uses ConfigFile::getInstance()
      */
     protected function readTypes()
     {
         $cf = ConfigFile::getInstance();
         foreach ($this->fields as $name => $path) {
+            if (strpos($name, ':group:') === 0) {
+                $this->fieldsTypes[$name] = 'group';
+                continue;
+            }
             $v = $cf->getDbEntry($path);
             if ($v !== null) {
                 $type = is_array($v) ? 'select' : $v;
@@ -171,12 +188,13 @@ class Form
      * config file
      *
      * @param string $form_name
+     * @param array  $form
      */
-    public function loadForm($form_name)
+    public function loadForm($form_name, $form)
     {
         $this->name = $form_name;
-        $this->readFormPaths();
+        $this->readFormPaths($form);
         $this->readTypes();
     }
 }
-?>
+?>
\ No newline at end of file
diff --git a/setup/lib/FormDisplay.class.php b/libraries/config/FormDisplay.class.php
similarity index 61%
rename from setup/lib/FormDisplay.class.php
rename to libraries/config/FormDisplay.class.php
index 7b6bfeb..5a08f5e 100644
--- a/setup/lib/FormDisplay.class.php
+++ b/libraries/config/FormDisplay.class.php
@@ -1,4 +1,5 @@
 <?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
 /**
  * Form management class, displays and processes forms
  *
@@ -8,16 +9,14 @@
  * o translated_path - work_path modified for HTML field name, a path with
  *                     slashes changed to hyphens, eg. Servers-4-verbose
  *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin
  */
 
 /**
  * Core libraries.
  */
-require_once './setup/lib/FormDisplay.tpl.php';
-require_once './setup/lib/validate.lib.php';
+require_once './libraries/config/FormDisplay.tpl.php';
+require_once './libraries/config/validate.lib.php';
 require_once './libraries/js_escape.lib.php';
 
 /**
@@ -28,7 +27,7 @@ class FormDisplay
 {
     /**
      * Form list
-     * @var array
+     * @var Form[]
      */
     private $forms = array();
 
@@ -58,25 +57,49 @@ class FormDisplay
      * Will be looked up in $GLOBALS: str{value} or strSetup{value}
      * @var array
      */
-    private $js_lang_strings = array('error_nan_p', 'error_nan_nneg',
-        'error_incorrect_port');
+    private $js_lang_strings = array();
 
     /**
      * Tells whether forms have been validated
      * @var bool
      */
-    private $is_valdiated = true;
+    private $is_validated = true;
+
+    /**
+     * Dictionary with user preferences keys
+     * @var array
+     */
+    private $userprefs_keys;
+
+    /**
+     * Dictionary with disallowed user preferences keys
+     * @var array
+     */
+    private $userprefs_disallow;
+
+    public function __construct()
+    {
+        $this->js_lang_strings = array(
+            'error_nan_p' => __('Not a positive number'),
+            'error_nan_nneg' => __('Not a non-negative number'),
+            'error_incorrect_port' => __('Not a valid port number'),
+            'error_invalid_value' => __('Incorrect value'),
+            'error_value_lte' => __('Value must be equal or lower than %s'));
+        // initialize validators
+        PMA_config_get_validators();
+    }
 
     /**
      * Registers form in form manager
      *
      * @param string $form_name
+     * @param array  $form
      * @param int    $server_id 0 if new server, validation; >= 1 if editing a server
      */
-    public function registerForm($form_name, $server_id = null)
+    public function registerForm($form_name, array $form, $server_id = null)
     {
-        $this->forms[$form_name] = new Form($form_name, $server_id);
-        $this->is_valdiated = false;
+        $this->forms[$form_name] = new Form($form_name, $form, $server_id);
+        $this->is_validated = false;
         foreach ($this->forms[$form_name]->fields as $path) {
             $work_path = $server_id === null
                 ? $path
@@ -90,12 +113,12 @@ class FormDisplay
      * Processes forms, returns true on successful save
      *
      * @param  bool  $allow_partial_save  allows for partial form saving on failed validation
+     * @param  bool  $check_form_submit   whether check for $_POST['submit_save']
      * @return boolean
      */
-    public function process($allow_partial_save = true)
+    public function process($allow_partial_save = true, $check_form_submit = true)
     {
-        // gather list of forms to save
-        if (!isset($_POST['submit_save'])) {
+        if ($check_form_submit && !isset($_POST['submit_save'])) {
             return false;
         }
 
@@ -108,10 +131,14 @@ class FormDisplay
 
     /**
      * Runs validation for all registered forms
+     *
+     * @uses ConfigFile::getInstance()
+     * @uses ConfigFile::getValue()
+     * @uses PMA_config_validate()
      */
     private function _validate()
     {
-        if ($this->is_valdiated) {
+        if ($this->is_validated) {
             return;
         }
 
@@ -130,7 +157,7 @@ class FormDisplay
         }
 
         // run validation
-        $errors = validate($paths, $values, false);
+        $errors = PMA_config_validate($paths, $values, false);
 
         // change error keys from canonical paths to work paths
         if (is_array($errors) && count($errors) > 0) {
@@ -145,13 +172,25 @@ class FormDisplay
                 $this->errors[$work_path] = $error_list;
             }
         }
-        $this->is_valdiated = true;
+        $this->is_validated = true;
     }
 
-
     /**
      * Outputs HTML for forms
      *
+     * @uses ConfigFile::getInstance()
+     * @uses ConfigFile::get()
+     * @uses display_fieldset_bottom()
+     * @uses display_fieldset_top()
+     * @uses display_form_bottom()
+     * @uses display_form_top()
+     * @uses display_js()
+     * @uses display_tabs_bottom()
+     * @uses display_tabs_top()
+     * @uses js_validate()
+     * @uses PMA_config_get_validators()
+     * @uses PMA_jsFormat()
+     * @uses PMA_lang()
      * @param bool $tabbed_form
      * @param bool   $show_restore_default  whether show "restore default" button besides the input field
      */
@@ -162,7 +201,7 @@ class FormDisplay
         $js = array();
         $js_default = array();
         $tabbed_form = $tabbed_form && (count($this->forms) > 1);
-        $validators = ConfigFile::getInstance()->getDbEntry('_validators');
+        $validators = PMA_config_get_validators();
 
         display_form_top();
 
@@ -187,10 +226,13 @@ class FormDisplay
             $this->_validate();
         }
 
+        // user preferences
+        $this->_loadUserprefsInfo();
+
         // display forms
         foreach ($this->forms as $form) {
             /* @var $form Form */
-            $form_desc = isset($GLOBALS["strSetupForm_{$form->name}_desc"])
+            $form_desc = isset($GLOBALS["strConfigForm_{$form->name}_desc"])
                 ? PMA_lang("Form_{$form->name}_desc")
                 : '';
             $form_errors = isset($this->errors[$form->name])
@@ -201,9 +243,14 @@ class FormDisplay
             foreach ($form->fields as $field => $path) {
                 $work_path = array_search($path, $this->system_paths);
                 $translated_path = $this->translated_paths[$work_path];
+                // always true/false for user preferences display
+                // otherwise null
+                $userprefs_allow = isset($this->userprefs_keys[$path])
+                    ? !isset($this->userprefs_disallow[$path])
+                    : null;
                 // display input
                 $this->_displayFieldInput($form, $field, $path, $work_path,
-                    $translated_path, $show_restore_default, $js_default);
+                    $translated_path, $show_restore_default, $userprefs_allow, $js_default);
                 // register JS validators for this field
                 if (isset($validators[$path])) {
                     js_validate($translated_path, $validators[$path], $js);
@@ -221,35 +268,45 @@ class FormDisplay
         if (!$js_lang_sent) {
             $js_lang_sent = true;
             $js_lang = array();
-            foreach ($this->js_lang_strings as $str) {
-                $lang = isset($GLOBALS["strSetup$str"])
-                    ? $GLOBALS["strSetup$str"]
-                    : filter_input($GLOBALS["str$str"]); // null if not set
-                $js_lang[] = "'$str': '" . PMA_jsFormat($lang, false) . '\'';
+            foreach ($this->js_lang_strings as $strName => $strValue) {
+                $js_lang[] = "'$strName': '" . PMA_jsFormat($strValue, false) . '\'';
             }
-            $js[] = '$.extend(PMA_messages, {' . implode(",\n\t", $js_lang) . '})';
+            $js[] = "$.extend(PMA_messages, {\n\t" . implode(",\n\t", $js_lang) . '})';
         }
 
-        $js[] = '$.extend(defaultValues, {' . implode(",\n\t", $js_default) . '})';
+        $js[] = "$.extend(defaultValues, {\n\t" . implode(",\n\t", $js_default) . '})';
         display_js($js);
     }
 
     /**
      * Prepares data for input field display and outputs HTML code
      *
+     * @uses ConfigFile::get()
+     * @uses ConfigFile::getDefault()
+     * @uses ConfigFile::getInstance()
+     * @uses display_group_footer()
+     * @uses display_group_header()
+     * @uses display_input()
+     * @uses Form::getOptionType()
+     * @uses Form::getOptionValueList()
+     * @uses PMA_escapeJsString()
+     * @uses PMA_lang_desc()
+     * @uses PMA_lang_name()
      * @param Form   $form
      * @param string $field                 field name as it appears in $form
      * @param string $system_path           field path, eg. Servers/1/verbose
      * @param string $work_path             work path, eg. Servers/4/verbose
      * @param string $translated_path       work path changed so that it can be used as XHTML id
      * @param bool   $show_restore_default  whether show "restore default" button besides the input field
+     * @param mixed  $userprefs_allow       whether user preferences are enabled for this field
+     *                                      (null - no support, true/false - enabled/disabled)
      * @param array  &$js_default           array which stores JavaScript code to be displayed
      */
     private function _displayFieldInput(Form $form, $field, $system_path, $work_path,
-        $translated_path, $show_restore_default, array &$js_default)
+            $translated_path, $show_restore_default, $userprefs_allow, array &$js_default)
     {
         $name = PMA_lang_name($system_path);
-        $description = PMA_lang_desc($system_path);
+        $description = PMA_lang_name($system_path, 'desc', '');
 
         $cf = ConfigFile::getInstance();
         $value = $cf->get($work_path);
@@ -263,7 +320,9 @@ class FormDisplay
         $opts = array(
             'doc' => $this->getDocLink($system_path),
             'wiki' =>  $this->getWikiLink($system_path),
-            'show_restore_default' => $show_restore_default);
+            'show_restore_default' => $show_restore_default,
+            'userprefs_allow' => $userprefs_allow,
+            'userprefs_comment' => PMA_lang_name($system_path, 'cmt', ''));
         if (isset($form->default[$system_path])) {
             $opts['setvalue'] = $form->default[$system_path];
         }
@@ -275,28 +334,33 @@ class FormDisplay
             case 'string':
                 $type = 'text';
                 break;
-            case 'double':
-                $type = 'text';
+            case 'short_string':
+                $type = 'short_text';
                 break;
+            case 'double':
             case 'integer':
-                $type = 'text';
+                $type = 'number_text';
                 break;
             case 'boolean':
                 $type = 'checkbox';
                 break;
             case 'select':
                 $type = 'select';
-                $opts['values'] = array();
-                $values = $form->getOptionValueList($form->fields[$field]);
-                foreach ($values as $v) {
-                    $opts['values'][$v] = $v;
-                }
+                $opts['values'] = $form->getOptionValueList($form->fields[$field]);
                 break;
             case 'array':
                 $type = 'list';
                 $value = (array) $value;
                 $value_default = (array) $value_default;
                 break;
+            case 'group':
+                $text = substr($field, 7);
+                if ($text != 'end') {
+                    display_group_header($text);
+                } else {
+                    display_group_footer();
+                }
+                return;
             case 'NULL':
             	trigger_error("Field $system_path has no type", E_USER_WARNING);
             	return;
@@ -310,11 +374,14 @@ class FormDisplay
                 }
             }
         }
+        $this->_setComments($system_path, $opts);
 
         // send default value to form's JS
         $js_line = '\'' . $translated_path . '\': ';
         switch ($type) {
             case 'text':
+            case 'short_text':
+            case 'number_text':
                 $js_line .= '\'' . PMA_escapeJsString($value_default) . '\'';
                 break;
             case 'checkbox':
@@ -338,6 +405,9 @@ class FormDisplay
 
     /**
      * Displays errors
+     *
+     * @uses display_errors()
+     * @uses PMA_lang_name()
      */
     public function displayErrors()
     {
@@ -351,7 +421,7 @@ class FormDisplay
                 $path = $this->system_paths[$system_path];
                 $name = PMA_lang_name($path);
             } else {
-                $name = $GLOBALS["strSetupForm_$system_path"];
+                $name = $GLOBALS["strConfigForm_$system_path"];
             }
             display_errors($name, $error_list);
         }
@@ -359,6 +429,11 @@ class FormDisplay
 
     /**
      * Reverts erroneous fields to their default values
+     *
+     * @uses ConfigFile::getDefault()
+     * @uses ConfigFile::getInstance()
+     * @uses ConfigFile::set()
+     *
      */
     public function fixErrors()
     {
@@ -386,11 +461,17 @@ class FormDisplay
      */
     private function _validateSelect(&$value, array $allowed)
     {
-        foreach ($allowed as $v) {
-          if ($value == $v) {
-              settype($value, gettype($v));
-              return true;
-          }
+        $value_cmp = is_bool($value)
+            ? (int) $value
+            : $value;
+        foreach ($allowed as $vk => $v) {
+            // equality comparison only if both values are numeric or not numeric
+            // (allows to skip 0 == 'string' equalling to true) or identity (for string-string)
+            if (($vk == $value && !(is_numeric($value_cmp) xor is_numeric($vk)))
+                    || $vk === $value) {
+                settype($value, gettype($v));
+                return true;
+            }
         }
         return false;
     }
@@ -398,6 +479,13 @@ class FormDisplay
     /**
      * Validates and saves form data to session
      *
+     * @uses ConfigFile::get()
+     * @uses ConfigFile::getInstance()
+     * @uses ConfigFile::getServerCount()
+     * @uses ConfigFile::set()
+     * @uses Form::getOptionType()
+     * @uses Form::getOptionValueList()
+     * @uses PMA_lang_name()
      * @param  array|string  $forms               array of form names
      * @param  bool          $allow_partial_save  allows for partial form saving on failed validation
      * @return boolean  true on success (no errors and all saved)
@@ -410,6 +498,11 @@ class FormDisplay
 
         $values = array();
         $to_save = array();
+        $is_setup_script = defined('PMA_SETUP') && PMA_SETUP;
+        if ($is_setup_script) {
+            $this->_loadUserprefsInfo();
+        }
+
         $this->errors = array();
         foreach ($forms as $form) {
             /* @var $form Form */
@@ -426,23 +519,38 @@ class FormDisplay
             foreach ($form->fields as $field => $system_path) {
                 $work_path = array_search($system_path, $this->system_paths);
                 $key = $this->translated_paths[$work_path];
+                $type = $form->getOptionType($field);
+
+                // skip groups
+                if ($type == 'group') {
+                    continue;
+                }
 
                 // ensure the value is set
                 if (!isset($_POST[$key])) {
                     // checkboxes aren't set by browsers if they're off
-                    if ($form->getOptionType($field) == 'boolean') {
+                    if ($type == 'boolean') {
                         $_POST[$key] = false;
                     } else {
-                        $this->errors[$form->name][] = PMA_lang(
-                            'error_missing_field_data',
+                        $this->errors[$form->name][] = sprintf(
+                            __('Missing data for %s'),
                             '<i>' . PMA_lang_name($system_path) . '</i>');
                         $result = false;
                         continue;
                     }
                 }
 
+                // user preferences allow/disallow
+                if ($is_setup_script && isset($this->userprefs_keys[$system_path])) {
+                    if (isset($this->userprefs_disallow[$system_path])
+                            && isset($_POST[$key . '-userprefs-allow'])) {
+                        unset($this->userprefs_disallow[$system_path]);
+                    } else if (!isset($_POST[$key . '-userprefs-allow'])) {
+                        $this->userprefs_disallow[$system_path] = true;
+                    }
+                }
+
                 // cast variables to correct type
-                $type = $form->getOptionType($field);
                 switch ($type) {
                     case 'double':
                         settype($_POST[$key], 'float');
@@ -461,11 +569,14 @@ class FormDisplay
                         }
                         break;
                     case 'string':
+                    case 'short_string':
                         $_POST[$key] = trim($_POST[$key]);
                         break;
                     case 'array':
                         // eliminate empty values and ensure we have an array
-                        $post_values = explode("\n", $_POST[$key]);
+                        $post_values = is_array($_POST[$key])
+                            ? $_POST[$key]
+                            : explode("\n", $_POST[$key]);
                         $_POST[$key] = array();
                         foreach ($post_values as $v) {
                             $v = trim($v);
@@ -509,6 +620,9 @@ class FormDisplay
                 }
                 $cf->set($work_path, $values[$path], $path);
             }
+            if ($is_setup_script) {
+                $cf->set('UserprefsDisallow', array_keys($this->userprefs_disallow));
+            }
         }
 
         // don't look for non-critical errors
@@ -540,7 +654,7 @@ class FormDisplay
         if ($test == 'Import' || $test == 'Export') {
             return '';
         }
-        return '../Documentation.html#cfg_' . self::_getOptName($path);
+        return 'Documentation.html#cfg_' . $this->_getOptName($path);
     }
 
     /**
@@ -551,7 +665,7 @@ class FormDisplay
      */
     public function getWikiLink($path)
     {
-        $opt_name = self::_getOptName($path);
+        $opt_name = $this->_getOptName($path);
         if (substr($opt_name, 0, 7) == 'Servers') {
             $opt_name = substr($opt_name, 8);
             if (strpos($opt_name, 'AllowDeny') === 0) {
@@ -577,9 +691,88 @@ class FormDisplay
      * @param string $path
      * @return string
      */
-    private static function _getOptName($path)
+    private function _getOptName($path)
+    {
+        return str_replace(array('Servers/1/', '/'), array('Servers/', '_'), $path);
+    }
+
+    /**
+     * Fills out {@link userprefs_keys} and {@link userprefs_disallow}
+     *
+     * @uses PMA_read_userprefs_fieldnames()
+     */
+    private function _loadUserprefsInfo()
+    {
+        if ($this->userprefs_keys === null) {
+            $this->userprefs_keys = array_flip(PMA_read_userprefs_fieldnames());
+            // read real config for user preferences display
+            $userprefs_disallow = defined('PMA_SETUP') && PMA_SETUP
+                ? ConfigFile::getInstance()->get('UserprefsDisallow', array())
+                : $GLOBALS['cfg']['UserprefsDisallow'];
+            $this->userprefs_disallow = array_flip($userprefs_disallow);
+        }
+    }
+
+    /**
+     * Sets field comments and warnings based on current environment
+     *
+     * @param string $system_path
+     * @param array  $opts
+     */
+    private function _setComments($system_path, array &$opts)
     {
-      return str_replace(array('Servers/1/', '/'), array('Servers/', '_'), $path);
+        // RecodingEngine - mark unavailable types
+        if ($system_path == 'RecodingEngine') {
+            $comment = '';
+            if (!function_exists('iconv')) {
+                $opts['values']['iconv'] .= ' (' . __('unavailable') . ')';
+                $comment = sprintf(__('"%s" requires %s extension'), 'iconv', 'iconv');
+            }
+            if (!function_exists('recode_string')) {
+                $opts['values']['recode'] .= ' (' . __('unavailable') . ')';
+                $comment .= ($comment ? ", " : '') . sprintf(__('"%s" requires %s extension'),
+                    'recode', 'recode');
+            }
+            $opts['comment'] = $comment;
+            $opts['comment_warning'] = true;
+        }
+        // ZipDump, GZipDump, BZipDump - check function availability
+        if ($system_path == 'ZipDump' || $system_path == 'GZipDump' || $system_path == 'BZipDump') {
+            $comment = '';
+            $funcs = array(
+                'ZipDump'  => array('zip_open', 'gzcompress'),
+                'GZipDump' => array('gzopen', 'gzencode'),
+                'BZipDump' => array('bzopen', 'bzcompress'));
+            if (!function_exists($funcs[$system_path][0])) {
+                $comment = sprintf(__('import will not work, missing function (%s)'),
+                    $funcs[$system_path][0]);
+            }
+            if (!function_exists($funcs[$system_path][1])) {
+                $comment .= ($comment ? '; ' : '') . sprintf(__('export will not work, missing function (%s)'),
+                    $funcs[$system_path][1]);
+            }
+            $opts['comment'] = $comment;
+            $opts['comment_warning'] = true;
+        }
+        if ($system_path == 'SQLQuery/Validate' && !$GLOBALS['cfg']['SQLValidator']['use']) {
+            $opts['comment'] = __('SQL Validator is disabled');
+            $opts['comment_warning'] = true;
+        }
+        if ($system_path == 'SQLValidator/use') {
+            if (!class_exists('SOAPClient')) {
+                @include_once 'SOAP/Client.php';
+                if (!class_exists('SOAP_Client')) {
+                    $opts['comment'] = __('SOAP extension not found');
+                    $opts['comment_warning'] = true;
+                }
+            }
+        }
+        if (!defined('PMA_SETUP') || !PMA_SETUP) {
+            if (($system_path == 'MaxDbList' || $system_path == 'MaxTableList'
+                    || $system_path == 'QueryHistoryMax')) {
+                $opts['comment'] = sprintf(__('maximum %s'), $GLOBALS['cfg'][$system_path]);
+            }
+        }
     }
 }
-?>
+?>
\ No newline at end of file
diff --git a/libraries/config/FormDisplay.tpl.php b/libraries/config/FormDisplay.tpl.php
new file mode 100644
index 0000000..40c59d1
--- /dev/null
+++ b/libraries/config/FormDisplay.tpl.php
@@ -0,0 +1,429 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Form templates
+ *
+ * @package phpMyAdmin
+ */
+
+/**
+ * Displays top part of the form
+ *
+ * @uses PMA_generate_common_hidden_inputs()
+ * @uses PMA_getHiddenFields()
+ * @param string $action         default: $_SERVER['REQUEST_URI']
+ * @param string $method         'post' or 'get'
+ * @param array  $hidden_fields  array of form hidden fields (key: field name)
+ */
+function display_form_top($action = null, $method = 'post', $hidden_fields = null)
+{
+    static $has_check_page_refresh = false;
+
+    if ($action === null) {
+        $action = $_SERVER['REQUEST_URI'];
+    }
+    if ($method != 'post') {
+        $method = 'get';
+    }
+?>
+<form method="<?php echo $method ?>" action="<?php echo htmlspecialchars($action) ?>" class="config-form">
+<input type="hidden" name="tab_hash" value="" />
+<?php
+    // we do validation on page refresh when browser remembers field values,
+    // add a field with known value which will be used for checks
+    if (!$has_check_page_refresh) {
+        $has_check_page_refresh = true;
+        echo '<input type="hidden" name="check_page_refresh" id="check_page_refresh"'
+            . ' value="" />' . "\n";
+    }
+    echo PMA_generate_common_hidden_inputs('', '', 0, 'server') . "\n";
+    echo PMA_getHiddenFields((array)$hidden_fields);
+}
+
+/**
+ * Displays form tabs which are given by an array indexed by fieldset id
+ * ({@link display_fieldset_top}), with values being tab titles.
+ *
+ * @param array $tabs
+ */
+function display_tabs_top($tabs)
+{
+?>
+<ul class="tabs">
+<?php foreach ($tabs as $tab_id => $tab_name): ?>
+    <li><a href="#<?php echo $tab_id ?>"><?php echo $tab_name ?></a></li>
+<?php endforeach; ?>
+</ul>
+<br clear="right" />
+<div class="tabs_contents">
+<?php
+}
+
+
+/**
+ * Displays top part of a fieldset
+ *
+ * @param string $title
+ * @param string $description
+ * @param array  $errors
+ * @param array  $attributes
+ */
+function display_fieldset_top($title = '', $description = '', $errors = null, $attributes = array())
+{
+    global $_FormDisplayGroup;
+
+    $_FormDisplayGroup = false;
+
+    $attributes = array_merge(array('class' => 'optbox'), $attributes);
+    foreach ($attributes as $k => &$attr) {
+        $attr = $k . '="' . htmlspecialchars($attr) . '"';
+    }
+
+    echo '<fieldset ' . implode(' ', $attributes) . '>';
+    echo '<legend>' . $title . '</legend>';
+    if (!empty($description)) {
+        echo '<p>' . $description . '</p>';
+    }
+    // this must match with displayErrors() in scripts.js
+    if (is_array($errors) && count($errors) > 0) {
+        echo '<dl class="errors">';
+        foreach ($errors as $error) {
+            echo '<dd>' . $error . '</dd>';
+        }
+        echo '</dl>';
+    }
+?>
+<table width="100%" cellspacing="0">
+<?php
+}
+
+/**
+ * Displays input field
+ *
+ * $opts keys:
+ * o doc - (string) documentation link
+ * o errors - error array
+ * o setvalue - (string) shows button allowing to set poredefined value
+ * o show_restore_default - (boolean) whether show "restore default" button
+ * o userprefs_allow - whether user preferences are enabled for this field (null - no support,
+ *                     true/false - enabled/disabled)
+ * o userprefs_comment - (string) field comment
+ * o values - key - value paris for <select> fields
+ * o values_escaped - (boolean) tells whether values array is already escaped (defaults to false)
+ * o values_disabled -  (array)list of disabled values (keys from values)
+ * o comment - (string) tooltip comment
+ * o comment_warning - (bool) whether this comments warns about something
+ * o wiki - (string) wiki link
+ *
+ * @uses $GLOBALS['_FormDisplayGroup']
+ * @uses $GLOBALS['cfg']['ThemePath']
+ * @uses $_SESSION['PMA_Theme']
+ * @uses display_group_footer()
+ * @param string $path
+ * @param string $name
+ * @param string $description
+ * @param string $type
+ * @param mixed  $value
+ * @param bool   $value_is_default
+ * @param array  $opts
+ */
+function display_input($path, $name, $description = '', $type, $value, $value_is_default = true, $opts = null)
+{
+    global $_FormDisplayGroup;
+    static $base_dir, $img_path;
+
+    $is_setup_script = defined('PMA_SETUP') && PMA_SETUP;
+    if ($base_dir === null) {
+        $base_dir = $is_setup_script ? '../' : '';
+        $img_path = $is_setup_script
+            ? '../' . ltrim($GLOBALS['cfg']['ThemePath'], './') . '/original/img/'
+            : $_SESSION['PMA_Theme']->img_path;
+    }
+    $has_errors = isset($opts['errors']) && !empty($opts['errors']);
+    $option_is_disabled = !$is_setup_script && isset($opts['userprefs_allow']) && !$opts['userprefs_allow'];
+    $name_id = 'name="' . htmlspecialchars($path) . '" id="' . htmlspecialchars($path) . '"';
+    $field_class = $type == 'checkbox' ? 'checkbox' : '';
+    if (!$value_is_default) {
+        $field_class .= ($field_class == '' ? '' : ' ') . ($has_errors ? 'custom field-error' : 'custom');
+    }
+    $field_class = $field_class ? ' class="' . $field_class . '"' : '';
+    $tr_class = $_FormDisplayGroup ? 'group-field' : '';
+    if (isset($opts['setvalue']) && $opts['setvalue'] == ':group') {
+        unset($opts['setvalue']);
+        $tr_class = 'group-header-field';
+        if ($_FormDisplayGroup) {
+            display_group_footer();
+        }
+        $_FormDisplayGroup = true;
+    }
+    if ($option_is_disabled) {
+        $tr_class .= ($tr_class ? ' ' : '') . 'disabled-field';
+    }
+    $tr_class = $tr_class ? ' class="' . $tr_class . '"' : '';
+?>
+<tr<?php echo $tr_class ?>>
+    <th>
+        <label for="<?php echo htmlspecialchars($path) ?>"><?php echo $name ?></label>
+        <?php if (!empty($opts['doc']) || !empty($opts['wiki'])) { ?>
+        <span class="doc">
+            <?php if (!empty($opts['doc'])) { ?><a href="<?php echo $base_dir . $opts['doc']  ?>" target="documentation"><img class="icon" src="<?php echo $img_path ?>b_help.png" width="11" height="11" alt="Doc" title="<?php echo __('Documentation') ?>" /></a><?php } ?>
+            <?php if (!empty($opts['wiki'])){ ?><a href="<?php echo $opts['wiki'] ?>" target="wiki"><img class="icon" src="<?php echo $img_path ?>b_info.png" width="11" height="11" alt="Wiki" title="Wiki" /></a><?php } ?>
+        </span>
+        <?php } ?>
+        <?php if ($option_is_disabled) { ?>
+            <span class="disabled-notice" title="<?php echo __('This setting is disabled, it will not be applied to your configuration') ?>"><?php echo __('Disabled') ?></span>
+        <?php } ?>
+        <?php if (!empty($description)) { ?><small><?php echo $description ?></small><?php } ?>
+    </th>
+    <td>
+    <?php
+    switch ($type) {
+        case 'text':
+            echo '<input type="text" size="60" ' . $name_id . $field_class
+                . ' value="' . htmlspecialchars($value) . '" />';
+          break;
+        case 'short_text':
+            echo '<input type="text" size="25" ' . $name_id . $field_class
+                . ' value="' . htmlspecialchars($value) . '" />';
+          break;
+        case 'number_text':
+            echo '<input type="text" size="15" ' . $name_id . $field_class
+                . ' value="' . htmlspecialchars($value) . '" />';
+          break;
+        case 'checkbox':
+            echo '<span' . $field_class . '><input type="checkbox" ' . $name_id
+              . ($value ? ' checked="checked"' : '') . ' /></span>';
+          break;
+        case 'select':
+            echo '<select ' . $name_id . $field_class . '>';
+            $escape = !(isset($opts['values_escaped']) && $opts['values_escaped']);
+            $values_disabled = isset($opts['values_disabled'])
+                ? array_flip($opts['values_disabled']) : array();
+            foreach ($opts['values'] as $opt_value_key => $opt_value) {
+                // set names for boolean values
+                if (is_bool($opt_value)) {
+                    $opt_value = strtolower($opt_value ? __('Yes') : __('No'));
+                }
+                // escape if necessary
+                if ($escape) {
+                    $display = htmlspecialchars($opt_value);
+                    $display_value = htmlspecialchars($opt_value_key);
+                } else {
+                    $display = $opt_value;
+                    $display_value = $opt_value_key;
+                }
+                // compare with selected value
+                // boolean values are cast to integers when used as array keys
+                $selected = is_bool($value)
+                    ? (int) $value === $opt_value_key
+                    : $opt_value_key === $value;
+                echo '<option value="' . $display_value . '"'
+                    . ($selected ? ' selected="selected"' : '')
+                    . (isset($values_disabled[$opt_value_key]) ? ' disabled="disabled"' : '')
+                    . '>' . $display . '</option>';
+            }
+            echo '</select>';
+            break;
+        case 'list':
+            echo '<textarea cols="40" rows="5" ' . $name_id . $field_class . '>'
+                . htmlspecialchars(implode("\n", $value))
+                . '</textarea>';
+            break;
+    }
+    if (isset($opts['comment']) && $opts['comment']) {
+        $class = 'field-comment-mark';
+        if (isset($opts['comment_warning']) && $opts['comment_warning']) {
+            $class .= ' field-comment-warning';
+        }
+        ?>
+        <span class="<?php echo $class ?>" title="<?php echo htmlspecialchars($opts['comment']) ?>">i</span>
+        <?php
+    }
+    if ($is_setup_script && isset($opts['userprefs_comment']) && $opts['userprefs_comment']) {
+        ?>
+        <a class="userprefs-comment" title="<?php echo htmlspecialchars($opts['userprefs_comment']) ?>"><img alt="comment" src="<?php echo $img_path ?>b_tblops.png" width="16" height="16" /></a>
+        <?php
+    }
+    if (isset($opts['setvalue']) && $opts['setvalue']) {
+        ?>
+        <a class="set-value" href="#<?php echo htmlspecialchars("$path={$opts['setvalue']}") ?>" title="<?php echo sprintf(__('Set value: %s'), htmlspecialchars($opts['setvalue'])) ?>" style="display:none"><img alt="set-value" src="<?php echo $img_path ?>b_edit.png" width="16" height="16" /></a>
+        <?php
+    }
+    if (isset($opts['show_restore_default']) && $opts['show_restore_default']) {
+        ?>
+        <a class="restore-default" href="#<?php echo $path ?>" title="<?php echo __('Restore default value') ?>" style="display:none"><img alt="restore-default" src="<?php echo $img_path ?>s_reload.png" width="16" height="16" /></a>
+        <?php
+    }
+    // this must match with displayErrors() in scripts/config.js
+    if ($has_errors) {
+        echo "\n        <dl class=\"inline_errors\">";
+        foreach ($opts['errors'] as $error) {
+            echo '<dd>' . htmlspecialchars($error) . '</dd>';
+        }
+        echo '</dl>';
+    }
+    ?>
+    </td>
+    <?php
+    if ($is_setup_script && isset($opts['userprefs_allow'])) {
+    ?>
+    <td class="userprefs-allow" title="<?php echo __('Allow users to customize this value') ?>">
+        <input type="checkbox" name="<?php echo $path ?>-userprefs-allow" <?php if ($opts['userprefs_allow']) echo 'checked="checked"' ?> />
+    </td>
+    <?php
+    } else if ($is_setup_script) {
+        echo '<td> </td>';
+    }
+    ?>
+</tr>
+<?php
+}
+
+/**
+ * Display group header
+ *
+ * @uses $GLOBALS['_FormDisplayGroup']
+ * @uses display_group_footer()
+ * @param string $header_text
+ */
+function display_group_header($header_text)
+{
+    global $_FormDisplayGroup;
+
+    if ($_FormDisplayGroup) {
+        display_group_footer();
+    }
+    $_FormDisplayGroup = true;
+    if (!$header_text) {
+        return;
+    }
+    $colspan = 2;
+    if (defined('PMA_SETUP') && PMA_SETUP) {
+        $colspan++;
+    }
+?>
+<tr class="group-header">
+    <th colspan="<?php echo $colspan ?>">
+        <?php echo $header_text ?>
+    </th>
+</tr>
+<?php
+}
+
+/**
+ * Display group footer
+ *
+ * @uses $GLOBALS['_FormDisplayGroup']
+ */
+function display_group_footer()
+{
+    global $_FormDisplayGroup;
+
+    $_FormDisplayGroup = false;
+}
+
+/**
+ * Displays bottom part of a fieldset
+ */
+function display_fieldset_bottom()
+{
+    $colspan = 2;
+    if (defined('PMA_SETUP') && PMA_SETUP) {
+        $colspan++;
+    }
+?>
+<tr>
+    <td colspan="<?php echo $colspan ?>" class="lastrow">
+        <input type="submit" name="submit_save" value="<?php echo __('Save') ?>" class="green" />
+        <input type="button" name="submit_reset" value="<?php echo __('Reset') ?>" />
+    </td>
+</tr>
+</table>
+</fieldset>
+
+<?php
+}
+
+/**
+ * Displays simple bottom part of a fieldset (without submit buttons)
+ */
+function display_fieldset_bottom_simple()
+{
+?>
+</table>
+</fieldset>
+
+<?php
+}
+
+/**
+ * Closes form tabs
+ */
+function display_tabs_bottom()
+{
+    echo "</div>\n";
+}
+
+/**
+ * Displays bottom part of the form
+ */
+function display_form_bottom()
+{
+    echo "</form>\n";
+}
+
+/**
+ * Appends JS validation code to $js_array
+ *
+ * @uses PMA_escapeJsString()
+ * @param string       $field_id
+ * @param string|array $validator
+ * @param array        $js_array
+ */
+function js_validate($field_id, $validators, &$js_array)
+{
+    foreach ((array)$validators as $validator) {
+        $validator = (array)$validator;
+        $v_name = array_shift($validator);
+        $v_args = array();
+        foreach ($validator as $arg) {
+            $v_args[] = PMA_escapeJsString($arg);
+        }
+        $v_args = $v_args ? ", ['" . implode("', '", $v_args) . "']" : '';
+        $js_array[] = "validateField('$field_id', '$v_name', true$v_args)";
+    }
+}
+
+/**
+ * Displays JavaScript code
+ *
+ * @param array $js_array
+ */
+function display_js($js_array)
+{
+    if (empty($js_array)) {
+        return;
+    }
+?>
+<script type="text/javascript">
+<?php echo implode(";\n", $js_array) . ";\n" ?>
+</script>
+<?php
+}
+
+/**
+ * Displays error list
+ *
+ * @param string $name
+ * @param array  $error_list
+ */
+function display_errors($name, $error_list)
+{
+    echo '<dl>';
+    echo '<dt>' . htmlspecialchars($name) . '</dt>';
+    foreach ($error_list as $error) {
+        echo '<dd>' . htmlspecialchars($error) . '</dd>';
+    }
+    echo '</dl>';
+}
+?>
\ No newline at end of file
diff --git a/libraries/config/config_functions.lib.php b/libraries/config/config_functions.lib.php
new file mode 100644
index 0000000..6f9aabb
--- /dev/null
+++ b/libraries/config/config_functions.lib.php
@@ -0,0 +1,100 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Common config manipulation functions
+ *
+ * @package phpMyAdmin
+ */
+
+/**
+ * Returns sanitized language string, taking into account our special codes
+ * for formatting. Takes variable number of arguments.
+ * Based on PMA_sanitize from sanitize.lib.php.
+ *
+ * @param  string  $lang_key key in $GLOBALS WITHOUT 'strSetup' prefix
+ * @param  mixed   $args     arguments for sprintf
+ * @return string
+ */
+function PMA_lang($lang_key)
+{
+    static $search, $replace;
+
+    // some quick cache'ing
+    if ($search === null) {
+        $replace_pairs = array(
+            '<'         => '<',
+            '>'         => '>',
+            '[em]'      => '<em>',
+            '[/em]'     => '</em>',
+            '[strong]'  => '<strong>',
+            '[/strong]' => '</strong>',
+            '[code]'    => '<code>',
+            '[/code]'   => '</code>',
+            '[kbd]'     => '<kbd>',
+            '[/kbd]'    => '</kbd>',
+            '[br]'      => '<br />',
+            '[sup]'     => '<sup>',
+            '[/sup]'    => '</sup>');
+        if (defined('PMA_SETUP')) {
+            $replace_pairs['[a at Documentation.html'] = '[a at ../Documentation.html';
+        }
+        $search = array_keys($replace_pairs);
+        $replace = array_values($replace_pairs);
+    }
+    $message = isset($GLOBALS["strConfig$lang_key"]) ? $GLOBALS["strConfig$lang_key"] : $lang_key;
+    $message = str_replace($search, $replace, $message);
+    // replace [a@"$1"]$2[/a] with <a href="$1">$2</a>
+    $message = preg_replace('#\[a@("?)([^\]]+)\1\]([^\[]+)\[/a\]#e',
+        "PMA_lang_link_replace('$2', '$3')", $message);
+
+    if (func_num_args() == 1) {
+        return $message;
+    } else {
+        $args = func_get_args();
+        array_shift($args);
+        return vsprintf($message, $args);
+    }
+}
+
+/**
+ * Returns translated field name/description or comment
+ *
+ * @param string $canonical_path
+ * @param string $type  'name', 'desc' or 'cmt'
+ * @param mixed  $default
+ * @return string
+ */
+function PMA_lang_name($canonical_path, $type = 'name', $default = 'key')
+{
+    $lang_key = str_replace(
+    	array('Servers/1/', '/'),
+    	array('Servers/', '_'),
+    	$canonical_path) . '_' . $type;
+    return isset($GLOBALS["strConfig$lang_key"])
+        ? ($type == 'desc' ? PMA_lang($lang_key) : $GLOBALS["strConfig$lang_key"])
+        : ($default == 'key' ? $lang_key : $default);
+}
+
+/**
+ * Wraps link in <a> tags and replaces argument separator in internal links
+ * to the one returned by PMA_get_arg_separator()
+ *
+ * @param string $link
+ * @param string $text
+ * @return string
+ */
+function PMA_lang_link_replace($link, $text)
+{
+    static $separator;
+
+    if (!isset($separator)) {
+        $separator = PMA_get_arg_separator('html');
+    }
+
+    if (!preg_match('#^http://#', $link)) {
+        $link = str_replace('&', $separator, $link);
+    }
+
+    return '<a href="' . $link . '">' . $text . '</a>';
+}
+?>
\ No newline at end of file
diff --git a/libraries/config/messages.inc.php b/libraries/config/messages.inc.php
new file mode 100644
index 0000000..7dc5c14
--- /dev/null
+++ b/libraries/config/messages.inc.php
@@ -0,0 +1,498 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Messages for phpMyAdmin.
+ *
+ * This file is here for easy transition to Gettext. You should not add any
+ * new messages here, use instead gettext directly in your template/PHP
+ * file.
+ *
+ * @package phpMyAdmin
+ */
+
+if (!function_exists('__')) {
+    die('Bad invocation!');
+}
+
+$strConfigAllowArbitraryServer_desc = __('If enabled user can enter any MySQL server in login form for cookie auth');
+$strConfigAllowArbitraryServer_name = __('Allow login to any MySQL server');
+$strConfigAllowThirdPartyFraming_desc = __('Enabling this allows a page located on a different domain to call phpMyAdmin inside a frame, and is a potential [strong]security hole[/strong] allowing cross-frame scripting attacks');
+$strConfigAllowThirdPartyFraming_name = __('Allow third party framing');
+$strConfigAllowUserDropDatabase_name = __('Show "Drop database" link to normal users');
+$strConfigblowfish_secret_desc = __('Secret passphrase used for encrypting cookies in [kbd]cookie[/kbd] authentication');
+$strConfigblowfish_secret_name = __('Blowfish secret');
+$strConfigBrowseMarkerEnable_desc = __('Highlight selected rows');
+$strConfigBrowseMarkerEnable_name = __('Row marker');
+$strConfigBrowsePointerEnable_desc = __('Highlight row pointed by the mouse cursor');
+$strConfigBrowsePointerEnable_name = __('Highlight pointer');
+$strConfigBZipDump_desc = __('Enable [a at http://en.wikipedia.org/wiki/Bzip2]bzip2[/a] compression for import and export operations');
+$strConfigBZipDump_name = __('Bzip2');
+$strConfigCharEditing_desc = __('Defines which type of editing controls should be used for CHAR and VARCHAR columns; [kbd]input[/kbd] - allows limiting of input length, [kbd]textarea[/kbd] - allows newlines in columns');
+$strConfigCharEditing_name = __('CHAR columns editing');
+$strConfigCharTextareaCols_desc = __('Number of columns for CHAR/VARCHAR textareas');
+$strConfigCharTextareaCols_name = __('CHAR textarea columns');
+$strConfigCharTextareaRows_desc = __('Number of rows for CHAR/VARCHAR textareas');
+$strConfigCharTextareaRows_name = __('CHAR textarea rows');
+$strConfigCheckConfigurationPermissions_name = __('Check config file permissions');
+$strConfigCompressOnFly_desc = __('Compress gzip/bzip2 exports on the fly without the need for much memory; if you encounter problems with created gzip/bzip2 files disable this feature');
+$strConfigCompressOnFly_name = __('Compress on the fly');
+$strConfigConfigurationFile = __('Configuration file');
+$strConfigConfirm_desc = __('Whether a warning ("Are your really sure...") should be displayed when you\'re about to lose data');
+$strConfigConfirm_name = __('Confirm DROP queries');
+$strConfigCtrlArrowsMoving_name = __('Field navigation using Ctrl+Arrows');
+$strConfigDBG_php_name = __('Debug PHP');
+$strConfigDBG_sql_name = __('Debug SQL');
+$strConfigDefaultDisplay_name = __('Default display direction');
+$strConfigDefaultPropDisplay_desc = __('[kbd]horizontal[/kbd], [kbd]vertical[/kbd] or a number that indicates maximum number for which vertical model is used');
+$strConfigDefaultPropDisplay_name = __('Display direction for altering/creating columns');
+$strConfigDefaultTabDatabase_desc = __('Tab that is displayed when entering a database');
+$strConfigDefaultTabDatabase_name = __('Default database tab');
+$strConfigDefaultTabServer_desc = __('Tab that is displayed when entering a server');
+$strConfigDefaultTabServer_name = __('Default server tab');
+$strConfigDefaultTabTable_desc = __('Tab that is displayed when entering a table');
+$strConfigDefaultTabTable_name = __('Default table tab');
+$strConfigDisplayBinaryAsHex_desc = __('Show binary contents as HEX by default');
+$strConfigDisplayBinaryAsHex_name = __('Show binary contents as HEX');
+$strConfigDisplayDatabasesList_desc = __('Show database listing as a list instead of a drop down');
+$strConfigDisplayDatabasesList_name = __('Display databases as a list');
+$strConfigDisplayServersList_desc = __('Show server listing as a list instead of a drop down');
+$strConfigDisplayServersList_name = __('Display servers as a list');
+$strConfigEditInWindow_desc = __('Edit SQL queries in popup window');
+$strConfigEditInWindow_name = __('Edit in window');
+$strConfigError_Handler_display_name = __('Display errors');
+$strConfigError_Handler_gather_name = __('Gather errors');
+$strConfigErrorIconic_desc = __('Show icons for warning, error and information messages');
+$strConfigErrorIconic_name = __('Iconic errors');
+$strConfigExecTimeLimit_desc = __('Set the number of seconds a script is allowed to run ([kbd]0[/kbd] for no limit)');
+$strConfigExecTimeLimit_name = __('Maximum execution time');
+$strConfigExport_asfile_name = __('Save as file');
+$strConfigExport_charset_name = __('Character set of the file');
+$strConfigExport_codegen_format_name = __('Format');
+$strConfigExport_compression_name = __('Compression');
+$strConfigExport_csv_columns_name = __('Put columns names in the first row');
+$strConfigExport_csv_enclosed_name = __('Columns enclosed by');
+$strConfigExport_csv_escaped_name = __('Columns escaped by');
+$strConfigExport_csv_null_name = __('Replace NULL by');
+$strConfigExport_csv_removeCRLF_name = __('Remove CRLF characters within columns');
+$strConfigExport_csv_separator_name = __('Columns terminated by');
+$strConfigExport_csv_terminated_name = __('Lines terminated by');
+$strConfigExport_excel_columns_name = __('Put columns names in the first row');
+$strConfigExport_excel_edition_name = __('Excel edition');
+$strConfigExport_excel_null_name = __('Replace NULL by');
+$strConfigExport_excel_removeCRLF_name = __('Remove CRLF characters within columns');
+$strConfigExport_file_template_database_name = __('Database name template');
+$strConfigExport_file_template_server_name = __('Server name template');
+$strConfigExport_file_template_table_name = __('Table name template');
+$strConfigExport_format_name = __('Format');
+$strConfigExport_htmlword_columns_name = __('Put columns names in the first row');
+$strConfigExport_htmlword_null_name = __('Replace NULL by');
+$strConfigExport_htmlword_structure_or_data_name = __('Dump table');
+$strConfigExport_latex_caption_name = __('Include table caption');
+$strConfigExport_latex_columns_name = __('Put columns names in the first row');
+$strConfigExport_latex_comments_name = __('Comments');
+$strConfigExport_latex_data_caption_name = __('Table caption');
+$strConfigExport_latex_data_continued_caption_name = __('Continued table caption');
+$strConfigExport_latex_data_label_name = __('Label key');
+$strConfigExport_latex_mime_name = __('MIME type');
+$strConfigExport_latex_null_name  = __('Replace NULL by');
+$strConfigExport_latex_relation_name = __('Relations');
+$strConfigExport_latex_structure_caption_name = __('Table caption');
+$strConfigExport_latex_structure_continued_caption_name = __('Continued table caption');
+$strConfigExport_latex_structure_label_name = __('Label key');
+$strConfigExport_latex_structure_or_data_name = __('Dump table');
+$strConfigExport_method_name = __('Export method');
+$strConfigExport_ods_columns_name = __('Put columns names in the first row');
+$strConfigExport_ods_null_name = __('Replace NULL by');
+$strConfigExport_odt_columns_name = __('Put columns names in the first row');
+$strConfigExport_odt_comments_name = __('Comments');
+$strConfigExport_odt_mime_name = __('MIME type');
+$strConfigExport_odt_null_name = __('Replace NULL by');
+$strConfigExport_odt_relation_name = __('Relations');
+$strConfigExport_odt_structure_or_data_name = __('Dump table');
+$strConfigExport_onserver_name = __('Save on server');
+$strConfigExport_onserver_overwrite_name = __('Overwrite existing file(s)');
+$strConfigExport_remember_file_template_name = __('Remember file name template');
+$strConfigExport_sql_auto_increment_name = __('Add AUTO_INCREMENT value');
+$strConfigExport_sql_backquotes_name = __('Enclose table and column names with backquotes');
+$strConfigExport_sql_compatibility_name = __('SQL compatibility mode');
+$strConfigExport_sql_create_table_statements_name = __('Syntax to use when inserting data');
+$strConfigExport_sql_dates_name = __('Creation/Update/Check dates');
+$strConfigExport_sql_delayed_name = __('Use delayed inserts');
+$strConfigExport_sql_disable_fk_name = __('Disable foreign key checks');
+$strConfigExport_sql_drop_database_name = sprintf(__('Add %s'), 'DROP DATABASE');
+$strConfigExport_sql_drop_table_name = sprintf(__('Add %s'), 'DROP TABLE / VIEW / PROCEDURE / FUNCTION / EVENT');
+$strConfigExport_sql_hex_for_blob_name = __('Use hexadecimal for BLOB');
+$strConfigExport_sql_if_not_exists_name = sprintf(__('Add %s'), 'IF NOT EXISTS');
+$strConfigExport_sql_ignore_name = __('Use ignore inserts');
+$strConfigExport_sql_include_comments_name = __('Comments');
+$strConfigExport_sql_max_query_size_name = __('Maximal length of created query');
+$strConfigExport_sql_mime_name = __('MIME type');
+$strConfigExport_sql_procedure_function_name = sprintf(__('Add %s'), 'CREATE PROCEDURE / FUNCTION / EVENT');
+$strConfigExport_sql_relation_name = __('Relations');
+$strConfigExport_sql_structure_or_data_name = __('Dump table');
+$strConfigExport_sql_type_name = __('Export type');
+$strConfigExport_sql_use_transaction_name = __('Enclose export in a transaction');
+$strConfigExport_sql_utc_time_name = __('Export time in UTC');
+$strConfigExport_texytext_columns_name = __('Put columns names in the first row');
+$strConfigExport_texytext_null_name = __('Replace NULL by');
+$strConfigExport_texytext_structure_or_data_name = __('Dump table');
+$strConfigExport_xls_columns_name = __('Put columns names in the first row');
+$strConfigExport_xls_null_name = __('Replace NULL by');
+$strConfigExport_xlsx_columns_name = __('Put columns names in the first row');
+$strConfigExport_xlsx_null_name = __('Replace NULL by');
+$strConfigForceSSL_desc = __('Force secured connection while using phpMyAdmin');
+$strConfigForceSSL_name = __('Force SSL connection');
+$strConfigForeignKeyDropdownOrder_desc = __('Sort order for items in a foreign-key dropdown box; [kbd]content[/kbd] is the referenced data, [kbd]id[/kbd] is the key value');
+$strConfigForeignKeyDropdownOrder_name = __('Foreign key dropdown order');
+$strConfigForeignKeyMaxLimit_desc = __('A dropdown will be used if fewer items are present');
+$strConfigForeignKeyMaxLimit_name = __('Foreign key limit');
+$strConfigForm_Browse = __('Browse mode');
+$strConfigForm_Browse_desc = __('Customize browse mode');
+$strConfigForm_CodeGen = 'CodeGen';
+$strConfigForm_CodeGen_desc = __('Customize default options');
+$strConfigForm_Csv = __('CSV');
+$strConfigForm_Csv_desc = __('Customize default options');
+$strConfigForm_Developer = __('Developer');
+$strConfigForm_Developer_desc = __('Settings for phpMyAdmin developers');
+$strConfigForm_Edit = __('Edit mode');
+$strConfigForm_Edit_desc = __('Customize edit mode');
+$strConfigForm_Export = __('Export');
+$strConfigForm_Export_defaults = __('Export defaults');
+$strConfigForm_Export_defaults_desc = __('Customize default export options');
+$strConfigForm_Features = __('Features');
+$strConfigForm_General = __('General');
+$strConfigForm_General_desc = __('Set some commonly used options');
+$strConfigForm_Import = __('Import');
+$strConfigForm_Import_defaults = __('Import defaults');
+$strConfigForm_Import_defaults_desc = __('Customize default common import options');
+$strConfigForm_Import_export = __('Import / export');
+$strConfigForm_Import_export_desc = __('Set import and export directories and compression options');
+$strConfigForm_Latex = __('LaTeX');
+$strConfigForm_Latex_desc = __('Customize default options');
+$strConfigForm_Left_databases = __('Databases');
+$strConfigForm_Left_databases_desc = __('Databases display options');
+$strConfigForm_Left_frame = __('Navigation frame');
+$strConfigForm_Left_frame_desc = __('Customize appearance of the navigation frame');
+$strConfigForm_Left_servers = __('Servers');
+$strConfigForm_Left_servers_desc = __('Servers display options');
+$strConfigForm_Left_tables = __('Tables');
+$strConfigForm_Left_tables_desc = __('Tables display options');
+$strConfigForm_Main_frame = __('Main frame');
+$strConfigForm_Microsoft_Office = __('Microsoft Office');
+$strConfigForm_Microsoft_Office_desc = __('Customize default options');
+$strConfigForm_Open_Document = __('Open Document');
+$strConfigForm_Open_Document_desc = __('Customize default options');
+$strConfigForm_Other_core_settings = __('Other core settings');
+$strConfigForm_Other_core_settings_desc = __('Settings that didn\'t fit enywhere else');
+$strConfigForm_Page_titles = __('Page titles');
+$strConfigForm_Page_titles_desc = __('Specify browser\'s title bar text. Refer to [a at Documentation.html#cfg_TitleTable]documentation[/a] for magic strings that can be used to get special values.');
+$strConfigForm_Query_window = __('Query window');
+$strConfigForm_Query_window_desc = __('Customize query window options');
+$strConfigForm_Security = __('Security');
+$strConfigForm_Security_desc = __('Please note that phpMyAdmin is just a user interface and its features do not limit MySQL');
+$strConfigForm_Server = __('Basic settings');
+$strConfigForm_Server_auth = __('Authentication');
+$strConfigForm_Server_auth_desc = __('Authentication settings');
+$strConfigForm_Server_config = __('Server configuration');
+$strConfigForm_Server_config_desc = __('Advanced server configuration, do not change these options unless you know what they are for');
+$strConfigForm_Server_desc = __('Enter server connection parameters');
+$strConfigForm_Server_pmadb = __('Configuration storage');
+$strConfigForm_Server_pmadb_desc = __('Configure phpMyAdmin configuration storage to gain access to additional features, see [a at Documentation.html#linked-tables]phpMyAdmin configuration storage[/a] in documentation');
+$strConfigForm_Server_tracking = __('Changes tracking');
+$strConfigForm_Server_tracking_desc = __('Tracking of changes made in database. Requires configured PMA database.');
+$strConfigFormset_Export = __('Customize export options');
+$strConfigFormset_Features = __('Features');
+$strConfigFormset_Import = __('Customize import defaults');
+$strConfigFormset_Left_frame = __('Customize navigation frame');
+$strConfigFormset_Main_frame = __('Customize main frame');
+$strConfigFormset_Sql_queries = __('SQL queries');
+$strConfigForm_Sql = __('SQL');
+$strConfigForm_Sql_box = __('SQL Query box');
+$strConfigForm_Sql_box_desc = __('Customize links shown in SQL Query boxes');
+$strConfigForm_Sql_desc = __('Customize default options');
+$strConfigForm_Sql_queries = __('SQL queries');
+$strConfigForm_Sql_queries_desc = __('SQL queries settings');
+$strConfigForm_Sql_validator = __('SQL Validator');
+$strConfigForm_Sql_validator_desc = __('If you wish to use the SQL Validator service, you should be aware that [strong]all SQL statements are stored anonymously for statistical purposes[/strong].[br][em][a at http://sqlvalidator.mimer.com/]Mimer SQL Validator[/a], Copyright 2002 Upright Database Technology. All rights reserved.[/em]');
+$strConfigForm_Startup = __('Startup');
+$strConfigForm_Startup_desc = __('Customize startup page');
+$strConfigForm_Tabs = __('Tabs');
+$strConfigForm_Tabs_desc = __('Choose how you want tabs to work');
+$strConfigForm_Text_fields = __('Text fields');
+$strConfigForm_Text_fields_desc = __('Customize text input fields');
+$strConfigForm_Texy = __('Texy! text');
+$strConfigForm_Texy_desc = __('Customize default options');
+$strConfigForm_Warnings = __('Warnings');
+$strConfigForm_Warnings_desc = __('Disable some of the warnings shown by phpMyAdmin');
+$strConfigGZipDump_desc = __('Enable [a at http://en.wikipedia.org/wiki/Gzip]gzip[/a] compression for import and export operations');
+$strConfigGZipDump_name = __('GZip');
+$strConfigIconvExtraParams_name = __('Extra parameters for iconv');
+$strConfigIgnoreMultiSubmitErrors_desc = __('If enabled, phpMyAdmin continues computing multiple-statement queries even if one of the queries failed');
+$strConfigIgnoreMultiSubmitErrors_name = __('Ignore multiple statement errors');
+$strConfigImport_allow_interrupt_desc = __('Allow interrupt of import in case script detects it is close to time limit. This might be good way to import large files, however it can break transactions.');
+$strConfigImport_allow_interrupt_name = __('Partial import: allow interrupt');
+$strConfigImport_charset_name = __('Character set of the file');
+$strConfigImport_csv_col_names_name = __('Lines terminated by');
+$strConfigImport_csv_enclosed_name = __('Columns enclosed by');
+$strConfigImport_csv_escaped_name = __('Columns escaped by');
+$strConfigImport_csv_ignore_name = __('Ignore duplicate rows');
+$strConfigImport_csv_replace_name = __('Replace table data with file');
+$strConfigImport_csv_terminated_name = __('Columns terminated by');
+$strConfigImport_format_desc = __('Default format; be aware that this list depends on location (database, table) and only SQL is always available');
+$strConfigImport_format_name = __('Format of imported file');
+$strConfigImport_ldi_enclosed_name = __('Columns enclosed by');
+$strConfigImport_ldi_escaped_name = __('Columns escaped by');
+$strConfigImport_ldi_ignore_name = __('Ignore duplicate rows');
+$strConfigImport_ldi_local_option_name = __('Use LOCAL keyword');
+$strConfigImport_ldi_replace_name = __('Replace table data with file');
+$strConfigImport_ldi_terminated_name = __('Columns terminated by');
+$strConfigImport_ods_col_names_name = __('Column names in first row');
+$strConfigImport_ods_empty_rows_name = __('Do not import empty rows');
+$strConfigImport_ods_recognize_currency_name = __('Import currencies ($5.00 to 5.00)');
+$strConfigImport_ods_recognize_percentages_name = __('Import percentages as proper decimals (12.00% to .12)');
+$strConfigImport_skip_queries_desc = __('Number of queries to skip from start');
+$strConfigImport_skip_queries_name = __('Partial import: skip queries');
+$strConfigImport_sql_compatibility_name = __('SQL compatibility mode');
+$strConfigImport_sql_no_auto_value_on_zero_name = __('Do not use AUTO_INCREMENT for zero values');
+$strConfigImport_xls_col_names_name = __('Column names in first row');
+$strConfigImport_xlsx_col_names_name = __('Column names in first row');
+$strConfigInitialSlidersState_name = __('Initial state for sliders');
+$strConfigInsertRows_desc = __('How many rows can be inserted at one time');
+$strConfigInsertRows_name = __('Number of inserted rows');
+$strConfigLeftDefaultTabTable_name = __('Target for quick access icon');
+$strConfigLeftDisplayLogo_desc = __('Show logo in left frame');
+$strConfigLeftDisplayLogo_name = __('Display logo');
+$strConfigLeftDisplayServers_desc = __('Display server choice at the top of the left frame');
+$strConfigLeftDisplayServers_name = __('Display servers selection');
+$strConfigLeftFrameDBSeparator_desc = __('String that separates databases into different tree levels');
+$strConfigLeftFrameDBSeparator_name = __('Database tree separator');
+$strConfigLeftFrameDBTree_desc = __('Only light version; display databases in a tree (determined by the separator defined below)');
+$strConfigLeftFrameDBTree_name = __('Display databases in a tree');
+$strConfigLeftFrameLight_desc = __('Disable this if you want to see all databases at once');
+$strConfigLeftFrameLight_name = __('Use light version');
+$strConfigLeftFrameTableLevel_name = __('Maximum table tree depth');
+$strConfigLeftFrameTableSeparator_desc = __('String that separates tables into different tree levels');
+$strConfigLeftFrameTableSeparator_name = __('Table tree separator');
+$strConfigLeftLogoLink_desc = __('URL where logo in the navigation frame will point to');
+$strConfigLeftLogoLink_name = __('Logo link URL');
+$strConfigLeftLogoLinkWindow_desc = __('Open the linked page in the main window ([kbd]main[/kbd]) or in a new one ([kbd]new[/kbd])');
+$strConfigLeftLogoLinkWindow_name = __('Logo link target');
+$strConfigLeftPointerEnable_desc = __('Highlight server under the mouse cursor');
+$strConfigLeftPointerEnable_name = __('Enable highlighting');
+$strConfigLightTabs_desc = __('Use less graphically intense tabs');
+$strConfigLightTabs_name = __('Light tabs');
+$strConfigLimitChars_desc = __('Maximum number of characters shown in any non-numeric column on browse view');
+$strConfigLimitChars_name = __('Limit column characters');
+$strConfigLoginCookieDeleteAll_desc = __('If TRUE, logout deletes cookies for all servers; when set to FALSE, logout only occurs for the current server. Setting this to FALSE makes it easy to forget to log out from other servers when connected to multiple servers.');
+$strConfigLoginCookieDeleteAll_name = __('Delete all cookies on logout');
+$strConfigLoginCookieRecall_desc = __('Define whether the previous login should be recalled or not in cookie authentication mode');
+$strConfigLoginCookieRecall_name = __('Recall user name');
+$strConfigLoginCookieStore_desc = __('Defines how long (in seconds) a login cookie should be stored in browser. The default of 0 means that it will be kept for the existing session only, and will be deleted as soon as you close the browser window. This is recommended for non-trusted environments.');
+$strConfigLoginCookieStore_name = __('Login cookie store');
+$strConfigLoginCookieValidity_desc = __('Define how long (in seconds) a login cookie is valid');
+$strConfigLoginCookieValidity_name = __('Login cookie validity');
+$strConfigLongtextDoubleTextarea_desc = __('Double size of textarea for LONGTEXT fields');
+$strConfigLongtextDoubleTextarea_name = __('Bigger textarea for LONGTEXT');
+$strConfigMainPageIconic_name = __('Use icons on main page');
+$strConfigMaxCharactersInDisplayedSQL_desc = __('Maximum number of characters used when a SQL query is displayed');
+$strConfigMaxCharactersInDisplayedSQL_name = __('Maximum displayed SQL length');
+$strConfigMaxDbList_cmt = __('Users cannot set a higher value');
+$strConfigMaxDbList_desc = __('Maximum number of databases displayed in left frame and database list');
+$strConfigMaxDbList_name = __('Maximum databases');
+$strConfigMaxRows_desc = __('Number of rows displayed when browsing a result set. If the result set contains more rows, "Previous" and "Next" links will be shown.');
+$strConfigMaxRows_name = __('Maximum number of rows to display');
+$strConfigMaxTableList_cmt = __('Users cannot set a higher value');
+$strConfigMaxTableList_desc = __('Maximum number of tables displayed in table list');
+$strConfigMaxTableList_name = __('Maximum tables');
+$strConfigMcryptDisableWarning_desc = __('Disable the default warning that is displayed if mcrypt is missing for cookie authentication');
+$strConfigMcryptDisableWarning_name = __('mcrypt warning');
+$strConfigMemoryLimit_desc = __('The number of bytes a script is allowed to allocate, eg. [kbd]32M[/kbd] ([kbd]0[/kbd] for no limit)');
+$strConfigMemoryLimit_name = __('Memory limit');
+$strConfigModifyDeleteAtLeft_name = __('Show left delete link');
+$strConfigModifyDeleteAtRight_name = __('Show right delete link');
+$strConfigNaturalOrder_desc = __('Use natural order for sorting table and database names');
+$strConfigNaturalOrder_name = __('Natural order');
+$strConfigNavigationBarIconic_desc = __('Use only icons, only text or both');
+$strConfigNavigationBarIconic_name = __('Iconic navigation bar');
+$strConfigOBGzip_desc = __('use GZip output buffering for increased speed in HTTP transfers');
+$strConfigOBGzip_name = __('GZip output buffering');
+$strConfigOrder_desc = __('[kbd]SMART[/kbd] - i.e. descending order for columns of type TIME, DATE, DATETIME and TIMESTAMP, ascending order otherwise');
+$strConfigOrder_name = __('Default sorting order');
+$strConfigPersistentConnections_desc = __('Use persistent connections to MySQL databases');
+$strConfigPersistentConnections_name = __('Persistent connections');
+$strConfigPmaNoRelation_DisableWarning_desc = __('Disable the default warning that is displayed on the database details Structure page if any of the required tables for the relation features could not be found');
+$strConfigPmaNoRelation_DisableWarning_name = __('Missing phpMyAdmin configuration storage tables');
+$strConfigPropertiesIconic_desc = __('Use only icons, only text or both');
+$strConfigPropertiesIconic_name = __('Iconic table operations');
+$strConfigProtectBinary_desc = __('Disallow BLOB and BINARY columns from editing');
+$strConfigProtectBinary_name = __('Protect binary columns');
+$strConfigQueryHistoryDB_desc = __('Enable if you want DB-based query history (requires phpMyAdmin configuration storage). If disabled, this utilizes JS-routines to display query history (lost by window close).');
+$strConfigQueryHistoryDB_name = __('Permanent query history');
+$strConfigQueryHistoryMax_cmt = __('Users cannot set a higher value');
+$strConfigQueryHistoryMax_desc = __('How many queries are kept in history');
+$strConfigQueryHistoryMax_name = __('Query history length');
+$strConfigQueryWindowDefTab_desc = __('Tab displayed when opening a new query window');
+$strConfigQueryWindowDefTab_name = __('Default query window tab');
+$strConfigQueryWindowHeight_desc = __('Query window height (in pixels)');
+$strConfigQueryWindowHeight_name = __('Query window height');
+$strConfigQueryWindowWidth_desc = __('Query window height (in pixels)');
+$strConfigQueryWindowWidth_name = __('Query window width');
+$strConfigRecodingEngine_desc = __('Select which functions will be used for character set conversion');
+$strConfigRecodingEngine_name = __('Recoding engine');
+$strConfigRepeatCells_desc = __('Repeat the headers every X cells, [kbd]0[/kbd] deactivates this feature');
+$strConfigRepeatCells_name = __('Repeat headers');
+$strConfigReplaceHelpImg_desc = __('Show help button instead of Documentation text');
+$strConfigReplaceHelpImg_name = __('Show help button');
+$strConfigRestoreDefaultValue = __('Restore default value');
+$strConfigSaveDir_desc = __('Directory where exports can be saved on server');
+$strConfigSaveDir_name = __('Save directory');
+$strConfigServers_AllowDeny_order_desc = __('Leave blank if not used');
+$strConfigServers_AllowDeny_order_name = __('Host authorization order');
+$strConfigServers_AllowDeny_rules_desc = __('Leave blank for defaults');
+$strConfigServers_AllowDeny_rules_name = __('Host authorization rules');
+$strConfigServers_AllowNoPassword_name = __('Allow logins without a password');
+$strConfigServers_AllowRoot_name = __('Allow root login');
+$strConfigServers_auth_http_realm_desc = __('HTTP Basic Auth Realm name to display when doing HTTP Auth');
+$strConfigServers_auth_http_realm_name = __('HTTP Realm');
+$strConfigServers_auth_swekey_config_desc = __('The path for the config file for [a at http://swekey.com]SweKey hardware authentication[/a] (not located in your document root; suggested: /etc/swekey.conf)');
+$strConfigServers_auth_swekey_config_name = __('SweKey config file');
+$strConfigServers_auth_type_desc = __('Authentication method to use');
+$strConfigServers_auth_type_name = __('Authentication type');
+$strConfigServers_bookmarktable_desc = __('Leave blank for no [a at http://wiki.phpmyadmin.net/pma/bookmark]bookmark[/a] support, suggested: [kbd]pma_bookmark[/kbd]');
+$strConfigServers_bookmarktable_name = __('Bookmark table');
+$strConfigServers_column_info_desc = __('Leave blank for no column comments/mime types, suggested: [kbd]pma_column_info[/kbd]');
+$strConfigServers_column_info_name = __('Column information table');
+$strConfigServers_compress_desc = __('Compress connection to MySQL server');
+$strConfigServers_compress_name = __('Compress connection');
+$strConfigServers_connect_type_desc = __('How to connect to server, keep [kbd]tcp[/kbd] if unsure');
+$strConfigServers_connect_type_name = __('Connection type');
+$strConfigServers_controlpass_name = __('Control user password');
+$strConfigServers_controluser_desc = __('A special MySQL user configured with limited permissions, more information available on [a at http://wiki.phpmyadmin.net/pma/controluser]wiki[/a]');
+$strConfigServers_controluser_name = __('Control user');
+$strConfigServers_CountTables_desc = __('Count tables when showing database list');
+$strConfigServers_CountTables_name = __('Count tables');
+$strConfigServers_designer_coords_desc = __('Leave blank for no Designer support, suggested: [kbd]pma_designer_coords[/kbd]');
+$strConfigServers_designer_coords_name = __('Designer table');
+$strConfigServers_DisableIS_desc = __('More information on [a at http://sf.net/support/tracker.php?aid=1849494]PMA bug tracker[/a] and [a at http://bugs.mysql.com/19588]MySQL Bugs[/a]');
+$strConfigServers_DisableIS_name = __('Disable use of INFORMATION_SCHEMA');
+$strConfigServers_extension_desc = __('What PHP extension to use; you should use mysqli if supported');
+$strConfigServers_extension_name = __('PHP extension to use');
+$strConfigServers_hide_db_desc = __('Hide databases matching regular expression (PCRE)');
+$strConfigServers_hide_db_name = __('Hide databases');
+$strConfigServers_history_desc = __('Leave blank for no SQL query history support, suggested: [kbd]pma_history[/kbd]');
+$strConfigServers_history_name = __('SQL query history table');
+$strConfigServers_host_desc = __('Hostname where MySQL server is running');
+$strConfigServers_host_name = __('Server hostname');
+$strConfigServers_LogoutURL_name = __('Logout URL');
+$strConfigServers_nopassword_desc = __('Try to connect without password');
+$strConfigServers_nopassword_name = __('Connect without password');
+$strConfigServers_only_db_desc = __('You can use MySQL wildcard characters (% and _), escape them if you want to use their literal instances, i.e. use [kbd]\'my\_db\'[/kbd] and not [kbd]\'my_db\'[/kbd]. Using this option you can sort database list, just enter their names in order and use [kbd]*[/kbd] at the end to show the rest in alphabetical order.');
+$strConfigServers_only_db_name = __('Show only listed databases');
+$strConfigServers_password_desc = __('Leave empty if not using config auth');
+$strConfigServers_password_name = __('Password for config auth');
+$strConfigServers_pdf_pages_desc = __('Leave blank for no PDF schema support, suggested: [kbd]pma_pdf_pages[/kbd]');
+$strConfigServers_pdf_pages_name = __('PDF schema: pages table');
+$strConfigServers_pmadb_desc = __('Database used for relations, bookmarks, and PDF features. See [a at http://wiki.phpmyadmin.net/pma/pmadb]pmadb[/a] for complete information. Leave blank for no support. Suggested: [kbd]phpmyadmin[/kbd]');
+$strConfigServers_pmadb_name = __('Database name');
+$strConfigServers_port_desc = __('Port on which MySQL server is listening, leave empty for default');
+$strConfigServers_port_name = __('Server port');
+$strConfigServers_relation_desc = __('Leave blank for no [a at http://wiki.phpmyadmin.net/pma/relation]relation-links[/a] support, suggested: [kbd]pma_relation[/kbd]');
+$strConfigServers_relation_name = __('Relation table');
+$strConfigServers_ShowDatabasesCommand_desc = __('SQL command to fetch available databases');
+$strConfigServers_ShowDatabasesCommand_name = __('SHOW DATABASES command');
+$strConfigServers_SignonSession_desc = __('See [a at http://wiki.phpmyadmin.net/pma/auth_types#signon]authentication types[/a] for an example');
+$strConfigServers_SignonSession_name = __('Signon session name');
+$strConfigServers_SignonURL_name = __('Signon URL');
+$strConfigServers_socket_desc = __('Socket on which MySQL server is listening, leave empty for default');
+$strConfigServers_socket_name = __('Server socket');
+$strConfigServers_ssl_desc = __('Enable SSL for connection to MySQL server');
+$strConfigServers_ssl_name = __('Use SSL');
+$strConfigServers_table_coords_desc = __('Leave blank for no PDF schema support, suggested: [kbd]pma_table_coords[/kbd]');
+$strConfigServers_table_coords_name = __('PDF schema: table coordinates');
+$strConfigServers_table_info_desc = __('Table to describe the display columns, leave blank for no support; suggested: [kbd]pma_table_info[/kbd]');
+$strConfigServers_table_info_name = __('Display columns table');
+$strConfigServers_tracking_add_drop_database_desc = __('Whether a DROP DATABASE IF EXISTS statement will be added as first line to the log when creating a database.');
+$strConfigServers_tracking_add_drop_database_name = __('Add DROP DATABASE');
+$strConfigServers_tracking_add_drop_table_desc = __('Whether a DROP TABLE IF EXISTS statement will be added as first line to the log when creating a table.');
+$strConfigServers_tracking_add_drop_table_name = __('Add DROP TABLE');
+$strConfigServers_tracking_add_drop_view_desc = __('Whether a DROP VIEW IF EXISTS statement will be added as first line to the log when creating a view.');
+$strConfigServers_tracking_add_drop_view_name = __('Add DROP VIEW');
+$strConfigServers_tracking_default_statements_desc = __('Defines the list of statements the auto-creation uses for new versions.');
+$strConfigServers_tracking_default_statements_name = __('Statements to track');
+$strConfigServers_tracking_desc = __('Leave blank for no SQL query tracking support, suggested: [kbd]pma_tracking[/kbd]');
+$strConfigServers_tracking_name = __('SQL query tracking table');
+$strConfigServers_tracking_version_auto_create_desc = __('Whether the tracking mechanism creates versions for tables and views automatically.');
+$strConfigServers_tracking_version_auto_create_name = __('Automatically create versions');
+$strConfigServers_userconfig_desc = __('Leave blank for no user preferences storage in database, suggested: [kbd]pma_config[/kbd]');
+$strConfigServers_userconfig_name = __('User preferences storage table');
+$strConfigServers_user_desc = __('Leave empty if not using config auth');
+$strConfigServers_user_name = __('User for config auth');
+$strConfigServers_verbose_check_desc = __('Disable if you know that your pma_* tables are up to date. This prevents compatibility checks and thereby increases performance');
+$strConfigServers_verbose_check_name = __('Verbose check');
+$strConfigServers_verbose_desc = __('A user-friendly description of this server. Leave blank to display the hostname instead.');
+$strConfigServers_verbose_name = __('Verbose name of this server');
+$strConfigShowAll_desc = __('Whether a user should be displayed a "show all (rows)" button');
+$strConfigShowAll_name = __('Allow to display all the rows');
+$strConfigShowChgPassword_desc = __('Please note that enabling this has no effect with [kbd]config[/kbd] authentication mode because the password is hard coded in the configuration file; this does not limit the ability to execute the same command directly');
+$strConfigShowChgPassword_name = __('Show password change form');
+$strConfigShowCreateDb_name = __('Show create database form');
+$strConfigShowFieldTypesInDataEditView_desc = __('Defines whether or not type fields should be initially displayed in edit/insert mode');
+$strConfigShowFieldTypesInDataEditView_name = __('Show field types');
+$strConfigShowFunctionFields_desc = __('Display the function fields in edit/insert mode');
+$strConfigShowFunctionFields_name = __('Show function fields');
+$strConfigShowPhpInfo_desc = __('Shows link to [a at http://php.net/manual/function.phpinfo.php]phpinfo()[/a] output');
+$strConfigShowPhpInfo_name = __('Show phpinfo() link');
+$strConfigShowServerInfo_name = __('Show detailed MySQL server information');
+$strConfigShowSQL_desc = __('Defines whether SQL queries generated by phpMyAdmin should be displayed');
+$strConfigShowSQL_name = __('Show SQL queries');
+$strConfigShowStats_desc = __('Allow to display database and table statistics (eg. space usage)');
+$strConfigShowStats_name = __('Show statistics');
+$strConfigShowTooltipAliasDB_desc = __('If tooltips are enabled and a database comment is set, this will flip the comment and the real name');
+$strConfigShowTooltipAliasDB_name = __('Display database comment instead of its name');
+$strConfigShowTooltipAliasTB_desc = __('When setting this to [kbd]nested[/kbd], the alias of the table name is only used to split/nest the tables according to the $cfg[\'LeftFrameTableSeparator\'] directive, so only the folder is called like the alias, the table name itself stays unchanged');
+$strConfigShowTooltipAliasTB_name = __('Display table comment instead of its name');
+$strConfigShowTooltip_name = __('Display table comments in tooltips');
+$strConfigSkipLockedTables_desc = __('Mark used tables and make it possible to show databases with locked tables');
+$strConfigSkipLockedTables_name = __('Skip locked tables');
+$strConfigSQLQuery_Edit_name = __('Edit');
+$strConfigSQLQuery_Explain_name = __('Explain SQL');
+$strConfigSQLQuery_Refresh_name = __('Refresh');
+$strConfigSQLQuery_ShowAsPHP_name = __('Create PHP Code');
+$strConfigSQLQuery_Validate_desc = __('Requires SQL Validator to be enabled');
+$strConfigSQLQuery_Validate_name = __('Validate SQL');
+$strConfigSQLValidator_password_name = __('Password');
+$strConfigSQLValidator_use_desc = __('[strong]Warning:[/strong] requires PHP SOAP extension or PEAR SOAP to be installed');
+$strConfigSQLValidator_use_name = __('Enable SQL Validator');
+$strConfigSQLValidator_username_desc = __('If you have a custom username, specify it here (defaults to [kbd]anonymous[/kbd])');
+$strConfigSQLValidator_username_name = __('Username');
+$strConfigSuggestDBName_desc = __('Suggest a database name on the "Create Database" form (if possible) or keep the text field empty');
+$strConfigSuggestDBName_name = __('Suggest new database name');
+$strConfigSuhosinDisableWarning_desc = __('A warning is displayed on the main page if Suhosin is detected');
+$strConfigSuhosinDisableWarning_name = __('Suhosin warning');
+$strConfigTextareaCols_desc = __('Textarea size (columns) in edit mode, this value will be emphasized for SQL query textareas (*2) and for query window (*1.25)');
+$strConfigTextareaCols_name = __('Textarea columns');
+$strConfigTextareaRows_desc = __('Textarea size (rows) in edit mode, this value will be emphasized for SQL query textareas (*2) and for query window (*1.25)');
+$strConfigTextareaRows_name = __('Textarea rows');
+$strConfigTitleDatabase_desc = __('Title of browser window when a database is selected');
+$strConfigTitleDatabase_name = __('Database');
+$strConfigTitleDefault_desc = __('Title of browser window when nothing is selected');
+$strConfigTitleDefault_name = __('Default title');
+$strConfigTitleServer_desc = __('Title of browser window when a server is selected');
+$strConfigTitleServer_name = __('Server');
+$strConfigTitleTable_desc = __('Title of browser window when a table is selected');
+$strConfigTitleTable_name = __('Table');
+$strConfigTrustedProxies_desc = __('Input proxies as [kbd]IP: trusted HTTP header[/kbd]. The following example specifies that phpMyAdmin should trust a HTTP_X_FORWARDED_FOR (X-Forwarded-For) header coming from the proxy 1.2.3.4:[br][kbd]1.2.3.4: HTTP_X_FORWARDED_FOR[/kbd]');
+$strConfigTrustedProxies_name = __('List of trusted proxies for IP allow/deny');
+$strConfigUploadDir_desc = __('Directory on server where you can upload files for import');
+$strConfigUploadDir_name = __('Upload directory');
+$strConfigUseDbSearch_desc = __('Allow for searching inside the entire database');
+$strConfigUseDbSearch_name = __('Use database search');
+$strConfigUserprefsDeveloperTab_desc = __('When disabled, users cannot set any of the options below, regardless of the checkbox on the right');
+$strConfigUserprefsDeveloperTab_name = __('Enable the Developer tab in settings');
+$strConfigVerboseMultiSubmit_desc = __('Show affected rows of each statement on multiple-statement queries. See libraries/import.lib.php for defaults on how many queries a statement may contain.');
+$strConfigVerboseMultiSubmit_name = __('Verbose multiple statements');
+$strConfigVersionCheckLink = __('Check for latest version');
+$strConfigZipDump_desc = __('Enable [a at http://en.wikipedia.org/wiki/ZIP_(file_format)]ZIP[/a] compression for import and export operations');
+$strConfigZipDump_name = __('ZIP');
+
+?>
\ No newline at end of file
diff --git a/libraries/config/setup.forms.php b/libraries/config/setup.forms.php
new file mode 100644
index 0000000..af8d284
--- /dev/null
+++ b/libraries/config/setup.forms.php
@@ -0,0 +1,368 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * List of avaible forms, each form is described as an array of fields to display.
+ * Fields MUST have their counterparts in the $cfg array.
+ *
+ * There are two possible notations:
+ * $forms['Form group']['Form name'] = array('Servers' => array(1 => array('host')));
+ * can be written as
+ * $forms['Form group']['Form name'] = array('Servers/1/host');
+ *
+ * You can assign default values set by special button ("set value: ..."), eg.:
+ * 'Servers/1/pmadb' => 'phpmyadmin'
+ *
+ * To group options, use:
+ * ':group:' . __('group name') // just define a group
+ * or
+ * 'option' => ':group' // group starting from this option
+ * End group blocks with:
+ * ':group:end'
+ *
+ * @package phpMyAdmin-setup
+ */
+
+$forms = array();
+$forms['_config.php'] = array(
+    'DefaultLang',
+    'ServerDefault');
+$forms['Servers']['Server'] = array('Servers' => array(1 => array(
+    'verbose',
+    'host',
+    'port',
+    'socket',
+    'ssl',
+    'connect_type',
+    'extension',
+    'compress',
+    'nopassword')));
+$forms['Servers']['Server_auth'] = array('Servers' => array(1 => array(
+    'auth_type',
+    ':group:' . __('Config authentication'),
+        'user',
+        'password',
+        ':group:end',
+    ':group:' . __('Cookie authentication'),
+        'auth_swekey_config' => './swekey.conf',
+        ':group:end',
+    ':group:' . __('HTTP authentication'),
+        'auth_http_realm',
+        ':group:end',
+    ':group:' . __('Signon authentication'),
+        'SignonSession',
+        'SignonURL',
+        'LogoutURL')));
+$forms['Servers']['Server_config'] = array('Servers' => array(1 => array(
+    'only_db',
+    'hide_db',
+    'AllowRoot',
+    'AllowNoPassword',
+    'DisableIS',
+    'AllowDeny/order',
+    'AllowDeny/rules',
+    'ShowDatabasesCommand',
+    'CountTables')));
+$forms['Servers']['Server_pmadb'] = array('Servers' => array(1 => array(
+    'pmadb' => 'phpmyadmin',
+    'controluser',
+    'controlpass',
+    'verbose_check',
+    'bookmarktable' => 'pma_bookmark',
+    'relation' => 'pma_relation',
+    'userconfig' => 'pma_userconfig',
+    'table_info' => 'pma_table_info',
+    'column_info' => 'pma_column_info',
+    'history' => 'pma_history',
+    'tracking' => 'pma_tracking',
+    'table_coords' => 'pma_table_coords',
+    'pdf_pages' => 'pma_pdf_pages',
+    'designer_coords' => 'pma_designer_coords')));
+$forms['Servers']['Server_tracking'] = array('Servers' => array(1 => array(
+    'tracking_version_auto_create',
+    'tracking_default_statements',
+    'tracking_add_drop_view',
+    'tracking_add_drop_table',
+    'tracking_add_drop_database',
+)));
+$forms['Features']['Import_export'] = array(
+    'UploadDir',
+    'SaveDir',
+    'RecodingEngine' => ':group',
+        'IconvExtraParams',
+        ':group:end',
+    'ZipDump',
+    'GZipDump',
+    'BZipDump',
+    'CompressOnFly');
+$forms['Features']['Security'] = array(
+    'blowfish_secret',
+    'ForceSSL',
+    'CheckConfigurationPermissions',
+    'TrustedProxies',
+    'AllowUserDropDatabase',
+    'AllowArbitraryServer',
+    'LoginCookieRecall',
+    'LoginCookieValidity',
+    'LoginCookieStore',
+    'LoginCookieDeleteAll');
+$forms['Features']['Page_titles'] = array(
+    'TitleDefault',
+    'TitleTable',
+    'TitleDatabase',
+    'TitleServer');
+$forms['Features']['Warnings'] = array(
+    'PmaNoRelation_DisableWarning',
+    'SuhosinDisableWarning',
+    'McryptDisableWarning');
+$forms['Features']['Developer'] = array(
+    'UserprefsDeveloperTab',
+    'Error_Handler/display',
+    'Error_Handler/gather',
+    'DBG/sql',
+    'DBG/php');
+$forms['Features']['Other_core_settings'] = array(
+    'NaturalOrder',
+    'InitialSlidersState',
+    'ErrorIconic',
+    'ReplaceHelpImg',
+    'MaxDbList',
+    'MaxTableList',
+    'OBGzip',
+    'PersistentConnections',
+    'ExecTimeLimit',
+    'MemoryLimit',
+    'SkipLockedTables',
+    'UseDbSearch',
+    'AllowThirdPartyFraming');
+$forms['Sql_queries']['Sql_queries'] = array(
+    'ShowSQL',
+    'Confirm',
+    'QueryHistoryDB',
+    'QueryHistoryMax',
+    'IgnoreMultiSubmitErrors',
+    'VerboseMultiSubmit',
+    'MaxCharactersInDisplayedSQL',
+    'EditInWindow',
+    //'QueryWindowWidth', // overridden in theme
+    //'QueryWindowHeight',
+    'QueryWindowDefTab');
+$forms['Sql_queries']['Sql_box'] = array('SQLQuery' => array(
+    'Edit',
+    'Explain',
+    'ShowAsPHP',
+    'Validate',
+    'Refresh'));
+$forms['Sql_queries']['Sql_validator'] = array('SQLValidator' => array(
+    'use',
+    'username',
+    'password'));
+$forms['Left_frame']['Left_frame'] = array(
+    'LeftFrameLight',
+    'LeftDisplayLogo',
+    'LeftLogoLink',
+    'LeftLogoLinkWindow',
+    'LeftPointerEnable');
+$forms['Left_frame']['Left_servers'] = array(
+    'LeftDisplayServers',
+    'DisplayServersList');
+$forms['Left_frame']['Left_databases'] = array(
+    'DisplayDatabasesList',
+    'LeftFrameDBTree',
+    'LeftFrameDBSeparator',
+    'ShowTooltipAliasDB');
+$forms['Left_frame']['Left_tables'] = array(
+    'LeftDefaultTabTable',
+    'LeftFrameTableSeparator',
+    'LeftFrameTableLevel',
+    'ShowTooltip',
+    'ShowTooltipAliasTB');
+$forms['Main_frame']['Startup'] = array(
+    'MainPageIconic',
+    'ShowCreateDb' => ':group',
+        'SuggestDBName',
+        ':group:end',
+    'ShowStats',
+    'ShowServerInfo',
+    'ShowPhpInfo',
+    'ShowChgPassword');
+$forms['Main_frame']['Browse'] = array(
+    'NavigationBarIconic',
+    'ShowAll',
+    'MaxRows',
+    'Order',
+    'BrowsePointerEnable',
+    'BrowseMarkerEnable',
+    'RepeatCells',
+    'LimitChars',
+    'ModifyDeleteAtLeft',
+    'ModifyDeleteAtRight',
+    'DefaultDisplay');
+$forms['Main_frame']['Edit'] = array(
+    'ProtectBinary',
+    'ShowFunctionFields',
+    'ShowFieldTypesInDataEditView',
+    'CharEditing',
+    'CharTextareaCols',
+    'CharTextareaRows',
+    'TextareaCols',
+    'TextareaRows',
+    'LongtextDoubleTextarea',
+    'InsertRows',
+    'ForeignKeyDropdownOrder',
+    'ForeignKeyMaxLimit',
+    'DefaultPropDisplay');
+$forms['Main_frame']['Tabs'] = array(
+    'LightTabs',
+    'PropertiesIconic',
+    'DefaultTabServer',
+    'DefaultTabDatabase',
+    'DefaultTabTable',
+	'QueryWindowDefTab');
+$forms['Import']['Import_defaults'] = array('Import' => array(
+    'format',
+    'charset',
+    'allow_interrupt',
+    'skip_queries'));
+$forms['Import']['Sql'] = array('Import' => array(
+    'sql_compatibility',
+    'sql_no_auto_value_on_zero'));
+$forms['Import']['Csv'] = array('Import' => array(
+    ':group:' . __('CSV'),
+        'csv_replace',
+        'csv_ignore',
+        'csv_terminated',
+        'csv_enclosed',
+        'csv_escaped',
+        'csv_col_names',
+        ':group:end',
+    ':group:' . __('CSV using LOAD DATA'),
+        'ldi_replace',
+        'ldi_ignore',
+        'ldi_terminated',
+        'ldi_enclosed',
+        'ldi_escaped',
+        'ldi_local_option',
+        ':group:end'));
+$forms['Import']['Microsoft_Office'] = array('Import' => array(
+    ':group:' . __('Excel 97-2003 XLS Workbook'),
+        'xls_col_names',
+        ':group:end',
+    ':group:' . __('Excel 2007 XLSX Workbook'),
+        'xlsx_col_names'));
+$forms['Import']['Open_Document'] = array('Import' => array(
+    ':group:' . __('Open Document Spreadsheet'),
+        'ods_col_names',
+        'ods_empty_rows',
+        'ods_recognize_percentages',
+        'ods_recognize_currency'));
+$forms['Export']['Export_defaults'] = array('Export' => array(
+    'method',
+    'format',
+    'compression',
+    'charset',
+    'asfile' => ':group',
+    'onserver',
+    'onserver_overwrite',
+    ':group:end',
+    'remember_file_template',
+    'file_template_table',
+    'file_template_database',
+    'file_template_server'));
+$forms['Export']['Sql'] = array('Export' => array(
+    'sql_include_comments' => ':group',
+        'sql_dates',
+        'sql_relation',
+        'sql_mime',
+        ':group:end',
+    'sql_use_transaction',
+    'sql_disable_fk',
+    'sql_compatibility',
+    ':group:' . __('Database export options'),
+        'sql_drop_database',
+        'sql_structure_or_data',
+        ':group:end',
+    ':group:' . __('Structure'),
+        'sql_drop_table',
+        'sql_procedure_function',
+        'sql_create_table_statements' => ':group',
+            'sql_if_not_exists',
+            'sql_auto_increment',
+            ':group:end',
+        'sql_backquotes',
+        ':group:end',
+    ':group:' . __('Data'),
+        'sql_delayed',
+        'sql_ignore',
+        'sql_type',
+        'sql_insert_syntax',
+        'sql_max_query_size',
+        'sql_hex_for_blob',
+        'sql_utc_time'));
+$forms['Export']['CodeGen'] = array('Export' => array(
+    'codegen_format'));
+$forms['Export']['Csv'] = array('Export' => array(
+    ':group:' . __('CSV'),
+        'csv_separator',
+        'csv_enclosed',
+        'csv_escaped',
+        'csv_terminated',
+        'csv_null',
+        'csv_removeCRLF',
+        'csv_columns',
+        ':group:end',
+    ':group:' . __('CSV for MS Excel'),
+        'excel_null',
+        'excel_removeCRLF',
+        'excel_columns',
+        'excel_edition'));
+$forms['Export']['Latex'] = array('Export' => array(
+    'latex_caption',
+    'latex_structure_or_data',
+    ':group:' . __('Structure'),
+        'latex_structure_caption',
+        'latex_structure_continued_caption',
+        'latex_structure_label',
+        'latex_relation',
+        'latex_comments',
+        'latex_mime',
+        ':group:end',
+    ':group:' . __('Data'),
+        'latex_columns',
+        'latex_data_caption',
+        'latex_data_continued_caption',
+        'latex_data_label',
+        'latex_null'));
+$forms['Export']['Microsoft_Office'] = array('Export' => array(
+    ':group:' . __('Excel 97-2003 XLS Workbook'),
+        'xls_null',
+        'xls_columns',
+        ':group:end',
+    ':group:' . __('Excel 2007 XLSX Workbook'),
+        'xlsx_null',
+        'xlsx_columns',
+        ':group:end',
+    ':group:' . __('Microsoft Word 2000'),
+        'htmlword_structure_or_data',
+        'htmlword_null',
+        'htmlword_columns'));
+$forms['Export']['Open_Document'] = array('Export' => array(
+    ':group:' . __('Open Document Spreadsheet'),
+        'ods_columns',
+        'ods_null',
+        ':group:end',
+    ':group:' . __('Open Document Text'),
+        'odt_structure_or_data',
+        ':group:' . __('Structure'),
+            'odt_relation',
+            'odt_comments',
+            'odt_mime',
+            ':group:end',
+        ':group:' . __('Data'),
+            'odt_columns',
+            'odt_null'));
+$forms['Export']['Texy'] = array('Export' => array(
+    'texytext_structure_or_data',
+    ':group:' . __('Data'),
+        'texytext_null',
+        'texytext_columns'));
+?>
\ No newline at end of file
diff --git a/libraries/config/user_preferences.forms.php b/libraries/config/user_preferences.forms.php
new file mode 100644
index 0000000..564f093
--- /dev/null
+++ b/libraries/config/user_preferences.forms.php
@@ -0,0 +1,268 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * List of avaible forms, each form is described as an array of fields to display.
+ * Fields MUST have their counterparts in the $cfg array.
+ *
+ * To define form field, use the notatnion below:
+ * $forms['Form group']['Form name'] = array('Option/path');
+ *
+ * You can assign default values set by special button ("set value: ..."), eg.:
+ * 'Servers/1/pmadb' => 'phpmyadmin'
+ *
+ * To group options, use:
+ * ':group:' . __('group name') // just define a group
+ * or
+ * 'option' => ':group' // group starting from this option
+ * End group blocks with:
+ * ':group:end'
+ *
+ * @package phpMyAdmin
+ */
+
+$forms = array();
+$forms['Features']['General'] = array(
+    'NaturalOrder',
+    'InitialSlidersState',
+    'ErrorIconic',
+    'ReplaceHelpImg',
+    'Servers/1/only_db', // saves to Server/only_db
+    'Servers/1/hide_db', // saves to Server/hide_db
+    'SkipLockedTables',
+    'MaxDbList',
+    'MaxTableList');
+$forms['Features']['Text_fields'] = array(
+    'CharEditing',
+    'CharTextareaCols',
+    'CharTextareaRows',
+    'TextareaCols',
+    'TextareaRows',
+    'LongtextDoubleTextarea');
+$forms['Features']['Page_titles'] = array(
+    'TitleDefault',
+    'TitleTable',
+    'TitleDatabase',
+    'TitleServer');
+$forms['Features']['Warnings'] = array(
+    'PmaNoRelation_DisableWarning',
+    'SuhosinDisableWarning',
+    'McryptDisableWarning');
+// settings from this form are treated specially, see prefs_forms.php and user_preferences.lib.php
+$forms['Features']['Developer'] = array(
+    'Error_Handler/display',
+    'Error_Handler/gather',
+    'DBG/sql',
+    'DBG/php');
+$forms['Sql_queries']['Sql_queries'] = array(
+    'ShowSQL',
+    'Confirm',
+    'QueryHistoryMax',
+    'IgnoreMultiSubmitErrors',
+    'VerboseMultiSubmit',
+    'MaxCharactersInDisplayedSQL',
+    'EditInWindow',
+    //'QueryWindowWidth', // overridden in theme
+    //'QueryWindowHeight',
+    'QueryWindowDefTab');
+$forms['Sql_queries']['Sql_box'] = array(
+    'SQLQuery/Edit',
+    'SQLQuery/Explain',
+    'SQLQuery/ShowAsPHP',
+    'SQLQuery/Validate',
+    'SQLQuery/Refresh');
+$forms['Left_frame']['Left_frame'] = array(
+    'LeftFrameLight',
+    'LeftDisplayLogo',
+    'LeftLogoLink',
+    'LeftLogoLinkWindow',
+    'LeftPointerEnable');
+$forms['Left_frame']['Left_databases'] = array(
+    'DisplayDatabasesList',
+    'LeftFrameDBTree',
+    'LeftFrameDBSeparator',
+    'ShowTooltipAliasDB');
+$forms['Left_frame']['Left_tables'] = array(
+    'LeftDefaultTabTable',
+    'LeftFrameTableSeparator',
+    'LeftFrameTableLevel',
+    'ShowTooltip',
+    'ShowTooltipAliasTB');
+$forms['Main_frame']['Startup'] = array(
+    'MainPageIconic',
+    'ShowCreateDb' => ':group',
+        'SuggestDBName',
+        ':group:end',
+    'ShowStats',
+    'ShowServerInfo');
+$forms['Main_frame']['Browse'] = array(
+    'NavigationBarIconic',
+    'ShowAll',
+    'MaxRows',
+    'Order',
+    'DisplayBinaryAsHex',
+    'BrowsePointerEnable',
+    'BrowseMarkerEnable',
+    'RepeatCells',
+    'LimitChars',
+    'ModifyDeleteAtLeft',
+    'ModifyDeleteAtRight',
+    'DefaultDisplay');
+$forms['Main_frame']['Edit'] = array(
+    'ProtectBinary',
+    'ShowFunctionFields',
+    'ShowFieldTypesInDataEditView',
+    'InsertRows',
+    'ForeignKeyDropdownOrder',
+    'ForeignKeyMaxLimit',
+    'CtrlArrowsMoving',
+    'DefaultPropDisplay');
+$forms['Main_frame']['Tabs'] = array(
+    'LightTabs',
+    'PropertiesIconic',
+    'DefaultTabServer',
+    'DefaultTabDatabase',
+    'DefaultTabTable');
+$forms['Import']['Import_defaults'] = array(
+    'Import/format',
+    'Import/charset',    
+    'Import/allow_interrupt',
+    'Import/skip_queries');
+$forms['Import']['Sql'] = array(
+    'Import/sql_compatibility',
+    'Import/sql_no_auto_value_on_zero');
+$forms['Import']['Csv'] = array(
+    ':group:' . __('CSV'),
+        'Import/csv_replace',
+        'Import/csv_ignore',
+        'Import/csv_terminated',
+        'Import/csv_enclosed',
+        'Import/csv_escaped',
+        'Import/csv_col_names',
+        ':group:end',
+    ':group:' . __('CSV using LOAD DATA'),
+        'Import/ldi_replace',
+        'Import/ldi_ignore',
+        'Import/ldi_terminated',
+        'Import/ldi_enclosed',
+        'Import/ldi_escaped',
+        'Import/ldi_local_option');
+$forms['Import']['Microsoft_Office'] = array(
+    ':group:' . __('Excel 97-2003 XLS Workbook'),
+        'Import/xls_col_names',
+        ':group:end',
+    ':group:' . __('Excel 2007 XLSX Workbook'),
+        'Import/xlsx_col_names');
+$forms['Import']['Open_Document'] = array(
+    ':group:' . __('Open Document Spreadsheet'),
+        'Import/ods_col_names',
+        'Import/ods_empty_rows',
+        'Import/ods_recognize_percentages',
+        'Import/ods_recognize_currency');
+$forms['Export']['Export_defaults'] = array(
+    'Export/method',
+    'Export/format',
+    'Export/compression',
+    'Export/charset',
+    'Export/asfile',
+    'Export/remember_file_template',
+    'Export/file_template_table',
+    'Export/file_template_database',
+    'Export/file_template_server');
+$forms['Export']['Sql'] = array(
+    'Export/sql_include_comments' => ':group',
+        'Export/sql_dates',
+        'Export/sql_relation',
+        'Export/sql_mime',
+        ':group:end',
+    'Export/sql_use_transaction',
+    'Export/sql_disable_fk',
+    'Export/sql_compatibility',
+    ':group:' . __('Database export options'),
+        'Export/sql_drop_database',
+        'Export/sql_structure_or_data',
+        ':group:end',
+    ':group:' . __('Structure'),
+        'Export/sql_drop_table',
+        'Export/sql_procedure_function',
+        'Export/sql_create_table_statements' => ':group',
+            'Export/sql_if_not_exists',
+            'Export/sql_auto_increment',
+            ':group:end',
+        'Export/sql_backquotes',
+        ':group:end',
+    ':group:' . __('Data'),
+        'Export/sql_delayed',
+        'Export/sql_ignore',
+        'Export/sql_type',
+        'Export/sql_insert_syntax',
+        'Export/sql_max_query_size',
+        'Export/sql_hex_for_blob',
+        'Export/sql_utc_time');
+$forms['Export']['CodeGen'] = array(
+    'Export/codegen_format');
+$forms['Export']['Csv'] = array(
+    ':group:' . __('CSV'),
+        'Export/csv_separator',
+        'Export/csv_enclosed',
+        'Export/csv_escaped',
+        'Export/csv_terminated',
+        'Export/csv_null',
+        'Export/csv_removeCRLF',
+        'Export/csv_columns',
+        ':group:end',
+    ':group:' . __('CSV for MS Excel'),
+        'Export/excel_null',
+        'Export/excel_removeCRLF',
+        'Export/excel_columns',
+        'Export/excel_edition');
+$forms['Export']['Latex'] = array(
+    'Export/latex_caption',
+    'Export/latex_structure_or_data',
+    ':group:' . __('Structure'),
+        'Export/latex_structure_caption',
+        'Export/latex_structure_continued_caption',
+        'Export/latex_structure_label',
+        'Export/latex_relation',
+        'Export/latex_comments',
+        'Export/latex_mime',
+        ':group:end',
+    ':group:' . __('Data'),
+        'Export/latex_columns',
+        'Export/latex_data_caption',
+        'Export/latex_data_continued_caption',
+        'Export/latex_data_label',
+        'Export/latex_null');
+$forms['Export']['Microsoft_Office'] = array(
+    ':group:' . __('Excel 97-2003 XLS Workbook'),
+        'Export/xls_null',
+        'Export/xls_columns',
+        ':group:end',
+    ':group:' . __('Excel 2007 XLSX Workbook'),
+        'Export/xlsx_null',
+        'Export/xlsx_columns',
+        ':group:end',
+    ':group:' . __('Microsoft Word 2000'),
+        'Export/htmlword_structure_or_data',
+        'Export/htmlword_null',
+        'Export/htmlword_columns');
+$forms['Export']['Open_Document'] = array(
+    ':group:' . __('Open Document Spreadsheet'),
+        'Export/ods_columns',
+        'Export/ods_null',
+        ':group:end',
+    ':group:' . __('Open Document Text'),
+        'Export/odt_structure_or_data',
+        ':group:' . __('Structure'),
+            'Export/odt_relation',
+            'Export/odt_comments',
+            'Export/odt_mime',
+            ':group:end',
+        ':group:' . __('Data'),
+            'Export/odt_columns',
+            'Export/odt_null');
+$forms['Export']['Texy'] = array(
+    'Export/texytext_structure_or_data',
+    ':group:' . __('Data'),
+        'Export/texytext_null',
+        'Export/texytext_columns');
+?>
\ No newline at end of file
diff --git a/setup/lib/validate.lib.php b/libraries/config/validate.lib.php
similarity index 62%
rename from setup/lib/validate.lib.php
rename to libraries/config/validate.lib.php
index c69b9f4..7c35fff 100644
--- a/setup/lib/validate.lib.php
+++ b/libraries/config/validate.lib.php
@@ -1,4 +1,5 @@
 <?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
 /**
  * Various validation functions
  *
@@ -9,14 +10,49 @@
  * assigned to a form element (formset name or field path). Even if there are
  * no errors, key must be set with an empty value.
  *
- * Valdiation functions are assigned in $cfg_db['_validators'] (config_info.inc.php).
+ * Valdiation functions are assigned in $cfg_db['_validators'] (config.values.php).
  *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin
  */
 
 /**
+ * Returns validator list
+ *
+ * @uses ConfigFile::getDbEntry()
+ * @uses ConfigFile::getInstance()
+ * @return array
+ */
+function PMA_config_get_validators()
+{
+    static $validators = null;
+
+    if ($validators === null) {
+        $cf = ConfigFile::getInstance();
+        $validators = $cf->getDbEntry('_validators', array());
+        if (!defined('PMA_SETUP') || !PMA_SETUP) {
+            $uvs = $cf->getDbEntry('_userValidators', array());
+            foreach ($uvs as $field => $uv_list) {
+                $uv_list = (array)$uv_list;
+                foreach ($uv_list as &$uv) {
+                    if (!is_array($uv)) {
+                        continue;
+                    }
+                    for ($i = 1; $i < count($uv); $i++) {
+                        if (substr($uv[$i], 0, 6) == 'value:') {
+                            $uv[$i] = PMA_array_read(substr($uv[$i], 6), $GLOBALS['cfg']);
+                        }
+                    }
+                }
+                $validators[$field] = isset($validators[$field])
+                    ? array_merge((array)$validators[$field], $uv_list)
+                    : $uv_list;
+            }
+        }
+    }
+    return $validators;
+}
+
+/**
  * Runs validation $validator_id on values $values and returns error list.
  *
  * Return values:
@@ -25,18 +61,21 @@
  *   cleanup in HTML documen
  * o false - when no validators match name(s) given by $validator_id
  *
+ * @uses ConfigFile::getCanonicalPath()
+ * @uses ConfigFile::getInstance()
+ * @uses PMA_config_get_validators()
  * @param string|array  $validator_id
  * @param array         $values
  * @param bool          $isPostSource  tells whether $values are directly from POST request
  * @return bool|array
  */
-function validate($validator_id, &$values, $isPostSource)
+function PMA_config_validate($validator_id, &$values, $isPostSource)
 {
     // find validators
-    $cf = ConfigFile::getInstance();
     $validator_id = (array) $validator_id;
-    $validators = $cf->getDbEntry('_validators');
+    $validators = PMA_config_get_validators();
     $vids = array();
+    $cf = ConfigFile::getInstance();
     foreach ($validator_id as &$vid) {
         $vid = $cf->getCanonicalPath($vid);
         if (isset($validators[$vid])) {
@@ -60,18 +99,25 @@ function validate($validator_id, &$values, $isPostSource)
     // validate
     $result = array();
     foreach ($vids as $vid) {
-        $r = call_user_func($validators[$vid], $vid, $arguments);
-        // merge results
-        if (is_array($r)) {
-            foreach ($r as $key => $error_list) {
-                // skip empty values if $isPostSource is false
-                if (!$isPostSource && empty($error_list)) {
-                    continue;
-                }
-                if (!isset($result[$key])) {
-                    $result[$key] = array();
+        // call appropriate validation functions
+        foreach ((array)$validators[$vid] as $validator) {
+            $vdef = (array) $validator;
+            $vname = array_shift($vdef);
+            $args = array_merge(array($vid, &$arguments), $vdef);
+            $r = call_user_func_array($vname, $args);
+
+            // merge results
+            if (is_array($r)) {
+                foreach ($r as $key => $error_list) {
+                    // skip empty values if $isPostSource is false
+                    if (!$isPostSource && empty($error_list)) {
+                        continue;
+                    }
+                    if (!isset($result[$key])) {
+                        $result[$key] = array();
+                    }
+                    $result[$key] = array_merge($result[$key], (array)$error_list);
                 }
-                $result[$key] = array_merge($result[$key], (array)$error_list);
             }
         }
     }
@@ -86,6 +132,16 @@ function validate($validator_id, &$values, $isPostSource)
 }
 
 /**
+ * Empty error handler, used to temporarily restore PHP internal error handler
+ * 
+ * @return bool
+ */
+function PMA_null_error_handler()
+{
+    return false;
+}
+
+/**
  * Ensures that $php_errormsg variable will be registered in case of an error
  * and enables output buffering (when $start = true).
  * Called with $start = false disables output buffering end restores
@@ -95,17 +151,25 @@ function validate($validator_id, &$values, $isPostSource)
  */
 function test_php_errormsg($start = true)
 {
-    static $old_html_errors, $old_track_errors;
+    static $old_html_errors, $old_track_errors, $old_error_reporting;
+    static $old_display_errors;
     if ($start) {
         $old_html_errors = ini_get('html_errors');
         $old_track_errors = ini_get('track_errors');
+        $old_display_errors = ini_get('display_errors');
+        $old_error_reporting = error_reporting(E_ALL);
         ini_set('html_errors', false);
         ini_set('track_errors', true);
+        ini_set('display_errors', true);
+        set_error_handler("PMA_null_error_handler");
         ob_start();
     } else {
         ob_end_clean();
+        restore_error_handler();
+        error_reporting($old_error_reporting);
         ini_set('html_errors', $old_html_errors);
         ini_set('track_errors', $old_track_errors);
+        ini_set('display_errors', $old_display_errors);
     }
 }
 
@@ -131,14 +195,14 @@ function test_db_connection($extension, $connect_type, $host, $port, $socket, $u
     if ($extension == 'mysql') {
         $conn = @mysql_connect($host . $socket . $port, $user, $pass);
         if (!$conn) {
-            $error = PMA_lang('error_connection');
+            $error = __('Could not connect to MySQL server');
         } else {
             mysql_close($conn);
         }
     } else {
         $conn = @mysqli_connect($host, $user, $pass, null, $port, $socket);
         if (!$conn) {
-            $error = PMA_lang('error_connection');
+            $error = __('Could not connect to MySQL server');
         } else {
             mysqli_close($conn);
         }
@@ -153,6 +217,7 @@ function test_db_connection($extension, $connect_type, $host, $port, $socket, $u
 /**
  * Validate server config
  *
+ * @uses test_db_connection()
  * @param string $path
  * @param array  $values
  * @return array
@@ -162,15 +227,15 @@ function validate_server($path, $values)
     $result = array('Server' => '', 'Servers/1/user' => '', 'Servers/1/SignonSession' => '', 'Servers/1/SignonURL' => '');
     $error = false;
     if ($values['Servers/1/auth_type'] == 'config' && empty($values['Servers/1/user'])) {
-        $result['Servers/1/user'] = PMA_lang('error_empty_user_for_config_auth');
+        $result['Servers/1/user'] = __('Empty username while using config authentication method');
         $error = true;
     }
     if ($values['Servers/1/auth_type'] == 'signon' && empty($values['Servers/1/SignonSession'])) {
-        $result['Servers/1/SignonSession'] = PMA_lang('error_empty_signon_session');
+        $result['Servers/1/SignonSession'] = __('Empty signon session name while using signon authentication method');
         $error = true;
     }
     if ($values['Servers/1/auth_type'] == 'signon' && empty($values['Servers/1/SignonURL'])) {
-        $result['Servers/1/SignonURL'] = PMA_lang('error_empty_signon_url');
+        $result['Servers/1/SignonURL'] = __('Empty signon URL while using signon authentication method');
         $error = true;
     }
 
@@ -187,13 +252,14 @@ function validate_server($path, $values)
 /**
  * Validate pmadb config
  *
+ * @uses test_db_connection()
  * @param string $path
  * @param array  $values
  * @return array
  */
 function validate_pmadb($path, $values)
 {
-    $tables = array('Servers/1/bookmarktable', 'Servers/1/relation', 'Servers/1/table_info', 'Servers/1/table_coords', 'Servers/1/pdf_pages', 'Servers/1/column_info', 'Servers/1/history', 'Servers/1/designer_coords');
+    //$tables = array('Servers/1/bookmarktable', 'Servers/1/relation', 'Servers/1/table_info', 'Servers/1/table_coords', 'Servers/1/pdf_pages', 'Servers/1/column_info', 'Servers/1/history', 'Servers/1/designer_coords');
     $result = array('Server_pmadb' => '', 'Servers/1/controluser' => '', 'Servers/1/controlpass' => '');
     $error = false;
 
@@ -203,15 +269,17 @@ function validate_pmadb($path, $values)
 
     $result = array();
     if ($values['Servers/1/controluser'] == '') {
-        $result['Servers/1/controluser'] = PMA_lang('error_empty_pmadb_user');
+        $result['Servers/1/controluser'] = __('Empty phpMyAdmin control user while using pmadb');
         $error = true;
     }
     if ($values['Servers/1/controlpass'] == '') {
-        $result['Servers/1/controlpass'] = PMA_lang('error_empty_pmadb_password');
+        $result['Servers/1/controlpass'] = __('Empty phpMyAdmin control user password while using pmadb');
         $error = true;
     }
     if (!$error) {
-        $test = test_db_connection($values['Servers/1/extension'], $values['Servers/1/connect_type'], $values['Servers/1/host'], $values['Servers/1/port'], $values['Servers/1/socket'], $values['Servers/1/controluser'], $values['Servers/1/controlpass'], 'Server_pmadb');
+        $test = test_db_connection($values['Servers/1/extension'], $values['Servers/1/connect_type'],
+            $values['Servers/1/host'], $values['Servers/1/port'], $values['Servers/1/socket'],
+            $values['Servers/1/controluser'], $values['Servers/1/controlpass'], 'Server_pmadb');
         if ($test !== true) {
             $result = array_merge($result, $test);
         }
@@ -223,6 +291,7 @@ function validate_pmadb($path, $values)
 /**
  * Validates regular expression
  *
+ * @uses test_php_errormsg()
  * @param string $path
  * @param array  $values
  * @return array
@@ -239,7 +308,6 @@ function validate_regex($path, $values)
 
     $matches = array();
     preg_match($values[$path], '', $matches);
-    ob_end_clean();
 
     test_php_errormsg(false);
 
@@ -283,14 +351,14 @@ function validate_trusted_proxies($path, $values)
         $matches = array();
         // we catch anything that may (or may not) be an IP
         if (!preg_match("/^(.+):(?:[ ]?)\\w+$/", $line, $matches)) {
-            $result[$path][] = PMA_lang('error_incorrect_value') . ': ' . $line;
+            $result[$path][] = __('Incorrect value') . ': ' . $line;
             continue;
         }
         // now let's check whether we really have an IP address
         if (filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false
             && filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
             $ip = htmlspecialchars(trim($matches[1]));
-            $result[$path][] = PMA_lang('error_incorrect_ip_address', $ip);
+            $result[$path][] = sprintf(__('Incorrect IP address: %s'), $ip);
             continue;
         }
     }
@@ -298,7 +366,6 @@ function validate_trusted_proxies($path, $values)
     return $result;
 }
 
-
 /**
  * Tests integer value
  *
@@ -307,17 +374,17 @@ function validate_trusted_proxies($path, $values)
  * @param bool   $allow_neg       allow negative values
  * @param bool   $allow_zero      allow zero
  * @param int    $max_value       max allowed value
- * @param string $error_lang_key  error message key: $GLOBALS["strSetup$error_lang_key"]
+ * @param string $error_string    error message key: $GLOBALS["strConfig$error_lang_key"]
  * @return string  empty string if test is successful
  */
-function test_number($path, $values, $allow_neg, $allow_zero, $max_value, $error_lang_key)
+function test_number($path, $values, $allow_neg, $allow_zero, $max_value, $error_string)
 {
     if ($values[$path] === '') {
         return '';
     }
 
     if (intval($values[$path]) != $values[$path] || (!$allow_neg && $values[$path] < 0) || (!$allow_zero && $values[$path] == 0) || $values[$path] > $max_value) {
-        return PMA_lang($error_lang_key);
+        return $error_string;
     }
 
     return '';
@@ -326,36 +393,68 @@ function test_number($path, $values, $allow_neg, $allow_zero, $max_value, $error
 /**
  * Validates port number
  *
+ * @uses test_number()
  * @param string $path
  * @param array  $values
  * @return array
  */
 function validate_port_number($path, $values)
 {
-    return array($path => test_number($path, $values, false, false, 65536, 'error_incorrect_port'));
+    return array($path => test_number($path, $values, false, false, 65535, __('Not a valid port number')));
 }
 
 /**
  * Validates positive number
  *
+ * @uses test_number()
  * @param string $path
  * @param array  $values
  * @return array
  */
 function validate_positive_number($path, $values)
 {
-    return array($path => test_number($path, $values, false, false, PHP_INT_MAX, 'error_nan_p'));
+    return array($path => test_number($path, $values, false, false, PHP_INT_MAX, __('Not a positive number')));
 }
 
 /**
  * Validates non-negative number
  *
+ * @uses test_number()
  * @param string $path
  * @param array  $values
  * @return array
  */
 function validate_non_negative_number($path, $values)
 {
-    return array($path => test_number($path, $values, false, true, PHP_INT_MAX, 'error_nan_nneg'));
+    return array($path => test_number($path, $values, false, true, PHP_INT_MAX, __('Not a non-negative number')));
+}
+
+/**
+ * Validates value according to given regular expression
+ * Pattern and modifiers must be a valid for PCRE <b>and</b> JavaScript RegExp
+ *
+ * @param string $path
+ * @param array  $values
+ * @param string $regex
+ * @return void
+ */
+function validate_by_regex($path, $values, $regex)
+{
+    $result = preg_match($regex, $values[$path]);
+    return array($path => ($result ? '' : __('Incorrect value')));
+}
+
+/**
+ * Validates upper bound for numeric inputs
+ * 
+ * @param string $path
+ * @param array  $values
+ * @param int    $max_value
+ * @return array
+ */
+function validate_upper_bound($path, $values, $max_value)
+{
+    $result = $values[$path] <= $max_value;
+    return array($path => ($result ? '' : sprintf(__('Value must be equal or lower than %s'), $max_value)));
 }
-?>
+?>
\ No newline at end of file
diff --git a/libraries/core.lib.php b/libraries/core.lib.php
index 8bfc035..97d443a 100644
--- a/libraries/core.lib.php
+++ b/libraries/core.lib.php
@@ -574,4 +574,89 @@ function PMA_sendHeaderLocation($uri)
         }
     }
 }
+
+/**
+ * Returns value of an element in $array given by $path.
+ * $path is a string describing position of an element in an associative array,
+ * eg. Servers/1/host refers to $array[Servers][1][host]
+ *
+ * @param  string   $path
+ * @param  array    $array
+ * @param  mixed    $default
+ * @return mixed    array element or $default
+ */
+function PMA_array_read($path, $array, $default = null)
+{
+    $keys = explode('/', $path);
+    $value =& $array;
+    foreach ($keys as $key) {
+        if (!isset($value[$key])) {
+            return $default;
+        }
+        $value =& $value[$key];
+    }
+    return $value;
+}
+
+/**
+ * Stores value in an array
+ *
+ * @param  string   $path
+ * @param  array    &$array
+ * @param  mixed    $value
+ */
+function PMA_array_write($path, &$array, $value)
+{
+    $keys = explode('/', $path);
+    $last_key = array_pop($keys);
+    $a =& $array;
+    foreach ($keys as $key) {
+        if (!isset($a[$key])) {
+            $a[$key] = array();
+        }
+        $a =& $a[$key];
+    }
+    $a[$last_key] = $value;
+}
+
+/**
+ * Removes value from an array
+ *
+ * @param  string   $path
+ * @param  array    &$array
+ * @param  mixed    $value
+ */
+function PMA_array_remove($path, &$array)
+{
+    $keys = explode('/', $path);
+    $keys_last = array_pop($keys);
+    $path = array();
+    $depth = 0;
+
+    $path[0] =& $array;
+    $found = true;
+    // go as deep as required or possible
+    foreach ($keys as $key) {
+        if (!isset($path[$depth][$key])) {
+            $found = false;
+            break;
+        }
+        $depth++;
+        $path[$depth] =& $path[$depth-1][$key];
+    }
+    // if element found, remove it
+    if ($found) {
+        unset($path[$depth][$keys_last]);
+        $depth--;
+    }
+
+    // remove empty nested arrays
+    for (; $depth >= 0; $depth--) {
+        if (!isset($path[$depth+1]) || count($path[$depth+1]) == 0) {
+            unset($path[$depth][$keys[$depth]]);
+        } else {
+            break;
+        }
+    }
+}
 ?>
diff --git a/libraries/db_links.inc.php b/libraries/db_links.inc.php
index 0dfa5a8..7eaf343 100644
--- a/libraries/db_links.inc.php
+++ b/libraries/db_links.inc.php
@@ -102,21 +102,23 @@ $tabs = array();
 $tabs[] =& $tab_structure;
 $tabs[] =& $tab_sql;
 $tabs[] =& $tab_search;
-if (PMA_Tracker::isActive()) {
-    $tabs[] =& $tab_tracking;
-}
 $tabs[] =& $tab_qbe;
 $tabs[] =& $tab_export;
 if (! $db_is_information_schema) {
     $tabs[] =& $tab_import;
-    if ($cfgRelation['designerwork']) {
-        $tabs[] =& $tab_designer;
-    }
     $tabs[] =& $tab_operation;
     if ($is_superuser) {
         $tabs[] =& $tab_privileges;
     }
 }
+if (PMA_Tracker::isActive()) {
+    $tabs[] =& $tab_tracking;
+}
+if (! $db_is_information_schema) {
+    if ($cfgRelation['designerwork']) {
+        $tabs[] =& $tab_designer;
+    }
+}
 
 $url_params['db'] = $db;
 
diff --git a/libraries/display_export.lib.php b/libraries/display_export.lib.php
index 62641f3..ad52bac 100644
--- a/libraries/display_export.lib.php
+++ b/libraries/display_export.lib.php
@@ -69,7 +69,7 @@ if(isset($_GET['export_method'])) {
     $cfg['Export']['method'] = 'quick';
 }
 // The export method (quick, custom or custom-no-form)
-echo '<input type="hidden" name="export_method" value="' . $cfg['Export']['method'] . '" />';
+echo '<input type="hidden" name="export_method" value="' . htmlspecialchars($cfg['Export']['method']) . '" />';
 
 
 if(isset($_GET['sql_query'])) {
@@ -255,23 +255,17 @@ if(isset($_GET['sql_query'])) {
                             echo $_GET['filename_template'];
                         } else {
                             if ($export_type == 'database') {
-                                if (isset($_COOKIE) && !empty($_COOKIE['pma_db_filename_template'])) {
-                                    echo htmlspecialchars($_COOKIE['pma_db_filename_template']);
-                                } else {
-                                    echo $GLOBALS['cfg']['Export']['file_template_database'];
-                                }
+                                echo htmlspecialchars($GLOBALS['PMA_Config']->getUserValue(
+                                    'pma_db_filename_template',
+                                    $GLOBALS['cfg']['Export']['file_template_database']));
                             } elseif ($export_type == 'table') {
-                                if (isset($_COOKIE) && !empty($_COOKIE['pma_table_filename_template'])) {
-                                    echo htmlspecialchars($_COOKIE['pma_table_filename_template']);
-                                } else {
-                                    echo $GLOBALS['cfg']['Export']['file_template_table'];
-                                }
+                                echo htmlspecialchars($GLOBALS['PMA_Config']->getUserValue(
+                                    'pma_table_filename_template',
+                                    $GLOBALS['cfg']['Export']['file_template_table']));
                             } else {
-                                if (isset($_COOKIE) && !empty($_COOKIE['pma_server_filename_template'])) {
-                                    echo htmlspecialchars($_COOKIE['pma_server_filename_template']);
-                                } else {
-                                    echo $GLOBALS['cfg']['Export']['file_template_server'];
-                                }
+                                echo htmlspecialchars($GLOBALS['PMA_Config']->getUserValue(
+                                    'pma_server_filename_template',
+                                    $GLOBALS['cfg']['Export']['file_template_server']));
                             }
                     }
                         echo '"';
diff --git a/libraries/export/sql.php b/libraries/export/sql.php
index 2d6708d..ade857f 100644
--- a/libraries/export/sql.php
+++ b/libraries/export/sql.php
@@ -109,7 +109,7 @@ if (isset($plugin_list)) {
             /* begin CREATE TABLE statements*/
             $plugin_list['sql']['options'][] =
                 array('type' => 'begin_subgroup', 'subgroup_header' => array('type' => 'bool', 'name' => 'create_table_statements', 'text' => __('<code>CREATE TABLE</code> options:')));
-                $plugin_list['sql']['options'][] =
+            $plugin_list['sql']['options'][] =
                 array('type' => 'bool', 'name' => 'if_not_exists', 'text' => '<code>IF NOT EXISTS</code>');
             $plugin_list['sql']['options'][] =
                 array('type' => 'bool', 'name' => 'auto_increment', 'text' => '<code>AUTO_INCREMENT</code>');
diff --git a/libraries/footer.inc.php b/libraries/footer.inc.php
index 715cf3b..dfa7ab9 100644
--- a/libraries/footer.inc.php
+++ b/libraries/footer.inc.php
@@ -115,7 +115,15 @@ if (window.parent.refreshNavigation) {
     window.parent.refreshNavigation();
 }
         <?php
+    } else if (isset($_GET['reload_left_frame']) && $_GET['reload_left_frame'] == '1') {
+        // reload left frame (used by user preferences)
+        ?>
+        if (window.parent && window.parent.frame_navigation) {
+            window.parent.frame_navigation.location.reload();
+        }
+        <?php
     }
+
     ?>
 // set current db, table and sql query in the querywindow
 if (window.parent.reload_querywindow) {
diff --git a/libraries/header.inc.php b/libraries/header.inc.php
index c6f7107..ea159a3 100644
--- a/libraries/header.inc.php
+++ b/libraries/header.inc.php
@@ -21,6 +21,14 @@ if (empty($GLOBALS['is_header_sent'])) {
     require_once './libraries/ob.lib.php';
     PMA_outBufferPre();
 
+    // if database storage for user preferences is transient, offer to load
+    // exported settings from localStorage (detection will be done in JavaScript)
+    $userprefs_offer_import = $GLOBALS['PMA_Config']->get('user_preferences') == 'session'
+            && !isset($_SESSION['userprefs_autoload']);
+    if ($userprefs_offer_import) {
+        $GLOBALS['js_include'][] = 'config.js';
+    }
+
     // For re-usability, moved http-headers and stylesheets
     // to a seperate file. It can now be included by header.inc.php,
     // querywindow.php.
@@ -58,6 +66,12 @@ if (empty($GLOBALS['is_header_sent'])) {
         PMA_Message::notice(__('Cookies must be enabled past this point.'))->display();
     }
 
+    // offer to load user preferences from localStorage
+    if ($userprefs_offer_import) {
+        require_once './libraries/user_preferences.lib.php';
+        PMA_userprefs_autoload_header();
+    }
+
     if (!defined('PMA_DISPLAY_HEADING')) {
         define('PMA_DISPLAY_HEADING', 1);
     }
diff --git a/libraries/header_meta_style.inc.php b/libraries/header_meta_style.inc.php
index 55e7991..46cca27 100644
--- a/libraries/header_meta_style.inc.php
+++ b/libraries/header_meta_style.inc.php
@@ -53,7 +53,7 @@ if ($GLOBALS['text_dir'] == 'ltr') {
 <?php
     }
 ?>
-    <link rel="stylesheet" type="text/css" href="<?php echo defined('PMA_PATH_TO_BASEDIR') ? PMA_PATH_TO_BASEDIR : ''; ?>phpmyadmin.css.php?<?php echo PMA_generate_common_url(); ?>&js_frame=<?php echo isset($print_view) ? 'print' : 'right'; ?>&nocache=<?php echo $GLOBALS['PMA_Config']->getThemeUniqueValue(); ?>" />
+    <link rel="stylesheet" type="text/css" href="<?php echo defined('PMA_PATH_TO_BASEDIR') ? PMA_PATH_TO_BASEDIR : ''; ?>phpmyadmin.css.php<?php echo PMA_generate_common_url(array('server' => $GLOBALS['server'])); ?>&js_frame=<?php echo isset($print_view) ? 'print' : 'right'; ?>&nocache=<?php echo $GLOBALS['PMA_Config']->getThemeUniqueValue(); ?>" />
     <link rel="stylesheet" type="text/css" href="<?php echo defined('PMA_PATH_TO_BASEDIR') ? PMA_PATH_TO_BASEDIR : ''; ?>print.css" media="print" />
     <link rel="stylesheet" type="text/css" href="<?php echo $GLOBALS['pmaThemePath']; ?>/jquery/jquery-ui-1.8.custom.css" />
     <meta name="robots" content="noindex,nofollow" />
diff --git a/libraries/header_scripts.inc.php b/libraries/header_scripts.inc.php
index 94aff1a..8126dd3 100644
--- a/libraries/header_scripts.inc.php
+++ b/libraries/header_scripts.inc.php
@@ -59,7 +59,7 @@ foreach ($GLOBALS['js_include'] as $js_script_file) {
 // Updates the title of the frameset if possible (ns4 does not allow this)
 if (typeof(parent.document) != 'undefined' && typeof(parent.document) != 'unknown'
     && typeof(parent.document.title) == 'string') {
-    parent.document.title = '<?php echo PMA_sanitize(PMA_escapeJsString($title)); ?>';
+    parent.document.title = '<?php echo PMA_sanitize(PMA_escapeJsString(htmlspecialchars($title))); ?>';
 }
 
 <?php
diff --git a/libraries/navigation_header.inc.php b/libraries/navigation_header.inc.php
index d6cb383..6c5b266 100644
--- a/libraries/navigation_header.inc.php
+++ b/libraries/navigation_header.inc.php
@@ -29,22 +29,26 @@ if ($GLOBALS['cfg']['LeftDisplayLogo']) {
             .'alt="' . $logo . '" id="imgpmalogo" />';
     }
 
-    echo '<div id="pmalogo">' . "\n"
-        .'<a href="' . $GLOBALS['cfg']['LeftLogoLink'];
-    switch ($GLOBALS['cfg']['LeftLogoLinkWindow']) {
-        case 'new':
-            echo '" target="_blank"';
-            break;
-        case 'main':
-            // do not add our parameters for an external link
-            if (substr(strtolower($GLOBALS['cfg']['LeftLogoLink']), 0, 4) !== 'http') {
-                echo '?' . $query_url . '" target="frame_content"';
-            } else {
-                echo '"';
-            }
+    echo '<div id="pmalogo">' . "\n";
+    if ($GLOBALS['cfg']['LeftLogoLink']) {
+        echo '<a href="' . htmlspecialchars($GLOBALS['cfg']['LeftLogoLink']);
+        switch ($GLOBALS['cfg']['LeftLogoLinkWindow']) {
+            case 'new':
+                echo '" target="_blank"';
+                break;
+            case 'main':
+                // do not add our parameters for an external link
+                if (substr(strtolower($GLOBALS['cfg']['LeftLogoLink']), 0, 4) !== '://') {
+                    echo '?' . $query_url . '" target="frame_content"';
+                } else {
+                    echo '" target="_blank"';
+                }
+        }
+        echo '>' . $logo . '</a>' . "\n";
+    } else {
+        echo $logo . "\n";
     }
-    echo '>' . $logo . '</a>' . "\n"
-        .'</div>' . "\n";
+    echo '</div>' . "\n";
 } // end of display logo
 ?>
 <div id="leftframelinks">
diff --git a/libraries/relation.lib.php b/libraries/relation.lib.php
index e6ebdc5..74800fe 100644
--- a/libraries/relation.lib.php
+++ b/libraries/relation.lib.php
@@ -136,6 +136,10 @@ function PMA_printRelationsParamDiagnostic($cfgRelation)
 
     PMA_printDiagMessageForFeature(__('Tracking'), 'trackingwork', $messages);
 
+    PMA_printDiagMessageForParameter('userconfig', isset($cfgRelation['userconfig']), $messages, 'userconfig');
+
+    PMA_printDiagMessageForFeature(__('User preferences'), 'userconfigwork', $messages);
+
     echo '</table>' . "\n";
 
     echo '<p>' . __('Quick steps to setup advanced features:') . '</p>';
@@ -212,6 +216,7 @@ function PMA__getRelationsParam()
     $cfgRelation['historywork'] = false;
     $cfgRelation['trackingwork'] = false;
     $cfgRelation['designerwork'] = false;
+    $cfgRelation['userconfigwork'] = false;
     $cfgRelation['allworks']    = false;
     $cfgRelation['user']        = null;
     $cfgRelation['db']          = null;
@@ -262,6 +267,8 @@ function PMA__getRelationsParam()
             $cfgRelation['history'] = $curr_table[0];
         } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['tracking']) {
             $cfgRelation['tracking'] = $curr_table[0];
+        } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['userconfig']) {
+            $cfgRelation['userconfig'] = $curr_table[0];
         }
     } // end while
     PMA_DBI_free_result($tab_rs);
@@ -316,6 +323,10 @@ function PMA__getRelationsParam()
         $cfgRelation['trackingwork']     = true;
     }
 
+    if (isset($cfgRelation['userconfig'])) {
+        $cfgRelation['userconfigwork']   = true;
+    }
+
     // we do not absolutely need that the internal relations or the PDF
     // schema feature be activated
     if (isset($cfgRelation['designer_coords'])) {
@@ -329,7 +340,7 @@ function PMA__getRelationsParam()
     if ($cfgRelation['relwork'] && $cfgRelation['displaywork']
      && $cfgRelation['pdfwork'] && $cfgRelation['commwork']
      && $cfgRelation['mimework'] && $cfgRelation['historywork']
-     && $cfgRelation['trackingwork']
+     && $cfgRelation['trackingwork'] && $cfgRelation['userconfigwork']
      && $cfgRelation['bookmarkwork'] && $cfgRelation['designerwork']) {
         $cfgRelation['allworks'] = true;
     }
diff --git a/libraries/server_links.inc.php b/libraries/server_links.inc.php
index c5d384f..5cd7a67 100644
--- a/libraries/server_links.inc.php
+++ b/libraries/server_links.inc.php
@@ -47,6 +47,29 @@ $tabs['status']['icon'] = 's_status.png';
 $tabs['status']['link'] = 'server_status.php';
 $tabs['status']['text'] = __('Status');
 
+if (! empty($binary_logs)) {
+    $tabs['binlog']['icon'] = 's_tbl.png';
+    $tabs['binlog']['link'] = 'server_binlog.php';
+    $tabs['binlog']['text'] = __('Binary log');
+}
+$tabs['process']['icon'] = 's_process.png';
+$tabs['process']['link'] = 'server_processlist.php';
+$tabs['process']['text'] = __('Processes');
+
+if ($is_superuser) {
+    $tabs['rights']['icon'] = 's_rights.png';
+    $tabs['rights']['link'] = 'server_privileges.php';
+    $tabs['rights']['text'] = __('Privileges');
+}
+
+$tabs['export']['icon'] = 'b_export.png';
+$tabs['export']['link'] = 'server_export.php';
+$tabs['export']['text'] = __('Export');
+
+$tabs['import']['icon'] = 'b_import.png';
+$tabs['import']['link'] = 'server_import.php';
+$tabs['import']['text'] = __('Import');
+
 $tabs['vars']['icon'] = 's_vars.png';
 $tabs['vars']['link'] = 'server_variables.php';
 $tabs['vars']['text'] = __('Variables');
@@ -60,36 +83,21 @@ $tabs['engine']['link'] = 'server_engines.php';
 $tabs['engine']['text'] = __('Engines');
 
 if ($is_superuser) {
-    $tabs['rights']['icon'] = 's_rights.png';
-    $tabs['rights']['link'] = 'server_privileges.php';
-    $tabs['rights']['text'] = __('Privileges');
-
     $tabs['replication']['icon'] = 's_replication.png';
     $tabs['replication']['link'] = 'server_replication.php';
     $tabs['replication']['text'] = __('Replication');
 }
 
-if (! empty($binary_logs)) {
-    $tabs['binlog']['icon'] = 's_tbl.png';
-    $tabs['binlog']['link'] = 'server_binlog.php';
-    $tabs['binlog']['text'] = __('Binary log');
-}
-$tabs['process']['icon'] = 's_process.png';
-$tabs['process']['link'] = 'server_processlist.php';
-$tabs['process']['text'] = __('Processes');
-
-$tabs['export']['icon'] = 'b_export.png';
-$tabs['export']['link'] = 'server_export.php';
-$tabs['export']['text'] = __('Export');
-
-$tabs['import']['icon'] = 'b_import.png';
-$tabs['import']['link'] = 'server_import.php';
-$tabs['import']['text'] = __('Import');
-
 $tabs['synchronize']['icon'] = 's_sync.png';
 $tabs['synchronize']['link'] = 'server_synchronize.php';
 $tabs['synchronize']['text'] = __('Synchronize');
 
+$tabs['settings']['icon'] = 'b_tblops.png';
+$tabs['settings']['link'] = 'prefs_manage.php';
+$tabs['settings']['text'] = __('Settings');
+$tabs['settings']['active'] = in_array(basename($GLOBALS['PMA_PHP_SELF']),
+    array('prefs_forms.php', 'prefs_manage.php'));
+
 echo PMA_generate_html_tabs($tabs, array());
 unset($tabs);
 
diff --git a/libraries/tbl_links.inc.php b/libraries/tbl_links.inc.php
index 22789f3..bc72d21 100644
--- a/libraries/tbl_links.inc.php
+++ b/libraries/tbl_links.inc.php
@@ -61,13 +61,6 @@ $tabs['search']['icon'] = 'b_search.png';
 $tabs['search']['text'] = __('Search');
 $tabs['search']['link'] = 'tbl_select.php';
 
-if(PMA_Tracker::isActive())
-{
-    $tabs['tracking']['icon'] = 'eye.png';
-    $tabs['tracking']['text'] = __('Tracking');
-    $tabs['tracking']['link'] = 'tbl_tracking.php';
-}
-
 if (! (isset($db_is_information_schema) && $db_is_information_schema)) {
     $tabs['insert']['icon'] = 'b_insrow.png';
     $tabs['insert']['link'] = 'tbl_change.php';
@@ -92,6 +85,13 @@ if (! $tbl_is_view && ! (isset($db_is_information_schema) && $db_is_information_
     $tabs['operation']['link'] = 'tbl_operations.php';
     $tabs['operation']['text'] = __('Operations');
 }
+if(PMA_Tracker::isActive()) {
+    $tabs['tracking']['icon'] = 'eye.png';
+    $tabs['tracking']['text'] = __('Tracking');
+    $tabs['tracking']['link'] = 'tbl_tracking.php';
+}
+if (! $tbl_is_view && ! (isset($db_is_information_schema) && $db_is_information_schema)) {
+}
 
 /**
  * Views support a limited number of operations
diff --git a/libraries/user_preferences.inc.php b/libraries/user_preferences.inc.php
new file mode 100644
index 0000000..b86e4a1
--- /dev/null
+++ b/libraries/user_preferences.inc.php
@@ -0,0 +1,72 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Common header for user preferences pages
+ *
+ * @package phpMyAdmin
+ */
+if (!defined('PHPMYADMIN')) {
+    exit;
+}
+
+// show server tabs
+require './libraries/server_links.inc.php';
+
+// build user preferences menu
+
+$form_param = filter_input(INPUT_GET, 'form');
+if (!isset($forms[$form_param])) {
+    $forms_keys = array_keys($forms);
+    $form_param = array_shift($forms_keys);
+}
+$tabs_icons = array(
+    'Features'    => 'b_tblops.png',
+    'Sql_queries' => 'b_sql.png',
+    'Left_frame'  => 'b_select.png',
+    'Main_frame'  => 'b_props.png',
+    'Import'      => 'b_import.png',
+    'Export'      => 'b_export.png');
+echo '<ul id="topmenu2">';
+echo PMA_generate_html_tab(array(
+    'link' => 'prefs_manage.php',
+    'text' => __('Manage your settings'))) . "\n";
+echo '<li>   </li>' . "\n";
+$script_name = basename($GLOBALS['PMA_PHP_SELF']);
+foreach (array_keys($forms) as $formset) {
+    $tab = array(
+        'link' => 'prefs_forms.php',
+        'text' => PMA_lang('Form_' . $formset),
+        'icon' => $tabs_icons[$formset],
+        'active' => ($script_name == 'prefs_forms.php' && $formset == $form_param));
+    echo PMA_generate_html_tab($tab, array('form' => $formset)) . "\n";
+}
+echo '</ul><div class="clearfloat"></div>';
+
+// show "configuration saved" message and reload navigation frame if needed
+if (!empty($_GET['saved'])) {
+    $message = PMA_Message::rawSuccess(__('Configuration has been saved'));
+    $message->display();
+}
+
+// debug info
+if ($cfg['DBG']['php']) {
+    $arr = ConfigFile::getInstance()->getConfigArray();
+    $arr2 = array();
+    foreach ($arr as $k => $v) {
+        $arr2[] = "<b>$k</b> " . var_export($v, true);
+    }
+    $arr2 = implode(', ', $arr2);
+    $arr2 .= '<br />Blacklist: ' . (empty($cfg['UserprefsDisallow'])
+            ? '<i>empty</i>'
+            : implode(', ', $cfg['UserprefsDisallow']));
+    $msg = PMA_Message::notice('Settings: ' . $arr2);
+    $msg->display();
+}
+
+// warn about using session storage for settings
+$cfgRelation = PMA_getRelationsParam();
+if (!$cfgRelation['userconfigwork']) {
+    $msg = __('Your preferences will be saved for current session only. Storing them permanently requires %sphpMyAdmin configuration storage%s.');
+    $msg = PMA_sanitize(sprintf($msg, '[a at ./Documentation.html#linked-tables at _blank]', '[/a]'));
+    PMA_Message::notice($msg)->display();
+}
diff --git a/libraries/user_preferences.lib.php b/libraries/user_preferences.lib.php
new file mode 100644
index 0000000..c513a19
--- /dev/null
+++ b/libraries/user_preferences.lib.php
@@ -0,0 +1,316 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Functions for displaying user preferences pages
+ *
+ * @package phpMyAdmin
+ */
+
+/**
+ * Common initialization for user preferences modification pages
+ *
+ * @uses ConfigFile::getInstance()
+ * @uses ConfigFile::resetConfigData()
+ * @uses ConfigFile::setAllowedKeys()
+ * @uses ConfigFile::setCfgUpdateReadMapping()
+ * @uses ConfigFile::updateWithGlobalConfig()
+ * @uses PMA_read_userprefs_fieldnames()
+ */
+function PMA_userprefs_pageinit()
+{
+    $forms_all_keys = PMA_read_userprefs_fieldnames($GLOBALS['forms']);
+    $cf = ConfigFile::getInstance();
+    $cf->resetConfigData(); // start with a clean instance
+    $cf->setAllowedKeys($forms_all_keys);
+    $cf->setCfgUpdateReadMapping(array(
+        'Server/hide_db' => 'Servers/1/hide_db',
+        'Server/only_db' => 'Servers/1/only_db'));
+    $cf->updateWithGlobalConfig($GLOBALS['cfg']);
+}
+
+/**
+ * Loads user preferences
+ *
+ * Returns an array:
+ * * config_data - path => value pairs
+ * * mtime - last modification time
+ * * type - 'db' (config read from pmadb) or 'session' (read from user session)
+ *
+ * @uses $_SESSION['userconfig']
+ * @uses $GLOBALS['controllink']
+ * @uses PMA_array_merge_recursive
+ * @uses PMA_backquote()
+ * @uses PMA_DBI_fetch_single_row()
+ * @uses PMA_getRelationsParam()
+ * @uses PMA_sqlAddslashes()
+ * @uses $GLOBALS['controllink']
+ * @return array
+ */
+function PMA_load_userprefs()
+{
+    $cfgRelation = PMA_getRelationsParam();
+    if (!$cfgRelation['userconfigwork']) {
+        // no pmadb table, use session storage
+        if (!isset($_SESSION['userconfig'])) {
+            $_SESSION['userconfig'] = array(
+                'db' => array(),
+                'ts' => time());
+        }
+        return array(
+            'config_data' => $_SESSION['userconfig']['db'],
+            'mtime' => $_SESSION['userconfig']['ts'],
+            'type' => 'session');
+    }
+    // load configuration from pmadb
+    $query_table = PMA_backquote($cfgRelation['db']) . '.' . PMA_backquote($cfgRelation['userconfig']);
+    $query = '
+        SELECT `config_data`, UNIX_TIMESTAMP(`timevalue`) ts
+        FROM ' . $query_table . '
+          WHERE `username` = \'' . PMA_sqlAddslashes($cfgRelation['user']) . '\'';
+    $row = PMA_DBI_fetch_single_row($query, 'ASSOC', $GLOBALS['controllink']);
+    return array(
+        'config_data' => $row ? unserialize($row['config_data']) : array(),
+        'mtime' => $row ? $row['ts'] : time(),
+        'type' => 'db');
+}
+
+/**
+ * Saves user preferences
+ *
+ * @uses $_SESSION['cache'][...]['userprefs']
+ * @uses $_SESSION['userconfig']
+ * @uses $GLOBALS['cfg']['ServerDefault']
+ * @uses $GLOBALS['controllink']
+ * @uses $GLOBALS['server']
+ * @uses ConfigFile::getConfigArray()
+ * @uses ConfigFile::getInstance()
+ * @uses PMA_backquote()
+ * @uses PMA_DBI_fetch_value
+ * @uses PMA_DBI_getError()
+ * @uses PMA_DBI_try_query()
+ * @uses PMA_Message::addMessage()
+ * @uses PMA_Message::error()
+ * @uses PMA_Message::rawError()
+ * @uses PMA_sqlAddslashes()
+ * @uses PMA_getRelationsParam()
+ * @param array $config_data
+ * @return true|PMA_Message
+ */
+function PMA_save_userprefs(array $config_array)
+{
+    $cfgRelation = PMA_getRelationsParam();
+    $server = isset($GLOBALS['server'])
+        ? $GLOBALS['server']
+        : $GLOBALS['cfg']['ServerDefault'];
+    $cache_key = 'server_' . $server;
+    if (!$cfgRelation['userconfigwork']) {
+        // no pmadb table, use session storage
+        $_SESSION['userconfig'] = array(
+            'db' => $config_array,
+            'ts' => time());
+        if (isset($_SESSION['cache'][$cache_key]['userprefs'])) {
+           unset($_SESSION['cache'][$cache_key]['userprefs']);
+        }
+        return true;
+    }
+
+    // save configuration to pmadb
+    $query_table = PMA_backquote($cfgRelation['db']) . '.' . PMA_backquote($cfgRelation['userconfig']);
+    $query = '
+        SELECT `username`
+        FROM ' . $query_table . '
+          WHERE `username` = \'' . PMA_sqlAddslashes($cfgRelation['user']) . '\'';
+
+    $has_config = PMA_DBI_fetch_value($query, 0, 0, $GLOBALS['controllink']);
+    $config_data = serialize($config_array);
+    if ($has_config) {
+        $query = '
+            UPDATE ' . $query_table . '
+            SET `config_data` = \'' . PMA_sqlAddslashes($config_data) . '\'
+            WHERE `username` = \'' . PMA_sqlAddslashes($cfgRelation['user']) . '\'';
+    } else {
+        $query = '
+            INSERT INTO ' . $query_table . ' (`username`, `config_data`)
+            VALUES (\'' . PMA_sqlAddslashes($cfgRelation['user']) . '\',
+                \'' . PMA_sqlAddslashes($config_data) . '\')';
+    }
+    if (isset($_SESSION['cache'][$cache_key]['userprefs'])) {
+        unset($_SESSION['cache'][$cache_key]['userprefs']);
+    }
+    if (!PMA_DBI_try_query($query, $GLOBALS['controllink'])) {
+        $message = PMA_Message::error(__('Could not save configuration'));
+        $message->addMessage('<br /><br />');
+        $message->addMessage(PMA_Message::rawError(PMA_DBI_getError($GLOBALS['controllink'])));
+        return $message;
+    }
+    return true;
+}
+
+/**
+ * Returns a user preferences array filtered by $cfg['UserprefsDisallow']
+ * (blacklist) and keys from user preferences form (whitelist)
+ *
+ * @uses PMA_array_write()
+ * @uses PMA_read_userprefs_fieldnames()
+ * @param array $config_data path => value pairs
+ * @return array
+ */
+function PMA_apply_userprefs(array $config_data)
+{
+    $cfg = array();
+    $blacklist = array_flip($GLOBALS['cfg']['UserprefsDisallow']);
+    if (!$GLOBALS['cfg']['UserprefsDeveloperTab']) {
+        // disallow everything in the Developers tab
+        $blacklist['Error_Handler/display'] = true;
+        $blacklist['Error_Handler/gather'] = true;
+        $blacklist['DBG/sql'] = true;
+        $blacklist['DBG/php'] = true;
+    }
+    $whitelist = array_flip(PMA_read_userprefs_fieldnames());
+    // whitelist some additional fields which are custom handled
+    $whitelist['ThemeDefault'] = true;
+    $whitelist['fontsize'] = true;
+    $whitelist['lang'] = true;
+    $whitelist['collation_connection'] = true;
+    $whitelist['Server/hide_db'] = true;
+    $whitelist['Server/only_db'] = true;
+    foreach ($config_data as $path => $value) {
+        if (!isset($whitelist[$path]) || isset($blacklist[$path])) {
+            continue;
+        }
+        PMA_array_write($path, $cfg, $value);
+    }
+    return $cfg;
+}
+
+/**
+ * Reads user preferences field names
+ *
+ * @param array|null $forms
+ * @return array
+ */
+function PMA_read_userprefs_fieldnames(array $forms = null)
+{
+    static $names;
+
+    // return cached results
+    if ($names !== null) {
+        return $names;
+    }
+    if (is_null($forms)) {
+        $forms = array();
+        include 'libraries/config/user_preferences.forms.php';
+    }
+    $names = array();
+    foreach ($forms as $formset) {
+        foreach ($formset as $form) {
+            foreach ($form as $k => $v) {
+                $names[] = is_int($k) ? $v : $k;
+            }
+        }
+    }
+    return $names;
+}
+
+/**
+ * Updates one user preferences option (loads and saves to database).
+ *
+ * No validation is done!
+ *
+ * @uses PMA_load_userprefs()
+ * @uses PMA_save_userprefs()
+ * @param string $cfg_name
+ * @param mixed $value
+ * @return void
+ */
+function PMA_persist_option($path, $value, $default_value)
+{
+    $prefs = PMA_load_userprefs();
+    if ($value === $default_value) {
+        if (isset($prefs['config_data'][$path])) {
+            unset($prefs['config_data'][$path]);
+        } else {
+            return;
+        }
+    } else {
+        $prefs['config_data'][$path] = $value;
+    }
+    PMA_save_userprefs($prefs['config_data']);
+}
+
+/**
+ * Redirects after saving new user preferences
+ *
+ * @uses ConfigFile::getConfigArray()
+ * @uses ConfigFile::getInstance()
+ * @uses PMA_generate_common_url()
+ * @uses PMA_sendHeaderLocation()
+ * @param array  $forms
+ * @param array  $old_settings
+ * @param string $file_name
+ * @param array  $params
+ * @param string $hash
+ */
+function PMA_userprefs_redirect(array $forms, array $old_settings, $file_name, $params = null, $hash = null)
+{
+    $reload_left_frame = isset($params['reload_left_frame']) && $params['reload_left_frame'];
+    if (!$reload_left_frame) {
+        // compute differences and check whether left frame should be refreshed
+        $old_settings = isset($old_settings['config_data'])
+                ? $old_settings['config_data']
+                : array();
+        $new_settings = ConfigFile::getInstance()->getConfigArray();
+        $diff_keys = array_keys(array_diff_assoc($old_settings, $new_settings)
+                + array_diff_assoc($new_settings, $old_settings));
+        $check_keys = array('NaturalOrder', 'MainPageIconic', 'DefaultTabDatabase',
+            'Server/hide_db', 'Server/only_db');
+        $check_keys = array_merge($check_keys, $forms['Left_frame']['Left_frame'],
+             $forms['Left_frame']['Left_databases']);
+        $diff = array_intersect($check_keys, $diff_keys);
+        $reload_left_frame = !empty($diff);
+    }
+
+    // redirect
+    $url_params = array(
+        'saved' => 1,
+        'reload_left_frame' => $reload_left_frame);
+    if (is_array($params)) {
+        $url_params = array_merge($params, $url_params);
+    }
+    if ($hash) {
+        $hash = '#' . urlencode($hash);
+    }
+    PMA_sendHeaderLocation($GLOBALS['cfg']['PmaAbsoluteUri'] . $file_name
+            . PMA_generate_common_url($url_params, '&') . $hash);
+}
+
+/**
+ * Shows form which allows to quickly load settings stored in browser's local storage
+ *
+ * @uses $_REQUEST['prefs_autoload']
+ * @uses $_SESSION['userprefs_autoload']
+ * @uses PMA_generate_common_hidden_inputs()
+ */
+function PMA_userprefs_autoload_header()
+{
+    if (isset($_REQUEST['prefs_autoload']) && $_REQUEST['prefs_autoload'] == 'hide') {
+        $_SESSION['userprefs_autoload'] = true;
+        exit;
+    }
+    $script_name = basename(basename($GLOBALS['PMA_PHP_SELF']));
+    $return_url = $script_name . '?' . http_build_query($_GET, '', '&');
+    ?>
+    <div id="prefs_autoload" class="notice" style="display:none">
+        <form action="prefs_manage.php" method="post">
+            <?php echo PMA_generate_common_hidden_inputs() . "\n"; ?>
+            <input type="hidden" name="json" value="" />
+            <input type="hidden" name="submit_import" value="1" />
+            <input type="hidden" name="return_url" value="<?php echo htmlspecialchars($return_url) ?>" />
+            <?php echo __('Your browser has phpMyAdmin configuration for this domain. Would you like to import it for current session?') ?>
+            <br />
+            <a href="#yes"><?php echo __('Yes') ?></a> / <a href="#no"><?php echo __('No') ?></a>
+        </form>
+    </div>
+    <?php
+}
+?>
\ No newline at end of file
diff --git a/main.php b/main.php
index f81b0e4..3feefe5 100644
--- a/main.php
+++ b/main.php
@@ -143,6 +143,14 @@ echo PMA_Config::getFontsizeForm();
 echo '</li>';
 
 echo '</ul>';
+
+// User preferences
+
+echo '<ul>';
+echo PMA_printListItem(__('More settings'), 'li_user_preferences',
+                    './prefs_manage.php?' . $common_url_query);
+echo '<ul>';
+
 echo '</div>';
 
 
diff --git a/prefs_forms.php b/prefs_forms.php
new file mode 100644
index 0000000..40ea171
--- /dev/null
+++ b/prefs_forms.php
@@ -0,0 +1,89 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * User preferences page
+ *
+ * @package phpMyAdmin
+ */
+
+/**
+ * Gets some core libraries and displays a top message if required
+ */
+require_once './libraries/common.inc.php';
+require_once './libraries/user_preferences.lib.php';
+require_once './libraries/config/config_functions.lib.php';
+require_once './libraries/config/messages.inc.php';
+require_once './libraries/config/ConfigFile.class.php';
+require_once './libraries/config/Form.class.php';
+require_once './libraries/config/FormDisplay.class.php';
+require './libraries/config/user_preferences.forms.php';
+
+PMA_userprefs_pageinit();
+
+// handle form processing
+
+$form_param = filter_input(INPUT_GET, 'form');
+if (!isset($forms[$form_param])) {
+    $forms_keys = array_keys($forms);
+    $form_param = array_shift($forms_keys);
+}
+
+$form_display = new FormDisplay();
+foreach ($forms[$form_param] as $form_name => $form) {
+    // skip Developer form if no setting is available
+    if ($form_name == 'Developer' && !$GLOBALS['cfg']['UserprefsDeveloperTab']) {
+        continue;
+    }
+    $form_display->registerForm($form_name, $form, 1);
+}
+
+if (isset($_POST['revert'])) {
+    // revert erroneous fields to their default values
+    $form_display->fixErrors();
+    // redirect
+    $url_params = array('form' => $form_param);
+    PMA_sendHeaderLocation($cfg['PmaAbsoluteUri'] . 'prefs_forms.php'
+            . PMA_generate_common_url($url_params, '&'));
+    exit;
+}
+
+$error = null;
+if ($form_display->process(false) && !$form_display->hasErrors()) {
+    // save settings
+    $old_settings = PMA_load_userprefs();
+    $result = PMA_save_userprefs(ConfigFile::getInstance()->getConfigArray());
+    if ($result === true) {
+        // reload config
+        $GLOBALS['PMA_Config']->loadUserPreferences();
+        $hash = ltrim(filter_input(INPUT_POST, 'tab_hash'), '#');
+        PMA_userprefs_redirect($forms, $old_settings, 'prefs_forms.php', array(
+            'form' => $form_param), $hash);
+        exit;
+    } else {
+        $error = $result;
+    }
+}
+
+// display forms
+$GLOBALS['js_include'][] = 'config.js';
+require './libraries/header.inc.php';
+require './libraries/user_preferences.inc.php';
+if ($error) {
+    $error->display();
+}
+if ($form_display->hasErrors()) {
+    // form has errors
+    ?>
+    <div class="warning config-form">
+        <b><?php echo __('Cannot save settings, submitted form contains errors') ?></b>
+        <?php $form_display->displayErrors(); ?>
+    </div>
+    <?php
+}
+$form_display->display(true, true);
+
+/**
+ * Displays the footer
+ */
+require './libraries/footer.inc.php';
+?>
\ No newline at end of file
diff --git a/prefs_manage.php b/prefs_manage.php
new file mode 100644
index 0000000..d678f8a
--- /dev/null
+++ b/prefs_manage.php
@@ -0,0 +1,337 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * User preferences management page
+ *
+ * @package phpMyAdmin
+ */
+
+/**
+ * Gets some core libraries and displays a top message if required
+ */
+require_once './libraries/common.inc.php';
+require_once './libraries/user_preferences.lib.php';
+require_once './libraries/config/config_functions.lib.php';
+require_once './libraries/config/messages.inc.php';
+require_once './libraries/config/ConfigFile.class.php';
+require_once './libraries/config/Form.class.php';
+require_once './libraries/config/FormDisplay.class.php';
+require './libraries/config/user_preferences.forms.php';
+
+PMA_userprefs_pageinit();
+
+$error = '';
+if (isset($_POST['submit_export']) && filter_input(INPUT_POST, 'export_type') == 'text_file') {
+    // export to JSON file
+    $filename = 'phpMyAdmin-config-' . urlencode(PMA_getenv('HTTP_HOST')) . '.json';
+    header('Content-Type: application/json');
+    header('Content-Disposition: attachment; filename="' . $filename . '"');
+    header('Expires: ' . date(DATE_RFC1123));
+    $settings = PMA_load_userprefs();
+    echo json_encode($settings['config_data']);
+    return;
+} else if (isset($_POST['submit_get_json'])) {
+    $settings = PMA_load_userprefs();
+    header('Content-Type: application/json');
+    echo json_encode(array(
+        'prefs' => json_encode($settings['config_data']),
+        'mtime' => $settings['mtime']));
+    return;
+} else if (isset($_POST['submit_import'])) {
+    // load from JSON file
+    $json = '';
+    if (filter_input(INPUT_POST, 'import_type') == 'text_file'
+            && isset($_FILES['import_file'])
+            && $_FILES['import_file']['error'] == UPLOAD_ERR_OK
+            && is_uploaded_file($_FILES['import_file']['tmp_name'])) {
+        // read JSON from uploaded file
+        $open_basedir = @ini_get('open_basedir');
+        $file_to_unlink = '';
+        $import_file = $_FILES['import_file']['tmp_name'];
+
+        // If we are on a server with open_basedir, we must move the file
+        // before opening it. The doc explains how to create the "./tmp"
+        // directory
+        if (!empty($open_basedir)) {
+            $tmp_subdir = (PMA_IS_WINDOWS ? '.\\tmp\\' : './tmp/');
+            if (is_writable($tmp_subdir)) {
+                $import_file_new = tempnam($tmp_subdir, 'prefs');
+                if (move_uploaded_file($import_file, $import_file_new)) {
+                    $import_file = $import_file_new;
+                    $file_to_unlink = $import_file_new;
+                }
+            }
+        }
+        $json = file_get_contents($import_file);
+        if ($file_to_unlink) {
+            unlink($file_to_unlink);
+        }
+    } else {
+        // read from POST value (json)
+        $json = filter_input(INPUT_POST, 'json');
+    }
+
+    // hide header message
+    $_SESSION['userprefs_autoload'] = true;
+
+    $config = json_decode($json, true);
+    $return_url = filter_input(INPUT_POST, 'return_url');
+    if (!is_array($config)) {
+        $error = __('Could not import configuration');
+    } else {
+        // sanitize input values: treat them as though they came from HTTP POST request
+        $form_display = new FormDisplay();
+        foreach ($forms as $formset_id => $formset) {
+            foreach ($formset as $form_name => $form) {
+                $form_display->registerForm($formset_id . ': ' . $form_name, $form);
+            }
+        }
+        $cf = ConfigFile::getInstance();
+        $new_config = $cf->getFlatDefaultConfig();
+        if (!empty($_POST['import_merge'])) {
+            $new_config = array_merge($new_config, $cf->getConfigArray());
+        }
+        $new_config = array_merge($new_config, $config);
+        $_POST_bak = $_POST;
+        foreach ($new_config as $k => $v) {
+            $_POST[str_replace('/', '-', $k)] = $v;
+        }
+        $cf->resetConfigData();
+        $all_ok = $form_display->process(true, false);
+        $all_ok = $all_ok && !$form_display->hasErrors();
+        $_POST = $_POST_bak;
+
+        if (!$all_ok && isset($_POST['fix_errors'])) {
+            $form_display->fixErrors();
+            $all_ok = true;
+        }
+        if (!$all_ok) {
+            // mimic original form and post json in a hidden field
+            require './libraries/header.inc.php';
+            require './libraries/user_preferences.inc.php';
+            $msg = PMA_Message::warning(__('Configuration contains incorrect data for some fields.'));
+            $msg->display();
+            echo '<div class="config-form">';
+            $form_display->displayErrors();
+            echo '</div>';
+            ?>
+            <form action="prefs_manage.php" method="post">
+                <?php echo PMA_generate_common_hidden_inputs() . "\n"; ?>
+                <input type="hidden" name="json" value="<?php echo htmlspecialchars($json) ?>" />
+                <input type="hidden" name="fix_errors" value="1" />
+                <?php if (!empty($_POST['import_merge'])): ?>
+                <input type="hidden" name="import_merge" value="1" />
+                <?php endif; ?>
+                <?php if ($return_url): ?>
+                <input type="hidden" name="return_url" value="<?php echo htmlspecialchars($return_url) ?>" />
+                <?php endif; ?>
+                <p><?php echo __('Do you want to import remaining settings?') ?></p>
+                <input type="submit" name="submit_import" value="<?php echo __('Yes') ?>" />
+                <input type="submit" name="submit_ignore" value="<?php echo __('No') ?>" />
+            </form>
+            <?php
+            require './libraries/footer.inc.php';
+            return;
+        }
+
+        // check for ThemeDefault and fontsize
+        $params = array();
+        if (isset($config['ThemeDefault'])
+                && $_SESSION['PMA_Theme_Manager']->theme->getId() != $config['ThemeDefault']
+                && $_SESSION['PMA_Theme_Manager']->checkTheme($config['ThemeDefault'])) {
+            $_SESSION['PMA_Theme_Manager']->setActiveTheme($config['ThemeDefault']);
+            $_SESSION['PMA_Theme_Manager']->setThemeCookie();
+            $params['reload_left_frame'] = true;
+        }
+        if (isset($config['fontsize'])
+                && $config['fontsize'] != $GLOBALS['PMA_Config']->get('fontsize')) {
+            $params['set_fontsize'] = $config['fontsize'];
+            $params['reload_left_frame'] = true;
+        }
+        if (isset($config['lang'])
+                && $config['lang'] != $GLOBALS['lang']) {
+            $params['lang'] = $config['lang'];
+            $params['reload_left_frame'] = true;
+        }
+        if (isset($config['collation_connection'])
+                && $config['collation_connection'] != $GLOBALS['collation_connection']) {
+            $params['collation_connection'] = $config['collation_connection'];
+            $params['reload_left_frame'] = true;
+        }
+
+        // save settings
+        $old_settings = PMA_load_userprefs();
+        $result = PMA_save_userprefs($cf->getConfigArray());
+        if ($result === true) {
+            if ($return_url) {
+                $query = explode('&', parse_url($return_url, PHP_URL_QUERY));
+                $return_url = parse_url($return_url, PHP_URL_PATH);
+                foreach ($query as $q) {
+                    $pos = strpos($q, '=');
+                    $k = substr($q, 0, $pos);
+                    if ($k == 'token') {
+                        continue;
+                    }
+                    $params[$k] = substr($q, $pos+1);
+                }
+            } else {
+                $return_url = 'prefs_manage.php';
+            }
+            // reload config
+            $GLOBALS['PMA_Config']->loadUserPreferences();
+            PMA_userprefs_redirect($forms, $old_settings, $return_url, $params);
+            exit;
+        } else {
+            $error = $result;
+        }
+    }
+} else if (isset($_POST['submit_clear'])) {
+    $old_settings = PMA_load_userprefs();
+    $result = PMA_save_userprefs(array());
+    if ($result === true) {
+        $params = array();
+        if ($_SESSION['PMA_Theme_Manager']->theme->getId() != 'original') {
+            $GLOBALS['PMA_Config']->removeCookie($_SESSION['PMA_Theme_Manager']->getThemeCookieName());
+            unset($_SESSION['PMA_Theme_Manager']);
+            unset($_SESSION['PMA_Theme']);
+            $params['reload_left_frame'] = true;
+        }
+        if ($GLOBALS['PMA_Config']->get('fontsize') != '82%') {
+            $GLOBALS['PMA_Config']->removeCookie('pma_fontsize');
+            $params['reload_left_frame'] = true;
+        }
+        $GLOBALS['PMA_Config']->removeCookie('pma_collaction_connection');
+        $GLOBALS['PMA_Config']->removeCookie('pma_lang');
+        PMA_userprefs_redirect($forms, $old_settings, 'prefs_manage.php', $params);
+        exit;
+    } else {
+        $error = $result;
+    }
+    exit;
+}
+
+$GLOBALS['js_include'][] = 'config.js';
+require './libraries/header.inc.php';
+require './libraries/user_preferences.inc.php';
+if ($error) {
+    if (!$error instanceof PMA_Message) {
+        $error = PMA_Message::error($error);
+    }
+    $error->display();
+}
+?>
+<script type="text/javascript">
+<?php
+PMA_printJsValue("PMA_messages['strSavedOn']", __('Saved on: __DATE__'));
+?>
+</script>
+<div id="maincontainer">
+    <div id="main_pane_left">
+        <div class="group">
+            <h2><?php echo __('Import') ?></h2>
+            <form class="group-cnt prefs-form" name="prefs_import" action="prefs_manage.php" method="post" enctype="multipart/form-data">
+                <?php
+                echo PMA_generateHiddenMaxFileSize($max_upload_size) . "\n";
+                echo PMA_generate_common_hidden_inputs() . "\n";
+                ?>
+                <input type="hidden" name="json" value="" />
+                <input type="radio" id="import_text_file" name="import_type" value="text_file" checked="checked" />
+                <label for="import_text_file"><?php echo __('Import from file') ?></label>
+                <div id="opts_import_text_file" class="prefsmanage_opts">
+                    <label for="input_import_file"><?php echo __('Location of the text file'); ?></label>
+                    <input type="file" name="import_file" id="input_import_file" />
+                </div>
+                <input type="radio" id="import_local_storage" name="import_type" value="local_storage" disabled="disabled" />
+                <label for="import_local_storage"><?php echo __('Import from browser\'s storage') ?></label>
+                <div id="opts_import_local_storage" class="prefsmanage_opts disabled">
+                    <div class="localStorage-supported">
+                        <?php echo __('Settings will be imported from your browser\'s local storage.') ?>
+                        <br />
+                        <span class="localStorage-exists">
+                            <?php echo __('Saved on: __DATE__') ?>
+                        </span>
+                        <span class="localStorage-empty">
+                            <?php  PMA_Message::notice(__('You have no saved settings!'))->display() ?>
+                        </span>
+                    </div>
+                    <span class="localStorage-unsupported">
+                        <?php PMA_Message::notice(__('This feature is not supported by your web browser'))->display() ?>
+                    </span>
+                </div>
+
+                <input type="checkbox" id="import_merge" name="import_merge" />
+                <label for="import_merge"><?php echo __('Merge with current configuration') ?></label>
+                <br /><br />
+                <input type="submit" name="submit_import" value="<?php echo __('Go'); ?>" />
+            </form>
+        </div>
+        <?php
+        if (file_exists('./setup/index.php')) {
+            // show only if setup script is available, allows to disable this message
+            // by simply removing setup directory
+        ?>
+        <div class="group">
+            <h2><?php echo __('More settings') ?></h2>
+            <div class="group-cnt">
+                <?php
+                echo sprintf(__('You can set more settings by modifying config.inc.php, eg. by using %sSetup script%s.'), '<a href="setup/index.php">', '</a>');
+                echo PMA_showDocu('setup_script');
+                ?>
+            </div>
+        </div>
+        <?php
+        }
+        ?>
+    </div>
+    <div id="main_pane_right">
+        <div class="group">
+            <h2><?php echo __('Export') ?></h2>
+            <div class="click-hide-message group-cnt" style="display:none">
+                <?php
+                $message = PMA_Message::rawSuccess(__('Configuration has been saved'));
+                $message->display();
+                ?>
+            </div>
+            <form class="group-cnt prefs-form" name="prefs_export" action="prefs_manage.php" method="post">
+            <?php echo PMA_generate_common_hidden_inputs() . "\n" ?>
+                <div style="padding-bottom:0.5em">
+                    <input type="radio" id="export_text_file" name="export_type" value="text_file" checked="checked" />
+                    <label for="export_text_file"><?php echo __('Save as file') ?></label>
+                    <br />
+                    <input type="radio" id="export_local_storage" name="export_type" value="local_storage" disabled="disabled" />
+                    <label for="export_local_storage"><?php echo __('Save to browser\'s storage') ?></label>
+                </div>
+                <div id="opts_export_local_storage" class="prefsmanage_opts disabled">
+                    <span class="localStorage-supported">
+                        <?php echo __('Settings will be saved in your browser\'s local storage.') ?>
+                        <span class="localStorage-exists">
+                            <br /><b><?php echo __('Existing settings will be overwritten!') ?></b>
+                        </span>
+                    </span>
+                    <span class="localStorage-unsupported">
+                        <?php PMA_Message::notice(__('This feature is not supported by your web browser'))->display() ?>
+                    </span>
+                </div>
+                <br />
+                <input type="submit" name="submit_export" value="<?php echo __('Go'); ?>" />
+            </form>
+        </div>
+        <div class="group">
+            <h2><?php echo __('Reset') ?></h2>
+            <form class="group-cnt prefs-form" name="prefs_reset" action="prefs_manage.php" method="post">
+            <?php echo PMA_generate_common_hidden_inputs() . "\n" ?>
+                <?php echo __('You can reset all your settings and restore them to default values') ?>
+                <br /><br />
+                <input type="submit" name="submit_clear" value="<?php echo __('Reset') ?>" />
+            </form>
+
+        </div>
+    </div>
+    <br class="clearfloat" />
+</div>
+<?php
+/**
+ * Displays the footer
+ */
+require './libraries/footer.inc.php';
+?>
\ No newline at end of file
diff --git a/scripts/create_tables.sql b/scripts/create_tables.sql
index e4d0fc8..ca7325a 100644
--- a/scripts/create_tables.sql
+++ b/scripts/create_tables.sql
@@ -192,3 +192,18 @@ CREATE TABLE IF NOT EXISTS `pma_tracking` (
   `tracking_active` int(1) unsigned NOT NULL default '1',
   PRIMARY KEY  (`db_name`,`table_name`,`version`)
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=COMPACT;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `pma_userconfig`
+--
+
+CREATE TABLE IF NOT EXISTS `pma_userconfig` (
+  `username` varchar(64) NOT NULL,
+  `timevalue` timestamp NOT NULL,
+  `config_data` text NOT NULL,
+  PRIMARY KEY  (`username`)
+)
+  ENGINE=MyISAM COMMENT='User preferences storage for phpMyAdmin'
+  DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
diff --git a/scripts/find_unused_messages.sh b/scripts/find_unused_messages.sh
index ea8394b..bf01ffc 100755
--- a/scripts/find_unused_messages.sh
+++ b/scripts/find_unused_messages.sh
@@ -29,7 +29,7 @@ echo
 echo Not used messages present in messages file:
 echo
 
-diff $tmp1 $tmp2 | awk '/^</ {print $2}' | grep -Ev '(strSetup.*_(desc|name)|strSetupForm_|strSetupFormset_)'
+diff $tmp1 $tmp2 | awk '/^</ {print $2}' | grep -Ev '(strConfig.*_(desc|name)|strConfigForm_|strConfigFormset_)'
 
 
 rm -f $tmp1 $tmp2
diff --git a/setup/config.php b/setup/config.php
index e2bd132..fa18106 100644
--- a/setup/config.php
+++ b/setup/config.php
@@ -1,21 +1,23 @@
 <?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
 /**
  * Front controller for config view / download and clear
  *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin-setup
  */
 
 /**
  * Core libraries.
  */
 require './lib/common.inc.php';
-require_once './setup/lib/Form.class.php';
-require_once './setup/lib/FormDisplay.class.php';
+require_once './libraries/config/Form.class.php';
+require_once './libraries/config/FormDisplay.class.php';
+require_once './setup/lib/ConfigGenerator.class.php';
+
+require './libraries/config/setup.forms.php';
 
 $form_display = new FormDisplay();
-$form_display->registerForm('_config.php');
+$form_display->registerForm('_config.php', $forms['_config.php']);
 $form_display->save('_config.php');
 $config_file_path = ConfigFile::getInstance()->getFilePath();
 
@@ -27,7 +29,7 @@ if (PMA_ifSetOr($_POST['submit_clear'], '')) {
 	//
 	// Clear current config and return to main page
 	//
-	$_SESSION['ConfigFile'] = array();
+	ConfigFile::getInstance()->resetConfigData();
     // drop post data
     header('HTTP/1.1 303 See Other');
     header('Location: index.php');
@@ -38,13 +40,13 @@ if (PMA_ifSetOr($_POST['submit_clear'], '')) {
 	//
     header('Content-Type: text/plain');
     header('Content-Disposition: attachment; filename="config.inc.php"');
-    echo ConfigFile::getInstance()->getConfigFile();
+    echo ConfigGenerator::getConfigFile();
     exit;
 } elseif (PMA_ifSetOr($_POST['submit_save'], '')) {
 	//
 	// Save generated config file on the server
 	//
-    file_put_contents($config_file_path, ConfigFile::getInstance()->getConfigFile());
+    file_put_contents($config_file_path, ConfigGenerator::getConfigFile());
     header('HTTP/1.1 303 See Other');
     header('Location: index.php');
     exit;
@@ -54,7 +56,7 @@ if (PMA_ifSetOr($_POST['submit_clear'], '')) {
 	//
     $cfg = array();
     require_once $config_file_path;
-    $_SESSION['ConfigFile'] = $cfg;
+    ConfigFile::getInstance()->setConfigData($cfg);
     header('HTTP/1.1 303 See Other');
     header('Location: index.php');
     exit;
diff --git a/libraries/.htaccess b/setup/frames/.htaccess
similarity index 100%
copy from libraries/.htaccess
copy to setup/frames/.htaccess
diff --git a/setup/frames/config.inc.php b/setup/frames/config.inc.php
index 4e925d9..e56898f 100644
--- a/setup/frames/config.inc.php
+++ b/setup/frames/config.inc.php
@@ -1,10 +1,9 @@
 <?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
 /**
  * Config file view and save screen
  *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin-setup
  */
 
 if (!defined('PHPMYADMIN')) {
@@ -14,8 +13,9 @@ if (!defined('PHPMYADMIN')) {
 /**
  * Core libraries.
  */
-require_once './setup/lib/FormDisplay.class.php';
+require_once './libraries/config/FormDisplay.class.php';
 require_once './setup/lib/index.lib.php';
+require_once './setup/lib/ConfigGenerator.class.php';
 
 $config_readable = false;
 $config_writable = false;
@@ -29,7 +29,7 @@ check_config_rw($config_readable, $config_writable, $config_exists);
 <tr>
     <td>
         <textarea cols="50" rows="20" name="textconfig" id="textconfig" spellcheck="false"><?php
-            echo htmlspecialchars(ConfigFile::getInstance()->getConfigFile())
+            echo htmlspecialchars(ConfigGenerator::getConfigFile())
         ?></textarea>
     </td>
 </tr>
diff --git a/setup/frames/form.inc.php b/setup/frames/form.inc.php
index 019b110..27429b4 100644
--- a/setup/frames/form.inc.php
+++ b/setup/frames/form.inc.php
@@ -1,10 +1,9 @@
 <?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
 /**
  * Form edit view
  *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin-setup
  */
 
 if (!defined('PHPMYADMIN')) {
@@ -14,36 +13,24 @@ if (!defined('PHPMYADMIN')) {
 /**
  * Core libraries.
  */
-require_once './setup/lib/Form.class.php';
-require_once './setup/lib/FormDisplay.class.php';
+require_once './libraries/config/Form.class.php';
+require_once './libraries/config/FormDisplay.class.php';
 require_once './setup/lib/form_processing.lib.php';
 
-$formsets = array(
-    'features' => array(
-        'forms' => array('Import_export', 'Security', 'Sql_queries', 'Other_core_settings')),
-    'left_frame' => array(
-        'forms' => array('Left_frame', 'Left_servers', 'Left_databases', 'Left_tables')),
-    'main_frame' => array(
-        'forms' => array('Startup', 'Browse', 'Edit', 'Tabs', 'Sql_box')),
-    'import' => array(
-        'forms' => array('Import_defaults')),
-    'export' => array(
-        'forms' => array('Export_defaults'))
-);
+require './libraries/config/setup.forms.php';
 
 $formset_id = filter_input(INPUT_GET, 'formset');
 $mode = filter_input(INPUT_GET, 'mode');
-if (!isset($formsets[$formset_id])) {
+if (!isset($forms[$formset_id])) {
     die('Incorrect formset, check $formsets array in setup/frames/form.inc.php');
 }
 
-$formset = $formsets[$formset_id];
-if (isset($GLOBALS['strSetupFormset_' . $formset_id])) {
-    echo '<h2>' . $GLOBALS['strSetupFormset_' . $formset_id] . '</h2>';
+if (isset($GLOBALS['strConfigFormset_' . $formset_id])) {
+    echo '<h2>' . $GLOBALS['strConfigFormset_' . $formset_id] . '</h2>';
 }
 $form_display = new FormDisplay();
-foreach ($formset['forms'] as $form_name) {
-    $form_display->registerForm($form_name);
+foreach ($forms[$formset_id] as $form_name => $form) {
+    $form_display->registerForm($form_name, $form);
 }
 process_formset($form_display);
-?>
+?>
\ No newline at end of file
diff --git a/setup/frames/index.inc.php b/setup/frames/index.inc.php
index 43b6574..1b1285c 100644
--- a/setup/frames/index.inc.php
+++ b/setup/frames/index.inc.php
@@ -2,9 +2,7 @@
 /**
  * Overview (main page)
  *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin-setup
  */
 
 if (!defined('PHPMYADMIN')) {
@@ -15,7 +13,7 @@ if (!defined('PHPMYADMIN')) {
  * Core libraries.
  */
 require_once './libraries/display_select_lang.lib.php';
-require_once './setup/lib/FormDisplay.class.php';
+require_once './libraries/config/FormDisplay.class.php';
 require_once './setup/lib/index.lib.php';
 
 // prepare unfiltered language list
@@ -48,7 +46,8 @@ $config_writable = false;
 $config_exists = false;
 check_config_rw($config_readable, $config_writable, $config_exists);
 if (!$config_writable || !$config_readable) {
-    messages_set('error', 'config_rw', 'CannotLoadConfig', PMA_lang('CannotLoadConfigMsg'));
+    messages_set('error', 'config_rw', __('Cannot load or save configuration'),
+        PMA_lang(__('Please create web server writable folder [em]config[/em] in phpMyAdmin top level directory as described in [a at Documentation.html#setup_script]documentation[/a]. Otherwise you will be only able to download or display it.')));
 }
 //
 // Check https connection
@@ -56,11 +55,13 @@ if (!$config_writable || !$config_readable) {
 $is_https = !empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on';
 if (!$is_https) {
     $text = __('You are not using a secure connection; all data (including potentially sensitive information, like passwords) is transferred unencrypted!');
+
     if (!empty($_SERVER['REQUEST_URI']) && !empty($_SERVER['HTTP_HOST'])) {
-        $text .= ' ' . PMA_lang('InsecureConnectionMsg2',
+        $strInsecureConnectionMsg2 = __('If your server is also configured to accept HTTPS requests follow [a@%s]this link[/a] to use a secure connection.');
+        $text .= ' ' . PMA_lang($strInsecureConnectionMsg2,
             'https://' . htmlspecialchars($_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']));
     }
-    messages_set('warning', 'no_https', 'InsecureConnection', $text);
+    messages_set('warning', 'no_https', __('Insecure connection'), $text);
 }
 ?>
 
@@ -110,10 +111,10 @@ display_form_top('index.php', 'get', array(
 <tr>
     <th>#</th>
     <th><?php echo __('Name') ?></th>
-    <th>Authentication type</th>
+    <th><?php echo __('Authentication type') ?></th>
     <th colspan="2">DSN</th>
 </tr>
-<?php foreach ($_SESSION['ConfigFile']['Servers'] as $id => $server): ?>
+<?php foreach ($cf->getServers() as $id => $server): ?>
 <tr>
     <td><?php echo $id ?></td>
     <td><?php echo $cf->getServerName($id) ?></td>
@@ -186,7 +187,7 @@ if ($cf->getServerCount() > 0) {
     }
     $opts['values_disabled'][] = '-';
 
-    foreach ($_SESSION['ConfigFile']['Servers'] as $id => $server) {
+    foreach ($cf->getServers() as $id => $server) {
         $opts['values'][(string)$id] = $cf->getServerName($id) . " [$id]";
     }
 } else {
diff --git a/setup/frames/menu.inc.php b/setup/frames/menu.inc.php
index 1da3851..4a1ae9c 100644
--- a/setup/frames/menu.inc.php
+++ b/setup/frames/menu.inc.php
@@ -2,9 +2,7 @@
 /**
  * Menu items
  *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin-setup
  */
 
 if (!defined('PHPMYADMIN')) {
@@ -15,9 +13,10 @@ $separator = PMA_get_arg_separator('html');
 ?>
 <ul>
 	<li><a href="index.php"><?php echo __('Overview') ?></a></li>
-	<li><a href="?page=form<?php echo $separator ?>formset=features"><?php echo __('Features') ?></a></li>
-	<li><a href="?page=form<?php echo $separator ?>formset=left_frame"><?php echo __('Navigation frame') ?></a></li>
-	<li><a href="?page=form<?php echo $separator ?>formset=main_frame"><?php echo __('Main frame') ?></a></li>
-	<li><a href="?page=form<?php echo $separator ?>formset=import"><?php echo __('Import') ?></a></li>
-	<li><a href="?page=form<?php echo $separator ?>formset=export"><?php echo __('Export') ?></a></li>
+	<li><a href="?page=form<?php echo $separator ?>formset=Features"><?php echo __('Features') ?></a></li>
+	<li><a href="?page=form<?php echo $separator ?>formset=Sql_queries"><?php echo __('SQL queries') ?></a></li>
+	<li><a href="?page=form<?php echo $separator ?>formset=Left_frame"><?php echo __('Navigation frame') ?></a></li>
+	<li><a href="?page=form<?php echo $separator ?>formset=Main_frame"><?php echo __('Main frame') ?></a></li>
+	<li><a href="?page=form<?php echo $separator ?>formset=Import"><?php echo __('Import') ?></a></li>
+	<li><a href="?page=form<?php echo $separator ?>formset=Export"><?php echo __('Export') ?></a></li>
 </ul>
diff --git a/setup/frames/servers.inc.php b/setup/frames/servers.inc.php
index 17ff2f9..081c416 100644
--- a/setup/frames/servers.inc.php
+++ b/setup/frames/servers.inc.php
@@ -2,9 +2,7 @@
 /**
  * Server create and edit view
  *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin-setup
  */
 
 if (!defined('PHPMYADMIN')) {
@@ -14,10 +12,12 @@ if (!defined('PHPMYADMIN')) {
 /**
  * Core libraries.
  */
-require_once './setup/lib/Form.class.php';
-require_once './setup/lib/FormDisplay.class.php';
+require_once './libraries/config/Form.class.php';
+require_once './libraries/config/FormDisplay.class.php';
 require_once './setup/lib/form_processing.lib.php';
 
+require './libraries/config/setup.forms.php';
+
 $mode = filter_input(INPUT_GET, 'mode');
 $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
 
@@ -41,10 +41,8 @@ if (isset($page_title)) {
     echo '<h2>' . $page_title . '</h2>';
 }
 $form_display = new FormDisplay();
-$form_display->registerForm('Server', $id);
-$form_display->registerForm('Server_login_options', $id);
-$form_display->registerForm('Server_config', $id);
-$form_display->registerForm('Server_pmadb', $id);
-$form_display->registerForm('Server_tracking', $id);
+foreach ($forms['Servers'] as $form_name => $form) {
+    $form_display->registerForm($form_name, $form, $id);
+}
 process_formset($form_display);
-?>
+?>
\ No newline at end of file
diff --git a/setup/index.php b/setup/index.php
index 0d16e5f..7d78928 100644
--- a/setup/index.php
+++ b/setup/index.php
@@ -5,7 +5,6 @@
  * @package    phpMyAdmin-setup
  * @copyright  Copyright (c) 2008, Piotr Przybylski <piotrprz at gmail.com>
  * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
  */
 
 /**
@@ -37,6 +36,7 @@ require './libraries/header_http.inc.php';
 <script type="text/javascript" src="../js/jquery/jquery-1.4.2.js"></script>
 <script type="text/javascript" src="../js/jquery/jquery-ui-1.8.custom.js"></script>
 <script type="text/javascript" src="../js/jquery/jquery.json-2.2.js"></script>
+<script type="text/javascript" src="../js/config.js"></script>
 <script type="text/javascript" src="scripts.js"></script>
 </head>
 <body>
diff --git a/setup/lib/ConfigFile.class.php b/setup/lib/ConfigFile.class.php
deleted file mode 100644
index e7e7b28..0000000
--- a/setup/lib/ConfigFile.class.php
+++ /dev/null
@@ -1,322 +0,0 @@
-<?php
-/**
- * Config file management and generation
- *
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
- * @package    phpMyAdmin-setup
- */
-
-/**
- * Config file management and generation class
- *
- * @package    phpMyAdmin-setup
- */
-class ConfigFile
-{
-    /**
-     * Stores default PMA config from config.default.php
-     * @var array
-     */
-    private $cfg;
-
-    /**
-     * Stores allowed values for non-standard fields
-     * @var array
-     */
-    private $cfgDb;
-
-    /**
-     * Keys which will be always written to config file
-     * @var array
-     */
-    private $persistKeys;
-
-    /**
-     * ConfigFile instance
-     * @var ConfigFile
-     */
-    private static $_instance;
-
-    /**
-     * Private constructor, use {@link getInstance()}
-     */
-    private function __construct()
-    {
-        // load default config values
-        $cfg = &$this->cfg;
-        require './libraries/config.default.php';
-
-        // load additionsl config information
-        $cfg_db = &$this->cfgDb;
-        $persist_keys = array();
-        require './setup/lib/config_info.inc.php';
-
-        // apply default values overrides
-        if (count($cfg_db['_overrides'])) {
-            foreach ($cfg_db['_overrides'] as $path => $value) {
-                array_write($path, $cfg, $value);
-            }
-        }
-
-        // checking key presence is much faster than searching so move values to keys
-        $this->persistKeys = array_flip($persist_keys);
-    }
-
-    /**
-     * Returns class instance
-     *
-     * @return ConfigFile
-     */
-    public static function getInstance()
-    {
-        if (is_null(self::$_instance)) {
-            self::$_instance = new ConfigFile();
-        }
-        return self::$_instance;
-    }
-
-    /**
-     * Sets config value
-     *
-     * @param string $path
-     * @param mixed  $value
-     * @param string $canonical_path
-     */
-    public function set($path, $value, $canonical_path = null)
-    {
-        if ($canonical_path === null) {
-            $canonical_path = $this->getCanonicalPath($path);
-        }
-        // remove if the path isn't protected and it's empty or has a default value
-        $default_value = $this->getDefault($canonical_path);
-        if (!isset($this->persistKeys[$canonical_path])
-            && (($value == $default_value) || (empty($value) && empty($default_value)))) {
-            array_remove($path, $_SESSION['ConfigFile']);
-        } else {
-            array_write($path, $_SESSION['ConfigFile'], $value);
-        }
-    }
-
-    /**
-     * Returns config value or $default if it's not set
-     *
-     * @param  string $path
-     * @param  mixed  $default
-     * @return mixed
-     */
-    public function get($path, $default = null)
-    {
-        return array_read($path, $_SESSION['ConfigFile'], $default);
-    }
-
-    /**
-     * Returns default config value or $default it it's not set ie. it doesn't
-     * exist in config.default.php ($cfg) and config_info.inc.php
-     * ($_cfg_db['_overrides'])
-     *
-     * @param  string $canonical_path
-     * @param  mixed  $default
-     * @return mixed
-     */
-    public function getDefault($canonical_path, $default = null)
-    {
-        return array_read($canonical_path, $this->cfg, $default);
-    }
-
-    /**
-     * Returns config value, if it's not set uses the default one; returns
-     * $default if the path isn't set and doesn't contain a default value
-     *
-     * @param  string $path
-     * @param  mixed  $default
-     * @return mixed
-     */
-    public function getValue($path, $default = null)
-    {
-        $v = array_read($path, $_SESSION['ConfigFile'], null);
-        if ($v !== null) {
-            return $v;
-        }
-        $path = $this->getCanonicalPath($path);
-        return $this->getDefault($path, $default);
-    }
-
-    /**
-     * Returns canonical path
-     *
-     * @param string $path
-     * @return string
-     */
-    public function getCanonicalPath($path) {
-        return preg_replace('#^Servers/([\d]+)/#', 'Servers/1/', $path);
-    }
-
-    /**
-     * Returns config database entry for $path ($cfg_db in config_info.php)
-     *
-     * @param  string $path
-     * @param  mixed  $default
-     * @return mixed
-     */
-    public function getDbEntry($path, $default = null)
-    {
-        return array_read($path, $this->cfgDb, $default);
-    }
-
-    /**
-     * Returns server count
-     *
-     * @return int
-     */
-    public function getServerCount()
-    {
-      return isset($_SESSION['ConfigFile']['Servers'])
-          ? count($_SESSION['ConfigFile']['Servers'])
-          : 0;
-    }
-
-    /**
-     * Returns DSN of given server
-     *
-     * @param integer $server
-     * @return string
-     */
-    function getServerDSN($server)
-    {
-        if (!isset($_SESSION['ConfigFile']['Servers'][$server])) {
-            return '';
-        }
-
-        $path = 'Servers/' . $server;
-        $dsn = $this->getValue("$path/extension") . '://';
-        if ($this->getValue("$path/auth_type") == 'config') {
-            $dsn .= $this->getValue("$path/user");
-            if (!$this->getValue("$path/nopassword")) {
-                $dsn .= ':***';
-            }
-            $dsn .= '@';
-        }
-        if ($this->getValue("$path/connect_type") == 'tcp') {
-            $dsn .= $this->getValue("$path/host");
-            $port = $this->getValue("$path/port");
-            if ($port) {
-                $dsn .= ':' . $port;
-            }
-        } else {
-            $dsn .= $this->getValue("$path/socket");
-        }
-        return $dsn;
-    }
-
-    /**
-     * Returns server name
-     *
-     * @param int $id
-     * @return string
-     */
-    public function getServerName($id)
-    {
-        if (!isset($_SESSION['ConfigFile']['Servers'][$id])) {
-            return '';
-        }
-        $verbose = $this->get("Servers/$id/verbose");
-        if (!empty($verbose)) {
-            return $verbose;
-        }
-        $host = $this->get("Servers/$id/host");
-        return empty($host) ? 'localhost' : $host;
-    }
-
-    /**
-     * Removes server
-     *
-     * @param int $server
-     */
-    public function removeServer($server)
-    {
-        if (!isset($_SESSION['ConfigFile']['Servers'][$server])) {
-            return;
-        }
-        $last_server = $this->getServerCount();
-
-        for ($i = $server; $i < $last_server; $i++) {
-            $_SESSION['ConfigFile']['Servers'][$i] = $_SESSION['ConfigFile']['Servers'][$i+1];
-        }
-        unset($_SESSION['ConfigFile']['Servers'][$last_server]);
-
-        if (isset($_SESSION['ConfigFile']['ServerDefault'])
-            && $_SESSION['ConfigFile']['ServerDefault'] >= 0) {
-            unset($_SESSION['ConfigFile']['ServerDefault']);
-        }
-    }
-
-    /**
-     * Returns config file path
-     *
-     * @return unknown
-     */
-    public function getFilePath()
-    {
-        return $this->getDbEntry('_config_file_path');
-    }
-
-    /**
-     * Creates config file
-     *
-     * @return string
-     */
-    public function getConfigFile()
-    {
-        $crlf = (isset($_SESSION['eol']) && $_SESSION['eol'] == 'win') ? "\r\n" : "\n";
-        $c = $_SESSION['ConfigFile'];
-
-        // header
-        $ret = '<?php' . $crlf
-            . '/*' . $crlf
-            . ' * Generated configuration file' . $crlf
-            . ' * Generated by: phpMyAdmin '
-                    . $GLOBALS['PMA_Config']->get('PMA_VERSION')
-                    . ' setup script by Piotr Przybylski <piotrprz at gmail.com>' . $crlf
-            . ' * Date: ' . date(DATE_RFC1123) . $crlf
-            . ' */' . $crlf . $crlf;
-
-        // servers
-        if ($this->getServerCount() > 0) {
-            $ret .= "/* Servers configuration */$crlf\$i = 0;" . $crlf . $crlf;
-            foreach ($c['Servers'] as $id => $server) {
-                $ret .= '/* Server: ' . strtr($this->getServerName($id), '*/', '-') . " [$id] */" . $crlf
-                    . '$i++;' . $crlf;
-                foreach ($server as $k => $v) {
-                    $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
-                    $ret .= "\$cfg['Servers'][\$i]['$k'] = "
-                        . var_export($v, true) . ';' . $crlf;
-                }
-                $ret .= $crlf;
-            }
-            $ret .= '/* End of servers configuration */' . $crlf . $crlf;
-        }
-        unset($c['Servers']);
-
-        // other settings
-        $persistKeys = $this->persistKeys;
-        foreach ($c as $k => $v) {
-            $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
-            $ret .= "\$cfg['$k'] = " . var_export($v, true) . ';' . $crlf;
-            if (isset($persistKeys[$k])) {
-                unset($persistKeys[$k]);
-            }
-        }
-        // keep 1d array keys which are present in $persist_keys (config_info.inc.php)
-        foreach (array_keys($persistKeys) as $k) {
-            if (strpos($k, '/') === false) {
-                $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
-                $ret .= "\$cfg['$k'] = " . var_export($this->getDefault($k), true) . ';' . $crlf;
-            }
-        }
-        $ret .= '?>';
-
-        return $ret;
-    }
-}
-?>
diff --git a/setup/lib/ConfigGenerator.class.php b/setup/lib/ConfigGenerator.class.php
new file mode 100644
index 0000000..ddad7f1
--- /dev/null
+++ b/setup/lib/ConfigGenerator.class.php
@@ -0,0 +1,151 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Config file generator
+ *
+ * @package phpMyAdmin-setup
+ */
+
+/**
+ * Config file generation class
+ *
+ * @package phpMyAdmin
+ */
+class ConfigGenerator
+{
+    /**
+     * Creates config file
+     *
+     * @return string
+     */
+    public static function getConfigFile()
+    {
+        $cf = ConfigFile::getInstance();
+
+        $crlf = (isset($_SESSION['eol']) && $_SESSION['eol'] == 'win') ? "\r\n" : "\n";
+        $c = $cf->getConfig();
+
+        // header
+        $ret = '<?php' . $crlf
+            . '/*' . $crlf
+            . ' * Generated configuration file' . $crlf
+            . ' * Generated by: phpMyAdmin '
+                    . $GLOBALS['PMA_Config']->get('PMA_VERSION')
+                    . ' setup script by Piotr Przybylski <piotrprz at gmail.com>' . $crlf
+            . ' * Date: ' . date(DATE_RFC1123) . $crlf
+            . ' */' . $crlf . $crlf;
+
+        // servers
+        if ($cf->getServerCount() > 0) {
+            $ret .= "/* Servers configuration */$crlf\$i = 0;" . $crlf . $crlf;
+            foreach ($c['Servers'] as $id => $server) {
+                $ret .= '/* Server: ' . strtr($cf->getServerName($id), '*/', '-') . " [$id] */" . $crlf
+                    . '$i++;' . $crlf;
+                foreach ($server as $k => $v) {
+                    $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
+                    $ret .= "\$cfg['Servers'][\$i]['$k'] = "
+                        . (is_array($v) && self::_isZeroBasedArray($v)
+                                ? self::_exportZeroBasedArray($v, $crlf)
+                                : var_export($v, true))
+                        . ';' . $crlf;
+                }
+                $ret .= $crlf;
+            }
+            $ret .= '/* End of servers configuration */' . $crlf . $crlf;
+        }
+        unset($c['Servers']);
+
+        // other settings
+        $persistKeys = $cf->getPersistKeysMap();
+
+        foreach ($c as $k => $v) {
+            $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
+            $ret .= self::_getVarExport($k, $v, $crlf);
+            if (isset($persistKeys[$k])) {
+                unset($persistKeys[$k]);
+            }
+        }
+        // keep 1d array keys which are present in $persist_keys (config.values.php)
+        foreach (array_keys($persistKeys) as $k) {
+            if (strpos($k, '/') === false) {
+                $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
+                $ret .= self::_getVarExport($k, $cf->getDefault($k), $crlf);
+            }
+        }
+        $ret .= '?>';
+
+        return $ret;
+    }
+
+    /**
+     * Returns exported configuration variable
+     *
+     * @param string $var_name
+     * @param mixed  $var_value
+     * @param string $crlf
+     * @return string
+     */
+    private static function _getVarExport($var_name, $var_value, $crlf)
+    {
+        if (!is_array($var_value) || empty($var_value)) {
+            return "\$cfg['$var_name'] = " . var_export($var_value, true) . ';' . $crlf;
+        }
+        $ret = '';
+        if (self::_isZeroBasedArray($var_value)) {
+            $ret = "\$cfg['$var_name'] = " . self::_exportZeroBasedArray($var_value, $crlf)
+                . ';' . $crlf;
+        } else {
+            // string keys: $cfg[key][subkey] = value
+            foreach ($var_value as $k => $v) {
+                $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
+                $ret .= "\$cfg['$var_name']['$k'] = " . var_export($v, true) . ';' . $crlf;
+            }
+        }
+        return $ret;
+    }
+
+    /**
+     * Check whether $array is a continuous 0-based array
+     *
+     * @param array $array
+     * @return boolean
+     */
+    private static function _isZeroBasedArray(array $array)
+    {
+        for ($i = 0; $i < count($array); $i++) {
+            if (!isset($array[$i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Exports continuous 0-based array
+     *
+     * @param array $array
+     * @param string $crlf
+     * @return string
+     */
+    private static function _exportZeroBasedArray(array $array, $crlf)
+    {
+        $retv = array();
+        foreach ($array as $v) {
+            $retv[] = var_export($v, true);
+        }
+        $ret = "array(";
+        if (count($retv) <= 4) {
+            // up to 4 values - one line
+            $ret .= implode(', ', $retv);
+        } else {
+            // more than 4 values - value per line
+            $imax = count($retv)-1;
+            for ($i = 0; $i <= $imax; $i++) {
+                $ret .= ($i < $imax ? ($i > 0 ? ',' : '') : '') . $crlf . '    ' . $retv[$i];
+            }
+        }
+        $ret .= ')';
+        return $ret;
+    }
+}
+?>
\ No newline at end of file
diff --git a/setup/lib/FormDisplay.tpl.php b/setup/lib/FormDisplay.tpl.php
deleted file mode 100644
index f6cb5a5..0000000
--- a/setup/lib/FormDisplay.tpl.php
+++ /dev/null
@@ -1,293 +0,0 @@
-<?php
-/**
- * Form templates
- *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
- */
-
-/**
- * Displays top part of the form
- *
- * @param string $action         default: $_SERVER['REQUEST_URI']
- * @param string $method         'post' or 'get'
- * @param array  $hidden_fields  array of form hidden fields (key: field name)
- */
-function display_form_top($action = null, $method = 'post', $hidden_fields = null)
-{
-    static $has_check_page_refresh = false;
-
-    if ($action === null) {
-        $action = $_SERVER['REQUEST_URI'];
-    }
-    if ($method != 'post') {
-        $method = 'get';
-    }
-?>
-<form method="<?php echo $method ?>" action="<?php echo htmlspecialchars($action) ?>">
-<?php
-    // we do validation on page refresh when browser remembers field values,
-    // add a field with known value which will be used for checks
-    if (!$has_check_page_refresh) {
-        $has_check_page_refresh = true;
-        echo '<input type="hidden" name="check_page_refresh" id="check_page_refresh"'
-            . ' value="" />' . "\n";
-    }
-    echo PMA_generate_common_hidden_inputs() . "\n";
-    echo PMA_getHiddenFields((array)$hidden_fields);
-}
-
-/**
- * Displays form tabs which are given by an array indexed by fieldset id
- * ({@link display_fieldset_top}), with values being tab titles.
- *
- * @param array $tabs
- */
-function display_tabs_top($tabs) {
-?>
-<ul class="tabs">
-<?php foreach ($tabs as $tab_id => $tab_name): ?>
-    <li><a href="#<?php echo $tab_id ?>"><?php echo $tab_name ?></a></li>
-<?php endforeach; ?>
-</ul>
-<br clear="right" />
-<div class="tabs_contents">
-<?php
-}
-
-
-/**
- * Displays top part of a fieldset
- *
- * @param string $title
- * @param string $description
- * @param array  $errors
- * @param array  $attributes
- */
-function display_fieldset_top($title = '', $description = '', $errors = null, $attributes = array())
-{
-    $attributes = array_merge(array('class' => 'optbox'), $attributes);
-    foreach ($attributes as $k => &$attr) {
-        $attr = $k . '="' . htmlspecialchars($attr) . '"';
-    }
-
-    echo '<fieldset ' . implode(' ', $attributes) . '>';
-    echo '<legend>' . $title . '</legend>';
-    if (!empty($description)) {
-        echo '<p>' . $description . '</p>';
-    }
-    // this must match with displayErrors() in scripts.js
-    if (is_array($errors) && count($errors) > 0) {
-        echo '<dl class="errors">';
-        foreach ($errors as $error) {
-            echo '<dd>' . $error . '</dd>';
-        }
-        echo '</dl>';
-    }
-?>
-<table width="100%" cellspacing="0">
-<?php
-}
-
-/**
- * Displays input field
- *
- * $opts keys:
- * o doc - (string) documentation link
- * o errors - error array
- * o setvalue - (string) shows button allowing to set poredefined value
- * o show_restore_default - (boolean) whether show "restore default" button
- * o values - key - value paris for <select> fields
- * o values_escaped - (boolean) tells whether values array is already escaped (defaults to false)
- * o values_disabled -  (array)list of disabled values (keys from values)
- * o wiki - (string) wiki link
- *
- * @param string $path
- * @param string $name
- * @param string $description
- * @param string $type
- * @param mixed  $value
- * @param bool   $value_is_default
- * @param array  $opts
- */
-function display_input($path, $name, $description = '', $type, $value, $value_is_default = true, $opts = null)
-{
-    $field_class = $value_is_default ? '' : ' class="custom"';
-    $name_id = 'name="' . $path . '" id="' . $path . '"';
-?>
-<tr>
-    <th>
-        <label for="<?php echo htmlspecialchars($path) ?>"><?php echo $name ?></label>
-        <?php if (!empty($opts['doc']) || !empty($opts['wiki'])): ?>
-        <span class="doc">
-            <?php if (!empty($opts['doc'])) { ?><a href="<?php echo $opts['doc']  ?>" target="documentation"><img class="icon" src="../<?php echo $GLOBALS['cfg']['ThemePath'] ?>/original/img/b_help.png" width="11" height="11" alt="Doc" title="<?php echo __('Documentation') ?>" /></a><?php } ?>
-            <?php if (!empty($opts['wiki'])){ ?><a href="<?php echo $opts['wiki'] ?>" target="wiki"><img class="icon" src="../<?php echo $GLOBALS['cfg']['ThemePath'] ?>/original/img/b_info.png" width="11" height="11" alt="Wiki" title="Wiki" /></a><?php } ?>
-        </span>
-        <?php endif; ?>
-        <?php if (!empty($description)) { ?><small><?php echo $description ?></small><?php } ?>
-
-    </th>
-    <td>
-    <?php
-    switch ($type) {
-        case 'text':
-            echo '<input type="text" size="50" ' . $name_id . $field_class
-                . ' value="' . htmlspecialchars($value) . '" />';
-          break;
-        case 'checkbox':
-            echo '<span class="checkbox' . ($value_is_default ? '' : ' custom')
-              . '"><input type="checkbox" ' . $name_id
-              . ($value ? ' checked="checked"' : '') . ' /></span>';
-          break;
-        case 'select':
-            echo '<select ' . $name_id . $field_class . '>';
-            $escape = !(isset($opts['values_escaped']) && $opts['values_escaped']);
-            $values_disabled = isset($opts['values_disabled'])
-                ? array_flip($opts['values_disabled']) : array();
-            foreach ($opts['values'] as $opt_value => $opt_name) {
-                // set names for boolean values
-                if (is_bool($opt_name)) {
-                    $opt_name = $GLOBALS['strSetup' . ($opt_value ? 'True' : 'False')];
-                }
-                // cast boolean values to integers
-                $display_value = is_bool($opt_value) ? (int) $opt_value : $opt_value;
-                // escape if necessary
-                if ($escape) {
-                    $display = htmlspecialchars($opt_name);
-                    $display_value = htmlspecialchars($display_value);
-                } else {
-                    $display = $opt_name;
-                }
-                // compare with selected value
-                // boolean values are cast to integers when used as array keys
-                $selected = is_bool($value)
-                    ? (int) $value === $opt_value
-                    : $opt_value === $value;
-                echo '<option value="' . $display_value . '"'
-                    . ($selected ? ' selected="selected"' : '')
-                    . (isset($values_disabled[$opt_value]) ? ' disabled="disabled"' : '')
-                    . '>' . $display . '</option>';
-            }
-            echo '</select>';
-            break;
-        case 'list':
-            echo '<textarea cols="40" rows="5" ' . $name_id . $field_class . '>'
-                . htmlspecialchars(implode("\n", $value))
-                . '</textarea>';
-            break;
-    }
-    if (isset($opts['setvalue']) && $opts['setvalue']) {
-        ?>
-        <a class="set-value" href="#<?php echo "$path={$opts['setvalue']}" ?>" title="<?php echo sprintf(__('Set value: %s'), htmlspecialchars($opts['setvalue'])) ?>" style="display:none"><img alt="set-value" src="../<?php echo $GLOBALS['cfg']['ThemePath'] ?>/original/img/b_edit.png" width="16" height="16" /></a>
-        <?php
-    }
-    if (isset($opts['show_restore_default']) && $opts['show_restore_default']) {
-        ?>
-        <a class="restore-default" href="#<?php echo $path ?>" title="<?php echo __('Restore default value') ?>" style="display:none"><img alt="restore-default" src="../<?php echo $GLOBALS['cfg']['ThemePath'] ?>/original/img/s_reload.png" width="16" height="16" /></a>
-        <?php
-    }
-    // this must match with displayErrors() in scripts.js
-    if (isset($opts['errors']) && !empty($opts['errors'])) {
-        echo "\n        <dl class=\"inline_errors\">";
-        foreach ($opts['errors'] as $error) {
-            echo '<dd>' . htmlspecialchars($error) . '</dd>';
-        }
-        echo '</dl>';
-    }
-    ?>
-
-    </td>
-</tr>
-<?php
-}
-
-/**
- * Displays bottom part of a fieldset
- *
- * @param array $js_array
- */
-function display_fieldset_bottom()
-{
-?>
-<tr>
-    <td colspan="2" class="lastrow">
-        <input type="submit" name="submit_save" value="<?php echo __('Save') ?>" class="green" />
-        <input type="button" name="submit_reset" value="<?php echo __('Reset') ?>" />
-    </td>
-</tr>
-</table>
-</fieldset>
-
-<?php
-}
-
-/**
- * Displays simple bottom part of a fieldset (without submit buttons)
- */
-function display_fieldset_bottom_simple()
-{
-?>
-</table>
-</fieldset>
-
-<?php
-}
-
-/**
- * Closes form tabs
- */
-function display_tabs_bottom() {
-    echo "</div>\n";
-}
-
-/**
- * Displays bottom part of the form
- */
-function display_form_bottom()
-{
-    echo "</form>\n";
-}
-
-/**
- * Appends JS validation code to $js_array
- *
- * @param string $field_id
- * @param string $validator
- * @param array  $js_array
- */
-function js_validate($field_id, $validator, &$js_array) {
-    $js_array[] = "validateField('$field_id', '$validator', true)";
-}
-
-/**
- * Displays JavaScript code
- *
- * @param array $js_array
- */
-function display_js($js_array) {
-    if (empty($js_array)) {
-        return;
-    }
-?>
-<script type="text/javascript">
-<?php echo implode(";\n", $js_array) . ";\n" ?>
-</script>
-<?php
-}
-
-/**
- * Displays error list
- *
- * @param string $name
- * @param array  $error_list
- */
-function display_errors($name, $error_list) {
-    echo '<dl>';
-    echo '<dt>' . htmlspecialchars($name) . '</dt>';
-    foreach ($error_list as $error) {
-        echo '<dd>' . htmlspecialchars($error) . '</dd>';
-    }
-    echo '</dl>';
-}
-?>
diff --git a/setup/lib/common.inc.php b/setup/lib/common.inc.php
index 2d1f1f6..8b43caf 100644
--- a/setup/lib/common.inc.php
+++ b/setup/lib/common.inc.php
@@ -1,10 +1,9 @@
 <?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
 /**
  * Loads libraries/common.inc.php and preforms some additional actions
  *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin-setup
  */
 
 /**
@@ -20,9 +19,11 @@ if (!file_exists('./libraries/common.inc.php')) {
 }
 
 require_once './libraries/common.inc.php';
+require_once './libraries/config/config_functions.lib.php';
+require_once './libraries/config/messages.inc.php';
+require_once './libraries/config/ConfigFile.class.php';
 require_once './libraries/url_generating.lib.php';
-require_once './setup/lib/messages.inc.php';
-require_once './setup/lib/ConfigFile.class.php';
+require_once './libraries/user_preferences.lib.php';
 
 // use default error handler
 restore_error_handler();
@@ -30,201 +31,22 @@ restore_error_handler();
 // Save current language in a cookie, required since we use PMA_MINIMUM_COMMON
 $GLOBALS['PMA_Config']->setCookie('pma_lang', $GLOBALS['lang']);
 
-if (!isset($_SESSION['ConfigFile'])) {
-    $_SESSION['ConfigFile'] = array();
-}
+ConfigFile::getInstance()->setPersistKeys(array(
+    'DefaultLang',
+    'ServerDefault',
+    'UploadDir',
+    'SaveDir',
+    'Servers/1/verbose',
+    'Servers/1/host',
+    'Servers/1/port',
+    'Servers/1/socket',
+    'Servers/1/extension',
+    'Servers/1/connect_type',
+    'Servers/1/auth_type',
+    'Servers/1/user',
+    'Servers/1/password'));
 
 // allows for redirection even after sending some data
 ob_start();
 
-/**
- * Returns value of an element in $array given by $path.
- * $path is a string describing position of an element in an associative array,
- * eg. Servers/1/host refers to $array[Servers][1][host]
- *
- * @param  string   $path
- * @param  array    $array
- * @param  mixed    $default
- * @return mixed    array element or $default
- */
-function array_read($path, $array, $default = null)
-{
-    $keys = explode('/', $path);
-    $value =& $array;
-    foreach ($keys as $key) {
-        if (!isset($value[$key])) {
-            return $default;
-        }
-        $value =& $value[$key];
-    }
-    return $value;
-}
-
-/**
- * Stores value in an array
- *
- * @param  string   $path
- * @param  array    &$array
- * @param  mixed    $value
- */
-function array_write($path, &$array, $value)
-{
-    $keys = explode('/', $path);
-    $last_key = array_pop($keys);
-    $a =& $array;
-    foreach ($keys as $key) {
-        if (!isset($a[$key])) {
-            $a[$key] = array();
-        }
-        $a =& $a[$key];
-    }
-    $a[$last_key] = $value;
-}
-
-/**
- * Removes value from an array
- *
- * @param  string   $path
- * @param  array    &$array
- * @param  mixed    $value
- */
-function array_remove($path, &$array)
-{
-    $keys = explode('/', $path);
-    $keys_last = array_pop($keys);
-    $path = array();
-    $depth = 0;
-
-    $path[0] =& $array;
-    $found = true;
-    // go as deep as required or possible
-    foreach ($keys as $key) {
-        if (!isset($path[$depth][$key])) {
-            $found = false;
-            break;
-        }
-        $depth++;
-        $path[$depth] =& $path[$depth-1][$key];
-    }
-    // if element found, remove it
-    if ($found) {
-        unset($path[$depth][$keys_last]);
-        $depth--;
-    }
-
-    // remove empty nested arrays
-    for (; $depth >= 0; $depth--) {
-        if (!isset($path[$depth+1]) || count($path[$depth+1]) == 0) {
-            unset($path[$depth][$keys[$depth]]);
-        } else {
-            break;
-        }
-    }
-}
-
-/**
- * Returns sanitized language string, taking into account our special codes
- * for formatting. Takes variable number of arguments.
- * Based on PMA_sanitize from sanitize.lib.php.
- *
- * @param  string  $lang_key key in $GLOBALS WITHOUT 'strSetup' prefix
- * @param  mixed   $args     arguments for sprintf
- * @return string
- */
-function PMA_lang($lang_key)
-{
-    static $search, $replace;
-
-    // some quick cache'ing
-    if ($search === null) {
-        $replace_pairs = array(
-            '<'         => '<',
-            '>'         => '>',
-            '[em]'      => '<em>',
-            '[/em]'     => '</em>',
-            '[strong]'  => '<strong>',
-            '[/strong]' => '</strong>',
-            '[code]'    => '<code>',
-            '[/code]'   => '</code>',
-            '[kbd]'     => '<kbd>',
-            '[/kbd]'    => '</kbd>',
-            '[br]'      => '<br />',
-            '[sup]'     => '<sup>',
-            '[/sup]'    => '</sup>');
-        $search = array_keys($replace_pairs);
-        $replace = array_values($replace_pairs);
-    }
-    if (!isset($GLOBALS["strSetup$lang_key"])) {
-        return $lang_key;
-    }
-    $message = str_replace($search, $replace, $GLOBALS["strSetup$lang_key"]);
-    // replace [a@"$1"]$2[/a] with <a href="$1">$2</a>
-    $message = preg_replace('#\[a@("?)([^\]]+)\1\]([^\[]+)\[/a\]#e',
-        "PMA_lang_link_replace('$2', '$3')", $message);
-
-    if (func_num_args() == 1) {
-        return $message;
-    } else {
-        $args = func_get_args();
-        array_shift($args);
-        return vsprintf($message, $args);
-    }
-}
-
-/**
- * Returns translated field name
- *
- * @param string $canonical_path
- * @return string
- */
-function PMA_lang_name($canonical_path)
-{
-    $lang_key = str_replace(
-    	array('Servers/1/', '/'),
-    	array('Servers/', '_'),
-    	$canonical_path) . '_name';
-    return isset($GLOBALS["strSetup$lang_key"])
-        ? $GLOBALS["strSetup$lang_key"]
-        : $lang_key;
-}
-
-/**
- * Returns translated field description
- *
- * @param string $canonical_path
- * @return string
- */
-function PMA_lang_desc($canonical_path)
-{
-    $lang_key = str_replace(
-    	array('Servers/1/', '/'),
-    	array('Servers/', '_'),
-    	$canonical_path) . '_desc';
-    return isset($GLOBALS["strSetup$lang_key"])
-        ? PMA_lang($lang_key)
-        : '';
-}
-
-/**
- * Wraps link in <a> tags and replaces argument separator in internal links
- * to the one returned by PMA_get_arg_separator()
- *
- * @param string $link
- * @param string $text
- * @return string
- */
-function PMA_lang_link_replace($link, $text)
-{
-    static $separator;
-
-    if (!isset($separator)) {
-        $separator = PMA_get_arg_separator('html');
-    }
-
-    if (!preg_match('#^http://#', $link)) {
-        $link = str_replace('&', $separator, $link);
-    }
-
-    return '<a href="' . $link . '">' . $text . '</a>';
-}
-?>
+?>
\ No newline at end of file
diff --git a/setup/lib/config_info.inc.php b/setup/lib/config_info.inc.php
deleted file mode 100644
index 71f2e23..0000000
--- a/setup/lib/config_info.inc.php
+++ /dev/null
@@ -1,144 +0,0 @@
-<?php
-/**
- * Description of options with non-standard values, list of persistent options
- * and validator assignments.
- *
- * By default data types are taken from config.default.php, here we define
- * only allowed values for select fields and type overrides.
- *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
- */
-
-if (!defined('PHPMYADMIN')) {
-    exit;
-}
-
-$cfg_db = array();
-
-// path to config file, relative to phpMyAdmin's root path
-$cfg_db['_config_file_path'] = SETUP_CONFIG_FILE;
-
-/**
- * Value meaning:
- * o array - select field, array contains allowed values
- * o string - type override
- *
- * Use normal array, paths won't be expanded
- */
-$cfg_db['Servers'] = array(1 => array(
-    'port'         => 'integer',
-    'connect_type' => array('tcp', 'socket'),
-    'extension'    => array('mysql', 'mysqli'),
-    'auth_type'    => array('config', 'http', 'signon', 'cookie'),
-    'AllowDeny'    => array(
-        'order'    => array('', 'deny,allow', 'allow,deny', 'explicit')),
-    'only_db'      => 'array'));
-$cfg_db['RecodingEngine'] = array('auto', 'iconv', 'recode', 'none');
-$cfg_db['OBGzip'] = array('auto', true, false);
-$cfg_db['ShowTooltipAliasTB'] = array('nested', true, false);
-$cfg_db['DisplayDatabasesList'] = array('auto', true, false);
-$cfg_db['LeftLogoLinkWindow'] = array('main', 'new');
-$cfg_db['LeftDefaultTabTable'] = array(
-    'tbl_structure.php', // fields list
-    'tbl_sql.php',       // SQL form
-    'tbl_select.php',    // search page
-    'tbl_change.php',    // insert row page
-    'sql.php');          // browse page
-$cfg_db['NavigationBarIconic'] = array(true, false, 'both');
-$cfg_db['Order'] = array('ASC', 'DESC', 'SMART');
-$cfg_db['ProtectBinary'] = array(false, 'blob', 'all');
-$cfg_db['CharEditing'] = array('input', 'textarea');
-$cfg_db['PropertiesIconic'] = array(true, false, 'both');
-$cfg_db['DefaultTabServer'] = array(
-    'main.php',                // the welcome page (recommended for multiuser setups)
-    'server_databases.php',    // list of databases
-    'server_status.php',       // runtime information
-    'server_variables.php',    // MySQL server variables
-    'server_privileges.php',   // user management
-    'server_processlist.php'); // process list
-$cfg_db['DefaultTabDatabase'] = array(
-    'db_structure.php',   // tables list
-    'db_sql.php',         // SQL form
-    'db_search.php',      // search query
-    'db_operations.php'); // operations on database
-$cfg_db['DefaultTabTable'] = array(
-    'tbl_structure.php', // fields list
-    'tbl_sql.php',       // SQL form
-    'tbl_select.php',    // search page
-    'tbl_change.php',    // insert row page
-    'sql.php');          // browse page
-$cfg_db['QueryWindowDefTab'] = array(
-	'sql',     // SQL
-	'files',   // Import files
-	'history', // SQL history
-	'full');   // All (SQL and SQL history)
-$cfg_db['Import']['format'] = array(
-    'csv',    // CSV
-    'docsql', // DocSQL
-    'ldi',    // CSV using LOAD DATA
-    'sql');   // SQL
-$cfg_db['Import']['sql_compatibility'] = array(
-    'NONE', 'ANSI', 'DB2', 'MAXDB', 'MYSQL323', 'MYSQL40', 'MSSQL', 'ORACLE',
-    // removed; in MySQL 5.0.33, this produces exports that
-    // can't be read by POSTGRESQL (see our bug #1596328)
-    //'POSTGRESQL',
-    'TRADITIONAL');
-$cfg_db['Import']['ldi_local_option'] = array('auto', true, false);
-$cfg_db['Export']['format'] = array('codegen', 'csv', 'excel', 'htmlexcel',
-    'htmlword', 'latex', 'ods', 'odt', 'pdf', 'sql', 'texytext', 'xls', 'xml',
-    'yaml');
-$cfg_db['Export']['compression'] = array('none', 'zip', 'gzip', 'bzip2');
-$cfg_db['Export']['charset'] = array_merge(array(''), $GLOBALS['cfg']['AvailableCharsets']);
-$cfg_db['Export']['method'] = array('quick', 'custom', 'custom-no-form');
-
-/**
- * Config options which will be placed in config file even if they are set
- * to their default values (use only full paths)
- */
-$persist_keys = array(
-    'DefaultLang',
-    'ServerDefault',
-    'UploadDir',
-    'SaveDir',
-    'Servers/1/verbose',
-    'Servers/1/host',
-    'Servers/1/port',
-    'Servers/1/socket',
-    'Servers/1/extension',
-    'Servers/1/connect_type',
-    'Servers/1/auth_type',
-    'Servers/1/user',
-    'Servers/1/password');
-
-/**
- * Default values overrides
- * Use only full paths
- */
-$cfg_db['_overrides'] = array();
-$cfg_db['_overrides']['Servers/1/extension'] = extension_loaded('mysqli')
-    ? 'mysqli' : 'mysql';
-
-/**
- * Validator assignments (functions from validate.lib.php and 'validators'
- * object in scripts.js)
- * Use only full paths and form ids
- */
-$cfg_db['_validators'] = array(
-    'Server' => 'validate_server',
-    'Server_pmadb' => 'validate_pmadb',
-    'Servers/1/port' => 'validate_port_number',
-    'Servers/1/hide_db' => 'validate_regex',
-    'TrustedProxies' => 'validate_trusted_proxies',
-    'LoginCookieValidity' => 'validate_positive_number',
-    'LoginCookieStore' => 'validate_non_negative_number',
-    'QueryHistoryMax' => 'validate_positive_number',
-    'LeftFrameTableLevel' => 'validate_positive_number',
-    'MaxRows' => 'validate_positive_number',
-    'CharTextareaCols' => 'validate_positive_number',
-    'CharTextareaRows' => 'validate_positive_number',
-    'InsertRows' => 'validate_positive_number',
-    'ForeignKeyMaxLimit' => 'validate_positive_number',
-    'Import/skip_queries' => 'validate_non_negative_number');
-?>
diff --git a/setup/lib/form_processing.lib.php b/setup/lib/form_processing.lib.php
index 7128a61..7bad38c 100644
--- a/setup/lib/form_processing.lib.php
+++ b/setup/lib/form_processing.lib.php
@@ -1,10 +1,9 @@
 <?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
 /**
  * Formset processing library
  *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin-setup
  */
 
 /**
@@ -41,13 +40,13 @@ function process_formset(FormDisplay $form_display) {
             ?>
             <div class="warning">
                 <h4><?php echo __('Warning') ?></h4>
-                <?php echo PMA_lang('error_form') ?><br />
-                <a href="?page=<?php echo $page . $formset . $id . $separator ?>mode=revert"><?php echo PMA_lang('RevertErroneousFields') ?></a>
+                <?php echo __('Submitted form contains errors') ?><br />
+                <a href="?page=<?php echo $page . $formset . $id . $separator ?>mode=revert"><?php echo __('Try to revert erroneous fields to their default values') ?></a>
             </div>
             <?php $form_display->displayErrors() ?>
-            <a class="btn" href="index.php"><?php echo PMA_lang('IgnoreErrors') ?></a>
+            <a class="btn" href="index.php"><?php echo __('Ignore errors') ?></a>
              
-            <a class="btn" href="?page=<?php echo $page . $formset . $id . $separator ?>mode=edit"><?php echo PMA_lang('ShowForm') ?></a>
+            <a class="btn" href="?page=<?php echo $page . $formset . $id . $separator ?>mode=edit"><?php echo __('Show form') ?></a>
             <?php
         } else {
             // drop post data
diff --git a/setup/lib/forms.inc.php b/setup/lib/forms.inc.php
deleted file mode 100644
index 3219709..0000000
--- a/setup/lib/forms.inc.php
+++ /dev/null
@@ -1,183 +0,0 @@
-<?php
-/**
- * List of avaible forms, each form is described as an array of fields to display.
- * Fields MUST have their counterparts in the $cfg array.
- *
- * There are two possible notations:
- * $forms['Form name'] = array('Servers' => array(1 => array('host')));
- * can be written as
- * $forms['Form name'] = array('Servers/1/host');
- *
- * You can assign default values set by special button ("set value: ..."), eg.:
- * $forms['Server_pmadb'] = array('Servers' => array(1 => array(
- *  'pmadb' => 'phpmyadmin')));
- *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
- */
-
-$forms = array();
-$forms['_config.php'] = array(
-    'DefaultLang',
-    'ServerDefault');
-$forms['Server'] = array('Servers' => array(1 => array(
-    'verbose',
-    'host',
-    'port',
-    'socket',
-    'ssl',
-    'connect_type',
-    'extension',
-    'compress',
-    'auth_type',
-    'auth_http_realm',
-    'user',
-    'password',
-    'nopassword',
-    'auth_swekey_config' => './swekey.conf')));
-$forms['Server_login_options'] = array('Servers' => array(1 => array(
-    'SignonSession',
-    'SignonURL',
-    'LogoutURL')));
-$forms['Server_config'] = array('Servers' => array(1 => array(
-    'only_db',
-    'hide_db',
-    'AllowRoot',
-    'AllowNoPassword',
-    'DisableIS',
-    'AllowDeny/order',
-    'AllowDeny/rules',
-    'ShowDatabasesCommand',
-    'CountTables')));
-$forms['Server_pmadb'] = array('Servers' => array(1 => array(
-    'pmadb' => 'phpmyadmin',
-    'controluser',
-    'controlpass',
-    'verbose_check',
-    'bookmarktable' => 'pma_bookmark',
-    'relation' => 'pma_relation',
-    'table_info' => 'pma_table_info',
-    'table_coords' => 'pma_table_coords',
-    'pdf_pages' => 'pma_pdf_pages',
-    'column_info' => 'pma_column_info',
-    'history' => 'pma_history',
-    'tracking' => 'pma_tracking',
-    'designer_coords' => 'pma_designer_coords')));
-$forms['Server_tracking'] = array('Servers' => array(1 => array(
-    'tracking_version_auto_create',
-    'tracking_default_statements',
-    'tracking_add_drop_view',
-    'tracking_add_drop_table',
-    'tracking_add_drop_database',
-)));
-$forms['Import_export'] = array(
-    'UploadDir',
-    'SaveDir',
-    'RecodingEngine',
-    'IconvExtraParams',
-    'ZipDump',
-    'GZipDump',
-    'BZipDump',
-    'CompressOnFly');
-$forms['Security'] = array(
-    'blowfish_secret',
-    'ForceSSL',
-    'CheckConfigurationPermissions',
-    'TrustedProxies',
-    'AllowUserDropDatabase',
-    'AllowArbitraryServer',
-    'LoginCookieRecall',
-    'LoginCookieValidity',
-    'LoginCookieStore',
-    'LoginCookieDeleteAll');
-$forms['Sql_queries'] = array(
-    'ShowSQL',
-    'Confirm',
-    'QueryHistoryDB',
-    'QueryHistoryMax',
-    'IgnoreMultiSubmitErrors',
-    'VerboseMultiSubmit');
-$forms['Other_core_settings'] = array(
-    'MaxDbList',
-    'MaxTableList',
-    'MaxCharactersInDisplayedSQL',
-    'OBGzip',
-    'PersistentConnections',
-    'ExecTimeLimit',
-    'MemoryLimit',
-    'SkipLockedTables',
-    'UseDbSearch');
-$forms['Left_frame'] = array(
-    'LeftFrameLight',
-    'LeftDisplayLogo',
-    'LeftLogoLink',
-    'LeftLogoLinkWindow',
-    'LeftDefaultTabTable',
-    'LeftPointerEnable');
-$forms['Left_servers'] = array(
-    'LeftDisplayServers',
-    'DisplayServersList');
-$forms['Left_databases'] = array(
-    'DisplayDatabasesList',
-    'LeftFrameDBTree',
-    'LeftFrameDBSeparator',
-    'ShowTooltipAliasDB');
-$forms['Left_tables'] = array(
-    'LeftFrameTableSeparator',
-    'LeftFrameTableLevel',
-    'ShowTooltip',
-    'ShowTooltipAliasTB');
-$forms['Startup'] = array(
-    'ShowStats',
-    'ShowPhpInfo',
-    'ShowServerInfo',
-    'ShowChgPassword',
-    'ShowCreateDb',
-    'SuggestDBName');
-$forms['Browse'] = array(
-    'NavigationBarIconic',
-    'ShowAll',
-    'MaxRows',
-    'Order',
-    'BrowsePointerEnable',
-    'BrowseMarkerEnable');
-$forms['Edit'] = array(
-    'ProtectBinary',
-    'ShowFunctionFields',
-    'CharEditing',
-    'CharTextareaCols',
-    'CharTextareaRows',
-    'InsertRows',
-    'ForeignKeyDropdownOrder',
-    'ForeignKeyMaxLimit');
-$forms['Tabs'] = array(
-    'LightTabs',
-    'PropertiesIconic',
-    'DefaultTabServer',
-    'DefaultTabDatabase',
-    'DefaultTabTable',
-	'QueryWindowDefTab');
-$forms['Sql_box'] = array('SQLQuery' => array(
-    'Edit',
-    'Explain',
-    'ShowAsPHP',
-    'Validate',
-    'Refresh'));
-$forms['Import_defaults'] = array('Import' => array(
-    'format',
-    'allow_interrupt',
-    'skip_queries'));
-$forms['Export_defaults'] = array('Export' => array(
-    'format',
-    'method',
-    'compression',
-    'asfile',
-    'charset',
-    'onserver',
-    'onserver_overwrite',
-    'remember_file_template',
-    'file_template_table',
-    'file_template_database',
-    'file_template_server'));
-?>
diff --git a/setup/lib/index.lib.php b/setup/lib/index.lib.php
index 115cc9f..17c9cf6 100644
--- a/setup/lib/index.lib.php
+++ b/setup/lib/index.lib.php
@@ -1,14 +1,12 @@
 <?php
-
+/* vim: set expandtab sw=4 ts=4 sts=4: */
 /**
  * Various checks and message functions used on index page.
  *
  * Security checks are the idea of Aung Khant <aungkhant[at]yehg.net>, http://yehg.net/lab
  * Version check taken from the old setup script by Michal ÄŒihaÅ™ <michal at cihar.com>
  *
- * @package    phpMyAdmin-setup
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin-setup
  */
 
 if (!defined('PHPMYADMIN')) {
@@ -44,7 +42,6 @@ function messages_begin()
 function messages_set($type, $id, $title, $message)
 {
     $fresh = !isset($_SESSION['messages'][$type][$id]);
-    $title = PMA_lang($title);
     $_SESSION['messages'][$type][$id] = array(
         'fresh' => $fresh,
         'active' => true,
@@ -118,15 +115,15 @@ function PMA_version_check()
             $data = curl_exec($ch);
             curl_close($ch);
         } else {
-            messages_set('error', $message_id, 'VersionCheck',
-                PMA_lang('VersionCheckWrapperError'));
+            messages_set('error', $message_id, __('Version check'),
+                __('Neither URL wrapper nor CURL is available. Version check is not possible.'));
             return;
         }
     }
 
     if (empty($data)) {
-        messages_set('error', $message_id, 'VersionCheck',
-            PMA_lang('VersionCheckDataError'));
+        messages_set('error', $message_id, __('Version check'),
+            __('Reading of version failed. Maybe you\'re offline or the upgrade server does not respond.'));
         return;
     }
 
@@ -142,30 +139,30 @@ function PMA_version_check()
 
     $version_upstream = version_to_int($version);
     if ($version_upstream === false) {
-        messages_set('error', $message_id, 'VersionCheck',
-            PMA_lang('VersionCheckInvalid'));
+        messages_set('error', $message_id, __('Version check'),
+            __('Got invalid version string from server'));
         return;
     }
 
     $version_local = version_to_int($GLOBALS['PMA_Config']->get('PMA_VERSION'));
     if ($version_local === false) {
-        messages_set('error', $message_id, 'VersionCheck',
-            PMA_lang('VersionCheckUnparsable'));
+        messages_set('error', $message_id, __('Version check'),
+            __('Unparsable version string'));
         return;
     }
 
     if ($version_upstream > $version_local) {
         $version = htmlspecialchars($version);
         $date = htmlspecialchars($date);
-        messages_set('notice', $message_id, 'VersionCheck',
-            PMA_lang('VersionCheckNewAvailable', $version, $date));
+        messages_set('notice', $message_id, __('Version check'),
+            sprintf(__('A newer version of phpMyAdmin is available and you should consider upgrading. The newest version is %s, released on %s.'), $version, $date));
     } else {
         if ($version_local % 100 == 0) {
-            messages_set('notice', $message_id, 'VersionCheck',
-                PMA_lang('VersionCheckNewAvailableSvn', $version, $date));
+            messages_set('notice', $message_id, __('Version check'),
+                PMA_sanitize(sprintf(__('You are using Git version, run [kbd]git pull[/kbd] :-)[br]The latest stable version is %s, released on %s.'), $version, $date)));
         } else {
-            messages_set('notice', $message_id, 'VersionCheck',
-                PMA_lang('VersionCheckNone'));
+            messages_set('notice', $message_id, __('Version check'),
+                __('No newer stable version is available'));
         }
     }
 }
@@ -200,7 +197,7 @@ function version_to_int($version)
                 $added = 0;
                 break;
             default:
-                messages_set('notice', 'version_match', 'VersionCheck',
+                messages_set('notice', 'version_match', __('Version check'),
                     'Unknown version part: ' . htmlspecialchars($matches[6]));
                 $added = 0;
                 break;
@@ -249,6 +246,19 @@ function perform_config_checks()
     $blowfish_secret = $cf->get('blowfish_secret');
     $blowfish_secret_set = false;
     $cookie_auth_used = false;
+
+    $strAllowArbitraryServerWarning = __('This [a@?page=form&formset=features#tab_Security]option[/a] should be disabled as it allows attackers to bruteforce login to any MySQL server. If you feel this is necessary, use [a@?page=form&formset=features#tab_Security]trusted proxies list[/a]. However, IP-based protection may not be reliable if your IP belongs to an ISP where thousands of users, including you, are connected to.');
+    $strBlowfishSecretMsg = __('You didn\'t have blowfish secret set and have enabled cookie authentication, so a key was automatically generated for you. It is used to encrypt cookies; you don\'t need to remember it.');
+    $strBZipDumpWarning = __('[a@?page=form&formset=features#tab_Import_export]Bzip2 compression and decompression[/a] requires functions (%s) which are unavailable on this system.');
+    $strDirectoryNotice = __('This value should be double checked to ensure that this directory is neither world accessible nor readable or writable by other users on your server.');
+    $strForceSSLNotice = __('This [a@?page=form&formset=features#tab_Security]option[/a] should be enabled if your web server supports it');
+    $strGZipDumpWarning = __('[a@?page=form&formset=features#tab_Import_export]GZip compression and decompression[/a] requires functions (%s) which are unavailable on this system.');
+    $strLoginCookieValidityWarning = __('[a@?page=form&formset=features#tab_Security]Login cookie validity[/a] should be set to 1800 seconds (30 minutes) at most. Values larger than 1800 may pose a security risk such as impersonation.');
+    $strSecurityInfoMsg = __('If you feel this is necessary, use additional protection settings - [a@?page=servers&mode=edit&id=%1$d#tab_Server_config]host authentication[/a] settings and [a@?page=form&formset=features#tab_Security]trusted proxies list[/a]. However, IP-based protection may not be reliable if your IP belongs to an ISP where thousands of users, including you, are connected to.');
+    $strServerAuthConfigMsg = __('You set the [kbd]config[/kbd] authentication type and included username and password for auto-login, which is not a desirable option for live hosts. Anyone who knows or guesses your phpMyAdmin URL can directly access your phpMyAdmin panel. Set [a@?page=servers&mode=edit&id=%1$d#tab_Server]authentication type[/a] to [kbd]cookie[/kbd] or [kbd]http[/kbd].');
+    $strZipDumpExportWarning = __('[a@?page=form&formset=features#tab_Import_export]Zip compression[/a] requires functions (%s) which are unavailable on this system.');
+    $strZipDumpImportWarning = __('[a@?page=form&formset=features#tab_Import_export]Zip decompression[/a] requires functions (%s) which are unavailable on this system.');
+
     for ($i = 1, $server_cnt = $cf->getServerCount(); $i <= $server_cnt; $i++) {
         $cookie_auth_server = ($cf->getValue("Servers/$i/auth_type") == 'cookie');
         $cookie_auth_used |= $cookie_auth_server;
@@ -268,9 +278,9 @@ function perform_config_checks()
         // should be enabled if possible
         //
         if (!$cf->getValue("Servers/$i/ssl")) {
-            $title = PMA_lang_name('Servers/1/ssl') . " ($server_name)";
+            $title = PMA_lang(PMA_lang_name('Servers/1/ssl')) . " ($server_name)";
             messages_set('notice', "Servers/$i/ssl", $title,
-                PMA_lang('ServerSslMsg'));
+                __('You should use SSL connections if your web server supports it'));
         }
 
         //
@@ -278,9 +288,9 @@ function perform_config_checks()
         // warn about using 'mysql'
         //
         if ($cf->getValue("Servers/$i/extension") == 'mysql') {
-            $title = PMA_lang_name('Servers/1/extension') . " ($server_name)";
+            $title = PMA_lang(PMA_lang_name('Servers/1/extension')) . " ($server_name)";
             messages_set('notice', "Servers/$i/extension", $title,
-                PMA_lang('ServerExtensionMsg'));
+                __('You should use mysqli for performance reasons'));
         }
 
         //
@@ -288,12 +298,12 @@ function perform_config_checks()
         // warn about full user credentials if 'auth_type' is 'config'
         //
         if ($cf->getValue("Servers/$i/auth_type") == 'config'
-            && $cf->getValue("Servers/$i/user") != ''
-            && $cf->getValue("Servers/$i/password") != '') {
-            $title = PMA_lang_name('Servers/1/auth_type') . " ($server_name)";
+                && $cf->getValue("Servers/$i/user") != ''
+                && $cf->getValue("Servers/$i/password") != '') {
+            $title = PMA_lang(PMA_lang_name('Servers/1/auth_type')) . " ($server_name)";
             messages_set('warning', "Servers/$i/auth_type", $title,
-                PMA_lang('ServerAuthConfigMsg', $i) . ' ' .
-                PMA_lang('ServerSecurityInfoMsg', $i));
+                    PMA_lang($strServerAuthConfigMsg, $i) . ' ' .
+                            PMA_lang($strSecurityInfoMsg, $i));
         }
 
         //
@@ -302,11 +312,11 @@ function perform_config_checks()
         // serious security flaw
         //
         if ($cf->getValue("Servers/$i/AllowRoot")
-            && $cf->getValue("Servers/$i/AllowNoPassword")) {
-            $title = PMA_lang_name('Servers/1/AllowNoPassword') . " ($server_name)";
+                && $cf->getValue("Servers/$i/AllowNoPassword")) {
+            $title = PMA_lang(PMA_lang_name('Servers/1/AllowNoPassword')) . " ($server_name)";
             messages_set('warning', "Servers/$i/AllowNoPassword", $title,
-                PMA_lang('ServerNoPasswordMsg') . ' ' .
-                PMA_lang('ServerSecurityInfoMsg', $i));
+                    __('You allow for connecting to the server without a password.') . ' ' .
+                            PMA_lang($strSecurityInfoMsg, $i));
         }
     }
 
@@ -317,25 +327,27 @@ function perform_config_checks()
     if ($cookie_auth_used) {
         if ($blowfish_secret_set) {
             // 'cookie' auth used, blowfish_secret was generated
-            messages_set('notice', 'blowfish_secret_created', 'blowfish_secret_name',
-                 PMA_lang('BlowfishSecretMsg'));
+            messages_set('notice', 'blowfish_secret_created',
+                PMA_lang(PMA_lang_name('blowfish_secret')),
+                $strBlowfishSecretMsg);
         } else {
             $blowfish_warnings = array();
             // check length
             if (strlen($blowfish_secret) < 8) {
                 // too short key
-                $blowfish_warnings[] = PMA_lang('BlowfishSecretLengthMsg');
+                $blowfish_warnings[] = __('Key is too short, it should have at least 8 characters');
             }
             // check used characters
             $has_digits = (bool) preg_match('/\d/', $blowfish_secret);
             $has_chars = (bool) preg_match('/\S/', $blowfish_secret);
             $has_nonword = (bool) preg_match('/\W/', $blowfish_secret);
             if (!$has_digits || !$has_chars || !$has_nonword) {
-                $blowfish_warnings[] = PMA_lang('BlowfishSecretCharsMsg');
+                $blowfish_warnings[] = PMA_lang(__('Key should contain letters, numbers [em]and[/em] special characters'));
             }
             if (!empty($blowfish_warnings)) {
                 messages_set('warning', 'blowfish_warnings' . count($blowfish_warnings),
-                    'blowfish_secret_name', implode("<br />", $blowfish_warnings));
+                    PMA_lang(PMA_lang_name('blowfish_secret')),
+                    implode("<br />", $blowfish_warnings));
             }
         }
     }
@@ -345,8 +357,9 @@ function perform_config_checks()
     // should be enabled if possible
     //
     if (!$cf->getValue('ForceSSL')) {
-        messages_set('notice', 'ForceSSL', 'ForceSSL_name',
-            PMA_lang('ForceSSLMsg'));
+        messages_set('notice', 'ForceSSL',
+            PMA_lang(PMA_lang_name('ForceSSL')),
+            PMA_lang($strForceSSLNotice));
     }
 
     //
@@ -354,8 +367,9 @@ function perform_config_checks()
     // should be disabled
     //
     if ($cf->getValue('AllowArbitraryServer')) {
-        messages_set('warning', 'AllowArbitraryServer', 'AllowArbitraryServer_name',
-            PMA_lang('AllowArbitraryServerMsg'));
+        messages_set('warning', 'AllowArbitraryServer',
+            PMA_lang(PMA_lang_name('AllowArbitraryServer')),
+            PMA_lang($strAllowArbitraryServerWarning));
     }
 
     //
@@ -363,8 +377,9 @@ function perform_config_checks()
     // should be at most 1800 (30 min)
     //
     if ($cf->getValue('LoginCookieValidity') > 1800) {
-        messages_set('warning', 'LoginCookieValidity', 'LoginCookieValidity_name',
-            PMA_lang('LoginCookieValidityMsg'));
+        messages_set('warning', 'LoginCookieValidity',
+            PMA_lang(PMA_lang_name('LoginCookieValidity')),
+            PMA_lang($strLoginCookieValidityWarning));
     }
 
     //
@@ -372,8 +387,9 @@ function perform_config_checks()
     // should not be world-accessible
     //
     if ($cf->getValue('SaveDir') != '') {
-        messages_set('notice', 'SaveDir', 'SaveDir_name',
-            PMA_lang('DirectoryNotice'));
+        messages_set('notice', 'SaveDir',
+            PMA_lang(PMA_lang_name('SaveDir')),
+            PMA_lang($strDirectoryNotice));
     }
 
     //
@@ -381,8 +397,9 @@ function perform_config_checks()
     // should not be world-accessible
     //
     if ($cf->getValue('TempDir') != '') {
-        messages_set('notice', 'TempDir', 'TempDir_name',
-            PMA_lang('DirectoryNotice'));
+        messages_set('notice', 'TempDir',
+            PMA_lang(PMA_lang_name('TempDir')),
+            PMA_lang($strDirectoryNotice));
     }
 
     //
@@ -390,9 +407,10 @@ function perform_config_checks()
     // requires zlib functions
     //
     if ($cf->getValue('GZipDump')
-        && (@!function_exists('gzopen') || @!function_exists('gzencode'))) {
-        messages_set('warning', 'GZipDump', 'GZipDump_name',
-            PMA_lang('GZipDumpWarning', 'gzencode'));
+            && (@!function_exists('gzopen') || @!function_exists('gzencode'))) {
+        messages_set('warning', 'GZipDump',
+            PMA_lang(PMA_lang_name('GZipDump')),
+            PMA_lang($strGZipDumpWarning, 'gzencode'));
     }
 
     //
@@ -400,15 +418,16 @@ function perform_config_checks()
     // requires bzip2 functions
     //
     if ($cf->getValue('BZipDump')
-        && (!@function_exists('bzopen') || !@function_exists('bzcompress'))) {
+            && (!@function_exists('bzopen') || !@function_exists('bzcompress'))) {
         $functions = @function_exists('bzopen')
-            ? '' :
-            'bzopen';
+                ? '' :
+                'bzopen';
         $functions .= @function_exists('bzcompress')
-            ? ''
-            : ($functions ? ', ' : '') . 'bzcompress';
-        messages_set('warning', 'BZipDump', 'BZipDump_name',
-            PMA_lang('BZipDumpWarning', $functions));
+                ? ''
+                : ($functions ? ', ' : '') . 'bzcompress';
+        messages_set('warning', 'BZipDump',
+            PMA_lang(PMA_lang_name('BZipDump')),
+            PMA_lang($strBZipDumpWarning, $functions));
     }
 
     //
@@ -416,8 +435,9 @@ function perform_config_checks()
     // requires zip_open in import
     //
     if ($cf->getValue('ZipDump') && !@function_exists('zip_open')) {
-        messages_set('warning', 'ZipDump_import', 'ZipDump_name',
-            PMA_lang('ZipDumpImportWarning', 'zip_open'));
+        messages_set('warning', 'ZipDump_import',
+            PMA_lang(PMA_lang_name('ZipDump')),
+            PMA_lang($strZipDumpImportWarning, 'zip_open'));
     }
 
     //
@@ -425,8 +445,9 @@ function perform_config_checks()
     // requires gzcompress in export
     //
     if ($cf->getValue('ZipDump') && !@function_exists('gzcompress')) {
-        messages_set('warning', 'ZipDump_export', 'ZipDump_name',
-            PMA_lang('ZipDumpExportWarning', 'gzcompress'));
+        messages_set('warning', 'ZipDump_export',
+            PMA_lang(PMA_lang_name('ZipDump')),
+            PMA_lang($strZipDumpExportWarning, 'gzcompress'));
     }
 }
-?>
+?>
\ No newline at end of file
diff --git a/setup/lib/messages.inc.php b/setup/lib/messages.inc.php
deleted file mode 100644
index 4284485..0000000
--- a/setup/lib/messages.inc.php
+++ /dev/null
@@ -1,381 +0,0 @@
-<?php
-/* $Id$ */
-/**
- * Messages for phpMyAdmin.
- *
- * This file is here for easy transition to Gettext. You should not add any
- * new messages here, use instead gettext directly in your template/PHP
- * file.
- */
-
-if (!function_exists('__')) {
-    die('Bad invocation!');
-}
-
-
-$strSetupAllowArbitraryServer_desc = __('If enabled user can enter any MySQL server in login form for cookie auth');
-$strSetupAllowArbitraryServerMsg = __('This [a@?page=form&formset=features#tab_Security]option[/a] should be disabled as it allows attackers to bruteforce login to any MySQL server. If you feel this is necessary, use [a@?page=form&formset=features#tab_Security]trusted proxies list[/a]. However, IP-based protection may not be reliable if your IP belongs to an ISP where thousands of users, including you, are connected to.');
-$strSetupAllowArbitraryServer_name = __('Allow login to any MySQL server');
-$strSetupAllowUserDropDatabase_name = __('Show "Drop database" link to normal users');
-$strSetupBlowfishSecretCharsMsg = __('Key should contain letters, numbers [em]and[/em] special characters');
-$strSetupblowfish_secret_desc = __('Secret passphrase used for encrypting cookies in [kbd]cookie[/kbd] authentication');
-$strSetupBlowfishSecretLengthMsg = __('Key is too short, it should have at least 8 characters');
-$strSetupBlowfishSecretMsg = __('You didn\'t have blowfish secret set and have enabled cookie authentication, so a key was automatically generated for you. It is used to encrypt cookies; you don\'t need to remember it.');
-$strSetupblowfish_secret_name = __('Blowfish secret');
-$strSetupBrowseMarkerEnable_desc = __('Highlight selected rows');
-$strSetupBrowseMarkerEnable_name = __('Row marker');
-$strSetupBrowsePointerEnable_desc = __('Highlight row pointed by the mouse cursor');
-$strSetupBrowsePointerEnable_name = __('Highlight pointer');
-$strSetupBZipDump_desc = __('Enable [a at http://en.wikipedia.org/wiki/Bzip2]bzip2[/a] compression for import and export operations');
-$strSetupBZipDump_name = __('Bzip2');
-$strSetupBZipDumpWarning = __('[a@?page=form&formset=features#tab_Import_export]Bzip2 compression and decompression[/a] requires functions (%s) which are unavailable on this system.');
-$strSetupCannotLoadConfig = __('Cannot load or save configuration');
-$strSetupCannotLoadConfigMsg = __('Please create web server writable folder [em]config[/em] in phpMyAdmin top level directory as described in [a at ../Documentation.html#setup_script]documentation[/a]. Otherwise you will be only able to download or display it.');
-$strSetupCharEditing_desc = __('Defines which type of editing controls should be used for CHAR and VARCHAR columns; [kbd]input[/kbd] - allows limiting of input length, [kbd]textarea[/kbd] - allows newlines in columns');
-$strSetupCharEditing_name = __('CHAR columns editing');
-$strSetupCharTextareaCols_desc = __('Number of columns for CHAR/VARCHAR textareas');
-$strSetupCharTextareaCols_name = __('CHAR textarea columns');
-$strSetupCharTextareaRows_desc = __('Number of rows for CHAR/VARCHAR textareas');
-$strSetupCharTextareaRows_name = __('CHAR textarea rows');
-$strSetupCheckConfigurationPermissions_name = __('Check config file permissions');
-$strSetupClear = __('Clear');
-$strSetupCompressOnFly_desc = __('Compress gzip/bzip2 exports on the fly without the need for much memory; if you encounter problems with created gzip/bzip2 files disable this feature');
-$strSetupCompressOnFly_name = __('Compress on the fly');
-$strSetupConfigurationFile = __('Configuration file');
-$strSetupConfirm_desc = __('Whether a warning ("Are your really sure...") should be displayed when you\'re about to lose data');
-$strSetupConfirm_name = __('Confirm DROP queries');
-$strSetupDefaultLanguage = __('Default language');
-$strSetupDefaultServer = __('Default server');
-$strSetupDefaultTabDatabase_desc = __('Tab that is displayed when entering a database');
-$strSetupDefaultTabDatabase_name = __('Default database tab');
-$strSetupDefaultTabServer_desc = __('Tab that is displayed when entering a server');
-$strSetupDefaultTabServer_name = __('Default server tab');
-$strSetupDefaultTabTable_desc = __('Tab that is displayed when entering a table');
-$strSetupDefaultTabTable_name = __('Default table tab');
-$strSetupDirectoryNotice = __('This value should be double checked to ensure that this directory is neither world accessible nor readable or writable by other users on your server.');
-$strSetupDisplayDatabasesList_desc = __('Show database listing as a list instead of a drop down');
-$strSetupDisplayDatabasesList_name = __('Display databases as a list');
-$strSetupDisplay = __('Display');
-$strSetupDisplayServersList_desc = __('Show server listing as a list instead of a drop down');
-$strSetupDisplayServersList_name = __('Display servers as a list');
-$strSetupDonateLink = __('Donate');
-$strSetupDownload = __('Download');
-$strSetupEndOfLine = __('End of line');
-$strSetuperror_connection = __('Could not connect to MySQL server');
-$strSetuperror_empty_pmadb_password = __('Empty phpMyAdmin control user password while using pmadb');
-$strSetuperror_empty_pmadb_user = __('Empty phpMyAdmin control user while using pmadb');
-$strSetuperror_empty_signon_session = __('Empty signon session name while using signon authentication method');
-$strSetuperror_empty_signon_url = __('Empty signon URL while using signon authentication method');
-$strSetuperror_empty_user_for_config_auth = __('Empty username while using config authentication method');
-$strSetuperror_form = __('Submitted form contains errors');
-$strSetuperror_incorrect_ip_address = __('Incorrect IP address: %s');
-$strSetuperror_incorrect_port = __('Not a valid port number');
-$strSetuperror_incorrect_value = __('Incorrect value');
-$strSetuperror_missing_field_data = __('Missing data for %s');
-$strSetuperror_nan_nneg = __('Not a non-negative number');
-$strSetuperror_nan_p = __('Not a positive number');
-$strSetupExecTimeLimit_desc = __('Set the number of seconds a script is allowed to run ([kbd]0[/kbd] for no limit)');
-$strSetupExecTimeLimit_name = __('Maximum execution time');
-$strSetupExport_asfile_name = __('Save as file');
-$strSetupExport_charset_name = __('Character set of the file');
-$strSetupExport_compression_name = __('Compression');
-$strSetupExport_file_template_database_name = __('Database name template');
-$strSetupExport_file_template_server_name = __('Server name template');
-$strSetupExport_file_template_table_name = __('Table name template');
-$strSetupExport_format_name = __('Format');
-$strSetupExport_method_name = __('Method');
-$strSetupExport_onserver_name = __('Save on server');
-$strSetupExport_onserver_overwrite_name = __('Overwrite existing file(s)');
-$strSetupExport_remember_file_template_name = __('Remember file name template');
-$strSetupFalse = __('no');
-$strSetupForceSSL_desc = __('Force secured connection while using phpMyAdmin');
-$strSetupForceSSLMsg = __('This [a@?page=form&formset=features#tab_Security]option[/a] should be enabled if your web server supports it');
-$strSetupForceSSL_name = __('Force SSL connection');
-$strSetupForeignKeyDropdownOrder_desc = __('Sort order for items in a foreign-key dropdown box; [kbd]content[/kbd] is the referenced data, [kbd]id[/kbd] is the key value');
-$strSetupForeignKeyDropdownOrder_name = __('Foreign key dropdown order');
-$strSetupForeignKeyMaxLimit_desc = __('A dropdown will be used if fewer items are present');
-$strSetupForeignKeyMaxLimit_name = __('Foreign key limit');
-$strSetupForm_Browse = __('Browse mode');
-$strSetupForm_Browse_desc = __('Customize browse mode');
-$strSetupForm_Edit_desc = __('Customize edit mode');
-$strSetupForm_Edit = __('Edit mode');
-$strSetupForm_Export_defaults_desc = __('Customize default export options');
-$strSetupForm_Export_defaults = __('Export defaults');
-$strSetupForm_Import_defaults_desc = __('Customize default common import options');
-$strSetupForm_Import_defaults = __('Import defaults');
-$strSetupForm_Import_export_desc = __('Set import and export directories and compression options');
-$strSetupForm_Import_export = __('Import / export');
-$strSetupForm_Left_databases = __('Databases');
-$strSetupForm_Left_databases_desc = __('Databases display options');
-$strSetupForm_Left_frame_desc = __('Customize appearance of the navigation frame');
-$strSetupForm_Left_frame = __('Navigation frame');
-$strSetupForm_Left_servers_desc = __('Servers display options');
-$strSetupForm_Left_servers = __('Servers');
-$strSetupForm_Left_tables_desc = __('Tables display options');
-$strSetupForm_Left_tables = __('Tables');
-$strSetupForm_Main_frame = __('Main frame');
-$strSetupForm_Other_core_settings_desc = __('Settings that didn\'t fit enywhere else');
-$strSetupForm_Other_core_settings = __('Other core settings');
-$strSetupForm_Query_window_desc = __('Customize query window options');
-$strSetupForm_Query_window = __('Query window');
-$strSetupForm_Security_desc = __('Please note that phpMyAdmin is just a user interface and its features do not limit MySQL');
-$strSetupForm_Security = __('Security');
-$strSetupForm_Server = __('Basic settings');
-$strSetupForm_Server_config_desc = __('Advanced server configuration, do not change these options unless you know what they are for');
-$strSetupForm_Server_config = __('Server configuration');
-$strSetupForm_Server_desc = __('Enter server connection parameters');
-$strSetupForm_Server_login_options_desc = __('Enter login options for signon authentication');
-$strSetupForm_Server_login_options = __('Signon login options');
-$strSetupForm_Server_pmadb_desc = __('Configure phpMyAdmin database to gain access to additional features, see [a at ../Documentation.html#linked-tables]phpMyAdmin configuration storage[/a] in documentation');
-$strSetupForm_Server_pmadb = __('PMA database');
-$strSetupForm_Server_tracking_desc = __('Tracking of changes made in database. Requires configured PMA database.');
-$strSetupForm_Server_tracking = __('Changes tracking');
-$strSetupFormset_customization = __('Customization');
-$strSetupFormset_export = __('Customize export options');
-$strSetupFormset_features = __('Features');
-$strSetupFormset_import = __('Customize import defaults');
-$strSetupFormset_left_frame = __('Customize navigation frame');
-$strSetupFormset_main_frame = __('Customize main frame');
-$strSetupForm_Sql_box_desc = __('Customize links shown in SQL Query boxes');
-$strSetupForm_Sql_box = __('SQL Query box');
-$strSetupForm_Sql_queries_desc = __('SQL queries settings, for SQL Query box options see [a@?page=form&formset=main_frame#tab_Sql_box]Navigation frame[/a] settings');
-$strSetupForm_Sql_queries = __('SQL queries');
-$strSetupForm_Startup_desc = __('Customize startup page');
-$strSetupForm_Startup = __('Startup');
-$strSetupForm_Tabs_desc = __('Choose how you want tabs to work');
-$strSetupForm_Tabs = __('Tabs');
-$strSetupGZipDump_desc = __('Enable [a at http://en.wikipedia.org/wiki/Gzip]gzip[/a] compression for import and export operations');
-$strSetupGZipDump_name = __('GZip');
-$strSetupGZipDumpWarning = __('[a@?page=form&formset=features#tab_Import_export]GZip compression and decompression[/a] requires functions (%s) which are unavailable on this system.');
-$strSetupHomepageLink = __('phpMyAdmin homepage');
-$strSetupIconvExtraParams_name = __('Extra parameters for iconv');
-$strSetupIgnoreErrors = __('Ignore errors');
-$strSetupIgnoreMultiSubmitErrors_desc = __('If enabled, phpMyAdmin continues computing multiple-statement queries even if one of the queries failed');
-$strSetupIgnoreMultiSubmitErrors_name = __('Ignore multiple statement errors');
-$strSetupImport_allow_interrupt_desc = __('Allow interrupt of import in case script detects it is close to time limit. This might be good way to import large files, however it can break transactions.');
-$strSetupImport_allow_interrupt_name = __('Partial import: allow interrupt');
-$strSetupImport_format_desc = __('Default format; be aware that this list depends on location (database, table) and only SQL is always available');
-$strSetupImport_format_name = __('Format of imported file');
-$strSetupImport_skip_queries_desc = __('Number of queries to skip from start');
-$strSetupImport_skip_queries_name = __('Partial import: skip queries');
-$strSetupInsecureConnection = __('Insecure connection');
-$strSetupInsecureConnectionMsg1 = __('You are not using a secure connection; all data (including potentially sensitive information, like passwords) is transferred unencrypted!');
-$strSetupInsecureConnectionMsg2 = __('If your server is also configured to accept HTTPS requests follow [a@%s]this link[/a] to use a secure connection.');
-$strSetupInsertRows_desc = __('How many rows can be inserted at one time');
-$strSetupInsertRows_name = __('Number of inserted rows');
-$strSetupLeftDefaultTabTable_name = __('Target for quick access icon');
-$strSetupLeftDisplayLogo_desc = __('Show logo in left frame');
-$strSetupLeftDisplayLogo_name = __('Display logo');
-$strSetupLeftDisplayServers_desc = __('Display server choice at the top of the left frame');
-$strSetupLeftDisplayServers_name = __('Display servers selection');
-$strSetupLeftFrameDBSeparator_desc = __('String that separates databases into different tree levels');
-$strSetupLeftFrameDBSeparator_name = __('Database tree separator');
-$strSetupLeftFrameDBTree_desc = __('Only light version; display databases in a tree (determined by the separator defined below)');
-$strSetupLeftFrameDBTree_name = __('Display databases in a tree');
-$strSetupLeftFrameLight_desc = __('Disable this if you want to see all databases at once');
-$strSetupLeftFrameLight_name = __('Use light version');
-$strSetupLeftFrameTableLevel_name = __('Maximum table tree depth');
-$strSetupLeftFrameTableSeparator_desc = __('String that separates tables into different tree levels');
-$strSetupLeftFrameTableSeparator_name = __('Table tree separator');
-$strSetupLeftLogoLink_name = __('Logo link URL');
-$strSetupLeftLogoLinkWindow_desc = __('Open the linked page in the main window ([kbd]main[/kbd]) or in a new one ([kbd]new[/kbd])');
-$strSetupLeftLogoLinkWindow_name = __('Logo link target');
-$strSetupLeftPointerEnable_desc = __('Highlight server under the mouse cursor');
-$strSetupLeftPointerEnable_name = __('Enable highlighting');
-$strSetupLetUserChoose = __('let the user choose');
-$strSetupLightTabs_desc = __('Use less graphically intense tabs');
-$strSetupLightTabs_name = __('Light tabs');
-$strSetupLoad = __('Load');
-$strSetupLoginCookieDeleteAll_desc = __('If TRUE, logout deletes cookies for all servers; when set to FALSE, logout only occurs for the current server. Setting this to FALSE makes it easy to forget to log out from other servers when connected to multiple servers.');
-$strSetupLoginCookieDeleteAll_name = __('Delete all cookies on logout');
-$strSetupLoginCookieRecall_desc = __('Define whether the previous login should be recalled or not in cookie authentication mode');
-$strSetupLoginCookieRecall_name = __('Recall user name');
-$strSetupLoginCookieStore_desc = __('Defines how long (in seconds) a login cookie should be stored in browser. The default of 0 means that it will be kept for the existing session only, and will be deleted as soon as you close the browser window. This is recommended for non-trusted environments.');
-$strSetupLoginCookieStore_name = __('Login cookie store');
-$strSetupLoginCookieValidity_desc = __('Define how long (in seconds) a login cookie is valid');
-$strSetupLoginCookieValidityMsg = __('[a@?page=form&formset=features#tab_Security]Login cookie validity[/a] should be set to 1800 seconds (30 minutes) at most. Values larger than 1800 may pose a security risk such as impersonation.');
-$strSetupLoginCookieValidity_name = __('Login cookie validity');
-$strSetupMaxCharactersInDisplayedSQL_desc = __('Maximum number of characters used when a SQL query is displayed');
-$strSetupMaxCharactersInDisplayedSQL_name = __('Maximum displayed SQL length');
-$strSetupMaxDbList_desc = __('Maximum number of databases displayed in left frame and database list');
-$strSetupMaxDbList_name = __('Maximum databases');
-$strSetupMaxRows_desc = __('Number of rows displayed when browsing a result set. If the result set contains more rows, "Previous" and "Next" links will be shown.');
-$strSetupMaxRows_name = __('Maximum number of rows to display');
-$strSetupMaxTableList_desc = __('Maximum number of tables displayed in table list');
-$strSetupMaxTableList_name = __('Maximum tables');
-$strSetupMemoryLimit_desc = __('The number of bytes a script is allowed to allocate, eg. [kbd]32M[/kbd] ([kbd]0[/kbd] for no limit)');
-$strSetupMemoryLimit_name = __('Memory limit');
-$strSetupNavigationBarIconic_desc = __('Use only icons, only text or both');
-$strSetupNavigationBarIconic_name = __('Iconic navigation bar');
-$strSetupNewServer = __('New server');
-$strSetupNoServers = __('There are no configured servers');
-$strSetupOBGzip_desc = __('use GZip output buffering for increased speed in HTTP transfers');
-$strSetupOBGzip_name = __('GZip output buffering');
-$strSetupOptionNone = __('- none -');
-$strSetupOrder_desc = __('[kbd]SMART[/kbd] - i.e. descending order for columns of type TIME, DATE, DATETIME and TIMESTAMP, ascending order otherwise');
-$strSetupOrder_name = __('Default sorting order');
-$strSetupOverview = __('Overview');
-$strSetupPersistentConnections_desc = __('Use persistent connections to MySQL databases');
-$strSetupPersistentConnections_name = __('Persistent connections');
-$strSetupPropertiesIconic_desc = __('Use only icons, only text or both');
-$strSetupPropertiesIconic_name = __('Iconic table operations');
-$strSetupProtectBinary_desc = __('Disallow BLOB and BINARY columns from editing');
-$strSetupProtectBinary_name = __('Protect binary columns');
-$strSetupQueryHistoryDB_desc = __('Enable if you want DB-based query history (requires pmadb). If disabled, this utilizes JS-routines to display query history (lost by window close).');
-$strSetupQueryHistoryDB_name = __('Permanent query history');
-$strSetupQueryHistoryMax_desc = __('How many queries are kept in history');
-$strSetupQueryHistoryMax_name = __('Query history length');
-$strSetupQueryWindowDefTab_desc = __('Tab displayed when opening a new query window');
-$strSetupQueryWindowDefTab_name = __('Default query window tab');
-$strSetupRecodingEngine_desc = __('Select which functions will be used for character set conversion');
-$strSetupRecodingEngine_name = __('Recoding engine');
-$strSetupRestoreDefaultValue = __('Restore default value');
-$strSetupRevertErroneousFields = __('Try to revert erroneous fields to their default values');
-$strSetupSaveDir_desc = __('Directory where exports can be saved on server');
-$strSetupSaveDir_name = __('Save directory');
-$strSetupServerAuthConfigMsg = __('You set the [kbd]config[/kbd] authentication type and included username and password for auto-login, which is not a desirable option for live hosts. Anyone who knows or guesses your phpMyAdmin URL can directly access your phpMyAdmin panel. Set [a@?page=servers&mode=edit&id=%1$d#tab_Server]authentication type[/a] to [kbd]cookie[/kbd] or [kbd]http[/kbd].');
-$strSetupServerExtensionMsg = __('You should use mysqli for performance reasons');
-$strSetupServerNoPasswordMsg = __('You allow for connecting to the server without a password.');
-$strSetupServersAdd = __('Add a new server');
-$strSetupServers_AllowDeny_order_desc = __('Leave blank if not used');
-$strSetupServers_AllowDeny_order_name = __('Host authentication order');
-$strSetupServers_AllowDeny_rules_desc = __('Leave blank for defaults');
-$strSetupServers_AllowDeny_rules_name = __('Host authentication rules');
-$strSetupServers_AllowNoPassword_name = __('Allow logins without a password');
-$strSetupServers_AllowRoot_name = __('Allow root login');
-$strSetupServers_auth_http_realm_desc = __('HTTP Basic Auth Realm name to display when doing HTTP Auth');
-$strSetupServers_auth_http_realm_name = __('HTTP Realm');
-$strSetupServers_auth_swekey_config_desc = __('The path for the config file for [a at http://swekey.com]SweKey hardware authentication[/a] (not located in your document root; suggested: /etc/swekey.conf)');
-$strSetupServers_auth_swekey_config_name = __('SweKey config file');
-$strSetupServers_auth_type_desc = __('Authentication method to use');
-$strSetupServers_auth_type_name = __('Authentication type');
-$strSetupServers_bookmarktable_desc = __('Leave blank for no [a at http://wiki.phpmyadmin.net/pma/bookmark]bookmark[/a] support, suggested: [kbd]pma_bookmark[/kbd]');
-$strSetupServers_bookmarktable_name = __('Bookmark table');
-$strSetupServers_column_info_desc = __('Leave blank for no column comments/mime types, suggested: [kbd]pma_column_info[/kbd]');
-$strSetupServers_column_info_name = __('Column information table');
-$strSetupServers_compress_desc = __('Compress connection to MySQL server');
-$strSetupServers_compress_name = __('Compress connection');
-$strSetupServers_connect_type_desc = __('How to connect to server, keep [kbd]tcp[/kbd] if unsure');
-$strSetupServers_connect_type_name = __('Connection type');
-$strSetupServers_controlpass_name = __('Control user password');
-$strSetupServers_controluser_desc = __('A special MySQL user configured with limited permissions, more information available on [a at http://wiki.phpmyadmin.net/pma/controluser]wiki[/a]');
-$strSetupServers_controluser_name = __('Control user');
-$strSetupServers_CountTables_desc = __('Count tables when showing database list');
-$strSetupServers_CountTables_name = __('Count tables');
-$strSetupServers_designer_coords_desc = __('Leave blank for no Designer support, suggested: [kbd]pma_designer_coords[/kbd]');
-$strSetupServers_designer_coords_name = __('Designer table');
-$strSetupServers_DisableIS_desc = __('More information on [a at http://sf.net/support/tracker.php?aid=1849494]PMA bug tracker[/a] and [a at http://bugs.mysql.com/19588]MySQL Bugs[/a]');
-$strSetupServers_DisableIS_name = __('Disable use of INFORMATION_SCHEMA');
-$strSetupServerSecurityInfoMsg = __('If you feel this is necessary, use additional protection settings - [a@?page=servers&mode=edit&id=%1$d#tab_Server_config]host authentication[/a] settings and [a@?page=form&formset=features#tab_Security]trusted proxies list[/a]. However, IP-based protection may not be reliable if your IP belongs to an ISP where thousands of users, including you, are connected to.');
-$strSetupServersEdit = __('Edit server');
-$strSetupServers_extension_desc = __('What PHP extension to use; you should use mysqli if supported');
-$strSetupServers_extension_name = __('PHP extension to use');
-$strSetupServers_hide_db_desc = __('Hide databases matching regular expression (PCRE)');
-$strSetupServers_hide_db_name = __('Hide databases');
-$strSetupServers_history_desc = __('Leave blank for no SQL query history support, suggested: [kbd]pma_history[/kbd]');
-$strSetupServers_history_name = __('SQL query history table');
-$strSetupServers_tracking_desc = __('Leave blank for no SQL query tracking support, suggested: [kbd]pma_tracking[/kbd]');
-$strSetupServers_tracking_name = __('SQL query tracking table');
-$strSetupServers_host_desc = __('Hostname where MySQL server is running');
-$strSetupServers_host_name = __('Server hostname');
-$strSetupServers_LogoutURL_name = __('Logout URL');
-$strSetupServers_nopassword_desc = __('Try to connect without password');
-$strSetupServers_nopassword_name = __('Connect without password');
-$strSetupServers_only_db_desc = __('You can use MySQL wildcard characters (% and _), escape them if you want to use their literal instances, i.e. use \'my\_db\' and not \'my_db\'');
-$strSetupServers_only_db_name = __('Show only listed databases');
-$strSetupServers_password_desc = __('Leave empty if not using config auth');
-$strSetupServers_password_name = __('Password for config auth');
-$strSetupServers_pdf_pages_desc = __('Leave blank for no PDF schema support, suggested: [kbd]pma_pdf_pages[/kbd]');
-$strSetupServers_pdf_pages_name = __('PDF schema: pages table');
-$strSetupServers_pmadb_desc = __('Database used for relations, bookmarks, and PDF features. See [a at http://wiki.phpmyadmin.net/pma/pmadb]pmadb[/a] for complete information. Leave blank for no support. Suggested: [kbd]phpmyadmin[/kbd]');
-$strSetupServers_pmadb_name = __('PMA database');
-$strSetupServers_port_desc = __('Port on which MySQL server is listening, leave empty for default');
-$strSetupServers_port_name = __('Server port');
-$strSetupServers_relation_desc = __('Leave blank for no [a at http://wiki.phpmyadmin.net/pma/relation]relation-links[/a] support, suggested: [kbd]pma_relation[/kbd]');
-$strSetupServers_relation_name = __('Relation table');
-$strSetupServers_ShowDatabasesCommand_desc = __('SQL command to fetch available databases');
-$strSetupServers_ShowDatabasesCommand_name = __('SHOW DATABASES command');
-$strSetupServers_SignonSession_desc = __('See [a at http://wiki.phpmyadmin.net/pma/auth_types#signon]authentication types[/a] for an example');
-$strSetupServers_SignonSession_name = __('Signon session name');
-$strSetupServers_SignonURL_name = __('Signon URL');
-$strSetupServers_tracking_version_auto_create_desc = __('Whether the tracking mechanism creates versions for tables and views automatically.');
-$strSetupServers_tracking_version_auto_create_name = __('Automatically create versions');
-$strSetupServers_tracking_default_statements_desc = __('Defines the list of statements the auto-creation uses for new versions.');
-$strSetupServers_tracking_default_statements_name = __('Statements to track');
-$strSetupServers_tracking_add_drop_view_desc = __('Whether a DROP VIEW IF EXISTS statement will be added as first line to the log when creating a view.');
-$strSetupServers_tracking_add_drop_view_name = __('Add DROP VIEW');
-$strSetupServers_tracking_add_drop_table_desc = __('Whether a DROP TABLE IF EXISTS statement will be added as first line to the log when creating a table.');
-$strSetupServers_tracking_add_drop_table_name = __('Add DROP TABLE');
-$strSetupServers_tracking_add_drop_database_desc = __('Whether a DROP DATABASE IF EXISTS statement will be added as first line to the log when creating a database.');
-$strSetupServers_tracking_add_drop_database_name = __('Add DROP DATABASE');
-$strSetupServerSslMsg = __('You should use SSL connections if your web server supports it');
-$strSetupServers_socket_desc = __('Socket on which MySQL server is listening, leave empty for default');
-$strSetupServers_socket_name = __('Server socket');
-$strSetupServers_ssl_desc = __('Enable SSL for connection to MySQL server');
-$strSetupServers_ssl_name = __('Use SSL');
-$strSetupServers_table_coords_desc = __('Leave blank for no PDF schema support, suggested: [kbd]pma_table_coords[/kbd]');
-$strSetupServers_table_coords_name = __('PDF schema: table coordinates');
-$strSetupServers_table_info_desc = __('Table to describe the display columns, leave blank for no support; suggested: [kbd]pma_table_info[/kbd]');
-$strSetupServers_table_info_name = __('Display columns table');
-$strSetupServers_user_desc = __('Leave empty if not using config auth');
-$strSetupServers_user_name = __('User for config auth');
-$strSetupServers_verbose_check_desc = __('Disable if you know that your pma_* tables are up to date. This prevents compatibility checks and thereby increases performance');
-$strSetupServers_verbose_check_name = __('Verbose check');
-$strSetupServers_verbose_desc = __('A user-friendly description of this server. Leave blank to display the hostname instead.');
-$strSetupServers_verbose_name = __('Verbose name of this server');
-$strSetupSetValue = __('Set value: %s');
-$strSetupShowAll_desc = __('Whether a user should be displayed a "show all (rows)" button');
-$strSetupShowAll_name = __('Allow to display all the rows');
-$strSetupShowChgPassword_desc = __('Please note that enabling this has no effect with [kbd]config[/kbd] authentication mode because the password is hard coded in the configuration file; this does not limit the ability to execute the same command directly');
-$strSetupShowChgPassword_name = __('Show password change form');
-$strSetupShowCreateDb_name = __('Show create database form');
-$strSetupShowForm = __('Show form');
-$strSetupShowFunctionFields_desc = __('Display the function fields in edit/insert mode');
-$strSetupShowFunctionFields_name = __('Show function fields');
-$strSetupShowHiddenMessages = __('Show hidden messages (#MSG_COUNT)');
-$strSetupShowPhpInfo_desc = __('Shows link to [a at http://php.net/manual/function.phpinfo.php]phpinfo()[/a] output');
-$strSetupShowPhpInfo_name = __('Show phpinfo() link');
-$strSetupShowServerInfo_name = __('Show detailed MySQL server information');
-$strSetupShowSQL_desc = __('Defines whether SQL queries generated by phpMyAdmin should be displayed');
-$strSetupShowSQL_name = __('Show SQL queries');
-$strSetupShowStats_desc = __('Allow to display database and table statistics (eg. space usage)');
-$strSetupShowStats_name = __('Show statistics');
-$strSetupShowTooltipAliasDB_desc = __('If tooltips are enabled and a database comment is set, this will flip the comment and the real name');
-$strSetupShowTooltipAliasDB_name = __('Display database comment instead of its name');
-$strSetupShowTooltipAliasTB_desc = __('When setting this to [kbd]nested[/kbd], the alias of the table name is only used to split/nest the tables according to the $cfg[\'LeftFrameTableSeparator\'] directive, so only the folder is called like the alias, the table name itself stays unchanged');
-$strSetupShowTooltipAliasTB_name = __('Display table comment instead of its name');
-$strSetupShowTooltip_name = __('Display table comments in tooltips');
-$strSetupSkipLockedTables_desc = __('Mark used tables and make it possible to show databases with locked tables');
-$strSetupSkipLockedTables_name = __('Skip locked tables');
-$strSetupSQLQuery_Edit_name = __('Edit');
-$strSetupSQLQuery_Explain_name = __('Explain SQL');
-$strSetupSQLQuery_Refresh_name = __('Refresh');
-$strSetupSQLQuery_ShowAsPHP_name = __('Create PHP Code');
-$strSetupSQLQuery_Validate_name = __('Validate SQL');
-$strSetupSuggestDBName_desc = __('Suggest a database name on the "Create Database" form (if possible) or keep the text field empty');
-$strSetupSuggestDBName_name = __('Suggest new database name');
-$strSetupTrue = __('yes');
-$strSetupTrustedProxies_desc = __('Input proxies as [kbd]IP: trusted HTTP header[/kbd]. The following example specifies that phpMyAdmin should trust a HTTP_X_FORWARDED_FOR (X-Forwarded-For) header coming from the proxy 1.2.3.4:[br][kbd]1.2.3.4: HTTP_X_FORWARDED_FOR[/kbd]');
-$strSetupTrustedProxies_name = __('List of trusted proxies for IP allow/deny');
-$strSetupUploadDir_desc = __('Directory on server where you can upload files for import');
-$strSetupUploadDir_name = __('Upload directory');
-$strSetupUseDbSearch_desc = __('Allow for searching inside the entire database');
-$strSetupUseDbSearch_name = __('Use database search');
-$strSetupVerboseMultiSubmit_desc = __('Show affected rows of each statement on multiple-statement queries. See libraries/import.lib.php for defaults on how many queries a statement may contain.');
-$strSetupVerboseMultiSubmit_name = __('Verbose multiple statements');
-$strSetupVersionCheckDataError = __('Reading of version failed. Maybe you\'re offline or the upgrade server does not respond.');
-$strSetupVersionCheckInvalid = __('Got invalid version string from server');
-$strSetupVersionCheckLink = __('Check for latest version');
-$strSetupVersionCheckNewAvailable = __('A newer version of phpMyAdmin is available and you should consider upgrading. The newest version is %s, released on %s.');
-$strSetupVersionCheckNewAvailableSvn = __('You are using Git version, run [kbd]git pull[/kbd] :-)[br]The latest stable version is %s, released on %s.');
-$strSetupVersionCheckNone = __('No newer stable version is available');
-$strSetupVersionCheckUnparsable = __('Unparsable version string');
-$strSetupVersionCheck = __('Version check');
-$strSetupVersionCheckWrapperError = __('Neither URL wrapper nor CURL is available. Version check is not possible.');
-$strSetupWarning = __('Warning');
-$strSetupZipDump_desc = __('Enable [a at http://en.wikipedia.org/wiki/ZIP_(file_format)]ZIP[/a] compression for import and export operations');
-$strSetupZipDumpExportWarning = __('[a@?page=form&formset=features#tab_Import_export]Zip compression[/a] requires functions (%s) which are unavailable on this system.');
-$strSetupZipDumpImportWarning = __('[a@?page=form&formset=features#tab_Import_export]Zip decompression[/a] requires functions (%s) which are unavailable on this system.');
-$strSetupZipDump_name = __('ZIP');
-
-?>
diff --git a/setup/scripts.js b/setup/scripts.js
index 7298e63..f223e04 100644
--- a/setup/scripts.js
+++ b/setup/scripts.js
@@ -1,7 +1,5 @@
 /**
- * functions used in setup script
- * 
- * @version $Id$
+ * Functions used in Setup configuration forms
  */
 
 // show this window in top frame
@@ -9,163 +7,6 @@ if (top != self) {
     window.top.location.href = location;
 }
 
-// default values for fields
-var defaultValues = {};
-
-// language strings
-var PMA_messages = {};
-
-/**
- * Returns field type
- *
- * @param Element field
- */
-function getFieldType(field) {
-	field = $(field);
-    var tagName = field.attr('tagName');
-	if (tagName == 'INPUT') {
-        return field.attr('type');
-    } else if (tagName == 'SELECT') {
-        return 'select';
-    } else if (tagName == 'TEXTAREA') {
-        return 'text';
-    }
-    return '';
-}
-
-/**
- * Sets field value
- *
- * value must be of type:
- * o undefined (omitted) - restore default value (form default, not PMA default)
- * o String - if field_type is 'text'
- * o boolean - if field_type is 'checkbox'
- * o Array of values - if field_type is 'select'
- *
- * @param Element field
- * @param String  field_type  see getFieldType
- * @param mixed   value
- */
-function setFieldValue(field, field_type, value) {
-	field = $(field);
-    switch (field_type) {
-        case 'text':
-            field.attr('value', (value != undefined ? value : field.attr('defaultValue')));
-            break;
-        case 'checkbox':
-            field.attr('checked', (value != undefined ? value : field.attr('defaultChecked')));
-            break;
-        case 'select':
-            var options = field.attr('options');
-        	var i, imax = options.length;
-            if (value == undefined) {
-                for (i = 0; i < imax; i++) {
-                	options[i].selected = options[i].defaultSelected;
-                }
-            } else {
-                for (i = 0; i < imax; i++) {
-                	options[i].selected = (value.indexOf(options[i].value) != -1);
-                }
-            }
-            break;
-    }
-    markField(field);
-}
-
-/**
- * Gets field value
- *
- * Will return one of:
- * o String - if type is 'text'
- * o boolean - if type is 'checkbox'
- * o Array of values - if type is 'select'
- *
- * @param Element field
- * @param String  field_type  see getFieldType
- * @return mixed
- */
-function getFieldValue(field, field_type) {
-	field = $(field);
-    switch (field_type) {
-        case 'text':
-            return field.attr('value');
-        case 'checkbox':
-            return field.attr('checked');
-        case 'select':
-        	var options = field.attr('options');
-            var i, imax = options.length, items = [];
-            for (i = 0; i < imax; i++) {
-                if (options[i].selected) {
-                    items.push(options[i].value);
-                }
-            }
-            return items;
-    }
-}
-
-/**
- * Returns values for all fields in fieldsets
- */
-function getAllValues() {
-    var elements = $('fieldset input, fieldset select, fieldset textarea');
-    var values = {};
-    var type, value;
-    for (var i = 0; i < elements.length; i++) {
-        type = getFieldType(elements[i]);
-        value = getFieldValue(elements[i], type);
-        if (typeof value != 'undefined') {
-            // we only have single selects, fatten array
-            if (type == 'select') {
-                value = value[0];
-            }
-            values[elements[i].name] = value;
-        }
-    }
-    return values;
-}
-
-/**
- * Checks whether field has its default value
- *
- * @param Element field
- * @param String  type
- * @return boolean
- */
-function checkFieldDefault(field, type) {
-    field = $(field);
-    var field_id = field.attr('id');
-    if (typeof defaultValues[field_id] == 'undefined') {
-        return true;
-    }
-    var isDefault = true;
-    var currentValue = getFieldValue(field, type);
-    if (type != 'select') {
-        isDefault = currentValue == defaultValues[field_id];
-    } else {
-        // compare arrays, will work for our representation of select values
-        if (currentValue.length != defaultValues[field_id].length) {
-            isDefault = false;
-        }
-        else {
-            for (var i = 0; i < currentValue.length; i++) {
-                if (currentValue[i] != defaultValues[field_id][i]) {
-                    isDefault = false;
-                    break;
-                }
-            }
-        }
-    }
-    return isDefault;
-}
-
-/**
- * Returns element's id prefix
- * @param Element element
- */
-function getIdPrefix(element) {
-    return $(element).attr('id').replace(/[^-]+$/, '');
-}
-
 // ------------------------------------------------------------------
 // Messages
 //
@@ -200,49 +41,13 @@ $(function() {
 // Form validation and field operations
 //
 
-// form validator assignments
-var validate = {};
-
-// form validator list
-var validators = {
-    // regexp: numeric value
-    _regexp_numeric: new RegExp('^[0-9]*$'),
-    /**
-     * Validates positive number
-     *
-     * @param boolean isKeyUp
-     */
-    validate_positive_number: function (isKeyUp) {
-        var result = this.value != '0' && validators._regexp_numeric.test(this.value);
-        return result ? true : PMA_messages['error_nan_p'];
-    },
-    /**
-     * Validates non-negative number
-     *
-     * @param boolean isKeyUp
-     */
-    validate_non_negative_number: function (isKeyUp) {
-        var result = validators._regexp_numeric.test(this.value);
-        return result ? true : PMA_messages['error_nan_nneg'];
-    },
-    /**
-     * Validates port number
-     *
-     * @param boolean isKeyUp
-     */
-    validate_port_number: function(isKeyUp) {
-        var result = validators._regexp_numeric.test(this.value) && this.value != '0';
-        if (!result || this.value > 65536) {
-            result = PMA_messages['error_incorrect_port'];
-        }
-        return result;
-    },
+$.extend(true, validators, {
     // field validators
     _field: {
         /**
          * hide_db field
          *
-         * @param boolean isKeyUp
+         * @param {boolean} isKeyUp
          */
         hide_db: function(isKeyUp) {
             if (!isKeyUp && this.value != '') {
@@ -255,7 +60,7 @@ var validators = {
 		/**
          * TrustedProxies field
          *
-         * @param boolean isKeyUp
+         * @param {boolean} isKeyUp
          */
         TrustedProxies: function(isKeyUp) {
             if (!isKeyUp && this.value != '') {
@@ -271,7 +76,7 @@ var validators = {
         /**
          * Validates Server fieldset
          *
-         * @param boolean isKeyUp
+         * @param {boolean} isKeyUp
          */
         Server: function(isKeyUp) {
             if (!isKeyUp) {
@@ -282,7 +87,7 @@ var validators = {
         /**
          * Validates Server_login_options fieldset
          *
-         * @param boolean isKeyUp
+         * @param {boolean} isKeyUp
          */
         Server_login_options: function(isKeyUp) {
             return validators._fieldset.Server.apply(this, [isKeyUp]);
@@ -290,7 +95,7 @@ var validators = {
         /**
          * Validates Server_pmadb fieldset
          *
-         * @param boolean isKeyUp
+         * @param {boolean} isKeyUp
          */
         Server_pmadb: function(isKeyUp) {
             if (isKeyUp) {
@@ -306,14 +111,14 @@ var validators = {
             return true;
         }
     }
-};
+});
 
 /**
  * Calls server-side validation procedures
  *
- * @param Element parent  input field in <fieldset> or <fieldset>
- * @param String id       validator id
- * @param Object values   values hash (element_id: value)
+ * @param {Element} parent  input field in <fieldset> or <fieldset>
+ * @param {String}  id      validator id
+ * @param {Object}  values  values hash {element1_id: value, ...}
  */
 function ajaxValidate(parent, id, values) {
 	parent = $(parent);
@@ -324,7 +129,7 @@ function ajaxValidate(parent, id, values) {
             return false;
         }
     }
- 
+
     if (parent.data('ajax') != null) {
     	parent.data('ajax').abort();
     }
@@ -349,7 +154,7 @@ function ajaxValidate(parent, id, values) {
             } else if (typeof response['error'] != 'undefined') {
                 error[parent.id] = [response['error']];
             } else {
-                for (key in response) {
+                for (var key in response) {
                 	var value = response[key];
                     error[key] = jQuery.isArray(value) ? value : [value];
                 }
@@ -364,366 +169,27 @@ function ajaxValidate(parent, id, values) {
     return true;
 }
 
-/**
- * Registers validator for given field
- *
- * @param String  id       field id
- * @param String  type     validator (key in validators object)
- * @param boolean onKeyUp  whether fire on key up
- * @param mixed   params   validation function parameters
- */
-function validateField(id, type, onKeyUp, params) {
-    if (typeof validators[type] == 'undefined') {
-        return;
-    }
-    if (typeof validate[id] == 'undefined') {
-        validate[id] = [];
-    }
-    validate[id].push([type, params, onKeyUp]);
-}
-
-/**
- * Returns valdiation functions associated with form field
- *
- * @param  String  field_id     form field id
- * @param  boolean onKeyUpOnly  see validateField
- * @return Array  array of [function, paramseters to be passed to function]
- */
-function getFieldValidators(field_id, onKeyUpOnly) {
-    // look for field bound validator
-    var name = field_id.match(/[^-]+$/)[0];
-    if (typeof validators._field[name] != 'undefined') {
-        return [[validators._field[name], null]];
-    }
-
-    // look for registered validators
-    var functions = [];
-    if (typeof validate[field_id] != 'undefined') {
-        // validate[field_id]: array of [type, params, onKeyUp]
-        for (var i = 0, imax = validate[field_id].length; i < imax; i++) {
-            if (onKeyUpOnly && !validate[field_id][i][2]) {
-                continue;
-            }
-            functions.push([validators[validate[field_id][i][0]], validate[field_id][i][1]]);
-        }
-    }
-
-    return functions;
-}
-
-/**
- * Displays errors for given form fields
- *
- * WARNING: created DOM elements must be identical with the ones made by
- * display_input() in FormDisplay.tpl.php!
- *
- * @param Object  error list (key: field id, value: error array)
- */
-function displayErrors(error_list) {
-    for (field_id in error_list) {
-        var errors = error_list[field_id];
-        var field = $('#'+field_id);
-        var isFieldset = field.attr('tagName') == 'FIELDSET';
-        var errorCnt = isFieldset
-            ? field.find('dl.errors')
-            : field.siblings('.inline_errors');
-
-        // remove empty errors (used to clear error list)
-        errors = $.grep(errors, function(item) {
-            return item != '';
-        });
-
-        if (errors.length) {
-            // if error container doesn't exist, create it
-            if (errorCnt.length == 0) {
-                if (isFieldset) {
-                    errorCnt = $('<dl class="errors" />');
-                    field.find('table').before(errorCnt);
-                } else {
-                    errorCnt = $('<dl class="inline_errors" />');
-                    field.closest('td').append(errorCnt);
-                }
-            }
-
-            var html = '';
-            for (var i = 0, imax = errors.length; i < imax; i++) {
-                html += '<dd>' + errors[i] + '</dd>';
-            }
-            errorCnt.html(html);
-        } else if (errorCnt !== null) {
-            // remove useless error container
-            errorCnt.remove();
-        }
-    }
-}
-
-/**
- * Validates fieldset and puts errors in 'errors' object
- *
- * @param Element field
- * @param boolean isKeyUp
- * @param Object  errors
- */
-function validate_fieldset(fieldset, isKeyUp, errors) {
-	fieldset = $(fieldset);
-    if (fieldset.length && typeof validators._fieldset[fieldset.attr('id')] != 'undefined') {
-        var fieldset_errors = validators._fieldset[fieldset.attr('id')].apply(fieldset[0], [isKeyUp]);
-        for (field_id in fieldset_errors) {
-            if (typeof errors[field_id] == 'undefined') {
-                errors[field_id] = [];
-            }
-            if (typeof fieldset_errors[field_id] == 'string') {
-                fieldset_errors[field_id] = [fieldset_errors[field_id]];
-            }
-            $.merge(errors[field_id], fieldset_errors[field_id]);
-        }
-    }
-}
-
-/**
- * Validates form field and puts errors in 'errors' object
- *
- * @param Element field
- * @param boolean isKeyUp
- * @param Object  errors
- */
-function validate_field(field, isKeyUp, errors) {
-	field = $(field);
-	var field_id = field.attr('id');
-    errors[field_id] = [];
-    var functions = getFieldValidators(field_id, isKeyUp);
-    for (var i = 0; i < functions.length; i++) {
-        var result = functions[i][0].apply(field[0], [isKeyUp, functions[i][1]]);
-        if (result !== true) {
-            if (typeof result == 'string') {
-            	result = [result];
-            }
-            $.merge(errors[field_id], result);
-        }
-    }
-}
-
-/**
- * Validates form field and parent fieldset
- *
- * @param Element field
- * @param boolean isKeyUp
- */
-function validate_field_and_fieldset(field, isKeyUp) {
-	field = $(field);
-    var errors = {};
-    validate_field(field, isKeyUp, errors);
-    validate_fieldset(field.closest('fieldset'), isKeyUp, errors);
-    displayErrors(errors);
-}
-
-/**
- * Marks field depending on its value (system default or custom)
- *
- * @param Element field
- */
-function markField(field) {
-	field = $(field);
-    var type = getFieldType(field);
-    var isDefault = checkFieldDefault(field, type);
-
-    // checkboxes uses parent <span> for marking
-    var fieldMarker = (type == 'checkbox') ? field.parent() : field;
-    setRestoreDefaultBtn(field, !isDefault);
-    fieldMarker[isDefault ? 'removeClass' : 'addClass']('custom');
-}
-
-/**
- * Enables or disables the "restore default value" button
- *
- * @param Element field
- * @param bool    display
- */
-function setRestoreDefaultBtn(field, display) {
-    var el = $(field).closest('td').find('.restore-default');
-    el.css('display', (el.css('display') ? '' : 'none'));
-}
-
-$(function() {
-    // register validators and mark custom values
-	var elements = $('input[id], select[id], textarea[id]');
-    $('input[id], select[id], textarea[id]').each(function(){
-        markField(this);
-        var el = $(this);
-        el.bind('change', function() {
-            validate_field_and_fieldset(this, false);
-            markField(this);
-        });
-        var tagName = el.attr('tagName');
-        // text fields can be validated after each change
-        if (tagName == 'INPUT' && el.attr('type') == 'text') {
-        	el.keyup(function() {
-                validate_field_and_fieldset(el, true);
-                markField(el);
-            });
-        }
-        // disable textarea spellcheck
-        if (tagName == 'TEXTAREA') {
-        	el.attr('spellcheck', false);
-        }    	
-    });
-
-	// check whether we've refreshed a page and browser remembered modified
-	// form values
-	var check_page_refresh = $('#check_page_refresh');
-	if (check_page_refresh.length == 0 || check_page_refresh.val() == '1') {
-		// run all field validators
-		var errors = {};
-		for (var i = 0; i < elements.length; i++) {
-			validate_field(elements[i], false, errors);
-		}
-		// run all fieldset validators
-		$('fieldset').each(function(){
-			validate_fieldset(this, false, errors);
-		});
-		
-		displayErrors(errors);
-	} else if (check_page_refresh) {
-		check_page_refresh.val('1');
-	}
-});
-
 //
 // END: Form validation and field operations
 // ------------------------------------------------------------------
 
 // ------------------------------------------------------------------
-// Tabbed forms
-//
-
-/**
- * Sets active tab
- *
- * @param Element tab_link
- */
-function setTab(tab_link) {
-    var tabs_menu = $(tab_link).closest('.tabs');
-
-    var links = tabs_menu.find('a');
-    var contents, link;
-    for (var i = 0, imax = links.length; i < imax; i++) {
-    	link = $(links[i]);
-        contents = $(link.attr('href'));
-        if (links[i] == tab_link) {
-        	link.addClass('active');
-            contents.css('display', 'block');
-        } else {
-            link.removeClass('active');
-            contents.css('display', 'none');
-        }
-    }
-    location.hash = 'tab_' + $(tab_link).attr('href').substr(1);
-}
-
-$(function() {
-    var tabs = $('.tabs');
-    var url_tab = location.hash.match(/^#tab_.+/)
-        ? $('a[href$="' + location.hash.substr(5) + '"]') : null;
-    if (url_tab) {
-        url_tab = url_tab[0];
-    }
-    // add tabs events and activate one tab (the first one or indicated by location hash)
-    for (var i = 0, imax = tabs.length; i < imax; i++) {
-        var links = $(tabs[i]).find('a');
-        var selected_tab = links[0];
-        for (var j = 0, jmax = links.length; j < jmax; j++) {
-            $(links[j]).click(function(e) {
-                e.preventDefault();
-                setTab(this);
-            });
-            if (links[j] == url_tab) {
-                selected_tab = links[j];
-            }
-        }
-        setTab(selected_tab);
-    }
-    // tab links handling, check each 200ms
-    // (works with history in FF, further browser support here would be an overkill)
-    var prev_hash = location.hash;
-    setInterval(function() {
-        if (location.hash != prev_hash) {
-            prev_hash = location.hash;
-            var url_tab = location.hash.match(/^#tab_.+/)
-                ? $('a[href$="' + location.hash.substr(5) + '"]') : null;
-            if (url_tab) {
-                setTab(url_tab[0]);
-            }
-        }
-    }, 200);
-});
-
-//
-// END: Tabbed forms
-// ------------------------------------------------------------------
-
-// ------------------------------------------------------------------
-// Form reset buttons
+// User preferences allow/disallow UI
 //
 
 $(function() {
-    $('input[type=button]').click(function(e) {
-        var fields = $(this).closest('fieldset').find('input, select, textarea');
-        for (var i = 0, imax = fields.length; i < imax; i++) {
-            setFieldValue(fields[i], getFieldType(fields[i]));
-        }
-    });
+   $('.userprefs-allow').click(function(e) {
+       if (this != e.target) {
+           return;
+       }
+       var el = $(this).find('input');
+       if (el.attr('disabled')) {
+           return;
+       }
+       el.attr('checked', !el.attr('checked'));
+   });
 });
 
 //
-// END: Form reset buttons
-// ------------------------------------------------------------------
-
-// ------------------------------------------------------------------
-// "Restore default" and "set value" buttons
-//
-
-/**
- * Restores field's default value
- *
- * @param String field_id
- */
-function restoreField(field_id) {
-    var field = $('#'+field_id);
-    if (field.length == 0 || defaultValues[field_id] == undefined) {
-        return;
-    }
-    setFieldValue(field, getFieldType(field), defaultValues[field_id]);
-}
-
-$(function() {
-    $('.restore-default, .set-value').each(function() {
-        var link = $(this);
-        link.css('opacity', 0.25);
-        if (!link.hasClass('restore-default')) {
-            // restore-default is handled by markField
-        	link.css('display', '');
-        }
-        link.bind({
-            mouseenter: function() {$(this).css('opacity', 1);},
-            mouseleave: function() {$(this).css('opacity', 0.25);},
-            click: function(e) {
-                e.preventDefault();
-                var href = $(this).attr('href').substr(1);
-                var field_id;
-                if ($(this).hasClass('restore-default')) {
-                    field_id = href;
-                    restoreField(field_id);
-                } else {
-                    field_id = href.match(/^[^=]+/)[0];
-                    var value = href.match(/=(.+)$/)[1];
-                    setFieldValue($('#'+field_id), 'text', value);
-                }
-                $('#'+field_id).trigger('change');
-            }
-        });
-    });
-});
-
-//
-// END: "Restore default" and "set value" buttons
-// ------------------------------------------------------------------
+// END: User preferences allow/disallow UI
+// ------------------------------------------------------------------
\ No newline at end of file
diff --git a/setup/styles.css b/setup/styles.css
index d5a399d..0cadd10 100644
--- a/setup/styles.css
+++ b/setup/styles.css
@@ -195,6 +195,11 @@ ul.tabs li a:hover, ul.tabs li a:active {
     margin-bottom: -3px;
 }
 
+.userprefs-comment {
+    cursor: help;
+    float: right;
+}
+
 /* forms */
 
 fieldset {
@@ -253,10 +258,6 @@ fieldset th {
     vertical-align: top;
 }
 
-fieldset th small {
-    display: block;
-}
-
 fieldset .doc {
     margin-left: 1em;
 }
@@ -266,27 +267,50 @@ fieldset td {
     vertical-align: top;
 }
 
+fieldset td.userprefs-allow {
+    padding: 0;
+    vertical-align: middle;
+    text-align: center;
+    width: 3em;
+}
+
+fieldset td.userprefs-allow:hover {
+    cursor: pointer;
+    background-color: #EEE;
+}
+
 fieldset th small {
+    display: block;
     font-weight: normal;
     font-family: sans-serif;
     font-size: x-small;
     color: #666;
 }
 
-fieldset th, fieldset td {
+fieldset th, fieldset td, .form .lastrow {
     border-top: 1px #555 dotted;
 }
 
+fieldset .group-header th {
+    background: #EAEDFF;
+    border: none;
+}
+
+fieldset .group-header + tr th, fieldset .group-header + tr td,
+fieldset p + table tr:first-child td, fieldset p + table tr:first-child th {
+    border-top: none;
+}
+
+fieldset .group-field th {
+    padding-left: 1em;
+}
+
 fieldset .lastrow, .form .lastrow {
     background: #F7FBFF;
     padding: 0.5em;
     text-align: center;
 }
 
-.form .lastrow {
-    border-top: 1px #555 dotted;
-}
-
 fieldset .lastrow input, .form .lastrow input {
     font-weight: bold;
 }
@@ -314,16 +338,20 @@ fieldset.simple .lastrow {
 
 span.checkbox {
     padding: 2px;
+    display: inline-block;
 }
 
 .custom { /* customized field */
     background: #FFC;
 }
 
-span.checkbox.custom {
+.checkbox.custom {
     padding: 1px;
     border: 1px #EDEC90 solid;
-    background: #FFC;
+}
+
+.field-error {
+    border-color: #C11 !important;
 }
 
 input[type="text"], select, textarea {
@@ -335,6 +363,22 @@ input[type="text"]:focus, select:focus, textarea:focus {
     background: #F7FBFF;
 }
 
+.field-comment {
+
+    position: relative;
+}
+
+.field-comment-mark {
+    cursor: help;
+    padding: 0 0.2em;
+    font-weight: bold;
+    font-style: italic;
+}
+
+.field-comment-warning {
+    color: #A00;
+}
+
 .green { /* default form button */
     color: #080;
 }
diff --git a/setup/validate.php b/setup/validate.php
index 68781bc..beeba71 100644
--- a/setup/validate.php
+++ b/setup/validate.php
@@ -1,11 +1,9 @@
 <?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
 /**
  * Validation callback.
  *
- * @package    phpMyAdmin-setup
- * @copyright  Copyright (c) 2008, Piotr Przybylski <piotrprz at gmail.com>
- * @license    http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
- * @version    $Id$
+ * @package phpMyAdmin-setup
  */
 
 /**
@@ -14,7 +12,7 @@
 require './lib/common.inc.php';
 
 $validators = array();
-require './setup/lib/validate.lib.php';
+require './libraries/config/validate.lib.php';
 
 header('Content-type: application/json');
 
@@ -24,7 +22,7 @@ if (!($values instanceof stdClass)) {
     die('Wrong data');
 }
 $values = (array)$values;
-$result = validate($vids, $values, true);
+$result = PMA_config_validate($vids, $values, true);
 if ($result === false) {
     $result = 'Wrong data or no validation for ' . $vids;
 }
diff --git a/themes/darkblue_orange/css/theme_right.css.php b/themes/darkblue_orange/css/theme_right.css.php
index c15f796..73f1c37 100644
--- a/themes/darkblue_orange/css/theme_right.css.php
+++ b/themes/darkblue_orange/css/theme_right.css.php
@@ -647,48 +647,88 @@ form.login label {
 /* specific elements */
 
 /* topmenu */
-ul#topmenu {
+ul#topmenu, ul#topmenu2, ul.tabs {
     font-weight:        bold;
     list-style-type:    none;
     margin:             0;
     padding:            0;
 }
 
-ul#topmenu li {
+ul#topmenu2 {
+    margin:             0.25em 0.5em 0;
+    height:             2em;
+    clear:              both;
+}
+
+ul#topmenu li, ul#topmenu2 li {
     float:              <?php echo $left; ?>;
     margin:             0;
     padding:            0;
     vertical-align:     middle;
 }
 
-#topmenu img {
+#topmenu img, #topmenu2 img {
     vertical-align:     middle;
     margin-<?php echo $right; ?>:       0.1em;
 }
 
 /* default tab styles */
-.tab, .tabcaution, .tabactive {
+ul#topmenu a, ul#topmenu span {
     display:            block;
     margin:             0.2em 0.2em 0 0.2em;
     padding:            0.2em 0.2em 0 0.2em;
     white-space:        nowrap;
 }
 
+ul#topmenu ul a {
+    margin:             0;
+    padding-bottom:     0.2em;
+}
+
+ul#topmenu .submenu {
+    position:           relative;
+}
+
+ul#topmenu ul {
+    padding:            0;
+    margin:             0;
+    position:           absolute;
+    right:              0;
+    list-style-type:    none;
+    display:            none;
+    border:             1px #666 solid;
+}
+
+ul#topmenu li:hover ul, ul#topmenu .submenuhover ul {
+    display:            block;
+}
+
+ul#topmenu ul li {
+    width:              100%;
+}
+
+ul#topmenu2 a {
+    display:            block;
+    margin:             0.1em;
+    padding:            0.2em;
+    white-space:        nowrap;
+}
+
 /* disabled tabs */
-span.tab {
+ul#topmenu span.tab {
     color:              #666666;
 }
 
 /* disabled drop/empty tabs */
-span.tabcaution {
+ul#topmenu span.tabcaution {
     color:              #ff6666;
 }
 
 /* enabled drop/empty tabs */
-a.tabcaution {
+ul#topmenu a.tabcaution {
     color:              #FF0000;
 }
-a.tabcaution:hover {
+ul#topmenu a.tabcaution:hover {
     color: #FFFFFF;
     background-color:   #FF0000;
 }
@@ -702,52 +742,83 @@ fieldset.caution a:hover {
 
 <?php if ($GLOBALS['cfg']['LightTabs']) { ?>
 /* active tab */
-a.tabactive {
+ul#topmenu a.tabactive, ul#topmenu2 a.tabactive {
     color:              black;
 }
+
+ul#topmenu ul {
+    background:         <?php echo $GLOBALS['cfg']['MainBackground']; ?>;
+}
 <?php } else { ?>
 #topmenu {
     margin-top:         0.5em;
     padding:            0.1em 0.3em 0.1em 0.3em;
 }
 
-ul#topmenu li {
+ul#topmenu ul {
+    -moz-box-shadow:    2px 2px 3px #666;
+    -webkit-box-shadow: 2px 2px 3px #666;
+    box-shadow:         2px 2px 3px #666;
+}
+
+ul#topmenu > li {
     border-bottom:      1pt solid black;
 }
 
 /* default tab styles */
-.tab, .tabcaution, .tabactive {
+ul#topmenu a, ul#topmenu span {
     background-color:   <?php echo $GLOBALS['cfg']['BgOne']; ?>;
-    border:             1pt solid <?php echo $GLOBALS['cfg']['BgTwo']; ?>;
-    border-bottom:      0;
+    border:             0 solid <?php echo $GLOBALS['cfg']['BgTwo']; ?>;
+    border-width:       1pt 1pt 0 1pt;
     -moz-border-radius: 0.4em 0.4em 0 0;
     border-radius:      0.4em 0.4em 0 0;
 }
 
+ul#topmenu ul a {
+    border-width:       1pt 0 0 0;
+    -moz-border-radius: 0;
+    border-radius:      0;
+}
+
+ul#topmenu ul li:first-child a {
+    border-width:       0;
+}
+
 /* enabled hover/active tabs */
-a.tab:hover,
-a.tabcaution:hover,
-.tabactive,
-.tabactive:hover {
+ul#topmenu > li > a:hover,
+ul#topmenu > li > .tabactive {
     margin:             0;
     padding:            0.2em 0.4em 0.2em 0.4em;
     text-decoration:    none;
 }
 
-a.tab:hover,
-.tabactive {
+ul#topmenu ul a:hover,
+ul#topmenu ul .tabactive {
+    text-decoration:    none;
+}
+
+ul#topmenu a.tab:hover,
+ul#topmenu .tabactive {
     background-color:   <?php echo $GLOBALS['cfg']['MainBackground']; ?>;
 }
 
+ul#topmenu2 a.tab:hover,
+ul#topmenu2 a.tabactive {
+    background-color:   <?php echo $GLOBALS['cfg']['BgOne']; ?>;
+    -moz-border-radius: 0.3em;
+    border-radius:      0.3em;
+    text-decoration:    none;
+}
+
 /* to be able to cancel the bottom border, use <li class="active"> */
-ul#topmenu li.active {
+ul#topmenu > li.active {
      border-bottom:      1pt solid <?php echo $GLOBALS['cfg']['MainBackground']; ?>;
 }
 
 /* disabled drop/empty tabs */
-span.tab,
+ul#topmenu span.tab,
 a.warning,
-span.tabcaution {
+ul#topmenu span.tabcaution {
     cursor:             url(<?php echo $_SESSION['PMA_Theme']->getImgPath(); ?>error.ico), default;
 }
 <?php } ?>
@@ -1146,6 +1217,10 @@ li#li_switch_dbstats {
 li#li_flush_privileges {
     list-style-image: url(<?php echo $_SESSION['PMA_Theme']->getImgPath(); ?>s_reload.png);
 }
+
+li#li_user_preferences {
+    list-style-image: url(<?php echo $_SESSION['PMA_Theme']->getImgPath(); ?>b_tblops.png);
+}
 /* END iconic view for ul items */
 <?php } /* end if $GLOBALS['cfg']['MainPageIconic'] */ ?>
 
@@ -1270,6 +1345,12 @@ code.sql, div.sqlvalidate {
     margin-top:         0;
 }
 
+.group-cnt {
+    padding: 0 0 0 0.5em;
+    display: inline-block;
+    width: 98%;
+}
+
 /* for elements that should be revealed only via js */
 .hide {
     display:            none;
@@ -1496,4 +1577,211 @@ a.close_enum_editor {
 td.more_opts {
     display: none;
     white-space: nowrap;
-}
\ No newline at end of file
+}
+
+/* config forms */
+.config-form ul.tabs {
+    margin:      1.1em 0.2em 0;
+    padding:     0 0 0.3em 0;
+    list-style:  none;
+    font-weight: bold;
+}
+
+.config-form ul.tabs li {
+    float: <?php echo $left; ?>;
+}
+
+.config-form ul.tabs li a {
+    display:          block;
+    margin:           0.1em 0.2em 0;
+    padding:          0.1em 0.4em;
+    white-space:      nowrap;
+    text-decoration:  none;
+    border:           1px solid <?php echo $GLOBALS['cfg']['BgTwo']; ?>;
+    border-bottom:    none;
+}
+
+.config-form ul.tabs li a:hover,
+.config-form ul.tabs li a:active,
+.config-form ul.tabs li a.active {
+    margin:           0;
+    padding:          0.1em 0.6em 0.2em;
+}
+
+.config-form ul.tabs li a.active {
+    background-color: <?php echo $GLOBALS['cfg']['BgOne']; ?>;
+}
+
+.config-form fieldset {
+    margin-top:   0;
+    padding:      0;
+    clear:        both;
+    /*border-color: <?php echo $GLOBALS['cfg']['BgTwo']; ?>;*/
+}
+
+.config-form legend {
+    display: none;
+}
+
+.config-form fieldset p {
+    margin:  0;
+    padding: 0.5em;
+}
+
+.config-form fieldset .errors { /* form error list */
+    margin:       0 -2px 1em -2px;
+    padding:      0.5em 1.5em;
+    background:   #FBEAD9;
+    border:       0 #C83838 solid;
+    border-width: 1px 0;
+    list-style:   none;
+    font-family:  sans-serif;
+    font-size:    small;
+}
+
+.config-form fieldset .inline_errors { /* field error list */
+    margin:     0.3em 0.3em 0.3em 0;
+    padding:    0;
+    list-style: none;
+    color:      #9A0000;
+	font-size:  small;
+}
+
+.config-form fieldset th {
+    padding:        0.3em 0.3em 0.3em 0.5em;
+    text-align:     left;
+    vertical-align: top;
+    width:          40%;
+    background:     transparent;
+}
+
+.config-form fieldset .doc, .config-form fieldset .disabled-notice {
+    margin-left: 1em;
+}
+
+.config-form fieldset .disabled-notice {
+    font-size: 80%;
+    text-transform: uppercase;
+    color: #E00;
+    cursor: help;
+}
+
+.config-form fieldset td {
+    padding-top:    0.3em;
+    padding-bottom: 0.3em;
+    vertical-align: top;
+}
+
+.config-form fieldset th small {
+    display:     block;
+    font-weight: normal;
+    font-family: sans-serif;
+    font-size:   x-small;
+    color:       #444;
+}
+
+.config-form fieldset th, .config-form fieldset td {
+    border-top: 1px <?php echo $GLOBALS['cfg']['BgTwo']; ?> solid;
+}
+
+fieldset .group-header th {
+    background: <?php echo $GLOBALS['cfg']['BgTwo']; ?>;
+}
+
+fieldset .group-header + tr th {
+    padding-top: 0.6em;
+}
+
+fieldset .group-field th {
+    padding-left: 1.5em;
+}
+
+fieldset .disabled-field th,
+fieldset .disabled-field th small,
+fieldset .disabled-field td {
+    color: #777;
+    background-color: #eee;
+}
+
+.config-form .lastrow {
+    border-top: 1px #000 solid;
+}
+
+.config-form .lastrow {
+    background: <?php echo $GLOBALS['cfg']['ThBackground']; ?>;;
+    padding:    0.5em;
+    text-align: center;
+}
+
+.config-form .lastrow input {
+    font-weight: bold;
+}
+
+/* form elements */
+
+.config-form span.checkbox {
+    padding: 2px;
+    display: inline-block;
+}
+
+.config-form .custom { /* customized field */
+    background: #FFC;
+}
+
+.config-form span.checkbox.custom {
+    padding:    1px;
+    border:     1px #EDEC90 solid;
+    background: #FFC;
+}
+
+.config-form .field-error {
+    border-color: #A11 !important;
+}
+
+.config-form input[type="text"],
+.config-form select,
+.config-form textarea {
+    border: 1px #A7A6AA solid;
+    height: auto;
+}
+
+.config-form input[type="text"]:focus,
+.config-form select:focus,
+.config-form textarea:focus {
+    border:     1px #6676FF solid;
+    background: #F7FBFF;
+}
+
+.config-form .field-comment-mark {
+    font-family: serif;
+    color: #00A;
+    cursor: help;
+    padding: 0 0.2em;
+    font-weight: bold;
+    font-style: italic;
+}
+
+.config-form .field-comment-warning {
+    color: #A00;
+}
+
+/* error list */
+.config-form dd {
+    margin-left: 0.5em;
+}
+
+.config-form dd:before {
+    content: "\25B8  ";
+}
+
+.click-hide-message {
+    cursor: pointer;
+}
+
+.prefsmanage_opts {
+    margin-<?php echo $left; ?>: 2em;
+}
+
+#prefs_autoload {
+    margin-bottom: 0.5em;
+}
diff --git a/themes/darkblue_orange/img/b_more.png b/themes/darkblue_orange/img/b_more.png
new file mode 100644
index 0000000..161e0ff
Binary files /dev/null and b/themes/darkblue_orange/img/b_more.png differ
diff --git a/themes/original/css/theme_right.css.php b/themes/original/css/theme_right.css.php
index 13a1152..1d6da61 100644
--- a/themes/original/css/theme_right.css.php
+++ b/themes/original/css/theme_right.css.php
@@ -16,7 +16,7 @@ if (!defined('PMA_MINIMUM_COMMON')) {
 /* general tags */
 html {
     font-size: <?php echo (null !== $GLOBALS['PMA_Config']->get('fontsize') ? $GLOBALS['PMA_Config']->get('fontsize') : (
-        isset($_COOKIE['pma_fontsize']) ? $_COOKIE['pma_fontsize'] : '84%'));?>;
+        isset($_COOKIE['pma_fontsize']) ? $_COOKIE['pma_fontsize'] : '82%'));?>;
 }
 
 input, select, textarea {
@@ -59,7 +59,7 @@ a:visited,
 a:active {
     text-decoration:    none;
     color:              #0000FF;
-    cursor: pointer;
+    cursor:             pointer;
 }
 
 a:hover {
@@ -523,7 +523,6 @@ fieldset.confirmation legend {
         <?php } ?>
     <?php } ?>
 }
-
 /* end messageboxes */
 
 
@@ -625,48 +624,88 @@ form.login label {
 /* specific elements */
 
 /* topmenu */
-ul#topmenu {
+ul#topmenu, ul#topmenu2, ul.tabs {
     font-weight:        bold;
     list-style-type:    none;
     margin:             0;
     padding:            0;
 }
 
-ul#topmenu li {
+ul#topmenu2 {
+    margin: 0.25em 0.5em 0;
+    height: 2em;
+    clear: both;
+}
+
+ul#topmenu li, ul#topmenu2 li {
     float:              <?php echo $left; ?>;
     margin:             0;
     padding:            0;
     vertical-align:     middle;
 }
 
-#topmenu img {
+#topmenu img, #topmenu2 img {
     vertical-align:     middle;
     margin-<?php echo $right; ?>:       0.1em;
 }
 
 /* default tab styles */
-.tab, .tabcaution, .tabactive {
+ul#topmenu a, ul#topmenu span {
     display:            block;
     margin:             0.2em 0.2em 0 0.2em;
     padding:            0.2em 0.2em 0 0.2em;
     white-space:        nowrap;
 }
 
+ul#topmenu ul a {
+    margin:             0;
+    padding-bottom:     0.2em;
+}
+
+ul#topmenu .submenu {
+    position:           relative;
+}
+
+ul#topmenu ul {
+    margin:             0;
+    padding:            0;
+    position:           absolute;
+    right:              0;
+    list-style-type:    none;
+    display:            none;
+    border:             1px #666 solid;
+}
+
+ul#topmenu li:hover ul, ul#topmenu .submenuhover ul {
+    display:            block;
+}
+
+ul#topmenu ul li {
+    width:              100%;
+}
+
+ul#topmenu2 a {
+    display:            block;
+    margin:             0.1em;
+    padding:            0.2em;
+    white-space:        nowrap;
+}
+
 /* disabled tabs */
-span.tab {
+ul#topmenu span.tab {
     color:              #666666;
 }
 
 /* disabled drop/empty tabs */
-span.tabcaution {
+ul#topmenu span.tabcaution {
     color:              #ff6666;
 }
 
 /* enabled drop/empty tabs */
-a.tabcaution {
+ul#topmenu a.tabcaution {
     color:              #FF0000;
 }
-a.tabcaution:hover {
+ul#topmenu a.tabcaution:hover {
     color: #FFFFFF;
     background-color:   #FF0000;
 }
@@ -680,52 +719,83 @@ fieldset.caution a:hover {
 
 <?php if ($GLOBALS['cfg']['LightTabs']) { ?>
 /* active tab */
-a.tabactive {
+ul#topmenu a.tabactive, ul#topmenu2 a.tabactive {
     color:              black;
 }
+
+ul#topmenu ul {
+    background:         <?php echo $GLOBALS['cfg']['MainBackground']; ?>;
+}
 <?php } else { ?>
 #topmenu {
     margin-top:         0.5em;
     padding:            0.1em 0.3em 0.1em 0.3em;
 }
 
-ul#topmenu li {
+ul#topmenu ul {
+    -moz-box-shadow:    2px 2px 3px #666;
+    -webkit-box-shadow: 2px 2px 3px #666;
+    box-shadow:         2px 2px 3px #666;
+}
+
+ul#topmenu > li {
     border-bottom:      1pt solid black;
 }
 
 /* default tab styles */
-.tab, .tabcaution, .tabactive {
+ul#topmenu a, ul#topmenu span {
     background-color:   <?php echo $GLOBALS['cfg']['BgOne']; ?>;
-    border:             1pt solid <?php echo $GLOBALS['cfg']['BgTwo']; ?>;
-    border-bottom:      0;
+    border:             0 solid <?php echo $GLOBALS['cfg']['BgTwo']; ?>;
+    border-width:       1pt 1pt 0 1pt;
     -moz-border-radius: 0.4em 0.4em 0 0;
     border-radius:      0.4em 0.4em 0 0;
 }
 
+ul#topmenu ul a {
+    border-width:       1pt 0 0 0;
+    -moz-border-radius: 0;
+    border-radius:      0;
+}
+
+ul#topmenu ul li:first-child a {
+    border-width:       0;
+}
+
 /* enabled hover/active tabs */
-a.tab:hover,
-a.tabcaution:hover,
-.tabactive,
-.tabactive:hover {
+ul#topmenu > li > a:hover,
+ul#topmenu > li > .tabactive {
     margin:             0;
     padding:            0.2em 0.4em 0.2em 0.4em;
     text-decoration:    none;
 }
 
-a.tab:hover,
-.tabactive {
+ul#topmenu ul a:hover,
+ul#topmenu ul .tabactive {
+    text-decoration:    none;
+}
+
+ul#topmenu a.tab:hover,
+ul#topmenu .tabactive {
     background-color:   <?php echo $GLOBALS['cfg']['MainBackground']; ?>;
 }
 
+ul#topmenu2 a.tab:hover,
+ul#topmenu2 a.tabactive {
+    background-color:   <?php echo $GLOBALS['cfg']['BgOne']; ?>;
+    -moz-border-radius: 0.3em;
+    border-radius:      0.3em;
+    text-decoration:    none;
+}
+
 /* to be able to cancel the bottom border, use <li class="active"> */
-ul#topmenu li.active {
+ul#topmenu > li.active {
      border-bottom:      1pt solid <?php echo $GLOBALS['cfg']['MainBackground']; ?>;
 }
 
 /* disabled drop/empty tabs */
-span.tab,
+ul#topmenu span.tab,
 a.warning,
-span.tabcaution {
+ul#topmenu span.tabcaution {
     cursor:             url(<?php echo $_SESSION['PMA_Theme']->getImgPath(); ?>error.ico), default;
 }
 <?php } ?>
@@ -1097,6 +1167,10 @@ li#li_switch_dbstats {
 li#li_flush_privileges {
     list-style-image: url(<?php echo $_SESSION['PMA_Theme']->getImgPath(); ?>s_reload.png);
 }
+
+li#li_user_preferences {
+    list-style-image: url(<?php echo $_SESSION['PMA_Theme']->getImgPath(); ?>b_tblops.png);
+}
 /* END iconic view for ul items */
 <?php } /* end if $GLOBALS['cfg']['MainPageIconic'] */ ?>
 
@@ -1220,11 +1294,17 @@ code.sql, div.sqlvalidate {
 }
 
 .group h2 {
-    background:   <?php echo $GLOBALS['cfg']['ThBackground']; ?>;
+    background:         <?php echo $GLOBALS['cfg']['ThBackground']; ?>;
     padding:            0.1em 0.3em;
     margin-top:         0;
 }
 
+.group-cnt {
+    padding: 0 0 0 0.5em;
+    display: inline-block;
+    width: 98%;
+}
+
 /* for elements that should be revealed only via js */
 .hide {
     display:            none;
@@ -1423,8 +1503,6 @@ a.close_enum_editor {
     width: 100%;
 }
 
-#enum_editor input, #enum_editor_no_js input {
-    float: bottom;
 }
 
 #enum_editor_output {
@@ -1452,4 +1530,211 @@ iframe.IE_hack {
     display: none;
     border: 0;
     filter: alpha(opacity=0);
-}
\ No newline at end of file
+}
+
+/* config forms */
+.config-form ul.tabs {
+    margin:      1.1em 0.2em 0;
+    padding:     0 0 0.3em 0;
+    list-style:  none;
+    font-weight: bold;
+}
+
+.config-form ul.tabs li {
+    float: <?php echo $left; ?>;
+}
+
+.config-form ul.tabs li a {
+    display:          block;
+    margin:           0.1em 0.2em 0;
+    padding:          0.1em 0.4em;
+    white-space:      nowrap;
+    text-decoration:  none;
+    border:           1px solid <?php echo $GLOBALS['cfg']['BgTwo']; ?>;
+    border-bottom:    none;
+}
+
+.config-form ul.tabs li a:hover,
+.config-form ul.tabs li a:active,
+.config-form ul.tabs li a.active {
+    margin:           0;
+    padding:          0.1em 0.6em 0.2em;
+}
+
+.config-form ul.tabs li a.active {
+    background-color: <?php echo $GLOBALS['cfg']['BgOne']; ?>;
+}
+
+.config-form fieldset {
+    margin-top:   0;
+    padding:      0;
+    clear:        both;
+    /*border-color: <?php echo $GLOBALS['cfg']['BgTwo']; ?>;*/
+}
+
+.config-form legend {
+    display: none;
+}
+
+.config-form fieldset p {
+    margin:  0;
+    padding: 0.5em;
+}
+
+.config-form fieldset .errors { /* form error list */
+    margin:       0 -2px 1em -2px;
+    padding:      0.5em 1.5em;
+    background:   #FBEAD9;
+    border:       0 #C83838 solid;
+    border-width: 1px 0;
+    list-style:   none;
+    font-family:  sans-serif;
+    font-size:    small;
+}
+
+.config-form fieldset .inline_errors { /* field error list */
+    margin:     0.3em 0.3em 0.3em 0;
+    padding:    0;
+    list-style: none;
+    color:      #9A0000;
+	font-size:  small;
+}
+
+.config-form fieldset th {
+    padding:        0.3em 0.3em 0.3em 0.5em;
+    text-align:     left;
+    vertical-align: top;
+    width:          40%;
+    background:     transparent;
+}
+
+.config-form fieldset .doc, .config-form fieldset .disabled-notice {
+    margin-left: 1em;
+}
+
+.config-form fieldset .disabled-notice {
+    font-size: 80%;
+    text-transform: uppercase;
+    color: #E00;
+    cursor: help;
+}
+
+.config-form fieldset td {
+    padding-top:    0.3em;
+    padding-bottom: 0.3em;
+    vertical-align: top;
+}
+
+.config-form fieldset th small {
+    display:     block;
+    font-weight: normal;
+    font-family: sans-serif;
+    font-size:   x-small;
+    color:       #444;
+}
+
+.config-form fieldset th, .config-form fieldset td {
+    border-top: 1px <?php echo $GLOBALS['cfg']['BgTwo']; ?> solid;
+}
+
+fieldset .group-header th {
+    background: <?php echo $GLOBALS['cfg']['BgTwo']; ?>;
+}
+
+fieldset .group-header + tr th {
+    padding-top: 0.6em;
+}
+
+fieldset .group-field th {
+    padding-left: 1.5em;
+}
+
+fieldset .disabled-field th,
+fieldset .disabled-field th small,
+fieldset .disabled-field td {
+    color: #666;
+    background-color: #ddd;
+}
+
+.config-form .lastrow {
+    border-top: 1px #000 solid;
+}
+
+.config-form .lastrow {
+    background: <?php echo $GLOBALS['cfg']['ThBackground']; ?>;;
+    padding:    0.5em;
+    text-align: center;
+}
+
+.config-form .lastrow input {
+    font-weight: bold;
+}
+
+/* form elements */
+
+.config-form span.checkbox {
+    padding: 2px;
+    display: inline-block;
+}
+
+.config-form .custom { /* customized field */
+    background: #FFC;
+}
+
+.config-form span.checkbox.custom {
+    padding:    1px;
+    border:     1px #EDEC90 solid;
+    background: #FFC;
+}
+
+.config-form .field-error {
+    border-color: #A11 !important;
+}
+
+.config-form input[type="text"],
+.config-form select,
+.config-form textarea {
+    border: 1px #A7A6AA solid;
+    height: auto;
+}
+
+.config-form input[type="text"]:focus,
+.config-form select:focus,
+.config-form textarea:focus {
+    border:     1px #6676FF solid;
+    background: #F7FBFF;
+}
+
+.config-form .field-comment-mark {
+    font-family: serif;
+    color: #007;
+    cursor: help;
+    padding: 0 0.2em;
+    font-weight: bold;
+    font-style: italic;
+}
+
+.config-form .field-comment-warning {
+    color: #A00;
+}
+
+/* error list */
+.config-form dd {
+    margin-left: 0.5em;
+}
+
+.config-form dd:before {
+    content: "\25B8  ";
+}
+
+.click-hide-message {
+    cursor: pointer;
+}
+
+.prefsmanage_opts {
+    margin-<?php echo $left; ?>: 2em;
+}
+
+#prefs_autoload {
+    margin-bottom: 0.5em;
+}
diff --git a/themes/original/img/b_more.png b/themes/original/img/b_more.png
new file mode 100644
index 0000000..4a12e8c
Binary files /dev/null and b/themes/original/img/b_more.png differ


hooks/post-receive
-- 
phpMyAdmin




More information about the Git mailing list