summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt1
-rw-r--r--includes/common.inc1
-rw-r--r--includes/image.inc292
-rw-r--r--modules/system.module13
-rw-r--r--modules/system/system.module13
-rw-r--r--modules/upload.module28
-rw-r--r--modules/upload/upload.module28
-rw-r--r--modules/user.module37
-rw-r--r--modules/user/user.module37
9 files changed, 388 insertions, 62 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 1adf7c5ea..b829d56c9 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -23,6 +23,7 @@ Drupal x.x.x, xxxx-xx-xx
* added a simple contact module that allows users to contact each other using e-mail.
- multi-site configuration:
* made it possible to run multiple sites from a single code base.
+- added an image API: enables better image handling.
- block system:
* extended the block visibility settings.
- theme system:
diff --git a/includes/common.inc b/includes/common.inc
index 8a45ff94a..0ace8d84b 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -1806,6 +1806,7 @@ include_once 'includes/menu.inc';
include_once 'includes/tablesort.inc';
include_once 'includes/file.inc';
include_once 'includes/xmlrpc.inc';
+include_once 'includes/image.inc';
// Set the Drupal custom error handler.
set_error_handler('error_handler');
diff --git a/includes/image.inc b/includes/image.inc
new file mode 100644
index 000000000..b485496d7
--- /dev/null
+++ b/includes/image.inc
@@ -0,0 +1,292 @@
+<?php
+// $Id$
+
+/**
+ * Return a list of available toolkits.
+ *
+ * @return An array of toolkit name => descriptive title
+ */
+function image_get_available_toolkits() {
+ $toolkits = file_scan_directory('includes', 'image\..*\.inc$');
+
+ $output = array();
+ foreach ($toolkits as $file => $toolkit) {
+ include_once($file);
+ $function = str_replace('.', '_', $toolkit->name) . '_info';
+ if (function_exists($function)) {
+ $info = $function();
+ $output[$info['name']] = $info['title'];
+ }
+ }
+ $output['gd'] = t('Built-in GD Toolkit');
+ return $output;
+}
+
+/**
+ * Retrieve the name of the currently used toolkit.
+ *
+ * @return String containing the name of the toolkit.
+ */
+function image_get_toolkit() {
+ static $toolkit;
+ if (!$toolkit) {
+ $toolkit = variable_get('image_toolkit', 'gd');
+ if ($toolkit != 'gd') {
+ include_once 'includes/image.'.$toolkit.'.inc';
+ }
+ }
+
+ return $toolkit;
+}
+
+/**
+ * Invokes the given method using the currently selected toolkit.
+ *
+ * @param $method A string containing the method to invoke.
+ * @param $params An optional array of parameters to pass to the toolkit method
+ *
+ * @return Mixed values (typically Boolean for successful operation)
+ */
+function image_toolkit_invoke($method, $params = array()) {
+ $toolkit = image_get_toolkit();
+
+ $function = 'image_' . $toolkit . '_'. $method;
+ if (function_exists($function)) {
+ return call_user_func_array($function, $params);
+ }
+ else {
+ drupal_set_message(t('%method is not supported by %toolkit.', array('%method' => "<em>$method</em>", '%toolkit' => "<em>$toolkit</em>")));
+ }
+}
+
+
+/**
+ * Get details about an image.
+ *
+ * @return array containing information about the image
+ * 'width': image's width in pixels
+ * 'height': image's height in pixels
+ * 'extension': commonly used extension for the image
+ * 'mime_type': image's MIME type ('image/jpeg', 'image/gif', etc.)
+ */
+function image_get_info($file) {
+ if (!file_exists($file)) {
+ return false;
+ }
+
+ $details = false;
+ $data = @getimagesize($file);
+
+ if (is_array($data)) {
+ $extensions = array('1' => 'gif', '2' => 'jpg', '3' => 'png');
+ $extension = array_key_exists($data[2], $extensions) ? $extensions[$data[2]] : '';
+ $details = array('width' => $data[0],
+ 'height' => $data[1],
+ 'extension' => $extension,
+ 'mime_type' => $data['mime']);
+ }
+
+ return $details;
+}
+
+/**
+ * Scales an image to the given width and height while maintaining aspect
+ * ratio.
+ *
+ * @param $source The filepath of the source image
+ * @param $destination The file path of the destination image
+ * @param $width The target width
+ * @param $height The target height
+ *
+ * @return True or false, based on success
+ */
+function image_scale($source, $destination, $width, $height) {
+ $info = image_get_info($source);
+
+ // don't scale up
+ if ($width > $info['width'] && $height > $info['height']) {
+ return false;
+ }
+
+ $aspect = $info['height'] / $info['width'];
+ if ($aspect < $height / $width) {
+ $width = (int)min($width, $info['width']);
+ $height = (int)round($width * $aspect);
+ } else {
+ $height = (int)min($height, $info['height']);
+ $width = (int)round($height / $aspect);
+ }
+
+ return image_toolkit_invoke('resize', array($source, $destination, $width, $height));
+}
+
+/**
+ * Resize an image to the given dimensions (ignoring aspect ratio).
+ *
+ * @param $source The filepath of the source image.
+ * @param $destination The file path of the destination image.
+ * @param $width The target width.
+ * @param $height The target height.
+ */
+function image_resize($source, $destination, $width, $height) {
+ return image_toolkit_invoke('resize', array($source, $destination, $width, $height));
+}
+
+/**
+ * Rotate an image by the given number of degrees.
+ *
+ * @param $source The filepath of the source image
+ * @param $destination The file path of the destination image
+ * @param $degrees The number of (clockwise) degrees to rotate the image
+ */
+function image_rotate($source, $destination, $degrees) {
+ return image_toolkit_invoke('rotate', array($source, $destination, $degrees));
+}
+
+/**
+ * Crop an image to the rectangle specified by the given rectangle.
+ *
+ * @param $source The filepath of the source image
+ * @param $destination The file path of the destination image
+ * @param $x The top left co-ordinate of the crop area (x axis value)
+ * @param $y The top left co-ordinate of the crop area (y axis value)
+ * @param $width The target width
+ * @param $height The target height
+ */
+function image_crop($source, $destination, $x, $y, $width, $height) {
+ return image_toolkit_invoke('crop', array($source, $destination, $x, $y, $width, $height));
+}
+
+/**
+ * GD Toolkit functions
+ */
+
+/**
+ * Verify GD settings (that the extension is actually installed).
+ */
+function image_gd_settings() {
+ if (!extension_loaded('gd')) {
+ drupal_set_message(t('Unable to load the GD toolkit'), 'error');
+ }
+}
+
+/**
+ * Scale an image to the specified size using GD.
+ */
+function image_gd_resize($source, $destination, $width, $height) {
+ if (!file_exists($source)) {
+ return false;
+ }
+
+ $info = image_get_info($source);
+ if (!$info) {
+ return false;
+ }
+
+ $im = image_gd_open($source, $info['extension']);
+ if (!$im) {
+ return false;
+ }
+
+ // GD1 doesn't have true color
+ if (function_exists('imageCreateTrueColor')) {
+ $res = imageCreateTrueColor($width, $height);
+ }
+ else {
+ $res = imageCreate($width, $height);
+ }
+
+ // GD1 doesn't have copyResampled
+ if (function_exists('imageCopyResampled')) {
+ imageCopyResampled($res, $im, 0, 0, 0, 0, $width, $height, $info['width'], $info['height']);
+ }
+ else {
+ imageCopyResized($res, $im, 0, 0, 0, 0, $width, $height, $info['width'], $info['height']);
+ }
+ $result = image_gd_close($res, $destination, $info['extension']);
+
+ imageDestroy($res);
+ imageDestroy($im);
+
+ return $result;
+}
+
+/**
+ * Rotate an image the given number of degrees.
+ */
+function image_gd_rotate($source, $destination, $degrees, $bg_color = 0) {
+ if (!function_exists('imageRotate')) {
+ return false;
+ }
+
+ $info = image_get_info($source);
+ if (!$info) {
+ return false;
+ }
+
+ $im = image_gd_open($source, $info['extension']);
+ if (!$im) {
+ return false;
+ }
+
+ $res = imageRotate($im, $degrees, $bg_color);
+
+ $result = image_gd_close($res, $destination, $info['extension']);
+
+ return $result;
+}
+
+/**
+ * Crop an image using the GD toolkit.
+ */
+function image_gd_crop($source, $destination, $x, $y, $width, $height) {
+ $info = image_get_info($source);
+ if (!$info) {
+ return false;
+ }
+
+ $im = image_gd_open($source, $info['extension']);
+
+ // GD1 doesn't have true color
+ if (function_exists('imageCreateTrueColor')) {
+ $res = imageCreateTrueColor($width, $height);
+ }
+ else {
+ $res = imageCreate($width, $height);
+ }
+
+ imageCopy($im, $res, 0, 0, $x, $y, $width, $height);
+
+ $result = image_gd_close($res, $destination, $info['extension']);
+
+ imageDestroy($res);
+ imageDestroy($im);
+
+ return $result;
+}
+
+/**
+ * GD helper function to create an image resource from a file.
+ */
+function image_gd_open($file, $extension) {
+ $extension = str_replace('jpg', 'jpeg', $extension);
+ $open_func = 'imageCreateFrom'. $extension;
+ if (!function_exists($open_func)) {
+ return false;
+ }
+ return $open_func($file);
+}
+
+/**
+ * GD helper to write an image resource to a destination file.
+ */
+function image_gd_close($res, $destination, $extension) {
+ $extension = str_replace('jpg', 'jpeg', $extension);
+ $close_func = 'image'. $extension;
+ if (!function_exists($close_func)) {
+ return false;
+ }
+ return $close_func($res, $destination);
+}
+
+?>
diff --git a/modules/system.module b/modules/system.module
index b0dcfb443..e42fd19d8 100644
--- a/modules/system.module
+++ b/modules/system.module
@@ -239,6 +239,17 @@ function system_view_general() {
$group .= form_radios(t('Download method'), 'file_downloads', variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC), array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using http directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are transferred by Drupal.')), t('If you want any sort of access control on the downloading of files, this needs to be set to <em>private</em>. You can change this at any time, however all download URLs will change and there may be unexpected problems so it is not recommended.'));
$output .= form_group(t('File system settings'), $group);
+ // image handling:
+ $group = '';
+ $toolkits_available = image_get_available_toolkits();
+ if (count($toolkits_available) > 1) {
+ $group .= form_radios(t('Select an image processing toolkit'), 'image_toolkit', variable_get('image_toolkit', image_get_toolkit()), $toolkits_available);
+ }
+ $group .= image_toolkit_invoke('settings');
+ if ($group) {
+ $output .= form_group(t('Image handling'), $group);
+ }
+
// date settings:
$zones = _system_zonelist();
@@ -612,7 +623,7 @@ function system_theme_settings() {
// Check for a new uploaded logo, and use that instead.
if ($file = file_check_upload('logo_upload')) {
- if (in_array($file->filemime, array('image/jpeg', 'image/gif', 'image/png'))) {
+ if ($info = image_get_info($file->filepath)) {
$parts = pathinfo($file->filename);
$filename = ($key) ? str_replace('/', '_', $key) . '_logo.' . $parts['extension'] : 'logo.' . $parts['extension'];
diff --git a/modules/system/system.module b/modules/system/system.module
index b0dcfb443..e42fd19d8 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -239,6 +239,17 @@ function system_view_general() {
$group .= form_radios(t('Download method'), 'file_downloads', variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC), array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using http directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are transferred by Drupal.')), t('If you want any sort of access control on the downloading of files, this needs to be set to <em>private</em>. You can change this at any time, however all download URLs will change and there may be unexpected problems so it is not recommended.'));
$output .= form_group(t('File system settings'), $group);
+ // image handling:
+ $group = '';
+ $toolkits_available = image_get_available_toolkits();
+ if (count($toolkits_available) > 1) {
+ $group .= form_radios(t('Select an image processing toolkit'), 'image_toolkit', variable_get('image_toolkit', image_get_toolkit()), $toolkits_available);
+ }
+ $group .= image_toolkit_invoke('settings');
+ if ($group) {
+ $output .= form_group(t('Image handling'), $group);
+ }
+
// date settings:
$zones = _system_zonelist();
@@ -612,7 +623,7 @@ function system_theme_settings() {
// Check for a new uploaded logo, and use that instead.
if ($file = file_check_upload('logo_upload')) {
- if (in_array($file->filemime, array('image/jpeg', 'image/gif', 'image/png'))) {
+ if ($info = image_get_info($file->filepath)) {
$parts = pathinfo($file->filename);
$filename = ($key) ? str_replace('/', '_', $key) . '_logo.' . $parts['extension'] : 'logo.' . $parts['extension'];
diff --git a/modules/upload.module b/modules/upload.module
index c1fc08641..559b46d87 100644
--- a/modules/upload.module
+++ b/modules/upload.module
@@ -63,7 +63,8 @@ function upload_menu($may_cache) {
function upload_admin() {
system_settings_save();
- $group .= form_textfield(t('Maximum total file size'), 'upload_maxsize_total', variable_get('upload_maxsize_total', 0), 5, 5, t('The maximum size of a file a user can upload in megabytes. Enter 0 for unlimited.'));
+ $group .= form_textfield(t('Maximum total file size'), 'upload_maxsize_total', variable_get('upload_maxsize_total', 0), 10, 10, t('The maximum size of a file a user can upload in megabytes. Enter 0 for unlimited.'));
+ $group .= form_textfield(t('Maximum resolution for uploaded images'), 'upload_max_resolution', variable_get('upload_max_resolution', 0), 10, 10, t('The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Set to 0 for no restriction.'));
$output = form_group(t('General settings'), $group);
@@ -138,7 +139,9 @@ function upload_nodeapi(&$node, $op, $arg) {
if (($file = file_check_upload('upload')) && user_access('upload files')) {
global $user;
- $max_size = variable_get("upload_maxsize_total", 0);
+ $file = _upload_image($file);
+
+ $maxsize = variable_get("upload_maxsize_total", 0);
$total_size = upload_count_size() + $filesize;
$total_usersize = upload_count_size($user->uid) + $filesize;
@@ -371,4 +374,25 @@ function upload_load($node) {
return $files;
}
+/**
+ * Check an upload, if it is an image, make sure it fits within the
+ * maximum dimensions allowed.
+ */
+function _upload_image($file) {
+ $info = image_get_info($file->filepath);
+
+ if ($info) {
+ list($width, $height) = explode('x', variable_get('upload_max_resolution', 0));
+ if ($width && $height) {
+ $result = image_scale($file->filepath, $file->filepath, $width, $height);
+ if ($result) {
+ $file->filesize = filesize($file->filepath);
+ drupal_set_message(t('Your image was resized to fit within the maximum allowed resolution of %resolution pixels.', array('%resolution' => variable_get('upload_max_resolution', 0))));
+ }
+ }
+ }
+
+ return $file;
+}
+
?>
diff --git a/modules/upload/upload.module b/modules/upload/upload.module
index c1fc08641..559b46d87 100644
--- a/modules/upload/upload.module
+++ b/modules/upload/upload.module
@@ -63,7 +63,8 @@ function upload_menu($may_cache) {
function upload_admin() {
system_settings_save();
- $group .= form_textfield(t('Maximum total file size'), 'upload_maxsize_total', variable_get('upload_maxsize_total', 0), 5, 5, t('The maximum size of a file a user can upload in megabytes. Enter 0 for unlimited.'));
+ $group .= form_textfield(t('Maximum total file size'), 'upload_maxsize_total', variable_get('upload_maxsize_total', 0), 10, 10, t('The maximum size of a file a user can upload in megabytes. Enter 0 for unlimited.'));
+ $group .= form_textfield(t('Maximum resolution for uploaded images'), 'upload_max_resolution', variable_get('upload_max_resolution', 0), 10, 10, t('The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Set to 0 for no restriction.'));
$output = form_group(t('General settings'), $group);
@@ -138,7 +139,9 @@ function upload_nodeapi(&$node, $op, $arg) {
if (($file = file_check_upload('upload')) && user_access('upload files')) {
global $user;
- $max_size = variable_get("upload_maxsize_total", 0);
+ $file = _upload_image($file);
+
+ $maxsize = variable_get("upload_maxsize_total", 0);
$total_size = upload_count_size() + $filesize;
$total_usersize = upload_count_size($user->uid) + $filesize;
@@ -371,4 +374,25 @@ function upload_load($node) {
return $files;
}
+/**
+ * Check an upload, if it is an image, make sure it fits within the
+ * maximum dimensions allowed.
+ */
+function _upload_image($file) {
+ $info = image_get_info($file->filepath);
+
+ if ($info) {
+ list($width, $height) = explode('x', variable_get('upload_max_resolution', 0));
+ if ($width && $height) {
+ $result = image_scale($file->filepath, $file->filepath, $width, $height);
+ if ($result) {
+ $file->filesize = filesize($file->filepath);
+ drupal_set_message(t('Your image was resized to fit within the maximum allowed resolution of %resolution pixels.', array('%resolution' => variable_get('upload_max_resolution', 0))));
+ }
+ }
+ }
+
+ return $file;
+}
+
?>
diff --git a/modules/user.module b/modules/user.module
index d896367bc..785d72b80 100644
--- a/modules/user.module
+++ b/modules/user.module
@@ -227,20 +227,19 @@ function user_validate_picture($file, &$edit, $user) {
// Check that uploaded file is an image, with a maximum file size
// and maximum height/width.
- $extension = strtolower(strrchr($file->filename, '.'));
- $size = @getimagesize($file->filepath);
+ $info = image_get_info($file->filepath);
list($maxwidth, $maxheight) = explode('x', variable_get('user_picture_dimensions', '85x85'));
- if ((!in_array($size[2], array(1, 2, 3))) || (!in_array($extension, array('.gif', '.jpg', '.png', '.jpeg')))) {
+ if (!$info || !$info['extension']) {
form_set_error('picture', t('The uploaded file was not an image.'));
}
- else if ($file->size > (variable_get('user_picture_file_size', '30') * 1000)) {
- form_set_error('picture', t('The uploaded image is too large; the maximum file size is %size kB.', array('%size' => variable_get('user_picture_file_size', '30'))));
- }
- else if ($size[0] > $maxwidth || $size[1] > $maxheight) {
+ else if (!image_scale($file->filepath, $file->filepath, $maxwidth, $maxheight)) {
form_set_error('picture', t('The uploaded image is too large; the maximum dimensions are %dimensions pixels.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'))));
}
- else if ($file = file_save_upload('picture', variable_get('user_picture_path', 'pictures') .'/picture-'. $user->uid . $extension, 1)) {
+ else if (filesize($file->filepath) > (variable_get('user_picture_file_size', '30') * 1000)) {
+ form_set_error('picture', t('The uploaded image is too large; the maximum file size is %size kB.', array('%size' => variable_get('user_picture_file_size', '30'))));
+ }
+ else if ($file = file_save_upload('picture', variable_get('user_picture_path', 'pictures') .'/picture-'. $user->uid . '.' . $info['extension'], 1)) {
$edit['picture'] = $file->filepath;
}
else {
@@ -403,26 +402,8 @@ function user_perm() {
*/
function user_file_download($file) {
if (strpos($file, variable_get('user_picture_path', 'pictures') .'/picture-') === 0) {
- list($width, $height, $type, $attr) = @getimagesize(file_create_path($file));
- $types = array(
- IMAGETYPE_GIF => 'image/gif',
- IMAGETYPE_JPEG => 'image/jpeg',
- IMAGETYPE_PNG => 'image/png',
- IMAGETYPE_SWF => 'application/x-shockwave-flash',
- IMAGETYPE_PSD => 'image/psd',
- IMAGETYPE_BMP => 'image/bmp',
- IMAGETYPE_TIFF_II => 'image/tiff',
- IMAGETYPE_TIFF_MM => 'image/tiff',
- IMAGETYPE_JPC => 'application/octet-stream',
- IMAGETYPE_JP2 => 'image/jp2',
- IMAGETYPE_JPX => 'application/octet-stream',
- IMAGETYPE_JB2 => 'application/octet-stream',
- IMAGETYPE_SWC => 'application/x-shockwave-flash',
- IMAGETYPE_IFF => 'image/iff',
- IMAGETYPE_WBMP => 'image/vnd.wap.wbmp',
- IMAGETYPE_XBM => 'image/xbm'
- );
- return array('Content-type: '. $types[$type]);
+ $info = image_get_info(file_create_path($file));
+ return array('Content-type: '. $info['mime_type']);
}
}
diff --git a/modules/user/user.module b/modules/user/user.module
index d896367bc..785d72b80 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -227,20 +227,19 @@ function user_validate_picture($file, &$edit, $user) {
// Check that uploaded file is an image, with a maximum file size
// and maximum height/width.
- $extension = strtolower(strrchr($file->filename, '.'));
- $size = @getimagesize($file->filepath);
+ $info = image_get_info($file->filepath);
list($maxwidth, $maxheight) = explode('x', variable_get('user_picture_dimensions', '85x85'));
- if ((!in_array($size[2], array(1, 2, 3))) || (!in_array($extension, array('.gif', '.jpg', '.png', '.jpeg')))) {
+ if (!$info || !$info['extension']) {
form_set_error('picture', t('The uploaded file was not an image.'));
}
- else if ($file->size > (variable_get('user_picture_file_size', '30') * 1000)) {
- form_set_error('picture', t('The uploaded image is too large; the maximum file size is %size kB.', array('%size' => variable_get('user_picture_file_size', '30'))));
- }
- else if ($size[0] > $maxwidth || $size[1] > $maxheight) {
+ else if (!image_scale($file->filepath, $file->filepath, $maxwidth, $maxheight)) {
form_set_error('picture', t('The uploaded image is too large; the maximum dimensions are %dimensions pixels.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'))));
}
- else if ($file = file_save_upload('picture', variable_get('user_picture_path', 'pictures') .'/picture-'. $user->uid . $extension, 1)) {
+ else if (filesize($file->filepath) > (variable_get('user_picture_file_size', '30') * 1000)) {
+ form_set_error('picture', t('The uploaded image is too large; the maximum file size is %size kB.', array('%size' => variable_get('user_picture_file_size', '30'))));
+ }
+ else if ($file = file_save_upload('picture', variable_get('user_picture_path', 'pictures') .'/picture-'. $user->uid . '.' . $info['extension'], 1)) {
$edit['picture'] = $file->filepath;
}
else {
@@ -403,26 +402,8 @@ function user_perm() {
*/
function user_file_download($file) {
if (strpos($file, variable_get('user_picture_path', 'pictures') .'/picture-') === 0) {
- list($width, $height, $type, $attr) = @getimagesize(file_create_path($file));
- $types = array(
- IMAGETYPE_GIF => 'image/gif',
- IMAGETYPE_JPEG => 'image/jpeg',
- IMAGETYPE_PNG => 'image/png',
- IMAGETYPE_SWF => 'application/x-shockwave-flash',
- IMAGETYPE_PSD => 'image/psd',
- IMAGETYPE_BMP => 'image/bmp',
- IMAGETYPE_TIFF_II => 'image/tiff',
- IMAGETYPE_TIFF_MM => 'image/tiff',
- IMAGETYPE_JPC => 'application/octet-stream',
- IMAGETYPE_JP2 => 'image/jp2',
- IMAGETYPE_JPX => 'application/octet-stream',
- IMAGETYPE_JB2 => 'application/octet-stream',
- IMAGETYPE_SWC => 'application/x-shockwave-flash',
- IMAGETYPE_IFF => 'image/iff',
- IMAGETYPE_WBMP => 'image/vnd.wap.wbmp',
- IMAGETYPE_XBM => 'image/xbm'
- );
- return array('Content-type: '. $types[$type]);
+ $info = image_get_info(file_create_path($file));
+ return array('Content-type: '. $info['mime_type']);
}
}