mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-01-08 11:11:39 +09:00
파일이나 확장자가 이미지, 오디오, 동영상이며, MIME 타입이 전혀 다른 경우에만 확장자를 고치도록 수정
direct가 아닌 첨부파일 본문 삽입시의 오류 수정 이미지, 오디오, 동영상 MIME 타입을 mime_content_type()의 반환값으로 수정
This commit is contained in:
parent
ac9141b4f2
commit
6db830c4c4
9 changed files with 122 additions and 100 deletions
|
|
@ -97,7 +97,7 @@ class FilenameFilter
|
||||||
*/
|
*/
|
||||||
public static function isDirectDownload($filename)
|
public static function isDirectDownload($filename)
|
||||||
{
|
{
|
||||||
if (preg_match('/\.(as[fx]|avi|flac|flv|gif|jpe?g|m4[av]|midi?|mkv|moov|mov|mp[1234]|mpe?g|ogg|png|qt|ram?|rmm?|wav|web[mp]|wm[av])$/i', $filename))
|
if (preg_match('/\.(as[fx]|avi|flac|flv|gif|jpe?g|m4[av]|midi?|mkv|moov|mov|mp[1234]|mpe?g|og[gv]|png|qt|ram?|rmm?|wav|web[mp]|wm[av])$/i', $filename))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,11 +63,20 @@ class Image
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
$img_type = [
|
||||||
|
IMG_GIF => 'gif',
|
||||||
|
IMG_JPG => 'jpg',
|
||||||
|
// jpeg is the same as jpg
|
||||||
|
IMG_PNG => 'png',
|
||||||
|
IMG_WEBP => 'webp',
|
||||||
|
IMG_WBMP => 'wbmp',
|
||||||
|
IMG_XPM => 'xpm',
|
||||||
|
(defined('IMG_BMP') ? IMG_BMP : 64) => 'bmp',
|
||||||
|
];
|
||||||
return [
|
return [
|
||||||
'width' => $image_info[0],
|
'width' => $image_info[0],
|
||||||
'height' => $image_info[1],
|
'height' => $image_info[1],
|
||||||
'type' => image_type_to_extension($image_info[2], false),
|
'type' => $img_type[$image_info[2]],
|
||||||
'mime' => $image_info['mime'],
|
|
||||||
'bits' => $image_info['bits'] ?? null,
|
'bits' => $image_info['bits'] ?? null,
|
||||||
'channels' => $image_info['channels'] ?? null,
|
'channels' => $image_info['channels'] ?? null,
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class MIME
|
||||||
public static function getTypeByExtension($extension)
|
public static function getTypeByExtension($extension)
|
||||||
{
|
{
|
||||||
$extension = strtolower($extension);
|
$extension = strtolower($extension);
|
||||||
return array_key_exists($extension, self::$_types) ? self::$_types[$extension] : self::$_default;
|
return array_key_exists($extension, self::$_types) ? self::$_types[$extension][0] : self::$_default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -30,7 +30,7 @@ class MIME
|
||||||
$extension = strrchr($filename, '.');
|
$extension = strrchr($filename, '.');
|
||||||
if ($extension === false) return self::$_default;
|
if ($extension === false) return self::$_default;
|
||||||
$extension = strtolower(substr($extension, 1));
|
$extension = strtolower(substr($extension, 1));
|
||||||
return array_key_exists($extension, self::$_types) ? self::$_types[$extension] : self::$_default;
|
return array_key_exists($extension, self::$_types) ? self::$_types[$extension][0] : self::$_default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -41,9 +41,12 @@ class MIME
|
||||||
*/
|
*/
|
||||||
public static function getExtensionByType($type)
|
public static function getExtensionByType($type)
|
||||||
{
|
{
|
||||||
foreach (self::$_types as $extension => $mime)
|
foreach (self::$_types as $extension => $mimes)
|
||||||
{
|
{
|
||||||
if (!strncasecmp($type, $mime, strlen($type))) return $extension;
|
foreach ($mimes as $mime)
|
||||||
|
{
|
||||||
|
if (!strncasecmp($type, $mime, strlen($type))) return $extension;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -59,96 +62,106 @@ class MIME
|
||||||
protected static $_types = array(
|
protected static $_types = array(
|
||||||
|
|
||||||
// Text-based document formats.
|
// Text-based document formats.
|
||||||
'html' => 'text/html',
|
'html' => ['text/html'],
|
||||||
'htm' => 'text/html',
|
'htm' => ['text/html'],
|
||||||
'shtml' => 'text/html',
|
'shtml' => ['text/html'],
|
||||||
'txt' => 'text/plain',
|
'txt' => ['text/plain'],
|
||||||
'text' => 'text/plain',
|
'text' => ['text/plain'],
|
||||||
'log' => 'text/plain',
|
'log' => ['text/plain'],
|
||||||
'md' => 'text/markdown',
|
'md' => ['text/markdown'],
|
||||||
'markdown' => 'text/markdown',
|
'markdown' => ['text/markdown'],
|
||||||
'rtf' => 'text/rtf',
|
'rtf' => ['text/rtf'],
|
||||||
'xml' => 'text/xml',
|
'xml' => ['text/xml'],
|
||||||
'xsl' => 'text/xml',
|
'xsl' => ['text/xml'],
|
||||||
'css' => 'text/css',
|
'css' => ['text/css'],
|
||||||
'csv' => 'text/csv',
|
'csv' => ['text/csv'],
|
||||||
|
|
||||||
// Binary document formats.
|
// Binary document formats.
|
||||||
'doc' => 'application/msword',
|
'doc' => ['application/msword'],
|
||||||
'dot' => 'application/msword',
|
'dot' => ['application/msword'],
|
||||||
'xls' => 'application/vnd.ms-excel',
|
'xls' => ['application/vnd.ms-excel'],
|
||||||
'ppt' => 'application/vnd.ms-powerpoint',
|
'ppt' => ['application/vnd.ms-powerpoint'],
|
||||||
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
|
||||||
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
'dotx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
|
||||||
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
|
||||||
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation'],
|
||||||
'odt' => 'application/vnd.oasis.opendocument.text',
|
'odt' => ['application/vnd.oasis.opendocument.text'],
|
||||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
'ods' => ['application/vnd.oasis.opendocument.spreadsheet'],
|
||||||
'odp' => 'application/vnd.oasis.opendocument.presentation',
|
'odp' => ['application/vnd.oasis.opendocument.presentation'],
|
||||||
'odg' => 'application/vnd.oasis.opendocument.graphics',
|
'odg' => ['application/vnd.oasis.opendocument.graphics'],
|
||||||
'odb' => 'application/vnd.oasis.opendocument.database',
|
'odb' => ['application/vnd.oasis.opendocument.database'],
|
||||||
'pdf' => 'application/pdf',
|
'pdf' => ['application/pdf'],
|
||||||
|
'dvi' => ['application/x-dvi'],
|
||||||
|
|
||||||
// Images.
|
// Images.
|
||||||
'bmp' => 'image/bmp',
|
'bmp' => ['image/bmp'],
|
||||||
'gif' => 'image/gif',
|
'gif' => ['image/gif'],
|
||||||
'jpg' => 'image/jpeg',
|
'jpg' => ['image/jpeg'],
|
||||||
'jpeg' => 'image/jpeg',
|
'jpeg' => ['image/jpeg'],
|
||||||
'jpe' => 'image/jpeg',
|
'jpe' => ['image/jpeg'],
|
||||||
'png' => 'image/png',
|
'png' => ['image/png'],
|
||||||
'svg' => 'image/svg+xml',
|
'webp' => ['image/webp'],
|
||||||
'tiff' => 'image/tiff',
|
'svg' => ['image/svg+xml'],
|
||||||
'tif' => 'image/tiff',
|
'tiff' => ['image/tiff'],
|
||||||
'ico' => 'image/vnd.microsoft.icon',
|
'tif' => ['image/tiff'],
|
||||||
|
'ico' => ['image/x-icon'],
|
||||||
|
|
||||||
// Audio.
|
// Audio.
|
||||||
'mid' => 'audio/midi',
|
'mid' => ['audio/midi'],
|
||||||
'midi' => 'audio/midi',
|
'midi' => ['audio/midi'],
|
||||||
'mpga' => 'audio/mpeg',
|
'mp3' => ['audio/mpeg'],
|
||||||
'mp2' => 'audio/mpeg',
|
'mpga' => ['audio/mpeg'],
|
||||||
'mp3' => 'audio/mpeg',
|
'mp2' => ['audio/mpeg'],
|
||||||
'aif' => 'audio/x-aiff',
|
'aif' => ['audio/x-aiff'],
|
||||||
'aiff' => 'audio/x-aiff',
|
'aiff' => ['audio/x-aiff'],
|
||||||
'ra' => 'audio/x-realaudio',
|
'ra' => ['audio/x-realaudio'],
|
||||||
'wav' => 'audio/x-wav',
|
'wav' => ['audio/x-wav'],
|
||||||
'ogg' => 'audio/ogg',
|
'ogg' => ['audio/ogg'],
|
||||||
|
'm4a' => ['audio/x-m4a'],
|
||||||
|
|
||||||
// Video.
|
// Video.
|
||||||
'avi' => 'video/x-msvideo',
|
'avi' => ['video/x-msvideo'],
|
||||||
'flv' => 'video/x-flv',
|
'flv' => ['video/x-flv'],
|
||||||
'mpeg' => 'video/mpeg',
|
'mpg' => ['video/mpeg'],
|
||||||
'mpg' => 'video/mpeg',
|
'mpeg' => ['video/mpeg'],
|
||||||
'mpe' => 'video/mpeg',
|
'mpe' => ['video/mpeg'],
|
||||||
'mp4' => 'video/mpeg',
|
'mp4' => ['video/mp4'],
|
||||||
'qt' => 'video/quicktime',
|
'webm' => ['video/webm'],
|
||||||
'mov' => 'video/quicktime',
|
'ogv' => ['video/ogg'],
|
||||||
'movie' => 'video/x-sgi-movie',
|
'mov' => ['video/quicktime'],
|
||||||
'rv' => 'video/vnd.rn-realvideo',
|
'moov' => ['video/quicktime'],
|
||||||
'dvi' => 'application/x-dvi',
|
'qt' => ['video/quicktime'],
|
||||||
|
'movie' => ['video/x-sgi-movie'],
|
||||||
|
'rv' => ['video/vnd.rn-realvideo'],
|
||||||
|
'mkv' => ['video/x-matroska'],
|
||||||
|
'wmv' => ['video/x-ms-asf'],
|
||||||
|
'wma' => ['video/x-ms-asf'],
|
||||||
|
'asf' => ['video/x-ms-asf'],
|
||||||
|
'm4v' => ['video/x-m4v'],
|
||||||
|
|
||||||
// Other multimedia file formats.
|
// Other multimedia file formats.
|
||||||
'psd' => 'application/x-photoshop',
|
'psd' => ['application/x-photoshop'],
|
||||||
'swf' => 'application/x-shockwave-flash',
|
'swf' => ['application/x-shockwave-flash'],
|
||||||
'ai' => 'application/postscript',
|
'ai' => ['application/postscript'],
|
||||||
'eps' => 'application/postscript',
|
'eps' => ['application/postscript'],
|
||||||
'ps' => 'application/postscript',
|
'ps' => ['application/postscript'],
|
||||||
'mif' => 'application/vnd.mif',
|
'mif' => ['application/vnd.mif'],
|
||||||
'xul' => 'application/vnd.mozilla.xul+xml',
|
'xul' => ['application/vnd.mozilla.xul+xml'],
|
||||||
|
|
||||||
// Source code formats.
|
// Source code formats.
|
||||||
'phps' => 'application/x-httpd-php-source',
|
'phps' => ['application/x-httpd-php-source'],
|
||||||
'js' => 'application/x-javascript',
|
'js' => ['application/x-javascript'],
|
||||||
|
|
||||||
// Archives.
|
// Archives.
|
||||||
'bz2' => 'application/x-bzip',
|
'bz2' => ['application/x-bzip'],
|
||||||
'gz' => 'application/x-gzip',
|
'gz' => ['application/x-gzip'],
|
||||||
'tar' => 'application/x-tar',
|
'tar' => ['application/x-tar'],
|
||||||
'tgz' => 'application/x-tar',
|
'tgz' => ['application/x-tar'],
|
||||||
'gtar' => 'application/x-gtar',
|
'gtar' => ['application/x-gtar'],
|
||||||
'rar' => 'application/x-rar-compressed',
|
'rar' => ['application/x-rar-compressed'],
|
||||||
'zip' => 'application/x-zip',
|
'zip' => ['application/x-zip'],
|
||||||
|
|
||||||
// RFC822 email message.
|
// RFC822 email message.
|
||||||
'eml' => 'message/rfc822',
|
'eml' => ['message/rfc822'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -154,10 +154,10 @@
|
||||||
if(/\.(jpe?g|png|gif|webp)$/i.test(result.source_filename)) {
|
if(/\.(jpe?g|png|gif|webp)$/i.test(result.source_filename)) {
|
||||||
temp_code += '<img src="' + result.download_url + '" alt="' + result.source_filename + '" editor_component="image_link" data-file-srl="' + result.file_srl + '" />';
|
temp_code += '<img src="' + result.download_url + '" alt="' + result.source_filename + '" editor_component="image_link" data-file-srl="' + result.file_srl + '" />';
|
||||||
}
|
}
|
||||||
else if(/\.(mp3)$/i.test(result.source_filename)) {
|
else if(/\.(mp3|ogg|wav)$/i.test(result.source_filename)) {
|
||||||
temp_code += '<audio src="' + result.download_url + '" controls data-file-srl="' + result.file_srl + '" />';
|
temp_code += '<audio src="' + result.download_url + '" controls data-file-srl="' + result.file_srl + '" />';
|
||||||
}
|
}
|
||||||
else if(/\.(mp4|webm|ogg)$/i.test(result.source_filename)) {
|
else if(/\.(mp4|webm|ogv)$/i.test(result.source_filename)) {
|
||||||
if(result.original_type === 'image/gif') {
|
if(result.original_type === 'image/gif') {
|
||||||
temp_code += '<video src="' + result.download_url + '" autoplay loop muted data-file-srl="' + result.file_srl + '" />';
|
temp_code += '<video src="' + result.download_url + '" autoplay loop muted data-file-srl="' + result.file_srl + '" />';
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -326,10 +326,10 @@
|
||||||
if(/\.(jpe?g|png|gif|webp)$/i.test(result.source_filename)) {
|
if(/\.(jpe?g|png|gif|webp)$/i.test(result.source_filename)) {
|
||||||
temp_code += '<img src="' + result.download_url + '" alt="' + result.source_filename + '" editor_component="image_link" data-file-srl="' + result.file_srl + '" />';
|
temp_code += '<img src="' + result.download_url + '" alt="' + result.source_filename + '" editor_component="image_link" data-file-srl="' + result.file_srl + '" />';
|
||||||
}
|
}
|
||||||
else if(/\.(mp3)$/i.test(result.source_filename)) {
|
else if(/\.(mp3|ogg|wav)$/i.test(result.source_filename)) {
|
||||||
temp_code += '<audio src="' + result.download_url + '" controls data-file-srl="' + result.file_srl + '" />';
|
temp_code += '<audio src="' + result.download_url + '" controls data-file-srl="' + result.file_srl + '" />';
|
||||||
}
|
}
|
||||||
else if(/\.(mp4|webm|ogg)$/i.test(result.source_filename)) {
|
else if(/\.(mp4|webm|ogv)$/i.test(result.source_filename)) {
|
||||||
if(result.original_type === 'image/gif') {
|
if(result.original_type === 'image/gif') {
|
||||||
temp_code += '<video src="' + result.download_url + '" autoplay loop muted data-file-srl="' + result.file_srl + '" />';
|
temp_code += '<video src="' + result.download_url + '" autoplay loop muted data-file-srl="' + result.file_srl + '" />';
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -343,7 +343,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(temp_code === '') {
|
if(temp_code === '') {
|
||||||
temp_code += '<a href="' + fileinfo.download_url + '" data-file-srl="' + fileinfo.file_srl + '">' + fileinfo.source_filename + "</a>\n";
|
temp_code += '<a href="' + result.download_url + '" data-file-srl="' + result.file_srl + '">' + result.source_filename + "</a>\n";
|
||||||
}
|
}
|
||||||
_getCkeInstance(data.editorSequence).insertHtml(temp_code, "unfiltered_html");
|
_getCkeInstance(data.editorSequence).insertHtml(temp_code, "unfiltered_html");
|
||||||
});
|
});
|
||||||
|
|
@ -437,7 +437,7 @@
|
||||||
file.source_filename = file.source_filename.replace("&", "&");
|
file.source_filename = file.source_filename.replace("&", "&");
|
||||||
if(file.thumbnail_filename) {
|
if(file.thumbnail_filename) {
|
||||||
file.download_url = file.thumbnail_filename;
|
file.download_url = file.thumbnail_filename;
|
||||||
if(/\.(mp4|webm|ogg)$/i.test(file.source_filename)) {
|
if(/\.(mp4|webm|ogv)$/i.test(file.source_filename)) {
|
||||||
result_image.push(template_fileimte_video(file));
|
result_image.push(template_fileimte_video(file));
|
||||||
} else {
|
} else {
|
||||||
result_image.push(template_fileimte_image(file));
|
result_image.push(template_fileimte_image(file));
|
||||||
|
|
|
||||||
|
|
@ -884,17 +884,13 @@ class fileController extends file
|
||||||
$file_info['converted'] = false;
|
$file_info['converted'] = false;
|
||||||
|
|
||||||
// Correct extension
|
// Correct extension
|
||||||
if($extension_by_type = Rhymix\Framework\MIME::getExtensionByType($file_info['type']))
|
if($file_info['extension'])
|
||||||
{
|
{
|
||||||
$target_types = ['image', 'audio', 'video'];
|
$type_by_extension = Rhymix\Framework\MIME::getTypeByExtension($file_info['extension']);
|
||||||
if(in_array(array_shift(explode('/', $file_info['type'])), $target_types))
|
if(!in_array($type_by_extension, [$file_info['type'], 'application/octet-stream']))
|
||||||
{
|
{
|
||||||
$file_info['extension'] = $extension_by_type;
|
$extension_by_type = Rhymix\Framework\MIME::getExtensionByType($file_info['type']);
|
||||||
}
|
if($extension_by_type && preg_match('@^(?:image|audio|video)/@m', $file_info['type'] . PHP_EOL . $type_by_extension))
|
||||||
elseif($file_info['extension'])
|
|
||||||
{
|
|
||||||
$type_by_extension = Rhymix\Framework\MIME::getTypeByExtension($file_info['extension']);
|
|
||||||
if(in_array(array_shift(explode('/', $type_by_extension)), $target_types))
|
|
||||||
{
|
{
|
||||||
$file_info['extension'] = $extension_by_type;
|
$file_info['extension'] = $extension_by_type;
|
||||||
}
|
}
|
||||||
|
|
@ -924,7 +920,7 @@ class fileController extends file
|
||||||
}
|
}
|
||||||
|
|
||||||
// video
|
// video
|
||||||
if(in_array($file_info['extension'], ['mp4', 'webm', 'ogg']))
|
if(in_array($file_info['extension'], ['mp4', 'webm', 'ogv']))
|
||||||
{
|
{
|
||||||
$file_info = $this->adjustUploadedVideo($file_info, $config);
|
$file_info = $this->adjustUploadedVideo($file_info, $config);
|
||||||
}
|
}
|
||||||
|
|
@ -1123,7 +1119,7 @@ class fileController extends file
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust image rotation
|
// Adjust image rotation
|
||||||
if ($config->image_autorotate && in_array($image_info['type'], ['jpg', 'jpeg']) && function_exists('exif_read_data'))
|
if ($config->image_autorotate && $image_info['type'] === 'jpg' && function_exists('exif_read_data'))
|
||||||
{
|
{
|
||||||
$exif = @exif_read_data($file_info['tmp_name']);
|
$exif = @exif_read_data($file_info['tmp_name']);
|
||||||
if($exif && isset($exif['Orientation']))
|
if($exif && isset($exif['Orientation']))
|
||||||
|
|
|
||||||
|
|
@ -98,4 +98,5 @@ $lang->video_mp4_gif_time = 'Treat as GIF';
|
||||||
$lang->about_video_mp4_gif_time = 'treat silent MP4 videos with duration less than the set time as GIF images, and play with auto and loop.';
|
$lang->about_video_mp4_gif_time = 'treat silent MP4 videos with duration less than the set time as GIF images, and play with auto and loop.';
|
||||||
$lang->ffmpeg_path = 'FFmpeg path';
|
$lang->ffmpeg_path = 'FFmpeg path';
|
||||||
$lang->ffprobe_path = 'FFprobe path';
|
$lang->ffprobe_path = 'FFprobe path';
|
||||||
$lang->msg_cannot_use_ffmpeg = 'FFmpeg and FFprobe must can be executed by PHP';
|
$lang->msg_cannot_use_ffmpeg = 'FFmpeg and FFprobe must can be executed by PHP.';
|
||||||
|
$lang->msg_cannot_use_exif = 'PHP Exif module is required.';
|
||||||
|
|
@ -100,3 +100,4 @@ $lang->about_video_mp4_gif_time = '설정된 시간 이하의 길이를 가진
|
||||||
$lang->ffmpeg_path = 'FFmpeg 경로';
|
$lang->ffmpeg_path = 'FFmpeg 경로';
|
||||||
$lang->ffprobe_path = 'FFprobe 경로';
|
$lang->ffprobe_path = 'FFprobe 경로';
|
||||||
$lang->msg_cannot_use_ffmpeg = 'PHP에서 FFmpeg 및 FFprobe를 실행할 수 있어야 합니다.';
|
$lang->msg_cannot_use_ffmpeg = 'PHP에서 FFmpeg 및 FFprobe를 실행할 수 있어야 합니다.';
|
||||||
|
$lang->msg_cannot_use_exif = 'PHP Exif 모듈이 필요합니다.';
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,7 @@
|
||||||
{$lang->cmd_no}
|
{$lang->cmd_no}
|
||||||
</label>
|
</label>
|
||||||
<p class="x_help-block">{$lang->about_image_autorotate}</p>
|
<p class="x_help-block">{$lang->about_image_autorotate}</p>
|
||||||
|
<p class="x_text-info" cond="!function_exists('exif_read_data')">{$lang->msg_cannot_use_exif}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="x_control-group">
|
<div class="x_control-group">
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@
|
||||||
{$lang->cmd_no}
|
{$lang->cmd_no}
|
||||||
</label>
|
</label>
|
||||||
<p class="x_help-block">{$lang->about_image_autorotate}</p>
|
<p class="x_help-block">{$lang->about_image_autorotate}</p>
|
||||||
|
<p class="x_text-info" cond="!function_exists('exif_read_data')">{$lang->msg_cannot_use_exif}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="x_control-group">
|
<div class="x_control-group">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue