[Phpmyadmin-git] [SCM] phpMyAdmin branch, master, updated. RELEASE_3_4_3_2-15589-g79b5bd6

Madhura Jayaratne madhuracj at users.sourceforge.net
Wed Aug 17 15:56:02 CEST 2011


The branch, master has been updated
       via  79b5bd602e50cc5eff4c32c85df673f7eac94862 (commit)
       via  d501fc1fe6f1f449ddadb13dacf505a841e7ec85 (commit)
       via  0387ea0b40ad47dea5fad3c2b432452b31605dd1 (commit)
       via  46722b80359c81626bdbc429329b1bc710db3530 (commit)
       via  5e11e88a147e16c96c33547e199dca31d1a20c77 (commit)
       via  5744b9622d0bc76250e20127fd4a0329919f4af9 (commit)
       via  7d7dd02e8cd2048f3e11585da86892bf7c4a6dea (commit)
       via  16a039392b4a8ea028b38f969ef7e4e586532b94 (commit)
       via  9ed1cd7c3ef2eb5cb9b3511aec280f89937b3cd0 (commit)
       via  d6bf1cd451be99703fe428fb90747ef71b625a3e (commit)
       via  cb176b2648f0d787d115290212ab829372414a16 (commit)
       via  005a4ce61b0f5818f8bcba83f8eda7a3192301f3 (commit)
       via  bedd7087f369567288ccdbb0898ed4dec90666e3 (commit)
       via  cb0eca28e4014555c219b290e47a282474281e94 (commit)
       via  414ac18e624fafb84cd82f89eb8ae628f6e93957 (commit)
       via  333dc9ccec0e6f16ea7dbf65acdd9549311d169b (commit)
       via  f60672d0d3f8864a67ca92c7f5044b74073fe430 (commit)
       via  760d895036176c2d2ca60d63150ce9b5a44379cd (commit)
       via  68d617ad17d60851d69c50d58d728702f8cd6cff (commit)
       via  591be45324f3e67c281c2e36d8624daf741bca0e (commit)
       via  881d2f29b7d3021be171964fa735ac634921c400 (commit)
       via  81667ad578c52a47071394bb4baba5e51be7ac0d (commit)
       via  7f94f8ea738d727389f63bd99d33b4e6f4130220 (commit)
       via  ca0bf0be2763b2659fb44391f329a8cb80256b3e (commit)
       via  b67c913fadc71fec51d139d96cf5afe98656db1f (commit)
       via  84f2882bbf19dd8f1eec3b81a29a3eecb63b2af2 (commit)
       via  fa3e058e251d72a758629248a7ced02b89b3d62a (commit)
       via  0e8492769354e5b5e2187d4fcda73f174c8f0417 (commit)
       via  9c316b7b1158b9207c8a87d04ddbedebac1a42dc (commit)
       via  acb6656961eb5191e7e3f8cd3ea09638f5d5f3ec (commit)
       via  a1f2d5311ad9c47092e4b95f28125bc2a7bfdaa3 (commit)
       via  2f6a53f50d979aca1c06891e8774e5952d4e0d80 (commit)
       via  2b749e30c562c76441589e7123b8dbb4e520f47a (commit)
       via  218a2b561c7b242e4a10c11b7da7dbac4bcdadfe (commit)
       via  1a16ba7caecf157d7ac976acdd8df16bff698c10 (commit)
       via  2923f1cdb58d07ddc99146e85e0d91d8f98a45eb (commit)
       via  981cfeac2ede69205da710ac38714938bcb85239 (commit)
       via  e2d535cc56d05d9ff0ffa9716f6580ef1a4fadf3 (commit)
       via  3da9f02130a4f7fa951f72d0667a4e543f76b683 (commit)
       via  175a6e094801ff0a4097eaeeeda665ab8f35e212 (commit)
       via  7fe1ce201fc793c09b5833a4933c0b0bf81348a0 (commit)
       via  ba99e8fe12e3a13c839f9bb488ad1ade636bed4e (commit)
       via  dc823602428de00f987425ccdbbb903044572551 (commit)
       via  3611d48325f6e2990a5d29060503237f83d52257 (commit)
       via  36c55adb9ebc4b341bc52e3ad839b9909365fa78 (commit)
       via  304a5d666b1f52695851df6a9d2ead74e3f8f9c1 (commit)
       via  fe10dec01f77a40afab3a0c97d03ee9d458d7501 (commit)
       via  f00b473c17bce475816f0be84b48f572f404fbb5 (commit)
       via  e62c03f7a5b153ec7524157a7ec8878f46ce0162 (commit)
       via  7a955d4c66a0690d66f312aca1460d6f7d3da9b0 (commit)
       via  d3bd2d5d91c25c77a192041216898d17059df401 (commit)
       via  3efcd0e24bd9a096611ae94d2c35bc2b5f48455a (commit)
       via  ed5c01dc440f28486a3f6db546d5faf7d7e41165 (commit)
       via  5ccc1dec16ec46422544c984f4b884ae25fef066 (commit)
       via  516557716a37836df650387bfbc0034031476c24 (commit)
       via  0a80147c4623dff9420cda8ef7e26a0f279566c4 (commit)
       via  6ae969a5ee3d2e30ccf3d95aefa7f641a3ccd2db (commit)
       via  6c6e43b78a43e323de38331e6f0e7668851e59fe (commit)
       via  c53750eac09bbff5388613d97297b1cdece2e99f (commit)
       via  db1f83b55b151c100a3aa9a81f7856432f730386 (commit)
       via  c73380be3509626fbdb7b5027b7d80abb16f2588 (commit)
       via  c3189393448f80543ecdb6c94c8c533f204cb0ad (commit)
       via  e456f221494e1ccf76d5b8f73ca5e6896feec113 (commit)
       via  47a8dcfc8885a0086fc8c8b9b5a49e783d81180a (commit)
       via  aed7270cb99b80ccc7abe970a566e6241ccec159 (commit)
       via  01976f1663f7d36d18f65574276f7250b506ef94 (commit)
       via  003496969e3a5ab8a04e939c945f42c90dfe7f49 (commit)
       via  b48a250ca8ceb4ab07caa502f05772b9d02acb25 (commit)
       via  ec7feea9b04d173f2468d7fa3294be23b1965427 (commit)
       via  11ca5daa412c0338d63020f94f74530e95463ce9 (commit)
       via  1f2ba4e9cc51c2bf2b1c1b96f78f29143e033e36 (commit)
       via  47fdfad3361fc5840776060c2326505de1512ee3 (commit)
       via  6f35aaa8e46e1bc50b4b5e38d4b9c4810c5c71ce (commit)
       via  47762d7b14815296256dea277647f152c1c5c2fc (commit)
       via  015ad8968008284f565ecd1274f37ddcd89ca06e (commit)
       via  4d7b7d9a88012563463df82b904a6859400de7d9 (commit)
       via  0e4435266b588de8788b01bb92bf8261c3762ab5 (commit)
       via  2a402a3103c5a12e6c9d2fd2515d7695da2942ff (commit)
       via  5a6379f93e97a4535a3a78b56ddc6a5cbe3901e8 (commit)
       via  96785858bc79297b34b06722fc833bb033aa10c4 (commit)
       via  d85c777c78a854d56d39cb6420624e22eedc6586 (commit)
       via  1b9ddd2efa71971ef1b78356cc878af437cdf5dd (commit)
       via  ba93a625b9de49fc10c1d65a880768258497459c (commit)
       via  7af88c04c75641fc3aba7e26935c0ef8f9e2dcbe (commit)
       via  ed23518a44fdd62c5394c785e515d65f7c4910eb (commit)
       via  ffb970f169f6e9642fd9fe924cca88f8c14695d2 (commit)
       via  83d8d3a8ed3043f52b1f1ef42af33fccfead1e87 (commit)
       via  b2d703dbea2077c9ff48686ee230d7a7ff224318 (commit)
       via  166b571964d6c3513359512b8eef83584f2f9ddf (commit)
       via  56090dd46f34e485199541d1262dc70c85001ede (commit)
       via  f5bd53fae03e41c2b26f3769ce891270d00d39e9 (commit)
       via  c18ef53b57ba72a6b35e479b3510d855cc636aa7 (commit)
       via  bb987837ebf198e60503231bbf7cc9a50eea3337 (commit)
       via  6e7c3adbc15eb1f4b822a083b954cbc39a02bc13 (commit)
       via  0c9301f7dbc88ee49021f708d9004e0b57975fd8 (commit)
       via  fd0cb076c0c415c321edf8e811c9691d6f2ca06f (commit)
       via  4ee9d4834639659f73635825f367c842fcd0e090 (commit)
       via  c97bb579250bdafa23e60386facf3f12034d287b (commit)
       via  b1634f80fd598d67130b7fccd29f7bc8dbc726b4 (commit)
       via  ac4f0a10b0593b20cb49116df0170912ab292e69 (commit)
       via  66f73b4114bf8e60496fe052ec86b33c65c3137e (commit)
       via  e0e0dea09b25da67f60d787b0c2312dbbc5a7660 (commit)
       via  1d9ef026089b7b52061f4558ddaaed10d500df60 (commit)
       via  a1e6b187c60999d1934ed5f7428c95f0a5d3820d (commit)
       via  f76785603f311153f7217ec45575c98440b07381 (commit)
       via  2bf70868bbd9c69036470b4a9cbfe2fe29e1a8fc (commit)
       via  242534a78ad3d26334cd97dcf8346c7cd327179b (commit)
       via  be8ce3d5b61a069ab2dc4caf2206db1af67cd15c (commit)
       via  e7135574bd2acefa90c7b2e654d2344d3027e479 (commit)
       via  b9e5125870e8d6575f679d59d46e1fddec2f9e0c (commit)
       via  c821997a5a69e8f37ce8b802211774b33a479103 (commit)
       via  3ca86a3929e201898e692ab3608d0dcf1a8a4bf2 (commit)
       via  4e8cc7dc97871ba757517d0791488d57abee71a1 (commit)
       via  6f3cf75e317dda6dc4a41a5b0c1227962edd30e0 (commit)
       via  2795a9061ca0a2c4f344303b686c64dbbc7032cd (commit)
       via  c81db372d79bf96acc8a4a2cdb2fe7f0430b57e4 (commit)
       via  faced3027aa337a629f69a3e6b67410ad9f07df3 (commit)
       via  a58bb10e1839d0740cb634112f36462d52d4ac6f (commit)
       via  28519cf25befaba56aa677d38af2847c2a7febcb (commit)
       via  6f4db19f53370d1e220ba396408dc6e03e0061d9 (commit)
       via  c6a8098239bac87d105525173e14cf1d1cbc0afa (commit)
       via  5a1018fc43c63c12c8ba8787e83ce4d48f91ff6e (commit)
       via  4d111205b1dfb1ef220b052f8ba96b8b1c47af0d (commit)
       via  93ab68dd131616369dccd0a6a62ff5f1a1a710d2 (commit)
       via  cfeb031d1f8d7c31cb3fdf6b376ba7b7ea757a59 (commit)
       via  ae88c2e758de107313e8a8cfaa192c42984a9fb8 (commit)
       via  c4faafdc792abb3b2bef62b70ab7f32fd85aa143 (commit)
       via  1bc0473fe2b2c5fe24ccb2a1541b70e584009265 (commit)
       via  b8ddd56d78598c497e4b4b0b1ffa27ed0550ebc8 (commit)
       via  67ef96d1f6d6bbf6b7d906a02c4c79898a11ee66 (commit)
       via  52501828f77f16baac93b16f706c6262ed55a926 (commit)
       via  ff3efd4b7d3ac7b00117d7ef78f239972e3f9d50 (commit)
       via  5ac3f567c454764152631c26a9dafec7bf7eef0a (commit)
       via  da6fe46a4d34c650e3d7f0b70d04ea22730f8e19 (commit)
       via  d257d46dee97fb57173642fafe26a9f8b7f5b10c (commit)
       via  63900d009441d8e81714ea56337d5b736806fca1 (commit)
      from  c04a557c02c590eb141661780f731540d46ba74c (commit)


- Log -----------------------------------------------------------------
commit 79b5bd602e50cc5eff4c32c85df673f7eac94862
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Aug 17 19:14:43 2011 +0530

    Changelog entries for GIS features

commit d501fc1fe6f1f449ddadb13dacf505a841e7ec85
Merge: c04a557 0387ea0
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Aug 17 18:02:25 2011 +0530

    Merge branch 'OpenGIS'

commit 0387ea0b40ad47dea5fad3c2b432452b31605dd1
Merge: 46722b8 aca93f4
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Aug 17 16:48:50 2011 +0530

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

commit 46722b80359c81626bdbc429329b1bc710db3530
Merge: 5e11e88 576e76d
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Aug 17 16:43:18 2011 +0530

    Merge branch 'master' into OpenGIS

commit 5e11e88a147e16c96c33547e199dca31d1a20c77
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Aug 13 17:31:38 2011 +0530

    Mention the use of TempDir for ESRI Shapefile imports

commit 5744b9622d0bc76250e20127fd4a0329919f4af9
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Aug 13 17:24:39 2011 +0530

    Documentation about importing ESRI Shapefiles

commit 7d7dd02e8cd2048f3e11585da86892bf7c4a6dea
Merge: 16a0393 9147f30
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Aug 13 14:12:46 2011 +0530

    Merge branch 'master' into OpenGIS
    
    Conflicts:
    	tbl_select.php

commit 16a039392b4a8ea028b38f969ef7e4e586532b94
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Aug 13 10:11:08 2011 +0530

    Remove tab characters

commit 9ed1cd7c3ef2eb5cb9b3511aec280f89937b3cd0
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Aug 13 10:10:32 2011 +0530

    Use abstract test class to avoid code duplications in tests

commit d6bf1cd451be99703fe428fb90747ef71b625a3e
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Aug 13 10:02:39 2011 +0530

    Adhere to coding style

commit cb176b2648f0d787d115290212ab829372414a16
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Aug 13 00:17:36 2011 +0530

    Unit tests for PMA_GIS_Factory class

commit 005a4ce61b0f5818f8bcba83f8eda7a3192301f3
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Aug 12 15:09:03 2011 +0530

    Unit test for PMA_GIS_modifyQuery

commit bedd7087f369567288ccdbb0898ed4dec90666e3
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Aug 12 14:03:40 2011 +0530

    Wrap long lines

commit cb0eca28e4014555c219b290e47a282474281e94
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Aug 12 13:50:28 2011 +0530

    Rename functions to match PEAR coding style

commit 414ac18e624fafb84cd82f89eb8ae628f6e93957
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Aug 12 13:32:43 2011 +0530

    Remove redundant parameter

commit 333dc9ccec0e6f16ea7dbf65acdd9549311d169b
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Aug 12 11:59:22 2011 +0530

    Unit tests for PMA_GIS_Multipolygon class

commit f60672d0d3f8864a67ca92c7f5044b74073fe430
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Aug 12 11:22:57 2011 +0530

    More tests for PMA_GIS_Polygon class

commit 760d895036176c2d2ca60d63150ce9b5a44379cd
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Aug 12 08:30:14 2011 +0530

    Unit tests for PMA_GIS_Polygon class

commit 68d617ad17d60851d69c50d58d728702f8cd6cff
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Aug 12 07:03:24 2011 +0530

    Unit tests for PMA_GIS_Multilinestring class

commit 591be45324f3e67c281c2e36d8624daf741bca0e
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Aug 11 22:40:55 2011 +0530

    Unit tests for PMA_GIS_Linestring class

commit 881d2f29b7d3021be171964fa735ac634921c400
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Aug 11 22:01:24 2011 +0530

    Tests for PMA_GIS_Multipoint class

commit 81667ad578c52a47071394bb4baba5e51be7ac0d
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Aug 11 21:45:24 2011 +0530

    Unit tests for PMA_GIS_Point class

commit 7f94f8ea738d727389f63bd99d33b4e6f4130220
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Aug 11 21:21:19 2011 +0530

    Wrap long lines

commit ca0bf0be2763b2659fb44391f329a8cb80256b3e
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Aug 11 21:20:24 2011 +0530

    Fix coding style

commit b67c913fadc71fec51d139d96cf5afe98656db1f
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Aug 10 00:23:43 2011 +0530

    Avoid undefined variable notice.

commit 84f2882bbf19dd8f1eec3b81a29a3eecb63b2af2
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Aug 10 00:09:42 2011 +0530

    Added missing question mark in the URL

commit fa3e058e251d72a758629248a7ced02b89b3d62a
Merge: 0e84927 630cdd9
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Tue Aug 9 06:16:12 2011 +0530

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

commit 0e8492769354e5b5e2187d4fcda73f174c8f0417
Merge: 9c316b7 c00b1e5
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Mon Aug 8 07:45:53 2011 +0530

    Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into OpenGIS
    
    Conflicts:
    	libraries/common.lib.php

commit 9c316b7b1158b9207c8a87d04ddbedebac1a42dc
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Aug 7 07:11:38 2011 +0530

    Reduce font size. Remove black from the color list

commit acb6656961eb5191e7e3f8cd3ea09638f5d5f3ec
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Aug 6 10:59:06 2011 +0530

    Labels for each part in the geometry is not a good idea

commit a1f2d5311ad9c47092e4b95f28125bc2a7bfdaa3
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Aug 6 10:35:15 2011 +0530

    Abstract function definition to the PMA_GIS_Geometry class

commit 2f6a53f50d979aca1c06891e8774e5952d4e0d80
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Aug 6 10:18:21 2011 +0530

    Labels for polygons and multipolygons

commit 2b749e30c562c76441589e7123b8dbb4e520f47a
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Aug 6 10:03:23 2011 +0530

    Should verify that the point is not empty first

commit 218a2b561c7b242e4a10c11b7da7dbac4bcdadfe
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Aug 5 05:55:51 2011 +0530

    Labels for linestrings and multilinestring exported to PNG and PDF

commit 1a16ba7caecf157d7ac976acdd8df16bff698c10
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Aug 5 05:29:29 2011 +0530

    Labels for points and multipoint exported to PDF

commit 2923f1cdb58d07ddc99146e85e0d91d8f98a45eb
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Aug 5 05:05:22 2011 +0530

    Labels for multipoints exported to PNG

commit 981cfeac2ede69205da710ac38714938bcb85239
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Aug 5 05:01:08 2011 +0530

    Labels for exporting points as PNG

commit e2d535cc56d05d9ff0ffa9716f6580ef1a4fadf3
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Aug 4 09:39:58 2011 +0530

    Use $cfg['PDFDefaultPageSize'] when exporting to PDF

commit 3da9f02130a4f7fa951f72d0667a4e543f76b683
Merge: 175a6e0 54fbcaa
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Aug 3 18:17:57 2011 +0530

    Merge branch 'master' into OpenGIS

commit 175a6e094801ff0a4097eaeeeda665ab8f35e212
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Aug 3 18:11:32 2011 +0530

    Use hexadecimal form to create a unique condition for geometry fields

commit 7fe1ce201fc793c09b5833a4933c0b0bf81348a0
Merge: ba99e8f 663d073
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Aug 3 00:53:53 2011 +0530

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

commit ba99e8fe12e3a13c839f9bb488ad1ade636bed4e
Merge: dc82360 19172fb
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Tue Aug 2 00:34:27 2011 +0530

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

commit dc823602428de00f987425ccdbbb903044572551
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Tue Aug 2 00:32:32 2011 +0530

    Prepares and insert GIS data to the input field on pressing 'enter'

commit 3611d48325f6e2990a5d29060503237f83d52257
Merge: 36c55ad 15a384a
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Mon Aug 1 09:40:36 2011 +0530

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

commit 36c55adb9ebc4b341bc52e3ad839b9909365fa78
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Mon Aug 1 09:36:29 2011 +0530

    Disabling causes problems as value is not passed. Use readonly.

commit 304a5d666b1f52695851df6a9d2ead74e3f8f9c1
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Mon Aug 1 00:25:02 2011 +0530

    Avoid undefined variables

commit fe10dec01f77a40afab3a0c97d03ee9d458d7501
Merge: f00b473 1917807
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 23:25:33 2011 +0530

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

commit f00b473c17bce475816f0be84b48f572f404fbb5
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 23:14:43 2011 +0530

    Accept WKTs without SRID

commit e62c03f7a5b153ec7524157a7ec8878f46ce0162
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 22:28:02 2011 +0530

    Avoid undefined index

commit 7a955d4c66a0690d66f312aca1460d6f7d3da9b0
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 21:55:21 2011 +0530

    GIS data editor to insert geometry type parameters

commit d3bd2d5d91c25c77a192041216898d17059df401
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 18:33:02 2011 +0530

    Refractor common code to gis_data_editor.js. Remove hidden input to track null checkbox.

commit 3efcd0e24bd9a096611ae94d2c35bc2b5f48455a
Merge: 6c6e43b ed5c01d
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 16:24:20 2011 +0530

    Merge branch 'master' of ssh://repo.or.cz/srv/git/phpmyadmin/madhuracj into OpenGIS

commit ed5c01dc440f28486a3f6db546d5faf7d7e41165
Merge: 5ccc1de e3b91b7
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 16:13:26 2011 +0530

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

commit 5ccc1dec16ec46422544c984f4b884ae25fef066
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 15:53:35 2011 +0530

    Styles adjusted to suit the AJAX dialog

commit 516557716a37836df650387bfbc0034031476c24
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 15:32:59 2011 +0530

    Remove the content when AJAX dialog closes

commit 0a80147c4623dff9420cda8ef7e26a0f279566c4
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 14:34:29 2011 +0530

    In multi editing this used to cause duplicate IDs for elements

commit 6ae969a5ee3d2e30ccf3d95aefa7f641a3ccd2db
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 14:04:12 2011 +0530

    Serve OpenStreetMap.js locally

commit 6c6e43b78a43e323de38331e6f0e7668851e59fe
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 10:15:10 2011 +0530

    Control selection based on the selected function.

commit c53750eac09bbff5388613d97297b1cdece2e99f
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 09:07:58 2011 +0530

    'Function based search' for functions that tests spatial relations between geometric objects

commit db1f83b55b151c100a3aa9a81f7856432f730386
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 01:40:55 2011 +0530

    Make it possible to compare with WKB

commit c73380be3509626fbdb7b5027b7d80abb16f2588
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 01:26:31 2011 +0530

    Make it more readable

commit c3189393448f80543ecdb6c94c8c533f204cb0ad
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 01:14:42 2011 +0530

    Use curly brackets for if/else and foreach blocks

commit e456f221494e1ccf76d5b8f73ca5e6896feec113
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 31 01:11:11 2011 +0530

    Detect the output type of the functions being applied

commit 47a8dcfc8885a0086fc8c8b9b5a49e783d81180a
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Jul 28 12:06:15 2011 +0530

    Function based search - for unary functions

commit aed7270cb99b80ccc7abe970a566e6241ccec159
Merge: 01976f1 66c0be9
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jul 30 22:53:07 2011 +0530

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

commit 01976f1663f7d36d18f65574276f7250b506ef94
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Jul 28 11:44:18 2011 +0530

    Handle the cases where URL is too long

commit 003496969e3a5ab8a04e939c945f42c90dfe7f49
Merge: b48a250 e58eea5
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Jul 28 06:01:39 2011 +0530

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

commit b48a250ca8ceb4ab07caa502f05772b9d02acb25
Merge: ec7feea ad4975b
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Tue Jul 26 21:45:43 2011 +0530

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

commit ec7feea9b04d173f2468d7fa3294be23b1965427
Merge: 11ca5da c3863f0
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 24 23:05:35 2011 +0530

    Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into OpenGIS
    
    Conflicts:
    	libraries/import.lib.php
    	libraries/zip_extension.lib.php

commit 11ca5daa412c0338d63020f94f74530e95463ce9
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 24 22:30:52 2011 +0530

    Change of color

commit 1f2ba4e9cc51c2bf2b1c1b96f78f29143e033e36
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 24 22:17:03 2011 +0530

    Resolves problems with point and multipoint visualizations due to the assumption of empty values as zeros

commit 47fdfad3361fc5840776060c2326505de1512ee3
Merge: 6f35aaa 4925260
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Jul 22 04:07:09 2011 +0530

    Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into OpenGIS
    
    Conflicts:
    	libraries/gis/pma_gis_geometrycollection.php

commit 6f35aaa8e46e1bc50b4b5e38d4b9c4810c5c71ce
Merge: 47762d7 75bb94f
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Jul 20 23:15:01 2011 +0530

    Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into OpenGIS
    
    Conflicts:
    	libraries/import.lib.php

commit 47762d7b14815296256dea277647f152c1c5c2fc
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Jul 20 23:07:53 2011 +0530

    Better organized JS code

commit 015ad8968008284f565ecd1274f37ddcd89ca06e
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Jul 20 15:41:35 2011 +0530

    Size of GIS visualization auto adjusted to fit the available space

commit 4d7b7d9a88012563463df82b904a6859400de7d9
Merge: 0e44352 1b56916
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Mon Jul 18 14:08:37 2011 +0530

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

commit 0e4435266b588de8788b01bb92bf8261c3762ab5
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Mon Jul 18 14:03:21 2011 +0530

    Change of classes to avoid conflicts with classes used in tbl_gis_visualization.js

commit 2a402a3103c5a12e6c9d2fd2515d7695da2942ff
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Mon Jul 18 13:43:46 2011 +0530

    OpenStreetMaps based data visualization for GIS data editor

commit 5a6379f93e97a4535a3a78b56ddc6a5cbe3901e8
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 17 16:59:25 2011 +0530

    SVG based data visualization for GIS data editor

commit 96785858bc79297b34b06722fc833bb033aa10c4
Merge: d85c777 10fa6c5
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jul 16 14:19:27 2011 +0530

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

commit d85c777c78a854d56d39cb6420624e22eedc6586
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jul 16 14:17:17 2011 +0530

    Chose the correct GIS type

commit 1b9ddd2efa71971ef1b78356cc878af437cdf5dd
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jul 16 13:23:11 2011 +0530

    These should be PMA_messages[]

commit ba93a625b9de49fc10c1d65a880768258497459c
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jul 16 13:14:29 2011 +0530

    Make JS messages translatable.

commit 7af88c04c75641fc3aba7e26935c0ef8f9e2dcbe
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jul 16 11:05:53 2011 +0530

    Cleanup spaces

commit ed23518a44fdd62c5394c785e515d65f7c4910eb
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jul 16 10:50:22 2011 +0530

    Handle adding polygons and geometry objects

commit ffb970f169f6e9642fd9fe924cca88f8c14695d2
Merge: 83d8d3a 10cbf3b
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jul 16 02:18:41 2011 +0530

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

commit 83d8d3a8ed3043f52b1f1ef42af33fccfead1e87
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jul 16 02:11:18 2011 +0530

    Handle adding linestrings and inner rings. Better comments

commit b2d703dbea2077c9ff48686ee230d7a7ff224318
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jul 16 00:29:00 2011 +0530

    Add points with JavaScript

commit 166b571964d6c3513359512b8eef83584f2f9ddf
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Jul 15 23:13:00 2011 +0530

    Non JS version does not need this parameters.

commit 56090dd46f34e485199541d1262dc70c85001ede
Merge: f5bd53f 108f738
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Jul 15 18:35:32 2011 +0530

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

commit f5bd53fae03e41c2b26f3769ce891270d00d39e9
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Jul 15 18:31:15 2011 +0530

    Remove hidden fields not used.

commit c18ef53b57ba72a6b35e479b3510d855cc636aa7
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Jul 15 18:30:28 2011 +0530

    Do not use PMA_mysqlDie() to handle these errors.

commit bb987837ebf198e60503231bbf7cc9a50eea3337
Merge: 6e7c3ad 117dd68
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Jul 15 00:34:28 2011 +0530

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

commit 6e7c3adbc15eb1f4b822a083b954cbc39a02bc13
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Jul 15 00:27:31 2011 +0530

    Trigger AJAX calls on data change and update the output

commit 0c9301f7dbc88ee49021f708d9004e0b57975fd8
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Jul 15 00:04:32 2011 +0530

    Corrected order of includes.

commit fd0cb076c0c415c321edf8e811c9691d6f2ca06f
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Jul 15 00:03:48 2011 +0530

    Better styling for GIS data editor.

commit 4ee9d4834639659f73635825f367c842fcd0e090
Merge: c97bb57 7f5cbe9
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Jul 14 19:49:59 2011 +0530

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

commit c97bb579250bdafa23e60386facf3f12034d287b
Merge: b1634f8 ac4f0a1
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Jul 14 19:45:16 2011 +0530

    Merge branch 'master' of ssh://repo.or.cz/srv/git/phpmyadmin/madhuracj into OpenGIS

commit b1634f80fd598d67130b7fccd29f7bc8dbc726b4
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Jul 14 19:39:39 2011 +0530

    GIS data editor extended for JS enabled browsers

commit ac4f0a10b0593b20cb49116df0170912ab292e69
Merge: 66f73b4 ad87dcf
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Jul 14 10:01:41 2011 +0530

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

commit 66f73b4114bf8e60496fe052ec86b33c65c3137e
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Jul 14 09:59:35 2011 +0530

    Better error handling.

commit e0e0dea09b25da67f60d787b0c2312dbbc5a7660
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Jul 14 00:09:25 2011 +0530

    1) Better error handling. 2)Typo

commit 1d9ef026089b7b52061f4558ddaaed10d500df60
Merge: a1e6b18 f57faf6
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Jul 13 23:55:14 2011 +0530

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

commit a1e6b187c60999d1934ed5f7428c95f0a5d3820d
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Jul 13 23:51:25 2011 +0530

    Correctly display error message for zero data.

commit f76785603f311153f7217ec45575c98440b07381
Merge: 2bf7086 2c0d2ac
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Jul 13 00:20:41 2011 +0530

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

commit 2bf70868bbd9c69036470b4a9cbfe2fe29e1a8fc
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Jul 13 00:19:11 2011 +0530

    Avoid undefined variables

commit 242534a78ad3d26334cd97dcf8346c7cd327179b
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Wed Jul 13 00:17:09 2011 +0530

    Avoid divide by zero error

commit be8ce3d5b61a069ab2dc4caf2206db1af67cd15c
Merge: e713557 7802be3
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Tue Jul 12 19:04:47 2011 +0530

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

commit e7135574bd2acefa90c7b2e654d2344d3027e479
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Tue Jul 12 14:21:48 2011 +0530

    Trim the name before being displayed as the tooltip.

commit b9e5125870e8d6575f679d59d46e1fddec2f9e0c
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Mon Jul 11 22:25:45 2011 +0530

    Correctly display null and empty values in geometry columns

commit c821997a5a69e8f37ce8b802211774b33a479103
Merge: 3ca86a3 4bb11fd
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Mon Jul 11 21:36:38 2011 +0530

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

commit 3ca86a3929e201898e692ab3608d0dcf1a8a4bf2
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Mon Jul 11 21:29:48 2011 +0530

    Protection against malformed WKT and null

commit 4e8cc7dc97871ba757517d0791488d57abee71a1
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 10 23:29:05 2011 +0530

    Avoid accessing undefined variables

commit 6f3cf75e317dda6dc4a41a5b0c1227962edd30e0
Merge: 2795a90 4ae5cb0
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 10 22:26:15 2011 +0530

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

commit 2795a9061ca0a2c4f344303b686c64dbbc7032cd
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 10 22:13:50 2011 +0530

    Resolve problems due to merge commit

commit c81db372d79bf96acc8a4a2cdb2fe7f0430b57e4
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jul 9 19:18:03 2011 +0530

    Manually implemented PointOnSurface() function as it is not yet implemented in MySQL

commit faced3027aa337a629f69a3e6b67410ad9f07df3
Merge: a58bb10 429328b
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jul 9 15:41:56 2011 +0530

    Merge remote branch 'origin/master' into OpenGIS

commit a58bb10e1839d0740cb634112f36462d52d4ac6f
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Jul 8 18:32:35 2011 +0530

    Correctly import multipolygons from ESRI shape files

commit 28519cf25befaba56aa677d38af2847c2a7febcb
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Fri Jul 8 18:31:19 2011 +0530

    ESRI shape files imported from a zip archive

commit 6f4db19f53370d1e220ba396408dc6e03e0061d9
Merge: c6a8098 b856161
Author: Madhura <madhura.cj at gmail.com>
Date:   Fri Jul 8 18:05:52 2011 +0530

    Merge remote branch 'origin/master' into OpenGIS

commit c6a8098239bac87d105525173e14cf1d1cbc0afa
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Mon Jul 4 00:31:24 2011 +0530

    Typo

commit 5a1018fc43c63c12c8ba8787e83ce4d48f91ff6e
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 3 23:56:47 2011 +0530

    Increase memory limit and time limit

commit 4d111205b1dfb1ef220b052f8ba96b8b1c47af0d
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 3 22:46:48 2011 +0530

    A polygon needs to have atleast 4 points - more instances

commit 93ab68dd131616369dccd0a6a62ff5f1a1a710d2
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 3 22:41:52 2011 +0530

    A polygon needs to have atleast 4 points - more instances

commit cfeb031d1f8d7c31cb3fdf6b376ba7b7ea757a59
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 3 22:36:34 2011 +0530

    A polygon needs to have atleast 4 points.

commit ae88c2e758de107313e8a8cfaa192c42984a9fb8
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 3 22:14:14 2011 +0530

    Tabs replaced with spaces

commit c4faafdc792abb3b2bef62b70ab7f32fd85aa143
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 3 22:12:02 2011 +0530

    Import GIS data from ESRI shape files

commit 1bc0473fe2b2c5fe24ccb2a1541b70e584009265
Merge: b8ddd56 64e4f9f
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jul 3 21:42:04 2011 +0530

    Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into OpenGIS
    
    Conflicts:
    	tbl_replace.php

commit b8ddd56d78598c497e4b4b0b1ffa27ed0550ebc8
Merge: 67ef96d cbf00bc
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Jun 30 10:01:33 2011 +0530

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

commit 67ef96d1f6d6bbf6b7d906a02c4c79898a11ee66
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Thu Jun 30 09:58:09 2011 +0530

    Check whether the variable is set before accessing it.

commit 52501828f77f16baac93b16f706c6262ed55a926
Merge: ff3efd4 02b1b32
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jun 26 18:01:41 2011 +0530

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

commit ff3efd4b7d3ac7b00117d7ef78f239972e3f9d50
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sun Jun 26 17:57:12 2011 +0530

    Editing geometry data using GIS data editor.

commit 5ac3f567c454764152631c26a9dafec7bf7eef0a
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jun 25 23:01:48 2011 +0530

    GIS data editing for POINT

commit da6fe46a4d34c650e3d7f0b70d04ea22730f8e19
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jun 25 21:24:07 2011 +0530

    GISFromWKB functions in data insert/edit window fixed.

commit d257d46dee97fb57173642fafe26a9f8b7f5b10c
Merge: 63900d0 5403fc1
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jun 25 19:48:40 2011 +0530

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

commit 63900d009441d8e81714ea56337d5b736806fca1
Author: Madhura Jayaratne <madhura.cj at gmail.com>
Date:   Sat Jun 25 19:39:31 2011 +0530

    GIS data editor for environments without JavaScript support.
    GIS data preserved while editing.

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

Summary of changes:
 ChangeLog                                         |    3 +
 Documentation.html                                |   42 ++-
 gis_data_editor.php                               |  335 +++++++++++
 js/OpenStreetMap.js                               |  125 ++++
 js/gis_data_editor.js                             |  309 ++++++++++
 js/messages.php                                   |   12 +
 js/sql.js                                         |   10 +-
 js/tbl_change.js                                  |   29 +-
 js/tbl_gis_visualization.js                       |  146 ++++--
 js/tbl_select.js                                  |   89 +++-
 libraries/bfShapeFiles/ShapeFile.lib.php          |  649 +++++++++++++++++++++
 libraries/common.lib.php                          |  193 ++++++-
 libraries/config.default.php                      |    1 +
 libraries/display_tbl.lib.php                     |   96 ++--
 libraries/gis/pma_gis_factory.php                 |    7 +-
 libraries/gis/pma_gis_geometry.php                |   53 ++-
 libraries/gis/pma_gis_geometrycollection.php      |   81 +++
 libraries/gis/pma_gis_linestring.php              |   76 +++
 libraries/gis/pma_gis_multilinestring.php         |  119 ++++
 libraries/gis/pma_gis_multipoint.php              |  130 ++++-
 libraries/gis/pma_gis_multipolygon.php            |  209 +++++++
 libraries/gis/pma_gis_point.php                   |  104 +++-
 libraries/gis/pma_gis_polygon.php                 |  254 ++++++++
 libraries/gis/pma_gis_visualization.php           |   62 ++-
 libraries/gis_visualization.lib.php               |   19 +-
 libraries/import.lib.php                          |   43 +-
 libraries/import/shp.php                          |  399 +++++++++++++
 libraries/tbl_select.lib.php                      |  134 ++++-
 libraries/zip_extension.lib.php                   |   79 +++-
 sql.php                                           |    9 +
 tbl_change.php                                    |   35 +-
 tbl_gis_visualization.php                         |   39 +--
 tbl_replace.php                                   |   35 +-
 tbl_select.php                                    |   60 ++-
 test/classes/gis/PMA_GIS_Factory_test.php         |   80 +++
 test/classes/gis/PMA_GIS_Geometry_test.php        |   60 ++
 test/classes/gis/PMA_GIS_Linestring_test.php      |  142 +++++
 test/classes/gis/PMA_GIS_Multilinestring_test.php |  182 ++++++
 test/classes/gis/PMA_GIS_Multipoint_test.php      |  146 +++++
 test/classes/gis/PMA_GIS_Multipolygon_test.php    |  139 +++++
 test/classes/gis/PMA_GIS_Point_test.php           |  148 +++++
 test/classes/gis/PMA_GIS_Polygon_test.php         |  299 ++++++++++
 test/libraries/PMA_GIS_modifyQuery_test.php       |   94 +++
 themes/original/css/theme_right.css.php           |   38 ++
 themes/pmahomme/css/theme_right.css.php           |   38 ++
 45 files changed, 5090 insertions(+), 262 deletions(-)
 create mode 100644 gis_data_editor.php
 create mode 100644 js/OpenStreetMap.js
 create mode 100644 js/gis_data_editor.js
 create mode 100644 libraries/bfShapeFiles/ShapeFile.lib.php
 create mode 100644 libraries/import/shp.php
 create mode 100644 test/classes/gis/PMA_GIS_Factory_test.php
 create mode 100644 test/classes/gis/PMA_GIS_Geometry_test.php
 create mode 100644 test/classes/gis/PMA_GIS_Linestring_test.php
 create mode 100644 test/classes/gis/PMA_GIS_Multilinestring_test.php
 create mode 100644 test/classes/gis/PMA_GIS_Multipoint_test.php
 create mode 100644 test/classes/gis/PMA_GIS_Multipolygon_test.php
 create mode 100644 test/classes/gis/PMA_GIS_Point_test.php
 create mode 100644 test/classes/gis/PMA_GIS_Polygon_test.php
 create mode 100644 test/libraries/PMA_GIS_modifyQuery_test.php

diff --git a/ChangeLog b/ChangeLog
index e6c1bc4..f70eae5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -44,6 +44,9 @@ phpMyAdmin - ChangeLog
 - bug #3380946 [export] no uid Query result export (Suhosin limit)
 + Grid editing in browse mode (replaces row inline edit)
 + Zoom-search in table Search
++ [interface] Editor for GIS data
++ [import] Import GIS data from ESRI Shapefiles
++ [interface] 'Function based search' for GIS data
 
 3.4.5.0 (not yet released)
 - bug #3375325 [interface] Page list in navigation frame looks odd
diff --git a/Documentation.html b/Documentation.html
index 8f7e66f..758a2bc 100644
--- a/Documentation.html
+++ b/Documentation.html
@@ -2088,9 +2088,10 @@ $cfg['TrustedProxies'] =
         The name of the directory where temporary files can be stored. 
         <br /><br />
 
-        This is needed to work around limitations of <tt>open_basedir</tt> 
-        for uploaded files, see
-        <a href="#faq1_11"><abbr title="Frequently Asked Questions">FAQ</abbr>
+        This is needed for importing ESRI Shapefiles, see
+        <a href="#faq6_30"><abbr title="Frequently Asked Questions">FAQ</abbr>
+        6.30</a> and to work around limitations of <tt>open_basedir</tt> for uploaded
+        files, see <a href="#faq1_11"><abbr title="Frequently Asked Questions">FAQ</abbr>
         1.11</a>.
         <br /><br />
 
@@ -4373,6 +4374,41 @@ INSERT INTO REL_towns VALUES ('M', 'Montréal');
 
 <p> Not every table can be put to the chart. Only tables with one, two or three columns can be visualised as a chart. Moreover the table must be in a special format for chart script to understand it. Currently supported formats can be found in the <a href="http://wiki.phpmyadmin.net/pma/Charts#Data_formats_for_query_results_chart">wiki</a>.</p>
 
+<h4 id="faq6_30">
+    <a href="#faq6_30">6.30 Import: How can I import ESRI Shapefiles</a></h4>
+
+    <p> 
+        An ESRI Shapefile is actually a set of several files, where .shp file contains 
+        geometry data and .dbf file contains data related to those geometry data. 
+        To read data from .dbf file you need to have PHP compiled with the dBase extension 
+        (--enable-dbase). Otherwise only geometry data will be imported.
+    </p>
+
+    <p>To upload these set of files you can use either of the following methods:</p>
+    <ul>
+        <li>
+            <p>
+            Configure upload directory with 
+            <a href="#cfg_UploadDir" class="configrule">$cfg['UploadDir']</a>, upload both 
+            .shp and .dbf files with the same filename and chose the .shp file from the import page.
+            </p>
+        </li>
+        <li>
+            <p>
+            Create a Zip archive with .shp and .dbf files and import it. For this to work, 
+            you need to set <a href="#cfg_TempDir" class="configrule">$cfg['TempDir']</a> to a
+            place where the web server user can write (for example <tt>'./tmp'</tt>).
+            </p>
+
+            <p> To create the temporary directory on a UNIX-based system, you can do:</p>
+<pre>
+cd phpMyAdmin
+mkdir tmp
+chmod o+rwx tmp
+</pre>
+        </li>
+    </ul>
+
 <h3 id="faqproject">phpMyAdmin project</h3>
 
 <h4 id="faq7_1">
