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

@ -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>