Merge pull request #1200 from conory/pr/gif

GIF → MP4 더 완벽하게...
This commit is contained in:
conory 2019-10-10 16:36:34 +09:00 committed by GitHub
commit ca8204a4c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 1446 additions and 869 deletions

View file

@ -97,7 +97,12 @@ class FilenameFilter
*/
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))
$images = 'gif|jpe?g|png|webp';
$audios = 'mp3|wav|ogg|flac|aac';
$videos = 'mp4|webm|ogv';
$legacy = 'avi|as[fx]|flv|m4[av]|midi?|mkv|moo?v|mpe?g|qt|r[am]m?|wm[av]';
if (preg_match(sprintf('/\.(?:%s|%s|%s|%s)$/i', $images, $audios, $videos, $legacy), $filename))
{
return true;
}

View file

@ -0,0 +1,84 @@
<?php
namespace Rhymix\Framework;
/**
* The image class.
*/
class Image
{
/**
* Check if a file is an image
*
* @param string $filename
* @return bool
*/
public static function isImage($filename)
{
return array_shift(explode('/', MIME::getContentType($filename))) === 'image';
}
/**
* Check if a file is an animated GIF.
*
* @param string $filename
* @return bool
*/
public static function isAnimatedGIF($filename)
{
if (MIME::getContentType($filename) !== 'image/gif')
{
return false;
}
if (!$fp = @fopen($filename, 'rb'))
{
return false;
}
$frames = 0;
while (!feof($fp) && $frames < 2)
{
$frames += preg_match_all('#\x00\x21\xF9\x04.{4}\x00[\x2C\x21]#s', fread($fp, 1024 * 16) ?: '');
if (!feof($fp))
{
fseek($fp, -9, SEEK_CUR);
}
}
fclose($fp);
return $frames > 1;
}
/**
* Get image information
*
* @param string $filename
* @return array|false
*/
public static function getImageInfo($filename)
{
if (!self::isImage($filename))
{
return false;
}
if (!$image_info = @getimagesize($filename))
{
return false;
}
$img_type = [
IMAGETYPE_GIF => 'gif',
IMAGETYPE_JPEG => 'jpg',
IMAGETYPE_JPEG2000 => 'jp2',
IMAGETYPE_PNG => 'png',
(defined('IMAGETYPE_WEBP') ? IMAGETYPE_WEBP : 18) => 'webp',
IMAGETYPE_BMP => 'bmp',
IMAGETYPE_PSD => 'psd',
IMAGETYPE_ICO => 'ico',
];
return [
'width' => $image_info[0],
'height' => $image_info[1],
'type' => $img_type[$image_info[2]],
'bits' => $image_info['bits'] ?? null,
'channels' => $image_info['channels'] ?? null,
];
}
}

View file

@ -7,6 +7,38 @@ namespace Rhymix\Framework;
*/
class MIME
{
/**
* Get the MIME type of a file, detected by its content.
*
* This method returns the MIME type of a file, or false on error.
*
* @param string $filename
* @return array|false
*/
public static function getContentType($filename)
{
$filename = rtrim($filename, '/\\');
if (Storage::exists($filename) && @is_file($filename) && @is_readable($filename))
{
if (function_exists('mime_content_type'))
{
return @mime_content_type($filename) ?: false;
}
elseif (($image = @getimagesize($filename)) && $image['mime'])
{
return $image['mime'];
}
else
{
return self::getTypeByFilename($filename);
}
}
else
{
return false;
}
}
/**
* Get the MIME type for the given extension.
*
@ -16,7 +48,7 @@ class MIME
public static function getTypeByExtension($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 +62,7 @@ class MIME
$extension = strrchr($filename, '.');
if ($extension === false) return self::$_default;
$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 +73,12 @@ class MIME
*/
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;
}
@ -59,96 +94,108 @@ class MIME
protected static $_types = array(
// Text-based document formats.
'html' => 'text/html',
'htm' => 'text/html',
'shtml' => 'text/html',
'txt' => 'text/plain',
'text' => 'text/plain',
'log' => 'text/plain',
'md' => 'text/markdown',
'markdown' => 'text/markdown',
'rtf' => 'text/rtf',
'xml' => 'text/xml',
'xsl' => 'text/xml',
'css' => 'text/css',
'csv' => 'text/csv',
'html' => ['text/html'],
'htm' => ['text/html'],
'shtml' => ['text/html'],
'txt' => ['text/plain'],
'text' => ['text/plain'],
'log' => ['text/plain'],
'md' => ['text/markdown'],
'markdown' => ['text/markdown'],
'rtf' => ['text/rtf'],
'xml' => ['text/xml'],
'xsl' => ['text/xml'],
'css' => ['text/css'],
'csv' => ['text/csv'],
// Binary document formats.
'doc' => 'application/msword',
'dot' => 'application/msword',
'xls' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'odt' => 'application/vnd.oasis.opendocument.text',
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
'odp' => 'application/vnd.oasis.opendocument.presentation',
'odg' => 'application/vnd.oasis.opendocument.graphics',
'odb' => 'application/vnd.oasis.opendocument.database',
'pdf' => 'application/pdf',
'doc' => ['application/msword'],
'dot' => ['application/msword'],
'xls' => ['application/vnd.ms-excel'],
'ppt' => ['application/vnd.ms-powerpoint'],
'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
'dotx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation'],
'odt' => ['application/vnd.oasis.opendocument.text'],
'ods' => ['application/vnd.oasis.opendocument.spreadsheet'],
'odp' => ['application/vnd.oasis.opendocument.presentation'],
'odg' => ['application/vnd.oasis.opendocument.graphics'],
'odb' => ['application/vnd.oasis.opendocument.database'],
'pdf' => ['application/pdf'],
'dvi' => ['application/x-dvi'],
// Images.
'bmp' => 'image/bmp',
'gif' => 'image/gif',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpe' => 'image/jpeg',
'png' => 'image/png',
'svg' => 'image/svg+xml',
'tiff' => 'image/tiff',
'tif' => 'image/tiff',
'ico' => 'image/vnd.microsoft.icon',
'bmp' => ['image/bmp'],
'gif' => ['image/gif'],
'jpg' => ['image/jpeg'],
'jpeg' => ['image/jpeg'],
'jpe' => ['image/jpeg'],
'png' => ['image/png'],
'webp' => ['image/webp'],
'svg' => ['image/svg+xml'],
'tiff' => ['image/tiff'],
'tif' => ['image/tiff'],
'ico' => ['image/x-icon'],
// Audio.
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mpga' => 'audio/mpeg',
'mp2' => 'audio/mpeg',
'mp3' => 'audio/mpeg',
'aif' => 'audio/x-aiff',
'aiff' => 'audio/x-aiff',
'ra' => 'audio/x-realaudio',
'wav' => 'audio/x-wav',
'ogg' => 'audio/ogg',
'mid' => ['audio/midi'],
'midi' => ['audio/midi'],
'mp3' => ['audio/mpeg'],
'mpga' => ['audio/mpeg'],
'mp2' => ['audio/mpeg'],
'ogg' => ['audio/ogg'],
'wav' => ['audio/wav', 'audio/x-wav'],
'flac' => ['audio/flac'],
'aac' => ['audio/aac', 'audio/aacp', 'audio/x-hx-aac-adts'],
'aif' => ['audio/x-aiff'],
'aiff' => ['audio/x-aiff'],
'ra' => ['audio/x-realaudio'],
'm4a' => ['audio/x-m4a'],
// Video.
'avi' => 'video/x-msvideo',
'flv' => 'video/x-flv',
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpe' => 'video/mpeg',
'mp4' => 'video/mpeg',
'qt' => 'video/quicktime',
'mov' => 'video/quicktime',
'movie' => 'video/x-sgi-movie',
'rv' => 'video/vnd.rn-realvideo',
'dvi' => 'application/x-dvi',
'avi' => ['video/x-msvideo'],
'flv' => ['video/x-flv'],
'mpg' => ['video/mpeg'],
'mpeg' => ['video/mpeg'],
'mpe' => ['video/mpeg'],
'mp4' => ['video/mp4', 'audio/mp4'],
'webm' => ['video/webm', 'audio/webm'],
'ogv' => ['video/ogg'],
'mov' => ['video/quicktime'],
'moov' => ['video/quicktime'],
'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.
'psd' => 'application/x-photoshop',
'swf' => 'application/x-shockwave-flash',
'ai' => 'application/postscript',
'eps' => 'application/postscript',
'ps' => 'application/postscript',
'mif' => 'application/vnd.mif',
'xul' => 'application/vnd.mozilla.xul+xml',
'psd' => ['application/x-photoshop'],
'swf' => ['application/x-shockwave-flash'],
'ai' => ['application/postscript'],
'eps' => ['application/postscript'],
'ps' => ['application/postscript'],
'mif' => ['application/vnd.mif'],
'xul' => ['application/vnd.mozilla.xul+xml'],
// Source code formats.
'phps' => 'application/x-httpd-php-source',
'js' => 'application/x-javascript',
'phps' => ['application/x-httpd-php-source'],
'js' => ['application/x-javascript'],
// Archives.
'bz2' => 'application/x-bzip',
'gz' => 'application/x-gzip',
'tar' => 'application/x-tar',
'tgz' => 'application/x-tar',
'gtar' => 'application/x-gtar',
'rar' => 'application/x-rar-compressed',
'zip' => 'application/x-zip',
'bz2' => ['application/x-bzip'],
'gz' => ['application/x-gzip'],
'tar' => ['application/x-tar'],
'tgz' => ['application/x-tar'],
'gtar' => ['application/x-gtar'],
'rar' => ['application/x-rar-compressed'],
'zip' => ['application/x-zip'],
// RFC822 email message.
'eml' => 'message/rfc822',
'eml' => ['message/rfc822'],
);
}

View file

@ -143,6 +143,18 @@ class Storage
return @self::exists($path) && @is_writable($path);
}
/**
* Check if the given path is executable.
*
* @param string $path
* @return bool
*/
public static function isExecutable($path)
{
$path = rtrim($path, '/\\');
return @self::exists($path) && @is_executable($path);
}
/**
* Get the size of a file.
*
@ -499,6 +511,51 @@ class Storage
return true;
}
/**
* Move uploaded $source to $destination.
*
* This method returns true on success and false on failure.
*
* @param string $source
* @param string $destination
* @param string $type
* @return bool
*/
public static function moveUploadedFile($source, $destination, $type = null)
{
if ($type === 'copy')
{
if (!self::copy($source, $destination))
{
if (!self::copy($source, $destination))
{
return false;
}
}
}
elseif ($type === 'move')
{
if (!self::move($source, $destination))
{
if (!self::move($source, $destination))
{
return false;
}
}
}
else
{
if (!@move_uploaded_file($source, $destination))
{
if (!@move_uploaded_file($source, $destination))
{
return false;
}
}
}
return true;
}
/**
* Delete a file.
*

View file

@ -691,4 +691,4 @@ function is_empty_html_content($str)
$str = strip_tags($str, '<img><audio><video><iframe><object><embed>');
$str = utf8_trim(utf8_clean(html_entity_decode($str, ENT_QUOTES, 'UTF-8')));
return $str === '';
}
}

View file

@ -112,7 +112,25 @@
width: 100%;
height: 100%;
}
.xefu-file-video {
position: absolute;
top: 50%;
left: 50%;
margin: -15px;
width: 30px;
height: 30px;
background: rgb(0,0,0,.5);
border-radius: 50%;
}
.xefu-file-video-play {
position: absolute;
top: 50%;
left: 50%;
margin: -8px -5px;
border-width: 8px 0 8px 13px;
border-style: solid;
border-color: transparent transparent transparent #fff;
}
.selected {
}

View file

@ -23,7 +23,8 @@
actSetCover : '.xefu-act-set-cover',
tmplXeUploaderFileitem : '<li class="xefu-file xe-clearfix" data-file-srl="{{file_srl}}"><span class="xefu-file-name">{{source_filename}}</span><span class="xefu-file-info"><span>{{disp_file_size}}</span><span><input type="checkbox" data-file-srl="{{file_srl}}"> Select</span></span></li>',
tmplXeUploaderFileitemImage: '<li class="xefu-file xefu-file-image {{#if cover_image}}xefu-is-cover-image{{/if}}" data-file-srl="{{file_srl}}"><strong class="xefu-file-name">{{source_filename}}</strong><span class="xefu-file-info"><span class="xefu-file-size">{{disp_file_size}}</span><span><img src="{{download_url}}" alt=""></span><span><input type="checkbox" data-file-srl="{{file_srl}}"></span><button class="xefu-act-set-cover" data-file-srl="{{file_srl}}" title="Be a cover image"><i class="xi-check-circle"></i></button></span></li>'
tmplXeUploaderFileitemImage: '<li class="xefu-file xefu-file-image {{#if cover_image}}xefu-is-cover-image{{/if}}" data-file-srl="{{file_srl}}"><strong class="xefu-file-name">{{source_filename}}</strong><span class="xefu-file-info"><span class="xefu-file-size">{{disp_file_size}}</span><span><img src="{{thumbnail_url}}" alt=""></span><span><input type="checkbox" data-file-srl="{{file_srl}}"></span><button class="xefu-act-set-cover" data-file-srl="{{file_srl}}" title="Be a cover image"><i class="xi-check-circle"></i></button></span></li>',
tmplXeUploaderFileitemVideo: '<li class="xefu-file xefu-file-image {{#if cover_image}}xefu-is-cover-image{{/if}}" data-file-srl="{{file_srl}}"><strong class="xefu-file-name">{{source_filename}}</strong><span class="xefu-file-info"><span class="xefu-file-size">{{disp_file_size}}</span><span><span class="xefu-file-video"><span class="xefu-file-video-play"></span></span><img src="{{thumbnail_url}}" alt=""></span><span><input type="checkbox" data-file-srl="{{file_srl}}"></span><button class="xefu-act-set-cover" data-file-srl="{{file_srl}}" title="Be a cover image"><i class="xi-check-circle"></i></button></span></li>'
};
var _elements = [
@ -150,21 +151,29 @@
}
if(result.error == 0) {
if(/\.(jpe?g|png|gif)$/i.test(result.source_filename)) {
if(/\.(gif|jpe?g|png|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 + '" />';
}
if(/\.(mp3)$/i.test(result.source_filename)) {
else if(/\.(mp3|wav|ogg|flac|aac)$/i.test(result.source_filename)) {
temp_code += '<audio src="' + result.download_url + '" controls data-file-srl="' + result.file_srl + '" />';
}
if(/\.(mp4|webm)$/i.test(result.source_filename)) {
temp_code += '<video src="' + result.download_url + '" controls data-file-srl="' + result.file_srl + '" />';
else if(/\.(mp4|webm|ogv)$/i.test(result.source_filename)) {
if(result.original_type === 'image/gif') {
temp_code += '<video src="' + result.download_url + '" autoplay loop muted data-file-srl="' + result.file_srl + '" />';
} else {
temp_code += '<video src="' + result.download_url + '" controls data-file-srl="' + result.file_srl + '" />';
}
}
if(temp_code !== '') {
if (opt.autoinsertImage === 'paragraph') {
temp_code = "<p>" + temp_code + "</p>\n";
}
if (opt.autoinsertImage !== 'none') {
_getCkeInstance(settings.formData.editor_sequence).insertHtml(temp_code, "unfiltered_html");
try {
_getCkeInstance(settings.formData.editor_sequence).insertHtml(temp_code, "unfiltered_html");
}
catch(err) {}
}
}
} else if (result.message) {
@ -317,24 +326,33 @@
if(!result) return;
var temp_code = '';
if(/\.(jpe?g|png|gif)$/i.test(result.source_filename)) {
if(/\.(gif|jpe?g|png|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 + '" />';
}
if(/\.(mp3)$/i.test(result.source_filename)) {
else if(/\.(mp3|wav|ogg|flac|aac)$/i.test(result.source_filename)) {
temp_code += '<audio src="' + result.download_url + '" controls data-file-srl="' + result.file_srl + '" />';
}
if(/\.(mp4|webm)$/i.test(result.source_filename)) {
temp_code += '<video src="' + result.download_url + '" controls data-file-srl="' + result.file_srl + '" />';
else if(/\.(mp4|webm|ogv)$/i.test(result.source_filename)) {
if(result.original_type === 'image/gif') {
temp_code += '<video src="' + result.download_url + '" autoplay loop muted data-file-srl="' + result.file_srl + '" />';
} else {
temp_code += '<video src="' + result.download_url + '" controls data-file-srl="' + result.file_srl + '" />';
}
}
if(temp_code !== '') {
if (data.settings.autoinsertImage === 'paragraph') {
temp_code = "<p>" + temp_code + "</p>\n";
}
}
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");
try {
_getCkeInstance(data.editorSequence).insertHtml(temp_code, "unfiltered_html");
}
catch(err) {}
});
},
/**
@ -402,8 +420,10 @@
var tmpl_fileitem = data.settings.tmplXeUploaderFileitem;
var tmpl_fileitem_image = data.settings.tmplXeUploaderFileitemImage;
var tmpl_fileitem_video = data.settings.tmplXeUploaderFileitemVideo;
var template_fileimte = Handlebars.compile(tmpl_fileitem);
var template_fileimte_image = Handlebars.compile(tmpl_fileitem_image);
var template_fileimte_video = Handlebars.compile(tmpl_fileitem_video);
var result_image = [];
var result = [];
@ -417,16 +437,24 @@
// 이미지와 그외 파일 분리
$.each(res.files, function (index, file) {
if(data.files[file.file_srl]) return;
data.files[file.file_srl] = file;
$container.data(data);
file.thumbnail_url = file.download_url;
file.source_filename = file.source_filename.replace("&amp;", "&");
if(/\.(jpe?g|png|gif)$/i.test(file.source_filename)) {
result_image.push(template_fileimte_image(file));
if(file.thumbnail_filename) {
file.thumbnail_url = file.thumbnail_filename;
if(/\.(mp4|webm|ogv)$/i.test(file.source_filename)) {
result_image.push(template_fileimte_video(file));
} else {
result_image.push(template_fileimte_image(file));
}
}
else
{
else if(/\.(gif|jpe?g|png|webp)$/i.test(file.source_filename)) {
result_image.push(template_fileimte_image(file));
} else {
result.push(template_fileimte(file));
}
});

View file

@ -353,3 +353,11 @@ $lang->license_agreement = 'License Agreement';
$lang->license = 'GPL v2';
$lang->cmd_license_agree = 'I understand the license, and I accept it.';
$lang->msg_must_accept_license_agreement = 'You must accept the license agreement in order to continue.';
$lang->image = 'Image';
$lang->audio = 'Audio';
$lang->video = 'Video';
$lang->text = 'Text';
$lang->image_quality = 'Quality';
$lang->standard = 'Standard';
$lang->unlimited = 'Unlimited';
$lang->admin = 'Admin';

View file

@ -357,3 +357,11 @@ $lang->license_agreement = '사용권 동의';
$lang->license = 'GPL v2';
$lang->cmd_license_agree = '사용권에 대해 이해했으며, 이에 동의합니다.';
$lang->msg_must_accept_license_agreement = '사용권에 동의해야 설치를 진행할 수 있습니다.';
$lang->image = '이미지';
$lang->audio = '오디오';
$lang->video = '동영상';
$lang->text = '텍스트';
$lang->image_quality = '화질';
$lang->standard = '표준';
$lang->unlimited = '제한 없음';
$lang->admin = '관리자';

View file

@ -270,7 +270,6 @@ $lang->thumbnail_target = 'Extract Thumbnail From';
$lang->thumbnail_target_all = 'All images';
$lang->thumbnail_target_attachment = 'Attached images only';
$lang->thumbnail_type = 'Thumbnail Type';
$lang->thumbnail_quality = 'Quality';
$lang->input_header_script = 'Header Script';
$lang->detail_input_header_script = 'Content added here will be printed at the top of every page, except the admin module.';
$lang->input_footer_script = 'Footer Script';

View file

@ -273,7 +273,6 @@ $lang->detail_input_footer_script = '모든 페이지의 최하단에 코드를
$lang->thumbnail_crop = '크기에 맞추어 잘라내기';
$lang->thumbnail_ratio = '비율 유지 (여백이 생길 수 있음)';
$lang->thumbnail_none = '썸네일 생성하지 않음';
$lang->thumbnail_quality = '화질';
$lang->admin_ip_allow = '관리자 로그인 허용 IP';
$lang->admin_ip_deny = '관리자 로그인 금지 IP';
$lang->local_ip_address = '로컬 IP 주소';

View file

@ -136,9 +136,9 @@
<input type="radio" name="thumbnail_type" id="thumbnail_type_ratio" value="ratio" checked="checked"|cond="$thumbnail_type == 'ratio'" />
{$lang->thumbnail_ratio}
</label>
<select name="thumbnail_quality" id="thumbnail_quality" style="width:100px;min-width:100px">
<select name="thumbnail_quality" id="thumbnail_quality" style="min-width:120px">
<!--@for($q = 50; $q <= 100; $q += 5)-->
<option value="{$q}" selected="selected"|cond="$thumbnail_quality == $q">{$lang->thumbnail_quality} {$q}%</option>
<option value="{$q}" selected="selected"|cond="$thumbnail_quality === $q">{$lang->image_quality} {$q}%<!--@if($q === 75)--> ({$lang->standard})<!--@end--></option>
<!--@endfor-->
</select>
</div>

View file

@ -1126,30 +1126,34 @@ class documentItem extends BaseObject
// Find an image file among attached files if exists
if($this->hasUploadedFiles())
{
$file_list = $this->getUploadedFiles();
$first_image = null;
foreach($file_list as $file)
foreach($this->getUploadedFiles() as $file)
{
if($file->direct_download !== 'Y') continue;
if($file->cover_image === 'Y' && file_exists($file->uploaded_filename))
if($file->thumbnail_filename && file_exists($file->thumbnail_filename))
{
$file->uploaded_filename = $file->thumbnail_filename;
}
else
{
if($file->direct_download !== 'Y' || !preg_match('/\.(jpe?g|png|gif|webp|bmp)$/i', $file->source_filename))
{
continue;
}
if(!file_exists($file->uploaded_filename))
{
continue;
}
}
if($file->cover_image === 'Y')
{
$source_file = $file->uploaded_filename;
break;
}
if($first_image) continue;
if(preg_match("/\.(jpe?g|png|gif|bmp)$/i", $file->source_filename))
if(!$first_image)
{
if(file_exists($file->uploaded_filename))
{
$first_image = $file->uploaded_filename;
}
$first_image = $file->uploaded_filename;
}
}
if(!$source_file && $first_image)
{
$source_file = $first_image;

View file

@ -47,11 +47,9 @@ class fileAdminController extends file
$oFileController->deleteFile($file_srl);
}
$this->setMessage( sprintf(lang('msg_checked_file_is_deleted'), $file_count) );
$returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : getNotEncodedUrl('', 'module', 'admin', 'act', 'dispFileAdminList');
$this->setRedirectUrl($returnUrl);
$this->setMessage(sprintf(lang('msg_checked_file_is_deleted'), $file_count));
$this->setRedirectUrl(Context::get('success_return_url') ?: getNotEncodedUrl('', 'module', 'admin', 'act', 'dispFileAdminList'));
}
/**
@ -66,19 +64,21 @@ class fileAdminController extends file
$config->allowed_filesize = Context::get('allowed_filesize');
$config->allowed_attach_size = Context::get('allowed_attach_size');
$config->allowed_filetypes = Context::get('allowed_filetypes');
$config->max_image_width = intval(Context::get('max_image_width')) ?: '';
$config->max_image_height = intval(Context::get('max_image_height')) ?: '';
$config->max_image_size_action = Context::get('max_image_size_action') ?: '';
$config->max_image_size_quality = max(50, min(100, intval(Context::get('max_image_size_quality'))));
$config->max_image_size_admin = Context::get('max_image_size_admin') === 'Y' ? 'Y' : 'N';
$config->image_autoconv['bmp2jpg'] = Context::get('image_autoconv_bmp2jpg') === 'Y' ? true : false;
$config->image_autoconv['png2jpg'] = Context::get('image_autoconv_png2jpg') === 'Y' ? true : false;
$config->image_autoconv['webp2jpg'] = Context::get('image_autoconv_webp2jpg') === 'Y' ? true : false;
$config->image_autoconv['gif2mp4'] = Context::get('image_autoconv_gif2mp4') === 'Y' ? true : false;
$config->image_autoconv_quality = max(50, min(100, intval(Context::get('image_autoconv_quality'))));
$config->ffmpeg_command = escape(utf8_trim(Context::get('ffmpeg_command'))) ?: '/usr/bin/ffmpeg';
$config->max_image_width = intval(Context::get('max_image_width')) ?: '';
$config->max_image_height = intval(Context::get('max_image_height')) ?: '';
$config->max_image_size_action = Context::get('max_image_size_action') ?: '';
$config->max_image_size_admin = Context::get('max_image_size_admin') === 'Y' ? 'Y' : 'N';
$config->image_quality_adjustment = max(50, min(100, intval(Context::get('image_quality_adjustment'))));
$config->image_autorotate = Context::get('image_autorotate') === 'Y' ? true : false;
$config->image_autorotate_quality = max(50, min(100, intval(Context::get('image_autorotate_quality'))));
$config->image_remove_exif_data = Context::get('image_remove_exif_data') === 'Y' ? true : false;
$config->video_thumbnail = Context::get('video_thumbnail') === 'Y' ? true : false;
$config->video_mp4_gif_time = intval(Context::get('video_mp4_gif_time'));
$config->ffmpeg_command = escape(utf8_trim(Context::get('ffmpeg_command'))) ?: '/usr/bin/ffmpeg';
$config->ffprobe_command = escape(utf8_trim(Context::get('ffprobe_command'))) ?: '/usr/bin/ffprobe';
// Check maximum file size
if (PHP_INT_SIZE < 8)
@ -105,10 +105,8 @@ class fileAdminController extends file
}
// Save and redirect
$oModuleController = getController('module');
$output = $oModuleController->insertModuleConfig('file',$config);
$returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : getNotEncodedUrl('', 'module', 'admin', 'act', 'dispFileAdminUploadConfig');
$output = getController('module')->insertModuleConfig('file', $config);
$returnUrl = Context::get('success_return_url') ?: getNotEncodedUrl('', 'module', 'admin', 'act', 'dispFileAdminUploadConfig');
return $this->setRedirectUrl($returnUrl, $output);
}
@ -127,14 +125,8 @@ class fileAdminController extends file
$config->inline_download_format = array_map('utf8_trim', Context::get('inline_download_format'));
// Save and redirect
$oModuleController = getController('module');
$output = $oModuleController->insertModuleConfig('file',$config);
if(!$output->toBool())
{
return $output;
}
$returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : getNotEncodedUrl('', 'module', 'admin', 'act', 'dispFileAdminDownloadConfig');
$output = getController('module')->insertModuleConfig('file', $config);
$returnUrl = Context::get('success_return_url') ?: getNotEncodedUrl('', 'module', 'admin', 'act', 'dispFileAdminDownloadConfig');
return $this->setRedirectUrl($returnUrl, $output);
}
@ -150,14 +142,8 @@ class fileAdminController extends file
$config->save_changelog = Context::get('save_changelog') === 'Y' ? 'Y' : 'N';
// Save and redirect
$oModuleController = getController('module');
$output = $oModuleController->insertModuleConfig('file',$config);
if(!$output->toBool())
{
return $output;
}
$returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : getNotEncodedUrl('', 'module', 'admin', 'act', 'dispFileAdminOtherConfig');
$output = getController('module')->insertModuleConfig('file', $config);
$returnUrl = Context::get('success_return_url') ?: getNotEncodedUrl('', 'module', 'admin', 'act', 'dispFileAdminOtherConfig');
return $this->setRedirectUrl($returnUrl, $output);
}
@ -168,84 +154,84 @@ class fileAdminController extends file
*/
function procFileAdminInsertModuleConfig()
{
// Get variables
$module_srl = Context::get('target_module_srl');
// In order to configure multiple modules at once
if(preg_match('/^([0-9,]+)$/',$module_srl)) $module_srl = explode(',',$module_srl);
else $module_srl = array($module_srl);
$file_config = new stdClass;
$file_config->allowed_filesize = Context::get('allowed_filesize');
$file_config->allowed_attach_size = Context::get('allowed_attach_size');
$file_config->allowed_filetypes = Context::get('allowed_filetypes');
$file_config->max_image_width = intval(Context::get('max_image_width')) ?: '';
$file_config->max_image_height = intval(Context::get('max_image_height')) ?: '';
$file_config->max_image_size_action = Context::get('max_image_size_action') ?: '';
$file_config->max_image_size_quality = max(50, min(100, intval(Context::get('max_image_size_quality'))));
$file_config->max_image_size_admin = Context::get('max_image_size_admin') === 'Y' ? 'Y' : 'N';
$file_config->image_autoconv['bmp2jpg'] = Context::get('image_autoconv_bmp2jpg') === 'Y' ? true : false;
$file_config->image_autoconv['png2jpg'] = Context::get('image_autoconv_png2jpg') === 'Y' ? true : false;
$file_config->image_autoconv['webp2jpg'] = Context::get('image_autoconv_webp2jpg') === 'Y' ? true : false;
$file_config->image_autoconv['gif2mp4'] = Context::get('image_autoconv_gif2mp4') === 'Y' ? true : false;
$file_config->image_autoconv_quality = max(50, min(100, intval(Context::get('image_autoconv_quality'))));
$file_config->ffmpeg_command = escape(utf8_trim(Context::get('ffmpeg_command'))) ?: '/usr/bin/ffmpeg';
$file_config->image_autorotate = Context::get('image_autorotate') === 'Y' ? true : false;
$file_config->image_autorotate_quality = max(50, min(100, intval(Context::get('image_autorotate_quality'))));
// Check maximum file size
if (PHP_INT_SIZE < 8)
$config = new stdClass;
// Default
if(!Context::get('use_default_file_config'))
{
if ($file_config->allowed_filesize > 2047 || $file_config->allowed_attach_size > 2047)
$config->use_default_file_config = 'N';
$config->allowed_filesize = Context::get('allowed_filesize');
$config->allowed_attach_size = Context::get('allowed_attach_size');
$config->allowed_filetypes = Context::get('allowed_filetypes');
// Check maximum file size
if (PHP_INT_SIZE < 8)
{
throw new Rhymix\Framework\Exception('msg_32bit_max_2047mb');
if ($config->allowed_filesize > 2047 || $config->allowed_attach_size > 2047)
{
throw new Rhymix\Framework\Exception('msg_32bit_max_2047mb');
}
}
// Simplify allowed_filetypes
$config->allowed_extensions = strtr(strtolower(trim($config->allowed_filetypes)), array('*.' => '', ';' => ','));
if ($config->allowed_extensions)
{
$config->allowed_extensions = array_map('trim', explode(',', $config->allowed_filetypes));
$config->allowed_filetypes = implode(';', array_map(function($ext) {
return '*.' . $ext;
}, $config->allowed_extensions));
}
else
{
$config->allowed_extensions = array();
$config->allowed_filetypes = '*.*';
}
}
// Simplify allowed_filetypes
$file_config->allowed_extensions = strtr(strtolower(trim($file_config->allowed_filetypes)), array('*.' => '', ';' => ','));
if ($file_config->allowed_extensions)
// Image
if(!Context::get('use_image_default_file_config'))
{
$file_config->allowed_extensions = array_map('trim', explode(',', $file_config->allowed_filetypes));
$file_config->allowed_filetypes = implode(';', array_map(function($ext) {
return '*.' . $ext;
}, $file_config->allowed_extensions));
}
else
{
$file_config->allowed_extensions = array();
$file_config->allowed_filetypes = '*.*';
$config->use_image_default_file_config = 'N';
$config->image_autoconv['bmp2jpg'] = Context::get('image_autoconv_bmp2jpg') === 'Y' ? true : false;
$config->image_autoconv['png2jpg'] = Context::get('image_autoconv_png2jpg') === 'Y' ? true : false;
$config->image_autoconv['webp2jpg'] = Context::get('image_autoconv_webp2jpg') === 'Y' ? true : false;
$config->image_autoconv['gif2mp4'] = Context::get('image_autoconv_gif2mp4') === 'Y' ? true : false;
$config->max_image_width = intval(Context::get('max_image_width')) ?: '';
$config->max_image_height = intval(Context::get('max_image_height')) ?: '';
$config->max_image_size_action = Context::get('max_image_size_action') ?: '';
$config->max_image_size_admin = Context::get('max_image_size_admin') === 'Y' ? 'Y' : 'N';
$config->image_quality_adjustment = max(50, min(100, intval(Context::get('image_quality_adjustment'))));
$config->image_autorotate = Context::get('image_autorotate') === 'Y' ? true : false;
$config->image_remove_exif_data = Context::get('image_remove_exif_data') === 'Y' ? true : false;
}
// Use default config
if(Context::get('use_default_file_config') === 'Y')
// Video
if(!Context::get('use_video_default_file_config'))
{
$file_config = new stdClass;
$file_config->use_default_file_config = true;
$config->use_video_default_file_config = 'N';
$config->video_thumbnail = Context::get('video_thumbnail') === 'Y' ? true : false;
$config->video_mp4_gif_time = intval(Context::get('video_mp4_gif_time'));
}
// Check download grant
// Set download groups
$download_grant = Context::get('download_grant');
if(!is_array($download_grant))
{
$file_config->download_grant = explode('|@|',$download_grant);
}
else
{
$file_config->download_grant = array_values($download_grant);
}
$config->download_grant = is_array($download_grant) ? array_values($download_grant) : array($download_grant);
// Update
$oModuleController = getController('module');
for($i=0;$i<count($module_srl);$i++)
foreach(explode(',', Context::get('target_module_srl')) as $module_srl)
{
$srl = trim($module_srl[$i]);
if(!$srl) continue;
$oModuleController->insertModulePartConfig('file',$srl,$file_config);
$output = $oModuleController->insertModulePartConfig('file', trim($module_srl), $config);
if(!$output->toBool())
{
return $output;
}
}
$this->setError(-1);
$this->setMessage('success_updated', 'info');
$returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : getNotEncodedUrl('', 'module', 'admin', 'act', 'dispBoardAdminContent');
$this->setRedirectUrl($returnUrl);
$this->setRedirectUrl(Context::get('success_return_url') ?: getNotEncodedUrl('', 'module', 'admin', 'act', 'dispBoardAdminContent'));
}
/**

View file

@ -218,7 +218,8 @@ class fileAdminView extends file
{
$oFileModel = getModel('file');
$config = $oFileModel->getFileConfig();
Context::set('config',$config);
Context::set('config', $config);
Context::set('is_ffmpeg', function_exists('exec') && Rhymix\Framework\Storage::isExecutable($config->ffmpeg_command) && Rhymix\Framework\Storage::isExecutable($config->ffprobe_command));
// Set a template file
$this->setTemplatePath($this->module_path.'tpl');

View file

@ -85,7 +85,30 @@ class file extends ModuleObject
{
return true;
}
if(!$oDB->isColumnExists('files', 'thumbnail_filename'))
{
return true;
}
if(!$oDB->isColumnExists('files', 'mime_type'))
{
return true;
}
if(!$oDB->isColumnExists('files', 'original_type'))
{
return true;
}
if(!$oDB->isColumnExists('files', 'width'))
{
return true;
}
if(!$oDB->isColumnExists('files', 'height'))
{
return true;
}
if(!$oDB->isColumnExists('files', 'duration'))
{
return true;
}
return false;
}
@ -161,6 +184,31 @@ class file extends ModuleObject
{
$oModuleController->insertTrigger('comment.copyCommentByDocument', 'file', 'controller', 'triggerAddCopyCommentByDocument', 'add');
}
if(!$oDB->isColumnExists('files', 'thumbnail_filename'))
{
$oDB->addColumn('files', 'thumbnail_filename', 'varchar', '250', null, false, 'uploaded_filename');
}
if(!$oDB->isColumnExists('files', 'mime_type'))
{
$oDB->addColumn('files', 'mime_type', 'varchar', '60', '', true, 'file_size');
$oDB->addIndex('files', 'idx_mime_type', 'mime_type');
}
if(!$oDB->isColumnExists('files', 'original_type'))
{
$oDB->addColumn('files', 'original_type', 'varchar', '60', null, false, 'mime_type');
}
if(!$oDB->isColumnExists('files', 'width'))
{
$oDB->addColumn('files', 'width', 'number', '11', null, false, 'original_type');
}
if(!$oDB->isColumnExists('files', 'height'))
{
$oDB->addColumn('files', 'height', 'number', '11', null, false, 'width');
}
if(!$oDB->isColumnExists('files', 'duration'))
{
$oDB->addColumn('files', 'duration', 'number', '11', null, false, 'height');
}
}
/**

View file

@ -147,6 +147,8 @@ class fileController extends file
$this->add('direct_download', $output->get('direct_download'));
$this->add('source_filename', $output->get('source_filename'));
$this->add('upload_target_srl', $output->get('upload_target_srl'));
$this->add('thumbnail_filename', $output->get('thumbnail_filename'));
$this->add('original_type', $output->get('original_type'));
if ($output->get('direct_download') === 'Y')
{
$this->add('download_url', $oFileModel->getDirectFileUrl($output->get('uploaded_filename')));
@ -184,7 +186,7 @@ class fileController extends file
$oFileModel = getModel('file');
$logged_info = Context::get('logged_info');
$file_info = $oFileModel->getFile($file_srl);
if($file_info->file_srl == $file_srl && $oFileModel->getFileGrant($file_info, $logged_info)->is_deletable)
if($file_info->file_srl == $file_srl && $oFileModel->isDeletable($file_info))
{
$this->deleteFile($file_srl);
}
@ -289,18 +291,12 @@ class fileController extends file
$sid = Context::get('sid');
$logged_info = Context::get('logged_info');
// Get file information from the DB
$columnList = array('file_srl', 'sid', 'isvalid', 'source_filename', 'module_srl', 'uploaded_filename', 'file_size', 'member_srl', 'upload_target_srl', 'upload_target_type');
$file_obj = $oFileModel->getFile($file_srl, $columnList);
$file_obj = $oFileModel->getFile($file_srl);
// If the requested file information is incorrect, an error that file cannot be found appears
if($file_obj->file_srl != $file_srl || $file_obj->sid !== $sid)
{
throw new Rhymix\Framework\Exceptions\TargetNotFound('msg_file_not_found');
}
// Notify that file download is not allowed when standing-by(Only a top-administrator is permitted)
if($logged_info->is_admin != 'Y' && $file_obj->isvalid != 'Y')
{
throw new Rhymix\Framework\Exceptions\NotPermitted('msg_not_permitted_download');
}
// File name
$filename = $file_obj->source_filename;
$file_module_config = $oFileModel->getFileModuleConfig($file_obj->module_srl);
@ -354,52 +350,13 @@ class fileController extends file
throw new Rhymix\Framework\Exceptions\NotPermitted('msg_not_allowed_outlink');
}
}
// Check if a permission for file download is granted
$downloadGrantCount = 0;
if(is_array($file_module_config->download_grant))
// Check if the file is downloadable
if(!$oFileModel->isDownloadable($file_obj))
{
foreach($file_module_config->download_grant AS $value)
if($value) $downloadGrantCount++;
throw new Rhymix\Framework\Exceptions\NotPermitted('msg_not_permitted_download');
}
if(is_array($file_module_config->download_grant) && $downloadGrantCount>0)
{
if(!Context::get('is_logged'))
{
throw new Rhymix\Framework\Exceptions\NotPermitted('msg_not_permitted_download');
}
$logged_info = Context::get('logged_info');
if($logged_info->is_admin != 'Y')
{
$oModuleModel =& getModel('module');
$columnList = array('module_srl', 'site_srl');
$module_info = $oModuleModel->getModuleInfoByModuleSrl($file_obj->module_srl, $columnList);
if(!$oModuleModel->isSiteAdmin($logged_info, $module_info->site_srl))
{
$oMemberModel =& getModel('member');
$member_groups = $oMemberModel->getMemberGroups($logged_info->member_srl, $module_info->site_srl);
$is_permitted = false;
for($i=0;$i<count($file_module_config->download_grant);$i++)
{
$group_srl = $file_module_config->download_grant[$i];
if($member_groups[$group_srl])
{
$is_permitted = true;
break;
}
}
if(!$is_permitted)
{
throw new Rhymix\Framework\Exceptions\NotPermitted('msg_not_permitted_download');
}
}
}
}
// Call a trigger (before)
$output = ModuleHandler::triggerCall('file.downloadFile', 'before', $file_obj);
if(!$output->toBool())
@ -610,11 +567,7 @@ class fileController extends file
$file_info = $output->data;
if(!$file_info) continue;
$file_grant = $oFileModel->getFileGrant($file_info, $logged_info);
if(!$file_grant->is_deletable) continue;
if(!$oFileModel->isDeletable($file_info)) continue;
if($upload_target_srl && $file_srl) $output = $this->deleteFile($file_srl);
}
}
@ -864,50 +817,66 @@ class fileController extends file
$trigger_obj->upload_target_srl = $upload_target_srl;
$output = ModuleHandler::triggerCall('file.insertFile', 'before', $trigger_obj);
if(!$output->toBool()) return $output;
// A workaround for Firefox upload bug
if(preg_match('/^=\?UTF-8\?B\?(.+)\?=$/i', $file_info['name'], $match))
{
$file_info['name'] = base64_decode(strtr($match[1], ':', '/'));
}
// Sanitize filename
$file_info['name'] = Rhymix\Framework\Filters\FilenameFilter::clean($file_info['name']);
// Get extension
$extension = explode('.', $file_info['name']) ?: array('');
$extension = strtolower(array_pop($extension));
// Add extra fields to file info array
$file_info['extension'] = $extension;
$file_info['resized'] = false;
// Set base information
$file_info['name'] = Rhymix\Framework\Filters\FilenameFilter::clean($file_info['name']);
$file_info['type'] = $file_info['original_type'] = Rhymix\Framework\MIME::getContentType($file_info['tmp_name']);
$file_info['extension'] = $file_info['original_extension'] = strtolower(array_pop(explode('.', $file_info['name'])));
$file_info['width'] = null;
$file_info['height'] = null;
$file_info['duration'] = null;
$file_info['thumbnail'] = null;
$file_info['converted'] = false;
// Correct extension
if($file_info['extension'])
{
$type_by_extension = Rhymix\Framework\MIME::getTypeByExtension($file_info['extension']);
if(!in_array($type_by_extension, [$file_info['type'], 'application/octet-stream']))
{
$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))
{
$file_info['extension'] = $extension_by_type;
}
}
}
// Get file module configuration
$oFileModel = getModel('file');
$config = $oFileModel->getFileConfig($module_srl);
// Check file type
// Check file extension
if(!$manual_insert && !$this->user->isAdmin())
{
// Check file type
if(isset($config->allowed_extensions) && count($config->allowed_extensions))
if($config->allowed_extensions && !in_array($file_info['extension'], $config->allowed_extensions))
{
if(!in_array($extension, $config->allowed_extensions))
{
throw new Rhymix\Framework\Exception('msg_not_allowed_filetype');
}
throw new Rhymix\Framework\Exception('msg_not_allowed_filetype');
}
}
// Check image type and size
// Adjust
if(!$manual_insert)
{
if(in_array($extension, array('gif', 'jpg', 'jpeg', 'png', 'webp', 'bmp')))
// image
if(in_array($file_info['extension'], ['gif', 'jpg', 'jpeg', 'png', 'webp', 'bmp']))
{
$file_info = $this->checkUploadedImage($file_info, $config);
$file_info = $this->adjustUploadedImage($file_info, $config);
}
// video
if(in_array($file_info['extension'], ['mp4', 'webm', 'ogv']))
{
$file_info = $this->adjustUploadedVideo($file_info, $config);
}
}
// Check file size
if(!$manual_insert && !$this->user->isAdmin())
{
@ -928,102 +897,98 @@ class fileController extends file
}
}
// Get file_srl
$file_srl = getNextSequence();
$file_regdate = date('YmdHis');
// Set upload path by checking if the attachement is an image or other kinds of file
if(Rhymix\Framework\Filters\FilenameFilter::isDirectDownload($file_info['name']))
$args = new stdClass;
$args->file_srl = getNextSequence();
$args->regdate = date('YmdHis');
$args->module_srl = $module_srl;
$args->upload_target_srl = $upload_target_srl;
$args->download_count = $download_count;
$args->member_srl = Rhymix\Framework\Session::getMemberSrl();
$args->source_filename = $file_info['name'];
$args->sid = Rhymix\Framework\Security::getRandom(32, 'hex');
$args->mime_type = $file_info['type'];
$args->width = $file_info['width'];
$args->height = $file_info['height'];
$args->duration = $file_info['duration'];
// Set original type if file type is changed
$args->original_type = null;
if($args->mime_type !== $file_info['original_type'])
{
$path = $this->getStoragePath('images', $file_srl, $module_srl, $upload_target_srl, $file_regdate);
// change to random file name. because window php bug. window php is not recognize unicode character file name - by cherryfilter
$ext = substr(strrchr($file_info['name'],'.'),1);
$filename = $path . Rhymix\Framework\Security::getRandom(32, 'hex') . '.' . $ext;
while(file_exists($filename))
{
$filename = $path . Rhymix\Framework\Security::getRandom(32, 'hex') . '.' . $ext;
}
$direct_download = 'Y';
$args->original_type = $file_info['original_type'];
}
// Add changed extension
if($file_info['extension'] && $file_info['extension'] !== $file_info['original_extension'])
{
$args->source_filename .= '.' . $file_info['extension'];
}
// Set storage path by checking if the attachement is an image or other kinds of file
if($direct = Rhymix\Framework\Filters\FilenameFilter::isDirectDownload($args->source_filename))
{
$storage_path = $this->getStoragePath('images', $args->file_srl, $module_srl, $upload_target_srl, $args->regdate);
}
else
{
$path = $this->getStoragePath('binaries', $file_srl, $module_srl, $upload_target_srl, $file_regdate);
$filename = $path . Rhymix\Framework\Security::getRandom(32, 'hex');
while(file_exists($filename))
{
$filename = $path . Rhymix\Framework\Security::getRandom(32, 'hex');
}
$direct_download = 'N';
$storage_path = $this->getStoragePath('binaries', $args->file_srl, $module_srl, $upload_target_srl, $args->regdate);
}
$args->direct_download = $direct ? 'Y' : 'N';
// Create a directory
if(!Rhymix\Framework\Storage::isDirectory($path) && !Rhymix\Framework\Storage::createDirectory($path))
if(!Rhymix\Framework\Storage::isDirectory($storage_path) && !Rhymix\Framework\Storage::createDirectory($storage_path))
{
throw new Rhymix\Framework\Exception('msg_not_permitted_create');
}
// Move the file
if($manual_insert && !$file_info['converted'])
// Set move type and uploaded filename
$move_type = $manual_insert ? 'copy' : '';
if($file_info['converted'] || starts_with(RX_BASEDIR . 'files/attach/chunks/', $file_info['tmp_name']))
{
@copy($file_info['tmp_name'], $filename);
if(!file_exists($filename))
{
@copy($file_info['tmp_name'], $filename);
if(!file_exists($filename))
{
throw new Rhymix\Framework\Exception('msg_file_upload_error');
}
}
$move_type = 'move';
}
elseif(starts_with(RX_BASEDIR . 'files/attach/chunks/', $file_info['tmp_name']) || $file_info['converted'])
$extension = ($direct && $file_info['extension']) ? ('.' . $file_info['extension']) : '';
$uploaded_filename = $storage_path . Rhymix\Framework\Security::getRandom(32, 'hex') . $extension;
while(file_exists($uploaded_filename))
{
if (!Rhymix\Framework\Storage::move($file_info['tmp_name'], $filename))
{
if (!Rhymix\Framework\Storage::move($file_info['tmp_name'], $filename))
{
throw new Rhymix\Framework\Exception('msg_file_upload_error');
}
}
}
else
{
if(!@move_uploaded_file($file_info['tmp_name'], $filename))
{
if(!@move_uploaded_file($file_info['tmp_name'], $filename))
{
throw new Rhymix\Framework\Exception('msg_file_upload_error');
}
}
$uploaded_filename = $storage_path . Rhymix\Framework\Security::getRandom(32, 'hex') . $extension;
}
// Get member information
$oMemberModel = getModel('member');
$member_srl = $oMemberModel->getLoggedMemberSrl();
// List file information
$args = new stdClass;
$args->file_srl = $file_srl;
$args->upload_target_srl = $upload_target_srl;
$args->module_srl = $module_srl;
$args->direct_download = $direct_download;
$args->source_filename = $file_info['name'];
$args->uploaded_filename = './' . substr($filename, strlen(RX_BASEDIR));
$args->download_count = $download_count;
$args->file_size = @filesize($filename);
$args->comment = NULL;
$args->member_srl = $member_srl;
$args->regdate = $file_regdate;
$args->sid = Rhymix\Framework\Security::getRandom(32, 'hex');
// Move the uploaded file
if(!Rhymix\Framework\Storage::moveUploadedFile($file_info['tmp_name'], $uploaded_filename, $move_type))
{
throw new Rhymix\Framework\Exception('msg_file_upload_error');
}
$args->uploaded_filename = './' . substr($uploaded_filename, strlen(RX_BASEDIR));
$args->file_size = @filesize($uploaded_filename);
// Move the generated thumbnail image
if($file_info['thumbnail'])
{
$thumbnail_filename = $storage_path . Rhymix\Framework\Security::getRandom(32, 'hex') . '.jpg';
while(file_exists($thumbnail_filename))
{
$thumbnail_filename = $storage_path . Rhymix\Framework\Security::getRandom(32, 'hex') . '.jpg';
}
if(Rhymix\Framework\Storage::moveUploadedFile($file_info['thumbnail'], $thumbnail_filename, 'move'))
{
$args->thumbnail_filename = './' . substr($thumbnail_filename, strlen(RX_BASEDIR));
}
}
$oDB = DB::getInstance();
$oDB->begin();
// Insert file information
$output = executeQuery('file.insertFile', $args);
if(!$output->toBool())
{
$oDB->rollback();
$this->deleteFile($args);
return $output;
}
// Insert changelog
if($config->save_changelog === 'Y')
{
$clargs = new stdClass;
@ -1036,6 +1001,7 @@ class fileController extends file
if(!$output->toBool())
{
$oDB->rollback();
$this->deleteFile($args);
return $output;
}
}
@ -1044,9 +1010,9 @@ class fileController extends file
// Call a trigger (after)
ModuleHandler::triggerCall('file.insertFile', 'after', $args);
$_SESSION['__XE_UPLOADING_FILES_INFO__'][$args->file_srl] = true;
$output->add('file_srl', $args->file_srl);
$output->add('file_size', $args->file_size);
$output->add('sid', $args->sid);
@ -1054,46 +1020,58 @@ class fileController extends file
$output->add('source_filename', $args->source_filename);
$output->add('upload_target_srl', $upload_target_srl);
$output->add('uploaded_filename', $args->uploaded_filename);
$output->add('thumbnail_filename', $args->thumbnail_filename);
$output->add('original_type', $args->original_type);
return $output;
}
/**
* Check uploaded image
* Adjust uploaded image
*/
public function checkUploadedImage($file_info, $config)
public function adjustUploadedImage($file_info, $config)
{
// Get image information
$image_info = @getimagesize($file_info['tmp_name']);
if (!$image_info)
if (!$image_info = Rhymix\Framework\Image::getImageInfo($file_info['tmp_name']))
{
return $file_info;
}
$image_width = $image_info[0];
$image_height = $image_info[1];
$image_type = $image_info[2];
$convert = false;
// Set image size
$file_info['width'] = $image_info['width'];
$file_info['height'] = $image_info['height'];
// Check image type
if($config->image_autoconv['bmp2jpg'] && function_exists('imagebmp') && $image_type === 6)
// Set base information
$force = false;
$adjusted = [
'width' => $image_info['width'],
'height' => $image_info['height'],
'type' => $image_info['type'],
'quality' => $config->image_quality_adjustment,
'rotate' => 0,
];
$is_animated = Rhymix\Framework\Image::isAnimatedGIF($file_info['tmp_name']);
// Adjust image type
if ($config->image_autoconv['gif2mp4'] && $is_animated && function_exists('exec') && Rhymix\Framework\Storage::isExecutable($config->ffmpeg_command))
{
$convert = array($image_width, $image_height, 'jpg', $config->image_autoconv_quality ?: 75, 0);
$adjusted['type'] = 'mp4';
}
if($config->image_autoconv['png2jpg'] && function_exists('imagepng') && $image_type === 3)
elseif ($config->image_autoconv['png2jpg'] && $image_info['type'] === 'png' && function_exists('imagepng'))
{
$convert = array($image_width, $image_height, 'jpg', $config->image_autoconv_quality ?: 75, 0);
$adjusted['type'] = 'jpg';
}
if($config->image_autoconv['webp2jpg'] && function_exists('imagewebp') && $image_type === 18)
elseif ($config->image_autoconv['webp2jpg'] && $image_info['type'] === 'webp' && function_exists('imagewebp'))
{
$convert = array($image_width, $image_height, 'jpg', $config->image_autoconv_quality ?: 75, 0);
$adjusted['type'] = 'jpg';
}
if($config->image_autoconv['gif2mp4'] && function_exists('exec') && $image_type === 1)
elseif ($config->image_autoconv['bmp2jpg'] && $image_info['type'] === 'bmp' && function_exists('imagebmp'))
{
$convert = array($image_width, $image_height, 'mp4', $config->image_autoconv_quality ?: 75, 0);
$adjusted['type'] = 'jpg';
}
// Check image rotation
if($config->image_autorotate && $image_type !== 1 && function_exists('exif_read_data'))
// Adjust image rotation
if ($config->image_autorotate && $image_info['type'] === 'jpg' && function_exists('exif_read_data'))
{
$exif = @exif_read_data($file_info['tmp_name']);
if($exif && isset($exif['Orientation']))
@ -1107,32 +1085,33 @@ class fileController extends file
}
if ($rotate)
{
$convert = $convert ?: array($image_width, $image_height, $file_info['extension']);
if ($rotate == 90 || $rotate == 270)
if ($rotate === 90 || $rotate === 270)
{
$image_height = $convert[0];
$image_width = $convert[1];
$convert[0] = $image_width;
$convert[1] = $image_height;
$adjusted['width'] = $image_info['height'];
$adjusted['height'] = $image_info['width'];
}
$convert[3] = $config->image_autorotate_quality ?: 75;
$convert[4] = $rotate;
$adjusted['rotate'] = $rotate;
}
}
unset($exif);
}
// Check image size
if($config->max_image_size_action && ($config->max_image_width || $config->max_image_height) && (!$this->user->isAdmin() || $config->max_image_size_admin === 'Y'))
// Adjust image size
if ($config->max_image_size_action && ($config->max_image_width || $config->max_image_height) && (!$this->user->isAdmin() || $config->max_image_size_admin === 'Y'))
{
$exceeded = false;
if ($config->max_image_width > 0 && $image_width > $config->max_image_width)
$exceeded = 0;
$resize_width = $adjusted['width'];
$resize_height = $adjusted['height'];
if ($config->max_image_width > 0 && $adjusted['width'] > $config->max_image_width)
{
$exceeded = true;
$resize_width = $config->max_image_width;
$resize_height = $adjusted['height'] * ($config->max_image_width / $adjusted['width']);
$exceeded++;
}
elseif ($config->max_image_height > 0 && $image_height > $config->max_image_height)
if ($config->max_image_height > 0 && $resize_height > $config->max_image_height)
{
$exceeded = true;
$resize_width = $resize_width * ($config->max_image_height / $resize_height);
$resize_height = $config->max_image_height;
$exceeded++;
}
if ($exceeded)
@ -1152,64 +1131,151 @@ class fileController extends file
{
$message = sprintf(lang('msg_exceeds_max_image_height'), $config->max_image_height);
}
throw new Rhymix\Framework\Exception($message);
}
// Resize automatically
else
$adjusted['width'] = (int)$resize_width;
$adjusted['height'] = (int)$resize_height;
if (!$is_animated && $adjusted['type'] === $image_info['type'])
{
$resize_width = $image_width;
$resize_height = $image_height;
if ($config->max_image_width > 0 && $image_width > $config->max_image_width)
{
$resize_width = $config->max_image_width;
$resize_height = $image_height * ($config->max_image_width / $image_width);
}
if ($config->max_image_height > 0 && $resize_height > $config->max_image_height)
{
$resize_width = $resize_width * ($config->max_image_height / $resize_height);
$resize_height = $config->max_image_height;
}
$target_type = in_array($image_type, array(6, 8, 18)) ? 'jpg' : $file_info['extension'];
$rotate = ($convert && $convert[4]) ? $convert[4] : 0;
$convert = array(intval($resize_width), intval($resize_height), $target_type, $config->max_image_size_quality ?: 75, $rotate);
$adjusted['type'] = 'jpg';
}
}
}
// Convert image if necessary
if ($convert)
// Set force for remove EXIF data
if($config->image_remove_exif_data && $image_info['type'] === 'jpg' && function_exists('exif_read_data'))
{
if ($convert[2] === 'mp4')
if(!isset($exif))
{
$command = $config->ffmpeg_command ?: '/usr/bin/ffmpeg';
$exif = @exif_read_data($file_info['tmp_name']);
}
if($exif && (isset($exif['Model']) || isset($exif['Software']) || isset($exif['GPSVersion'])))
{
$force = true;
}
}
// Convert image if adjusted
if (
$force ||
$adjusted['width'] !== $image_info['width'] ||
$adjusted['height'] !== $image_info['height'] ||
$adjusted['type'] !== $image_info['type'] ||
$adjusted['rotate'] !== 0
)
{
$output_name = $file_info['tmp_name'] . '.converted.' . $adjusted['type'];
// Generate an output file
if ($adjusted['type'] === 'mp4')
{
$adjusted['width'] -= $adjusted['width'] % 2;
$adjusted['height'] -= $adjusted['height'] % 2;
// Convert using ffmpeg
$command = $config->ffmpeg_command;
$command .= ' -i ' . escapeshellarg($file_info['tmp_name']);
$command .= ' -movflags faststart -pix_fmt yuv420p -c:v libx264 -crf 23 -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2"';
$command .= ' ' . escapeshellarg($file_info['tmp_name'] . '.mp4');
$status = @exec($command, $output, $return_var);
$result = $return_var == 0 ? true : false;
$newext = '.mp4';
$command .= ' -movflags +faststart -pix_fmt yuv420p -c:v libx264 -crf 23';
$command .= sprintf(' -vf "scale=%d:%d"', $adjusted['width'], $adjusted['height']);
$command .= ' ' . escapeshellarg($output_name);
@exec($command, $output, $return_var);
$result = $return_var === 0 ? true : false;
// Generate a thumbnail image
if ($result)
{
$thumbnail_name = $file_info['tmp_name'] . '.thumbnail.jpg';
if (FileHandler::createImageFile($file_info['tmp_name'], $thumbnail_name, $adjusted['width'], $adjusted['height'], 'jpg', 'crop', $adjusted['quality']))
{
$file_info['thumbnail'] = $thumbnail_name;
}
}
}
else
{
$result = FileHandler::createImageFile($file_info['tmp_name'], $file_info['tmp_name'] . '.conv', $convert[0], $convert[1], $convert[2], 'crop', $convert[3], $convert[4]);
$newext = '.conv';
$result = FileHandler::createImageFile($file_info['tmp_name'], $output_name, $adjusted['width'], $adjusted['height'], $adjusted['type'], 'crop', $adjusted['quality'], $adjusted['rotate']);
}
// Change to information in the output file
if ($result)
{
$file_info['name'] = preg_replace('/\.' . preg_quote($file_info['extension'], '/') . '$/i', '.' . $convert[2], $file_info['name']);
$file_info['tmp_name'] = $file_info['tmp_name'] . $newext;
$file_info['size'] = filesize($file_info['tmp_name']);
$file_info['extension'] = $convert[2];
$file_info['tmp_name'] = $output_name;
$file_info['size'] = filesize($output_name);
$file_info['type'] = Rhymix\Framework\MIME::getContentType($output_name);
$file_info['extension'] = $adjusted['type'];
$file_info['width'] = $adjusted['width'];
$file_info['height'] = $adjusted['height'];
$file_info['converted'] = true;
}
}
return $file_info;
}
/**
* Adjust uploaded video
*/
public function adjustUploadedVideo($file_info, $config)
{
if (!function_exists('exec') || !Rhymix\Framework\Storage::isExecutable($config->ffmpeg_command) || !Rhymix\Framework\Storage::isExecutable($config->ffprobe_command))
{
return $file_info;
}
// Analyze video file
$command = $config->ffprobe_command;
$command .= ' -v quiet -print_format json -show_streams';
$command .= ' ' . escapeshellarg($file_info['tmp_name']);
@exec($command, $output, $return_var);
if ($return_var !== 0 || !$output = json_decode(implode('', $output), true))
{
return $file_info;
}
// Get stream information
$stream_info = [];
foreach ($output['streams'] as $info)
{
$stream_info[$info['codec_type']] = $info;
}
if (empty($stream_info['video']))
{
return $file_info;
}
// Set video size
$file_info['width'] = (int)$stream_info['video']['width'];
$file_info['height'] = (int)$stream_info['video']['height'];
$file_info['duration'] = (int)$stream_info['video']['duration'];
// MP4
if ($file_info['extension'] === 'mp4')
{
// Treat as GIF
if ($config->video_mp4_gif_time && $file_info['duration'] <= $config->video_mp4_gif_time && empty($stream_info['audio']))
{
$file_info['original_type'] = 'image/gif';
}
}
// Generate a thumbnail image
if ($config->video_thumbnail)
{
$thumbnail_name = $file_info['tmp_name'] . '.thumbnail.jpeg';
$command = $config->ffmpeg_command;
$command .= sprintf(' -ss 00:00:00.%d -i %s -vframes 1', mt_rand(0, 99), escapeshellarg($file_info['tmp_name']));
$command .= ' ' . escapeshellarg($thumbnail_name);
@exec($command, $output, $return_var);
if ($return_var === 0)
{
$file_info['thumbnail'] = $thumbnail_name;
}
}
return $file_info;
}
/**
* Delete the attachment
*
@ -1304,6 +1370,13 @@ class fileController extends file
// Remove empty directories
Rhymix\Framework\Storage::deleteEmptyDirectory(dirname(FileHandler::getRealPath($file->uploaded_filename)), true);
// Remove thumbnail
if ($file->thumbnail_filename)
{
Rhymix\Framework\Storage::delete(FileHandler::getRealPath($file->thumbnail_filename));
Rhymix\Framework\Storage::deleteEmptyDirectory(dirname(FileHandler::getRealPath($file->thumbnail_filename)), true);
}
}
$oDB->commit();
@ -1558,7 +1631,6 @@ class fileController extends file
{
return sprintf('%sfiles/attach/%s/%04d/%02d/%02d/', $prefix, $file_type, substr($regdate, 0, 4), substr($regdate, 4, 2), substr($regdate, 6, 2));
}
// 1 or 0: module_srl 및 업로드 대상 번호에 따라 3자리씩 끊어서 정리
else
{
@ -1566,7 +1638,7 @@ class fileController extends file
return sprintf('%sfiles/attach/%s/%d/%s', $prefix, $file_type, $module_srl, $components);
}
}
/**
* Find the attachment where a key is upload_target_srl and then return java script code
*

View file

@ -24,107 +24,215 @@ class fileModel extends file
*/
function getFileList()
{
$oModuleModel = getModel('module');
$mid = Context::get('mid');
$file_list = [];
$attached_size = 0;
$editor_sequence = Context::get('editor_sequence');
$upload_target_srl = Context::get('upload_target_srl');
if(!$upload_target_srl) $upload_target_srl = $_SESSION['upload_info'][$editor_sequence]->upload_target_srl;
$upload_target_srl = Context::get('upload_target_srl') ?: 0;
if(!$upload_target_srl && isset($_SESSION['upload_info'][$editor_sequence]))
{
$upload_target_srl = $_SESSION['upload_info'][$editor_sequence]->upload_target_srl;
}
// Get uploaded files
if($upload_target_srl)
{
$oDocumentModel = getModel('document');
$oModuleModel = getModel('module');
$oCommentModel = getModel('comment');
$logged_info = Context::get('logged_info');
$oDocumentModel = getModel('document');
$oDocument = $oDocumentModel->getDocument($upload_target_srl);
// comment 권한 확인
// Check permissions of the comment
if(!$oDocument->isExists())
{
$oComment = $oCommentModel->getComment($upload_target_srl);
if($oComment->isExists() && !$oComment->isAccessible())
if($oComment->isExists())
{
throw new Rhymix\Framework\Exceptions\NotPermitted;
if(!$oComment->isAccessible())
{
throw new Rhymix\Framework\Exceptions\NotPermitted;
}
$oDocument = $oDocumentModel->getDocument($oComment->get('document_srl'));
}
$oDocument = $oDocumentModel->getDocument($oComment->get('document_srl'));
}
// document 권한 확인
// Check permissions of the document
if($oDocument->isExists() && !$oDocument->isAccessible())
{
throw new Rhymix\Framework\Exceptions\NotPermitted;
}
// 모듈 권한 확인
if($oDocument->isExists())
// Check permissions of the module
if($module_srl = isset($oComment) ? $oComment->get('module_srl') : $oDocument->get('module_srl'))
{
$grant = $oModuleModel->getGrant($oModuleModel->getModuleInfoByModuleSrl($oDocument->get('module_srl')), $logged_info);
$module_info = $oModuleModel->getModuleInfoByModuleSrl($module_srl);
if(empty($module_info->module_srl))
{
throw new Rhymix\Framework\Exceptions\NotPermitted;
}
$grant = $oModuleModel->getGrant($module_info, Context::get('logged_info'));
if(!$grant->access)
{
throw new Rhymix\Framework\Exceptions\NotPermitted;
}
}
$tmp_files = $this->getFiles($upload_target_srl);
if($tmp_files instanceof BaseObject && !$tmp_files->toBool()) return $tmp_files;
$files = array();
foreach($tmp_files as $file_info)
// Set file list
foreach($this->getFiles($upload_target_srl) as $file_info)
{
if(!$file_info->file_srl) continue;
$obj = new stdClass;
$obj->file_srl = $file_info->file_srl;
$obj->source_filename = $file_info->source_filename;
$obj->thumbnail_filename = $file_info->thumbnail_filename;
$obj->file_size = $file_info->file_size;
$obj->disp_file_size = FileHandler::filesize($file_info->file_size);
if($file_info->direct_download == 'N')
{
$obj->download_url = $this->getDownloadUrl($file_info->file_srl, $file_info->sid, $file_info->module_srl);
}
else
$obj->mime_type = $file_info->mime_type;
$obj->original_type = $file_info->original_type;
$obj->direct_download = $file_info->direct_download;
$obj->cover_image = ($file_info->cover_image === 'Y') ? true : false;
$obj->download_url = $file_info->download_url;
if($obj->direct_download === 'Y' && $this->isDownloadable($file_info))
{
$obj->download_url = $this->getDirectFileUrl($file_info->uploaded_filename);
}
$obj->direct_download = $file_info->direct_download;
$obj->cover_image = ($file_info->cover_image === 'Y') ? true : false;
$files[] = $obj;
$file_list[] = $obj;
$attached_size += $file_info->file_size;
}
}
// Set output
$this->add('files', $file_list);
$this->add('attached_size', FileHandler::filesize($attached_size));
$this->add('editor_sequence', $editor_sequence);
$this->add('upload_target_srl', $upload_target_srl);
// Set upload config
$upload_config = $this->getUploadConfig();
if($this->user->isAdmin())
{
$this->add('allowed_filesize', sprintf('%s (%s)', lang('common.unlimited'), lang('common.admin')));
$this->add('allowed_attach_size', sprintf('%s (%s)', lang('common.unlimited'), lang('common.admin')));
$this->add('allowed_extensions', []);
}
else
{
$upload_target_srl = 0;
$attached_size = 0;
$files = array();
$this->add('allowed_filesize', FileHandler::filesize($upload_config->allowed_filesize * 1024 * 1024));
$this->add('allowed_attach_size', FileHandler::filesize($upload_config->allowed_attach_size * 1024 * 1024));
$this->add('allowed_extensions', $upload_config->allowed_extensions);
}
// Display upload status
$upload_status = $this->getUploadStatus($attached_size);
// Check remained file size until upload complete
//$config = $oModuleModel->getModuleInfoByMid($mid); //perhaps config varialbles not used
$file_config = $this->getUploadConfig();
$left_size = $file_config->allowed_attach_size*1024*1024 - $attached_size;
// Settings of required information
$attached_size = FileHandler::filesize($attached_size);
$allowed_attach_size = FileHandler::filesize($file_config->allowed_attach_size*1024*1024);
$allowed_filesize = FileHandler::filesize($file_config->allowed_filesize*1024*1024);
$allowed_filetypes = $file_config->allowed_filetypes;
$allowed_extensions = $file_config->allowed_extensions ?: array();
$this->add("files",$files);
$this->add("editor_sequence",$editor_sequence);
$this->add("upload_target_srl",$upload_target_srl);
$this->add("upload_status",$upload_status);
$this->add("left_size",$left_size);
$this->add('attached_size', $attached_size);
$this->add('allowed_attach_size', $allowed_attach_size);
$this->add('allowed_filesize', $allowed_filesize);
$this->add('allowed_filetypes', $allowed_filetypes);
$this->add('allowed_extensions', $allowed_extensions);
// for compatibility
$this->add('allowed_filetypes', $upload_config->allowed_filetypes);
$this->add('upload_status', $this->getUploadStatus($attached_size));
$this->add('left_size', $upload_config->allowed_attach_size * 1024 * 1024 - $attached_size);
}
/**
* Check if the file is downloadable
*
* @param object $file_info
* @param object $member_info
* @return bool
*/
function isDownloadable($file_info, $member_info = null)
{
if(!$member_info)
{
$member_info = $this->user;
}
if($this->isDeletable($file_info, $member_info))
{
return true;
}
// Check the validity
if($file_info->isvalid !== 'Y')
{
return false;
}
// Check download groups
$config = $this->getFileConfig($file_info->module_srl);
if($config->download_groups)
{
if(empty($member_info->member_srl))
{
return false;
}
if(!isset($member_info->group_list))
{
$member_info->group_list = getModel('member')->getMemberGroups($member_info->member_srl);
}
$is_group = false;
foreach($config->download_groups as $group_srl)
{
if(isset($member_info->group_list[$group_srl]))
{
$is_group = true;
break;
}
}
if(!$is_group)
{
return false;
}
}
return true;
}
/**
* Check if the file is deletable
*
* @param object $file_info
* @param object $member_info
* @return bool
*/
function isDeletable($file_info, $member_info = null)
{
if(!$member_info)
{
$member_info = $this->user;
}
if($member_info->is_admin === 'Y' || $member_info->member_srl == $file_info->member_srl)
{
return true;
}
if(isset($_SESSION['__XE_UPLOADING_FILES_INFO__'][$file_info->file_srl]))
{
return true;
}
// Check permissions of the module
$oModuleModel = getModel('module');
$module_info = $oModuleModel->getModuleInfoByModuleSrl($file_info->module_srl);
if(empty($module_info->module_srl))
{
return false;
}
$grant = $oModuleModel->getGrant($module_info, $member_info);
if($grant->manager)
{
return true;
}
// Check permissions of the document
$oDocument = getModel('document')->getDocument($file_info->upload_target_srl);
if($oDocument->isExists() && $oDocument->isGranted())
{
return true;
}
// Check permissions of the comment
$oComment = getModel('comment')->getComment($file_info->upload_target_srl);
if($oComment->isExists() && $oComment->isGranted())
{
return true;
}
return false;
}
/**
* Return number of attachments which belongs to a specific document
*
@ -175,90 +283,46 @@ class fileModel extends file
*/
function getFileConfig($module_srl = null)
{
// Get configurations (using module model object)
$oModuleModel = getModel('module');
$file_module_config = $oModuleModel->getModuleConfig('file');
if($module_srl) $file_config = $oModuleModel->getModulePartConfig('file',$module_srl);
if(!$file_config) $file_config = $file_module_config;
$config = new stdClass();
if($file_config)
$config = $oModuleModel->getModuleConfig('file') ?: new stdClass;
if($module_srl)
{
$config->use_default_file_config = $file_config->use_default_file_config;
$config->allowed_filesize = $file_config->allowed_filesize;
$config->allowed_attach_size = $file_config->allowed_attach_size;
$config->allowed_filetypes = $file_config->allowed_filetypes;
$config->allowed_extensions = $file_config->allowed_extensions;
$config->inline_download_format = $file_config->inline_download_format;
$config->max_image_width = $file_config->max_image_width;
$config->max_image_height = $file_config->max_image_height;
$config->max_image_size_action = $file_config->max_image_size_action;
$config->max_image_size_quality = $file_config->max_image_size_quality;
$config->max_image_size_admin = $file_config->max_image_size_admin;
$config->image_autoconv = $file_config->image_autoconv;
$config->image_autoconv_quality = $file_config->image_autoconv_quality;
$config->image_autorotate = $file_config->image_autorotate;
$config->image_autorotate_quality = $file_config->image_autorotate_quality;
$config->ffmpeg_command = $file_config->ffmpeg_command;
$config->download_grant = $file_config->download_grant;
$config->allow_outlink = $file_config->allow_outlink;
$config->allow_outlink_site = $file_config->allow_outlink_site;
$config->allow_outlink_format = $file_config->allow_outlink_format;
$config->save_changelog = $file_config->save_changelog;
$module_config = $oModuleModel->getModulePartConfig('file', $module_srl);
foreach((array)$module_config as $key => $value)
{
$config->$key = $value;
}
}
// Property for all files comes first than each property
if(!$config->allowed_filesize) $config->allowed_filesize = $file_module_config->allowed_filesize;
if(!$config->allowed_attach_size) $config->allowed_attach_size = $file_module_config->allowed_attach_size;
if(!$config->allowed_filetypes) $config->allowed_filetypes = $file_module_config->allowed_filetypes;
if(!$config->allowed_extensions) $config->allowed_extensions = $file_module_config->allowed_extensions;
if(!$config->allow_outlink) $config->allow_outlink = $file_module_config->allow_outlink;
if(!$config->allow_outlink_site) $config->allow_outlink_site = $file_module_config->allow_outlink_site;
if(!$config->allow_outlink_format) $config->allow_outlink_format = $file_module_config->allow_outlink_format;
if(!$config->download_grant) $config->download_grant = $file_module_config->download_grant;
if(!$config->max_image_width) $config->max_image_width = $file_module_config->max_image_width;
if(!$config->max_image_height) $config->max_image_height = $file_module_config->max_image_height;
if(!$config->max_image_size_action) $config->max_image_size_action = $file_module_config->max_image_size_action;
if(!$config->max_image_size_quality) $config->max_image_size_quality = $file_module_config->max_image_size_quality;
if(!$config->max_image_size_admin) $config->max_image_size_admin = $file_module_config->max_image_size_admin;
if(!$config->image_autoconv) $config->image_autoconv = $file_module_config->image_autoconv;
if(!$config->image_autoconv_quality) $config->image_autoconv_quality = $file_module_config->image_autoconv_quality;
if(!$config->image_autorotate) $config->image_autorotate = $file_module_config->image_autorotate;
if(!$config->image_autorotate_quality) $config->image_autorotate_quality = $file_module_config->image_autorotate_quality;
if(!$config->ffmpeg_command) $config->ffmpeg_command = $file_module_config->ffmpeg_command;
if(!$config->save_changelog) $config->save_changelog = $file_module_config->save_changelog;
// Default setting if not exists
if(!$config->allowed_filesize) $config->allowed_filesize = '2';
if(!$config->allowed_attach_size) $config->allowed_attach_size = '3';
if(!$config->allowed_filetypes) $config->allowed_filetypes = '*.*';
if(!$config->allow_outlink) $config->allow_outlink = 'Y';
if(!$config->download_grant) $config->download_grant = array();
if(!$config->inline_download_format) $config->inline_download_format = array();
if(!$config->max_image_size_quality) $config->max_image_size_quality = 75;
if(!$config->image_autoconv) $config->image_autoconv = array();
if(!$config->image_autoconv_quality) $config->image_autoconv_quality = 75;
if(!$config->image_autorotate_quality) $config->image_autorotate_quality = 75;
$config->allowed_filesize = $config->allowed_filesize ?? '2';
$config->allowed_attach_size = $config->allowed_attach_size ?? '3';
$config->allowed_filetypes = $config->allowed_filetypes ?? '*.*';
$config->allow_outlink = $config->allow_outlink ?? 'Y';
$config->download_grant = $config->download_grant ?? [];
$config->inline_download_format = $config->inline_download_format ?? [];
$config->image_autoconv = $config->image_autoconv ?? [];
$config->image_quality_adjustment = $config->image_quality_adjustment ?? 75;
$config->video_mp4_gif_time = $config->video_mp4_gif_time ?? 0;
$config->ffmpeg_command = $config->ffmpeg_command ?? '/usr/bin/ffmpeg';
$config->ffprobe_command = $config->ffprobe_command ?? '/usr/bin/ffprobe';
// Format allowed_filetypes
if($config->allowed_filetypes && !isset($config->allowed_extensions))
// Set allowed_extensions
if(!isset($config->allowed_extensions))
{
$config->allowed_extensions = [];
$config->allowed_filetypes = trim($config->allowed_filetypes);
if($config->allowed_filetypes === '*.*')
{
$config->allowed_extensions = array();
}
else
if($config->allowed_filetypes !== '*.*')
{
$config->allowed_extensions = array_map(function($ext) {
return strtolower(substr(strrchr(trim($ext), '.'), 1));
}, explode(';', $config->allowed_filetypes));
}
}
// Set download_groups
$config->download_groups = is_array($config->download_grant) ? array_filter($config->download_grant) : [];
return $config;
}
@ -338,26 +402,16 @@ class fileModel extends file
*/
function getUploadConfig()
{
$logged_info = Context::get('logged_info');
$module_srl = Context::get('module_srl');
// Get the current module if module_srl doesn't exist
if(!$module_srl)
$config = $this->getFileConfig(Context::get('module_srl') ?: Context::get('current_module_info')->module_srl);
if($this->user->isAdmin())
{
$current_module_info = Context::get('current_module_info');
$module_srl = $current_module_info->module_srl;
$module_config = getModel('module')->getModuleConfig('file');
$config->allowed_filesize = max($config->allowed_filesize, $module_config->allowed_filesize);
$config->allowed_attach_size = max($config->allowed_attach_size, $module_config->allowed_attach_size);
$config->allowed_extensions = [];
$config->allowed_filetypes = '*.*';
}
$file_config = $this->getFileConfig($module_srl);
if($logged_info->is_admin == 'Y')
{
$oModuleModel = getModel('module');
$module_config = $oModuleModel->getModuleConfig('file');
$file_config->allowed_filesize = max($file_config->allowed_filesize, $module_config->allowed_filesize);
$file_config->allowed_attach_size = max($file_config->allowed_attach_size, $module_config->allowed_attach_size);
$file_config->allowed_filetypes = '*.*';
}
return $file_config;
return $config;
}
/**
@ -393,10 +447,7 @@ class fileModel extends file
}
/**
* Return file configuration of the module
*
* @param int $module_srl The sequence of module to get configuration
* @return object
* method for compatibility
*/
function getFileModuleConfig($module_srl)
{
@ -404,34 +455,11 @@ class fileModel extends file
}
/**
* Returns a grant of file
*
* @param object $file_info The file information to get grant
* @param object $member_info The member information to get grant
* @return object Returns a grant of file
* method for compatibility
*/
function getFileGrant($file_info, $member_info)
{
if(!$file_info) return null;
$file_grant = new stdClass;
if($_SESSION['__XE_UPLOADING_FILES_INFO__'][$file_info->file_srl])
{
$file_grant->is_deletable = true;
return $file_grant;
}
$oModuleModel = getModel('module');
$grant = $oModuleModel->getGrant($oModuleModel->getModuleInfoByModuleSrl($file_info->module_srl), $member_info);
$oDocumentModel = getModel('document');
$oDocument = $oDocumentModel->getDocument($file_info->upload_target_srl);
if($oDocument->isExists()) $document_grant = $oDocument->isGranted();
$file_grant->is_deletable = ($document_grant || $member_info->is_admin == 'Y' || $member_info->member_srl == $file_info->member_srl || $grant->manager);
return $file_grant;
return (object)['is_deletable' => $this->isDeletable($file_info, $member_info)];
}
}
/* End of file file.model.php */

View file

@ -24,27 +24,30 @@ class fileView extends file
function triggerDispFileAdditionSetup(&$obj)
{
$current_module_srl = Context::get('module_srl');
$current_module_srls = Context::get('module_srls');
if(!$current_module_srl && !$current_module_srls)
if(!$current_module_srl)
{
// Get information of the current module
$current_module_info = Context::get('current_module_info');
$current_module_srl = $current_module_info->module_srl;
if(!$current_module_srl) return;
$current_module_srl = Context::get('current_module_info')->module_srl;
if(!$current_module_srl)
{
return;
}
}
// Get file configurations of the module
$oFileModel = getModel('file');
$file_config = $oFileModel->getFileModuleConfig($current_module_srl);
Context::set('file_config', $file_config);
$config = $oFileModel->getFileConfig($current_module_srl);
Context::set('config', $config);
Context::set('is_ffmpeg', function_exists('exec') && Rhymix\Framework\Storage::isExecutable($config->ffmpeg_command) && Rhymix\Framework\Storage::isExecutable($config->ffprobe_command));
// Get a permission for group setting
$oMemberModel = getModel('member');
$site_module_info = Context::get('site_module_info');
$group_list = $oMemberModel->getGroups($site_module_info->site_srl);
$group_list = $oMemberModel->getGroups();
Context::set('group_list', $group_list);
// Set a template file
$oTemplate = &TemplateHandler::getInstance();
$tpl = $oTemplate->compile($this->module_path.'tpl', 'file_module_config');
$oTemplate = TemplateHandler::getInstance();
$tpl = $oTemplate->compile($this->module_path . 'tpl', 'file_module_config');
$obj .= $tpl;
}
}

