From 28519cf25befaba56aa677d38af2847c2a7febcb Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Fri, 8 Jul 2011 18:31:19 +0530 Subject: [PATCH] ESRI shape files imported from a zip archive --- libraries/import/shp.php | 35 ++++++++++++++- libraries/zip_extension.lib.php | 78 ++++++++++++++++++++++++++++++--- 2 files changed, 107 insertions(+), 6 deletions(-) diff --git a/libraries/import/shp.php b/libraries/import/shp.php index e6f97e0635..4bfdf4d3db 100644 --- a/libraries/import/shp.php +++ b/libraries/import/shp.php @@ -208,16 +208,49 @@ if (isset($plugin_list)) { } $shp = new PMA_ShapeFile(1); + // If the zip archive has more than one file, get the 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']; + } + + // 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']) . '/' . $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. - if (! empty($local_import_file) && ! empty($cfg['UploadDir']) && $compression == 'none') { + 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(''); + // Delete the .dbf file extracted to 'TempDir' + if ($temp_dbf_file) { + unlink($dbf_file_path); + } + $esri_types = array( 0 => 'Null Shape', 1 => 'Point', diff --git a/libraries/zip_extension.lib.php b/libraries/zip_extension.lib.php index 05279118e1..3153a962c3 100644 --- a/libraries/zip_extension.lib.php +++ b/libraries/zip_extension.lib.php @@ -10,11 +10,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 +29,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 +46,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; } } @@ -68,6 +73,69 @@ function PMA_getZipContents($file) return (array('error' => $error_message, 'data' => $file_data)); } +/** + * 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 *