Merge pull request #1182 from kijin/develop

파일 업로드 관련 기능 개선
This commit is contained in:
Kijin Sung 2019-08-01 21:01:46 +09:00 committed by GitHub
commit 16cf00154d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 726 additions and 185 deletions

View file

@ -479,9 +479,11 @@ class FileHandler
* @param int $resize_height Height to resize
* @param string $target_type If $target_type is set (gif, jpg, png, bmp), result image will be saved as target type
* @param string $thumbnail_type Thumbnail type(crop, ratio)
* @param int $quality Compression ratio (0~100)
* @param int $rotate Rotation degrees (0~360)
* @return bool TRUE: success, FALSE: failed
*/
public static function createImageFile($source_file, $target_file, $resize_width = 0, $resize_height = 0, $target_type = '', $thumbnail_type = 'crop')
public static function createImageFile($source_file, $target_file, $resize_width = 0, $resize_height = 0, $target_type = '', $thumbnail_type = 'crop', $quality = 100, $rotate = 0)
{
// check params
if (($source_file = self::exists($source_file)) === FALSE)
@ -527,6 +529,12 @@ class FileHandler
case '6' :
$type = 'bmp';
break;
case '8' :
$type = 'wbmp';
break;
case '18' :
$type = 'webp';
break;
default :
return;
}
@ -537,49 +545,6 @@ class FileHandler
}
$target_type = strtolower($target_type);
// if original image is larger than specified size to resize, calculate the ratio
$width_per = ($resize_width > 0 && $width >= $resize_width) ? $resize_width / $width : 1;
$height_per = ($resize_height > 0 && $height >= $resize_height) ? $resize_height / $height : 1;
$per = NULL;
if($thumbnail_type == 'ratio')
{
$per = ($width_per > $height_per) ? $height_per : $width_per;
$resize_width = $width * $per;
$resize_height = $height * $per;
}
else
{
$per = ($width_per < $height_per) ? $height_per : $width_per;
}
// create temporary image with target size
$thumb = NULL;
if(function_exists('imagecreateTRUEcolor'))
{
$thumb = imagecreateTRUEcolor($resize_width, $resize_height);
}
else if(function_exists('imagecreate'))
{
$thumb = imagecreate($resize_width, $resize_height);
}
if(!$thumb)
{
return FALSE;
}
if($target_type == 'png' && function_exists('imagecolorallocatealpha') && function_exists('imagesavealpha') && function_exists('imagealphablending'))
{
imagefill($thumb, 0, 0, imagecolorallocatealpha($thumb, 0, 0, 0, 127));
imagesavealpha($thumb, TRUE);
imagealphablending($thumb, TRUE);
}
else
{
imagefilledrectangle($thumb, 0, 0, $resize_width - 1, $resize_height - 1, imagecolorallocate($thumb, 255, 255, 255));
}
// create temporary image having original type
$source = NULL;
switch($type)
@ -603,13 +568,24 @@ class FileHandler
$source = @imagecreatefrompng($source_file);
}
break;
case 'wbmp' :
case 'bmp' :
if(function_exists('imagecreatefrombmp'))
{
$source = @imagecreatefrombmp($source_file);
}
break;
case 'wbmp' :
if(function_exists('imagecreatefromwbmp'))
{
$source = @imagecreatefromwbmp($source_file);
}
break;
case 'webp' :
if(function_exists('imagecreatefromwebp'))
{
$source = @imagecreatefromwebp($source_file);
}
break;
}
if(!$source)
@ -618,27 +594,86 @@ class FileHandler
return FALSE;
}
// resize original image and put it into temporary image
$new_width = (int) ($width * $per);
$new_height = (int) ($height * $per);
$x = 0;
$y = 0;
if($thumbnail_type == 'crop')
// Rotate image
if ($rotate)
{
$x = (int) ($resize_width / 2 - $new_width / 2);
$y = (int) ($resize_height / 2 - $new_height / 2);
$source = imagerotate($source, $rotate, 0);
$width = imagesx($source);
$height = imagesy($source);
}
if(function_exists('imagecopyresampled'))
// If resize not needed, skip thumbnail generation
if ($width == $resize_width && $height == $resize_height)
{
imagecopyresampled($thumb, $source, $x, $y, 0, 0, $new_width, $new_height, $width, $height);
$thumb = &$source;
}
else
{
imagecopyresized($thumb, $source, $x, $y, 0, 0, $new_width, $new_height, $width, $height);
}
// if original image is larger than specified size to resize, calculate the ratio
$width_per = ($resize_width > 0 && $width >= $resize_width) ? $resize_width / $width : 1;
$height_per = ($resize_height > 0 && $height >= $resize_height) ? $resize_height / $height : 1;
$per = NULL;
if($thumbnail_type == 'ratio')
{
$per = ($width_per > $height_per) ? $height_per : $width_per;
$resize_width = $width * $per;
$resize_height = $height * $per;
}
else
{
$per = ($width_per < $height_per) ? $height_per : $width_per;
}
// create temporary image with target size
$thumb = NULL;
if(function_exists('imagecreateTRUEcolor'))
{
$thumb = imagecreateTRUEcolor($resize_width, $resize_height);
}
else if(function_exists('imagecreate'))
{
$thumb = imagecreate($resize_width, $resize_height);
}
if(!$thumb)
{
return FALSE;
}
if($target_type == 'png' && function_exists('imagecolorallocatealpha') && function_exists('imagesavealpha') && function_exists('imagealphablending'))
{
imagefill($thumb, 0, 0, imagecolorallocatealpha($thumb, 0, 0, 0, 127));
imagesavealpha($thumb, TRUE);
imagealphablending($thumb, TRUE);
}
else
{
imagefilledrectangle($thumb, 0, 0, $resize_width - 1, $resize_height - 1, imagecolorallocate($thumb, 255, 255, 255));
}
// resize original image and put it into temporary image
$new_width = (int) ($width * $per);
$new_height = (int) ($height * $per);
$x = 0;
$y = 0;
if($thumbnail_type == 'crop')
{
$x = (int) ($resize_width / 2 - $new_width / 2);
$y = (int) ($resize_height / 2 - $new_height / 2);
}
if(function_exists('imagecopyresampled'))
{
imagecopyresampled($thumb, $source, $x, $y, 0, 0, $new_width, $new_height, $width, $height);
}
else
{
imagecopyresized($thumb, $source, $x, $y, 0, 0, $new_width, $new_height, $width, $height);
}
}
// create directory
self::makeDir(dirname($target_file));
@ -656,7 +691,7 @@ class FileHandler
case 'jpg' :
if(function_exists('imagejpeg'))
{
$output = imagejpeg($thumb, $target_file, 100);
$output = imagejpeg($thumb, $target_file, $quality);
}
break;
case 'png' :
@ -665,11 +700,22 @@ class FileHandler
$output = imagepng($thumb, $target_file, 9);
}
break;
case 'wbmp' :
case 'bmp' :
if(function_exists('imagebmp'))
{
$output = imagebmp($thumb, $target_file);
}
break;
case 'wbmp' :
if(function_exists('imagewbmp'))
{
$output = imagewbmp($thumb, $target_file, 100);
$output = imagewbmp($thumb, $target_file);
}
break;
case 'webp' :
if(function_exists('imagewebp'))
{
$output = imagewebp($thumb, $target_file);
}
break;
}