View file

@ -18,19 +18,6 @@ $lang->allow_outlink_format = 'Allowed Formats';
$lang->allowed_filesize = 'Maximum File Size';
$lang->allowed_attach_size = 'Maximum Attachments';
$lang->allowed_filetypes = 'Allowed extentsions';
$lang->max_image_size = 'Maximum Image Size';
$lang->max_image_size_action_nothing = 'If exceeded, do nothing';
$lang->max_image_size_action_block = 'If exceeded, block upload';
$lang->max_image_size_action_resize = 'If exceeded, resize automatically';
$lang->max_image_size_admin = 'Also apply to administrator';
$lang->image_resize_quality = 'Quality';
$lang->image_autoconv = 'Auto-Convert Image';
$lang->image_autoconv_bmp2jpg = 'BMP → JPG';
$lang->image_autoconv_png2jpg = 'PNG → JPG';
$lang->image_autoconv_webp2jpg = 'WebP → JPG';
$lang->image_autoconv_gif2mp4 = 'GIF → MP4';
$lang->ffmpeg_path = 'Path to ffmpeg';
$lang->image_autorotate = 'Auto-Rotate Image';
$lang->inline_download_format = 'Open in current window';
$lang->inline_download_image = 'Image';
$lang->inline_download_audio = 'Audio';
@ -51,10 +38,6 @@ $lang->about_allowed_filesize_global = 'This is the global limit on the size of
$lang->about_allowed_attach_size_global = 'This is the global limit on the combined size of all attachments in one document.';
$lang->about_allowed_size_limits = 'The file size will be limited to the value set in php.ini (%sB) in IE9 and below and older Android browsers.';
$lang->about_allowed_filetypes = 'Rhymix no longer uses the old *.* syntax. Simply list the extensions you wish to allow.<br />Please use a comma (,) to separate items: e.g. doc, zip, pdf';
$lang->about_max_image_size = 'You can limit the maximum width and/or height of uploaded images.<br />This limit does not apply to files uploaded by the administrator.';
$lang->about_image_autoconv = 'Automatically convert types of images that often cause trouble or waste disk space into other types.<br />This also works for WebP images that incorrectly have the JPG extension.<br />If enabled, this feature also applies to images uploaded by the administrator.';
$lang->about_image_autoconv_mp4 = 'Automatically convert animated GIF images into MP4 videos to save storage and bandwidth.<br />Videos may not play properly in older browsers.';
$lang->about_image_autorotate = 'Automatically correct images that are rotated by mobile devices.<br />If enabled, this feature also applies to images uploaded by the administrator.';
$lang->about_save_changelog = 'Keep a log of new and deleted files in the database.';
$lang->cmd_delete_checked_file = 'Delete Selected Item(s)';
$lang->cmd_move_to_document = 'Move to Document';
@ -88,3 +71,34 @@ $lang->msg_32bit_max_2047mb = 'On 32-bit servers, the file size limit cannot exc
$lang->no_files = 'No Files';
$lang->file_manager = 'Manage selected files';
$lang->selected_file = 'Selected files';
$lang->use_image_default_file_config = 'Use Default Settings Of Image File';
$lang->about_use_image_default_file_config = 'Follow the default settings of image file from the File module.';
$lang->use_video_default_file_config = 'Use Default Settings Of Video File';
$lang->about_use_video_default_file_config = 'Follow the video settings of image file from the File module.';
$lang->image_autoconv = 'Image Type';
$lang->about_image_autoconv = 'convert the type of uploaded images. You can fix images that often cause trouble or waste disk space into other types.<br />This also works for WebP images that incorrectly have the JPG extension.';
$lang->image_autoconv_bmp2jpg = 'BMP → JPG';
$lang->image_autoconv_png2jpg = 'PNG → JPG';
$lang->image_autoconv_webp2jpg = 'WebP → JPG';
$lang->max_image_size = 'Image Size';
$lang->about_max_image_size = 'limit the size of uploaded images.<br />This limit does not apply to files uploaded by the administrator.';
$lang->max_image_size_action_nothing = 'If exceeded, do nothing';
$lang->max_image_size_action_block = 'If exceeded, block upload';
$lang->max_image_size_action_resize = 'If exceeded, resize automatically';
$lang->max_image_size_admin = 'Also apply to administrator';
$lang->image_quality_adjustment = 'Image Quality';
$lang->about_image_quality_adjustment = 'adjust the quality of images that will is converted by other settings.<br />If set to more than 75% (Standard), the file size may be larger than the original.';
$lang->image_autorotate = 'Fix Image Rotation';
$lang->about_image_autorotate = 'correct images that are rotated by mobile devices.';
$lang->image_remove_exif_data = 'Remove EXIF';
$lang->about_image_remove_exif_data = 'remove EXIF data including camera, GPS information, and more in image file for privacy.<br />Even if this option is not used, EXIF data may be removed when the image is converted by other settings.';
$lang->image_autoconv_gif2mp4 = 'Convert GIF';
$lang->about_image_autoconv_gif2mp4 = 'convert animated GIF images into MP4 videos to save storage and bandwidth.<br />Videos may not play properly in older browsers.';
$lang->video_thumbnail = 'Video Thumbnail';
$lang->about_video_thumbnail = 'extract a thumbnail image from uploaded video.';
$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->ffmpeg_path = 'FFmpeg path';
$lang->ffprobe_path = 'FFprobe path';
$lang->msg_cannot_use_ffmpeg = 'FFmpeg and FFprobe must can be executed by PHP.';
$lang->msg_cannot_use_exif = 'PHP Exif module is required.';

