zip_extension.lib.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Interface for the zip extension
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. if (! defined('PHPMYADMIN')) {
  9. exit;
  10. }
  11. /**
  12. * Gets zip file contents
  13. *
  14. * @param string $file zip file
  15. * @param string $specific_entry regular expression to match a file
  16. *
  17. * @return array ($error_message, $file_data); $error_message
  18. * is empty if no error
  19. */
  20. function PMA_getZipContents($file, $specific_entry = null)
  21. {
  22. $error_message = '';
  23. $file_data = '';
  24. $zip_handle = zip_open($file);
  25. if (!is_resource($zip_handle)) {
  26. $error_message = __('Error in ZIP archive:')
  27. . ' ' . PMA_getZipError($zip_handle);
  28. zip_close($zip_handle);
  29. return (array('error' => $error_message, 'data' => $file_data));
  30. }
  31. $first_zip_entry = zip_read($zip_handle);
  32. if (false === $first_zip_entry) {
  33. $error_message = __('No files found inside ZIP archive!');
  34. zip_close($zip_handle);
  35. return (array('error' => $error_message, 'data' => $file_data));
  36. }
  37. /* Is the the zip really an ODS file? */
  38. $read = zip_entry_read($first_zip_entry);
  39. $ods_mime = 'application/vnd.oasis.opendocument.spreadsheet';
  40. if (!strcmp($ods_mime, $read)) {
  41. $specific_entry = '/^content\.xml$/';
  42. }
  43. if (!isset($specific_entry)) {
  44. zip_entry_open($zip_handle, $first_zip_entry, 'r');
  45. /* File pointer has already been moved,
  46. * so include what was read above */
  47. $file_data = $read;
  48. $file_data .= zip_entry_read(
  49. $first_zip_entry,
  50. zip_entry_filesize($first_zip_entry)
  51. );
  52. zip_entry_close($first_zip_entry);
  53. zip_close($zip_handle);
  54. return (array('error' => $error_message, 'data' => $file_data));
  55. }
  56. /* Return the correct contents, not just the first entry */
  57. for ( ; ; ) {
  58. $entry = zip_read($zip_handle);
  59. if (is_resource($entry)) {
  60. if (preg_match($specific_entry, zip_entry_name($entry))) {
  61. zip_entry_open($zip_handle, $entry, 'r');
  62. $file_data = zip_entry_read(
  63. $entry,
  64. zip_entry_filesize($entry)
  65. );
  66. zip_entry_close($entry);
  67. break;
  68. }
  69. } else {
  70. /**
  71. * Either we have reached the end of the zip and still
  72. * haven't found $specific_entry or there was a parsing
  73. * error that we must display
  74. */
  75. if ($entry === false) {
  76. $error_message = __('Error in ZIP archive:')
  77. . ' Could not find "' . $specific_entry . '"';
  78. } else {
  79. $error_message = __('Error in ZIP archive:')
  80. . ' ' . PMA_getZipError($zip_handle);
  81. }
  82. break;
  83. }
  84. }
  85. zip_close($zip_handle);
  86. return (array('error' => $error_message, 'data' => $file_data));
  87. }
  88. /**
  89. * Returns the file name of the first file that matches the given $file_regexp.
  90. *
  91. * @param string $file_regexp regular expression for the file name to match
  92. * @param string $file zip archive
  93. *
  94. * @return string the file name of the first file that matches the given regexp
  95. */
  96. function PMA_findFileFromZipArchive ($file_regexp, $file)
  97. {
  98. $zip_handle = zip_open($file);
  99. if (is_resource($zip_handle)) {
  100. $entry = zip_read($zip_handle);
  101. while (is_resource($entry)) {
  102. if (preg_match($file_regexp, zip_entry_name($entry))) {
  103. $file_name = zip_entry_name($entry);
  104. zip_close($zip_handle);
  105. return $file_name;
  106. }
  107. $entry = zip_read($zip_handle);
  108. }
  109. }
  110. zip_close($zip_handle);
  111. return false;
  112. }
  113. /**
  114. * Returns the number of files in the zip archive.
  115. *
  116. * @param string $file zip archive
  117. *
  118. * @return int the number of files in the zip archive
  119. */
  120. function PMA_getNoOfFilesInZip($file)
  121. {
  122. $count = 0;
  123. $zip_handle = zip_open($file);
  124. if (is_resource($zip_handle)) {
  125. $entry = zip_read($zip_handle);
  126. while (is_resource($entry)) {
  127. $count++;
  128. $entry = zip_read($zip_handle);
  129. }
  130. }
  131. zip_close($zip_handle);
  132. return $count;
  133. }
  134. /**
  135. * Extracts a set of files from the given zip archive to a given destinations.
  136. *
  137. * @param string $zip_path path to the zip archive
  138. * @param string $destination destination to extract files
  139. * @param array $entries files in archive that should be extracted
  140. *
  141. * @return bool true on sucess, false otherwise
  142. */
  143. function PMA_zipExtract($zip_path, $destination, $entries)
  144. {
  145. $zip = new ZipArchive;
  146. if ($zip->open($zip_path) === true) {
  147. $zip->extractTo($destination, $entries);
  148. $zip->close();
  149. return true;
  150. }
  151. return false;
  152. }
  153. /**
  154. * Gets zip error message
  155. *
  156. * @param resource $code error code
  157. *
  158. * @return string error message
  159. */
  160. function PMA_getZipError($code)
  161. {
  162. // I don't think this needs translation
  163. switch ($code) {
  164. case ZIPARCHIVE::ER_MULTIDISK:
  165. $message = 'Multi-disk zip archives not supported';
  166. break;
  167. case ZIPARCHIVE::ER_READ:
  168. $message = 'Read error';
  169. break;
  170. case ZIPARCHIVE::ER_CRC:
  171. $message = 'CRC error';
  172. break;
  173. case ZIPARCHIVE::ER_NOZIP:
  174. $message = 'Not a zip archive';
  175. break;
  176. case ZIPARCHIVE::ER_INCONS:
  177. $message = 'Zip archive inconsistent';
  178. break;
  179. default:
  180. $message = $code;
  181. }
  182. return $message;
  183. }
  184. ?>