'
. '' . "\n";
return $html;
}
/**
* Computes the memory limit for export
*
* @return int $memory_limit the memory limit
*/
public static function getMemoryLimit()
{
$memory_limit = trim(ini_get('memory_limit'));
$memory_limit_num = (int)substr($memory_limit, 0, -1);
$lowerLastChar = strtolower(substr($memory_limit, -1));
// 2 MB as default
if (empty($memory_limit) || '-1' == $memory_limit) {
$memory_limit = 2 * 1024 * 1024;
} elseif ($lowerLastChar == 'm') {
$memory_limit = $memory_limit_num * 1024 * 1024;
} elseif ($lowerLastChar == 'k') {
$memory_limit = $memory_limit_num * 1024;
} elseif ($lowerLastChar == 'g') {
$memory_limit = $memory_limit_num * 1024 * 1024 * 1024;
} else {
$memory_limit = (int)$memory_limit;
}
// Some of memory is needed for other things and as threshold.
// During export I had allocated (see memory_get_usage function)
// approx 1.2MB so this comes from that.
if ($memory_limit > 1500000) {
$memory_limit -= 1500000;
}
// Some memory is needed for compression, assume 1/3
$memory_limit /= 8;
return $memory_limit;
}
/**
* Return the filename and MIME type for export file
*
* @param string $export_type type of export
* @param string $remember_template whether to remember template
* @param ExportPlugin $export_plugin the export plugin
* @param string $compression compression asked
* @param string $filename_template the filename template
*
* @return string[] the filename template and mime type
*/
public static function getFilenameAndMimetype(
$export_type, $remember_template, $export_plugin, $compression,
$filename_template
) {
if ($export_type == 'server') {
if (! empty($remember_template)) {
$GLOBALS['PMA_Config']->setUserValue(
'pma_server_filename_template',
'Export/file_template_server',
$filename_template
);
}
} elseif ($export_type == 'database') {
if (! empty($remember_template)) {
$GLOBALS['PMA_Config']->setUserValue(
'pma_db_filename_template',
'Export/file_template_database',
$filename_template
);
}
} else {
if (! empty($remember_template)) {
$GLOBALS['PMA_Config']->setUserValue(
'pma_table_filename_template',
'Export/file_template_table',
$filename_template
);
}
}
$filename = Util::expandUserString($filename_template);
// remove dots in filename (coming from either the template or already
// part of the filename) to avoid a remote code execution vulnerability
$filename = Sanitize::sanitizeFilename($filename, $replaceDots = true);
// Grab basic dump extension and mime type
// Check if the user already added extension;
// get the substring where the extension would be if it was included
$extension_start_pos = mb_strlen($filename) - mb_strlen(
$export_plugin->getProperties()->getExtension()
) - 1;
$user_extension = mb_substr(
$filename, $extension_start_pos, mb_strlen($filename)
);
$required_extension = "." . $export_plugin->getProperties()->getExtension();
if (mb_strtolower($user_extension) != $required_extension) {
$filename .= $required_extension;
}
$mime_type = $export_plugin->getProperties()->getMimeType();
// If dump is going to be compressed, set correct mime_type and add
// compression to extension
if ($compression == 'gzip') {
$filename .= '.gz';
$mime_type = 'application/x-gzip';
} elseif ($compression == 'zip') {
$filename .= '.zip';
$mime_type = 'application/zip';
}
return array($filename, $mime_type);
}
/**
* Open the export file
*
* @param string $filename the export filename
* @param boolean $quick_export whether it's a quick export or not
*
* @return array the full save filename, possible message and the file handle
*/
public static function openFile($filename, $quick_export)
{
$file_handle = null;
$message = '';
$doNotSaveItOver = true;
if(isset($_POST['quick_export_onserver_overwrite'])) {
$doNotSaveItOver = $_POST['quick_export_onserver_overwrite'] != 'saveitover';
}
$save_filename = Util::userDir($GLOBALS['cfg']['SaveDir'])
. preg_replace('@[/\\\\]@', '_', $filename);
if (@file_exists($save_filename)
&& ((! $quick_export && empty($_POST['onserver_overwrite']))
|| ($quick_export
&& $doNotSaveItOver))
) {
$message = Message::error(
__(
'File %s already exists on server, '
. 'change filename or check overwrite option.'
)
);
$message->addParam($save_filename);
} elseif (@is_file($save_filename) && ! @is_writable($save_filename)) {
$message = Message::error(
__(
'The web server does not have permission '
. 'to save the file %s.'
)
);
$message->addParam($save_filename);
} elseif (! $file_handle = @fopen($save_filename, 'w')) {
$message = Message::error(
__(
'The web server does not have permission '
. 'to save the file %s.'
)
);
$message->addParam($save_filename);
}
return array($save_filename, $message, $file_handle);
}
/**
* Close the export file
*
* @param resource $file_handle the export file handle
* @param string $dump_buffer the current dump buffer
* @param string $save_filename the export filename
*
* @return Message $message a message object (or empty string)
*/
public static function closeFile($file_handle, $dump_buffer, $save_filename)
{
$write_result = @fwrite($file_handle, $dump_buffer);
fclose($file_handle);
// Here, use strlen rather than mb_strlen to get the length
// in bytes to compare against the number of bytes written.
if (strlen($dump_buffer) > 0
&& (! $write_result || $write_result != strlen($dump_buffer))
) {
$message = new Message(
__('Insufficient space to save the file %s.'),
Message::ERROR,
array($save_filename)
);
} else {
$message = new Message(
__('Dump has been saved to file %s.'),
Message::SUCCESS,
array($save_filename)
);
}
return $message;
}
/**
* Compress the export buffer
*
* @param array|string $dump_buffer the current dump buffer
* @param string $compression the compression mode
* @param string $filename the filename
*
* @return object $message a message object (or empty string)
*/
public static function compress($dump_buffer, $compression, $filename)
{
if ($compression == 'zip' && function_exists('gzcompress')) {
$zipExtension = new ZipExtension();
$filename = substr($filename, 0, -4); // remove extension (.zip)
$dump_buffer = $zipExtension->createFile($dump_buffer, $filename);
} elseif ($compression == 'gzip' && self::gzencodeNeeded()) {
// without the optional parameter level because it bugs
$dump_buffer = gzencode($dump_buffer);
}
return $dump_buffer;
}
/**
* Saves the dump_buffer for a particular table in an array
* Used in separate files export
*
* @param string $object_name the name of current object to be stored
* @param boolean $append optional boolean to append to an existing index or not
*
* @return void
*/
public static function saveObjectInBuffer($object_name, $append = false)
{
global $dump_buffer_objects, $dump_buffer, $dump_buffer_len;
if (! empty($dump_buffer)) {
if ($append && isset($dump_buffer_objects[$object_name])) {
$dump_buffer_objects[$object_name] .= $dump_buffer;
} else {
$dump_buffer_objects[$object_name] = $dump_buffer;
}
}
// Re - initialize
$dump_buffer = '';
$dump_buffer_len = 0;
}
/**
* Returns HTML containing the header for a displayed export
*
* @param string $export_type the export type
* @param string $db the database name
* @param string $table the table name
*
* @return string[] the generated HTML and back button
*/
public static function getHtmlForDisplayedExportHeader($export_type, $db, $table)
{
$html = '
';
/**
* Displays a back button with all the $_POST data in the URL
* (store in a variable to also display after the textarea)
*/
$back_button = '