View file

@ -18,23 +18,10 @@ $lang->allow_outlink_format = '외부 접근 허용 확장자';
$lang->allowed_filesize = '파일 용량 제한';
$lang->allowed_attach_size = '문서 첨부 제한';
$lang->allowed_filetypes = '허용 확장자';
$lang->max_image_size = '이미지 크기 제한';
$lang->max_image_size_action_nothing = '초과시 아무 것도 하지 않음';
$lang->max_image_size_action_block = '초과시 업로드 금지';
$lang->max_image_size_action_resize = '초과시 자동 크기 조정';
$lang->max_image_size_admin = '관리자에게도 적용';
$lang->image_resize_quality = '화질';
$lang->image_autoconv = '이미지 자동 변환';
$lang->image_autoconv_bmp2jpg = 'BMP → JPG';
$lang->image_autoconv_png2jpg = 'PNG → JPG';
$lang->image_autoconv_webp2jpg = 'WebP → JPG';
$lang->image_autoconv_gif2mp4 = 'GIF → MP4';
$lang->ffmpeg_path = 'ffmpeg 경로';
$lang->image_autorotate = '이미지 자동 회전';
$lang->inline_download_format = '다운로드시 현재 창 사용';
$lang->inline_download_image = '이미지';
$lang->inline_download_audio = '오디오';
$lang->inline_download_video = '비디오';
$lang->inline_download_video = '동영상';
$lang->inline_download_text = '텍스트 (HTML 제외)';
$lang->inline_download_pdf = 'PDF';
$lang->file_save_changelog = '변경 내역 기록';
@ -51,10 +38,6 @@ $lang->about_allowed_filesize_global = '관리자를 포함하여 사이트 전
$lang->about_allowed_attach_size_global = '관리자를 포함하여 사이트 전체에 적용되는 문서당 총 첨부 용량 제한입니다.';
$lang->about_allowed_size_limits = 'IE9 이하, 구버전 안드로이드 등에서는 php.ini에서 지정한 %sB로 제한됩니다.';
$lang->about_allowed_filetypes = '업로드를 허용할 확장자 목록입니다. 구 버전의 *.* 문법은 사용하지 않습니다.<br />여러 개 입력시 쉼표(,)을 이용해서 구분해 주세요. 예) doc, zip, pdf';
$lang->about_max_image_size = '이미지 파일의 가로, 세로, 또는 가로세로 크기를 모두 제한할 수 있습니다.<br />관리자가 업로드한 파일에는 적용되지 않습니다.';
$lang->about_image_autoconv = '종종 문제를 일으키거나 용량을 낭비하는 이미지 타입을 다른 타입으로 자동 변환합니다.<br />WebP 이미지에 JPG 확장자가 잘못 부여된 경우에도 변환할 수 있습니다.<br />관리자가 업로드한 파일에도 적용됩니다.';
$lang->about_image_autoconv_mp4 = '움직이는 GIF 이미지를 MP4 동영상으로 변환하여 용량 및 트래픽을 절약합니다.<br />구형 브라우저에서는 동영상이 재생되지 않을 수도 있습니다.';
$lang->about_image_autorotate = '모바일 기기 등에서 잘못 회전된 이미지를 바로잡습니다.<br />관리자가 업로드한 파일에도 적용됩니다.';
$lang->about_save_changelog = '파일 저장 및 삭제 내역을 DB에 기록합니다.';
$lang->cmd_delete_checked_file = '선택항목 삭제';
$lang->cmd_move_to_document = '문서로 이동';
@ -89,3 +72,34 @@ $lang->msg_32bit_max_2047mb = '32비트 서버에서는 파일 크기 제한이
$lang->no_files = '파일이 없습니다.';
$lang->file_manager = '선택한 파일 관리';
$lang->selected_file = '선택한 파일';
$lang->use_image_default_file_config = '이미지 파일 기본 설정 사용';
$lang->about_use_image_default_file_config = '파일 모듈의 이미지 파일 기본 설정을 따릅니다.';
$lang->use_video_default_file_config = '동영상 파일 기본 설정 사용';
$lang->about_use_video_default_file_config = '파일 모듈의 동영상 파일 기본 설정을 따릅니다.';
$lang->image_autoconv = '이미지 타입';
$lang->about_image_autoconv = '업로드된 이미지의 타입을 변환합니다. 종종 문제를 일으키거나 용량을 낭비하는 이미지를 해결할 수 있습니다.<br />WebP 이미지에 JPG 확장자가 잘못 부여된 경우에도 변환할 수 있습니다.';
$lang->image_autoconv_bmp2jpg = 'BMP → JPG';
$lang->image_autoconv_png2jpg = 'PNG → JPG';
$lang->image_autoconv_webp2jpg = 'WebP → JPG';
$lang->max_image_size = '이미지 크기';
$lang->about_max_image_size = '업로드된 이미지의 크기를 제한하거나 조정합니다. 관리자가 업로드한 파일에는 적용되지 않습니다.';
$lang->max_image_size_action_nothing = '초과시 아무 것도 하지 않음';
$lang->max_image_size_action_block = '초과시 업로드 금지';
$lang->max_image_size_action_resize = '초과시 자동 크기 조정';
$lang->max_image_size_admin = '관리자에게도 적용';
$lang->image_quality_adjustment = '이미지 화질';
$lang->about_image_quality_adjustment = '다른 설정에 의해 이미지가 변환될 경우 화질을 조정합니다.<br />75% (표준) 이상으로 설정시 오히려 원본보다 용량이 늘어날 수 있습니다.';
$lang->image_autorotate = '이미지 회전 수정';
$lang->about_image_autorotate = '모바일 기기 등에서 잘못 회전된 이미지를 바로잡습니다.';
$lang->image_remove_exif_data = 'EXIF 제거';
$lang->about_image_remove_exif_data = '프라이버시를 위해 이미지 파일에서 카메라, GPS 정보 등이 포함되어 있는 EXIF 데이터를 삭제합니다.<br />이 옵션을 사용하지 않아도 다른 설정에 의해 이미지가 변환될 경우에도 EXIF 데이터가 삭제될 수 있습니다.';
$lang->image_autoconv_gif2mp4 = 'GIF 변환';
$lang->about_image_autoconv_gif2mp4 = '움직이는 GIF 이미지를 MP4 동영상으로 변환하여 용량 및 트래픽을 절약합니다.<br />구형 브라우저에서는 동영상이 재생되지 않을 수도 있습니다.';
$lang->video_thumbnail = '동영상 섬네일';
$lang->about_video_thumbnail = '업로드된 동영상에서 섬네일 이미지를 추출합니다.';
$lang->video_mp4_gif_time = 'GIF로 취급';
$lang->about_video_mp4_gif_time = '설정된 시간 이하의 길이를 가진 짧고 소리 없는 MP4 동영상을 GIF 이미지로 취급하여 자동 및 반복 재생 상태로 삽입합니다.';
$lang->ffmpeg_path = 'FFmpeg 경로';
$lang->ffprobe_path = 'FFprobe 경로';
$lang->msg_cannot_use_ffmpeg = 'PHP에서 FFmpeg 및 FFprobe를 실행할 수 있어야 합니다.';
$lang->msg_cannot_use_exif = 'PHP Exif 모듈이 필요합니다.';