diff --git a/gis_data_editor.php b/gis_data_editor.php
new file mode 100644
index 0000000..7614aba
--- /dev/null
+++ b/gis_data_editor.php
@@ -0,0 +1,335 @@
+<?php
+require_once './libraries/common.inc.php';
+if (! isset($_REQUEST['get_gis_editor']) && ! isset($_REQUEST['generate'])) {
+    require_once './libraries/header_http.inc.php';
+    require_once './libraries/header_meta_style.inc.php';
+}
+require_once './libraries/gis/pma_gis_factory.php';
+require_once './libraries/gis_visualization.lib.php';
+
+// Get data if any posted
+$gis_data = array();
+if (PMA_isValid($_REQUEST['gis_data'], 'array')) {
+    $gis_data = $_REQUEST['gis_data'];
+}
+
+$gis_types = array(
+    'POINT',
+    'MULTIPOINT',
+    'LINESTRING',
+    'MULTILINESTRING',
+    'POLYGON',
+    'MULTIPOLYGON',
+    'GEOMETRYCOLLECTION'
+);
+
+// Extract type from the initial call and make sure that it's a valid one.
+// Extract from field's values if availbale, if not use the column type passed.
+if (! isset($gis_data['gis_type'])) {
+    if (isset($_REQUEST['type']) && $_REQUEST['type'] != '') {
+        $gis_data['gis_type'] = strtoupper($_REQUEST['type']);
+    }
+    if (isset($_REQUEST['value']) && trim($_REQUEST['value']) != '') {
+        $start = (substr($_REQUEST['value'], 0, 1) == "'") ? 1 : 0;
+        $gis_data['gis_type'] = substr($_REQUEST['value'], $start, strpos($_REQUEST['value'], "(") - $start);
+    }
+    if((! isset($gis_data['gis_type'])) || (! in_array($gis_data['gis_type'], $gis_types))) {
+        $gis_data['gis_type'] = $gis_types[0];
+    }
+}
+$geom_type = $gis_data['gis_type'];
+
+// Generate parameters from value passed.
+$gis_obj = PMA_GIS_Factory::factory($geom_type);
+if (isset($_REQUEST['value'])) {
+    $gis_data = array_merge($gis_data, $gis_obj->generateParams($_REQUEST['value']));
+}
+
+// Generate Well Known Text
+$srid = (isset($gis_data['srid']) && $gis_data['srid'] != '') ? htmlspecialchars($gis_data['srid']) : 0;
+$wkt = $gis_obj->generateWkt($gis_data, 0);
+$wkt_with_zero = $gis_obj->generateWkt($gis_data, 0, '0');
+$result = "'" . $wkt . "'," . $srid;
+
+// Gererate PNG or SVG based visualization
+$format = (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER <= 8) ? 'png' : 'svg';
+$visualizationSettings = array('width' => 450, 'height' => 300, 'spatialColumn' => 'wkt');
+$data = array(array('wkt' => $wkt_with_zero, 'srid' => $srid));
+$visualization = PMA_GIS_visualizationResults($data, $visualizationSettings, $format);
+$open_layers = PMA_GIS_visualizationResults($data, $visualizationSettings, 'ol');
+
+// If the call is to update the WKT and visualization make an AJAX response
+if(isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) {
+    $extra_data = array(
+        'result'        => $result,
+        'visualization' => $visualization,
+        'openLayers'    => $open_layers,
+    );
+    PMA_ajaxResponse(null, true, $extra_data);
+}
+
+// If the call is to get the whole content, start buffering, skipping </head> and <body> tags
+if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) {
+    ob_start();
+} else {
+?>
+</head>
+<body>
+<?php
+}
+?>
+    <form id="gis_data_editor_form" action="gis_data_editor.php" method="post">
+    <input type="hidden" id="pmaThemeImage" value="<?php echo($GLOBALS['pmaThemeImage']); ?>" />
+    <div id="gis_data_editor">
+        <h3><?php printf(__('Value for the column "%s"'), htmlspecialchars($_REQUEST['field'])); ?></h3>
+
+<?php   echo('<input type="hidden" name="field" value="' . htmlspecialchars($_REQUEST['field']) . '" />');
+        // The input field to which the final result should be added and corresponding null checkbox
+        if (isset($_REQUEST['input_name'])) {
+            echo('<input type="hidden" name="input_name" value="' . htmlspecialchars($_REQUEST['input_name']) . '" />');
+        }
+        echo PMA_generate_common_hidden_inputs();
+?>
+        <!-- Visualization section -->
+        <div id="placeholder" style="width:450px;height:300px;
+<?php       if ($srid != 0) {
+                echo('display:none;');
+            }
+?>      ">
+<?php       echo ($visualization);
+?>      </div>
+        <div id="openlayersmap" style="width:450px;height:300px;
+<?php       if ($srid == 0) {
+                echo('display:none;');
+            }
+?>      ">
+        </div>
+        <div class="choice" style="float:right;clear:right;">
+            <input type="checkbox" id="choice" value="useBaseLayer"
+<?php       if ($srid != 0) {
+                echo(' checked="checked"');
+            }
+?>          />
+            <label for="choice"><?php echo __("Use OpenStreetMaps as Base Layer"); ?></label>
+        </div>
+        <script language="javascript" type="text/javascript">
+            <?php echo($open_layers); ?>
+        </script>
+        <!-- End of visualization section -->
+
+        <!-- Header section - Inclueds GIS type selector and input field for SRID -->
+        <div id="gis_data_header">
+            <select name="gis_data[gis_type]" class="gis_type">
+<?php
+                foreach ($gis_types as $gis_type) {
+                    echo('<option value="' . $gis_type . '"');
+                    if ($geom_type == $gis_type) {
+                        echo(' selected="selected"');
+                    }
+                    echo('>' . $gis_type . '</option>');
+                }
+?>
+            </select>
+            <input type="submit" name="gis_data[go]" class="go" value="<?php echo __("Go")?>" />
+            <label for="srid"><?php echo __("SRID"); ?>: </label>
+            <input name="gis_data[srid]" type="text" value="<?php echo($srid); ?>" />
+        </div>
+        <!-- End of header section -->
+
+        <!-- Data section -->
+        <div id="gis_data">
+<?php   $geom_count = 1;
+        if ($geom_type == 'GEOMETRYCOLLECTION') {
+            $geom_count = (isset($gis_data[$geom_type]['geom_count'])) ? $gis_data[$geom_type]['geom_count'] : 1;
+            if (isset($gis_data[$geom_type]['add_geom'])) {
+                $geom_count++;
+            }
+            echo('<input type="hidden" name="gis_data[GEOMETRYCOLLECTION][geom_count]" value="' . $geom_count . '">');
+        }
+        for ($a = 0; $a < $geom_count; $a++) {
+            if ($geom_type == 'GEOMETRYCOLLECTION') {
+                echo('<br/><br/>'); echo __("Geometry"); echo($a + 1 . ':<br/>');
+                if (isset($gis_data[$a]['gis_type'])) {
+                    $type = $gis_data[$a]['gis_type'];
+                } else {
+                    $type = $gis_types[0];
+                }
+                echo('<select name="gis_data[' . $a . '][gis_type]" class="gis_type">');
+                foreach (array_slice($gis_types, 0, 6) as $gis_type) {
+                    echo('<option value="' . $gis_type . '"');
+                    if ($type == $gis_type) {
+                        echo(' selected="selected"');
+                    }
+                    echo('>' . $gis_type . '</option>');
+                }
+                echo('</select>');
+                echo('<input type="submit" name="gis_data[' . $a . '][go]" class="go" value="'); echo __("Go"); echo('">');
+            } else {
+                $type = $geom_type;
+            }
+
+            if ($type == 'POINT') {
+                echo('<br/>'); echo __("Point"); echo(' :');
+?>              <label for="x"><?php echo __("X"); ?></label>
+                <input name="gis_data[<?php echo($a); ?>][POINT][x]" type="text" value="<?php echo(isset($gis_data[$a]['POINT']['x']) ? htmlspecialchars($gis_data[$a]['POINT']['x']) : ''); ?>" />
+                <label for="y"><?php echo __("Y"); ?></label>
+                <input name="gis_data[<?php echo($a); ?>][POINT][y]" type="text" value="<?php echo(isset($gis_data[$a]['POINT']['y']) ? htmlspecialchars($gis_data[$a]['POINT']['y']) : ''); ?>" />
+<?php
+            } elseif ($type == 'MULTIPOINT' || $type == 'LINESTRING') {
+
+                $no_of_points = isset($gis_data[$a][$type]['no_of_points']) ? $gis_data[$a][$type]['no_of_points'] : 1;
+                if ($type == 'LINESTRING' && $no_of_points < 2) {
+                    $no_of_points = 2;
+                }
+                if ($type == 'MULTIPOINT' && $no_of_points < 1) {
+                    $no_of_points = 1;
+                }
+
+                if (isset($gis_data[$a][$type]['add_point'])) {
+                    $no_of_points++;
+                }
+                echo('<input type="hidden" name="gis_data[' . $a . '][' . $type . '][no_of_points]" value="' . $no_of_points . '">');
+
+                for ($i = 0; $i < $no_of_points; $i++) {
+                    echo('<br/>'); echo __("Point"); echo($i + 1 . ':');
+?>                  <label for="x"><?php echo  __("X"); ?></label>
+                    <input type="text" name="gis_data[<?php echo($a); ?>][<?php echo($type); ?>][<?php echo($i); ?>][x]" value="<?php echo(isset($gis_data[$a][$type][$i]['x']) ? htmlspecialchars($gis_data[$a][$type][$i]['x']) : ''); ?>" />
+                    <label for="y"><?php echo  __("Y"); ?></label>
+                    <input type="text" name="gis_data[<?php echo($a); ?>][<?php echo($type); ?>][<?php echo($i); ?>][y]" value="<?php echo(isset($gis_data[$a][$type][$i]['y']) ? htmlspecialchars($gis_data[$a][$type][$i]['y']) : ''); ?>" />
+<?php
+                }
+?>
+               <input type="submit" name="gis_data[<?php echo($a); ?>][<?php echo($type); ?>][add_point]" class="add addPoint" value="<?php echo __("Add a point"); ?>">
+<?php
+            } elseif ($type == 'MULTILINESTRING' || $type == 'POLYGON') {
+
+                $no_of_lines = isset($gis_data[$a][$type]['no_of_lines']) ? $gis_data[$a][$type]['no_of_lines'] : 1;
+                if ($no_of_lines < 1) {
+                    $no_of_lines = 1;
+                }
+                if (isset($gis_data[$a][$type]['add_line'])) {
+                    $no_of_lines++;
+                }
+                echo('<input type="hidden" name="gis_data[' . $a . '][' . $type . '][no_of_lines]" value="' . $no_of_lines . '">');
+
+                for ($i = 0; $i < $no_of_lines; $i++) {
+                    echo('<br/>');
+                    if ($type == 'MULTILINESTRING') {
+                        echo __("Linestring"); echo($i + 1 . ':');
+                    } else {
+                        if ($i == 0) {
+                            echo __("Outer Ring:");
+                        } else {
+                            echo __("Inner Ring"); echo($i . ':');
+                        }
+                    }
+
+                    $no_of_points = isset($gis_data[$a][$type][$i]['no_of_points']) ? $gis_data[$a][$type][$i]['no_of_points'] : 2;
+                    if ($type == 'MULTILINESTRING' && $no_of_points < 2) {
+                        $no_of_points = 2;
+                    }
+                    if ($type == 'POLYGON' && $no_of_points < 4) {
+                        $no_of_points = 4;
+                    }
+                    if (isset($gis_data[$a][$type][$i]['add_point'])) {
+                        $no_of_points++;
+                    }
+                    echo('<input type="hidden" name="gis_data[' . $a . '][' . $type . '][' . $i . '][no_of_points]" value="' . $no_of_points . '">');
+
+                    for ($j = 0; $j < $no_of_points; $j++) {
+                        echo('<br/>'); echo __("Point"); echo($j + 1 . ':');
+?>                      <label for="x"><?php echo  __("X"); ?></label>
+                        <input type="text" name="gis_data[<?php echo($a); ?>][<?php echo($type); ?>][<?php echo($i); ?>][<?php echo($j); ?>][x]" value="<?php echo(isset($gis_data[$a][$type][$i][$j]['x']) ? htmlspecialchars($gis_data[$a][$type][$i][$j]['x']) : ''); ?>" />
+                        <label for="y"><?php echo  __("Y"); ?></label>
+                        <input type="text" name="gis_data[<?php echo($a); ?>][<?php echo($type); ?>][<?php echo($i); ?>][<?php echo($j); ?>][y]" value="<?php echo(isset($gis_data[$a][$type][$i][$j]['x']) ? htmlspecialchars($gis_data[$a][$type][$i][$j]['y']) : ''); ?>" />
+<?php               }
+?>                  <input type="submit" name="gis_data[<?php echo($a); ?>][<?php echo($type); ?>][<?php echo($i); ?>][add_point]" class="add addPoint" value="<?php echo __("Add a point"); ?>">
+<?php           }
+                $caption = ($type == 'MULTILINESTRING') ? __('Add a linestring') : __('Add an inner ring');
+?>              <br/><input type="submit" name="gis_data[<?php echo($a); ?>][<?php echo($type); ?>][add_line]" class="add addLine" value="<?php echo($caption); ?>">
+<?php
+            } elseif ($type == 'MULTIPOLYGON') {
+                $no_of_polygons = isset($gis_data[$a][$type]['no_of_polygons']) ? $gis_data[$a][$type]['no_of_polygons'] : 1;
+                if ($no_of_polygons < 1) {
+                    $no_of_polygons = 1;
+                }
+                if (isset($gis_data[$a][$type]['add_polygon'])) {
+                    $no_of_polygons++;
+                }
+                echo('<input type="hidden" name="gis_data[' . $a . '][' . $type . '][no_of_polygons]" value="' . $no_of_polygons . '">');
+
+                for ($k = 0; $k < $no_of_polygons; $k++) {
+                    echo('<br/>'); echo __("Polygon"); echo($k + 1 . ':');
+                    $no_of_lines = isset($gis_data[$a][$type][$k]['no_of_lines']) ? $gis_data[$a][$type][$k]['no_of_lines'] : 1;
+                    if ($no_of_lines < 1) {
+                        $no_of_lines = 1;
+                    }
+                    if (isset($gis_data[$a][$type][$k]['add_line'])) {
+                        $no_of_lines++;
+                    }
+                    echo('<input type="hidden" name="gis_data[' . $a . '][' . $type . '][' . $k . '][no_of_lines]" value="' . $no_of_lines . '">');
+
+                    for ($i = 0; $i < $no_of_lines; $i++) {
+                        echo('<br/><br/>');
+                        if ($i == 0) {
+                            echo __("Outer Ring:");
+                        } else {
+                            echo __("Inner Ring"); echo($i . ':');
+                        }
+
+                        $no_of_points = isset($gis_data[$a][$type][$k][$i]['no_of_points']) ? $gis_data[$a][$type][$k][$i]['no_of_points'] : 4;
+                        if ($no_of_points < 4) {
+                            $no_of_points = 4;
+                        }
+                        if (isset($gis_data[$a][$type][$k][$i]['add_point'])) {
+                            $no_of_points++;
+                        }
+                        echo('<input type="hidden" name="gis_data[' . $a . '][' . $type . '][' . $k . '][' . $i . '][no_of_points]" value="' . $no_of_points . '">');
+
+                        for ($j = 0; $j < $no_of_points; $j++) {
+                            echo('<br/>'); echo __("Point"); echo($j + 1 . ':');
+?>                          <label for="x"><?php echo  __("X"); ?></label>
+                            <input type="text" name="<?php echo("gis_data[" . $a . "][" . $type . "][" . $k . "][" . $i . "][" . $j . "][x]"); ?>" value="<?php echo(isset($gis_data[$a][$type][$k][$i][$j]['x']) ? htmlspecialchars($gis_data[$a][$type][$k][$i][$j]['x']) : ''); ?>" />
+                            <label for="y"><?php echo  __("Y"); ?></label>
+                            <input type="text" name="<?php echo("gis_data[" . $a . "][" . $type . "][" . $k . "][" . $i . "][" . $j . "][y]"); ?>" value="<?php echo(isset($gis_data[$a][$type][$k][$i][$j]['y']) ? htmlspecialchars($gis_data[$a][$type][$k][$i][$j]['y']) : ''); ?>" />
+<?php                   }
+?>                      <input type="submit" name="<?php echo("gis_data[" . $a . "][" . $type . "][" . $k . "][" . $i . "][add_point]"); ?>" class="add addPoint" value="<?php echo __("Add a point"); ?>">
+<?php               }
+?>                  <br/><input type="submit" name="<?php echo("gis_data[" . $a . "][" . $type . "][" . $k . "][add_line]"); ?>" class="add addLine" value="<?php echo __('Add an inner ring') ?>"><br/>
+<?php           }
+?>              <br/><input type="submit" name="<?php echo("gis_data[" . $a . "][" . $type . "][add_polygon]"); ?>" class="add addPolygon" value="<?php echo __('Add a polygon') ?>">
+<?php       }
+        }
+        if ($geom_type == 'GEOMETRYCOLLECTION') {
+?>          <br/><br/><input type="submit" name="gis_data[GEOMETRYCOLLECTION][add_geom]" class="add addGeom" value="<?php  echo __("Add geometry"); ?>" />
+<?php   }
+?>      </div>
+        <!-- End of data section -->
+
+        <br/><input type="submit" name="gis_data[save]" value="<?php echo __('Go') ?>">
+        <div id="gis_data_output">
+            <h3><?php echo __('Output'); ?></h3>
+            <p><?php echo __('Chose "GeomFromText" from the "Function" column and paste the below string into the "Value" field'); ?></p>
+            <textarea id="gis_data_textarea" cols="95" rows="5">
+<?php           echo($result);
+?>          </textarea>
+        </div>
+    </div>
+    </form>
+<?php
+
+// If the call is to get the whole content, get the content in the buffer and make and AJAX response.
+if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) {
+    $extra_data['gis_editor'] = ob_get_contents();
+    PMA_ajaxResponse(NULL, ob_end_clean(), $extra_data);
+}
+?>
+</body>
+
+<?php
+/**
+ * Displays the footer
+ */
+require './libraries/footer.inc.php';
+
+?>
\ No newline at end of file
diff --git a/js/OpenStreetMap.js b/js/OpenStreetMap.js
new file mode 100644
index 0000000..aebfa65
--- /dev/null
+++ b/js/OpenStreetMap.js
@@ -0,0 +1,125 @@
+/**
+ * Namespace: Util.OSM
+ */
+OpenLayers.Util.OSM = {};
+
+/**
+ * Constant: MISSING_TILE_URL
+ * {String} URL of image to display for missing tiles
+ */
+OpenLayers.Util.OSM.MISSING_TILE_URL = "http://www.openstreetmap.org/openlayers/img/404.png";
+
+/**
+ * Property: originalOnImageLoadError
+ * {Function} Original onImageLoadError function.
+ */
+OpenLayers.Util.OSM.originalOnImageLoadError = OpenLayers.Util.onImageLoadError;
+
+/**
+ * Function: onImageLoadError
+ */
+OpenLayers.Util.onImageLoadError = function() {
+    if (this.src.match(/^http:\/\/[abc]\.[a-z]+\.openstreetmap\.org\//)) {
+        this.src = OpenLayers.Util.OSM.MISSING_TILE_URL;
+    } else if (this.src.match(/^http:\/\/[def]\.tah\.openstreetmap\.org\//)) {
+        // do nothing - this layer is transparent
+    } else {
+        OpenLayers.Util.OSM.originalOnImageLoadError;
+    }
+};
+
+/**
+ * Class: OpenLayers.Layer.OSM.Mapnik
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.OSM>
+ */
+OpenLayers.Layer.OSM.Mapnik = OpenLayers.Class(OpenLayers.Layer.OSM, {
+    /**
+     * Constructor: OpenLayers.Layer.OSM.Mapnik
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        var url = [
+            "http://a.tile.openstreetmap.org/${z}/${x}/${y}.png",
+            "http://b.tile.openstreetmap.org/${z}/${x}/${y}.png",
+            "http://c.tile.openstreetmap.org/${z}/${x}/${y}.png"
+        ];
+        options = OpenLayers.Util.extend({
+            numZoomLevels: 19,
+            buffer: 0,
+            transitionEffect: "resize"
+        }, options);
+        var newArguments = [name, url, options];
+        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.OSM.Mapnik"
+});
+
+/**
+ * Class: OpenLayers.Layer.OSM.Osmarender
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.OSM>
+ */
+OpenLayers.Layer.OSM.Osmarender = OpenLayers.Class(OpenLayers.Layer.OSM, {
+    /**
+     * Constructor: OpenLayers.Layer.OSM.Osmarender
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        var url = [
+            "http://a.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png",
+            "http://b.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png",
+            "http://c.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"
+        ];
+        options = OpenLayers.Util.extend({
+            numZoomLevels: 18,
+            buffer: 0,
+            transitionEffect: "resize"
+        }, options);
+        var newArguments = [name, url, options];
+        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.OSM.Osmarender"
+});
+
+/**
+ * Class: OpenLayers.Layer.OSM.CycleMap
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.OSM>
+ */
+OpenLayers.Layer.OSM.CycleMap = OpenLayers.Class(OpenLayers.Layer.OSM, {
+    /**
+     * Constructor: OpenLayers.Layer.OSM.CycleMap
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        var url = [
+            "http://a.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png",
+            "http://b.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png",
+            "http://c.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png"
+        ];
+        options = OpenLayers.Util.extend({
+            numZoomLevels: 19,
+            buffer: 0,
+            transitionEffect: "resize"
+        }, options);
+        var newArguments = [name, url, options];
+        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.OSM.CycleMap"
+});
diff --git a/js/gis_data_editor.js b/js/gis_data_editor.js
new file mode 100644
index 0000000..b2bab89
--- /dev/null
+++ b/js/gis_data_editor.js
@@ -0,0 +1,309 @@
+/**
+ * @fileoverview    functions used in GIS data editor
+ *
+ * @requires    jQuery
+ *
+ */
+
+/**
+ * Closes the GIS data editor and perform necessary clean up work.
+ */
+function closeGISEditor(){
+    $("#popup_background").fadeOut("fast");
+    $("#gis_editor").fadeOut("fast");
+    $("#gis_editor").html('');
+}
+
+/**
+ * Prepares the HTML recieved via AJAX.
+ */
+function prepareJSVersion() {
+    // Hide 'Go' buttons associated with the dropdowns
+    $('.go').hide();
+
+    // Change the text on the submit button
+    $("input[name='gis_data[save]']")
+        .attr('value', PMA_messages['strCopy'])
+        .insertAfter($('#gis_data_textarea'))
+        .before('<br><br>');
+
+    // Add close and cancel links
+    $('#gis_data_editor').prepend('<a class="close_gis_editor">' + PMA_messages['strClose'] + '</a>');
+    $('<a class="cancel_gis_editor"> ' + PMA_messages['strCancel'] + '</a>')
+        .insertAfter($("input[name='gis_data[save]']"));
+
+    // Remove the unnecessary text
+    $('div#gis_data_output p').remove();
+
+    // Remove 'add' buttons and add links
+    $('.add').each(function(e) {
+        var $button = $(this);
+        $button.addClass('addJs').removeClass('add');
+        var classes = $button.attr('class');
+        $button
+            .after('<a class="' + classes + '" name="' + $button.attr('name') 
+                + '">+ ' + $button.attr('value') + '</a>')
+            .remove();
+    });
+}
+
+/**
+ * Returns the HTML for a data point.
+ *
+ * @param pointNumber point number
+ * @param prefix      prefix of the name
+ * @returns the HTML for a data point
+ */
+function addDataPoint(pointNumber, prefix) {
+    return '<br>' + PMA_messages['strPoint'] + (pointNumber + 1) + ':'
+        + '<label for="x"> ' + PMA_messages['strX'] + ' </label>'
+        + '<input type="text" name="' + prefix + '[' + pointNumber + '][x]" value="">'
+        + '<label for="y"> ' + PMA_messages['strY'] + ' </label>'
+        + '<input type="text" name="' + prefix + '[' + pointNumber + '][y]" value="">';
+}
+
+/**
+ * Initialize the visualization in the GIS data editor.
+ */
+function initGISEditorVisualization() {
+    // Loads either SVG or OSM visualization based on the choice
+    selectVisualization();
+    // Adds necessary styles to the div that coontains the openStreetMap
+    styleOSM();
+    // Loads the SVG element and make a reference to it
+    loadSVG();
+    // Adds controllers for zooming and panning
+    addZoomPanControllers();
+    zoomAndPan();
+}
+
+/**
+ * Opens up the GIS data editor.
+ * 
+ * @param value      current value of the geometry field
+ * @param field      field name
+ * @param type       geometry type
+ * @param input_name name of the input field
+ * @param token      token
+ */
+function openGISEditor(value, field, type, input_name, token) {
+    // Center the popup
+    var windowWidth = document.documentElement.clientWidth;
+    var windowHeight = document.documentElement.clientHeight;
+    var popupWidth = windowWidth * 0.9;
+    var popupHeight = windowHeight * 0.9;
+    var popupOffsetTop = windowHeight / 2 - popupHeight / 2;
+    var popupOffsetLeft = windowWidth / 2 - popupWidth / 2;
+    var $gis_editor = $("#gis_editor");
+    $gis_editor.css({"top": popupOffsetTop, "left": popupOffsetLeft, "width": popupWidth, "height": popupHeight});
+
+    $.post('gis_data_editor.php', {
+        'field' : field,
+        'value' : value,
+        'type' : type,
+        'input_name' : input_name,
+        'get_gis_editor' : true,
+        'token' : token
+    }, function(data) {
+        if(data.success == true) {
+            $gis_editor.html(data.gis_editor);
+            initGISEditorVisualization();
+            prepareJSVersion();
+        } else {
+            PMA_ajaxShowMessage(data.error);
+        }
+    }, 'json');
+
+    // Make it appear
+    $("#popup_background").css({"opacity":"0.7"});
+    $("#popup_background").fadeIn("fast");
+    $gis_editor.fadeIn("fast");
+}
+
+/**
+ * Prepare and insert the GIS data in Well Known Text format
+ * to the input field.
+ */
+function insertDataAndClose() {
+    var $form = $('form#gis_data_editor_form');
+    var input_name = $form.find("input[name='input_name']").val();
+
+    $.post('gis_data_editor.php', $form.serialize() + "&generate=true", function(data) {
+        if(data.success == true) {
+            $("input[name='" + input_name + "']").val(data.result);
+        } else {
+            PMA_ajaxShowMessage(data.error);
+        }
+    }, 'json');
+    closeGISEditor();
+}
+
+$(document).ready(function() {
+
+    // Remove the class that is added due to the URL being too long.
+    $('.open_gis_editor a').removeClass('formLinkSubmit');
+    
+    /**
+     * Prepares and insert the GIS data to the input field on clicking 'copy'.
+     */
+    $("input[name='gis_data[save]']").live('click', function(event) {
+        event.preventDefault();
+        insertDataAndClose();
+    });
+
+    /**
+     * Prepares and insert the GIS data to the input field on pressing 'enter'.
+     */
+    $('#gis_editor').live('submit', function(event) {
+        event.preventDefault();
+        insertDataAndClose();
+    });
+
+    /**
+     * Trigger asynchronous calls on data change and update the output.
+     */
+    $('#gis_editor').find("input[type='text']").live('change', function() {
+        var $form = $('form#gis_data_editor_form');
+        $.post('gis_data_editor.php', $form.serialize() + "&generate=true", function(data) {
+            if(data.success == true) {
+                $('#gis_data_textarea').val(data.result);
+                $('#placeholder').empty().removeClass('hasSVG').html(data.visualization);
+                $('#openlayersmap').empty();
+                eval(data.openLayers);
+                initGISEditorVisualization();
+            } else {
+                PMA_ajaxShowMessage(data.error);
+            }
+        }, 'json');
+    });
+
+    /**
+     * Update the form on change of the GIS type.
+     */
+    $(".gis_type").live('change', function(event) {
+        var $gis_editor = $("#gis_editor");
+        var $form = $('form#gis_data_editor_form');
+
+        $.post('gis_data_editor.php', $form.serialize() + "&get_gis_editor=true", function(data) {
+            if(data.success == true) {
+                $gis_editor.html(data.gis_editor);
+                initGISEditorVisualization();
+                prepareJSVersion();
+            } else {
+                PMA_ajaxShowMessage(data.error);
+            }
+        }, 'json');
+    });
+
+    /**
+     * Handles closing of the GIS data editor.
+     */
+    $('.close_gis_editor, .cancel_gis_editor').live('click', function() {
+        closeGISEditor();
+    });
+
+    /**
+     * Handles adding data points
+     */
+    $('.addJs.addPoint').live('click', function() {
+        var $a = $(this);
+        var name = $a.attr('name');
+        // Eg. name = gis_data[0][MULTIPOINT][add_point] => prefix = gis_data[0][MULTIPOINT]
+        var prefix = name.substr(0, name.length - 11);
+        // Find the number of points
+        var $noOfPointsInput = $("input[name='" + prefix + "[no_of_points]" + "']");
+        var noOfPoints = parseInt($noOfPointsInput.attr('value'));
+        // Add the new data point
+        var html = addDataPoint(noOfPoints, prefix);
+        $a.before(html);
+        $noOfPointsInput.attr('value', noOfPoints + 1);
+    });
+
+    /**
+     * Handles adding linestrings and inner rings
+     */
+    $('.addLine.addJs').live('click', function() {
+        var $a = $(this);
+        var name = $a.attr('name');
+
+        // Eg. name = gis_data[0][MULTILINESTRING][add_line] => prefix = gis_data[0][MULTILINESTRING]
+        var prefix = name.substr(0, name.length - 10);
+        var type = prefix.slice(prefix.lastIndexOf('[') + 1, prefix.lastIndexOf(']'));
+
+        // Find the number of lines
+        var $noOfLinesInput = $("input[name='" + prefix + "[no_of_lines]" + "']");
+        var noOfLines = parseInt($noOfLinesInput.attr('value'));
+
+        // Add the new linesting of inner ring based on the type
+        var html = '<br>';
+        if (type == 'MULTILINESTRING') {
+            html += PMA_messages['strLineString'] + (noOfLines + 1) + ':';
+            var noOfPoints = 2;
+        } else {
+            html += PMA_messages['strInnerRing'] + noOfLines + ':';
+            var noOfPoints = 4;
+        }
+        html += '<input type="hidden" name="' + prefix + '[' + noOfLines + '][no_of_points]" value="' + noOfPoints + '">';
+        for (i = 0; i < noOfPoints; i++) {
+            html += addDataPoint(i, (prefix + '[' + noOfLines + ']'));
+        }
+        html += '<a class="addPoint addJs" name="' + prefix + '[' + noOfLines + '][add_point]">+ ' 
+            + PMA_messages['strAddPoint'] + '</a><br>';
+
+        $a.before(html);
+        $noOfLinesInput.attr('value', noOfLines + 1);
+    });
+
+    /**
+     * Handles adding polygons
+     */
+    $('.addJs.addPolygon').live('click', function() {
+        var $a = $(this);
+        var name = $a.attr('name');
+        // Eg. name = gis_data[0][MULTIPOLYGON][add_polygon] => prefix = gis_data[0][MULTIPOLYGON]
+        var prefix = name.substr(0, name.length - 13);
+        // Find the number of polygons
+        var $noOfPolygonsInput = $("input[name='" + prefix + "[no_of_polygons]" + "']");
+        var noOfPolygons = parseInt($noOfPolygonsInput.attr('value'));
+
+        // Add the new polygon
+        var html = PMA_messages['strPolygon'] + (noOfPolygons + 1) + ':<br>';
+        html += '<input type="hidden" name="' + prefix + '[' + noOfPolygons + '][no_of_lines]" value="1">';
+            + '<br>' + PMA_messages['strOuterRing'] + ':';
+            + '<input type="hidden" name="' + prefix + '[' + noOfPolygons + '][0][no_of_points]" value="4">';
+        for (i = 0; i < 4; i++) {
+            html += addDataPoint(i, (prefix + '[' + noOfPolygons + '][0]'));
+        }
+        html += '<a class="addPoint addJs" name="' + prefix + '[' + noOfPolygons + '][0][add_point]">+ ' 
+            + PMA_messages['strAddPoint'] + '</a><br>'
+            + '<a class="addLine addJs" name="' + prefix + '[' + noOfPolygons + '][add_line]">+ ' 
+            + PMA_messages['strAddInnerRing'] + '</a><br><br>';
+
+        $a.before(html);
+        $noOfPolygonsInput.attr('value', noOfPolygons + 1);
+    });
+
+    /**
+     * Handles adding geoms
+     */
+    $('.addJs.addGeom').live('click', function() {
+        var $a = $(this);
+        var prefix = 'gis_data[GEOMETRYCOLLECTION]';
+        // Find the number of geoms
+        var $noOfGeomsInput = $("input[name='" + prefix + "[geom_count]" + "']");
+        var noOfGeoms = parseInt($noOfGeomsInput.attr('value'));
+
+        var html1 = PMA_messages['strGeometry'] + (noOfGeoms + 1) + ':<br>';
+        var $geomType = $("select[name='gis_data[" + (noOfGeoms - 1) + "][gis_type]']").clone();
+        $geomType.attr('name', 'gis_data[' + noOfGeoms + '][gis_type]').val('POINT');
+        var html2 = '<br>' + PMA_messages['strPoint'] + ' :'
+            + '<label for="x"> ' + PMA_messages['strX'] + ' </label>'
+            + '<input type="text" name="gis_data[' + noOfGeoms + '][POINT][x]" value="">'
+            + '<label for="y"> ' + PMA_messages['strY'] + ' </label>'
+            + '<input type="text" name="gis_data[' + noOfGeoms + '][POINT][y]" value="">'
+            + '<br><br>';
+
+        $a.before(html1); $geomType.insertBefore($a); $a.before(html2);
+        $noOfGeomsInput.attr('value', noOfGeoms + 1);
+    });
+});
diff --git a/js/messages.php b/js/messages.php
index a8c7d10..10beb0a 100644
--- a/js/messages.php
+++ b/js/messages.php
@@ -280,6 +280,18 @@ $js_messages['strSameInputs'] = '<strong>' . __('Select two different columns')
 
 /* For tbl_change.js */
 $js_messages['strIgnore'] = __('Ignore');
+$js_messages['strCopy'] = __('Copy');
+$js_messages['strX'] = __('X');
+$js_messages['strY'] = __('Y');
+$js_messages['strPoint'] = __('Point');
+$js_messages['strLineString'] = __('Linestring');
+$js_messages['strPolygon'] = __('Polygon');
+$js_messages['strGeometry'] = __('Geometry');
+$js_messages['strInnerRing'] = __('Inner Ring');
+$js_messages['strOuterRing'] = __('Outer Ring');
+$js_messages['strAddPoint'] = __('Add a point');
+$js_messages['strAddInnerRing'] = __('Add an inner ring');
+$js_messages['strAddPolygon'] = __('Add a polygon');
 
 /* For tbl_structure.js */
 $js_messages['strAddColumns'] = __('Add columns');
diff --git a/js/sql.js b/js/sql.js
index f4a7475..99fd93c 100644
--- a/js/sql.js
+++ b/js/sql.js
@@ -334,10 +334,10 @@ $(document).ready(function() {
              */
             var button_options = {};
             // in the following function we need to use $(this)
-            button_options[PMA_messages['strCancel']] = function() {$(this).parent().dialog('close').remove();}
+            button_options[PMA_messages['strCancel']] = function() {$(this).dialog('close').remove();}
 
             var button_options_error = {};
-            button_options_error[PMA_messages['strOK']] = function() {$(this).parent().dialog('close').remove();}
+            button_options_error[PMA_messages['strOK']] = function() {$(this).dialog('close').remove();}
             var $form = $("#resultsForm");
             var $msgbox = PMA_ajaxShowMessage();
 
@@ -351,6 +351,9 @@ $(document).ready(function() {
                         height: 230,
                         width: 900,
                         open: PMA_verifyTypeOfAllColumns,
+                        close: function(event, ui) {
+                            $('#change_row_dialog').remove();
+                        },
                         buttons : button_options_error
                     })// end dialog options
                 } else {
@@ -361,6 +364,9 @@ $(document).ready(function() {
                         height: 600,
                         width: 900,
                         open: PMA_verifyTypeOfAllColumns,
+                        close: function(event, ui) {
+                            $('#change_row_dialog').remove();
+                        },
                         buttons : button_options
                     })
                     //Remove the top menu container from the dialog
diff --git a/js/tbl_change.js b/js/tbl_change.js
index 17677b9..25bc120 100644
--- a/js/tbl_change.js
+++ b/js/tbl_change.js
@@ -218,11 +218,38 @@ function verificationsAfterFieldChange(urlField, multi_edit, theType)
  * Ajax handlers for Change Table page
  *
  * Actions Ajaxified here:
- * Submit Data to be inserted into the table
+ * Submit Data to be inserted into the table.
  * Restart insertion with 'N' rows.
  */
 $(document).ready(function() {
 
+    $('.open_gis_editor').live('click', function(event) {
+        event.preventDefault();
+
+        var $span = $(this);
+        // Current value
+        var value = $span.parent('td').children("input[type='text']").val();
+        // Field name
+        var field = $span.parents('tr').children('td:first').find("input[type='hidden']").val();
+        // Column type
+        var type = $span.parents('tr').find('span.column_type').text();
+        // Names of input field and null checkbox
+        var input_name = $span.parent('td').children("input[type='text']").attr('name');
+        //Token
+        var token = $("input[name='token']").val();
+
+        openGISEditor(value, field, type, input_name, token);
+    });
+
+    /**
+     * Uncheck the null checkbox as geometry data is placed on the input field
+     */
+    $("input[name='gis_data[save]']").live('click', function(event) {
+        var input_name = $('form#gis_data_editor_form').find("input[name='input_name']").val();   
+        var $null_checkbox = $("input[name='" + input_name + "']").parents('tr').find('.checkbox_null');
+        $null_checkbox.attr('checked', false);
+    });
+
     // these were hidden via the "hide" class
     $('.foreign_values_anchor').show();
 
diff --git a/js/tbl_gis_visualization.js b/js/tbl_gis_visualization.js
index 978cd69..0a84189 100644
--- a/js/tbl_gis_visualization.js
+++ b/js/tbl_gis_visualization.js
@@ -8,7 +8,9 @@
  */
 
 var x = 0;
+var default_x = 0;
 var y = 0;
+var default_y = 0;
 var scale = 1;
 var svg;
 
@@ -51,56 +53,52 @@ function zoomAndPan()
 }
 
 /**
- * Ajax handlers for GIS visualization page
- *
- * Actions Ajaxified here:
- *
- * Zooming in and zooming out on mousewheel movement.
- * Panning the visualization on dragging.
- * Zooming in on double clicking.
- * Zooming out on clicking the zoom out button.
- * Panning on clicking the arrow buttons.
- * Displaying tooltips for GIS objects.
+ * Initially loads either SVG or OSM visualization based on the choice.
  */
-$(document).ready(function() {
-    var $placeholder = $('#placeholder');
-    var $openlayersmap = $('#openlayersmap');
-
-   if ($('#choice').prop('checked') != true) {
-        $openlayersmap.hide();
+function selectVisualization() {
+    if ($('#choice').prop('checked') != true) {
+        $('#openlayersmap').hide();
     } else {
-        $placeholder.hide();
+        $('#placeholder').hide();
     }
+    $('.choice').show();
+}
 
+/**
+ * Adds necessary styles to the div that coontains the openStreetMap.
+ */
+function styleOSM() {
+    var $placeholder = $('#placeholder');
     var cssObj = {
         'border' : '1px solid #aaa',
         'width' : $placeholder.width(),
         'height' : $placeholder.height(),
         'float' : 'right'
     };
-    $openlayersmap.css(cssObj);
-    drawOpenLayers();
+    $('#openlayersmap').css(cssObj);
+}
 
-    $('.choice').show();
-    $('#choice').bind('click', function() {
-        if ($(this).prop('checked') == false) {
-            $placeholder.show();
-            $openlayersmap.hide();
-        } else {
-            $placeholder.hide();
-            $openlayersmap.show();
-        }
-    });
+/**
+ * Loads the SVG element and make a reference to it.
+ */
+function loadSVG() {
+    var $placeholder = $('#placeholder');
 
-    $('#placeholder').svg({
+    $placeholder.svg({
         onLoad: function(svg_ref) {
             svg = svg_ref;
         }
     });
 
-    // Removes the second SVG element unnecessarily added due to the above command.
-    $('#placeholder').find('svg:nth-child(2)').remove();
+    // Removes the second SVG element unnecessarily added due to the above command
+    $placeholder.find('svg:nth-child(2)').remove();
+}
 
+/**
+ * Adds controllers for zooming and panning.
+ */
+function addZoomPanControllers() {
+    var $placeholder = $('#placeholder');
     if ($("#placeholder svg").length > 0) {
         var pmaThemeImage = $('#pmaThemeImage').attr('value');
         // add panning arrows
@@ -113,7 +111,81 @@ $(document).ready(function() {
         $('<img class="button" id="zoom_world" src="' + pmaThemeImage + 'zoom-world-mini.png">').appendTo($placeholder);
         $('<img class="button" id="zoom_out" src="' + pmaThemeImage + 'zoom-minus-mini.png">').appendTo($placeholder);
     }
+}
 
+/**
+ * Resizes the GIS visualization to fit into the space available.
+ */
+function resizeGISVisualization() {
+    var $placeholder = $('#placeholder');
+
+    // Hide inputs for width and height
+    $("input[name='visualizationSettings[width]']").parents('tr').remove();
+    $("input[name='visualizationSettings[height]']").parents('tr').remove();
+
+    var old_width = $placeholder.width();
+    var extraPadding = 100;
+    var leftWidth = $('.gis_table').width();
+    var windowWidth = document.documentElement.clientWidth;
+    var visWidth = windowWidth - extraPadding - leftWidth;
+
+    // Assign new value for width
+    $placeholder.width(visWidth);
+    $('svg').attr('width', visWidth);
+
+    // Assign the offset created due to resizing to default_x and center the svg.
+    default_x = (visWidth - old_width) / 2;
+    x = default_x;
+}
+
+/**
+ * Initialize the GIS visualization.
+ */
+function initGISVisualization() {
+    // Loads either SVG or OSM visualization based on the choice
+    selectVisualization();
+    // Resizes the GIS visualization to fit into the space available
+    resizeGISVisualization();
+    // Adds necessary styles to the div that coontains the openStreetMap
+    styleOSM();
+    // Draws openStreetMap with openLayers
+    drawOpenLayers();
+    // Loads the SVG element and make a reference to it
+    loadSVG();
+    // Adds controllers for zooming and panning
+    addZoomPanControllers();
+    zoomAndPan();
+}
+
+/**
+ * Ajax handlers for GIS visualization page
+ *
+ * Actions Ajaxified here:
+ *
+ * Zooming in and zooming out on mousewheel movement.
+ * Panning the visualization on dragging.
+ * Zooming in on double clicking.
+ * Zooming out on clicking the zoom out button.
+ * Panning on clicking the arrow buttons.
+ * Displaying tooltips for GIS objects.
+ */
+$(document).ready(function() {
+
+    // If we are in GIS visualization, initialize it
+    if ($('.gis_table').length > 0) {
+        initGISVisualization();
+    }
+    
+    $('#choice').live('click', function() {
+        if ($(this).prop('checked') == false) {
+            $('#placeholder').show();
+            $('#openlayersmap').hide();
+        } else {
+            $('#placeholder').hide();
+            $('#openlayersmap').show();
+        }
+    });
+    
     $('#placeholder').live('mousewheel', function(event, delta) {
         if (delta > 0) {
             //zoom in
@@ -135,13 +207,13 @@ $(document).ready(function() {
 
     var dragX = 0; var dragY = 0;
     $('svg').live('dragstart', function(event, dd) {
-        $placeholder.addClass('placeholderDrag');
+        $('#placeholder').addClass('placeholderDrag');
         dragX = Math.round(dd.offsetX);
         dragY = Math.round(dd.offsetY);
     });
 
     $('svg').live('mouseup', function(event) {
-        $placeholder.removeClass('placeholderDrag');
+        $('#placeholder').removeClass('placeholderDrag');
     });
 
     $('svg').live('drag', function(event, dd) {
@@ -178,8 +250,8 @@ $(document).ready(function() {
     $('#zoom_world').live('click', function(e) {
         e.preventDefault();
         scale = 1;
-        x = 0;
-        y = 0;
+        x = default_x;
+        y = default_y;
         zoomAndPan();
     });
 
@@ -225,7 +297,7 @@ $(document).ready(function() {
      */
     $('.polygon, .multipolygon, .point, .multipoint, .linestring, .multilinestring, '
             + '.geometrycollection').live('mousemove', function(event) {
-        contents = $(this).attr('name');
+        contents = $.trim($(this).attr('name'));
         $("#tooltip").remove();
         if (contents != '') {
             $('<div id="tooltip">' + contents + '</div>').css({
diff --git a/js/tbl_select.js b/js/tbl_select.js
index af2242a..4f6ddf0 100644
--- a/js/tbl_select.js
+++ b/js/tbl_select.js
@@ -68,7 +68,7 @@ $(document).ready(function() {
                 $("#sqlqueryresults").html(response);
                 $("#sqlqueryresults").trigger('appendAnchor');
                 $('#tbl_search_form')
-                // work around for bug #3168569 - Issue on toggling the "Hide search criteria" in chrome.
+                // workaround for bug #3168569 - Issue on toggling the "Hide search criteria" in chrome.
                  .slideToggle()    
                  .hide();
                 $('#togglesearchformlink')
@@ -87,4 +87,91 @@ $(document).ready(function() {
             });
         }) // end $.post()
     })
+
+    // Following section is related to the 'function based search' for geometry data types.
+    // Initialy hide all the open_gis_editor spans
+    $('.open_search_gis_editor').hide();
+
+    $('.geom_func').bind('change', function() {
+        var $geomFuncSelector = $(this);
+
+        var binaryFunctions = [
+          'Contains',
+          'Crosses',
+          'Disjoint',
+          'Equals',
+          'Intersects',
+          'Overlaps',
+          'Touches',
+          'Within',
+          'MBRContains',
+          'MBRDisjoint',
+          'MBREquals',
+          'MBRIntersects',
+          'MBROverlaps',
+          'MBRTouches',
+          'MBRWithin',
+          'ST_Contains',
+          'ST_Crosses',
+          'ST_Disjoint',
+          'ST_Equals',
+          'ST_Intersects',
+          'ST_Overlaps',
+          'ST_Touches',
+          'ST_Within',
+        ];
+
+        var tempArray = [
+           'Envelope',
+           'EndPoint',
+           'StartPoint',
+           'ExteriorRing',
+           'Centroid',
+           'PointOnSurface'
+        ];
+        var outputGeomFunctions = binaryFunctions.concat(tempArray);
+
+        // If the chosen function takes two geomerty objects as parameters
+        var $operator = $geomFuncSelector.parents('tr').find('td:nth-child(5)').find('select');
+        if ($.inArray($geomFuncSelector.val(), binaryFunctions) >= 0){
+            $operator.attr('readonly', true);
+        } else {
+            $operator.attr('readonly', false);
+        }
+
+        // if the chosen function's output is a geometry, enable GIS editor
+        var $editorSpan = $geomFuncSelector.parents('tr').find('.open_search_gis_editor');
+        if ($.inArray($geomFuncSelector.val(), outputGeomFunctions) >= 0){
+            $editorSpan.show();
+        } else {
+            $editorSpan.hide();
+        }
+        
+    });
+
+    $('.open_search_gis_editor').live('click', function(event) {
+        event.preventDefault();
+
+        var $span = $(this);
+        // Current value
+        var value = $span.parent('td').children("input[type='text']").val();
+        // Field name
+        var field = 'Parameter';
+        // Column type
+        var geom_func = $span.parents('tr').find('.geom_func').val();
+        if (geom_func == 'Envelope') {
+            var type = 'polygon';
+        } else if (geom_func == 'ExteriorRing') {
+            var type = 'linestring';
+        } else {
+            var type = 'point';
+        }
+        // Names of input field and null checkbox
+        var input_name = $span.parent('td').children("input[type='text']").attr('name');
+        //Token
+        var token = $("input[name='token']").val();
+
+        openGISEditor(value, field, type, input_name, token);
+    });
+
 }, 'top.frame_content'); // end $(document).ready()
diff --git a/libraries/bfShapeFiles/ShapeFile.lib.php b/libraries/bfShapeFiles/ShapeFile.lib.php
new file mode 100644
index 0000000..0680708
--- /dev/null
+++ b/libraries/bfShapeFiles/ShapeFile.lib.php
@@ -0,0 +1,649 @@
+<?php
+  function loadData($type, $data) {
+    if (!$data) return $data;
+    $tmp = unpack($type, $data);
+    return current($tmp);
+  }
+
+  function swap($binValue) {
+    $result = $binValue{strlen($binValue) - 1};
+    for($i = strlen($binValue) - 2; $i >= 0 ; $i--) {
+      $result .= $binValue{$i};
+    }
+
+    return $result;
+  }
+
+  function packDouble($value, $mode = 'LE') {
+    $value = (double)$value;
+    $bin = pack("d", $value);
+
+    //We test if the conversion of an integer (1) is done as LE or BE by default
+    switch (pack ('L', 1)) {
+      case pack ('V', 1): //Little Endian
+        $result = ($mode == 'LE') ? $bin : swap($bin);
+      break;
+      case pack ('N', 1): //Big Endian
+        $result = ($mode == 'BE') ? $bin : swap($bin);
+      break;
+      default: //Some other thing, we just return false
+        $result = FALSE;
+    }
+
+    return $result;
+  }
+
+  class ShapeFile {
+    var $FileName;
+
+    var $SHPFile;
+    var $SHXFile;
+    var $DBFFile;
+
+    var $DBFHeader;
+
+    var $lastError = "";
+
+    var $boundingBox = array("xmin" => 0.0, "ymin" => 0.0, "xmax" => 0.0, "ymax" => 0.0);
+    var $fileLength = 0;
+    var $shapeType = 0;
+
+    var $records;
+
+    function ShapeFile($shapeType, $boundingBox = array("xmin" => 0.0, "ymin" => 0.0, "xmax" => 0.0, "ymax" => 0.0), $FileName = NULL) {
+      $this->shapeType = $shapeType;
+      $this->boundingBox = $boundingBox;
+      $this->FileName = $FileName;
+      $this->fileLength = 50;
+    }
+
+    function loadFromFile($FileName) {
+      $this->FileName = $FileName;
+
+      if (($this->_openSHPFile()) && ($this->_openDBFFile())) {
+        $this->_loadHeaders();
+        $this->_loadRecords();
+        $this->_closeSHPFile();
+        $this->_closeDBFFile();
+      } else {
+        return false;
+      }
+    }
+
+    function saveToFile($FileName = NULL) {
+      if ($FileName != NULL) $this->FileName = $FileName;
+
+      if (($this->_openSHPFile(TRUE)) && ($this->_openSHXFile(TRUE)) && ($this->_openDBFFile(TRUE))) {
+        $this->_saveHeaders();
+        $this->_saveRecords();
+        $this->_closeSHPFile();
+        $this->_closeSHXFile();
+        $this->_closeDBFFile();
+      } else {
+        return false;
+      }
+    }
+
+    function addRecord($record) {
+      if ((isset($this->DBFHeader)) && (is_array($this->DBFHeader))) {
+        $record->updateDBFInfo($this->DBFHeader);
+      }
+
+      $this->fileLength += ($record->getContentLength() + 4);
+      $this->records[] = $record;
+      $this->records[count($this->records) - 1]->recordNumber = count($this->records);
+
+      return (count($this->records) - 1);
+    }
+
+    function deleteRecord($index) {
+      if (isset($this->records[$index])) {
+        $this->fileLength -= ($this->records[$index]->getContentLength() + 4);
+        for ($i = $index; $i < (count($this->records) - 1); $i++) {
+          $this->records[$i] = $this->records[$i + 1];
+        }
+        unset($this->records[count($this->records) - 1]);
+        $this->_deleteRecordFromDBF($index);
+      }
+    }
+
+    function getDBFHeader() {
+      return $this->DBFHeader;
+    }
+
+    function setDBFHeader($header) {
+      $this->DBFHeader = $header;
+
+      for ($i = 0; $i < count($this->records); $i++) {
+        $this->records[$i]->updateDBFInfo($header);
+      }
+    }
+
+    function getIndexFromDBFData($field, $value) {
+      $result = -1;
+      for ($i = 0; $i < (count($this->records) - 1); $i++) {
+        if (isset($this->records[$i]->DBFData[$field]) && (strtoupper($this->records[$i]->DBFData[$field]) == strtoupper($value))) {
+          $result = $i;
+        }
+      }
+
+      return $result;
+    }
+
+    function _loadDBFHeader() {
+      $DBFFile = fopen(str_replace('.*', '.dbf', $this->FileName), 'r');
+
+      $result = array();
+      $buff32 = array();
+      $i = 1;
+      $inHeader = true;
+
+      while ($inHeader) {
+        if (!feof($DBFFile)) {
+          $buff32 = fread($DBFFile, 32);
+          if ($i > 1) {
+            if (substr($buff32, 0, 1) == chr(13)) {
+              $inHeader = false;
+            } else {
+              $pos = strpos(substr($buff32, 0, 10), chr(0));
+              $pos = ($pos == 0 ? 10 : $pos);
+
+              $fieldName = substr($buff32, 0, $pos);
+              $fieldType = substr($buff32, 11, 1);
+              $fieldLen = ord(substr($buff32, 16, 1));
+              $fieldDec = ord(substr($buff32, 17, 1));
+
+              array_push($result, array($fieldName, $fieldType, $fieldLen, $fieldDec));
+            }
+          }
+          $i++;
+        } else {
+          $inHeader = false;
+        }
+      }
+
+      fclose($DBFFile);
+      return($result);
+    }
+
+    function _deleteRecordFromDBF($index) {
+      if (@dbase_delete_record($this->DBFFile, $index)) {
+        @dbase_pack($this->DBFFile);
+      }
+    }
+
+    function _loadHeaders() {
+      fseek($this->SHPFile, 24, SEEK_SET);
+      $this->fileLength = loadData("N", fread($this->SHPFile, 4));
+
+      fseek($this->SHPFile, 32, SEEK_SET);
+      $this->shapeType = loadData("V", fread($this->SHPFile, 4));
+
+      $this->boundingBox = array();
+      $this->boundingBox["xmin"] = loadData("d", fread($this->SHPFile, 8));
+      $this->boundingBox["ymin"] = loadData("d", fread($this->SHPFile, 8));
+      $this->boundingBox["xmax"] = loadData("d", fread($this->SHPFile, 8));
+      $this->boundingBox["ymax"] = loadData("d", fread($this->SHPFile, 8));
+
+      $this->DBFHeader = $this->_loadDBFHeader();
+    }
+
+    function _saveHeaders() {
+      fwrite($this->SHPFile, pack("NNNNNN", 9994, 0, 0, 0, 0, 0));
+      fwrite($this->SHPFile, pack("N", $this->fileLength));
+      fwrite($this->SHPFile, pack("V", 1000));
+      fwrite($this->SHPFile, pack("V", $this->shapeType));
+      fwrite($this->SHPFile, packDouble($this->boundingBox['xmin']));
+      fwrite($this->SHPFile, packDouble($this->boundingBox['ymin']));
+      fwrite($this->SHPFile, packDouble($this->boundingBox['xmax']));
+      fwrite($this->SHPFile, packDouble($this->boundingBox['ymax']));
+      fwrite($this->SHPFile, pack("dddd", 0, 0, 0, 0));
+
+      fwrite($this->SHXFile, pack("NNNNNN", 9994, 0, 0, 0, 0, 0));
+      fwrite($this->SHXFile, pack("N", 50 + 4*count($this->records)));
+      fwrite($this->SHXFile, pack("V", 1000));
+      fwrite($this->SHXFile, pack("V", $this->shapeType));
+      fwrite($this->SHXFile, packDouble($this->boundingBox['xmin']));
+      fwrite($this->SHXFile, packDouble($this->boundingBox['ymin']));
+      fwrite($this->SHXFile, packDouble($this->boundingBox['xmax']));
+      fwrite($this->SHXFile, packDouble($this->boundingBox['ymax']));
+      fwrite($this->SHXFile, pack("dddd", 0, 0, 0, 0));
+    }
+
+    function _loadRecords() {
+      fseek($this->SHPFile, 100);
+      while (!feof($this->SHPFile)) {
+        $bByte = ftell($this->SHPFile);
+        $record = new ShapeRecord(-1);
+        $record->loadFromFile($this->SHPFile, $this->DBFFile);
+        $eByte = ftell($this->SHPFile);
+        if (($eByte <= $bByte) || ($record->lastError != "")) {
+          return false;
+        }
+
+        $this->records[] = $record;
+      }
+    }
+
+    function _saveRecords() {
+      if (file_exists(str_replace('.*', '.dbf', $this->FileName))) {
+        @unlink(str_replace('.*', '.dbf', $this->FileName));
+      }
+      if (!($this->DBFFile = @dbase_create(str_replace('.*', '.dbf', $this->FileName), $this->DBFHeader))) {
+        return $this->setError(sprintf("It wasn't possible to create the DBase file '%s'", str_replace('.*', '.dbf', $this->FileName)));
+      }
+
+      $offset = 50;
+      if (is_array($this->records) && (count($this->records) > 0)) {
+        reset($this->records);
+        while (list($index, $record) = each($this->records)) {
+          //Save the record to the .shp file
+          $record->saveToFile($this->SHPFile, $this->DBFFile, $index + 1);
+
+          //Save the record to the .shx file
+          fwrite($this->SHXFile, pack("N", $offset));
+          fwrite($this->SHXFile, pack("N", $record->getContentLength()));
+          $offset += (4 + $record->getContentLength());
+        }
+      }
+      @dbase_pack($this->DBFFile);
+    }
+
+    function _openSHPFile($toWrite = false) {
+      $this->SHPFile = @fopen(str_replace('.*', '.shp', $this->FileName), ($toWrite ? "wb+" : "rb"));
+      if (!$this->SHPFile) {
+        return $this->setError(sprintf("It wasn't possible to open the Shape file '%s'", str_replace('.*', '.shp', $this->FileName)));
+      }
+
+      return TRUE;
+    }
+
+    function _closeSHPFile() {
+      if ($this->SHPFile) {
+        fclose($this->SHPFile);
+        $this->SHPFile = NULL;
+      }
+    }
+
+    function _openSHXFile($toWrite = false) {
+      $this->SHXFile = @fopen(str_replace('.*', '.shx', $this->FileName), ($toWrite ? "wb+" : "rb"));
+      if (!$this->SHXFile) {
+        return $this->setError(sprintf("It wasn't possible to open the Index file '%s'", str_replace('.*', '.shx', $this->FileName)));
+      }
+
+      return TRUE;
+    }
+
+    function _closeSHXFile() {
+      if ($this->SHXFile) {
+        fclose($this->SHXFile);
+        $this->SHXFile = NULL;
+      }
+    }
+
+    function _openDBFFile($toWrite = false) {
+      $checkFunction = $toWrite ? "is_writable" : "is_readable";
+      if (($toWrite) && (!file_exists(str_replace('.*', '.dbf', $this->FileName)))) {
+        if (!@dbase_create(str_replace('.*', '.dbf', $this->FileName), $this->DBFHeader)) {
+          return $this->setError(sprintf("It wasn't possible to create the DBase file '%s'", str_replace('.*', '.dbf', $this->FileName)));
+        }
+      }
+      if ($checkFunction(str_replace('.*', '.dbf', $this->FileName))) {
+        $this->DBFFile = dbase_open(str_replace('.*', '.dbf', $this->FileName), ($toWrite ? 2 : 0));
+        if (!$this->DBFFile) {
+          return $this->setError(sprintf("It wasn't possible to open the DBase file '%s'", str_replace('.*', '.dbf', $this->FileName)));
+        }
+      } else {
+        return $this->setError(sprintf("It wasn't possible to find the DBase file '%s'", str_replace('.*', '.dbf', $this->FileName)));
+      }
+      return TRUE;
+    }
+
+    function _closeDBFFile() {
+      if ($this->DBFFile) {
+        dbase_close($this->DBFFile);
+        $this->DBFFile = NULL;
+      }
+    }
+
+    function setError($error) {
+      $this->lastError = $error;
+      return false;
+    }
+  }
+
+  class ShapeRecord {
+    var $SHPFile = NULL;
+    var $DBFFile = NULL;
+
+    var $recordNumber = NULL;
+    var $shapeType = NULL;
+
+    var $lastError = "";
+
+    var $SHPData = array();
+    var $DBFData = array();
+
+    function ShapeRecord($shapeType) {
+      $this->shapeType = $shapeType;
+    }
+
+    function loadFromFile(&$SHPFile, &$DBFFile) {
+      $this->SHPFile = $SHPFile;
+      $this->DBFFile = $DBFFile;
+      $this->_loadHeaders();
+
+      switch ($this->shapeType) {
+        case 0:
+          $this->_loadNullRecord();
+        break;
+        case 1:
+          $this->_loadPointRecord();
+        break;
+        case 3:
+          $this->_loadPolyLineRecord();
+        break;
+        case 5:
+          $this->_loadPolygonRecord();
+        break;
+        case 8:
+          $this->_loadMultiPointRecord();
+        break;
+        default:
+          $this->setError(sprintf("The Shape Type '%s' is not supported.", $this->shapeType));
+        break;
+      }
+      $this->_loadDBFData();
+    }
+
+    function saveToFile(&$SHPFile, &$DBFFile, $recordNumber) {
+      $this->SHPFile = $SHPFile;
+      $this->DBFFile = $DBFFile;
+      $this->recordNumber = $recordNumber;
+      $this->_saveHeaders();
+
+      switch ($this->shapeType) {
+        case 0:
+          $this->_saveNullRecord();
+        break;
+        case 1:
+          $this->_savePointRecord();
+        break;
+        case 3:
+          $this->_savePolyLineRecord();
+        break;
+        case 5:
+          $this->_savePolygonRecord();
+        break;
+        case 8:
+          $this->_saveMultiPointRecord();
+        break;
+        default:
+          $this->setError(sprintf("The Shape Type '%s' is not supported.", $this->shapeType));
+        break;
+      }
+      $this->_saveDBFData();
+    }
+
+    function updateDBFInfo($header) {
+      $tmp = $this->DBFData;
+      unset($this->DBFData);
+      $this->DBFData = array();
+      reset($header);
+      while (list($key, $value) = each($header)) {
+        $this->DBFData[$value[0]] = (isset($tmp[$value[0]])) ? $tmp[$value[0]] : "";
+      }
+    }
+
+    function _loadHeaders() {
+      $this->recordNumber = loadData("N", fread($this->SHPFile, 4));
+      $tmp = loadData("N", fread($this->SHPFile, 4)); //We read the length of the record
+      $this->shapeType = loadData("V", fread($this->SHPFile, 4));
+    }
+
+    function _saveHeaders() {
+      fwrite($this->SHPFile, pack("N", $this->recordNumber));
+      fwrite($this->SHPFile, pack("N", $this->getContentLength()));
+      fwrite($this->SHPFile, pack("V", $this->shapeType));
+    }
+
+    function _loadPoint() {
+      $data = array();
+
+      $data["x"] = loadData("d", fread($this->SHPFile, 8));
+      $data["y"] = loadData("d", fread($this->SHPFile, 8));
+
+      return $data;
+    }
+
+    function _savePoint($data) {
+      fwrite($this->SHPFile, packDouble($data["x"]));
+      fwrite($this->SHPFile, packDouble($data["y"]));
+    }
+
+    function _loadNullRecord() {
+      $this->SHPData = array();
+    }
+
+    function _saveNullRecord() {
+      //Don't save anything
+    }
+
+    function _loadPointRecord() {
+      $this->SHPData = $this->_loadPoint();
+    }
+
+    function _savePointRecord() {
+      $this->_savePoint($this->SHPData);
+    }
+
+    function _loadMultiPointRecord() {
+      $this->SHPData = array();
+      $this->SHPData["xmin"] = loadData("d", fread($this->SHPFile, 8));
+      $this->SHPData["ymin"] = loadData("d", fread($this->SHPFile, 8));
+      $this->SHPData["xmax"] = loadData("d", fread($this->SHPFile, 8));
+      $this->SHPData["ymax"] = loadData("d", fread($this->SHPFile, 8));
+
+      $this->SHPData["numpoints"] = loadData("V", fread($this->SHPFile, 4));
+
+      for ($i = 0; $i <= $this->SHPData["numpoints"]; $i++) {
+        $this->SHPData["points"][] = $this->_loadPoint();
+      }
+    }
+
+    function _saveMultiPointRecord() {
+      fwrite($this->SHPFile, pack("dddd", $this->SHPData["xmin"], $this->SHPData["ymin"], $this->SHPData["xmax"], $this->SHPData["ymax"]));
+
+      fwrite($this->SHPFile, pack("V", $this->SHPData["numpoints"]));
+
+      for ($i = 0; $i <= $this->SHPData["numpoints"]; $i++) {
+        $this->_savePoint($this->SHPData["points"][$i]);
+      }
+    }
+
+    function _loadPolyLineRecord() {
+      $this->SHPData = array();
+      $this->SHPData["xmin"] = loadData("d", fread($this->SHPFile, 8));
+      $this->SHPData["ymin"] = loadData("d", fread($this->SHPFile, 8));
+      $this->SHPData["xmax"] = loadData("d", fread($this->SHPFile, 8));
+      $this->SHPData["ymax"] = loadData("d", fread($this->SHPFile, 8));
+
+      $this->SHPData["numparts"]  = loadData("V", fread($this->SHPFile, 4));
+      $this->SHPData["numpoints"] = loadData("V", fread($this->SHPFile, 4));
+
+      for ($i = 0; $i < $this->SHPData["numparts"]; $i++) {
+        $this->SHPData["parts"][$i] = loadData("V", fread($this->SHPFile, 4));
+      }
+
+      $firstIndex = ftell($this->SHPFile);
+      $readPoints = 0;
+      reset($this->SHPData["parts"]);
+      while (list($partIndex, $partData) = each($this->SHPData["parts"])) {
+        if (!isset($this->SHPData["parts"][$partIndex]["points"]) || !is_array($this->SHPData["parts"][$partIndex]["points"])) {
+          $this->SHPData["parts"][$partIndex] = array();
+          $this->SHPData["parts"][$partIndex]["points"] = array();
+        }
+        while (!in_array($readPoints, $this->SHPData["parts"]) && ($readPoints < ($this->SHPData["numpoints"])) && !feof($this->SHPFile)) {
+          $this->SHPData["parts"][$partIndex]["points"][] = $this->_loadPoint();
+          $readPoints++;
+        }
+      }
+
+      fseek($this->SHPFile, $firstIndex + ($readPoints*16));
+    }
+
+    function _savePolyLineRecord() {
+      fwrite($this->SHPFile, pack("dddd", $this->SHPData["xmin"], $this->SHPData["ymin"], $this->SHPData["xmax"], $this->SHPData["ymax"]));
+
+      fwrite($this->SHPFile, pack("VV", $this->SHPData["numparts"], $this->SHPData["numpoints"]));
+
+      for ($i = 0; $i < $this->SHPData["numparts"]; $i++) {
+        fwrite($this->SHPFile, pack("V", count($this->SHPData["parts"][$i])));
+      }
+
+      reset($this->SHPData["parts"]);
+      foreach ($this->SHPData["parts"] as $partData){
+        reset($partData["points"]);
+        while (list($pointIndex, $pointData) = each($partData["points"])) {
+          $this->_savePoint($pointData);
+        }
+      }
+    }
+
+    function _loadPolygonRecord() {
+      $this->_loadPolyLineRecord();
+    }
+
+    function _savePolygonRecord() {
+      $this->_savePolyLineRecord();
+    }
+
+    function addPoint($point, $partIndex = 0) {
+      switch ($this->shapeType) {
+        case 0:
+          //Don't add anything
+        break;
+        case 1:
+          //Substitutes the value of the current point
+          $this->SHPData = $point;
+        break;
+        case 3:
+        case 5:
+          //Adds a new point to the selected part
+          if (!isset($this->SHPData["xmin"]) || ($this->SHPData["xmin"] > $point["x"])) $this->SHPData["xmin"] = $point["x"];
+          if (!isset($this->SHPData["ymin"]) || ($this->SHPData["ymin"] > $point["y"])) $this->SHPData["ymin"] = $point["y"];
+          if (!isset($this->SHPData["xmax"]) || ($this->SHPData["xmax"] < $point["x"])) $this->SHPData["xmax"] = $point["x"];
+          if (!isset($this->SHPData["ymax"]) || ($this->SHPData["ymax"] < $point["y"])) $this->SHPData["ymax"] = $point["y"];
+
+          $this->SHPData["parts"][$partIndex]["points"][] = $point;
+
+          $this->SHPData["numparts"] = count($this->SHPData["parts"]);
+          $this->SHPData["numpoints"]++;
+        break;
+        case 8:
+          //Adds a new point
+          if (!isset($this->SHPData["xmin"]) || ($thi PData["parts"]);  < $point["y"])) $this->SHPData["ymax"] = $point["y"];  a["ymax"]));  try"); ?>" />   __('Add a polygon') ?>">   ring') ?>"><br/>  >  y']) ? htmlspecialchars($gis_data[$a][$type][$k][$i][$j]['y']) : ''); ?>" />  /pma/Charts#Data_formats_for_query_results_chart">wiki</a>.</p>            ’"NÂ+          †@NÂ+  °CDxÿ  `"NÂ+  ïCDxÿ         ÀïÎÃ+  u*NÂ+   àÎÃ+  ØäÎÃ+  ¨éÎÃ+  €JOÂ+          xôjÃ+          :Dxÿ          à8Dxÿ  k at NÂ+  à!     à!     °CDxÿ   DDxÿ  H¾JÃ+          ð:Dxÿ         ’"NÂ+          †@NÂ+  °CDxÿ  `"NÂ+  ïCDxÿ  àCDxÿ  ØCDxÿ  8KoÂ+  Œp˜         DDxÿ  u*NÂ+  €JOÂ+                  ð:Dxÿ         À9Dxÿ  k at NÂ+          G       H   I       J   K           M   N   O       P   °CDxÿ   DDxÿ  Hu!Ã+          <Dxÿ         ’"NÂ+          †@NÂ+  °CDxÿ         0ïÎÃ+  u*NÂ+    kÃ+   ©þÂ+   àÎÃ+  ØäÎÃ+  ¨éÎÃ+  €JOÂ+          Hu!Ã+          <Dxÿ         Ð:Dxÿ  k at NÂ+  8u!Ã+          <Dxÿ          ;Dxÿ  k at NÂ+  (u!Ã+          <Dxÿ         0;Dxÿ  k at NÂ+  u!Ã+          <Dxÿ         `;Dxÿ  k at NÂ+  	       ¨îÎÃ+  u*NÂ+         ¨éÎÃ+  à5Dxÿ          ŠøþÂ+  e)NÂ+         ØäÎÃ+   <Dxÿ          yøþÂ+  e)NÂ+          àÎÃ+  0<Dxÿ          ZøþÂ+  e)NÂ+  ؤþÂ+    kÃ+   ©þÂ+   àÎÃ+  ØkÃ+  ØäÎÃ+  ¨éÎÃ+  €JOÂ+          8KoÂ+                        mÊÂ+   DDxÿ  p;þÂ+          à=Dxÿ          °<Dxÿ  k at NÂ+      5   6   7   8   :   <   =   >       ?       @   B   D       °CDxÿ   DDxÿ  àmÇÂ+                  DDxÿ  u*NÂ+         EoÂ+  `<Dxÿ          mÊÂ+  e)NÂ+  EoÂ+          Õ_ at fÆS         Qöl±íÁƒ–Â+   DDxÿ  àmÇÂ+          ð>Dxÿ         À=Dxÿ  k at NÂ+  u]ÞÓ	4Q ÷U^Qʉ§ ¶uª¹ñìò*Ä“v°CDxÿ   DDxÿ  H¾“Â+          ÐÂ+          `EDxÿ  ¦2Ä+  ¦2Ä+         VÍÂ+  ïCDxÿ   EDxÿ  ØCDxÿ  @@Dxÿ  kÃ+  u*NÂ+  ØkÃ+   FDxÿ  ¢2Ä+  pEDxÿ           ADxÿ                 ÿÿÿÿÿÿÿÿ¢2Ä+          (DDxÿ                 s->SHPData["xmin"] > $point["x"])) $this->SHPData["xmin"] = $point["x"];
+          if (!isset($this->SHPData["ymin"]) || ($this->SHPData["ymin"] > $point["y"])) $this->SHPData["ymin"] = $point["y"];
+          if (!isset($this->SHPData["xmax"]) || ($this->SHPData["xmax"] < $point["x"])) $this->SHPData["xmax"] = $point["x"];
+          if (!isset($this->SHPData["ymax"]) || ($this->SHPData["ymax"] < $point["y"])) $this->SHPData["ymax"] = $point["y"];
+
+          $this->SHPData["points"][] = $point;
+          $this->SHPData["numpoints"]++;
+        break;
+        default:
+          $this->setError(sprintf("The Shape Type '%s' is not supported.", $this->shapeType));
+        break;
+      }
+    }
+
+    function deletePoint($pointIndex = 0, $partIndex = 0) {
+      switch ($this->shapeType) {
+        case 0:
+          //Don't delete anything
+        break;
+        case 1:
+          //Sets the value of the point to zero
+          $this->SHPData["x"] = 0.0;
+          $this->SHPData["y"] = 0.0;
+        break;
+        case 3:
+        case 5:
+          //Deletes the point from the selected part, if exists
+          if (isset($this->SHPData["parts"][$partIndex]) && isset($this->SHPData["parts"][$partIndex]["points"][$pointIndex])) {
+            for ($i = $pointIndex; $i < (count($this->SHPData["parts"][$partIndex]["points"]) - 1); $i++) {
+              $this->SHPData["parts"][$partIndex]["points"][$i] = $this->SHPData["parts"][$partIndex]["points"][$i + 1];
+            }
+            unset($this->SHPData["parts"][$partIndex]["points"][count($this->SHPData["parts"][$partIndex]["points"]) - 1]);
+
+            $this->SHPData["numparts"] = count($this->SHPData["parts"]);
+            $this->SHPData["numpoints"]--;
+          }
+        break;
+        case 8:
+          //Deletes the point, if exists
+          if (isset($this->SHPData["points"][$pointIndex])) {
+            for ($i = $pointIndex; $i < (count($this->SHPData["points"]) - 1); $i++) {
+              $this->SHPData["points"][$i] = $this->SHPData["points"][$i + 1];
+            }
+            unset($this->SHPData["points"][count($this->SHPData["points"]) - 1]);
+
+            $this->SHPData["numpoints"]--;
+          }
+        break;
+        default:
+          $this->setError(sprintf("The Shape Type '%s' is not supported.", $this->shapeType));
+        break;
+      }
+    }
+
+    function getContentLength() {
+      switch ($this->shapeType) {
+        case 0:
+          $result = 0;
+        break;
+        case 1:
+          $result = 10;
+        break;
+        case 3:
+        case 5:
+          $result = 22 + 2*count($this->SHPData["parts"]);
+          for ($i = 0; $i < count($this->SHPData["parts"]); $i++) {
+            $result += 8*count($this->SHPData["parts"][$i]["points"]);
+          }
+        break;
+        case 8:
+          $result = 20 + 8*count($this->SHPData["points"]);
+        break;
+        default:
+          $result = false;
+          $this->setError(sprintf("The Shape Type '%s' is not supported.", $this->shapeType));
+        break;
+      }
+      return $result;
+    }
+
+    function _loadDBFData() {
+      $this->DBFData = @dbase_get_record_with_names($this->DBFFile, $this->recordNumber);
+      unset($this->DBFData["deleted"]);
+    }
+
+    function _saveDBFData() {
+      unset($this->DBFData["deleted"]);
+      if ($this->recordNumber <= dbase_numrecords($this->DBFFile)) {
+        if (!dbase_replace_record($this->DBFFile, array_values($this->DBFData), $this->recordNumber)) {
+          $this->setError("I wasn't possible to update the information in the DBF file.");
+        }
+      } else {
+        if (!dbase_add_record($this->DBFFile, array_values($this->DBFData))) {
+          $this->setError("I wasn't possible to add the information to the DBF file.");
+        }
+      }
+    }
+
+    function setError($error) {
+      $this->lastError = $error;
+      return false;
+    }
+  }
+
+?>
diff --git a/libraries/common.lib.php b/libraries/common.lib.php
index 0b89345..f232b98 100644
--- a/libraries/common.lib.php
+++ b/libraries/common.lib.php
@@ -2073,6 +2073,13 @@ function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force
                     // this blob won't be part of the final condition
                     $con_val = null;
                 }
+            } elseif (in_array($meta->type, PMA_getGISDatatypes()) && ! empty($row[$i])) {
+                // do not build a too big condition
+                if (strlen($row[$i]) < 5000) {
+                    $condition .= '=0x' . bin2hex($row[$i]) . ' AND';
+                } else {
+                    $condition = '';
+                }
             } elseif ($meta->type == 'bit') {
                 $con_val = "= b'" . PMA_printable_bit_value($row[$i], $meta->length) . "'";
             } else {
@@ -2855,6 +2862,31 @@ function PMA_replace_binary_contents($content)
 }
 
 /**
+ * Converts GIS data to Well Known Text format
+ *
+ * @param  $data     GIS data
+ * @param  $includeSRID  Add SRID to the WKT
+ * @return GIS data in Well Know Text format
+ */
+function PMA_asWKT($data, $includeSRID = false) {
+    // Convert to WKT format
+    $hex = bin2hex($data);
+    $wktsql     = "SELECT ASTEXT(x'" . $hex . "')";
+    if ($includeSRID) {
+        $wktsql .= ", SRID(x'" . $hex . "')";
+    }
+    $wktresult  = PMA_DBI_try_query($wktsql, null, PMA_DBI_QUERY_STORE);
+    $wktarr     = PMA_DBI_fetch_row($wktresult, 0);
+    $wktval     = $wktarr[0];
+    if ($includeSRID) {
+        $srid = $wktarr[1];
+        $wktval = "'" . $wktval . "'," . $srid;
+    }
+    @PMA_DBI_free_result($wktresult);
+    return $wktval;
+}
+
+/**
  * If the string starts with a \r\n pair (0x0d0a) add an extra \n
  *
  * @param string $string
@@ -3166,22 +3198,157 @@ function PMA_getSupportedDatatypes($html = false, $selected = '')
  * @return   array   list of datatypes
  */
 
-function PMA_unsupportedDatatypes()
-{
-    // These GIS data types are not yet supported.
-    $no_support_types = array('geometry',
-                              'point',
-                              'linestring',
-                              'polygon',
-                              'multipoint',
-                              'multilinestring',
-                              'multipolygon',
-                              'geometrycollection'
-                        );
-
+function PMA_unsupportedDatatypes() {
+    $no_support_types = array();
     return $no_support_types;
 }
 
+function PMA_getGISDatatypes($upper_case = false) {
+    $gis_data_types = array('geometry',
+                            'point',
+                            'linestring',
+                            'polygon',
+                            'multipoint',
+                            'multilinestring',
+                            'multipolygon',
+                            'geometrycollection'
+                      );
+    if ($upper_case) {
+        for ($i = 0; $i < count($gis_data_types); $i++) {
+            $gis_data_types[$i] = strtoupper($gis_data_types[$i]);
+        }
+    }
+
+    return $gis_data_types;
+}
+
+/**
+ * Generates GIS data based on the string passed.
+ *
+ * @param string $gis_string GIS string
+ */
+function PMA_createGISData($gis_string) {
+    $gis_string =  trim($gis_string);
+    $geom_types = '(POINT|MULTIPOINT|LINESTRING|MULTILINESTRING|POLYGON|MULTIPOLYGON|GEOMETRYCOLLECTION)';
+    if (preg_match("/^'" . $geom_types . "\(.*\)',[0-9]*$/i", $gis_string)) {
+        return 'GeomFromText(' . $gis_string . ')';
+    } elseif (preg_match("/^" . $geom_types . "\(.*\)$/i", $gis_string)) {
+        return "GeomFromText('" . $gis_string . "')";
+    } else {
+        return $gis_string;
+    }
+}
+
+/**
+ * Returns the names and details of the functions
+ * that can be applied on geometry data typess.
+ *
+ * @param string $geom_type if provided the output is limited to the functions
+ *                          that are applicable to the provided geometry type.
+ * @param bool   $binary    if set to false functions that take two geometries
+ *                          as arguments will not be included.
+ * @param bool   $display   if set to true seperators will be added to the
+ *                          output array.
+ *
+ * @return array names and details of the functions that can be applied on
+ *               geometry data typess.
+ */
+function PMA_getGISFunctions($geom_type = null, $binary = true, $display = false) {
+
+    $funcs = array();
+    if ($display) {
+        $funcs[] = array('display' => ' ');
+    }
+
+    // Unary functions common to all geomety types
+    $funcs['Dimension']    = array('params' => 1, 'type' => 'int');
+    $funcs['Envelope']     = array('params' => 1, 'type' => 'Polygon');
+    $funcs['GeometryType'] = array('params' => 1, 'type' => 'text');
+    $funcs['SRID']         = array('params' => 1, 'type' => 'int');
+    $funcs['IsEmpty']      = array('params' => 1, 'type' => 'int');
+    $funcs['IsSimple']     = array('params' => 1, 'type' => 'int');
+
+    $geom_type = trim(strtolower($geom_type));
+    if ($display && $geom_type != 'geometry' && $geom_type != 'multipoint') {
+        $funcs[] = array('display' => '--------');
+    }
+
+    // Unary functions that are specific to each geomety type
+    if ($geom_type == 'point') {
+        $funcs['X'] = array('params' => 1, 'type' => 'float');
+        $funcs['Y'] = array('params' => 1, 'type' => 'float');
+
+    } elseif ($geom_type == 'multipoint') {
+        // no fucntions here
+    } elseif ($geom_type == 'linestring') {
+        $funcs['EndPoint']   = array('params' => 1, 'type' => 'point');
+        $funcs['GLength']    = array('params' => 1, 'type' => 'float');
+        $funcs['NumPoints']  = array('params' => 1, 'type' => 'int');
+        $funcs['StartPoint'] = array('params' => 1, 'type' => 'point');
+        $funcs['IsRing']     = array('params' => 1, 'type' => 'int');
+
+    } elseif ($geom_type == 'multilinestring') {
+        $funcs['GLength']  = array('params' => 1, 'type' => 'float');
+        $funcs['IsClosed'] = array('params' => 1, 'type' => 'int');
+
+    } elseif ($geom_type == 'polygon') {
+        $funcs['Area']             = array('params' => 1, 'type' => 'float');
+        $funcs['ExteriorRing']     = array('params' => 1, 'type' => 'linestring');
+        $funcs['NumInteriorRings'] = array('params' => 1, 'type' => 'int');
+
+    } elseif ($geom_type == 'multipolygon') {
+        $funcs['Area']     = array('params' => 1, 'type' => 'float');
+        $funcs['Centroid'] = array('params' => 1, 'type' => 'point');
+        // Not yet implemented in MySQL
+        //$funcs['PointOnSurface'] = array('params' => 1, 'type' => 'point');
+
+    } elseif ($geom_type == 'geometrycollection') {
+        $funcs['NumGeometries'] = array('params' => 1, 'type' => 'int');
+    }
+
+    // If we are asked for binary functions as well
+    if ($binary) {
+        // section seperator
+        if ($display) {
+            $funcs[] = array('display' => '--------');
+        }
+        if (PMA_MYSQL_INT_VERSION < 50601) {
+            $funcs['Crosses']    = array('params' => 2, 'type' => 'int');
+            $funcs['Contains']   = array('params' => 2, 'type' => 'int');
+            $funcs['Disjoint']   = array('params' => 2, 'type' => 'int');
+            $funcs['Equals']     = array('params' => 2, 'type' => 'int');
+            $funcs['Intersects'] = array('params' => 2, 'type' => 'int');
+            $funcs['Overlaps']   = array('params' => 2, 'type' => 'int');
+            $funcs['Touches']    = array('params' => 2, 'type' => 'int');
+            $funcs['Within']     = array('params' => 2, 'type' => 'int');
+        } else {
+            // If MySQl version is greaeter than or equal 5.6.1, use the ST_ prefix.
+            $funcs['ST_Crosses']    = array('params' => 2, 'type' => 'int');
+            $funcs['ST_Contains']   = array('params' => 2, 'type' => 'int');
+            $funcs['ST_Disjoint']   = array('params' => 2, 'type' => 'int');
+            $funcs['ST_Equals']     = array('params' => 2, 'type' => 'int');
+            $funcs['ST_Intersects'] = array('params' => 2, 'type' => 'int');
+            $funcs['ST_Overlaps']   = array('params' => 2, 'type' => 'int');
+            $funcs['ST_Touches']    = array('params' => 2, 'type' => 'int');
+            $funcs['ST_Within']     = array('params' => 2, 'type' => 'int');
+
+        }
+
+        if ($display) {
+            $funcs[] = array('display' => '--------');
+        }
+        // Minimum bounding rectangle functions
+        $funcs['MBRContains']   = array('params' => 2, 'type' => 'int');
+        $funcs['MBRDisjoint']   = array('params' => 2, 'type' => 'int');
+        $funcs['MBREquals']     = array('params' => 2, 'type' => 'int');
+        $funcs['MBRIntersects'] = array('params' => 2, 'type' => 'int');
+        $funcs['MBROverlaps']   = array('params' => 2, 'type' => 'int');
+        $funcs['MBRTouches']    = array('params' => 2, 'type' => 'int');
+        $funcs['MBRWithin']     = array('params' => 2, 'type' => 'int');
+    }
+    return $funcs;
+}
+
 /**
  * Creates a dropdown box with MySQL functions for a particular column.
  *
diff --git a/libraries/config.default.php b/libraries/config.default.php
index c40e784..9dea34a 100644
--- a/libraries/config.default.php
+++ b/libraries/config.default.php
@@ -2806,6 +2806,7 @@ if ($cfg['ShowFunctionFields']) {
         'FUNC_CHAR' => '',
         'FUNC_DATE' => '',
         'FUNC_NUMBER' => '',
+        'FUNC_SPATIAL' => 'GeomFromText',
         'first_timestamp' => 'NOW',
         'pk_char36' => 'UUID',
     );
diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php
index 4baa65f..ddcfb7a 100644
--- a/libraries/display_tbl.lib.php
+++ b/libraries/display_tbl.lib.php
@@ -1555,65 +1555,67 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql)
                 // Remove 'grid_edit' from $class as we do not allow to inline-edit geometry data.
                 $class = str_replace('grid_edit', '', $class);
 
-                // Display as [GEOMETRY - (size)]
-                if ('GEOM' == $_SESSION['tmp_user_values']['geometry_display']) {
-                    $geometry_text = PMA_handle_non_printable_contents(
-                        'GEOMETRY', (isset($row[$i]) ? $row[$i] : ''), $transform_function,
-                        $transform_options, $default_function, $meta
-                    );
-                    $vertical_display['data'][$row_no][$i] = PMA_buildValueDisplay(
-                        $class, $condition_field, $geometry_text
-                    );
-
-                // Display in Well Known Text(WKT) format.
-                } elseif ('WKT' == $_SESSION['tmp_user_values']['geometry_display']) {
-                    // Convert to WKT format
-                    $wktsql     = "SELECT ASTEXT (GeomFromWKB(x'" . PMA_substr(bin2hex($row[$i]), 8) . "'))";
-                    $wktresult  = PMA_DBI_try_query($wktsql, null, PMA_DBI_QUERY_STORE);
-                    $wktarr     = PMA_DBI_fetch_row($wktresult, 0);
-                    $wktval     = $wktarr[0];
-                    @PMA_DBI_free_result($wktresult);
-
-                    if (PMA_strlen($wktval) > $GLOBALS['cfg']['LimitChars']
-                        && $_SESSION['tmp_user_values']['display_text'] == 'P'
-                    ) {
-                        $wktval = PMA_substr($wktval, 0, $GLOBALS['cfg']['LimitChars']) . '...';
-                        $is_field_truncated = true;
-                    }
-
-                    $vertical_display['data'][$row_no][$i] = '<td ' . PMA_prepare_row_data(
-                        $class, $condition_field, $analyzed_sql, $meta, $map, $wktval, $transform_function,
-                        $default_function, $nowrap, $where_comparison, $transform_options, $is_field_truncated
-                    );
+                if (! isset($row[$i]) || is_null($row[$i])) {
+                    $vertical_display['data'][$row_no][$i] = PMA_buildNullDisplay($class, $condition_field);
+                } elseif ($row[$i] != '') {
+                    // Display as [GEOMETRY - (size)]
+                    if ('GEOM' == $_SESSION['tmp_user_values']['geometry_display']) {
+                        $geometry_text = PMA_handle_non_printable_contents(
+                            'GEOMETRY', (isset($row[$i]) ? $row[$i] : ''), $transform_function,
+                            $transform_options, $default_function, $meta
+                        );
+                        $vertical_display['data'][$row_no][$i] = PMA_buildValueDisplay(
+                            $class, $condition_field, $geometry_text
+                        );
 
-                // Display in  Well Known Binary(WKB) format.
-                } else {
-                    if ($_SESSION['tmp_user_values']['display_binary']) {
-                        if ($_SESSION['tmp_user_values']['display_binary_as_hex']
-                            && PMA_contains_nonprintable_ascii($row[$i])
-                        ) {
-                            $wkbval = PMA_substr(bin2hex($row[$i]), 8);
-                        } else {
-                            $wkbval = htmlspecialchars(PMA_replace_binary_contents($row[$i]));
-                        }
+                    // Display in Well Known Text(WKT) format.
+                    } elseif ('WKT' == $_SESSION['tmp_user_values']['geometry_display']) {
+                        // Convert to WKT format
+                        $wktval = PMA_asWKT($row[$i]);
 
-                        if (PMA_strlen($wkbval) > $GLOBALS['cfg']['LimitChars']
+                        if (PMA_strlen($wktval) > $GLOBALS['cfg']['LimitChars']
                             && $_SESSION['tmp_user_values']['display_text'] == 'P'
                         ) {
-                            $wkbval = PMA_substr($wkbval, 0, $GLOBALS['cfg']['LimitChars']) . '...';
+                            $wktval = PMA_substr($wktval, 0, $GLOBALS['cfg']['LimitChars']) . '...';
                             $is_field_truncated = true;
                         }
 
                         $vertical_display['data'][$row_no][$i] = '<td ' . PMA_prepare_row_data(
-                            $class, $condition_field, $analyzed_sql, $meta, $map, $wkbval, $transform_function,
+                            $class, $condition_field, $analyzed_sql, $meta, $map, $wktval, $transform_function,
                             $default_function, $nowrap, $where_comparison, $transform_options, $is_field_truncated
                         );
+
+                    // Display in  Well Known Binary(WKB) format.
                     } else {
-                        $wkbval = PMA_handle_non_printable_contents(
-                            'BINARY', $row[$i], $transform_function, $transform_options, $default_function, $meta, $_url_params
-                        );
-                        $vertical_display['data'][$row_no][$i] = PMA_buildValueDisplay($class, $condition_field, $wkbval);
+                        if ($_SESSION['tmp_user_values']['display_binary']) {
+                            if ($_SESSION['tmp_user_values']['display_binary_as_hex']
+                                && PMA_contains_nonprintable_ascii($row[$i])
+                            ) {
+                                $wkbval = PMA_substr(bin2hex($row[$i]), 8);
+                            } else {
+                                $wkbval = htmlspecialchars(PMA_replace_binary_contents($row[$i]));
+                            }
+
+                            if (PMA_strlen($wkbval) > $GLOBALS['cfg']['LimitChars']
+                                && $_SESSION['tmp_user_values']['display_text'] == 'P'
+                            ) {
+                                $wkbval = PMA_substr($wkbval, 0, $GLOBALS['cfg']['LimitChars']) . '...';
+                                $is_field_truncated = true;
+                            }
+
+                            $vertical_display['data'][$row_no][$i] = '<td ' . PMA_prepare_row_data(
+                                $class, $condition_field, $analyzed_sql, $meta, $map, $wkbval, $transform_function,
+                                $default_function, $nowrap, $where_comparison, $transform_options, $is_field_truncated
+                            );
+                        } else {
+                            $wkbval = PMA_handle_non_printable_contents(
+                                'BINARY', $row[$i], $transform_function, $transform_options, $default_function, $meta, $_url_params
+                            );
+                            $vertical_display['data'][$row_no][$i] = PMA_buildValueDisplay($class, $condition_field, $wkbval);
+                        }
                     }
+                } else {
+                    $vertical_display['data'][$row_no][$i] = PMA_buildEmptyDisplay($class, $condition_field, $meta);
                 }
 
             // n o t   n u m e r i c   a n d   n o t   B L O B
diff --git a/libraries/gis/pma_gis_factory.php b/libraries/gis/pma_gis_factory.php
index 73e6c4c..f6f7232 100644
--- a/libraries/gis/pma_gis_factory.php
+++ b/libraries/gis/pma_gis_factory.php
@@ -20,6 +20,9 @@ class PMA_GIS_Factory
         include_once './libraries/gis/pma_gis_geometry.php';
 
         $type_lower = strtolower($type);
+        if (! file_exists('./libraries/gis/pma_gis_' . $type_lower . '.php')) {
+            return false;
+        }
         if (include_once './libraries/gis/pma_gis_' . $type_lower . '.php') {
             switch($type) {
             case 'MULTIPOLYGON' :
@@ -37,10 +40,10 @@ class PMA_GIS_Factory
             case 'GEOMETRYCOLLECTION' :
                 return PMA_GIS_Geometrycollection::singleton();
             default :
-                throw new Exception('Unknown GIS data type');
+                return false;
             }
         } else {
-            throw new Exception('File not found');
+            return false;
         }
     }
 }
diff --git a/libraries/gis/pma_gis_geometry.php b/libraries/gis/pma_gis_geometry.php
index 787eaf3..c49c1a1 100644
--- a/libraries/gis/pma_gis_geometry.php
+++ b/libraries/gis/pma_gis_geometry.php
@@ -68,6 +68,17 @@ abstract class PMA_GIS_Geometry
     public abstract function scaleRow($spatial);
 
     /**
+     * Generate the WKT with the set of parameters passed by the GIS editor.
+     *
+     * @param array  $gis_data GIS data
+     * @param int    $index    Index into the parameter object
+     * @param string $empty    Value for empty points
+     *
+     * @return WKT with the set of parameters passed by the GIS editor
+     */
+    public abstract function generateWkt($gis_data, $index, $empty);
+
+    /**
      * Returns OpenLayers.Bounds object that correspond to the bounds of GIS data.
      *
      * @param string $srid       Spatial reference ID
@@ -122,6 +133,30 @@ abstract class PMA_GIS_Geometry
     }
 
     /**
+     * Generate parameters for the GIS data editor from the value of the GIS column.
+     * This method performs common work.
+     * More specific work is performed by each of the geom classes.
+     *
+     * @param $gis_string $value of the GIS column
+     *
+     * @return array parameters for the GIS editor from the value of the GIS column
+     */
+    protected function generateParams($value)
+    {
+        $geom_types = '(POINT|MULTIPOINT|LINESTRING|MULTILINESTRING|POLYGON|MULTIPOLYGON|GEOMETRYCOLLECTION)';
+        $srid = 0;
+        $wkt = '';
+        if (preg_match("/^'" . $geom_types . "\(.*\)',[0-9]*$/i", $value)) {
+            $last_comma = strripos($value, ",");
+            $srid = trim(substr($value, $last_comma + 1));
+            $wkt = trim(substr($value, 1, $last_comma - 2));
+        } elseif (preg_match("/^" . $geom_types . "\(.*\)$/i", $value)) {
+            $wkt = $value;
+        }
+        return array('srid' => $srid, 'wkt' => $wkt);
+    }
+
+    /**
      * Extracts points, scales and returns them as an array.
      *
      * @param string  $point_set  String of comma sperated points
@@ -141,14 +176,22 @@ abstract class PMA_GIS_Geometry
             // Extract cordinates of the point
             $cordinates = explode(" ", $point);
 
-            if ($scale_data != null) {
-                $x = ($cordinates[0] - $scale_data['x']) * $scale_data['scale'];
-                $y = $scale_data['height'] - ($cordinates[1] - $scale_data['y']) * $scale_data['scale'];
+            if (isset($cordinates[0]) && trim($cordinates[0]) != ''
+                && isset($cordinates[1]) && trim($cordinates[1]) != ''
+            ) {
+                if ($scale_data != null) {
+                    $x = ($cordinates[0] - $scale_data['x']) * $scale_data['scale'];
+                    $y = $scale_data['height'] - ($cordinates[1] - $scale_data['y']) * $scale_data['scale'];
+                } else {
+                    $x = trim($cordinates[0]);
+                    $y = trim($cordinates[1]);
+                }
             } else {
-                $x = $cordinates[0];
-                $y = $cordinates[1];
+                $x = '';
+                $y = '';
             }
 
+
             if (! $linear) {
                 $points_arr[] = array($x, $y);
             } else {
diff --git a/libraries/gis/pma_gis_geometrycollection.php b/libraries/gis/pma_gis_geometrycollection.php
index a3da6bf..96074d5 100644
--- a/libraries/gis/pma_gis_geometrycollection.php
+++ b/libraries/gis/pma_gis_geometrycollection.php
@@ -53,6 +53,9 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry
             $type = substr($sub_part, 0, $type_pos);
 
             $gis_obj = PMA_GIS_Factory::factory($type);
+            if (! $gis_obj) {
+                continue;
+            }
             $scale_data = $gis_obj->scaleRow($sub_part);
 
             // Upadate minimum/maximum values for x and y cordinates.
@@ -102,6 +105,9 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry
             $type = substr($sub_part, 0, $type_pos);
 
             $gis_obj = PMA_GIS_Factory::factory($type);
+            if (! $gis_obj) {
+                continue;
+            }
             $image = $gis_obj->prepareRowAsPng($sub_part, $label, $color, $scale_data, $image);
         }
         return $image;
@@ -130,6 +136,9 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry
             $type = substr($sub_part, 0, $type_pos);
 
             $gis_obj = PMA_GIS_Factory::factory($type);
+            if (! $gis_obj) {
+                continue;
+            }
             $pdf = $gis_obj->prepareRowAsPdf($sub_part, $label, $color, $scale_data, $pdf);
         }
         return $pdf;
@@ -159,6 +168,9 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry
             $type = substr($sub_part, 0, $type_pos);
 
             $gis_obj = PMA_GIS_Factory::factory($type);
+            if (! $gis_obj) {
+                continue;
+            }
             $row .= $gis_obj->prepareRowAsSvg($sub_part, $label, $color, $scale_data);
         }
         return $row;
@@ -190,6 +202,9 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry
             $type = substr($sub_part, 0, $type_pos);
 
             $gis_obj = PMA_GIS_Factory::factory($type);
+            if (! $gis_obj) {
+                continue;
+            }
             $row .= $gis_obj->prepareRowAsOl($sub_part, $srid, $label, $color, $scale_data);
         }
         return $row;
@@ -222,5 +237,71 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry
         }
         return $sub_parts;
     }
+
+    /**
+     * Generate the WKT with the set of parameters passed by the GIS editor.
+     *
+     * @param array  $gis_data GIS data
+     * @param int    $index    Index into the parameter object
+     * @param string $empty    Value for empty points
+     *
+     * @return WKT with the set of parameters passed by the GIS editor
+     */
+    public function generateWkt($gis_data, $index, $empty = '')
+    {
+        $geom_count = (isset($gis_data['GEOMETRYCOLLECTION']['geom_count']))
+            ? $gis_data['GEOMETRYCOLLECTION']['geom_count'] : 1;
+        $wkt = 'GEOMETRYCOLLECTION(';
+        for ($i = 0; $i < $geom_count; $i++) {
+            if (isset($gis_data[$i]['gis_type'])) {
+                $type = $gis_data[$i]['gis_type'];
+                $gis_obj = PMA_GIS_Factory::factory($type);
+                if (! $gis_obj) {
+                    continue;
+                }
+                $wkt .= $gis_obj->generateWkt($gis_data, $i, $empty) . ',';
+            }
+        }
+        if (isset($gis_data[0]['gis_type'])) {
+            $wkt = substr($wkt, 0, strlen($wkt) - 1);
+        }
+        $wkt .= ')';
+        return $wkt;
+    }
+
+    /** Generate parameters for the GIS data editor from the value of the GIS column.
+     *
+     * @param string $value of the GIS column
+     * @param index  $index of the geometry
+     *
+     * @return  parameters for the GIS data editor from the value of the GIS column
+     */
+    public function generateParams($value)
+    {
+        $params = array();
+        $data = PMA_GIS_Geometry::generateParams($value);
+        $params['srid'] = $data['srid'];
+        $wkt = $data['wkt'];
+
+        // Trim to remove leading 'GEOMETRYCOLLECTION(' and trailing ')'
+        $goem_col = substr($wkt, 19, (strlen($wkt) - 20));
+        // Split the geometry collection object to get its constituents.
+        $sub_parts = $this->_explodeGeomCol($goem_col);
+        $params['GEOMETRYCOLLECTION']['geom_count'] = count($sub_parts);
+
+        $i = 0;
+        foreach ($sub_parts as $sub_part) {
+            $type_pos = stripos($sub_part, '(');
+            $type = substr($sub_part, 0, $type_pos);
+
+            $gis_obj = PMA_GIS_Factory::factory($type);
+            if (! $gis_obj) {
+                continue;
+            }
+            $params = array_merge($params, $gis_obj->generateParams($sub_part, $i));
+            $i++;
+        }
+        return $params;
+    }
 }
 ?>
diff --git a/libraries/gis/pma_gis_linestring.php b/libraries/gis/pma_gis_linestring.php
index 97113b7..fc36b22 100644
--- a/libraries/gis/pma_gis_linestring.php
+++ b/libraries/gis/pma_gis_linestring.php
@@ -59,6 +59,7 @@ class PMA_GIS_Linestring extends PMA_GIS_Geometry
     public function prepareRowAsPng($spatial, $label, $line_color, $scale_data, $image)
     {
         // allocate colors
+        $black = imagecolorallocate($image, 0, 0, 0);
         $red   = hexdec(substr($line_color, 1, 2));
         $green = hexdec(substr($line_color, 3, 2));
         $blue  = hexdec(substr($line_color, 4, 2));
@@ -77,6 +78,10 @@ class PMA_GIS_Linestring extends PMA_GIS_Geometry
                 $temp_point = $point;
             }
         }
+        // print label if applicable
+        if (isset($label) && trim($label) != '') {
+            imagestring($image, 1, $points_arr[1][0], $points_arr[1][1], trim($label), $black);
+        }
         return $image;
     }
 
@@ -112,6 +117,12 @@ class PMA_GIS_Linestring extends PMA_GIS_Geometry
                 $temp_point = $point;
             }
         }
+        // print label
+        if (isset($label) && trim($label) != '') {
+            $pdf->SetXY($points_arr[1][0], $points_arr[1][1]);
+            $pdf->SetFontSize(5);
+            $pdf->Cell(0, 0, trim($label));
+        }
         return $pdf;
     }
 
@@ -196,5 +207,70 @@ class PMA_GIS_Linestring extends PMA_GIS_Geometry
             . json_encode($style_options) . '));';
         return $result;
     }
+
+    /**
+     * Generate the WKT with the set of parameters passed by the GIS editor.
+     *
+     * @param array  $gis_data GIS data
+     * @param int    $index    Index into the parameter object
+     * @param string $empty    Value for empty points
+     *
+     * @return WKT with the set of parameters passed by the GIS editor
+     */
+    public function generateWkt($gis_data, $index, $empty = '')
+    {
+        $no_of_points = isset($gis_data[$index]['LINESTRING']['no_of_points'])
+            ? $gis_data[$index]['LINESTRING']['no_of_points'] : 2;
+        if ($no_of_points < 2) {
+            $no_of_points = 2;
+        }
+        $wkt = 'LINESTRING(';
+        for ($i = 0; $i < $no_of_points; $i++) {
+            $wkt .= ((isset($gis_data[$index]['LINESTRING'][$i]['x'])
+                && trim($gis_data[$index]['LINESTRING'][$i]['x']) != '')
+                ? $gis_data[$index]['LINESTRING'][$i]['x'] : $empty)
+                . ' ' . ((isset($gis_data[$index]['LINESTRING'][$i]['y'])
+                && trim($gis_data[$index]['LINESTRING'][$i]['y']) != '')
+                ? $gis_data[$index]['LINESTRING'][$i]['y'] : $empty) .',';
+        }
+        $wkt = substr($wkt, 0, strlen($wkt) - 1);
+        $wkt .= ')';
+        return $wkt;
+    }
+
+    /**
+     * Generate parameters for the GIS data editor from the value of the GIS column.
+     *
+     * @param string $value of the GIS column
+     * @param index  $index of the geometry
+     *
+     * @return  parameters for the GIS data editor from the value of the GIS column
+     */
+    public function generateParams($value, $index = -1)
+    {
+        if ($index == -1) {
+            $index = 0;
+            $params = array();
+            $data = PMA_GIS_Geometry::generateParams($value);
+            $params['srid'] = $data['srid'];
+            $wkt = $data['wkt'];
+        } else {
+            $params[$index]['gis_type'] = 'LINESTRING';
+            $wkt = $value;
+        }
+
+        // Trim to remove leading 'LINESTRING(' and trailing ')'
+        $linestring = substr($wkt, 11, (strlen($wkt) - 12));
+        $points_arr = $this->extractPoints($linestring, null);
+
+        $no_of_points = count($points_arr);
+        $params[$index]['LINESTRING']['no_of_points'] = $no_of_points;
+        for ($i = 0; $i < $no_of_points; $i++) {
+            $params[$index]['LINESTRING'][$i]['x'] = $points_arr[$i][0];
+            $params[$index]['LINESTRING'][$i]['y'] = $points_arr[$i][1];
+        }
+
+        return $params;
+    }
 }
 ?>
diff --git a/libraries/gis/pma_gis_multilinestring.php b/libraries/gis/pma_gis_multilinestring.php
index 733cc84..f5aa31f 100644
--- a/libraries/gis/pma_gis_multilinestring.php
+++ b/libraries/gis/pma_gis_multilinestring.php
@@ -68,6 +68,7 @@ class PMA_GIS_Multilinestring extends PMA_GIS_Geometry
     public function prepareRowAsPng($spatial, $label, $line_color, $scale_data, $image)
     {
         // allocate colors
+        $black = imagecolorallocate($image, 0, 0, 0);
         $red   = hexdec(substr($line_color, 1, 2));
         $green = hexdec(substr($line_color, 3, 2));
         $blue  = hexdec(substr($line_color, 4, 2));
@@ -78,6 +79,7 @@ class PMA_GIS_Multilinestring extends PMA_GIS_Geometry
         // Seperate each linestring
         $linestirngs = explode("),(", $multilinestirng);
 
+        $first_line = true;
         foreach ($linestirngs as $linestring) {
             $points_arr = $this->extractPoints($linestring, $scale_data);
             foreach ($points_arr as $point) {
@@ -90,6 +92,11 @@ class PMA_GIS_Multilinestring extends PMA_GIS_Geometry
                 }
             }
             unset($temp_point);
+            // print label if applicable
+            if (isset($label) && trim($label) != '' && $first_line) {
+                imagestring($image, 1, $points_arr[1][0], $points_arr[1][1], trim($label), $black);
+            }
+            $first_line = false;
         }
         return $image;
     }
@@ -118,6 +125,7 @@ class PMA_GIS_Multilinestring extends PMA_GIS_Geometry
         // Seperate each linestring
         $linestirngs = explode("),(", $multilinestirng);
 
+        $first_line = true;
         foreach ($linestirngs as $linestring) {
             $points_arr = $this->extractPoints($linestring, $scale_data);
             foreach ($points_arr as $point) {
@@ -130,6 +138,13 @@ class PMA_GIS_Multilinestring extends PMA_GIS_Geometry
                 }
             }
             unset($temp_point);
+            // print label
+            if (isset($label) && trim($label) != '' && $first_line) {
+                $pdf->SetXY($points_arr[1][0], $points_arr[1][1]);
+                $pdf->SetFontSize(5);
+                $pdf->Cell(0, 0, trim($label));
+            }
+            $first_line = false;
         }
         return $pdf;
     }
@@ -225,5 +240,109 @@ class PMA_GIS_Multilinestring extends PMA_GIS_Geometry
         $row .= ')), null, ' . json_encode($style_options) . '));';
         return $row;
     }
+
+    /**
+     * Generate the WKT with the set of parameters passed by the GIS editor.
+     *
+     * @param array  $gis_data GIS data
+     * @param int    $index    Index into the parameter object
+     * @param string $empty    Value for empty points
+     *
+     * @return WKT with the set of parameters passed by the GIS editor
+     */
+    public function generateWkt($gis_data, $index, $empty = '')
+    {
+        $no_of_lines = isset($gis_data[$index]['MULTILINESTRING']['no_of_lines'])
+            ? $gis_data[$index]['MULTILINESTRING']['no_of_lines'] : 1;
+        if ($no_of_lines < 1) {
+            $no_of_lines = 1;
+        }
+        $wkt = 'MULTILINESTRING(';
+        for ($i = 0; $i < $no_of_lines; $i++) {
+            $no_of_points = isset($gis_data[$index]['MULTILINESTRING'][$i]['no_of_points'])
+                ? $gis_data[$index]['MULTILINESTRING'][$i]['no_of_points'] : 2;
+            if ($no_of_points < 2) {
+                $no_of_points = 2;
+            }
+            $wkt .= '(';
+            for ($j = 0; $j < $no_of_points; $j++) {
+                $wkt .= ((isset($gis_data[$index]['MULTILINESTRING'][$i][$j]['x'])
+                    && trim($gis_data[$index]['MULTILINESTRING'][$i][$j]['x']) != '')
+                    ? $gis_data[$index]['MULTILINESTRING'][$i][$j]['x'] : $empty)
+                    . ' ' . ((isset($gis_data[$index]['MULTILINESTRING'][$i][$j]['y'])
+                    && trim($gis_data[$index]['MULTILINESTRING'][$i][$j]['y']) != '')
+                    ? $gis_data[$index]['MULTILINESTRING'][$i][$j]['y'] : $empty) . ',';
+            }
+            $wkt = substr($wkt, 0, strlen($wkt) - 1);
+            $wkt .= '),';
+        }
+        $wkt = substr($wkt, 0, strlen($wkt) - 1);
+        $wkt .= ')';
+        return $wkt;
+    }
+
+    /**
+     * Generate the WKT for the data from ESRI shape files.
+     *
+     * @param array $row_data GIS data
+     *
+     * @return the WKT for the data from ESRI shape files
+     */
+    public function getShape($row_data)
+    {
+        $wkt = 'MULTILINESTRING(';
+        for ($i = 0; $i < $row_data['numparts']; $i++) {
+            $wkt .= '(';
+            foreach ($row_data['parts'][$i]['points'] as $point) {
+                $wkt .= $point['x'] . ' ' . $point['y'] . ',';
+            }
+            $wkt = substr($wkt, 0, strlen($wkt) - 1);
+            $wkt .= '),';
+        }
+        $wkt = substr($wkt, 0, strlen($wkt) - 1);
+        $wkt .= ')';
+        return $wkt;
+    }
+
+    /**
+     * Generate parameters for the GIS data editor from the value of the GIS column.
+     *
+     * @param string $value of the GIS column
+     * @param index  $index of the geometry
+     *
+     * @return  parameters for the GIS data editor from the value of the GIS column
+     */
+    public function generateParams($value, $index = -1)
+    {
+        if ($index == -1) {
+            $index = 0;
+            $params = array();
+            $data = PMA_GIS_Geometry::generateParams($value);
+            $params['srid'] = $data['srid'];
+            $wkt = $data['wkt'];
+        } else {
+            $params[$index]['gis_type'] = 'MULTILINESTRING';
+            $wkt = $value;
+        }
+
+        // Trim to remove leading 'MULTILINESTRING((' and trailing '))'
+        $multilinestirng = substr($wkt, 17, (strlen($wkt) - 19));
+        // Seperate each linestring
+        $linestirngs = explode("),(", $multilinestirng);
+        $params[$index]['MULTILINESTRING']['no_of_lines'] = count($linestirngs);
+
+        $j = 0;
+        foreach ($linestirngs as $linestring) {
+            $points_arr = $this->extractPoints($linestring, null);
+            $no_of_points = count($points_arr);
+            $params[$index]['MULTILINESTRING'][$j]['no_of_points'] = $no_of_points;
+            for ($i = 0; $i < $no_of_points; $i++) {
+                $params[$index]['MULTILINESTRING'][$j][$i]['x'] = $points_arr[$i][0];
+                $params[$index]['MULTILINESTRING'][$j][$i]['y'] = $points_arr[$i][1];
+            }
+            $j++;
+        }
+        return $params;
+    }
 }
 ?>
diff --git a/libraries/gis/pma_gis_multipoint.php b/libraries/gis/pma_gis_multipoint.php
index ce20f92..b557465 100644
--- a/libraries/gis/pma_gis_multipoint.php
+++ b/libraries/gis/pma_gis_multipoint.php
@@ -59,6 +59,7 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry
     public function prepareRowAsPng($spatial, $label, $point_color, $scale_data, $image)
     {
         // allocate colors
+        $black = imagecolorallocate($image, 0, 0, 0);
         $red   = hexdec(substr($point_color, 1, 2));
         $green = hexdec(substr($point_color, 3, 2));
         $blue  = hexdec(substr($point_color, 4, 2));
@@ -70,7 +71,15 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry
 
         foreach ($points_arr as $point) {
             // draw a small circle to mark the point
-            imagearc($image, $point[0], $point[1], 7, 7, 0, 360, $color);
+            if ($point[0] != '' && $point[1] != '') {
+                imagearc($image, $point[0], $point[1], 7, 7, 0, 360, $color);
+            }
+        }
+        // print label for each point
+        if ((isset($label) && trim($label) != '')
+            && ($points_arr[0][0] != '' && $points_arr[0][1] != '')
+        ) {
+            imagestring($image, 1, $points_arr[0][0], $points_arr[0][1], trim($label), $black);
         }
         return $image;
     }
@@ -100,7 +109,17 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry
 
         foreach ($points_arr as $point) {
             // draw a small circle to mark the point
-            $pdf->Circle($point[0], $point[1], 2, 0, 360, 'D', $line);
+            if ($point[0] != '' && $point[1] != '') {
+                $pdf->Circle($point[0], $point[1], 2, 0, 360, 'D', $line);
+            }
+        }
+        // print label for each point
+        if ((isset($label) && trim($label) != '')
+            && ($points_arr[0][0] != '' && $points_arr[0][1] != '')
+        ) {
+            $pdf->SetXY($points_arr[0][0], $points_arr[0][1]);
+            $pdf->SetFontSize(5);
+            $pdf->Cell(0, 0, trim($label));
         }
         return $pdf;
     }
@@ -131,12 +150,14 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry
 
         $row = '';
         foreach ($points_arr as $point) {
-            $row .= '<circle cx="' . $point[0] . '" cy="' . $point[1] . '" r="3"';
-            $point_options['id'] = $label . rand();
-            foreach ($point_options as $option => $val) {
-                $row .= ' ' . $option . '="' . trim($val) . '"';
+            if ($point[0] != '' && $point[1] != '') {
+                $row .= '<circle cx="' . $point[0] . '" cy="' . $point[1] . '" r="3"';
+                $point_options['id'] = $label . rand();
+                foreach ($point_options as $option => $val) {
+                    $row .= ' ' . $option . '="' . trim($val) . '"';
+                }
+                $row .= '/>';
             }
-            $row .= '/>';
         }
 
         return $row;
@@ -176,11 +197,15 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry
 
         $row = 'new Array(';
         foreach ($points_arr as $point) {
-            $row .= '(new OpenLayers.Geometry.Point(' . $point[0] . ', ' . $point[1]
-                . ')).transform(new OpenLayers.Projection("EPSG:' . $srid
-                . '"), map.getProjectionObject()), ';
+            if ($point[0] != '' && $point[1] != '') {
+                $row .= '(new OpenLayers.Geometry.Point(' . $point[0] . ', ' . $point[1]
+                    . ')).transform(new OpenLayers.Projection("EPSG:' . $srid
+                    . '"), map.getProjectionObject()), ';
+            }
+        }
+        if (substr($row, strlen($row) - 2) == ', ') {
+            $row = substr($row, 0, strlen($row) - 2);
         }
-        $row = substr($row, 0, strlen($row) - 2);
         $row .= ')';
 
         $result .= 'vectorLayer.addFeatures(new OpenLayers.Feature.Vector('
@@ -188,5 +213,88 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry
             . json_encode($style_options) . '));';
         return $result;
     }
+
+    /**
+     * Generate the WKT with the set of parameters passed by the GIS editor.
+     *
+     * @param array  $gis_data GIS data
+     * @param int    $index    Index into the parameter object
+     * @param string $empty    Multipoint does not adhere to this
+     *
+     * @return WKT with the set of parameters passed by the GIS editor
+     */
+    public function generateWkt($gis_data, $index, $empty = '')
+    {
+        $no_of_points = isset($gis_data[$index]['MULTIPOINT']['no_of_points'])
+            ? $gis_data[$index]['MULTIPOINT']['no_of_points'] : 1;
+        if ($no_of_points < 1) {
+            $no_of_points = 1;
+        }
+        $wkt = 'MULTIPOINT(';
+        for ($i = 0; $i < $no_of_points; $i++) {
+            $wkt .= ((isset($gis_data[$index]['MULTIPOINT'][$i]['x'])
+                && trim($gis_data[$index]['MULTIPOINT'][$i]['x']) != '')
+                ? $gis_data[$index]['MULTIPOINT'][$i]['x'] : '')
+                . ' ' . ((isset($gis_data[$index]['MULTIPOINT'][$i]['y'])
+                && trim($gis_data[$index]['MULTIPOINT'][$i]['y']) != '')
+                ? $gis_data[$index]['MULTIPOINT'][$i]['y'] : '') . ',';
+        }
+        $wkt = substr($wkt, 0, strlen($wkt) - 1);
+        $wkt .= ')';
+        return $wkt;
+    }
+
+    /**
+     * Generate the WKT for the data from ESRI shape files.
+     *
+     * @param array $row_data GIS data
+     *
+     * @return the WKT for the data from ESRI shape files
+     */
+    public function getShape($row_data)
+    {
+        $wkt = 'MULTIPOINT(';
+        for ($i = 0; $i < $row_data['numpoints']; $i++) {
+            $wkt .= $row_data['points'][$i]['x'] . ' ' . $row_data['points'][$i]['y'] . ',';
+        }
+        $wkt = substr($wkt, 0, strlen($wkt) - 1);
+        $wkt .= ')';
+        return $wkt;
+    }
+
+    /**
+     * Generate parameters for the GIS data editor from the value of the GIS column.
+     *
+     * @param string $value of the GIS column
+     * @param index  $index of the geometry
+     *
+     * @return  parameters for the GIS data editor from the value of the GIS column
+     */
+    public function generateParams($value, $index = -1)
+    {
+        if ($index == -1) {
+            $index = 0;
+            $params = array();
+            $data = PMA_GIS_Geometry::generateParams($value);
+            $params['srid'] = $data['srid'];
+            $wkt = $data['wkt'];
+        } else {
+            $params[$index]['gis_type'] = 'MULTIPOINT';
+            $wkt = $value;
+        }
+
+        // Trim to remove leading 'MULTIPOINT(' and trailing ')'
+        $points = substr($wkt, 11, (strlen($wkt) - 12));
+        $points_arr = $this->extractPoints($points, null);
+
+        $no_of_points = count($points_arr);
+        $params[$index]['MULTIPOINT']['no_of_points'] = $no_of_points;
+        for ($i = 0; $i < $no_of_points; $i++) {
+            $params[$index]['MULTIPOINT'][$i]['x'] = $points_arr[$i][0];
+            $params[$index]['MULTIPOINT'][$i]['y'] = $points_arr[$i][1];
+        }
+
+        return $params;
+    }
 }
 ?>
diff --git a/libraries/gis/pma_gis_multipolygon.php b/libraries/gis/pma_gis_multipolygon.php
index 431fc88..b5765ef 100644
--- a/libraries/gis/pma_gis_multipolygon.php
+++ b/libraries/gis/pma_gis_multipolygon.php
@@ -82,6 +82,7 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry
     public function prepareRowAsPng($spatial, $label, $fill_color, $scale_data, $image)
     {
         // allocate colors
+        $black = imagecolorallocate($image, 0, 0, 0);
         $red   = hexdec(substr($fill_color, 1, 2));
         $green = hexdec(substr($fill_color, 3, 2));
         $blue  = hexdec(substr($fill_color, 4, 2));
@@ -92,6 +93,7 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry
         // Seperate each polygon
         $polygons = explode(")),((", $multipolygon);
 
+        $first_poly = true;
         foreach ($polygons as $polygon) {
             // If the polygon doesnt have an inner polygon
             if (strpos($polygon, "),(") === false) {
@@ -112,6 +114,15 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry
             }
             // draw polygon
             imagefilledpolygon($image, $points_arr, sizeof($points_arr) / 2, $color);
+            // mark label point if applicable
+            if (isset($label) && trim($label) != '' && $first_poly) {
+                $label_point = array($points_arr[2], $points_arr[3]);
+            }
+            $first_poly = false;
+        }
+        // print label if applicable
+        if (isset($label_point)) {
+            imagestring($image, 1, $points_arr[2], $points_arr[3], trim($label), $black);
         }
         return $image;
     }
@@ -140,6 +151,7 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry
         // Seperate each polygon
         $polygons = explode(")),((", $multipolygon);
 
+        $first_poly = true;
         foreach ($polygons as $polygon) {
             // If the polygon doesnt have an inner polygon
             if (strpos($polygon, "),(") === false) {
@@ -161,6 +173,18 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry
             }
             // draw polygon
             $pdf->Polygon($points_arr, 'F*', array(), $color, true);
+            // mark label point if applicable
+            if (isset($label) && trim($label) != '' && $first_poly) {
+                $label_point = array($points_arr[2], $points_arr[3]);
+            }
+            $first_poly = false;
+        }
+
+        // print label if applicable
+        if (isset($label_point)) {
+            $pdf->SetXY($label_point[0], $label_point[1]);
+            $pdf->SetFontSize(5);
+            $pdf->Cell(0, 0, trim($label));
         }
         return $pdf;
     }
@@ -287,5 +311,190 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry
 
         return $row;
     }
+
+    /**
+     * Generate the WKT with the set of parameters passed by the GIS editor.
+     *
+     * @param array  $gis_data GIS data
+     * @param int    $index    Index into the parameter object
+     * @param string $empty    Value for empty points
+     *
+     * @return WKT with the set of parameters passed by the GIS editor
+     */
+    public function generateWkt($gis_data, $index, $empty = '')
+    {
+        $no_of_polygons = isset($gis_data[$index]['MULTIPOLYGON']['no_of_polygons'])
+            ? $gis_data[$index]['MULTIPOLYGON']['no_of_polygons'] : 1;
+        if ($no_of_polygons < 1) {
+            $no_of_polygons = 1;
+        }
+        $wkt = 'MULTIPOLYGON(';
+        for ($k = 0; $k < $no_of_polygons; $k++) {
+            $no_of_lines = isset($gis_data[$index]['MULTIPOLYGON'][$k]['no_of_lines'])
+                ? $gis_data[$index]['MULTIPOLYGON'][$k]['no_of_lines'] : 1;
+            if ($no_of_lines < 1) {
+                $no_of_lines = 1;
+            }
+            $wkt .= '(';
+            for ($i = 0; $i < $no_of_lines; $i++) {
+                $no_of_points = isset($gis_data[$index]['MULTIPOLYGON'][$k][$i]['no_of_points'])
+                    ? $gis_data[$index]['MULTIPOLYGON'][$k][$i]['no_of_points'] : 4;
+                if ($no_of_points < 4) {
+                    $no_of_points = 4;
+                }
+                $wkt .= '(';
+                for ($j = 0; $j < $no_of_points; $j++) {
+                    $wkt .= ((isset($gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['x'])
+                        && trim($gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['x']) != '')
+                        ? $gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['x'] : $empty)
+                        . ' ' . ((isset($gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['y'])
+                        && trim($gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['y']) != '')
+                        ? $gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['y'] : $empty) .',';
+                }
+                $wkt = substr($wkt, 0, strlen($wkt) - 1);
+                $wkt .= '),';
+            }
+            $wkt = substr($wkt, 0, strlen($wkt) - 1);
+            $wkt .= '),';
+        }
+        $wkt = substr($wkt, 0, strlen($wkt) - 1);
+        $wkt .= ')';
+        return $wkt;
+    }
+
+    /**
+     * Generate the WKT for the data from ESRI shape files.
+     *
+     * @param array $row_data GIS data
+     *
+     * @return the WKT for the data from ESRI shape files
+     */
+    public function getShape($row_data)
+    {
+        // Determines whether each line ring is an inner ring or an outer ring.
+        // If it's an inner ring get a point on the surface which can be used to
+        // correctly classify inner rings to their respective outer rings.
+        require_once './libraries/gis/pma_gis_polygon.php';
+        foreach ($row_data['parts'] as $i => $ring) {
+            $row_data['parts'][$i]['isOuter'] = PMA_GIS_Polygon::isOuterRing($ring['points']);
+        }
+
+        // Find points on surface for inner rings
+        foreach ($row_data['parts'] as $i => $ring) {
+            if (! $ring['isOuter']) {
+                $row_data['parts'][$i]['pointOnSurface'] = PMA_GIS_Polygon::getPointOnSurface($ring['points']);
+            }
+        }
+
+        // Classify inner rings to their respective outer rings.
+        foreach ($row_data['parts'] as $j => $ring1) {
+            if (! $ring1['isOuter']) {
+                foreach ($row_data['parts'] as $k => $ring2) {
+                    if ($ring2['isOuter']) {
+                        // If the pointOnSurface of the inner ring is also inside the outer ring
+                        if (PMA_GIS_Polygon::isPointInsidePolygon($ring1['pointOnSurface'], $ring2['points'])) {
+                            if (! isset($ring2['inner'])) {
+                                $row_data['parts'][$k]['inner'] = array();
+                            }
+                            $row_data['parts'][$k]['inner'][] = $j;
+                        }
+                    }
+                }
+            }
+        }
+
+        $wkt = 'MULTIPOLYGON(';
+        // for each polygon
+        foreach ($row_data['parts'] as $ring) {
+            if ($ring['isOuter']) {
+                $wkt .= '('; // start of polygon
+
+                $wkt .= '('; // start of outer ring
+                foreach($ring['points'] as $point) {
+                    $wkt .= $point['x'] . ' ' . $point['y'] . ',';
+                }
+                $wkt = substr($wkt, 0, strlen($wkt) - 1);
+                $wkt .= ')'; // end of outer ring
+
+                // inner rings if any
+                if (isset($ring['inner'])) {
+                    foreach ($ring['inner'] as $j) {
+                        $wkt .= ',('; // start of inner ring
+                        foreach ($row_data['parts'][$j]['points'] as $innerPoint) {
+                            $wkt .= $innerPoint['x'] . ' ' . $innerPoint['y'] . ',';
+                        }
+                        $wkt = substr($wkt, 0, strlen($wkt) - 1);
+                        $wkt .= ')';  // end of inner ring
+                    }
+                }
+
+                $wkt .= '),'; // end of polygon
+            }
+        }
+        $wkt = substr($wkt, 0, strlen($wkt) - 1);
+
+        $wkt .= ')'; // end of multipolygon
+        return $wkt;
+    }
+
+    /**
+     * Generate parameters for the GIS data editor from the value of the GIS column.
+     *
+     * @param string $value of the GIS column
+     * @param index  $index of the geometry
+     *
+     * @return  parameters for the GIS data editor from the value of the GIS column
+     */
+    public function generateParams($value, $index = -1)
+    {
+        if ($index == -1) {
+            $index = 0;
+            $params = array();
+            $data = PMA_GIS_Geometry::generateParams($value);
+            $params['srid'] = $data['srid'];
+            $wkt = $data['wkt'];
+        } else {
+            $params[$index]['gis_type'] = 'MULTIPOLYGON';
+            $wkt = $value;
+        }
+
+        // Trim to remove leading 'MULTIPOLYGON(((' and trailing ')))'
+        $multipolygon = substr($wkt, 15, (strlen($wkt) - 18));
+        // Seperate each polygon
+        $polygons = explode(")),((", $multipolygon);
+        $params[$index]['MULTIPOLYGON']['no_of_polygons'] = count($polygons);
+
+        $k = 0;
+        foreach ($polygons as $polygon) {
+            // If the polygon doesnt have an inner polygon
+            if (strpos($polygon, "),(") === false) {
+                $params[$index]['MULTIPOLYGON'][$k]['no_of_lines'] = 1;
+                $points_arr = $this->extractPoints($polygon, null);
+                $no_of_points = count($points_arr);
+                $params[$index]['MULTIPOLYGON'][$k][0]['no_of_points'] = $no_of_points;
+                for ($i = 0; $i < $no_of_points; $i++) {
+                    $params[$index]['MULTIPOLYGON'][$k][0][$i]['x'] = $points_arr[$i][0];
+                    $params[$index]['MULTIPOLYGON'][$k][0][$i]['y'] = $points_arr[$i][1];
+                }
+            } else {
+                // Seperate outer and inner polygons
+                $parts = explode("),(", $polygon);
+                $params[$index]['MULTIPOLYGON'][$k]['no_of_lines'] = count($parts);
+                $j = 0;
+                foreach ($parts as $ring) {
+                    $points_arr = $this->extractPoints($ring, null);
+                    $no_of_points = count($points_arr);
+                    $params[$index]['MULTIPOLYGON'][$k][$j]['no_of_points'] = $no_of_points;
+                    for ($i = 0; $i < $no_of_points; $i++) {
+                        $params[$index]['MULTIPOLYGON'][$k][$j][$i]['x'] = $points_arr[$i][0];
+                        $params[$index]['MULTIPOLYGON'][$k][$j][$i]['y'] = $points_arr[$i][1];
+                    }
+                    $j++;
+                }
+            }
+            $k++;
+        }
+        return $params;
+    }
 }
 ?>
diff --git a/libraries/gis/pma_gis_point.php b/libraries/gis/pma_gis_point.php
index 31531f3..82fb00c 100644
--- a/libraries/gis/pma_gis_point.php
+++ b/libraries/gis/pma_gis_point.php
@@ -59,6 +59,7 @@ class PMA_GIS_Point extends PMA_GIS_Geometry
     public function prepareRowAsPng($spatial, $label, $point_color, $scale_data, $image)
     {
         // allocate colors
+        $black = imagecolorallocate($image, 0, 0, 0);
         $red   = hexdec(substr($point_color, 1, 2));
         $green = hexdec(substr($point_color, 3, 2));
         $blue  = hexdec(substr($point_color, 4, 2));
@@ -69,7 +70,13 @@ class PMA_GIS_Point extends PMA_GIS_Geometry
         $points_arr = $this->extractPoints($point, $scale_data);
 
         // draw a small circle to mark the point
-        imagearc($image, $points_arr[0][0], $points_arr[0][1], 7, 7, 0, 360, $color);
+        if ($points_arr[0][0] != '' && $points_arr[0][1] != '') {
+            imagearc($image, $points_arr[0][0], $points_arr[0][1], 7, 7, 0, 360, $color);
+            // print label if applicable
+            if (isset($label) && trim($label) != '') {
+                imagestring($image, 1, $points_arr[0][0], $points_arr[0][1], trim($label), $black);
+            }
+        }
         return $image;
     }
 
@@ -97,7 +104,15 @@ class PMA_GIS_Point extends PMA_GIS_Geometry
         $points_arr = $this->extractPoints($point, $scale_data);
 
         // draw a small circle to mark the point
-        $pdf->Circle($points_arr[0][0], $points_arr[0][1], 2, 0, 360, 'D', $line);
+        if ($points_arr[0][0] != '' && $points_arr[0][1] != '') {
+            $pdf->Circle($points_arr[0][0], $points_arr[0][1], 2, 0, 360, 'D', $line);
+            // print label if applicable
+            if (isset($label) && trim($label) != '') {
+                $pdf->SetXY($points_arr[0][0], $points_arr[0][1]);
+                $pdf->SetFontSize(5);
+                $pdf->Cell(0, 0, trim($label));
+            }
+        }
         return $pdf;
     }
 
@@ -126,11 +141,14 @@ class PMA_GIS_Point extends PMA_GIS_Geometry
         $point = substr($spatial, 6, (strlen($spatial) - 7));
         $points_arr = $this->extractPoints($point, $scale_data);
 
-        $row = '<circle cx="' . $points_arr[0][0] . '" cy="' . $points_arr[0][1] . '" r="3"';
-        foreach ($point_options as $option => $val) {
-            $row .= ' ' . $option . '="' . trim($val) . '"';
+        $row = '';
+        if ($points_arr[0][0] != '' && $points_arr[0][1] != '') {
+            $row .= '<circle cx="' . $points_arr[0][0] . '" cy="' . $points_arr[0][1] . '" r="3"';
+            foreach ($point_options as $option => $val) {
+                $row .= ' ' . $option . '="' . trim($val) . '"';
+            }
+            $row .= '/>';
         }
-        $row .= '/>';
 
         return $row;
     }
@@ -167,12 +185,76 @@ class PMA_GIS_Point extends PMA_GIS_Geometry
         $point = substr($spatial, 6, (strlen($spatial) - 7));
         $points_arr = $this->extractPoints($point, null);
 
-        $result .= 'vectorLayer.addFeatures(new OpenLayers.Feature.Vector(('
-            . 'new OpenLayers.Geometry.Point(' . $points_arr[0][0] . ', '
-            . $points_arr[0][1] . ').transform(new OpenLayers.Projection("EPSG:'
-            . $srid . '"), map.getProjectionObject())), null, '
-            . json_encode($style_options) . '));';
+        if ($points_arr[0][0] != '' && $points_arr[0][1] != '') {
+            $result .= 'vectorLayer.addFeatures(new OpenLayers.Feature.Vector(('
+                . 'new OpenLayers.Geometry.Point(' . $points_arr[0][0] . ', '
+                . $points_arr[0][1] . ').transform(new OpenLayers.Projection("EPSG:'
+                . $srid . '"), map.getProjectionObject())), null, '
+                . json_encode($style_options) . '));';
+        }
         return $result;
     }
+
+    /**
+     * Generate the WKT with the set of parameters passed by the GIS editor.
+     *
+     * @param array  $gis_data GIS data
+     * @param int    $index    Index into the parameter object
+     * @param string $empty    Point deos not adhere to this parameter
+     *
+     * @return WKT with the set of parameters passed by the GIS editor
+     */
+    public function generateWkt($gis_data, $index, $empty = '')
+    {
+         return 'POINT('
+             . ((isset($gis_data[$index]['POINT']['x']) && trim($gis_data[$index]['POINT']['x']) != '')
+             ? $gis_data[$index]['POINT']['x'] : '') . ' '
+             . ((isset($gis_data[$index]['POINT']['y']) && trim($gis_data[$index]['POINT']['y']) != '')
+             ? $gis_data[$index]['POINT']['y'] : '') . ')';
+    }
+
+    /**
+     * Generate the WKT for the data from ESRI shape files.
+     *
+     * @param array $row_data GIS data
+     *
+     * @return the WKT for the data from ESRI shape files
+     */
+    public function getShape($row_data)
+    {
+        return 'POINT(' . (isset($row_data['x']) ? $row_data['x'] : '')
+             . ' ' . (isset($row_data['y']) ? $row_data['y'] : '') . ')';
+    }
+
+    /**
+     * Generate parameters for the GIS data editor from the value of the GIS column.
+     *
+     * @param string $value of the GIS column
+     * @param index  $index of the geometry
+     *
+     * @return  parameters for the GIS data editor from the value of the GIS column
+     */
+    public function generateParams($value, $index = -1)
+    {
+        if ($index == -1) {
+            $index = 0;
+            $params = array();
+            $data = PMA_GIS_Geometry::generateParams($value);
+            $params['srid'] = $data['srid'];
+            $wkt = $data['wkt'];
+        } else {
+            $params[$index]['gis_type'] = 'POINT';
+            $wkt = $value;
+        }
+
+        // Trim to remove leading 'POINT(' and trailing ')'
+        $point = substr($wkt, 6, (strlen($wkt) - 7));
+        $points_arr = $this->extractPoints($point, null);
+
+        $params[$index]['POINT']['x'] = $points_arr[0][0];
+        $params[$index]['POINT']['y'] = $points_arr[0][1];
+
+        return $params;
+    }
 }
 ?>
diff --git a/libraries/gis/pma_gis_polygon.php b/libraries/gis/pma_gis_polygon.php
index 02f0173..8f461ad 100644
--- a/libraries/gis/pma_gis_polygon.php
+++ b/libraries/gis/pma_gis_polygon.php
@@ -77,6 +77,7 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry
     public function prepareRowAsPng($spatial, $label, $fill_color, $scale_data, $image)
     {
         // allocate colors
+        $black = imagecolorallocate($image, 0, 0, 0);
         $red   = hexdec(substr($fill_color, 1, 2));
         $green = hexdec(substr($fill_color, 3, 2));
         $blue  = hexdec(substr($fill_color, 4, 2));
@@ -105,6 +106,10 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry
 
         // draw polygon
         imagefilledpolygon($image, $points_arr, sizeof($points_arr) / 2, $color);
+        // print label if applicable
+        if (isset($label) && trim($label) != '') {
+            imagestring($image, 1, $points_arr[2], $points_arr[3], trim($label), $black);
+        }
         return $image;
     }
 
@@ -150,6 +155,12 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry
 
         // draw polygon
         $pdf->Polygon($points_arr, 'F*', array(), $color, true);
+        // print label if applicable
+        if (isset($label) && trim($label) != '') {
+            $pdf->SetXY($points_arr[2], $points_arr[3]);
+            $pdf->SetFontSize(5);
+            $pdf->Cell(0, 0, trim($label));
+        }
         return $pdf;
     }
 
@@ -262,5 +273,248 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry
 
         return $row;
     }
+
+    /**
+     * Generate the WKT with the set of parameters passed by the GIS editor.
+     *
+     * @param array  $gis_data GIS data
+     * @param int    $index    Index into the parameter object
+     * @param string $empty    Value for empty points
+     *
+     * @return WKT with the set of parameters passed by the GIS editor
+     */
+    public function generateWkt($gis_data, $index, $empty = '')
+    {
+        $no_of_lines = isset($gis_data[$index]['POLYGON']['no_of_lines'])
+            ? $gis_data[$index]['POLYGON']['no_of_lines'] : 1;
+        if ($no_of_lines < 1) {
+            $no_of_lines = 1;
+        }
+        $wkt = 'POLYGON(';
+        for ($i = 0; $i < $no_of_lines; $i++) {
+            $no_of_points = isset($gis_data[$index]['POLYGON'][$i]['no_of_points'])
+                ? $gis_data[$index]['POLYGON'][$i]['no_of_points'] : 4;
+            if ($no_of_points < 4) {
+                $no_of_points = 4;
+            }
+            $wkt .= '(';
+            for ($j = 0; $j < $no_of_points; $j++) {
+                $wkt .= ((isset($gis_data[$index]['POLYGON'][$i][$j]['x'])
+                    && trim($gis_data[$index]['POLYGON'][$i][$j]['x']) != '')
+                    ? $gis_data[$index]['POLYGON'][$i][$j]['x'] : $empty)
+                    . ' ' . ((isset($gis_data[$index]['POLYGON'][$i][$j]['y'])
+                    && trim($gis_data[$index]['POLYGON'][$i][$j]['y']) != '')
+                    ? $gis_data[$index]['POLYGON'][$i][$j]['y'] : $empty) .',';
+            }
+            $wkt = substr($wkt, 0, strlen($wkt) - 1);
+            $wkt .= '),';
+        }
+        $wkt = substr($wkt, 0, strlen($wkt) - 1);
+        $wkt .= ')';
+        return $wkt;
+    }
+
+    /**
+     * Calculates the area of a closed simple polygon.
+     *
+     * @param array $ring array of points forming the ring
+     *
+     * @return the area of a closed simple polygon.
+     */
+    public static function area($ring)
+    {
+
+        $no_of_points = count($ring);
+
+        // If the last point is same as the first point ignore it
+        $last = count($ring) - 1;
+        if (($ring[0]['x'] == $ring[$last]['x'])
+            && ($ring[0]['y'] == $ring[$last]['y'])
+        ) {
+            $no_of_points--;
+        }
+
+        //         _n-1
+        // A = _1_ \    (X(i) * Y(i+1)) - (Y(i) * X(i+1))
+        //      2  /__
+        //         i=0
+        $area = 0;
+        for ($i = 0; $i < $no_of_points; $i++) {
+            $j = ($i + 1) % $no_of_points;
+            $area += $ring[$i]['x'] * $ring[$j]['y'];
+            $area -= $ring[$i]['y'] * $ring[$j]['x'];
+        }
+        $area /= 2.0;
+
+        return $area;
+    }
+
+    /**
+     * Determines whether a set of points represents an outer ring.
+     * If points are in clockwise orientation then, they form an outer ring.
+     *
+     * @param array $ring array of points forming the ring
+     *
+     * @return whether a set of points represents an outer ring.
+     */
+    public static function isOuterRing($ring)
+    {
+        // If area is negative then it's in clockwise orientation,
+        // i.e. it's an outer ring
+        if (PMA_GIS_Polygon::area($ring) < 0) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Determines whether a given point is inside a given polygon.
+     *
+     * @param array $point   x, y coordinates of the point
+     * @param array $polygon array of points forming the ring
+     *
+     * @return whether a given point is inside a given polygon
+     */
+    public static function isPointInsidePolygon($point, $polygon)
+    {
+        // If first point is repeated at the end remove it
+        $last = count($polygon) - 1;
+        if (($polygon[0]['x'] == $polygon[$last]['x'])
+            && ($polygon[0]['y'] == $polygon[$last]['y'])
+        ) {
+            $polygon = array_slice($polygon, 0, $last);
+        }
+
+        $no_of_points = count($polygon);
+        $counter = 0;
+
+        // Use ray casting algorithm
+        $p1 = $polygon[0];
+        for ($i = 1; $i <= $no_of_points; $i++) {
+            $p2 = $polygon[$i % $no_of_points];
+            if ($point['y'] > min(array($p1['y'], $p2['y']))) {
+                if ($point['y'] <= max(array($p1['y'], $p2['y']))) {
+                    if ($point['x'] <= max(array($p1['x'], $p2['x']))) {
+                        if ($p1['y'] != $p2['y']) {
+                            $xinters = ($point['y'] - $p1['y'])
+                                * ($p2['x'] - $p1['x'])
+                                / ($p2['y'] - $p1['y']) + $p1['x'];
+                            if ($p1['x'] == $p2['x'] || $point['x'] <= $xinters) {
+                                $counter++;
+                            }
+                        }
+                    }
+                }
+            }
+            $p1 = $p2;
+        }
+
+        if ($counter % 2 == 0) {
+            return  false;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     * Returns a point that is guaranteed to be on the surface of the ring.
+     * (for simple closed rings)
+     *
+     * @param array $ring array of points forming the ring
+     *
+     * @return a point on the surface of the ring
+     */
+    public static function getPointOnSurface($ring)
+    {
+        // Find two consecutive distinct points.
+        for ($i = 0; $i < count($ring) - 1; $i++) {
+            if ($ring[$i]['y'] != $ring[$i + 1]['y']) {
+                $x0 = $ring[$i]['x'];
+                $x1 = $ring[$i + 1]['x'];
+                $y0 = $ring[$i]['y'];
+                $y1 = $ring[$i + 1]['y'];
+                break;
+            }
+        }
+
+        if (! isset($x0)) {
+            return false;
+        }
+
+        // Find the mid point
+        $x2 = ($x0 + $x1) / 2;
+        $y2 = ($y0 + $y1) / 2;
+
+        // Always keep $epsilon < 1 to go with the reduction logic down here
+        $epsilon = 0.1;
+        $denominator = sqrt(pow(($y1 - $y0), 2) + pow(($x0 - $x1), 2));
+        $pointA = array(); $pointB = array();
+
+        while (true) {
+            // Get the points on either sides of the line
+            // with a distance of epsilon to the mid point
+            $pointA['x'] = $x2 + ($epsilon * ($y1 - $y0)) / $denominator;
+            $pointA['y'] = $y2 + ($pointA['x'] - $x2) * ($x0 - $x1) / ($y1 - $y0);
+
+            $pointB['x'] = $x2 + ($epsilon * ($y1 - $y0)) / (0 - $denominator);
+            $pointB['y'] = $y2 + ($pointB['x'] - $x2) * ($x0 - $x1) / ($y1 - $y0);
+
+            // One of the points should be inside the polygon,
+            // unless epcilon chosen is too large
+            if (PMA_GIS_Polygon::isPointInsidePolygon($pointA, $ring)) {
+                return $pointA;
+            } elseif (PMA_GIS_Polygon::isPointInsidePolygon($pointB, $ring)) {
+                return $pointB;
+            } else {
+                //If both are outside the polygon reduce the epsilon and
+                //recalculate the points(reduce exponentially for faster convergance)
+                $epsilon = pow($epsilon, 2);
+                if ($epsilon == 0) {
+                    return false;
+                }
+            }
+
+        }
+    }
+
+    /** Generate parameters for the GIS data editor from the value of the GIS column.
+     *
+     * @param string $value of the GIS column
+     * @param index  $index of the geometry
+     *
+     * @return  parameters for the GIS data editor from the value of the GIS column
+     */
+    public function generateParams($value, $index = -1)
+    {
+        if ($index == -1) {
+            $index = 0;
+            $params = array();
+            $data = PMA_GIS_Geometry::generateParams($value);
+            $params['srid'] = $data['srid'];
+            $wkt = $data['wkt'];
+        } else {
+            $params[$index]['gis_type'] = 'POLYGON';
+            $wkt = $value;
+        }
+
+        // Trim to remove leading 'POLYGON((' and trailing '))'
+        $polygon = substr($wkt, 9, (strlen($wkt) - 11));
+        // Seperate each linestring
+        $linerings = explode("),(", $polygon);
+        $params[$index]['POLYGON']['no_of_lines'] = count($linerings);
+
+        $j = 0;
+        foreach ($linerings as $linering) {
+            $points_arr = $this->extractPoints($linering, null);
+            $no_of_points = count($points_arr);
+            $params[$index]['POLYGON'][$j]['no_of_points'] = $no_of_points;
+            for ($i = 0; $i < $no_of_points; $i++) {
+                $params[$index]['POLYGON'][$j][$i]['x'] = $points_arr[$i][0];
+                $params[$index]['POLYGON'][$j][$i]['y'] = $points_arr[$i][1];
+            }
+            $j++;
+        }
+        return $params;
+    }
 }
 ?>
diff --git a/libraries/gis/pma_gis_visualization.php b/libraries/gis/pma_gis_visualization.php
index 2817a23..29f2e1c 100644
--- a/libraries/gis/pma_gis_visualization.php
+++ b/libraries/gis/pma_gis_visualization.php
@@ -18,15 +18,14 @@ class PMA_GIS_Visualization
 
         // Array of colors to be used for GIS visualizations.
         'colors' => array(
-            '#BCE02E',
+            '#B02EE0',
             '#E0642E',
             '#E0D62E',
             '#2E97E0',
-            '#B02EE0',
+            '#BCE02E',
             '#E02E75',
             '#5CE02E',
             '#E0B02E',
-            '#000000',
             '#0022E0',
             '#726CB1',
             '#481A36',
@@ -153,7 +152,7 @@ class PMA_GIS_Visualization
         $output .= '<g id="groupPanel">';
 
         $scale_data = $this->_scaleDataSet($this->_data);
-        $output .= $this->_prepareDataSet($this->_data, 0, $scale_data, 'svg', '');
+        $output .= $this->_prepareDataSet($this->_data, $scale_data, 'svg', '');
 
         $output .= '</g>';
         $output .= '</svg>';
@@ -206,7 +205,7 @@ class PMA_GIS_Visualization
         );
 
         $scale_data = $this->_scaleDataSet($this->_data);
-        $image = $this->_prepareDataSet($this->_data, 0, $scale_data, 'png', $image);
+        $image = $this->_prepareDataSet($this->_data, $scale_data, 'png', $image);
 
         return $image;
     }
@@ -256,7 +255,33 @@ class PMA_GIS_Visualization
     {
         $this->init();
         $scale_data = $this->_scaleDataSet($this->_data);
-        $output = $this->_prepareDataSet($this->_data, 0, $scale_data, 'ol', '');
+        $output =
+            'var options = {'
+                . 'projection: new OpenLayers.Projection("EPSG:900913"),'
+                . 'displayProjection: new OpenLayers.Projection("EPSG:4326"),'
+                . 'units: "m",'
+                . 'numZoomLevels: 18,'
+                . 'maxResolution: 156543.0339,'
+                . 'maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508),'
+                . 'restrictedExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508)'
+            . '};'
+            . 'var map = new OpenLayers.Map("openlayersmap", options);'
+            . 'var layerNone = new OpenLayers.Layer.Boxes("None", {isBaseLayer: true});'
+            . 'var layerMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");'
+            . 'var layerOsmarender = new OpenLayers.Layer.OSM.Osmarender("Osmarender");'
+            . 'var layerCycleMap = new OpenLayers.Layer.OSM.CycleMap("CycleMap");'
+            . 'map.addLayers([layerMapnik, layerOsmarender, layerCycleMap, layerNone]);'
+            . 'var vectorLayer = new OpenLayers.Layer.Vector("Data");'
+            . 'var bound;';
+        $output .= $this->_prepareDataSet($this->_data, $scale_data, 'ol', '');
+        $output .=
+              'map.addLayer(vectorLayer);'
+            . 'map.zoomToExtent(bound);'
+            . 'if (map.getZoom() < 2) {'
+                . 'map.zoomTo(2);'
+            . '}'
+            . 'map.addControl(new OpenLayers.Control.LayerSwitcher());'
+            . 'map.addControl(new OpenLayers.Control.MousePosition());';
         return $output;
     }
 
@@ -274,7 +299,7 @@ class PMA_GIS_Visualization
         include_once './libraries/tcpdf/tcpdf.php';
 
         // create pdf
-        $pdf = new TCPDF('', 'pt', 'A4', true, 'UTF-8', false);
+        $pdf = new TCPDF('', 'pt', $GLOBALS['cfg']['PDFDefaultPageSize'], true, 'UTF-8', false);
 
         // disable header and footer
         $pdf->setPrintHeader(false);
@@ -287,7 +312,7 @@ class PMA_GIS_Visualization
         $pdf->AddPage();
 
         $scale_data = $this->_scaleDataSet($this->_data);
-        $pdf = $this->_prepareDataSet($this->_data, 0, $scale_data, 'pdf', $pdf);
+        $pdf = $this->_prepareDataSet($this->_data, $scale_data, 'pdf', $pdf);
 
         // sanitize file name
         $file_name = $this->_sanitizeName($file_name, 'pdf');
@@ -319,6 +344,9 @@ class PMA_GIS_Visualization
             $type = substr($ref_data, 0, $type_pos);
 
             $gis_obj = PMA_GIS_Factory::factory($type);
+            if (! $gis_obj) {
+                continue;
+            }
             $scale_data = $gis_obj->scaleRow($row[$this->_settings['spatialColumn']]);
 
             // Upadate minimum/maximum values for x and y cordinates.
@@ -377,19 +405,19 @@ class PMA_GIS_Visualization
     /**
      * Prepares and return the dataset as needed by the visualization.
      *
-     * @param array  $data         Raw data
-     * @param int    $color_number Start index to the color array
-     * @param array  $scale_data   Data related to scaling
-     * @param string $format       Format of the visulaization
-     * @param image  $results      Image object in the case of png
+     * @param array  $data       Raw data
+     * @param array  $scale_data Data related to scaling
+     * @param string $format     Format of the visulaization
+     * @param image  $results    Image object in the case of png
      *
      * @return the formatted array of data.
      */
-    private function _prepareDataSet($data, $color_number, $scale_data, $format, $results)
+    private function _prepareDataSet($data, $scale_data, $format, $results)
     {
+        $color_number = 0;
+
         // loop through the rows
         foreach ($data as $row) {
-
             $index = $color_number % sizeof($this->_settings['colors']);
 
             // Figure out the data type
@@ -398,6 +426,9 @@ class PMA_GIS_Visualization
             $type = substr($ref_data, 0, $type_pos);
 
             $gis_obj = PMA_GIS_Factory::factory($type);
+            if (! $gis_obj) {
+                continue;
+            }
             $label = '';
             if (isset($this->_settings['labelColumn'])
                 && isset($row[$this->_settings['labelColumn']])
@@ -432,4 +463,3 @@ class PMA_GIS_Visualization
     }
 }
 ?>
-
diff --git a/libraries/gis_visualization.lib.php b/libraries/gis_visualization.lib.php
index cc15dc9..a35af80 100644
--- a/libraries/gis_visualization.lib.php
+++ b/libraries/gis_visualization.lib.php
@@ -16,7 +16,7 @@
  *
  * @return the modified sql query.
  */
-function PMA_GIS_modify_query($sql_query, $visualizationSettings)
+function PMA_GIS_modifyQuery($sql_query, $visualizationSettings)
 {
     $modified_query = 'SELECT ';
 
@@ -75,7 +75,9 @@ function PMA_GIS_modify_query($sql_query, $visualizationSettings)
         // If select cluase is *
     } else {
         // If label column is chosen add it to the query
-        if ($visualizationSettings['labelColumn'] != '') {
+        if (isset($v ationSettings['labelColumn'] != '') {  visualizationSettings)  p  ts)  se);  8)'    s'])) {  );  wkbval);  ams  x"]));  try"); ?>" />   __('Add a polygon') ?>">   ring') ?>"><br/>  >  y']) ? htmlspecialchars($gis_data[$a][$type][$k][$i][$j]['y']) : ''); ?>" />  /pma/Charts#Data_formats_for_query_results_chart">wiki</a>.</p>            ’"NÂ+          †@NÂ+  °CDxÿ  `"NÂ+  ïCDxÿ         ÀïÎÃ+  u*NÂ+   àÎÃ+  ØäÎÃ+  ¨éÎÃ+  €JOÂ+          xôjÃ+          :Dxÿ          à8Dxÿ  k at NÂ+  à!     à!     °CDxÿ   DDxÿ  H¾JÃ+          ð:Dxÿ         ’"NÂ+          †@NÂ+  °CDxÿ  `"NÂ+  ïCDxÿ  àCDxÿ  ØCDxÿ  8KoÂ+  Œp˜         DDxÿ  u*NÂ+  €JOÂ+                  ð:Dxÿ         À9Dxÿ  k at NÂ+          G       H   I       J   K           M   N   O       P   °CDxÿ   DDxÿ  Hu!Ã+          <Dxÿ         ’"NÂ+          †@NÂ+  °CDxÿ         0ïÎÃ+  u*NÂ+    kÃ+   ©þÂ+   àÎÃ+  ØäÎÃ+  ¨éÎÃ+  €JOÂ+          Hu!Ã+          <Dxÿ         Ð:Dxÿ  k at NÂ+  8u!Ã+          <Dxÿ          ;Dxÿ  k at NÂ+  (u!Ã+          <Dxÿ         0;Dxÿ  k at NÂ+  u!Ã+          <Dxÿ         `;Dxÿ  k at NÂ+  	       ¨îÎÃ+  u*NÂ+         ¨éÎÃ+  à5Dxÿ          ŠøþÂ+  e)NÂ+         ØäÎÃ+   <Dxÿ          yøþÂ+  e)NÂ+          àÎÃ+  0<Dxÿ          ZøþÂ+  e)NÂ+  ؤþÂ+    kÃ+   ©þÂ+   àÎÃ+  ØkÃ+  ØäÎÃ+  ¨éÎÃ+  €JOÂ+          8KoÂ+                        mÊÂ+   DDxÿ  p;þÂ+          à=Dxÿ          °<Dxÿ  k at NÂ+      5   6   7   8   :   <   =   >       ?       @   B   D       °CDxÿ   DDxÿ  àmÇÂ+                  DDxÿ  u*NÂ+         EoÂ+  `<Dxÿ          mÊÂ+  e)NÂ+  EoÂ+          Õ_ at fÆS         Qöl±íÁƒ–Â+   DDxÿ  àmÇÂ+          ð>Dxÿ         À=Dxÿ  k at NÂ+  u]ÞÓ	4Q ÷U^Qʉ§ ¶uª¹ñìò*Ä“v°CDxÿ   DDxÿ  H¾“Â+          ÐÂ+          `EDxÿ  ¦2Ä+  ¦2Ä+         VÍÂ+  ïCDxÿ   EDxÿ  ØCDxÿ  @@Dxÿ  kÃ+  u*NÂ+  ØkÃ+   FDxÿ  ¢2Ä+  pEDxÿ           ADxÿ                 ÿÿÿÿÿÿÿÿ¢2Ä+          (DDxÿ                 isualizationSettings['labelColumn'])
+            && $visualizationSettings['labelColumn'] != ''
+        ) {
             $modified_query .= '`' . $visualizationSettings['labelColumn'] .'`, ';
         }
 