View file

@ -372,12 +372,12 @@
data.uploadTargetSrl = res.uploadTargetSrl;
// @TODO 정리
$container.find('.allowed_filetypes').text(res.allowed_filetypes);
$container.find('.allowed_filetypes').text(res.allowed_extensions.join(', '));
$container.find('.allowed_filesize').text(res.allowed_filesize);
$container.find('.allowed_attach_size').text(res.allowed_attach_size);
$container.find('.attached_size').text(res.attached_size);
$container.find('.file_count').text(res.files.length);
if(res.allowed_filetypes === '*.*') {
if(res.allowed_extensions.length == 0) {
$container.find('.allowed_filetypes_container').hide();
} else {
$container.find('.allowed_filetypes_container').show();

View file

@ -758,6 +758,7 @@ class adminAdminController extends admin
$document_config = $oDocumentModel->getDocumentConfig();
$document_config->thumbnail_target = $vars->thumbnail_target ?: 'all';
$document_config->thumbnail_type = $vars->thumbnail_type ?: 'crop';
$document_config->thumbnail_quality = intval($vars->thumbnail_quality) ?: 75;
$oModuleController = getController('module');
$oModuleController->insertModuleConfig('document', $document_config);

View file

@ -517,6 +517,7 @@ class adminAdminView extends admin
$config = $oDocumentModel->getDocumentConfig();
Context::set('thumbnail_target', $config->thumbnail_target ?: 'all');
Context::set('thumbnail_type', $config->thumbnail_type ?: 'crop');
Context::set('thumbnail_quality', $config->thumbnail_quality ?: 75);
if ($config->thumbnail_type === 'none')
{
Context::set('thumbnail_target', 'none');

View file

@ -270,6 +270,7 @@ $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,6 +273,7 @@ $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,6 +136,11 @@
<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">
<!--@for($q = 50; $q <= 100; $q += 5)-->
<option value="{$q}" selected="selected"|cond="$thumbnail_quality == $q">{$lang->thumbnail_quality} {$q}%</option>
<!--@endfor-->
</select>
</div>
</div>
<div class="x_control-group">

View file

@ -656,6 +656,10 @@ class commentItem extends BaseObject
{
$thumbnail_type = $config->thumbnail_type ?: 'crop';
}
if(!$config->thumbnail_quality)
{
$config->thumbnail_quality = 75;
}
if(!$this->isAccessible())
{
@ -785,7 +789,7 @@ class commentItem extends BaseObject
if($source_file)
{
$output = FileHandler::createImageFile($source_file, $thumbnail_file, $width, $height, 'jpg', $thumbnail_type);
$output = FileHandler::createImageFile($source_file, $thumbnail_file, $width, $height, 'jpg', $thumbnail_type, $config->thumbnail_quality);
}
// Remove source file if it was temporary

View file

@ -1009,6 +1009,10 @@ class documentItem extends BaseObject
{
$thumbnail_type = $config->thumbnail_type ?: 'crop';
}
if(!$config->thumbnail_quality)
{
$config->thumbnail_quality = 75;
}
if(!$this->isAccessible())
{
@ -1143,7 +1147,7 @@ class documentItem extends BaseObject
if($source_file)
{
$output_file = FileHandler::createImageFile($source_file, $thumbnail_file, $width, $height, 'jpg', $thumbnail_type);
$output_file = FileHandler::createImageFile($source_file, $thumbnail_file, $width, $height, 'jpg', $thumbnail_type, $config->thumbnail_quality);
}
// Remove source file if it was temporary

View file

@ -65,7 +65,7 @@ $lang->msg_auto_saved = 'Automatically Saved.';
$lang->cmd_disable = 'Inactive';
$lang->cmd_enable = 'Active';
$lang->cmd_select_cover = 'Be a cover image';
$lang->default_editor_settings = 'Default settings for this module';
$lang->default_editor_settings = 'Use Default Settings';
$lang->editor_skin = 'Editor Skin';
$lang->upload_file_grant = 'Permission to upload files';
$lang->enable_default_component_grant = 'Permission to use default components';
@ -75,7 +75,7 @@ $lang->enable_autosave = 'Enable Auto-Save';
$lang->allow_html = 'allow HTML';
$lang->height_resizable = 'Height Resizable';
$lang->editor_height = 'Height of Editor';
$lang->about_default_editor_settings = 'Follow editor settings of Rhymix Admin page through whole site.';
$lang->about_default_editor_settings = 'Follow the default settings from the Editor module.';
$lang->about_content_font = 'Please use comma for multiple input.';
$lang->about_content_font_size = 'Please input units such as px or em.';
$lang->about_enable_autosave = 'You may decide whether the auto-save function will be used.';

View file

@ -79,7 +79,7 @@ $lang->enable_autosave = '자동저장 사용';
$lang->allow_html = 'HTML 허용';
$lang->height_resizable = '높이 조절 가능';
$lang->editor_height = '에디터 높이';
$lang->about_default_editor_settings = '사이트 전체 에디터 설정을 통일하여서 모듈별 에디터 설정을 단순하게 합니다.';
$lang->about_default_editor_settings = '에디터 모듈의 기본 설정을 따릅니다.';
$lang->about_content_font = '콤마(,)로 여러 폰트를 지정할 수 있습니다.';
$lang->about_content_font_size = '12px, 1em등 단위까지 포함해서 입력해주세요.';
$lang->about_enable_autosave = '글 작성 시 자동 저장 기능을 활성화 시킬 수 있습니다.';

View file

@ -14,11 +14,13 @@
<action name="procFileGetList" type="controller" permission="root" />
<action name="dispFileAdminList" type="view" admin_index="true" menu_name="file" menu_index="true" />
<action name="dispFileAdminConfig" type="view" menu_name="file" />
<action name="dispFileAdminUploadConfig" type="view" menu_name="file" />
<action name="dispFileAdminDownloadConfig" type="view" menu_name="file" />
<action name="procFileAdminAddCart" type="controller" />
<action name="procFileAdminDeleteChecked" type="controller" ruleset="deleteChecked" />
<action name="procFileAdminInsertConfig" type="controller" ruleset="insertConfig" />
<action name="procFileAdminInsertUploadConfig" type="controller" ruleset="insertConfig" />
<action name="procFileAdminInsertDownloadConfig" type="controller" />
<action name="procFileAdminInsertModuleConfig" type="controller" permission="manager" check_var="target_module_srl" ruleset="fileModuleConfig" />
</actions>
<menus>

View file

@ -55,21 +55,26 @@ class fileAdminController extends file
}
/**
* Add file information
* Save upload configuration
*
* @return Object
*/
function procFileAdminInsertConfig()
function procFileAdminInsertUploadConfig()
{
// Get configurations (using module model object)
$config = new stdClass();
// Update configuration
$config = getModel('module')->getModuleConfig('file');
$config->allowed_filesize = Context::get('allowed_filesize');
$config->allowed_attach_size = Context::get('allowed_attach_size');
$config->allowed_filetypes = str_replace(' ', '', Context::get('allowed_filetypes'));
$config->allow_outlink = Context::get('allow_outlink');
$config->allow_outlink_format = Context::get('allow_outlink_format');
$config->allow_outlink_site = Context::get('allow_outlink_site');
$config->inline_download_format = array_map('utf8_trim', Context::get('inline_download_format'));
$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->image_autoconv['bmp2jpg'] = Context::get('image_autoconv_bmp2jpg') === 'Y' ? true : false;
$config->image_autoconv['webp2jpg'] = Context::get('image_autoconv_webp2jpg') === 'Y' ? true : false;
$config->image_autoconv_quality = max(50, min(100, intval(Context::get('image_autoconv_quality'))));
$config->image_autorotate = Context::get('image_autorotate') === 'Y' ? true : false;
$config->image_autorotate_quality = max(50, min(100, intval(Context::get('image_autorotate_quality'))));
// Check maximum file size
if (PHP_INT_SIZE < 8)
@ -80,11 +85,52 @@ class fileAdminController extends file
}
}
// Create module Controller object
// 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 = '*.*';
}
// 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', 'dispFileAdminConfig');
$returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : getNotEncodedUrl('', 'module', 'admin', 'act', 'dispFileAdminUploadConfig');
return $this->setRedirectUrl($returnUrl, $output);
}
/**
* Save download configuration
*
* @return Object
*/
function procFileAdminInsertDownloadConfig()
{
// Update configuration
$config = getModel('module')->getModuleConfig('file');
$config->allow_outlink = Context::get('allow_outlink');
$config->allow_outlink_format = Context::get('allow_outlink_format');
$config->allow_outlink_site = Context::get('allow_outlink_site');
$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');
return $this->setRedirectUrl($returnUrl, $output);
}
@ -101,24 +147,19 @@ class fileAdminController extends file
if(preg_match('/^([0-9,]+)$/',$module_srl)) $module_srl = explode(',',$module_srl);
else $module_srl = array($module_srl);
$download_grant = Context::get('download_grant');
$file_config = new stdClass;
$file_config->allow_outlink = Context::get('allow_outlink');
$file_config->allow_outlink_format = Context::get('allow_outlink_format');
$file_config->allow_outlink_site = Context::get('allow_outlink_site');
$file_config->allowed_filesize = Context::get('allowed_filesize');
$file_config->allowed_attach_size = Context::get('allowed_attach_size');
$file_config->allowed_filetypes = str_replace(' ', '', Context::get('allowed_filetypes'));
if(!is_array($download_grant))
{
$file_config->download_grant = explode('|@|',$download_grant);
}
else
{
$file_config->download_grant = array_values($download_grant);
}
$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->image_autoconv['bmp2jpg'] = Context::get('image_autoconv_bmp2jpg') === 'Y' ? true : false;
$file_config->image_autoconv['webp2jpg'] = Context::get('image_autoconv_webp2jpg') === 'Y' ? true : false;
$file_config->image_autoconv_quality = max(50, min(100, intval(Context::get('image_autoconv_quality'))));
$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)
@ -129,6 +170,38 @@ class fileAdminController extends file
}
}
// Simplify allowed_filetypes
$file_config->allowed_extensions = strtr(strtolower(trim($file_config->allowed_filetypes)), array('*.' => '', ';' => ','));
if ($file_config->allowed_extensions)
{
$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 = '*.*';
}
// Use default config
if(Context::get('use_default_file_config') === 'Y')
{
$file_config = new stdClass;
$file_config->use_default_file_config = true;
}
// Check download grant
$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);
}
$oModuleController = getController('module');
for($i=0;$i<count($module_srl);$i++)
{

View file

@ -210,11 +210,11 @@ class fileAdminView extends file
}
/**
* Set attachment information (for administrator)
* Upload config screen
*
* @return Object
*/
function dispFileAdminConfig()
function dispFileAdminUploadConfig()
{
$oFileModel = getModel('file');
$config = $oFileModel->getFileConfig();
@ -222,7 +222,23 @@ class fileAdminView extends file
// Set a template file
$this->setTemplatePath($this->module_path.'tpl');
$this->setTemplateFile('adminConfig');
$this->setTemplateFile('upload_config');
}
/**
* Download config screen
*
* @return Object
*/
function dispFileAdminDownloadConfig()
{
$oFileModel = getModel('file');
$config = $oFileModel->getFileConfig();
Context::set('config',$config);
// Set a template file
$this->setTemplatePath($this->module_path.'tpl');
$this->setTemplateFile('download_config');
}
}
/* End of file file.admin.view.php */