View file

@ -1,22 +1,28 @@
<query id="insertFile" action="insert">
<tables>
<table name="files" />
</tables>
<columns>
<column name="file_srl" var="file_srl" notnull="notnull" />
<column name="upload_target_srl" var="upload_target_srl" filter="number" default="0" notnull="notnull" />
<column name="sid" var="sid" />
<column name="module_srl" var="module_srl" filter="number" default="0" notnull="notnull" />
<column name="source_filename" var="source_filename" notnull="notnull" minlength="1" maxlength="250" />
<column name="uploaded_filename" var="uploaded_filename" notnull="notnull" minlength="1" maxlength="250" />
<column name="file_size" var="file_size" notnull="notnull" default="0" />
<column name="direct_download" var="direct_download" notnull="notnull" default="N" />
<column name="comment" var="comment" />
<column name="download_count" var="download_count" default="0" />
<column name="member_srl" var="member_srl" default="0" />
<column name="cover_image" var="is_cover" default="N" />
<column name="regdate" var="regdate" default="curdate()" />
<column name="ipaddress" var="ipaddress" default="ipaddress()" />
<column name="isvalid" var="isvalid" default="N" />
</columns>
<tables>
<table name="files" />
</tables>
<columns>
<column name="file_srl" var="file_srl" notnull="notnull" />
<column name="upload_target_srl" var="upload_target_srl" filter="number" default="0" notnull="notnull" />
<column name="sid" var="sid" />
<column name="module_srl" var="module_srl" filter="number" default="0" notnull="notnull" />
<column name="member_srl" var="member_srl" default="0" />
<column name="download_count" var="download_count" default="0" />
<column name="direct_download" var="direct_download" notnull="notnull" default="N" />
<column name="source_filename" var="source_filename" notnull="notnull" minlength="1" maxlength="250" />
<column name="uploaded_filename" var="uploaded_filename" notnull="notnull" minlength="1" maxlength="250" />
<column name="thumbnail_filename" var="thumbnail_filename" />
<column name="file_size" var="file_size" notnull="notnull" default="0" />
<column name="mime_type" var="mime_type" notnull="notnull" />
<column name="original_type" var="original_type" />
<column name="width" var="width" />
<column name="height" var="height" />
<column name="duration" var="duration" />
<column name="comment" var="comment" />
<column name="isvalid" var="isvalid" default="N" />
<column name="cover_image" var="is_cover" default="N" />
<column name="regdate" var="regdate" default="curdate()" />
<column name="ipaddress" var="ipaddress" default="ipaddress()" />
</columns>
</query>

View file

@ -1,18 +1,24 @@
<table name="files">
<column name="file_srl" type="number" size="11" notnull="notnull" primary_key="primary_key" />
<column name="upload_target_srl" type="number" size="11" default="0" notnull="notnull" index="idx_upload_target_srl" />
<column name="upload_target_type" type="char" size="3" index="idx_upload_target_type" />
<column name="sid" type="varchar" size="60" />
<column name="module_srl" type="number" size="11" default="0" notnull="notnull" index="idx_module_srl" />
<column name="member_srl" type="number" size="11" notnull="notnull" index="idx_member_srl" />
<column name="download_count" type="number" size="11" notnull="notnull" default="0" index="idx_download_count" />
<column name="direct_download" type="char" size="1" default="N" notnull="notnull" />
<column name="source_filename" type="varchar" size="250" />
<column name="uploaded_filename" type="varchar" size="250" />
<column name="file_size" type="number" size="11" default="0" notnull="notnull" index="idx_file_size" />
<column name="comment" type="varchar" size="250" />
<column name="isvalid" type="char" size="1" default="N" index="idx_is_valid" />
<column name="cover_image" type="char" size="1" default="N" notnull="notnull" index="idx_list_order" />
<column name="regdate" type="date" index="idx_regdate" />
<column name="ipaddress" type="varchar" size="128" notnull="notnull" index="idx_ipaddress"/>
<column name="file_srl" type="number" size="11" notnull="notnull" primary_key="primary_key" />
<column name="upload_target_srl" type="number" size="11" default="0" notnull="notnull" index="idx_upload_target_srl" />
<column name="upload_target_type" type="char" size="3" index="idx_upload_target_type" />
<column name="sid" type="varchar" size="60" />
<column name="module_srl" type="number" size="11" default="0" notnull="notnull" index="idx_module_srl" />
<column name="member_srl" type="number" size="11" notnull="notnull" index="idx_member_srl" />
<column name="download_count" type="number" size="11" notnull="notnull" default="0" index="idx_download_count" />
<column name="direct_download" type="char" size="1" default="N" notnull="notnull" />
<column name="source_filename" type="varchar" size="250" />
<column name="uploaded_filename" type="varchar" size="250" />
<column name="thumbnail_filename" type="varchar" size="250" />
<column name="file_size" type="number" size="11" default="0" notnull="notnull" index="idx_file_size" />
<column name="mime_type" type="varchar" size="60" notnull="notnull" index="idx_mime_type" />
<column name="original_type" type="varchar" size="60" />
<column name="width" type="number" size="11" />
<column name="height" type="number" size="11" />
<column name="duration" type="number" size="11" />
<column name="comment" type="varchar" size="250" />
<column name="isvalid" type="char" size="1" default="N" index="idx_is_valid" />
<column name="cover_image" type="char" size="1" default="N" notnull="notnull" index="idx_list_order" />
<column name="regdate" type="date" index="idx_regdate" />
<column name="ipaddress" type="varchar" size="128" notnull="notnull" index="idx_ipaddress"/>
</table>