@@ -84,7 +86,8 @@ function PMA_GIS_modify_query($sql_query, $visualizationSettings)
             . '`) AS `' . $visualizationSettings['spatialColumn'] . '`, ';
 
         // Get the SRID
-        $modified_query .= 'SRID(`' . $visualizationSettings['spatialColumn'] . '`) AS `srid` ';
+        $modified_query .= 'SRID(`' . $visualizationSettings['spatialColumn']
+            . '`) AS `srid` ';
     }
 
     // Append the rest of the query
@@ -98,14 +101,16 @@ function PMA_GIS_modify_query($sql_query, $visualizationSettings)
 function sanitize($select)
 {
     $table_col = $select['table_name'] . "." . $select['column'];
-    $db_table_col = $select['db'] . "." . $select['table_name'] . "." . $select['column'];
+    $db_table_col = $select['db'] . "." . $select['table_name']
+        . "." . $select['column'];
 
     if ($select['expr'] == $select['column']) {
         return "`" . $select['column'] . "`";
     } elseif ($select['expr'] == $table_col) {
         return "`" . $select['table_name'] . "`.`" . $select['column'] . "`";
     } elseif ($select['expr'] == $db_table_col) {
-        return "`" . $select['db'] . "`.`" . $select['table_name'] . "`.`" . $select['column'] . "`";
+        return "`" . $select['db'] . "`.`" . $select['table_name']
+            . "`.`" . $select['column'] . "`";
     }
     return $select['expr'];
 }