View file

@ -21,6 +21,7 @@ class file extends ModuleObject
$config->allowed_filesize = '2';
$config->allowed_attach_size = '2';
$config->allowed_filetypes = '*.*';
$config->allowed_extensions = array();
$oModuleController->insertModuleConfig('file', $config);
// Generate a directory for the file module
FileHandler::makeDir('./files/attach/images');

View file

@ -861,48 +861,63 @@ class fileController extends file
$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;
// Get file module configuration
$oFileModel = getModel('file');
$config = $oFileModel->getFileConfig($module_srl);
// Check file type
if(!$manual_insert && !$this->user->isAdmin())
{
// Check file type
if(isset($config->allowed_extensions) && count($config->allowed_extensions))
{
if(!in_array($extension, $config->allowed_extensions))
{
throw new Rhymix\Framework\Exception('msg_not_allowed_filetype');
}
}
}
// Check image type and size
if(!$manual_insert)
{
// Get the file configurations
$logged_info = Context::get('logged_info');
if($logged_info->is_admin != 'Y')
if(in_array($extension, array('gif', 'jpg', 'jpeg', 'png', 'webp', 'bmp')))
{
$oFileModel = getModel('file');
$config = $oFileModel->getFileConfig($module_srl);
// check file type
if(isset($config->allowed_filetypes) && $config->allowed_filetypes !== '*.*')
{
$filetypes = explode(';', $config->allowed_filetypes);
$ext = array();
foreach($filetypes as $item) {
$item = explode('.', $item);
$ext[] = strtolower($item[1]);
}
$uploaded_ext = explode('.', $file_info['name']);
$uploaded_ext = strtolower(array_pop($uploaded_ext));
if(!in_array($uploaded_ext, $ext))
{
throw new Rhymix\Framework\Exception('msg_not_allowed_filetype');
}
}
$allowed_filesize = $config->allowed_filesize * 1024 * 1024;
$allowed_attach_size = $config->allowed_attach_size * 1024 * 1024;
// An error appears if file size exceeds a limit
if($allowed_filesize < filesize($file_info['tmp_name'])) throw new Rhymix\Framework\Exception('msg_exceeds_limit_size');
// Get total file size of all attachements (from DB)
$size_args = new stdClass;
$size_args->upload_target_srl = $upload_target_srl;
$output = executeQuery('file.getAttachedFileSize', $size_args);
$attached_size = (int)$output->data->attached_size + filesize($file_info['tmp_name']);
if($attached_size > $allowed_attach_size) throw new Rhymix\Framework\Exception('msg_exceeds_limit_size');
$file_info = $this->checkUploadedImage($file_info, $config);
}
}
// Sanitize filename
$file_info['name'] = Rhymix\Framework\Filters\FilenameFilter::clean($file_info['name']);
// Check file size
if(!$manual_insert && !$this->user->isAdmin())
{
$file_size = filesize($file_info['tmp_name']);
$allowed_filesize = $config->allowed_filesize * 1024 * 1024;
$allowed_attach_size = $config->allowed_attach_size * 1024 * 1024;
if($allowed_filesize < $file_size)
{
throw new Rhymix\Framework\Exception('msg_exceeds_limit_size');
}
$size_args = new stdClass;
$size_args->upload_target_srl = $upload_target_srl;
$output = executeQuery('file.getAttachedFileSize', $size_args);
if($allowed_attach_size < intval($output->data->attached_size) + $file_size)
{
throw new Rhymix\Framework\Exception('msg_exceeds_limit_size');
}
}
// Get file_srl
$file_srl = getNextSequence();
@ -940,7 +955,7 @@ class fileController extends file
}
// Move the file
if($manual_insert)
if($manual_insert && !$file_info['converted'])
{
@copy($file_info['tmp_name'], $filename);
if(!file_exists($filename))
@ -952,7 +967,7 @@ class fileController extends file
}
}
}
elseif(starts_with(RX_BASEDIR . 'files/attach/chunks/', $file_info['tmp_name']))
elseif(starts_with(RX_BASEDIR . 'files/attach/chunks/', $file_info['tmp_name']) || $file_info['converted'])
{
if (!Rhymix\Framework\Storage::move($file_info['tmp_name'], $filename))
{
@ -1009,6 +1024,136 @@ class fileController extends file
return $output;
}
/**
* Check uploaded image
*/
public function checkUploadedImage($file_info, $config)
{
// Get image information
$image_info = @getimagesize($file_info['tmp_name']);
if (!$image_info)
{
return $file_info;
}
$image_width = $image_info[0];
$image_height = $image_info[1];
$image_type = $image_info[2];
$convert = false;
// Check image type
if($config->image_autoconv['bmp2jpg'] && function_exists('imagebmp') && $image_type === 6)
{
$convert = array($image_width, $image_height, 'jpg', $config->image_autoconv_quality ?: 75, 0);
}
if($config->image_autoconv['webp2jpg'] && function_exists('imagewebp') && $image_type === 18)
{
$convert = array($image_width, $image_height, 'jpg', $config->image_autoconv_quality ?: 75, 0);
}
// Check image rotation
if($config->image_autorotate && function_exists('exif_read_data'))
{
$exif = @exif_read_data($file_info['tmp_name']);
if($exif && isset($exif['Orientation']))
{
switch ($exif['Orientation'])
{
case 3: $rotate = 180; break;
case 6: $rotate = 270; break;
case 8: $rotate = 90; break;
default: $rotate = 0;
}
if ($rotate)
{
$convert = $convert ?: array($image_width, $image_height, $file_info['extension']);
if ($rotate == 90 || $rotate == 270)
{
$image_height = $convert[0];
$image_width = $convert[1];
$convert[0] = $image_width;
$convert[1] = $image_height;
}
$convert[3] = $config->image_autorotate_quality ?: 75;
$convert[4] = $rotate;
}
}
unset($exif);
}
// Check image size
if($config->max_image_size_action && ($config->max_image_width || $config->max_image_height) && !$this->user->isAdmin())
{
$exceeded = false;
if ($config->max_image_width > 0 && $image_width > $config->max_image_width)
{
$exceeded = true;
}
elseif ($config->max_image_height > 0 && $image_height > $config->max_image_height)
{
$exceeded = true;
}
if ($exceeded)
{
// Block upload
if ($config->max_image_size_action === 'block')
{
if ($config->max_image_width && $config->max_image_height)
{
$message = sprintf(lang('msg_exceeds_max_image_size'), $config->max_image_width, $config->max_image_height);
}
elseif ($config->max_image_width)
{
$message = sprintf(lang('msg_exceeds_max_image_width'), $config->max_image_width);
}
else
{
$message = sprintf(lang('msg_exceeds_max_image_height'), $config->max_image_height);
}
throw new Rhymix\Framework\Exception($message);
}
// Resize automatically
else
{
$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);
}
}
}
// Convert image if necessary
if ($convert)
{
$result = FileHandler::createImageFile($file_info['tmp_name'], $file_info['tmp_name'] . '.conv', $convert[0], $convert[1], $convert[2], 'crop', $convert[3], $convert[4]);
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'] . '.conv';
$file_info['size'] = filesize($file_info['tmp_name']);
$file_info['extension'] = $convert[2];
$file_info['converted'] = true;
}
}
return $file_info;
}
/**
* Delete the attachment
*

View file

@ -112,6 +112,7 @@ class fileModel extends file
$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;
$this->add("files",$files);
$this->add("editor_sequence",$editor_sequence);
$this->add("upload_target_srl",$upload_target_srl);
@ -121,6 +122,7 @@ class fileModel extends file
$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);
}
/**
@ -185,23 +187,44 @@ class fileModel extends file
if($file_config)
{
$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->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->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;
}
// 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->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;
// Default setting if not exists
if(!$config->allowed_filesize) $config->allowed_filesize = '2';
if(!$config->allowed_attach_size) $config->allowed_attach_size = '3';
@ -209,6 +232,26 @@ class fileModel extends file
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;
// Format allowed_filetypes
if($config->allowed_filetypes && !isset($config->allowed_extensions))
{
$config->allowed_filetypes = trim($config->allowed_filetypes);
if($config->allowed_filetypes === '*.*')
{
$config->allowed_extensions = '';
}
else
{
$config->allowed_extensions = array_map(function($ext) {
return strtolower(substr(strrchr(trim($ext), '.'), 1));
}, explode(';', $config->allowed_filetypes));
}
}
return $config;
}

View file

@ -3,6 +3,7 @@ $lang->file = 'File';
$lang->file_management = 'File Management';
$lang->file_upload = 'File Upload';
$lang->file_upload_config = 'File Upload Settings';
$lang->file_download_config = 'File Download Settings';
$lang->file_name = 'File Name';
$lang->file_size = 'File Size';
$lang->download_count = 'Number of Downloads';
@ -16,15 +17,26 @@ $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->image_resize_quality = 'Quality';
$lang->image_autoconv = 'Auto-Convert Image';
$lang->image_autoconv_bmp2jpg = 'BMP → JPG';
$lang->image_autoconv_webp2jpg = 'WebP → JPG';
$lang->image_autorotate = 'Auto-Rotate Image';
$lang->inline_download_format = 'Open in current window';
$lang->inline_download_image = 'Image';
$lang->inline_download_audio = 'Audio';
$lang->inline_download_video = 'Video';
$lang->inline_download_text = 'Text (except HTML)';
$lang->inline_download_pdf = 'PDF';
$lang->use_default_file_config = 'Use Default Settings';
$lang->about_use_default_file_config = 'Follow the default settings from the File module.';
$lang->about_inline_download_format = 'Selected types of files will be opened in the current window instead of a download dialog when a user clicks the download link.';
$lang->enable_download_group = 'Downloadable Groups';
$lang->about_allow_outlink = 'You can block other websites from accessing your download URLs directly.<br />This does not apply to images and other files that can be embedded directly in a document.';
$lang->about_allow_outlink = 'Allow other websites to link directly to your download URLs.<br />Rhymix does not control links to image files that can be embedded directly in a document.<br />in order to block external links to such images, you may need to modify your web server configuration.';
$lang->about_allow_outlink_format = 'These file formats will always be allowed.<br />Please use a comma (,) to separate items: e.g. doc, zip, pdf';
$lang->about_allow_outlink_site = 'These referers will always be allowed.<br />Please enter one full address per line: e.g. https://www.rhymix.org/';
$lang->about_allowed_filesize = 'You can limit the size of each attached file.<br />Administrators are limited to this setting or the limit set in the <a href="%s" target="_blank">file module</a>, whichever is greater.';
@ -32,7 +44,10 @@ $lang->about_allowed_attach_size = 'You can limit the total size of all attached
$lang->about_allowed_filesize_global = 'This is the global limit on the size of each attachment.';
$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 = 'To allow an extension, use "*.[extention]". To allow multiple extensions, use ";" between each extension. ex) *.* or *.jpg;*.gif; ';
$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_autorotate = 'Automatically correct images that are rotated by mobile devices.<br />If enabled, this feature also applies to images uploaded by the administrator.';
$lang->cmd_delete_checked_file = 'Delete Selected Item(s)';
$lang->cmd_move_to_document = 'Move to Document';
$lang->cmd_download = 'Download';
@ -40,6 +55,9 @@ $lang->msg_not_permitted_download = 'You do not have a permission to download.';
$lang->msg_file_cart_is_null = 'Please select a file(s) to delete.';
$lang->msg_checked_file_is_deleted = '%d attachment(s) was(were) deleted.';
$lang->msg_exceeds_limit_size = 'This file exceeds the attachment limit.';
$lang->msg_exceeds_max_image_size = 'This image is too large. Images must be no larger than %dx%dpx.';
$lang->msg_exceeds_max_image_width = 'This image is too large. The maximum permitted width is %dpx.';
$lang->msg_exceeds_max_image_height = 'This image is too large. The maximum permitted height is %dpx.';
$lang->msg_file_not_found = 'Could not find requested file.';
$lang->msg_file_key_expired = 'This download link is expired. Please initiate the download again.';
$lang->file_search_target_list['filename'] = 'File Name';

View file

@ -17,7 +17,7 @@ $lang->about_allow_outlink = 'Enlaces externos a Rusia Ripper puede bloquear el
$lang->about_allow_outlink_site = 'Archivos, independientemente de la configuración para permitir a los enlaces externos es la dirección del sitio. Entrada múltiples gubunhaeju un cambio en la línea, por favor. Ej.) https://www.rhymix.org/';
$lang->about_allowed_filesize = 'Puede definir el límite del tamaño del archivo adjunto.(exceptuando el administrador)';
$lang->about_allowed_attach_size = 'Puede definir el límite del tamaño total de los archivos adjuntos por documento.(exceptuando el administrador)';
$lang->about_allowed_filetypes = 'Para permitir una extensión use "*.extensión". Para permitir más de una extensión use ";". ej) *.* o *.jpg;*.gif;etc.';
$lang->about_allowed_filetypes = 'Rhymix ya no usa la antigua sintaxis *. *. Simplemente enumere las extensiones que desea permitir.<br />Utilice una coma (,) para separar los elementos: doc, zip, pdf';
$lang->cmd_delete_checked_file = 'Eliminar el archivo seleccionado';
$lang->cmd_move_to_document = 'Mover hacia el doncumento';
$lang->cmd_download = 'Descargar';

View file

@ -13,7 +13,7 @@ $lang->allowed_filetypes = 'Extensions consentis seulement peuvent etre attaches
$lang->enable_download_group = 'Groupe permis de telecharger';
$lang->about_allowed_filesize = 'Vous pouvez designer la limite de mesure pour chaque fichier.(Exclure administrateurs)';
$lang->about_allowed_attach_size = 'Vous pouvez designer la limite de mesure pour chaque document.(Exclure administrateurs)';
$lang->about_allowed_filetypes = 'Pour consentir une extension, utilisez "*.[extention]". Pour consentir plusieurs extensions, utilisez ";" entre chaque extension. ex) *.* ou *.jpg;*.gif;';
$lang->about_allowed_filetypes = 'Rhymix n\'utilise plus l\'ancienne syntaxe *. *. Indiquez simplement les extensions que vous souhaitez autoriser.<br />Utilisez une virgule (,) pour séparer les éléments: par exemple. doc, zip, pdf';
$lang->cmd_delete_checked_file = 'Supprimer item(s) slectionne(s)';
$lang->cmd_move_to_document = 'Bouger au Document';
$lang->cmd_download = 'Telecharger';

View file

@ -22,7 +22,7 @@ $lang->about_allow_outlink_format = '外部からのファイルリンク設定
$lang->about_allow_outlink_site = '外部からのファイルリンク設定に関係なく、常に外部からのリンクを許可するURLです。<br />複数登録時には、改行で記入してください。 ex) https://www.rhymix.org/';
$lang->about_allowed_filesize = '一つのファイルに対して、アップロード可能なファイルの最大サイズを指定します(管理者は除く)。';
$lang->about_allowed_attach_size = '一つの書き込みに対して、管理者以外のユーザーが添付可能な最大サイズを指定します。';
$lang->about_allowed_filetypes = '"*.拡張子"で指定し、 ";"で区切って任意の拡張子を追加して指定できます。ex) *.* or *.jpg;*.gif; ';
$lang->about_allowed_filetypes = 'アップロードを許容する拡張者リストです。 前のバージョンの*.* 文法は使用しません。<br /> いろいろな入力時にdoc,zip,pdfのようにコンマ(,)に区分してください。';
$lang->cmd_delete_checked_file = '選択リスト削除';
$lang->cmd_move_to_document = '書き込みに移動する';
$lang->cmd_download = 'ダウンロード';

View file

@ -3,6 +3,7 @@ $lang->file = '파일';
$lang->file_management = '파일 관리';
$lang->file_upload = '파일 업로드';
$lang->file_upload_config = '파일 업로드 설정';
$lang->file_download_config = '파일 다운로드 설정';
$lang->file_name = '파일 이름';
$lang->file_size = '파일 크기';
$lang->download_count = '다운로드 받은 수';
@ -11,28 +12,42 @@ $lang->is_valid = '유효';
$lang->is_stand_by = '대기';
$lang->file_list = '첨부 파일 목록';
$lang->allow_outlink = '다운로드 링크 외부 접근 허용';
$lang->allow_outlink_site = '다운로드 링크 허용 사이트';
$lang->allow_outlink_format = '다운로드 링크 허용 확장자';
$lang->allowed_filesize = '파일 크기 제한';
$lang->allow_outlink_site = '외부 접근 허용 사이트';
$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->image_resize_quality = '화질';
$lang->image_autoconv = '이미지 자동 변환';
$lang->image_autoconv_bmp2jpg = 'BMP → JPG';
$lang->image_autoconv_webp2jpg = 'WebP → JPG';
$lang->image_autorotate = '이미지 자동 회전';
$lang->inline_download_format = '다운로드시 현재 창 사용';
$lang->inline_download_image = '이미지';
$lang->inline_download_audio = '오디오';
$lang->inline_download_video = '비디오';
$lang->inline_download_text = '텍스트 (HTML 제외)';
$lang->inline_download_pdf = 'PDF';
$lang->use_default_file_config = '기본 파일 설정 사용';
$lang->about_use_default_file_config = '파일 모듈의 기본 설정을 따릅니다.';
$lang->about_inline_download_format = '선택한 종류의 파일은 다운로드 링크를 클릭하더라도 다운로드 창을 열지 않고 현재 창에 표시합니다.';
$lang->enable_download_group = '다운로드 가능 그룹';
$lang->about_allow_outlink = '다른 사이트에서 파일 다운로드 링크에 직접 접근하는 것을 차단합니다.<br />다운로드 링크를 사용하지 않고 본문에 바로 삽입할 수 있는 이미지 파일 등에는 적용되지 않습니다.';
$lang->about_allow_outlink = '다른 사이트에서 파일 다운로드 링크에 직접 접근하는 것을 허용합니다.<br />본문에 바로 삽입할 수 있는 이미지 파일은 라이믹스에서 접근을 통제할 수 없으며, 이를 차단하려면 웹서버 설정이 필요합니다.';
$lang->about_allow_outlink_format = '파일 외부 링크 설정에 상관없이 허용하는 파일 확장자입니다.<br />여러 개 입력시 쉼표(,)을 이용해서 구분해 주세요. 예) doc, zip, pdf';
$lang->about_allow_outlink_site = '파일 외부 링크 설정에 상관없이 허용하는 사이트 주소입니다.<br />여러 개 입력시 줄을 바꿔서 구분해 주세요. 예) https://www.rhymix.org/';
$lang->about_allowed_filesize = '각 파일의 용량을 제한할 수 있습니다.<br />관리자에게는 이 게시판의 제한과 <a href="%s" target="_blank">파일 모듈</a>의 제한 중 높은 쪽이 적용됩니다.';
$lang->about_allowed_attach_size = '하나의 문서에 첨부할 수 있는 최대 용량을 제한할 수 있습니다.<br />관리자에게는 이 게시판의 제한과 <a href="%s" target="_blank">파일 모듈</a>의 제한 중 높은 쪽이 적용됩니다.';
$lang->about_allowed_filesize_global = '관리자를 포함하여 사이트 전체에 적용되는 파일 크기 제한입니다.';
$lang->about_allowed_filesize_global = '관리자를 포함하여 사이트 전체에 적용되는 파일 용량 제한입니다.';
$lang->about_allowed_attach_size_global = '관리자를 포함하여 사이트 전체에 적용되는 문서당 총 첨부 용량 제한입니다.';
$lang->about_allowed_size_limits = 'IE9 이하, 구버전 안드로이드 등에서는 php.ini에서 지정한 %sB로 제한됩니다.';
$lang->about_allowed_filetypes = '"*.확장자"로 지정할 수 있고 ";" 으로 여러 개 지정이 가능합니다. 예) *.* or *.jpg;*.gif;';
$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_autorotate = '모바일 기기 등에서 잘못 회전된 이미지를 바로잡습니다.<br />관리자가 업로드한 파일에도 적용됩니다.';
$lang->cmd_delete_checked_file = '선택항목 삭제';
$lang->cmd_move_to_document = '문서로 이동';
$lang->cmd_download = '다운로드';
@ -41,6 +56,9 @@ $lang->msg_file_cart_is_null = '삭제할 파일을 선택해주세요.';
$lang->msg_checked_file_is_deleted = '%d개의 첨부 파일이 삭제되었습니다.';
$lang->msg_exceeds_limit_size = '허용된 용량을 초과하여 첨부가 되지 않았습니다.';
$lang->msg_not_allowed_filetype = '업로드할 수 없는 파일 형식입니다.';
$lang->msg_exceeds_max_image_size = '이미지가 너무 큽니다. %dx%dpx 이하의 이미지만 허용됩니다.';
$lang->msg_exceeds_max_image_width = '이미지가 너무 큽니다. 폭 %dpx 이하의 이미지만 허용됩니다.';
$lang->msg_exceeds_max_image_height = '이미지가 너무 큽니다. 높이 %dpx 이하의 이미지만 허용됩니다.';
$lang->msg_file_not_found = '요청한 파일을 찾을 수 없습니다.';
$lang->msg_file_key_expired = '다운로드 링크의 유효기간이 지났습니다. 다시 다운로드하여 주시기 바랍니다.';
$lang->file_search_target_list['filename'] = '파일 이름';

View file

@ -17,7 +17,7 @@ $lang->about_allow_outlink = '根据反向链接防止盗链。(*.wmv, *.mp3等
$lang->about_allow_outlink_site = '可以设置允许外链的站点。多个站点以换行来区分,即一行一个。 ex)https://www.rhymix.org/';
$lang->about_allowed_filesize = '最大单个上传文件大小(管理员不受此限制)。';
$lang->about_allowed_attach_size = '每个主题最大上传文件大小(管理员不受此限制)。';
$lang->about_allowed_filetypes = '可以用"*.扩展名"来指定或用 ";"来 区分多个扩展名 例) *.* or *.jpg;*.gif;';
$lang->about_allowed_filetypes = '允许上传的扩展者目录。 不使用前版本的*.*语法。<br />输入多个时,请与doc,zip,pdf一起用逗号区分。';
$lang->cmd_delete_checked_file = '删除所选项目';
$lang->cmd_move_to_document = '查看源主题';
$lang->cmd_download = '下载';

View file

@ -19,7 +19,7 @@ $lang->about_allow_outlink_format = '設定允許外部連結的檔案格式。
$lang->about_allow_outlink_site = '可設置允許外部檔案連結的網站名單。當數量太多時,可換行輸入。 例) https://www.rhymix.org/';
$lang->about_allowed_filesize = '最大單一上傳檔案大小(管理員不受此限制)。';
$lang->about_allowed_attach_size = '每個主題最大上傳檔案大小(管理員不受此限制)。';
$lang->about_allowed_filetypes = '可以用 "*.副檔名" 來指定或用分號 ";" 來區隔多個副檔名。 例) *.* or *.jpg; *.gif;';
$lang->about_allowed_filetypes = '允許上傳的擴展者目錄。 不使用前版本的*.*語法。<br /> 輸入多個時,請與doc,zip,pdf一起用逗號區分。';
$lang->cmd_delete_checked_file = '刪除所選項目';
$lang->cmd_move_to_document = '檢視原始主題';
$lang->cmd_download = '下載';

View file

@ -1,11 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<ruleset version="1.5.0">
<customrules>
<rule name="extension" type="regex" test="/^(?:\*\.\*|(\*\.\w+;\s*)*\*\.\w+;?)$/i" />
</customrules>
<fields>
<field name="allowed_filesize" required="true" rule="float" default="2" />
<field name="allowed_attach_size" required="true" rule="float" default="2" />
<field name="allowed_filetypes" required="true" rule="extension" />
</fields>
</ruleset>

View file

@ -1,11 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<ruleset version="1.5.0">
<customrules>
<rule name="extension" type="regex" test="/^(?:\*\.\*|(\*\.\w+;\s*)*\*\.\w+;?)$/i" />
</customrules>
<fields>
<field name="allowed_filesize" required="true" rule="float" default="2" />
<field name="allowed_attach_size" required="true" rule="float" default="2" />
<field name="allowed_filetypes" required="true" rule="extension" />
</fields>
</ruleset>

View file

@ -0,0 +1,5 @@
.use_default_file_config {
margin-top: -10px;
border-bottom: 1px solid #ccc;
background: #f5f5f5;
}

View file

@ -1,13 +1,13 @@
<include target="header.html" />
<div cond="$XE_VALIDATOR_MESSAGE && $XE_VALIDATOR_ID == 'modules/file/tpl/adminConfig/1'" class="message {$XE_VALIDATOR_MESSAGE_TYPE}">
<div cond="$XE_VALIDATOR_MESSAGE && $XE_VALIDATOR_ID == 'modules/file/tpl/download_config/1'" class="message {$XE_VALIDATOR_MESSAGE_TYPE}">
<p>{$XE_VALIDATOR_MESSAGE}</p>
</div>
<form ruleset="insertConfig" action="./" method="post" class="x_form-horizontal section">
<input type="hidden" name="module" value="file" />
<input type="hidden" name="act" value="procFileAdminInsertConfig" />
<input type="hidden" name="xe_validator_id" value="modules/file/tpl/adminConfig/1" />
<input type="hidden" name="act" value="procFileAdminInsertDownloadConfig" />
<input type="hidden" name="xe_validator_id" value="modules/file/tpl/download_config/1" />
<div class="x_control-group">
<label class="x_control-label">{$lang->allow_outlink}</label>
<div class="x_controls">
@ -41,27 +41,6 @@
<p class="x_help-block">{$lang->about_inline_download_format}</p>
</div>
</div>
<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">{$lang->about_allowed_filesize_global}<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">{$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 for="allowedFiletypes" class="x_control-label">{$lang->allowed_filetypes}</label>
<div class="x_controls">
<input id="allowedFiletypes" type="text" name="allowed_filetypes" value="{$config->allowed_filetypes}" />
<p class="x_help-block">{$lang->about_allowed_filetypes}</p>
</div>
</div>
<div class="x_clearfix btnArea">
<div class="x_pull-right">
<button type="submit" class="x_btn x_btn-primary">{$lang->cmd_save}</button>

View file

@ -1,3 +1,6 @@
<load target="css/config.css" />
<load target="js/config.js" />
<section class="section">
<h1>{$lang->file}</h1>
@ -7,6 +10,17 @@
<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}" />
<div class="x_control-group use_default_file_config">
<label for="allowed_filesize" 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" />
{$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">
@ -21,13 +35,74 @@
<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 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}</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="$file_config->image_autoconv['bmp2jpg']" disabled="disabled"|cond="!function_exists('imagebmp')" />
{$lang->image_autoconv_bmp2jpg}
</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">{$lang->about_image_autoconv}</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>
</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="{$file_config->allowed_filetypes}" />
<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>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->enable_download_group}</label>
<div class="x_controls">

View file

@ -7,7 +7,10 @@
<li class="x_active"|cond="$act == 'dispFileAdminList'">
<a href="{getUrl('', 'module', 'admin', 'act', 'dispFileAdminList')}">{$lang->file_list}</a>
</li>
<li class="x_active"|cond="$act == 'dispFileAdminConfig'">
<a href="{getUrl('', 'module', 'admin', 'act', 'dispFileAdminConfig')}">{$lang->file_upload_config}</a>
<li class="x_active"|cond="$act == 'dispFileAdminUploadConfig'">
<a href="{getUrl('', 'module', 'admin', 'act', 'dispFileAdminUploadConfig')}">{$lang->file_upload_config}</a>
</li>
<li class="x_active"|cond="$act == 'dispFileAdminDownloadConfig'">
<a href="{getUrl('', 'module', 'admin', 'act', 'dispFileAdminDownloadConfig')}">{$lang->file_download_config}</a>
</li>
</ul>

View file

@ -0,0 +1,12 @@
(function($) {
$(function() {
$('#use_default_file_config').on('change', function() {
if ($(this).is(':checked')) {
$('.use_custom_file_config').hide();
} else {
$('.use_custom_file_config').show();
}
});
});
})(jQuery);

View file

@ -0,0 +1,96 @@
<include target="header.html" />
<div cond="$XE_VALIDATOR_MESSAGE && $XE_VALIDATOR_ID == 'modules/file/tpl/upload_config/1'" class="message {$XE_VALIDATOR_MESSAGE_TYPE}">
<p>{$XE_VALIDATOR_MESSAGE}</p>
</div>
<form ruleset="insertConfig" action="./" method="post" class="x_form-horizontal section">
<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">
<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">{$lang->about_allowed_filesize_global}<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">{$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}</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_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">{$lang->about_image_autoconv}</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 ?: [])}" />
<p class="x_help-block">{$lang->about_allowed_filetypes}</p>
</div>
</div>
<div class="x_clearfix btnArea">
<div class="x_pull-right">
<button type="submit" class="x_btn x_btn-primary">{$lang->cmd_save}</button>
</div>
</div>
</form>