View file

@ -8,121 +8,182 @@
<input type="hidden" name="module" value="file" />
<input type="hidden" name="act" value="procFileAdminInsertModuleConfig" />
<input type="hidden" name="success_return_url" value="{getRequestUriByServerEnviroment()}" />
<input type="hidden" name="target_module_srl" value="{$module_info->module_srl?$module_info->module_srl:$module_srls}" />
<input type="hidden" name="target_module_srl" value="{$module_info->module_srl ?: $module_srls}" />
<div class="x_control-group use_default_file_config">
<label for="allowed_filesize" class="x_control-label">{$lang->use_default_file_config}</label>
<label class="x_control-label">{$lang->use_default_file_config}</label>
<div class="x_controls">
<label for="use_default_file_config" class="x_inline">
<input type="checkbox" name="use_default_file_config" id="use_default_file_config" value="Y" checked="checked"|cond="$file_config->use_default_file_config" />
<input type="checkbox" name="use_default_file_config" id="use_default_file_config" value="Y" checked="checked"|cond="$config->use_default_file_config !== 'N'" />
{$lang->about_use_default_file_config}
</label>
</div>
</div>
<div class="use_custom_file_config" style="display:none"|cond="$file_config->use_default_file_config">
<div class="x_control-group">
<label for="allowed_filesize" class="x_control-label">{$lang->allowed_filesize}</label>
<div class="x_controls">
<input type="number" min="0" name="allowed_filesize" id="allowed_filesize" value="{$file_config->allowed_filesize}" size="7" style="min-width:80px" /> MB
<p class="x_help-block">{sprintf($lang->about_allowed_filesize, getUrl('', 'module', 'admin', 'act', 'dispFileAdminConfig'))}<br />{sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}</p>
<div class="use_custom_file_config" style="display:none"|cond="$config->use_default_file_config !== 'N'">
<div class="x_control-group">
<label for="allowed_filesize" class="x_control-label">{$lang->allowed_filesize}</label>
<div class="x_controls">
<input type="number" min="0" name="allowed_filesize" id="allowed_filesize" value="{$config->allowed_filesize}" size="7" style="min-width:80px" /> MB
<p class="x_help-block">{sprintf($lang->about_allowed_filesize, getUrl('', 'module', 'admin', 'act', 'dispFileAdminConfig'))}<br />{sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}</p>
</div>
</div>
<div class="x_control-group">
<label for="allowed_attach_size" class="x_control-label">{$lang->allowed_attach_size}</label>
<div class="x_controls">
<input type="number" min="0" name="allowed_attach_size" id="allowed_attach_size" value="{$config->allowed_attach_size}" size="7" style="min-width:80px" /> MB
<p class="x_help-block">{sprintf($lang->about_allowed_attach_size, getUrl('', 'module', 'admin', 'act', 'dispFileAdminConfig'))}<br />{sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}</p>
</div>
</div>
<div class="x_control-group">
<label for="allowed_filetypes" class="x_control-label">{$lang->allowed_filetypes}</label>
<div class="x_controls">
<input type="text" name="allowed_filetypes" id="allowed_filetypes" value="{implode(', ', $config->allowed_extensions)}" />
<p class="x_help-block">{$lang->about_allowed_filetypes}</p>
</div>
</div>
</div>
<div class="x_control-group">
<label for="allowed_attach_size" class="x_control-label">{$lang->allowed_attach_size}</label>
<div class="x_control-group use_default_file_config">
<label class="x_control-label">{$lang->use_image_default_file_config}</label>
<div class="x_controls">
<input type="number" min="0" name="allowed_attach_size" id="allowed_attach_size" value="{$file_config->allowed_attach_size}" size="7" style="min-width:80px" /> MB
<p class="x_help-block">{sprintf($lang->about_allowed_attach_size, getUrl('', 'module', 'admin', 'act', 'dispFileAdminConfig'))}<br />{sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}</p>
<label for="use_image_default_file_config" class="x_inline">
<input type="checkbox" name="use_image_default_file_config" id="use_image_default_file_config" value="Y" checked="checked"|cond="$config->use_image_default_file_config !== 'N'" />
{$lang->about_use_image_default_file_config}
</label>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->max_image_size}</label>
<div class="x_controls">
<input type="number" min="0" name="max_image_width" id="max_image_width" value="{$file_config->max_image_width}" size="7" style="min-width:80px" /> &times;
<input type="number" min="0" name="max_image_height" id="max_image_height" value="{$file_config->max_image_height}" size="7" style="min-width:80px" /> px &nbsp;
<select name="max_image_size_action" id="max_image_size_action">
<option value="" selected="selected"|cond="$file_config->max_image_size_action == ''">{$lang->max_image_size_action_nothing}</option>
<option value="block" selected="selected"|cond="$file_config->max_image_size_action == 'block'">{$lang->max_image_size_action_block}</option>
<option value="resize" selected="selected"|cond="$file_config->max_image_size_action == 'resize'">{$lang->max_image_size_action_resize}</option>
</select>
<select name="max_image_size_quality" id="max_image_size_quality" style="width:100px;min-width:100px">
{@ $file_config->max_image_size_quality = $file_config->max_image_size_quality ?: 75}
<!--@for($q = 50; $q <= 100; $q += 5)-->
<option value="{$q}" selected="selected"|cond="$file_config->max_image_size_quality == $q">{$lang->image_resize_quality} {$q}%</option>
<!--@endfor-->
</select>
<p class="x_help-block">
{$lang->about_max_image_size}
<label for="max_image_size_admin">
<input type="checkbox" name="max_image_size_admin" id="max_image_size_admin" value="Y" checked="checked"|cond="$file_config->max_image_size_admin === 'Y'" />
{$lang->max_image_size_admin}
<div class="use_custom_image_file_config" style="display:none"|cond="$config->use_image_default_file_config !== 'N'">
<div class="x_control-group">
<label class="x_control-label">{$lang->image_autoconv}</label>
<div class="x_controls">
<label for="image_autoconv_bmp2jpg">
<input type="checkbox" name="image_autoconv_bmp2jpg" id="image_autoconv_bmp2jpg" value="Y" checked="checked"|cond="$config->image_autoconv['bmp2jpg']" disabled="disabled"|cond="!function_exists('imagebmp')" />
{$lang->image_autoconv_bmp2jpg}
</label>
</p>
<label for="image_autoconv_png2jpg">
<input type="checkbox" name="image_autoconv_png2jpg" id="image_autoconv_png2jpg" value="Y" checked="checked"|cond="$config->image_autoconv['png2jpg']" disabled="disabled"|cond="!function_exists('imagepng')" />
{$lang->image_autoconv_png2jpg}
</label>
<label for="image_autoconv_webp2jpg">
<input type="checkbox" name="image_autoconv_webp2jpg" id="image_autoconv_webp2jpg" value="Y" checked="checked"|cond="$config->image_autoconv['webp2jpg']" disabled="disabled"|cond="!function_exists('imagewebp')" />
{$lang->image_autoconv_webp2jpg}
</label>
<p class="x_help-block">{$lang->about_image_autoconv}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->max_image_size}</label>
<div class="x_controls">
<input type="number" min="0" name="max_image_width" id="max_image_width" value="{$config->max_image_width}" size="7" style="min-width:80px" /> &times;
<input type="number" min="0" name="max_image_height" id="max_image_height" value="{$config->max_image_height}" size="7" style="min-width:80px" /> px &nbsp;
<select name="max_image_size_action" id="max_image_size_action">
<option value="">{$lang->max_image_size_action_nothing}</option>
<option value="block" selected="selected"|cond="$config->max_image_size_action === 'block'">{$lang->max_image_size_action_block}</option>
<option value="resize" selected="selected"|cond="$config->max_image_size_action === 'resize'">{$lang->max_image_size_action_resize}</option>
</select>
<p class="x_help-block">
{$lang->about_max_image_size}
<label for="max_image_size_admin">
<input type="checkbox" name="max_image_size_admin" id="max_image_size_admin" value="Y" checked="checked"|cond="$config->max_image_size_admin === 'Y'" />
{$lang->max_image_size_admin}
</label>
</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->image_quality_adjustment}</label>
<div class="x_controls">
<select name="image_quality_adjustment" style="min-width:80px">
<!--@for($q = 50; $q <= 100; $q += 5)-->
<option value="{$q}" selected="selected"|cond="$config->image_quality_adjustment === $q">{$q}%<!--@if($q === 75)--> ({$lang->standard})<!--@end--></option>
<!--@endfor-->
</select>
<p class="x_help-block">{$lang->about_image_quality_adjustment}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->image_autorotate}</label>
<div class="x_controls">
<label for="image_autorotate_Y" class="x_inline">
<input type="radio" name="image_autorotate" id="image_autorotate_Y" value="Y" checked="checked"|cond="$config->image_autorotate === true" disabled="disabled"|cond="!function_exists('exif_read_data')" />
{$lang->cmd_yes}
</label>
<label for="image_autorotate_N" class="x_inline">
<input type="radio" name="image_autorotate" id="image_autorotate_N" value="N" checked="checked"|cond="$config->image_autorotate !== true" disabled="disabled"|cond="!function_exists('exif_read_data')" />
{$lang->cmd_no}
</label>
<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 class="x_control-group">
<label class="x_control-label">{$lang->image_remove_exif_data}</label>
<div class="x_controls">
<label for="image_remove_exif_data_Y" class="x_inline">
<input type="radio" name="image_remove_exif_data" id="image_remove_exif_data_Y" value="Y" checked="checked"|cond="$config->image_remove_exif_data === true" disabled="disabled"|cond="!function_exists('exif_read_data')" />
{$lang->cmd_yes}
</label>
<label for="image_remove_exif_data_N" class="x_inline">
<input type="radio" name="image_remove_exif_data" id="image_remove_exif_data_N" value="N" checked="checked"|cond="$config->image_remove_exif_data !== true" disabled="disabled"|cond="!function_exists('exif_read_data')" />
{$lang->cmd_no}
</label>
<p class="x_help-block">{$lang->about_image_remove_exif_data}</p>
<p class="x_text-info" cond="!function_exists('exif_read_data')">{$lang->msg_cannot_use_exif}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->image_autoconv_gif2mp4}</label>
<div class="x_controls">
<label for="image_autoconv_gif2mp4_Y" class="x_inline">
<input type="radio" name="image_autoconv_gif2mp4" id="image_autoconv_gif2mp4_Y" value="Y" checked="checked"|cond="$config->image_autoconv['gif2mp4'] === true" disabled="disabled"|cond="!$is_ffmpeg" />
{$lang->cmd_yes}
</label>
<label for="image_autoconv_gif2mp4_N" class="x_inline">
<input type="radio" name="image_autoconv_gif2mp4" id="image_autoconv_gif2mp4_N" value="N" checked="checked"|cond="$config->image_autoconv['gif2mp4'] !== true" disabled="disabled"|cond="!$is_ffmpeg" />
{$lang->cmd_no}
</label>
<p class="x_help-block">{$lang->about_image_autoconv_gif2mp4}</p>
<p class="x_text-info" cond="!$is_ffmpeg">{$lang->msg_cannot_use_ffmpeg}</p>
</div>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->image_autoconv}</label>
<div class="x_control-group use_default_file_config">
<label class="x_control-label">{$lang->use_video_default_file_config}</label>
<div class="x_controls">
<label for="image_autoconv_bmp2jpg" class="x_inline">
<input type="checkbox" name="image_autoconv_bmp2jpg" id="image_autoconv_bmp2jpg" value="Y" checked="checked"|cond="$file_config->image_autoconv['bmp2jpg']" disabled="disabled"|cond="!function_exists('imagebmp')" />
{$lang->image_autoconv_bmp2jpg}
<label for="use_video_default_file_config" class="x_inline">
<input type="checkbox" name="use_video_default_file_config" id="use_video_default_file_config" value="Y" checked="checked"|cond="$config->use_video_default_file_config !== 'N'" />
{$lang->about_use_video_default_file_config}
</label>
<label for="image_autoconv_png2jpg" class="x_inline">
<input type="checkbox" name="image_autoconv_png2jpg" id="image_autoconv_png2jpg" value="Y" checked="checked"|cond="$file_config->image_autoconv['png2jpg']" disabled="disabled"|cond="!function_exists('imagepng')" />
{$lang->image_autoconv_png2jpg}
</label>
<label for="image_autoconv_webp2jpg" class="x_inline">
<input type="checkbox" name="image_autoconv_webp2jpg" id="image_autoconv_webp2jpg" value="Y" checked="checked"|cond="$file_config->image_autoconv['webp2jpg']" disabled="disabled"|cond="!function_exists('imagewebp')" />
{$lang->image_autoconv_webp2jpg}
</label>
<select name="image_autoconv_quality" id="image_autoconv_quality" style="width:100px;min-width:100px">
{@ $file_config->image_autoconv_quality = $file_config->image_autoconv_quality ?: 75}
<!--@for($q = 50; $q <= 100; $q += 5)-->
<option value="{$q}" selected="selected"|cond="$file_config->image_autoconv_quality == $q">{$lang->image_resize_quality} {$q}%</option>
<!--@endfor-->
</select>
<p class="x_help-block" style="margin-bottom:10px">{$lang->about_image_autoconv}</p>
<label for="image_autoconv_gif2mp4" class="x_inline">
<input type="checkbox" name="image_autoconv_gif2mp4" id="image_autoconv_gif2mp4" value="Y" checked="checked"|cond="$file_config->image_autoconv['gif2mp4']" disabled="disabled"|cond="!function_exists('exec')" />
{$lang->image_autoconv_gif2mp4}
</label>
<input type="text" name="ffmpeg_command" id="ffmpeg_command" value="{$file_config->ffmpeg_command ?: '/usr/bin/ffmpeg'}" placeholder="{$lang->ffmpeg_path}" />
<p class="x_help-block">{$lang->about_image_autoconv_mp4}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->image_autorotate}</label>
<div class="x_controls">
<label for="image_autorotate_Y" class="x_inline">
<input type="radio" name="image_autorotate" id="image_autorotate_Y" value="Y" checked="checked"|cond="$file_config->image_autorotate === true" disabled="disabled"|cond="!function_exists('exif_read_data')" />
{$lang->cmd_yes}
</label>
<label for="image_autorotate_N" class="x_inline">
<input type="radio" name="image_autorotate" id="image_autorotate_N" value="N" checked="checked"|cond="$file_config->image_autorotate !== true" disabled="disabled"|cond="!function_exists('exif_read_data')" />
{$lang->cmd_no}
</label>
<select name="image_autorotate_quality" id="image_autorotate_quality" style="width:100px;min-width:100px">
{@ $file_config->image_autorotate_quality = $file_config->image_autorotate_quality ?: 75}
<!--@for($q = 50; $q <= 100; $q += 5)-->
<option value="{$q}" selected="selected"|cond="$file_config->image_autorotate_quality == $q">{$lang->image_resize_quality} {$q}%</option>
<!--@endfor-->
</select>
<p class="x_help-block">{$lang->about_image_autorotate}</p>
<div class="use_custom_video_file_config" style="display:none"|cond="$config->use_video_default_file_config !== 'N'">
<div class="x_control-group">
<label class="x_control-label">{$lang->video_thumbnail}</label>
<div class="x_controls">
<label for="video_thumbnail_Y" class="x_inline">
<input type="radio" name="video_thumbnail" id="video_thumbnail_Y" value="Y" checked="checked"|cond="$config->video_thumbnail === true" disabled="disabled"|cond="!$is_ffmpeg" />
{$lang->cmd_yes}
</label>
<label for="video_thumbnail_N" class="x_inline">
<input type="radio" name="video_thumbnail" id="video_thumbnail_N" value="N" checked="checked"|cond="$config->video_thumbnail !== true" disabled="disabled"|cond="!$is_ffmpeg" />
{$lang->cmd_no}
</label>
<p class="x_help-block">{$lang->about_video_thumbnail}</p>
<p class="x_text-info" cond="!$is_ffmpeg">{$lang->msg_cannot_use_ffmpeg}</p>
</div>
</div>
</div>
<div class="x_control-group">
<label for="allowed_filetypes" class="x_control-label">{$lang->allowed_filetypes}</label>
<div class="x_controls">
<input type="text" name="allowed_filetypes" id="allowed_filetypes" value="{implode(', ', $file_config->allowed_extensions ?: [])}" />
<p class="x_help-block">{$lang->about_allowed_filetypes}</p>
<div class="x_control-group">
<label class="x_control-label">{$lang->video_mp4_gif_time}</label>
<div class="x_controls">
<input type="number" min="0" name="video_mp4_gif_time" value="{$config->video_mp4_gif_time}" style="min-width:80px" disabled="disabled"|cond="!$is_ffmpeg" /> {$lang->unit_sec}
<p class="x_help-block">{$lang->about_video_mp4_gif_time}</p>
<p class="x_text-info" cond="!$is_ffmpeg">{$lang->msg_cannot_use_ffmpeg}</p>
</div>
</div>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->enable_download_group}</label>
<div class="x_controls">
<label loop="$group_list => $k, $v" for="grant_{$key}_{$v->group_srl}"><input type="checkbox" name="download_grant[]" value="{$v->group_srl}" id="grant_{$key}_{$v->group_srl}" checked="checked"|cond="in_array($v->group_srl, $file_config->download_grant)" /> {$v->title}</label>
<label loop="$group_list => $k, $v" for="grant_{$key}_{$v->group_srl}"><input type="checkbox" name="download_grant[]" value="{$v->group_srl}" id="grant_{$key}_{$v->group_srl}" checked="checked"|cond="in_array($v->group_srl, $config->download_grant)" /> {$v->title}</label>
</div>
</div>
<div class="btnArea">