@@ -119,7 +124,7 @@ function sanitize($select)
  *
  * @return string HTML and JS code for the GIS visualization
  */
-function PMA_GIS_visualization_results($data, &$visualizationSettings, $format)
+function PMA_GIS_visualizationResults($data, &$visualizationSettings, $format)
 {
     include_once './libraries/gis/pma_gis_visualization.php';
     include_once './libraries/gis/pma_gis_factory.php';
@@ -156,7 +161,7 @@ function PMA_GIS_visualization_results($data, &$visualizationSettings, $format)
  *
  * @return file File containing the visualization
  */
-function PMA_GIS_save_to_file($data, $visualizationSettings, $format, $fileName)
+function PMA_GIS_saveToFile($data, $visualizationSettings, $format, $fileName)
 {
     include_once './libraries/gis/pma_gis_visualization.php';
     include_once './libraries/gis/pma_gis_factory.php';
diff --git a/libraries/import.lib.php b/libraries/import.lib.php
index 0d0239c..df4290e 100644
--- a/libraries/import.lib.php
+++ b/libraries/import.lib.php
@@ -425,6 +425,7 @@ define("VARCHAR",   1);
 define("INT",       2);
 define("DECIMAL",   3);
 define("BIGINT",    4);
+define("GEOMETRY",  5);
 
 /* Decimal size defs */
 define("M",         0);
@@ -437,8 +438,9 @@ define("COL_NAMES", 1);
 define("ROWS",      2);
 
 /* Analysis array defs */
-define("TYPES",     0);
-define("SIZES",     1);
+define("TYPES",        0);
+define("SIZES",        1);
+define("FORMATTEDSQL", 2);
 
 /**
  * Obtains the precision (total # of digits) from a size of type decimal
@@ -916,7 +918,7 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = null, &$additional_sql =
     }
 
     if ($analyses != null) {
-        $type_array = array(NONE => "NULL", VARCHAR => "varchar", INT => "int", DECIMAL => "decimal", BIGINT => "bigint");
+        $type_array = array(NONE => "NULL", VARCHAR => "varchar", INT => "int", DECIMAL => "decimal", BIGINT => "bigint", GEOMETRY => 'geometry');
 
         /* TODO: Do more checking here to make sure they really are matched */
         if (count($tables) != count($analyses)) {
@@ -935,7 +937,10 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = null, &$additional_sql =
                     $size = 10;
                 }
 
-                $tempSQLStr .= PMA_backquote($tables[$i][COL_NAMES][$j]) . " " . $type_array[$analyses[$i][TYPES][$j]] . "(" . $size . ")";
+                $tempSQLStr .= PMA_backquote($tables[$i][COL_NAMES][$j]) . " " . $type_array[$analyses[$i][TYPES][$j]];
+                if ($analyses[$i][TYPES][$j] != GEOMETRY) {
+                    $tempSQLStr .= "(" . $size . ")";
+                }
 
                 if ($j != (count($tables[$i][COL_NAMES]) - 1)) {
                     $tempSQLStr .= ", ";
@@ -980,20 +985,28 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = null, &$additional_sql =
             $tempSQLStr .= "(";
 
             for ($k = 0; $k < $num_cols; ++$k) {
-                if ($analyses != null) {
-                    $is_varchar = ($analyses[$i][TYPES][$col_count] === VARCHAR);
+                // If fully formatted SQL, no need to enclose with aphostrophes, add shalshes etc.
+                if ($analyses != null
+                    && isset($analyses[$i][FORMATTEDSQL][$col_count])
+                    && $analyses[$i][FORMATTEDSQL][$col_count] == true
+                ) {
+                    $tempSQLStr .= (string) $tables[$i][ROWS][$j][$k];
                 } else {
-                    $is_varchar = !is_numeric($tables[$i][ROWS][$j][$k]);
-                }
+                    if ($analyses != null) {
+                        $is_varchar = ($analyses[$i][TYPES][$col_count] === VARCHAR);
+                    } else {
+                        $is_varchar = !is_numeric($tables[$i][ROWS][$j][$k]);
+                    }
 
-                /* Don't put quotes around NULL fields */
-                if (! strcmp($tables[$i][ROWS][$j][$k], 'NULL')) {
-                    $is_varchar = false;
-                }
+                    /* Don't put quotes around NULL fields */
+                    if (! strcmp($tables[$i][ROWS][$j][$k], 'NULL')) {
+                        $is_varchar = false;
+                    }
 
-                $tempSQLStr .= (($is_varchar) ? "'" : "");
-                $tempSQLStr .= PMA_sqlAddSlashes((string)$tables[$i][ROWS][$j][$k]);
-                $tempSQLStr .= (($is_varchar) ? "'" : "");
+                    $tempSQLStr .= (($is_varchar) ? "'" : "");
+                    $tempSQLStr .= PMA_sqlAddSlashes((string)$tables[$i][ROWS][$j][$k]);
+                    $tempSQLStr .= (($is_varchar) ? "'" : "");
+                }
 
                 if ($k != ($num_cols - 1)) {
                     $tempSQLStr .= ", ";
diff --git a/libraries/import/shp.php b/libraries/import/shp.php
new file mode 100644
index 0000000..7ee62fd
--- /dev/null
+++ b/libraries/import/shp.php
@@ -0,0 +1,399 @@
+<?php
+/**
+ * ESRI Shape file import plugin for phpMyAdmin
+ *
+ * @package phpMyAdmin-Import
+ * @subpackage ESRI_Shape
+ */
+if (! defined('PHPMYADMIN')) {
+    exit;
+}
+
+if (isset($plugin_list)) {
+    $plugin_list['shp'] = array(
+        'text' => __('ESRI Shape File'),
+        'extension' => 'shp',
+        'options' => array(),
+        'options_text' => __('Options'),
+    );
+} else {
+
+    if ((int) ini_get('memory_limit') < 512) {
+        ini_set('memory_limit', '512M');
+    }
+    set_time_limit(300);
+
+
+    // Append the bfShapeFiles directory to the include path variable
+    set_include_path(get_include_path() . PATH_SEPARATOR . getcwd() . '/libraries/bfShapeFiles/');
+    require_once './libraries/bfShapeFiles/ShapeFile.lib.php';
+
+    $GLOBALS['finished'] = false;
+    $buffer = '';
+    $eof = false;
+
+    // Returns specified number of bytes from the buffer.
+    // Buffer automatically fetches next chunk of data when the buffer falls short.
+    // Sets $eof when $GLOBALS['finished'] is set and the buffer falls short.
+    function readFromBuffer($length){
+        global $buffer, $eof;
+
+        if (strlen($buffer) < $length) {
+            if ($GLOBALS['finished']) {
+                $eof = true;
+            } else {
+                $buffer .= PMA_importGetNextChunk();
+            }
+        }
+        $result = substr($buffer, 0, $length);
+        $buffer = substr($buffer, $length);
+        return $result;
+    }
+
+    /**
+     * This class extends ShapeFile class to cater following phpMyAdmin specific requirements.
+     * 1) To load data from .dbf file only when the dBase extension is available.
+     * 2) To use PMA_importGetNextChunk() functionality to read data, rather than reading directly from a file.
+     *    Using readFromBuffer() in place of fread(). This makes it possible to use compressions.
+     */
+    class PMA_ShapeFile extends ShapeFile {
+
+        function _isDbaseLoaded()
+        {
+            return extension_loaded('dbase');
+        }
+
+        function loadFromFile($FileName)
+        {
+            $this->_loadHeaders();
+            $this->_loadRecords();
+            if ($this->_isDbaseLoaded()) {
+                $this->_closeDBFFile();
+            }
+        }
+
+        function _loadHeaders()
+        {
+            readFromBuffer(24);
+            $this->fileLength = loadData("N", readFromBuffer(4));
+
+            readFromBuffer(4);
+            $this->shapeType = loadData("V", readFromBuffer(4));
+
+            $this->boundingBox = array();
+            $this->boundingBox["xmin"] = loadData("d", readFromBuffer(8));
+            $this->boundingBox["ymin"] = loadData("d", readFromBuffer(8));
+            $this->boundingBox["xmax"] = loadData("d", readFromBuffer(8));
+            $this->boundingBox["ymax"] = loadData("d", readFromBuffer(8));
+
+            if ($this->_isDbaseLoaded() && $this->_openDBFFile()) {
+                $this->DBFHeader = $this->_loadDBFHeader();
+            }
+        }
+
+        function _loadRecords()
+        {
+            global $eof;
+            readFromBuffer(32);
+            while (true) {
+                $record = new PMA_ShapeRecord(-1);
+                $record->loadFromFile($this->SHPFile, $this->DBFFile);
+                if ($record->lastError != "") {
+                    return false;
+                }
+                if ($eof) {
+                    break;
+                }
+
+                $this->records[] = $record;
+            }
+        }
+    }
+
+    /**
+     * This class extends ShapeRecord class to cater following phpMyAdmin specific requirements.
+     * 1) To load data from .dbf file only when the dBase extension is available.
+     * 2) To use PMA_importGetNextChunk() functionality to read data, rather than reading directly from a file.
+     *    Using readFromBuffer() in place of fread(). This makes it possible to use compressions.
+     */
+    class PMA_ShapeRecord extends ShapeRecord {
+
+        function loadFromFile(&$SHPFile, &$DBFFile)
+        {
+            $this->DBFFile = $DBFFile;
+            $this->_loadHeaders();
+
+            switch ($this->shapeType) {
+                case 0:
+                    $this->_loadNullRecord();
+                    break;
+                case 1:
+                    $this->_loadPointRecord();
+                    break;
+                case 3:
+                    $this->_loadPolyLineRecord();
+                    break;
+                case 5:
+                    $this->_loadPolygonRecord();
+                    break;
+                case 8:
+                    $this->_loadMultiPointRecord();
+                    break;
+                default:
+                    $this->setError(sprintf("The Shape Type '%s' is not supported.", $this->shapeType));
+                    break;
+            }
+            if (extension_loaded('dbase') && isset($this->DBFFile)) {
+                $this->_loadDBFData();
+            }
+        }
+
+        function _loadHeaders()
+        {
+            $this->recordNumber = loadData("N", readFromBuffer(4));
+            $tmp = loadData("N", readFromBuffer(4)); //We read the length of the record
+            $this->shapeType = loadData("V", readFromBuffer(4));
+        }
+
+        function _loadPoint()
+        {
+            $data = array();
+
+            $data["x"] = loadData("d", readFromBuffer(8));
+            $data["y"] = loadData("d", readFromBuffer(8));
+
+            return $data;
+        }
+
+        function _loadMultiPointRecord()
+        {
+            $this->SHPData = array();
+            $this->SHPData["xmin"] = loadData("d", readFromBuffer(8));
+            $this->SHPData["ymin"] = loadData("d", readFromBuffer(8));
+            $this->SHPData["xmax"] = loadData("d", readFromBuffer(8));
+            $this->SHPData["ymax"] = loadData("d", readFromBuffer(8));
+
+            $this->SHPData["numpoints"] = loadData("V", readFromBuffer(4));
+
+            for ($i = 0; $i <= $this->SHPData["numpoints"]; $i++) {
+                $this->SHPData["points"][] = $this->_loadPoint();
+            }
+        }
+
+        function _loadPolyLineRecord()
+        {
+            $this->SHPData = array();
+            $this->SHPData["xmin"] = loadData("d", readFromBuffer(8));
+            $this->SHPData["ymin"] = loadData("d", readFromBuffer(8));
+            $this->SHPData["xmax"] = loadData("d", readFromBuffer(8));
+            $this->SHPData["ymax"] = loadData("d", readFromBuffer(8));
+
+            $this->SHPData["numparts"]  = loadData("V", readFromBuffer(4));
+            $this->SHPData["numpoints"] = loadData("V", readFromBuffer(4));
+
+            for ($i = 0; $i < $this->SHPData["numparts"]; $i++) {
+                $this->SHPData["parts"][$i] = loadData("V", readFromBuffer(4));
+            }
+
+            $readPoints = 0;
+            reset($this->SHPData["parts"]);
+            while (list($partIndex, $partData) = each($this->SHPData["parts"])) {
+                if (!isset($this->SHPData["parts"][$partIndex]["points"]) || !is_array($this->SHPData["parts"][$partIndex]["points"])) {
+                    $this->SHPData["parts"][$partIndex] = array();
+                    $this->SHPData["parts"][$partIndex]["points"] = array();
+                }
+                while (!in_array($readPoints, $this->SHPData["parts"]) && ($readPoints < ($this->SHPData["numpoints"]))) {
+                    $this->SHPData["parts"][$partIndex]["points"][] = $this->_loadPoint();
+                    $readPoints++;
+                }
+            }
+        }
+    }
+
+    $shp = new PMA_ShapeFile(1);
+    // If the zip archive has more than one file, get the correct content to the buffer from .shp file.
+    if ($compression == 'application/zip' && PMA_getNoOfFilesInZip($import_file) > 1) {
+        $zip_content =  PMA_getZipContents($import_file, '/^.*\.shp$/i');
+        $GLOBALS['import_text'] = $zip_content['data'];
+    }
+
+    $temp_dbf_file = false;
+    // We need dbase extension to handle .dbf file
+    if (extension_loaded('dbase')) {
+        // If we can extract the zip archive to 'TempDir' and use the files in it for import
+        if ($compression == 'application/zip'
+            && ! empty($cfg['TempDir'])
+            && is_writable($cfg['TempDir'])
+        ) {
+            $dbf_file_name = PMA_findFileFromZipArchive('/^.*\.dbf$/i', $import_file);
+            // If the corresponding .dbf file is in the zip archive
+            if ($dbf_file_name) {
+                // Extract the .dbf file and point to it.
+                $extracted =  PMA_zipExtract($import_file, realpath($cfg['TempDir']), array($dbf_file_name));
+                if ($extracted) {
+                    $dbf_file_path = realpath($cfg['TempDir']) . (PMA_IS_WINDOWS ? '\\' : '/') . $dbf_file_name;
+                    $temp_dbf_file = true;
+                    // Replace the .dbf with .*, as required by the bsShapeFiles library.
+                    $file_name = substr($dbf_file_path, 0, strlen($dbf_file_path) - 4) . '.*';
+                    $shp->FileName = $file_name;
+                }
+            }
+        }
+        // If file is in UploadDir, use .dbf file in the same UploadDir to load extra data.
+        elseif (! empty($local_import_file) && ! empty($cfg['UploadDir']) && $compression == 'none') {
+            // Replace the .shp with .*, so the bsShapeFiles library correctly locates .dbf file.
+            $file_name = substr($import_file, 0, strlen($import_file) - 4) . '.*';
+            $shp->FileName = $file_name;
+        }
+    }
+
+    // Load data
+    $shp->loadFromFile('');
+    if ($shp->lastError != "") {
+        $error = true;
+        $message = PMA_Message::error(__('There was an error importing the ESRI shape file: "%s".'));
+        $message->addParam($shp->lastError);
+        return;
+    }
+
+    // Delete the .dbf file extracted to 'TempDir'
+    if ($temp_dbf_file) {
+        unlink($dbf_file_path);
+    }
+
+    $esri_types = array(
+        0  => 'Null Shape',
+        1  => 'Point',
+        3  => 'PolyLine',
+        5  => 'Polygon',
+        8  => 'MultiPoint',
+        11 => 'PointZ',
+        13 => 'PolyLineZ',
+        15 => 'PolygonZ',
+        18 => 'MultiPointZ',
+        21 => 'PointM',
+        23 => 'PolyLineM',
+        25 => 'PolygonM',
+        28 => 'MultiPointM',
+        31 => 'MultiPatch',
+    );
+
+    require_once './libraries/gis/pma_gis_geometry.php';
+    switch ($shp->shapeType) {
+        // ESRI Null Shape
+        case 0:
+            $gis_obj = null;
+            break;
+        // ESRI Point
+        case 1:
+            require_once './libraries/gis/pma_gis_point.php';
+            $gis_obj = PMA_GIS_Point::singleton();
+            break;
+        // ESRI PolyLine
+        case 3:
+            require_once './libraries/gis/pma_gis_multilinestring.php';
+            $gis_obj = PMA_GIS_Multilinestring::singleton();
+            break;
+        // ESRI Polygon
+        case 5:
+            require_once './libraries/gis/pma_gis_multipolygon.php';
+            $gis_obj = PMA_GIS_Multipolygon::singleton();
+            break;
+        // ESRI MultiPoint
+        case 8:
+            require_once './libraries/gis/pma_gis_multipoint.php';
+            $gis_obj = PMA_GIS_Multipoint::singleton();
+            break;
+        default:
+            $error = true;
+            if (! isset($esri_types[$shp->shapeType])) {
+                $message = PMA_Message::error(__('You tried to import an invalid file or the imported file contains invalid data'));
+            } else {
+                $message = PMA_Message::error(__('MySQL Spatial Extension does not support ESRI type "%s".'));
+                $message->addParam($param);
+            }
+            return;
+    }
+
+    $num_rows = count($shp->records);
+    // If .dbf file is loaded, the number of extra data columns
+    $num_data_cols = isset($shp->DBFHeader) ? count($shp->DBFHeader) : 0;
+
+    $rows = array();
+    $col_names = array();
+    if ($num_rows != 0) {
+        foreach($shp->records as $record){
+            $tempRow = array();
+            if ($gis_obj == null) {
+                $tempRow[] = null;
+            } else {
+                $tempRow[] = "GeomFromText('" . $gis_obj->getShape($record->SHPData) . "')";
+            }
+
+            if (isset($shp->DBFHeader)) {
+                foreach ($shp->DBFHeader as $c) {
+                    $cell = trim($record->DBFData[$c[0]]);
+
+                    if (! strcmp($cell, '')) {
+                        $cell = 'NULL';
+                    }
+
+                    $tempRow[] = $cell;
+                }
+            }
+            $rows[] = $tempRow;
+        }
+    }
+
+    if(count($rows) == 0) {
+        $error = true;
+        $message = PMA_Message::error(__('The imported file does not contain any data'));
+        return;
+    }
+
+    // Column names for spatial column and the rest of the columns, if they are available
+    $col_names[] = 'SPATIAL';
+    for ($n = 0; $n < $num_data_cols; $n++) {
+        $col_names[] = $shp->DBFHeader[$n][0];
+    }
+
+    // Set table name based on the number of tables
+    if (strlen($db)) {
+        $result = PMA_DBI_fetch_result('SHOW TABLES');
+        $table_name = 'TABLE '.(count($result) + 1);
+    } else {
+        $table_name = 'TBL_NAME';
+    }
+    $tables = array(array($table_name, $col_names, $rows));
+
+    // Use data from shape file to chose best-fit MySQL types for each column
+    $analyses = array();
+    $analyses[] = PMA_analyzeTable($tables[0]);
+
+    $table_no = 0; $spatial_col = 0;
+    $analyses[$table_no][TYPES][$spatial_col] = GEOMETRY;
+    $analyses[$table_no][FORMATTEDSQL][$spatial_col] = true;
+
+    // Set database name to the currently selected one, if applicable
+    if (strlen($db)) {
+        $db_name = $db;
+        $options = array('create_db' => false);
+    } else {
+        $db_name = 'SHP_DB';
+        $options = null;
+    }
+
+    // Created and execute necessary SQL statements from data
+    $null_param = null;
+    PMA_buildSQL($db_name, $tables, $analyses, $null_param, $options);
+
+    unset($tables);
+    unset($analyses);
+
+    $finished = true;
+    $error = false;
+
+    // Commit any possible data in buffers
+    PMA_importRunQuery();
+}
+?>
diff --git a/libraries/tbl_select.lib.php b/libraries/tbl_select.lib.php
index 6384f60..af97aa4 100644
--- a/libraries/tbl_select.lib.php
+++ b/libraries/tbl_select.lib.php
@@ -3,8 +3,8 @@
 /**
  * Functions for the table-search page and zoom-search page
  *
- * Funtion PMA_tbl_getFields : Returns the fields of a table 
- * Funtion PMA_tbl_search_getWhereClause : Returns the where clause for query generation 
+ * Funtion PMA_tbl_getFields : Returns the fields of a table
+ * Funtion PMA_tbl_search_getWhereClause : Returns the where clause for query generation
  *
  * @package phpMyAdmin
  */
@@ -13,7 +13,7 @@ require_once 'url_generating.lib.php';
 
  /**
  * PMA_tbl_setTitle() sets the title for foreign keys display link
- * 
+ *
  * @param    $propertiesIconic    Type of icon property
  * @param    $themeImage          Icon Image
  * @return   string $str          Value of the Title
@@ -51,20 +51,26 @@ function PMA_tbl_setTitle($propertiesIconic,$pmaThemeImage){
  * @param    $db    								Selected database
  * @param    $table    								Selected table
  *
- * @return   array($fields_list,$fields_type,$fields_collation,$fields_null)    Array containing the field list, field types, collations and null constatint       
+ * @return   array($fields_list,$fields_type,$fields_collation,$fields_null)    Array containing the field list, field types, collations and null constatint
  *
  */
 
 function PMA_tbl_getFields($table,$db) {
-    
+
     // Gets the list and number of fields
 
     $result     = PMA_DBI_query('SHOW FULL FIELDS FROM ' . PMA_backquote($table) . ' FROM ' . PMA_backquote($db) . ';', null, PMA_DBI_QUERY_STORE);
     $fields_cnt = PMA_DBI_num_rows($result);
     $fields_list = $fields_null = $fields_type = $fields_collation = array();
+    $geom_column_present = false;
+    $geom_types = PMA_getGISDatatypes();
     while ($row = PMA_DBI_fetch_assoc($result)) {
         $fields_list[] = $row['Field'];
         $type          = $row['Type'];
+        // check whether table contains geometric columns
+        if (in_array($type, $geom_types)) {
+            $geom_column_present = true;
+        }
         // reformat mysql query output
         if (strncasecmp($type, 'set', 3) == 0
             || strncasecmp($type, 'enum', 4) == 0) {
@@ -93,20 +99,26 @@ function PMA_tbl_getFields($table,$db) {
     PMA_DBI_free_result($result);
     unset($result, $type);
 
-    return array($fields_list,$fields_type,$fields_collation,$fields_null);
-   
+    return array($fields_list,$fields_type,$fields_collation,$fields_null, $geom_column_present);
+
 }
 
 /* PMA_tbl_setTableHeader() sets the table header for displaying a table in query-by-example format
  *
- * @return   HTML content, the tags and content for table header       
+ * @return   HTML content, the tags and content for table header
  *
  */
 
-function PMA_tbl_setTableHeader(){
+function PMA_tbl_setTableHeader($geom_column_present = false){
+
+    // Display the Function column only if there is alteast one geomety colum
+    $func = '';
+    if ($geom_column_present) {
+        $func = '<th>' . __('Function') . '</th>';
+    }
 
 return '<thead>
-        <tr><th>' .  __('Column') . '</th>
+        <tr>' . $func . '<th>' .  __('Column') . '</th>
         <th>' .  __('Type') . '</th>
         <th>' .  __('Collation') . '</th>
         <th>' .  __('Operator') . '</th>
@@ -117,9 +129,9 @@ return '<thead>
 
 }
 
-/* PMA_tbl_getSubTabs() returns an array with necessary configrations to create sub-tabs(Table Search and Zoom Search) in the table_select page 
+/* PMA_tbl_getSubTabs() returns an array with necessary configrations to create sub-tabs(Table Search and Zoom Search) in the table_select page
  *
- * @return   array $subtabs    Array containing configuration (icon,text,link,id,args) of sub-tabs for Table Search and Zoom search       
+ * @return   array $subtabs    Array containing configuration (icon,text,link,id,args) of sub-tabs for Table Search and Zoom search
  *
  */
 
@@ -137,7 +149,7 @@ function PMA_tbl_getSubTabs(){
     $subtabs['zoom']['link'] = 'tbl_zoom_select.php';
     $subtabs['zoom']['text'] = __('Zoom Search');
     $subtabs['zoom']['id'] = 'zoom_search_id';
-	
+
     return $subtabs;
 
 }
@@ -164,12 +176,13 @@ function PMA_tbl_getSubTabs(){
  * @param    $titles              Selected title
  * @param    $foreignMaxLimit     Max limit of displaying foreign elements
  * @param    $fields              Array of search criteria inputs
+ * @param    $in_fbs              In function based search
  *
- * @return   string $str    HTML content for viewing foreing data and elements for search criteria input.       
+ * @return   string $str    HTML content for viewing foreing data and elements for search criteria input.
  *
  */
 
-function PMA_getForeignFields_Values($foreigners, $foreignData, $field, $tbl_fields_type, $i, $db, $table,$titles,$foreignMaxLimit, $fields){
+function PMA_getForeignFields_Values($foreigners, $foreignData, $field, $tbl_fields_type, $i, $db, $table, $titles, $foreignMaxLimit, $fields, $in_fbs = false){
 
     $str = '';
 
@@ -185,29 +198,40 @@ function PMA_getForeignFields_Values($foreigners, $foreignData, $field, $tbl_fie
                 $foreignData['foreign_display'],
                 '', $foreignMaxLimit);
         $str .= '            </select>' . "\n";
-    } 
+    }
     elseif ($foreignData['foreign_link'] == true) {
         if(isset($fields[$i]) && is_string($fields[$i])){
  	    $str .= '<input type="text" id="fieldID_' . $i .'"name="fields[' . $i . '] " value="' . $fields[$i] . '"';
-		     'id="field_' . md5($field) . '[' . $i .']" 
-		     class="textfield"/>' ; 
+		     'id="field_' . md5($field) . '[' . $i .']"
+		     class="textfield"/>' ;
         }
         else{
  	    $str .= '<input type="text" id="fieldID_' . $i .'"name="fields[' . $i . '] "';
-		     'id="field_' . md5($field) . '[' . $i .']" 
-		     class="textfield" />' ; 
+		     'id="field_' . md5($field) . '[' . $i .']"
+		     class="textfield" />' ;
         }
  ?>
 	<?php $str .= '<script type="text/javascript">';
         // <![CDATA[
 	$str .=  <<<EOT
-<a target="_blank" onclick="window.open(this.href, 'foreigners', 'width=640,height=240,scrollbars=yes'); return false" href="browse_foreigners.php? 
+<a target="_blank" onclick="window.open(this.href, 'foreigners', 'width=640,height=240,scrollbars=yes'); return false" href="browse_foreigners.php?
 EOT;
         $str .= '' . PMA_generate_common_url($db, $table) .  '&field=' . urlencode($field) . '&fieldkey=' . $i . '">' . str_replace("'", "\'", $titles['Browse']) . '</a>';
         // ]]
         $str .= '</script>';
-        } 
-    elseif (strncasecmp($tbl_fields_type[$i], 'enum', 4) == 0) {
+    } elseif (in_array($tbl_fields_type[$i], PMA_getGISDatatypes())) {
+        // g e o m e t r y
+        $str .= '<input type="text" name="fields[' . $i . ']"'
+        .' size="40" class="textfield" id="field_' . $i . '" />' .  "\n";
+
+        if ($in_fbs) {
+            $edit_url = 'gis_data_editor.php?' . PMA_generate_common_url();
+            $edit_str = PMA_getIcon('b_edit.png', __('Edit/Insert'), true);
+            $str .= '<span class="open_search_gis_editor">';
+            $str .= PMA_linkOrButton($edit_url, $edit_str, array(), false, false, '_blank');
+            $str .= '</span>';
+        }
+    } elseif (strncasecmp($tbl_fields_type[$i], 'enum', 4) == 0) {
         // e n u m s
         $enum_value=explode(', ', str_replace("'", '', substr($tbl_fields_type[$i], 5, -1)));
         $cnt_enum_value = count($enum_value);
@@ -224,7 +248,7 @@ EOT;
                         }
                 } // end for
         $str .= '            </select>' . "\n";
-    } 
+    }
     else {
         // o t h e r   c a s e s
         $the_class = 'textfield';
@@ -267,17 +291,61 @@ EOT;
  * @param    $func_type     Search fucntion/operator
  * @param    $unaryFlag     Whether operator unary or not
  *
- * @return   string $str    HTML content for viewing foreing data and elements for search criteria input.       
+ * @return   string $str    HTML content for viewing foreing data and elements for search criteria input.
  *
  */
 
-function PMA_tbl_search_getWhereClause($fields, $names, $types, $collations, $func_type, $unaryFlag){
-	
+function PMA_tbl_search_getWhereClause($fields, $names, $types, $collations, $func_type, $unaryFlag, $geom_func = null){
+
+    /**
+     * @todo move this to a more apropriate place
+     */
+    $geom_unary_functions = array(
+        'IsEmpty' => 1,
+        'IsSimple' => 1,
+        'IsRing' => 1,
+        'IsClosed' => 1,
+    );
+
+    $w = '';
+
+    // If geometry function is set apply it to the field name
+    if ($geom_func != null && trim($geom_func) != '') {
+        // Get details about the geometry fucntions
+        $geom_funcs = PMA_getGISFunctions($types, true, false);
+
+        // If the function takes a single parameter
+        if ($geom_funcs[$geom_func]['params'] == 1) {
+            $backquoted_name = $geom_func . '(' . PMA_backquote($names) . ')';
+            // If the function takes two parameters
+        } else {
+            // create gis data from the string
+            $gis_data = PMA_createGISData($fields);
+
+            $w = $geom_func . '(' . PMA_backquote($names) . ',' . $gis_data . ')';
+            return $w;
+        }
+
+        // New output type is the output type of the function being applied
+        $types = $geom_funcs[$geom_func]['type'];
+
+        // If the intended where clause is something like 'IsEmpty(`spatial_col_name`)'
+        if (isset($geom_unary_functions[$geom_func]) && trim($fields) == '') {
+            $w = $backquoted_name;
+            return $w;
+        }
+    } else {
+        $backquoted_name = PMA_backquote($names);
+    }
 
-    $w = ''; 
     if($unaryFlag){
         $fields = '';
-            $w = PMA_backquote($names) . ' ' . $func_type;
+            $w = $backquoted_name . ' ' . $func_type;
+
+    } elseif (in_array($types, PMA_getGISDatatypes())) {
+        // create gis data from the string
+        $gis_data = PMA_createGISData($fields);
+        $w = $backquoted_name . ' ' . $func_type . ' ' . $gis_data;
 
     } elseif (strncasecmp($types, 'enum', 4) == 0) {
         if (!empty($fields)) {
@@ -304,7 +372,7 @@ function PMA_tbl_search_getWhereClause($fields, $names, $types, $collations, $fu
                    $enum_where .= ', \'' . PMA_sqlAddslashes($fields[$e]) . '\'';
                }
 
-               $w = PMA_backquote($names) . ' ' . $func_type . ' ' . $parens_open . $enum_where . $parens_close;
+               $w = $backquoted_name . ' ' . $func_type . ' ' . $parens_open . $enum_where . $parens_close;
         }
 
     } elseif ($fields != '') {
@@ -336,12 +404,12 @@ function PMA_tbl_search_getWhereClause($fields, $names, $types, $collations, $fu
             $value = $quot . PMA_sqlAddslashes(trim($value)) . $quot;
 
             if ($func_type == 'BETWEEN' || $func_type == 'NOT BETWEEN')
-                $w = PMA_backquote($names) . ' ' . $func_type . ' ' . (isset($values[0]) ? $values[0] : '')  . ' AND ' . (isset($values[1]) ? $values[1] : '');
+                $w = $backquoted_name . ' ' . $func_type . ' ' . (isset($values[0]) ? $values[0] : '')  . ' AND ' . (isset($values[1]) ? $values[1] : '');
             else
-                $w = PMA_backquote($names) . ' ' . $func_type . ' (' . implode(',', $values) . ')';
+                $w = $backquoted_name . ' ' . $func_type . ' (' . implode(',', $values) . ')';
         }
         else {
-            $w = PMA_backquote($names) . ' ' . $func_type . ' ' . $quot . PMA_sqlAddslashes($fields) . $quot;;
+            $w = $backquoted_name . ' ' . $func_type . ' ' . $quot . PMA_sqlAddslashes($fields) . $quot;;
         }
 
     } // end if
diff --git a/libraries/zip_extension.lib.php b/libraries/zip_extension.lib.php
index b665b74..7bfa848 100644
--- a/libraries/zip_extension.lib.php
+++ b/libraries/zip_extension.lib.php
@@ -9,12 +9,12 @@
 /**
   * Gets zip file contents
   *
-  * @param string  $file
+  * @param string $specific_entry regular expression to match a file
   * @return  array  ($error_message, $file_data); $error_message
   *                  is empty if no error
   */
 
-function PMA_getZipContents($file)
+function PMA_getZipContents($file, $specific_entry = null)
 {
     $error_message = '';
     $file_data = '';
@@ -28,11 +28,15 @@ function PMA_getZipContents($file)
             $read = zip_entry_read($first_zip_entry);
             $ods_mime = 'application/vnd.oasis.opendocument.spreadsheet';
             if (!strcmp($ods_mime, $read)) {
+                $specific_entry = '/^content\.xml$/';
+            }
+
+            if (isset($specific_entry)) {
                 /* Return the correct contents, not just the first entry */
                 for ( ; ; ) {
                     $entry = zip_read($zip_handle);
                     if (is_resource($entry)) {
-                        if (!strcmp('content.xml', zip_entry_name($entry))) {
+                        if (preg_match($specific_entry, zip_entry_name($entry))) {
                             zip_entry_open($zip_handle, $entry, 'r');
                             $file_data = zip_entry_read($entry, zip_entry_filesize($entry));
                             zip_entry_close($entry);
@@ -41,15 +45,15 @@ function PMA_getZipContents($file)
                     } else {
                         /**
                          * Either we have reached the end of the zip and still
-                         * haven't found 'content.xml' or there was a parsing
+                         * haven't found $specific_entry or there was a parsing
                          * error that we must display
                          */
                         if ($entry === false) {
-                            $error_message = __('Error in ZIP archive:') . ' Could not find "content.xml"';
+                            $error_message = __('Error in ZIP archive:') . ' Could not find "' . $specific_entry . '"';
                         } else {
                             $error_message = __('Error in ZIP archive:') . ' ' . PMA_getZipError($zip_handle);
                         }
-                        
+
                         break;
                     }
                 }
@@ -69,6 +73,69 @@ function PMA_getZipContents($file)
 }
 
 /**
+ * Returns the file name of the first file that matches the given $file_regexp.
+ *
+ * @param string $file_regexp regular expression for the file name to match
+ * @param string $file        zip archive
+ */
+function PMA_findFileFromZipArchive ($file_regexp, $file)
+{
+    $zip_handle = zip_open($file);
+    $found = false;
+    if (is_resource($zip_handle)) {
+        $entry = zip_read($zip_handle);
+        while (is_resource($entry)) {
+            if (preg_match($file_regexp, zip_entry_name($entry))) {
+                $file_name = zip_entry_name($entry);
+                zip_close($zip_handle);
+                return $file_name;
+            }
+            $entry = zip_read($zip_handle);
+        }
+    }
+    zip_close($zip_handle);
+    return false;
+}
+
+/**
+ * Returns the number of files in the zip archive.
+ *
+ * @param string $file
+ */
+function PMA_getNoOfFilesInZip($file)
+{
+    $count = 0;
+    $zip_handle = zip_open($file);
+    $found = false;
+    if (is_resource($zip_handle)) {
+        $entry = zip_read($zip_handle);
+        while (is_resource($entry)) {
+            $count++;
+            $entry = zip_read($zip_handle);
+        }
+    }
+    zip_close($zip_handle);
+    return $count;
+}
+
+/**
+ * Extracts a set of files from the given zip archive to a given destinations.
+ *
+ * @param string $zip_path
+ * @param string $destination
+ * @param array  $entries
+ */
+function PMA_zipExtract($zip_path, $destination, $entries) {
+    $zip = new ZipArchive;
+    if ($zip->open($zip_path) === true) {
+        $zip->extractTo($destination, $entries);
+        $zip->close();
+        return true;
+    }
+    return false;
+}
+
+/**
   * Gets zip error message
   *
   * @param integer  error code
diff --git a/sql.php b/sql.php
index 6e5a05d..e2d956d 100644
--- a/sql.php
+++ b/sql.php
@@ -18,6 +18,15 @@ $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js';
 $GLOBALS['js_include'][] = 'jquery/timepicker.js';
 $GLOBALS['js_include'][] = 'tbl_change.js';
 
+// required for GIS editor loaded via AJAX
+$GLOBALS['js_include'][] = 'gis_data_editor.js';
+$GLOBALS['js_include'][] = 'jquery/jquery.svg.js';
+$GLOBALS['js_include'][] = 'jquery/jquery.mousewheel.js';
+$GLOBALS['js_include'][] = 'jquery/jquery.event.drag-2.0.min.js';
+$GLOBALS['js_include'][] = 'tbl_gis_visualization.js';
+$GLOBALS['js_include'][] = 'openlayers/OpenLayers.js';
+$GLOBALS['js_include'][] = 'OpenStreetMap.js';
+
 if (isset($_SESSION['profiling'])) {
     $GLOBALS['js_include'][] = 'highcharts/highcharts.js';
     /* Files required for chart exporting */
diff --git a/tbl_change.php b/tbl_change.php
index 9148ef3..5329f15 100644
--- a/tbl_change.php
+++ b/tbl_change.php
@@ -118,6 +118,16 @@ $GLOBALS['js_include'][] = 'functions.js';
 $GLOBALS['js_include'][] = 'tbl_change.js';
 $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js';
 $GLOBALS['js_include'][] = 'jquery/timepicker.js';
+
+// required for GIS editor
+$GLOBALS['js_include'][] = 'gis_data_editor.js';
+$GLOBALS['js_include'][] = 'jquery/jquery.svg.js';
+$GLOBALS['js_include'][] = 'jquery/jquery.mousewheel.js';
+$GLOBALS['js_include'][] = 'jquery/jquery.event.drag-2.0.min.js';
+$GLOBALS['js_include'][] = 'tbl_gis_visualization.js';
+$GLOBALS['js_include'][] = 'openlayers/OpenLayers.js';
+$GLOBALS['js_include'][] = 'OpenStreetMap.js';
+
 /**
  * HTTP and HTML headers
  */
@@ -472,6 +482,9 @@ foreach ($rows as $row_id => $vrow) {
 
          <?php } //End if
 
+        // Get a list of GIS data types.
+        $gis_data_types = PMA_getGISDatatypes();
+
         // Prepares the field value
         $real_null_value = false;
         $special_chars_encoded = '';
@@ -484,6 +497,10 @@ foreach ($rows as $row_id => $vrow) {
                 $data            = $vrow[$field['Field']];
             } elseif ($field['True_Type'] == 'bit') {
                 $special_chars = PMA_printable_bit_value($vrow[$field['Field']], $extracted_fieldspec['spec_in_brackets']);
+            } elseif (in_array($field['True_Type'], $gis_data_types)) {
+                // Convert gis data to Well Know Text format
+                $vrow[$field['Field']] = PMA_asWKT($vrow[$field['Field']], true);
+                $special_chars = htmlspecialchars($vrow[$field['Field']]);
             } else {
                 // special binary "characters"
                 if ($field['is_binary'] || ($field['is_blob'] && ! $cfg['ProtectBinary'])) {
@@ -897,7 +914,6 @@ foreach ($rows as $row_id => $vrow) {
                 }
             } // end if (web-server upload directory)
         } // end elseif (binary or blob)
-
         elseif (in_array($field['pma_type'], $no_support_types)) {
             // ignore this column to avoid changing it
         } else {
@@ -965,6 +981,21 @@ foreach ($rows as $row_id => $vrow) {
                 }
             }
         }
+        if (in_array($field['pma_type'], $gis_data_types)) {
+            $data_val = isset($vrow[$field['Field']]) ? $vrow[$field['Field']] : '';
+            $_url_params = array(
+                'field' => $field['Field_title'],
+                'value' => $data_val,
+             );
+            if ($field['pma_type'] != 'geometry') {
+                $_url_params = $_url_params + array('gis_data[gis_type]' => strtoupper($field['pma_type']));
+            }
+            $edit_url = 'gis_data_editor.php' . PMA_generate_common_url($_url_params);
+            $edit_str = PMA_getIcon('b_edit.png', __('Edit/Insert'), true);
+            echo('<span class="open_gis_editor">');
+            echo(PMA_linkOrButton($edit_url, $edit_str, array(), false, false, '_blank'));
+            echo('</span>');
+        }
         ?>
             </td>
         </tr>
@@ -975,8 +1006,8 @@ foreach ($rows as $row_id => $vrow) {
     echo '  </tbody></table><br />';
 } // end foreach on multi-edit
 ?>
+    <div id="gis_editor"></div><div id="popup_background"></div>
     <br />
-
     <fieldset id="actions_panel">
     <table border="0" cellpadding="5" cellspacing="0">
     <tr>
diff --git a/tbl_gis_visualization.php b/tbl_gis_visualization.php
index 5c54b2f..31bcd81 100644
--- a/tbl_gis_visualization.php
+++ b/tbl_gis_visualization.php
@@ -20,6 +20,7 @@ $GLOBALS['js_include'][] = 'jquery/jquery.svg.js';
 $GLOBALS['js_include'][] = 'jquery/jquery.mousewheel.js';
 $GLOBALS['js_include'][] = 'jquery/jquery.event.drag-2.0.min.js';
 $GLOBALS['js_include'][] = 'tbl_gis_visualization.js';
+$GLOBALS['js_include'][] = 'OpenStreetMap.js';
 
 // Allows for resending headers even after sending some data
 ob_start();
@@ -63,7 +64,7 @@ if (! isset($visualizationSettings['spatialColumn'])) {
 }
 
 // Convert geometric columns from bytes to text.
-$modified_query = PMA_GIS_modify_query($sql_query, $visualizationSettings);
+$modified_query = PMA_GIS_modifyQuery($sql_query, $visualizationSettings);
 $modified_result = PMA_DBI_try_query($modified_query);
 
 $data = array();
@@ -89,7 +90,7 @@ if (isset($_REQUEST['saveToFile'])) {
     }
 
     $save_format = $_REQUEST['fileFormat'];
-    PMA_GIS_save_to_file($data, $visualizationSettings, $save_format, $file_name);
+    PMA_GIS_saveToFile($data, $visualizationSettings, $save_format, $file_name);
     exit();
 }
 
@@ -97,7 +98,7 @@ $svg_support = (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER <= 8) ? fal
 $format = $svg_support ? 'svg' : 'png';
 
 // get the chart and settings after chart generation
-$visualization = PMA_GIS_visualization_results($data, $visualizationSettings, $format);
+$visualization = PMA_GIS_visualizationResults($data, $visualizationSettings, $format);
 
 /**
  * Displays the page
@@ -115,39 +116,9 @@ $visualization = PMA_GIS_visualization_results($data, $visualizationSettings, $f
     <div id="openlayersmap"></div>
     <input type="hidden" id="pmaThemeImage" value="<?php echo($GLOBALS['pmaThemeImage']); ?>" />
 
-    <script type="text/javascript" src="http://www.openstreetmap.org/openlayers/OpenStreetMap.js"></script>
     <script language="javascript" type="text/javascript">
         function drawOpenLayers() {
-            var options = {
-                projection: new OpenLayers.Projection("EPSG:900913"),
-                displayProjection: new OpenLayers.Projection("EPSG:4326"),
-                units: "m",
-                numZoomLevels: 18,
-                maxResolution: 156543.0339,
-                maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508),
-                restrictedExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508)
-            };
-            var map = new OpenLayers.Map('openlayersmap', options);
-
-            // create OSM layer
-            var layerNone = new OpenLayers.Layer.Boxes("None", {isBaseLayer: true});
-            var layerMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");
-            var layerOsmarender = new OpenLayers.Layer.OSM.Osmarender("Osmarender");
-            var layerCycleMap = new OpenLayers.Layer.OSM.CycleMap("CycleMap");
-            map.addLayers([layerMapnik, layerOsmarender, layerCycleMap, layerNone]);
-
-            // create a vector layer
-            var vectorLayer = new OpenLayers.Layer.Vector("Data");
-            var bound;
-            <?php echo (PMA_GIS_visualization_results($data, $visualizationSettings, 'ol')); ?>
-            map.addLayer(vectorLayer);
-
-            map.zoomToExtent(bound);
-            if (map.getZoom() < 2) {
-                map.zoomTo(2);
-            }
-            map.addControl(new OpenLayers.Control.LayerSwitcher());
-            map.addControl(new OpenLayers.Control.MousePosition());
+            <?php echo (PMA_GIS_visualizationResults($data, $visualizationSettings, 'ol')); ?>
         }
     </script>
 
diff --git a/tbl_replace.php b/tbl_replace.php
index a14574a..460908e 100644
--- a/tbl_replace.php
+++ b/tbl_replace.php
@@ -153,6 +153,28 @@ $func_optional_param = array(
     'UNIX_TIMESTAMP',
 );
 
+$gis_from_text_functions = array(
+    'GeomFromText',
+    'GeomCollFromText',
+    'LineFromText',
+    'MLineFromText',
+    'PointFromText',
+    'MPointFromText',
+    'PolyFromText',
+    'MPolyFromText',
+);
+
+$gis_from_wkb_functions = array(
+    'GeomFromWKB',
+    'GeomCollFromWKB',
+    'LineFromWKB',
+    'MLineFromWKB',
+    'PointFromWKB',
+    'MPointFromWKB',
+    'PolyFromWKB',
+    'MPolyFromWKB',
+);
+
 foreach ($loop_array as $rownumber => $where_clause) {
     // skip fields to be ignored
     if (! $using_key && isset($_REQUEST['insert_ignore_' . $where_clause])) {
@@ -238,10 +260,19 @@ foreach ($loop_array as $rownumber => $where_clause) {
             /* This way user will know what UUID new row has */
             $uuid = PMA_DBI_fetch_value('SELECT UUID()');
             $cur_value = "'" . $uuid . "'";
-        } elseif (!in_array($me_funcs[$key], $func_no_param)
+        } elseif ((in_array($me_funcs[$key], $gis_from_text_functions)
+            && substr($val, 0, 3) == "'''")
+            || in_array($me_funcs[$key], $gis_from_wkb_functions)
+        ) {
+            // Remove enclosing apostrophes
+            $val = substr($val, 1, strlen($val) - 2);
+            // Remove escaping apostrophes
+            $val = str_replace("''", "'", $val);
+            $cur_value = $me_funcs[$key] . '(' . $val . ')';
+        } elseif (! in_array($me_funcs[$key], $func_no_param)
                   || ($val != "''" && in_array($me_funcs[$key], $func_optional_param))) {
             $cur_value = $me_funcs[$key] . '(' . $val . ')';
-        } else {
+        }  else {
             $cur_value = $me_funcs[$key] . '()';
         }
 
diff --git a/tbl_select.php b/tbl_select.php
index e9b1eae..1191c3a 100644
--- a/tbl_select.php
+++ b/tbl_select.php
@@ -24,8 +24,18 @@ $GLOBALS['js_include'][] = 'tbl_change.js';
 $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js';
 $GLOBALS['js_include'][] = 'jquery/timepicker.js';
 
+// required for GIS editor loaded via AJAX
+$GLOBALS['js_include'][] = 'gis_data_editor.js';
+$GLOBALS['js_include'][] = 'jquery/jquery.svg.js';
+$GLOBALS['js_include'][] = 'jquery/jquery.mousewheel.js';
+$GLOBALS['js_include'][] = 'jquery/jquery.event.drag-2.0.min.js';
+$GLOBALS['js_include'][] = 'tbl_gis_visualization.js';
+$GLOBALS['js_include'][] = 'openlayers/OpenLayers.js';
+$GLOBALS['js_include'][] = 'OpenStreetMap.js';
+
 $titles['Browse'] = PMA_tbl_setTitle($GLOBALS['cfg']['PropertiesIconic'], $pmaThemeImage);
 
+$geom_types = PMA_getGISDatatypes();
 /**
  * Not selection yet required -> displays the selection form
  */
@@ -52,8 +62,7 @@ if (! isset($param) || $param[0] == '') {
     $err_url   = $goto . '?' . PMA_generate_common_url($db, $table);
 
     // Gets the list and number of fields
-
-    list($fields_list, $fields_type, $fields_collation, $fields_null) = PMA_tbl_getFields($table,$db);
+    list($fields_list, $fields_type, $fields_collation, $fields_null, $geom_column_present) = PMA_tbl_getFields($table,$db);
     $fields_cnt = count($fields_list);
 
     // retrieve keys into foreign fields, if any
@@ -82,7 +91,7 @@ echo PMA_generate_html_tabs(PMA_tbl_getSubTabs(), $url_params);
 <fieldset id="fieldset_table_qbe">
     <legend><?php echo __('Do a "query by example" (wildcard: "%")') ?></legend>
     <table class="data">
-    <?php echo PMA_tbl_setTableHeader(); ?>
+    <?php echo PMA_tbl_setTableHeader($geom_column_present); ?>
     <tbody>
     <?php
     $odd_row = true;
@@ -90,6 +99,27 @@ echo PMA_generate_html_tabs(PMA_tbl_getSubTabs(), $url_params);
     for ($i = 0; $i < $fields_cnt; $i++) {
         ?>
         <tr class="noclick <?php echo $odd_row ? 'odd' : 'even'; $odd_row = ! $odd_row; ?>">
+            <?php
+            // if 'Function' column is present
+            if ($geom_column_present) {
+                echo('<td>');
+                // if a geometry column
+                if (in_array($fields_type[$i], $geom_types)) {
+                    echo('<select class="geom_func" name="geom_func['. $i .']">');
+                        // get the relevant list of functions
+                        $funcs = PMA_getGISFunctions($fields_type[$i], true, true);
+                        foreach ($funcs as $func_name => $func) {
+                            $name =  isset($func['display']) ? $func['display'] : $func_name;
+                            echo('<option value="' . htmlspecialchars($name) . '">'
+                                . htmlspecialchars($name) . '</option>');
+                        }
+                    echo('</select>');
+                } else {
+                    echo(' ');
+                }
+                echo('</td>');
+            }
+            ?>
             <th><?php echo htmlspecialchars($fields_list[$i]); ?></th>
             <td><?php echo $fields_type[$i]; ?></td>
             <td><?php echo $fields_collation[$i]; ?></td>
@@ -131,8 +161,8 @@ echo PMA_generate_html_tabs(PMA_tbl_getSubTabs(), $url_params);
 
         $foreignData = PMA_getForeignData($foreigners, $field, false, '', '');
 
-	echo PMA_getForeignFields_Values($foreigners, $foreignData, $field, $fields_type, $i, $db, $table, $titles,$GLOBALS['cfg']['ForeignKeyMaxLimit'], '' );
-        
+	echo PMA_getForeignFields_Values($foreigners, $foreignData, $field, $fields_type, $i, $db, $table, $titles,$GLOBALS['cfg']['ForeignKeyMaxLimit'], '', true);
+
 	?>
             <input type="hidden" name="names[<?php echo $i; ?>]"
                 value="<?php echo htmlspecialchars($fields_list[$i]); ?>" />
@@ -147,6 +177,7 @@ echo PMA_generate_html_tabs(PMA_tbl_getSubTabs(), $url_params);
     ?>
     </tbody>
     </table>
+<div id="gis_editor"></div><div id="popup_background"></div>
 </fieldset>
 <?php
     PMA_generate_slider_effect('searchoptions', __('Options'));
@@ -228,7 +259,6 @@ echo PMA_generate_html_tabs(PMA_tbl_getSubTabs(), $url_params);
  * Selection criteria have been submitted -> do the work
  */
 else {
-    echo "ZZ";
     // Builds the query
 
     $sql_query = 'SELECT ' . (isset($distinct) ? 'DISTINCT ' : '');
@@ -258,14 +288,16 @@ else {
         $cnt_func = count($func);
         reset($func);
         while (list($i, $func_type) = each($func)) {
-            
-	    list($charsets[$i]) = explode('_', $collations[$i]);
+
+	        list($charsets[$i]) = explode('_', $collations[$i]);
             $unaryFlag =  (isset($GLOBALS['cfg']['UnaryOperators'][$func_type]) && $GLOBALS['cfg']['UnaryOperators'][$func_type] == 1) ? true : false;
-	    $whereClause = PMA_tbl_search_getWhereClause($fields[$i],$names[$i], $types[$i], $collations[$i], $func_type, $unaryFlag);
-	    if($whereClause)
-		$w[] = $whereClause;
-	
-        } // end for
+
+            $tmp_geom_func = isset($geom_func[$i]) ? $geom_func[$i] : null;
+	        $whereClause = PMA_tbl_search_getWhereClause($fields[$i],$names[$i], $types[$i], $collations[$i], $func_type, $unaryFlag, $tmp_geom_func);
+
+	        if($whereClause)
+		        $w[] = $whereClause;
+            } // end for
 	//print_r($w);
         if ($w) {
             $sql_query .= ' WHERE ' . implode(' AND ', $w);
@@ -278,4 +310,4 @@ else {
     require './sql.php';
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/test/classes/gis/PMA_GIS_Factory_test.php b/test/classes/gis/PMA_GIS_Factory_test.php
new file mode 100644
index 0000000..6d778ab
--- /dev/null
+++ b/test/classes/gis/PMA_GIS_Factory_test.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Test for PMA_GIS_Factory
+ *
+ * @package phpMyAdmin-test
+ */
+require_once 'libraries/gis/pma_gis_geometry.php';
+require_once 'libraries/gis/pma_gis_linestring.php';
+require_once 'libraries/gis/pma_gis_multilinestring.php';
+require_once 'libraries/gis/pma_gis_point.php';
+require_once 'libraries/gis/pma_gis_multipoint.php';
+require_once 'libraries/gis/pma_gis_polygon.php';
+require_once 'libraries/gis/pma_gis_multipolygon.php';
+require_once 'libraries/gis/pma_gis_geometrycollection.php';
+
+/*
+ * Include to test
+ */
+require_once 'libraries/gis/pma_gis_factory.php';
+
+/**
+ * Test class for PMA_GIS_Factory
+ */
+class PMA_GIS_FactoryTest extends PHPUnit_Framework_TestCase
+{
+
+    /**
+     * Test factory method
+     *
+     * @param string $type geometry type
+     * @param object $geom geometry object
+     *
+     * @dataProvider providerForTestFactory
+     * @return nothing
+     */
+    public function testFactory($type, $geom)
+    {
+        $this->assertInstanceOf($geom, PMA_GIS_Factory::factory($type));
+    }
+
+    /**
+     * data provider for testFactory
+     *
+     * @return data for testFactory
+     */
+    public function providerForTestFactory()
+    {
+        return array(
+            array(
+                'MULTIPOLYGON',
+                'PMA_GIS_Multipolygon'
+            ),
+            array(
+                'POLYGON',
+                'PMA_GIS_Polygon'
+            ),
+            array(
+                'MULTILINESTRING',
+                'PMA_GIS_Multilinestring'
+            ),
+            array(
+                    'LINESTRING',
+                'PMA_GIS_Linestring'
+            ),
+            array(
+                    'MULTIPOINT',
+                'PMA_GIS_Multipoint'
+            ),
+            array(
+                 'POINT',
+                'PMA_GIS_Point'
+            ),
+               array(
+                    'GEOMETRYCOLLECTION',
+                'PMA_GIS_Geometrycollection'
+            ),
+        );
+    }
+}
+?>
\ No newline at end of file
diff --git a/test/classes/gis/PMA_GIS_Geometry_test.php b/test/classes/gis/PMA_GIS_Geometry_test.php
new file mode 100644
index 0000000..37d4c42
--- /dev/null
+++ b/test/classes/gis/PMA_GIS_Geometry_test.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Abstract parent class for all PMA_GIS_<Geom_type> test classes
+ *
+ * @package phpMyAdmin-test
+ */
+
+require_once 'libraries/gis/pma_gis_geometry.php';
+
+/**
+ * Abstract parent class for all PMA_GIS_<Geom_type> test classes
+ */
+abstract class PMA_GIS_GeometryTest extends PHPUnit_Framework_TestCase
+{
+    /**
+     * test generateWkt method
+     *
+     * @param array  $gis_data array of GIS data
+     * @param int    $index    index
+     * @param string $empty    string to be insterted in place of missing values
+     * @param string $wkt      expected WKT
+     *
+     * @return nothing
+     * @dataProvider providerForTestGenerateWkt
+     */
+    public function testGenerateWkt($gis_data, $index, $empty, $wkt)
+    {
+        if ($empty == null) {
+            $this->assertEquals($this->object->generateWkt($gis_data, $index), $wkt);
+        } else {
+            $this->assertEquals(
+                $this->object->generateWkt($gis_data, $index, $empty),
+                $wkt
+            );
+        }
+    }
+
+    /**
+     * test generateParams method
+     *
+     * @param string $wkt    point in WKT form
+     * @param index  $index  index
+     * @param array  $params expected output array
+     *
+     * @dataProvider providerForTestGenerateParams
+     * @return nothing
+     */
+    public function testGenerateParams($wkt, $index, $params)
+    {
+        if ($index == null) {
+            $this->assertEquals($this->object->generateParams($wkt), $params);
+        } else {
+            $this->assertEquals(
+                $this->object->generateParams($wkt, $index),
+                $params
+            );
+        }
+    }
+}
+?>
\ No newline at end of file
diff --git a/test/classes/gis/PMA_GIS_Linestring_test.php b/test/classes/gis/PMA_GIS_Linestring_test.php
new file mode 100644
index 0000000..4bef75c
--- /dev/null
+++ b/test/classes/gis/PMA_GIS_Linestring_test.php
@@ -0,0 +1,142 @@
+<?php
+/**
+ * Test for PMA_GIS_Linestring
+ *
+ * @package phpMyAdmin-test
+ */
+
+require_once 'PMA_GIS_Geometry_test.php';
+require_once 'libraries/gis/pma_gis_geometry.php';
+require_once 'libraries/gis/pma_gis_linestring.php';
+
+/**
+ * Tests for PMA_GIS_Linestring class
+ */
+class PMA_GIS_LinestringTest extends PMA_GIS_GeometryTest
+{
+    /**
+     * @var    PMA_GIS_Linestring
+     * @access protected
+     */
+    protected $object;
+
+    /**
+     * Sets up the fixture, for example, opens a network connection.
+     * This method is called before a test is executed.
+     *
+     * @access protected
+     * @return nothing
+     */
+    protected function setUp()
+    {
+        $this->object = PMA_GIS_Linestring::singleton();
+    }
+
+    /**
+     * Tears down the fixture, for example, closes a network connection.
+     * This method is called after a test is executed.
+     *
+     * @access protected
+     * @return nothing
+     */
+    protected function tearDown()
+    {
+        unset($this->object);
+    }
+
+    /**
+     * data provider for testGenerateWkt
+     *
+     * @return data for testGenerateWkt
+     */
+    public function providerForTestGenerateWkt()
+    {
+        $temp1 = array(
+            0 => array(
+                'LINESTRING' => array(
+                    'no_of_points' => 2,
+                    0 => array('x' => 5.02, 'y' => 8.45),
+                    1 => array('x' => 6.14, 'y' => 0.15)
+                )
+            )
+        );
+
+        $temp2 = $temp1;
+        $temp2[0]['LINESTRING']['no_of_points'] = 3;
+        $temp2[0]['LINESTRING'][2] = array('x' => 1.56);
+
+        $temp3 = $temp2;
+        $temp3[0]['LINESTRING']['no_of_points'] = -1;
+
+        $temp4 = $temp3;
+        $temp4[0]['LINESTRING']['no_of_points'] = 3;
+        unset($temp4[0]['LINESTRING'][2]['x']);
+
+        return array(
+            array(
+                $temp1,
+                0,
+                null,
+                'LINESTRING(5.02 8.45,6.14 0.15)'
+            ),
+            // if a coordinate is missing, default is empty string
+            array(
+                $temp2,
+                0,
+                null,
+                'LINESTRING(5.02 8.45,6.14 0.15,1.56 )'
+            ),
+            // if no_of_points is not valid, it is considered as 2
+            array(
+                $temp3,
+                0,
+                null,
+                'LINESTRING(5.02 8.45,6.14 0.15)'
+            ),
+            // missing coordinates are replaced with provided values (3rd parameter)
+            array(
+                $temp4,
+                0,
+                '0',
+                'LINESTRING(5.02 8.45,6.14 0.15,0 0)'
+            )
+        );
+    }
+
+    /**
+     * data provider for testGenerateParams
+     *
+     * @return data for testGenerateParams
+     */
+    public function providerForTestGenerateParams()
+    {
+        $temp = array(
+            'LINESTRING' => array(
+                'no_of_points' => 2,
+                0 => array('x' => '5.02', 'y' => '8.45'),
+                1 => array('x' => '6.14', 'y' => '0.15')
+            )
+        );
+        $temp1 = $temp;
+        $temp1['gis_type'] = 'LINESTRING';
+
+        return array(
+            array(
+                "'LINESTRING(5.02 8.45,6.14 0.15)',124",
+                null,
+                array(
+                    'srid' => '124',
+                    0 => $temp
+                )
+            ),
+            array(
+                'LINESTRING(5.02 8.45,6.14 0.15)',
+                2,
+                array(
+                    2 => $temp1
+                )
+            )
+        );
+    }
+}
+?>
\ No newline at end of file
diff --git a/test/classes/gis/PMA_GIS_Multilinestring_test.php b/test/classes/gis/PMA_GIS_Multilinestring_test.php
new file mode 100644
index 0000000..cef0cef
--- /dev/null
+++ b/test/classes/gis/PMA_GIS_Multilinestring_test.php
@@ -0,0 +1,182 @@
+<?php
+/**
+ * Test for PMA_GIS_Multilinestring
+ *
+ * @package phpMyAdmin-test
+ */
+
+require_once 'PMA_GIS_Geometry_test.php';
+require_once 'libraries/gis/pma_gis_geometry.php';
+require_once 'libraries/gis/pma_gis_multilinestring.php';
+
+/**
+ * Tests for PMA_GIS_Multilinestring class
+ */
+class PMA_GIS_MultilinestringTest extends PMA_GIS_GeometryTest
+{
+    /**
+     * @var    PMA_GIS_Multilinestring
+     * @access protected
+     */
+    protected $object;
+
+    /**
+     * Sets up the fixture, for example, opens a network connection.
+     * This method is called before a test is executed.
+     *
+     * @access protected
+     * @return nothing
+     */
+    protected function setUp()
+    {
+        $this->object = PMA_GIS_Multilinestring::singleton();
+    }
+
+    /**
+     * Tears down the fixture, for example, closes a network connection.
+     * This method is called after a test is executed.
+     *
+     * @access protected
+     * @return nothing
+     */
+    protected function tearDown()
+    {
+        unset($this->object);
+    }
+
+    /**
+     * data provider for testGenerateWkt
+     *
+     * @return data for testGenerateWkt
+     */
+    public function providerForTestGenerateWkt()
+    {
+        $temp = array(
+            0 => array(
+                'MULTILINESTRING' => array(
+                    'no_of_lines' => 2,
+                    0 => array(
+                        'no_of_points' => 2,
+                        0 => array('x' => 5.02, 'y' => 8.45),
+                        1 => array('x' => 6.14, 'y' => 0.15)
+                    ),
+                    1 => array(
+                        'no_of_points' => 2,
+                        0 => array('x' => 1.23, 'y' => 4.25),
+                        1 => array('x' => 9.15, 'y' => 0.47)
+                    )
+                )
+            )
+        );
+
+        $temp1 = $temp;
+        unset($temp1[0]['MULTILINESTRING'][1][1]['y']);
+
+        return array(
+            array(
+                $temp,
+                0,
+                null,
+                'MULTILINESTRING((5.02 8.45,6.14 0.15),(1.23 4.25,9.15 0.47))'
+            ),
+            // values at undefined index
+            array(
+                $temp,
+                1,
+                null,
+                'MULTILINESTRING(( , ))'
+            ),
+            // if a coordinate is missing, default is empty string
+            array(
+                $temp1,
+                0,
+                null,
+                'MULTILINESTRING((5.02 8.45,6.14 0.15),(1.23 4.25,9.15 ))'
+            ),
+            // missing coordinates are replaced with provided values (3rd parameter)
+            array(
+                $temp1,
+                0,
+                '0',
+                'MULTILINESTRING((5.02 8.45,6.14 0.15),(1.23 4.25,9.15 0))'
+            )
+        );
+    }
+
+    /**
+     * test getShape method
+     *
+     * @return nothing
+     */
+    public function testGetShape()
+    {
+        $row_data = array(
+            'numparts' => 2,
+            'parts'    => array(
+                0 => array(
+                    'points' => array(
+                        0 => array('x' => 5.02, 'y' => 8.45),
+                        1 => array('x' => 6.14, 'y' => 0.15),
+                    ),
+                ),
+                1 => array(
+                    'points' => array(
+                        0 => array('x' => 1.23, 'y' => 4.25),
+                        1 => array('x' => 9.15, 'y' => 0.47),
+                    ),
+                ),
+            ),
+        );
+
+        $this->assertEquals(
+            $this->object->getShape($row_data),
+            'MULTILINESTRING((5.02 8.45,6.14 0.15),(1.23 4.25,9.15 0.47))'
+        );
+    }
+
+    /**
+     * data provider for testGenerateParams
+     *
+     * @return data for testGenerateParams
+     */
+    public function providerForTestGenerateParams()
+    {
+        $temp = array(
+            'MULTILINESTRING' => array(
+                'no_of_lines' => 2,
+                0 => array(
+                    'no_of_points' => 2,
+                    0 => array('x' => 5.02, 'y' => 8.45),
+                    1 => array('x' => 6.14, 'y' => 0.15),
+                ),
+                1 => array(
+                    'no_of_points' => 2,
+                    0 => array('x' => 1.23, 'y' => 4.25),
+                    1 => array('x' => 9.15, 'y' => 0.47),
+                )
+            )
+        );
+
+        $temp1 = $temp;
+        $temp1['gis_type'] = 'MULTILINESTRING';
+
+        return array(
+            array(
+                "'MULTILINESTRING((5.02 8.45,6.14 0.15),(1.23 4.25,9.15 0.47))',124",
+                null,
+                array(
+                    'srid' => '124',
+                    0 => $temp
+                )
+            ),
+            array(
+                'MULTILINESTRING((5.02 8.45,6.14 0.15),(1.23 4.25,9.15 0.47))',
+                2,
+                array(
+                    2 => $temp1
+                )
+            )
+        );
+    }
+}
+?>
\ No newline at end of file
diff --git a/test/classes/gis/PMA_GIS_Multipoint_test.php b/test/classes/gis/PMA_GIS_Multipoint_test.php
new file mode 100644
index 0000000..8ab0aef
--- /dev/null
+++ b/test/classes/gis/PMA_GIS_Multipoint_test.php
@@ -0,0 +1,146 @@
+<?php
+/**
+ * Test for PMA_GIS_Multipoint
+ *
+ * @package phpMyAdmin-test
+ */
+
+require_once 'PMA_GIS_Geometry_test.php';
+require_once 'libraries/gis/pma_gis_geometry.php';
+require_once 'libraries/gis/pma_gis_multipoint.php';
+
+/**
+ * Tests for PMA_GIS_Multipoint class
+ */
+class PMA_GIS_MultipointTest extends PMA_GIS_GeometryTest
+{
+    /**
+     * @var    PMA_GIS_Multipoint
+     * @access protected
+     */
+    protected $object;
+
+    /**
+     * Sets up the fixture, for example, opens a network connection.
+     * This method is called before a test is executed.
+     *
+     * @access protected
+     * @return nothing
+     */
+    protected function setUp()
+    {
+        $this->object = PMA_GIS_Multipoint::singleton();
+    }
+
+    /**
+     * Tears down the fixture, for example, closes a network connection.
+     * This method is called after a test is executed.
+     *
+     * @access protected
+     * @return nothing
+     */
+    protected function tearDown()
+    {
+        unset($this->object);
+    }
+
+    /**
+     * data provider for testGenerateWkt
+     *
+     * @return data for testGenerateWkt
+     */
+    public function providerForTestGenerateWkt()
+    {
+        $gis_data1 = array(
+            0 => array(
+                'MULTIPOINT' => array(
+                    'no_of_points' => 2,
+                    0 => array(
+                        'x' => 5.02,
+                        'y' => 8.45
+                    ),
+                    1 => array(
+                        'x' => 1.56,
+                        'y' => 4.36
+                    )
+                )
+            )
+        );
+
+        $gis_data2 = $gis_data1;
+        $gis_data2[0]['MULTIPOINT']['no_of_points'] = -1;
+
+        return array(
+            array(
+                $gis_data1,
+                0,
+                null,
+                'MULTIPOINT(5.02 8.45,1.56 4.36)'
+            ),
+            array(
+                $gis_data2,
+                0,
+                null,
+                'MULTIPOINT(5.02 8.45)'
+            )
+        );
+    }
+
+    /**
+     * test getShape method
+     *
+     * @return nothing
+     */
+    public function testGetShape()
+    {
+        $gis_data = array(
+            'numpoints' => 2,
+            'points' => array(
+                0 => array('x' => 5.02, 'y' => 8.45),
+                1 => array('x' => 6.14, 'y' => 0.15)
+            )
+        );
+
+        $this->assertEquals(
+            $this->object->getShape($gis_data),
+            'MULTIPOINT(5.02 8.45,6.14 0.15)'
+        );
+    }
+
+    /**
+     * data provider for testGenerateParams
+     *
+     * @return data for testGenerateParams
+     */
+    public function providerForTestGenerateParams()
+    {
+        $temp1 = array(
+            'MULTIPOINT' => array(
+                'no_of_points' => 2,
+                0 => array('x' => '5.02', 'y' => '8.45'),
+                1 => array('x' => '6.14', 'y' => '0.15')
+            )
+        );
+        $temp2 = $temp1;
+        $temp2['gis_type'] = 'MULTIPOINT';
+
+        return array(
+            array(
+                "'MULTIPOINT(5.02 8.45,6.14 0.15)',124",
+                null,
+                array(
+                    'srid' => '124',
+                    0 => $temp1
+                )
+            ),
+            array(
+                'MULTIPOINT(5.02 8.45,6.14 0.15)',
+                2,
+                array(
+                    2 => $temp2
+                )
+            )
+        );
+    }
+}
+?>
\ No newline at end of file
diff --git a/test/classes/gis/PMA_GIS_Multipolygon_test.php b/test/classes/gis/PMA_GIS_Multipolygon_test.php
new file mode 100644
index 0000000..1a43555
--- /dev/null
+++ b/test/classes/gis/PMA_GIS_Multipolygon_test.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Test for PMA_GIS_Multipolygon
+ *
+ * @package phpMyAdmin-test
+ */
+
+require_once 'PMA_GIS_Geometry_test.php';
+require_once 'libraries/gis/pma_gis_geometry.php';
+require_once 'libraries/gis/pma_gis_multipolygon.php';
+
+/**
+ * Tests for PMA_GIS_Multipolygon class
+ */
+class PMA_GIS_MultipolygonTest extends PMA_GIS_GeometryTest
+{
+    /**
+     * @var    PMA_GIS_Multipolygon
+     * @access protected
+     */
+    protected $object;
+
+    /**
+     * Sets up the fixture, for example, opens a network connection.
+     * This method is called before a test is executed.
+     *
+     * @access protected
+     * @return nothing
+     */
+    protected function setUp()
+    {
+        $this->object = PMA_GIS_Multipolygon::singleton();
+    }
+
+    /**
+     * Tears down the fixture, for example, closes a network connection.
+     * This method is called after a test is executed.
+     *
+     * @access protected
+     * @return nothing
+     */
+    protected function tearDown()
+    {
+        unset($this->object);
+    }
+
+    private function _getData()
+    {
+        return array(
+            'MULTIPOLYGON' => array(
+                'no_of_polygons' => 2,
+                0 => array(
+                    'no_of_lines' => 2,
+                    0 => array(
+                        'no_of_points' => 5,
+                        0 => array('x' => 35, 'y' => 10),
+                        1 => array('x' => 10, 'y' => 20),
+                        2 => array('x' => 15, 'y' => 40),
+                        3 => array('x' => 45, 'y' => 45),
+                        4 => array('x' => 35, 'y' => 10),
+                    ),
+                    1 => array(
+                        'no_of_points' => 4,
+                        0 => array('x' => 20, 'y' => 30),
+                        1 => array('x' => 35, 'y' => 32),
+                        2 => array('x' => 30, 'y' => 20),
+                        3 => array('x' => 20, 'y' => 30),
+                    )
+                ),
+                1 => array(
+                    'no_of_lines' => 1,
+                    0 => array(
+                        'no_of_points' => 4,
+                        0 => array('x' => 123, 'y' => 0),
+                        1 => array('x' => 23, 'y' => 30),
+                        2 => array('x' => 17, 'y' => 63),
+                        3 => array('x' => 123, 'y' => 0),
+                    )
+                )
+            )
+        );
+    }
+
+    /**
+     * data provider for testGenerateWkt
+     *
+     * @return data for testGenerateWkt
+     */
+    public function providerForTestGenerateWkt()
+    {
+        $temp = array(
+            0 => $this->_getData()
+        );
+
+        return array(
+            array(
+                $temp,
+                0,
+                null,
+                'MULTIPOLYGON(((35 10,10 20,15 40,45 45,35 10)'
+                    . ',(20 30,35 32,30 20,20 30)),((123 0,23 30,17 63,123 0)))'
+            ),
+        );
+    }
+
+    /**
+     * data provider for testGenerateParams
+     *
+     * @return data for testGenerateParams
+     */
+    public function providerForTestGenerateParams()
+    {
+        $temp = $this->_getData();
+
+        $temp1 = $this->_getData();
+        $temp1['gis_type'] = 'MULTIPOLYGON';
+
+        return array(
+            array(
+                "'MULTIPOLYGON(((35 10,10 20,15 40,45 45,35 10),"
+                . "(20 30,35 32,30 20,20 30)),((123 0,23 30,17 63,123 0)))',124",
+                null,
+                array(
+                    'srid' => '124',
+                    0 => $temp
+                )
+            ),
+            array(
+                'MULTIPOLYGON(((35 10,10 20,15 40,45 45,35 10)'
+                    . ',(20 30,35 32,30 20,20 30)),((123 0,23 30,17 63,123 0)))',
+                2,
+                array(
+                    2 => $temp1
+                )
+            )
+        );
+    }
+}
+?>
diff --git a/test/classes/gis/PMA_GIS_Point_test.php b/test/classes/gis/PMA_GIS_Point_test.php
new file mode 100644
index 0000000..a25a66a
--- /dev/null
+++ b/test/classes/gis/PMA_GIS_Point_test.php
@@ -0,0 +1,148 @@
+<?php
+/**
+ * Test for PMA_GIS_Point
+ *
+ * @package phpMyAdmin-test
+ */
+
+require_once 'PMA_GIS_Geometry_test.php';
+require_once 'libraries/gis/pma_gis_geometry.php';
+require_once 'libraries/gis/pma_gis_point.php';
+
+/**
+ * Tests for PMA_GIS_Point class.
+ */
+class PMA_GIS_PointTest extends PMA_GIS_GeometryTest
+{
+    /**
+     * @var    PMA_GIS_Point
+     * @access protected
+     */
+    protected $object;
+
+    /**
+     * Sets up the fixture, for example, opens a network connection.
+     * This method is called before a test is executed.
+     *
+     * @access protected
+     * @return nothing
+     */
+    protected function setUp()
+    {
+        $this->object = PMA_GIS_Point::singleton();
+    }
+
+    /**
+     * Tears down the fixture, for example, closes a network connection.
+     * This method is called after a test is executed.
+     *
+     * @access protected
+     * @return nothing
+     */
+    protected function tearDown()
+    {
+        unset($this->object);
+    }
+
+    /**
+     * data provider for testGenerateWkt
+     *
+     * @return data for testGenerateWkt
+     */
+    public function providerForTestGenerateWkt()
+    {
+        return array(
+            array(
+                array(0 => array('POINT' => array('x' => 5.02, 'y' => 8.45))),
+                0,
+                null,
+                'POINT(5.02 8.45)'
+            ),
+            array(
+                array(0 => array('POINT' => array('x' => 5.02, 'y' => 8.45))),
+                1,
+                null,
+                'POINT( )'
+            ),
+            array(
+                array(0 => array('POINT' => array('x' => 5.02))),
+                0,
+                null,
+                'POINT(5.02 )'
+            ),
+            array(
+                array(0 => array('POINT' => array('y' => 8.45))),
+                0,
+                null,
+                'POINT( 8.45)'
+            ),
+            array(
+                array(0 => array('POINT' => array())),
+                0,
+                null,
+                'POINT( )'
+            ),
+        );
+    }
+
+    /**
+     * test getShape method
+     *
+     * @param array  $row_data array of GIS data
+     * @param string $shape    expected shape in WKT
+     *
+     * @dataProvider providerForTestGetShape
+     * @return nothing
+     */
+    public function testGetShape($row_data, $shape)
+    {
+        $this->assertEquals($this->object->getShape($row_data), $shape);
+    }
+
+    /**
+     * data provider for testGetShape
+     *
+     * @return data for testGetShape
+     */
+    public function providerForTestGetShape()
+    {
+        return array(
+            array(
+                array('x' => 5.02, 'y' => 8.45),
+                'POINT(5.02 8.45)'
+            )
+        );
+    }
+
+    /**
+     * data provider for testGenerateParams
+     *
+     * @return data for testGenerateParams
+     */
+    public function providerForTestGenerateParams()
+    {
+        return array(
+            array(
+                "'POINT(5.02 8.45)',124",
+                null,
+                array(
+                    'srid' => '124',
+                    0      => array(
+                        'POINT'    => array('x' => '5.02', 'y' => '8.45')
+                    ),
+                )
+            ),
+            array(
+                'POINT(5.02 8.45)',
+                2,
+                array(
+                    2 => array(
+                        'gis_type' => 'POINT',
+                        'POINT'    => array('x' => '5.02', 'y' => '8.45')
+                    ),
+                )
+            )
+        );
+    }
+}
+?>
\ No newline at end of file
diff --git a/test/classes/gis/PMA_GIS_Polygon_test.php b/test/classes/gis/PMA_GIS_Polygon_test.php
new file mode 100644
index 0000000..b504acc
--- /dev/null
+++ b/test/classes/gis/PMA_GIS_Polygon_test.php
@@ -0,0 +1,299 @@
+<?php
+/**
+ * Test for PMA_GIS_Polygon
+ *
+ * @package phpMyAdmin-test
+ */
+
+require_once 'PMA_GIS_Geometry_test.php';
+require_once 'libraries/gis/pma_gis_geometry.php';
+require_once 'libraries/gis/pma_gis_polygon.php';
+
+/**
+ * Tests for PMA_GIS_Polygon class
+ */
+class PMA_GIS_PolygonTest extends PMA_GIS_GeometryTest
+{
+    /**
+     * @var    PMA_GIS_Polygon
+     * @access protected
+     */
+    protected $object;
+
+    /**
+     * Sets up the fixture, for example, opens a network connection.
+     * This method is called before a test is executed.
+     *
+     * @access protected
+     * @return nothing
+     */
+    protected function setUp()
+    {
+        $this->object = PMA_GIS_Polygon::singleton();
+    }
+
+    /**
+     * Tears down the fixture, for example, closes a network connection.
+     * This method is called after a test is executed.
+     *
+     * @access protected
+     * @return nothing
+     */
+    protected function tearDown()
+    {
+        unset($this->object);
+    }
+
+    private function _getData()
+    {
+        return array(
+            'POLYGON' => array(
+                'no_of_lines' => 2,
+                0 => array(
+                    'no_of_points' => 5,
+                    0 => array('x' => 35, 'y' => 10),
+                    1 => array('x' => 10, 'y' => 20),
+                    2 => array('x' => 15, 'y' => 40),
+                    3 => array('x' => 45, 'y' => 45),
+                    4 => array('x' => 35, 'y' => 10),
+                ),
+                1 => array(
+                    'no_of_points' => 4,
+                    0 => array('x' => 20, 'y' => 30),
+                    1 => array('x' => 35, 'y' => 32),
+                    2 => array('x' => 30, 'y' => 20),
+                    3 => array('x' => 20, 'y' => 30),
+                )
+            )
+        );
+    }
+
+    /**
+     * data provider for testGenerateWkt
+     *
+     * @return data for testGenerateWkt
+     */
+    public function providerForTestGenerateWkt()
+    {
+        $temp = array(
+            0 => $this->_getData()
+        );
+
+        $temp1 = $temp;
+        unset($temp1[0]['POLYGON'][1][3]['y']);
+
+        return array(
+            array(
+                $temp,
+                0,
+                null,
+                'POLYGON((35 10,10 20,15 40,45 45,35 10),(20 30,35 32,30 20,20 30))'
+            ),
+            // values at undefined index
+            array(
+                $temp,
+                1,
+                null,
+                'POLYGON(( , , , ))'
+            ),
+            // if a coordinate is missing, default is empty string
+            array(
+                $temp1,
+                0,
+                null,
+                'POLYGON((35 10,10 20,15 40,45 45,35 10),(20 30,35 32,30 20,20 ))'
+            ),
+            // missing coordinates are replaced with provided values (3rd parameter)
+            array(
+                $temp1,
+                0,
+                '0',
+                'POLYGON((35 10,10 20,15 40,45 45,35 10),(20 30,35 32,30 20,20 0))'
+            )
+        );
+    }
+
+    /**
+     * data provider for testGenerateParams
+     *
+     * @return data for testGenerateParams
+     */
+    public function providerForTestGenerateParams()
+    {
+        $temp = $this->_getData();
+
+        $temp1 = $temp;
+        $temp1['gis_type'] = 'POLYGON';
+
+        return array(
+            array(
+                "'POLYGON((35 10,10 20,15 40,45 45,35 10),(20 30,35 32,30 20,20 30))',124",
+                null,
+                array(
+                    'srid' => '124',
+                    0 => $temp
+                )
+            ),
+            array(
+                'POLYGON((35 10,10 20,15 40,45 45,35 10),(20 30,35 32,30 20,20 30))',
+                2,
+                array(
+                    2 => $temp1
+                )
+            )
+        );
+    }
+
+    /**
+     * test for Area
+     *
+     * @param array $ring array of points forming the ring
+     * @param fload $area area of the ring
+     *
+     * @dataProvider providerForTestArea
+     * @return nothing
+     */
+    public function testArea($ring, $area)
+    {
+        $this->assertEquals($this->object->area($ring), $area);
+    }
+
+    /**
+     * data provider for testArea
+     *
+     * @return data for testArea
+     */
+    public function providerForTestArea()
+    {
+        return array(
+            array(
+                array(
+                    0 => array('x' => 35, 'y' => 10),
+                    1 => array('x' => 10, 'y' => 10),
+                    2 => array('x' => 15, 'y' => 40)
+                ),
+                -375.00
+            ),
+            // first point of the ring repeated as the last point
+            array(
+                array(
+                    0 => array('x' => 35, 'y' => 10),
+                    1 => array('x' => 10, 'y' => 10),
+                    2 => array('x' => 15, 'y' => 40),
+                    3 => array('x' => 35, 'y' => 10)
+                ),
+                -375.00
+            ),
+            // anticlockwise gives positive area
+            array(
+                array(
+                    0 => array('x' => 15, 'y' => 40),
+                    1 => array('x' => 10, 'y' => 10),
+                    2 => array('x' => 35, 'y' => 10)
+                ),
+                375.00
+            )
+        );
+    }
+
+    /**
+     * test for isPointInsidePolygon
+     *
+     * @param array $point    x, y coordinates of the point
+     * @param array $polygon  array of points forming the ring
+     * @param bool  $isInside output
+     *
+     * @dataProvider providerForTestIsPointInsidePolygon
+     * @return nothing
+     */
+    public function testIsPointInsidePolygon($point, $polygon, $isInside)
+    {
+        $this->assertEquals(
+            $this->object->isPointInsidePolygon($point, $polygon),
+            $isInside
+        );
+    }
+
+    /**
+     * data provider for testIsPointInsidePolygon
+     *
+     * @return data for testIsPointInsidePolygon
+     */
+    public function providerForTestIsPointInsidePolygon()
+    {
+        $ring = array(
+            0 => array('x' => 35, 'y' => 10),
+            1 => array('x' => 10, 'y' => 10),
+            2 => array('x' => 15, 'y' => 40),
+            3 => array('x' => 35, 'y' => 10)
+        );
+
+        return array(
+            // point inside the ring
+            array(
+                array('x' => 20, 'y' => 15),
+                $ring,
+                true
+            ),
+            // point on an edge of the ring
+            array(
+                array('x' => 20, 'y' => 10),
+                $ring,
+                false
+            ),
+            // point on a vertex of the ring
+            array(
+                array('x' => 10, 'y' => 10),
+                $ring,
+                false
+            ),
+            // point outside the ring
+            array(
+                array('x' => 5, 'y' => 10),
+                $ring,
+                false
+            ),
+        );
+    }
+
+    /**
+     * test for getPointOnSurface
+     *
+     * @param array $ring array of points forming the ring
+     *
+     * @dataProvider providerForTestGetPointOnSurface
+     * @return nothing
+     */
+    public function testGetPointOnSurface($ring)
+    {
+        $this->assertEquals(
+            $this->object->isPointInsidePolygon(
+                $this->object->getPointOnSurface($ring),
+                $ring
+            ),
+            true
+        );
+    }
+
+    /**
+     * data provider for testGetPointOnSurface
+     *
+     * @return data for testGetPointOnSurface
+     */
+    public function providerForTestGetPointOnSurface()
+    {
+        $temp = $this->_getData();
+        unset($temp['POLYGON'][0]['no_of_points']);
+        unset($temp['POLYGON'][1]['no_of_points']);
+
+        return array(
+            array(
+                $temp['POLYGON'][0]
+            ),
+            array(
+                $temp['POLYGON'][1]
+            )
+        );
+    }
+}
+?>
\ No newline at end of file
diff --git a/test/libraries/PMA_GIS_modifyQuery_test.php b/test/libraries/PMA_GIS_modifyQuery_test.php
new file mode 100644
index 0000000..04e9e1a
--- /dev/null
+++ b/test/libraries/PMA_GIS_modifyQuery_test.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Tests for PMA_GIS_modifyQuery method
+ *
+ * @package phpMyAdmin-test
+ */
+
+require_once 'libraries/sqlparser.lib.php';
+require_once 'libraries/common.lib.php';
+/*
+ * Include to test
+ */
+require_once 'libraries/gis_visualization.lib.php';
+
+class PMA_GIS_modifyQueryTest extends PHPUnit_Framework_TestCase
+{
+    /**
+     * Test PMA_GIS_modifyQuery method
+     *
+     * @param string $sql_query      query to modify
+     * @param array  $settings       visualization settings
+     * @param string $modified_query modified query
+     *
+     * @dataProvider provider
+     * @return nothing
+     */
+    public function testModifyQuery($sql_query, $settings, $modified_query)
+    {
+        $this->assertEquals(
+            PMA_GIS_modifyQuery($sql_query, $settings),
+            $modified_query
+        );
+    }
+
+    /**
+     * data provider for testModifyQuery
+     *
+     * @return data for testModifyQuery
+     */
+    public function provider()
+    {
+        return array(
+            // select *
+            array(
+                'SELECT * FROM `foo` WHERE `bar` = `zoo`',
+                array('spatialColumn' => 'moo', 'labelColumn' => 'noo'),
+                'SELECT `noo`, ASTEXT(`moo`) AS `moo`, SRID(`moo`) AS `srid` FROM `foo` WHERE `bar` = `zoo`'
+            ),
+            // select * with no label column
+            array(
+                'SELECT * FROM `foo` WHERE `bar` = `zoo`',
+                array('spatialColumn' => 'moo'),
+                'SELECT ASTEXT(`moo`) AS `moo`, SRID(`moo`) AS `srid` FROM `foo` WHERE `bar` = `zoo`'
+            ),
+            // more columns
+            array(
+                'SELECT `aaa`, `moo`, `bbb`, `noo` FROM `foo` WHERE `bar` = `zoo`',
+                array('spatialColumn' => 'moo', 'labelColumn' => 'noo'),
+                'SELECT `noo`, ASTEXT(`moo`) AS `moo`, SRID(`moo`) AS `srid` FROM `foo` WHERE `bar` = `zoo`'
+            ),
+            // no labelColumn defined
+            array(
+                'SELECT `moo`, `noo` FROM `foo` WHERE `bar` = `zoo`',
+                array('spatialColumn' => 'moo'),
+                'SELECT ASTEXT(`moo`) AS `moo`, SRID(`moo`) AS `srid` FROM `foo` WHERE `bar` = `zoo`'
+            ),
+            // alias for spatialColumn
+            array(
+                'SELECT `aaa` AS `moo`, `noo` FROM `foo` WHERE `bar` = `zoo`',
+                array('spatialColumn' => 'moo', 'labelColumn' => 'noo'),
+                'SELECT `noo`, ASTEXT(`aaa`) AS `moo`, SRID(`aaa`) AS `srid` FROM `foo` WHERE `bar` = `zoo`'
+            ),
+            // alias for labelColumn
+            array(
+                'SELECT `moo`, `bbb` AS `noo` FROM `foo` WHERE `bar` = `zoo`',
+                array('spatialColumn' => 'moo', 'labelColumn' => 'noo'),
+                'SELECT `bbb` AS `noo`, ASTEXT(`moo`) AS `moo`, SRID(`moo`) AS `srid` FROM `foo` WHERE `bar` = `zoo`'
+            ),
+            // with database names
+            array(
+                'SELECT `db`.`moo`, `db`.`noo` FROM `foo` WHERE `bar` = `zoo`',
+                array('spatialColumn' => 'moo', 'labelColumn' => 'noo'),
+                'SELECT `db`.`noo`, ASTEXT(`db`.`moo`) AS `moo`, SRID(`db`.`moo`) AS `srid` FROM `foo` WHERE `bar` = `zoo`'
+            ),
+            // database names plus alias
+            array(
+                'SELECT `db`.`aaa` AS `moo`, `noo` FROM `foo` WHERE `bar` = `zoo`',
+                array('spatialColumn' => 'moo', 'labelColumn' => 'noo'),
+                'SELECT `noo`, ASTEXT(`db`.`aaa`) AS `moo`, SRID(`db`.`aaa`) AS `srid` FROM `foo` WHERE `bar` = `zoo`'
+            ),
+        );
+    }
+}
+?>
\ No newline at end of file
diff --git a/themes/original/css/theme_right.css.php b/themes/original/css/theme_right.css.php
index 64e64e4..6cb4233 100644
--- a/themes/original/css/theme_right.css.php
+++ b/themes/original/css/theme_right.css.php
@@ -1740,6 +1740,44 @@ input#input_import_file {
 }
 
 /**
+ * GIS data editor styles
+ */
+a.close_gis_editor {
+    float: right;
+}
+
+#gis_editor {
+    display: none;
+    position: fixed;
+    _position: absolute; /* hack for IE */
+    z-index: 101;
+    overflow-y: auto;
+    overflow-x: hidden;
+}
+
+#gis_data {
+    min-height: 230px;
+}
+
+#gis_data_textarea {
+    height: 6em;
+}
+
+#gis_data_editor {
+    background: #D0DCE0;
+    padding: 15px;
+    min-height: 500px;
+}
+
+#gis_data_editor .choice {
+    display: none;
+}
+
+#gis_data_editor input[type="text"] {
+    width: 75px;
+}
+
+/**
  * ENUM/SET editor styles
  */
 p.enum_notice {
diff --git a/themes/pmahomme/css/theme_right.css.php b/themes/pmahomme/css/theme_right.css.php
index 982e744..1103bfa 100644
--- a/themes/pmahomme/css/theme_right.css.php
+++ b/themes/pmahomme/css/theme_right.css.php
@@ -2135,6 +2135,44 @@ input#input_import_file {
 }
 
 /**
+ * GIS data editor styles
+ */
+a.close_gis_editor {
+    float: right;
+}
+
+#gis_editor {
+    display: none;
+    position: fixed;
+    _position: absolute; /* hack for IE */
+    z-index: 101;
+    overflow-y: auto;
+    overflow-x: hidden;
+}
+
+#gis_data {
+    min-height: 230px;
+}
+
+#gis_data_textarea {
+    height: 6em;
+}
+
+#gis_data_editor {
+    background: #D0DCE0;
+    padding: 15px;
+    min-height: 500px;
+}
+
+#gis_data_editor .choice {
+    display: none;
+}
+
+#gis_data_editor input[type="text"] {
+    width: 75px;
+}
+
+/**
  * ENUM/SET editor styles
  */
 p.enum_notice {


hooks/post-receive
-- 
phpMyAdmin




More information about the Git mailing list