View file

@ -1,6 +1,5 @@
(function($) {
$(function() {
$('#use_default_file_config').on('change', function() {
if ($(this).is(':checked')) {
$('.use_custom_file_config').hide();
@ -8,5 +7,19 @@
$('.use_custom_file_config').show();
}
});
$('#use_image_default_file_config').on('change', function() {
if ($(this).is(':checked')) {
$('.use_custom_image_file_config').hide();
} else {
$('.use_custom_image_file_config').show();
}
});
$('#use_video_default_file_config').on('change', function() {
if ($(this).is(':checked')) {
$('.use_custom_video_file_config').hide();
} else {
$('.use_custom_video_file_config').show();
}
});
});
})(jQuery);

View file

@ -8,6 +8,7 @@
<input type="hidden" name="module" value="file" />
<input type="hidden" name="act" value="procFileAdminInsertUploadConfig" />
<input type="hidden" name="xe_validator_id" value="modules/file/tpl/upload_config/1" />
<div class="x_control-group">
<label for="allowed_filesize" class="x_control-label">{$lang->allowed_filesize}</label>
<div class="x_controls">
@ -22,88 +23,151 @@
<p class="x_help-block">{$lang->about_allowed_attach_size_global}<br />{sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->max_image_size}</label>
<div class="x_controls">
<input type="number" min="0" name="max_image_width" id="max_image_width" value="{$config->max_image_width}" size="7" style="min-width:80px" /> &times;
<input type="number" min="0" name="max_image_height" id="max_image_height" value="{$config->max_image_height}" size="7" style="min-width:80px" /> px &nbsp;
<select name="max_image_size_action" id="max_image_size_action">
<option value="" selected="selected"|cond="$config->max_image_size_action == ''">{$lang->max_image_size_action_nothing}</option>
<option value="block" selected="selected"|cond="$config->max_image_size_action == 'block'">{$lang->max_image_size_action_block}</option>
<option value="resize" selected="selected"|cond="$config->max_image_size_action == 'resize'">{$lang->max_image_size_action_resize}</option>
</select>
<select name="max_image_size_quality" id="max_image_size_quality" style="width:100px;min-width:100px">
{@ $config->max_image_size_quality = $config->max_image_size_quality ?: 75}
<!--@for($q = 50; $q <= 100; $q += 5)-->
<option value="{$q}" selected="selected"|cond="$config->max_image_size_quality == $q">{$lang->image_resize_quality} {$q}%</option>
<!--@endfor-->
</select>
<p class="x_help-block">
{$lang->about_max_image_size}
<label for="max_image_size_admin">
<input type="checkbox" name="max_image_size_admin" id="max_image_size_admin" value="Y" checked="checked"|cond="$config->max_image_size_admin === 'Y'" />
{$lang->max_image_size_admin}
</label>
</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->image_autoconv}</label>
<div class="x_controls">
<label for="image_autoconv_bmp2jpg" class="x_inline">
<input type="checkbox" name="image_autoconv_bmp2jpg" id="image_autoconv_bmp2jpg" value="Y" checked="checked"|cond="$config->image_autoconv['bmp2jpg']" disabled="disabled"|cond="!function_exists('imagebmp')" />
{$lang->image_autoconv_bmp2jpg}
</label>
<label for="image_autoconv_png2jpg" class="x_inline">
<input type="checkbox" name="image_autoconv_png2jpg" id="image_autoconv_png2jpg" value="Y" checked="checked"|cond="$config->image_autoconv['png2jpg']" disabled="disabled"|cond="!function_exists('imagepng')" />
{$lang->image_autoconv_png2jpg}
</label>
<label for="image_autoconv_webp2jpg" class="x_inline">
<input type="checkbox" name="image_autoconv_webp2jpg" id="image_autoconv_webp2jpg" value="Y" checked="checked"|cond="$config->image_autoconv['webp2jpg']" disabled="disabled"|cond="!function_exists('imagewebp')" />
{$lang->image_autoconv_webp2jpg}
</label>
<select name="image_autoconv_quality" id="image_autoconv_quality" style="width:100px;min-width:100px">
{@ $config->image_autoconv_quality = $config->image_autoconv_quality ?: 75}
<!--@for($q = 50; $q <= 100; $q += 5)-->
<option value="{$q}" selected="selected"|cond="$config->image_autoconv_quality == $q">{$lang->image_resize_quality} {$q}%</option>
<!--@endfor-->
</select>
<p class="x_help-block" style="margin-bottom:10px">{$lang->about_image_autoconv}</p>
<label for="image_autoconv_gif2mp4" class="x_inline">
<input type="checkbox" name="image_autoconv_gif2mp4" id="image_autoconv_gif2mp4" value="Y" checked="checked"|cond="$config->image_autoconv['gif2mp4']" disabled="disabled"|cond="!function_exists('exec')" />
{$lang->image_autoconv_gif2mp4}
</label>
<input type="text" name="ffmpeg_command" id="ffmpeg_command" value="{$config->ffmpeg_command ?: '/usr/bin/ffmpeg'}" placeholder="{$lang->ffmpeg_path}" />
<p class="x_help-block">{$lang->about_image_autoconv_mp4}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->image_autorotate}</label>
<div class="x_controls">
<label for="image_autorotate_Y" class="x_inline">
<input type="radio" name="image_autorotate" id="image_autorotate_Y" value="Y" checked="checked"|cond="$config->image_autorotate === true" disabled="disabled"|cond="!function_exists('exif_read_data')" />
{$lang->cmd_yes}
</label>
<label for="image_autorotate_N" class="x_inline">
<input type="radio" name="image_autorotate" id="image_autorotate_N" value="N" checked="checked"|cond="$config->image_autorotate !== true" disabled="disabled"|cond="!function_exists('exif_read_data')" />
{$lang->cmd_no}
</label>
<select name="image_autorotate_quality" id="image_autorotate_quality" style="width:100px;min-width:100px">
{@ $config->image_autorotate_quality = $config->image_autorotate_quality ?: 75}
<!--@for($q = 50; $q <= 100; $q += 5)-->
<option value="{$q}" selected="selected"|cond="$config->image_autorotate_quality == $q">{$lang->image_resize_quality} {$q}%</option>
<!--@endfor-->
</select>
<p class="x_help-block">{$lang->about_image_autorotate}</p>
</div>
</div>
<div class="x_control-group">
<label for="allowedFiletypes" class="x_control-label">{$lang->allowed_filetypes}</label>
<div class="x_controls">
<input id="allowedFiletypes" type="text" name="allowed_filetypes" value="{implode(', ', $config->allowed_extensions ?: [])}" />
<input id="allowedFiletypes" type="text" name="allowed_filetypes" value="{implode(', ', $config->allowed_extensions)}" />
<p class="x_help-block">{$lang->about_allowed_filetypes}</p>
</div>
</div>
<section class="section">
<h1>{$lang->image}</h1>
<div class="x_control-group">
<label class="x_control-label">{$lang->image_autoconv}</label>
<div class="x_controls">
<label for="image_autoconv_bmp2jpg">
<input type="checkbox" name="image_autoconv_bmp2jpg" id="image_autoconv_bmp2jpg" value="Y" checked="checked"|cond="$config->image_autoconv['bmp2jpg']" disabled="disabled"|cond="!function_exists('imagebmp')" />
{$lang->image_autoconv_bmp2jpg}
</label>
<label for="image_autoconv_png2jpg">
<input type="checkbox" name="image_autoconv_png2jpg" id="image_autoconv_png2jpg" value="Y" checked="checked"|cond="$config->image_autoconv['png2jpg']" disabled="disabled"|cond="!function_exists('imagepng')" />
{$lang->image_autoconv_png2jpg}
</label>
<label for="image_autoconv_webp2jpg">
<input type="checkbox" name="image_autoconv_webp2jpg" id="image_autoconv_webp2jpg" value="Y" checked="checked"|cond="$config->image_autoconv['webp2jpg']" disabled="disabled"|cond="!function_exists('imagewebp')" />
{$lang->image_autoconv_webp2jpg}
</label>
<p class="x_help-block">{$lang->about_image_autoconv}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->max_image_size}</label>
<div class="x_controls">
<input type="number" min="0" name="max_image_width" id="max_image_width" value="{$config->max_image_width}" size="7" style="min-width:80px" /> &times;
<input type="number" min="0" name="max_image_height" id="max_image_height" value="{$config->max_image_height}" size="7" style="min-width:80px" /> px &nbsp;
<select name="max_image_size_action" id="max_image_size_action">
<option value="">{$lang->max_image_size_action_nothing}</option>
<option value="block" selected="selected"|cond="$config->max_image_size_action === 'block'">{$lang->max_image_size_action_block}</option>
<option value="resize" selected="selected"|cond="$config->max_image_size_action === 'resize'">{$lang->max_image_size_action_resize}</option>
</select>
<p class="x_help-block">
{$lang->about_max_image_size}
<label for="max_image_size_admin">
<input type="checkbox" name="max_image_size_admin" id="max_image_size_admin" value="Y" checked="checked"|cond="$config->max_image_size_admin === 'Y'" />
{$lang->max_image_size_admin}
</label>
</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->image_quality_adjustment}</label>
<div class="x_controls">
<select name="image_quality_adjustment" style="min-width:80px">
<!--@for($q = 50; $q <= 100; $q += 5)-->
<option value="{$q}" selected="selected"|cond="$config->image_quality_adjustment === $q">{$q}%<!--@if($q === 75)--> ({$lang->standard})<!--@end--></option>
<!--@endfor-->
</select>
<p class="x_help-block">{$lang->about_image_quality_adjustment}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->image_autorotate}</label>
<div class="x_controls">
<label for="image_autorotate_Y" class="x_inline">
<input type="radio" name="image_autorotate" id="image_autorotate_Y" value="Y" checked="checked"|cond="$config->image_autorotate === true" disabled="disabled"|cond="!function_exists('exif_read_data')" />
{$lang->cmd_yes}
</label>
<label for="image_autorotate_N" class="x_inline">
<input type="radio" name="image_autorotate" id="image_autorotate_N" value="N" checked="checked"|cond="$config->image_autorotate !== true" disabled="disabled"|cond="!function_exists('exif_read_data')" />
{$lang->cmd_no}
</label>
<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 class="x_control-group">
<label class="x_control-label">{$lang->image_remove_exif_data}</label>
<div class="x_controls">
<label for="image_remove_exif_data_Y" class="x_inline">
<input type="radio" name="image_remove_exif_data" id="image_remove_exif_data_Y" value="Y" checked="checked"|cond="$config->image_remove_exif_data === true" disabled="disabled"|cond="!function_exists('exif_read_data')" />
{$lang->cmd_yes}
</label>
<label for="image_remove_exif_data_N" class="x_inline">
<input type="radio" name="image_remove_exif_data" id="image_remove_exif_data_N" value="N" checked="checked"|cond="$config->image_remove_exif_data !== true" disabled="disabled"|cond="!function_exists('exif_read_data')" />
{$lang->cmd_no}
</label>
<p class="x_help-block">{$lang->about_image_remove_exif_data}</p>
<p class="x_text-info" cond="!function_exists('exif_read_data')">{$lang->msg_cannot_use_exif}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->image_autoconv_gif2mp4}</label>
<div class="x_controls">
<label for="image_autoconv_gif2mp4_Y" class="x_inline">
<input type="radio" name="image_autoconv_gif2mp4" id="image_autoconv_gif2mp4_Y" value="Y" checked="checked"|cond="$config->image_autoconv['gif2mp4'] === true" disabled="disabled"|cond="!$is_ffmpeg" />
{$lang->cmd_yes}
</label>
<label for="image_autoconv_gif2mp4_N" class="x_inline">
<input type="radio" name="image_autoconv_gif2mp4" id="image_autoconv_gif2mp4_N" value="N" checked="checked"|cond="$config->image_autoconv['gif2mp4'] !== true" disabled="disabled"|cond="!$is_ffmpeg" />
{$lang->cmd_no}
</label>
<p class="x_help-block">{$lang->about_image_autoconv_gif2mp4}</p>
<p class="x_text-info" cond="!$is_ffmpeg">{$lang->msg_cannot_use_ffmpeg}</p>
</div>
</div>
</section>
<section class="section">
<h1>{$lang->video}</h1>
<div class="x_control-group">
<label class="x_control-label">{$lang->video_thumbnail}</label>
<div class="x_controls">
<label for="video_thumbnail_Y" class="x_inline">
<input type="radio" name="video_thumbnail" id="video_thumbnail_Y" value="Y" checked="checked"|cond="$config->video_thumbnail === true" disabled="disabled"|cond="!$is_ffmpeg" />
{$lang->cmd_yes}
</label>
<label for="video_thumbnail_N" class="x_inline">
<input type="radio" name="video_thumbnail" id="video_thumbnail_N" value="N" checked="checked"|cond="$config->video_thumbnail !== true" disabled="disabled"|cond="!$is_ffmpeg" />
{$lang->cmd_no}
</label>
<p class="x_help-block">{$lang->about_video_thumbnail}</p>
<p class="x_text-info" cond="!$is_ffmpeg">{$lang->msg_cannot_use_ffmpeg}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->video_mp4_gif_time}</label>
<div class="x_controls">
<input type="number" min="0" name="video_mp4_gif_time" value="{$config->video_mp4_gif_time}" style="min-width:80px" disabled="disabled"|cond="!$is_ffmpeg" /> {$lang->unit_sec}
<p class="x_help-block">{$lang->about_video_mp4_gif_time}</p>
<p class="x_text-info" cond="!$is_ffmpeg">{$lang->msg_cannot_use_ffmpeg}</p>
</div>
</div>
</section>
<section class="section">
<h1>FFmpeg</h1>
<div class="x_control-group">
<label class="x_control-label">{$lang->ffmpeg_path}</label>
<div class="x_controls">
<input type="text" name="ffmpeg_command" value="{$config->ffmpeg_command}" />
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->ffprobe_path}</label>
<div class="x_controls">
<input type="text" name="ffprobe_command" value="{$config->ffprobe_command}" />
</div>
</div>
</section>
<div class="x_clearfix btnArea">
<div class="x_pull-right">
<button type="submit" class="x_btn x_btn-primary">{$lang->cmd_save}</button>

View file

@ -16,7 +16,11 @@ class MIMETest extends \Codeception\TestCase\Test
$this->assertEquals('odt', Rhymix\Framework\MIME::getExtensionByType('application/vnd.oasis.opendocument.text'));
$this->assertEquals('jpg', Rhymix\Framework\MIME::getExtensionByType('image/jpeg'));
$this->assertEquals('mpeg', Rhymix\Framework\MIME::getExtensionByType('video/mpeg'));
$this->assertEquals('mpg', Rhymix\Framework\MIME::getExtensionByType('video/mpeg'));
$this->assertEquals('ogg', Rhymix\Framework\MIME::getExtensionByType('audio/ogg'));
$this->assertEquals('ogv', Rhymix\Framework\MIME::getExtensionByType('video/ogg'));
$this->assertEquals('mp4', Rhymix\Framework\MIME::getExtensionByType('audio/mp4'));
$this->assertEquals('mp4', Rhymix\Framework\MIME::getExtensionByType('video/mp4'));
$this->assertFalse(Rhymix\Framework\MIME::getExtensionByType('application/octet-stream'));
}
}