mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-04-24 21:03:19 +09:00
Merge branch 'security/rve-2023-6' into develop
This commit is contained in:
commit
f4474070e1
12 changed files with 163 additions and 53 deletions
|
|
@ -91,8 +91,8 @@
|
|||
var chunkStatus = true;
|
||||
var defaultFormData = {
|
||||
"editor_sequence": data.editorSequence,
|
||||
"upload_target_srl" : data.uploadTargetSrl,
|
||||
"mid" : window.current_mid,
|
||||
"upload_target_srl" : data.uploadTargetSrl ? data.uploadTargetSrl : 0,
|
||||
"mid" : window.editor_mid ? window.editor_mid : window.current_mid,
|
||||
"act": 'procFileUpload'
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -293,6 +293,10 @@ class CommunicationView extends communication
|
|||
{
|
||||
$option->editor_toolbar_hide = 'Y';
|
||||
}
|
||||
if ($option->allow_fileupload)
|
||||
{
|
||||
$option->module_srl = MemberView::getInstance()->getMemberModuleSrl();
|
||||
}
|
||||
$editor = $oEditorModel->getEditor(getNextSequence(), $option);
|
||||
$editor = $editor . "\n" . '<input type="hidden" name="temp_srl" value="" />' . "\n";
|
||||
Context::set('editor', $editor);
|
||||
|
|
|
|||
|
|
@ -328,11 +328,10 @@ class EditorController extends Editor
|
|||
$editor_sequence = Context::get('editor_sequence');
|
||||
$primary_key = Context::get('primary_key');
|
||||
$oEditorModel = getModel('editor');
|
||||
$oFileController = getController('file');
|
||||
|
||||
$saved_doc = $oEditorModel->getSavedDoc(null);
|
||||
|
||||
$oFileController->setUploadInfo($editor_sequence, $saved_doc->document_srl);
|
||||
FileController::setUploadInfo($editor_sequence, $saved_doc->document_srl, intval($saved_doc->module_srl));
|
||||
$vars = $this->getVariables();
|
||||
$this->add("editor_sequence", $editor_sequence);
|
||||
$this->add("key", $primary_key);
|
||||
|
|
|
|||
|
|
@ -251,14 +251,29 @@ class EditorModel extends Editor
|
|||
}
|
||||
|
||||
Context::set('file_config',$file_config);
|
||||
|
||||
// Configure upload status such as file size
|
||||
$upload_status = FileModel::getUploadStatus();
|
||||
Context::set('upload_status', $upload_status);
|
||||
|
||||
// Upload enabled (internally caching)
|
||||
$oFileController = getController('file');
|
||||
$oFileController->setUploadInfo($option->editor_sequence, $upload_target_srl);
|
||||
FileController::setUploadInfo($option->editor_sequence, $upload_target_srl, $option->module_srl ?? 0);
|
||||
|
||||
// Set editor mid
|
||||
if (!empty($option->module_srl))
|
||||
{
|
||||
$option->mid = ModuleModel::getModuleInfoByModuleSrl($option->module_srl)->mid ?? null;
|
||||
}
|
||||
if (!empty($option->mid))
|
||||
{
|
||||
Context::addHtmlFooter('<script> var editor_mid = ' . json_encode($option->mid) . '; </script>');
|
||||
}
|
||||
|
||||
// Check if the file already exists
|
||||
if($upload_target_srl) $files_count = FileModel::getFilesCount($upload_target_srl);
|
||||
if ($upload_target_srl)
|
||||
{
|
||||
$files_count = FileModel::getFilesCount($upload_target_srl);
|
||||
}
|
||||
}
|
||||
Context::set('files_count', (int)$files_count);
|
||||
|
||||
|
|
@ -294,6 +309,7 @@ class EditorModel extends Editor
|
|||
// Initialize options
|
||||
$option = new stdClass();
|
||||
$option->module_type = $type;
|
||||
$option->module_srl = (int)$module_srl;
|
||||
|
||||
// Convert configuration keys according to type (document or comment).
|
||||
if($type == 'document')
|
||||
|
|
|
|||
|
|
@ -31,21 +31,24 @@ class FileController extends File
|
|||
// An error appears if not a normally uploaded file
|
||||
if(!$file_info || !is_uploaded_file($file_info['tmp_name'])) exit();
|
||||
|
||||
// Basic variables setting
|
||||
// Validate editor_sequence and module_srl.
|
||||
$editor_sequence = Context::get('editor_sequence');
|
||||
$module_srl = $this->module_srl;
|
||||
|
||||
// Exit a session if there is neither upload permission nor information
|
||||
if(!$_SESSION['upload_info'][$editor_sequence]->enabled)
|
||||
if (empty($_SESSION['upload_info'][$editor_sequence]->enabled))
|
||||
{
|
||||
throw new Rhymix\Framework\Exceptions\NotPermitted;
|
||||
throw new Rhymix\Framework\Exceptions\InvalidRequest(sprintf(lang('file.msg_invalid_upload_info'), 'editor_sequence'));
|
||||
}
|
||||
if ($_SESSION['upload_info'][$editor_sequence]->module_srl !== $module_srl)
|
||||
{
|
||||
throw new Rhymix\Framework\Exceptions\InvalidRequest(sprintf(lang('file.msg_invalid_upload_info'), 'module_srl'));
|
||||
}
|
||||
|
||||
// Get upload_target_srl
|
||||
$upload_target_srl = intval(Context::get('uploadTargetSrl')) ?: intval(Context::get('upload_target_srl'));
|
||||
if (!$upload_target_srl)
|
||||
// Validate upload_target_srl.
|
||||
$upload_target_srl = $_SESSION['upload_info'][$editor_sequence]->upload_target_srl;
|
||||
$submitted_upload_target_srl = intval(Context::get('uploadTargetSrl')) ?: intval(Context::get('upload_target_srl'));
|
||||
if ($submitted_upload_target_srl && $submitted_upload_target_srl !== intval($upload_target_srl))
|
||||
{
|
||||
$upload_target_srl = $_SESSION['upload_info'][$editor_sequence]->upload_target_srl;
|
||||
throw new Rhymix\Framework\Exceptions\InvalidRequest(sprintf(lang('file.msg_invalid_upload_info'), 'upload_target_srl'));
|
||||
}
|
||||
if (!$upload_target_srl)
|
||||
{
|
||||
|
|
@ -170,24 +173,39 @@ class FileController extends File
|
|||
function procFileIframeUpload()
|
||||
{
|
||||
// Basic variables setting
|
||||
$editor_sequence = Context::get('editor_sequence');
|
||||
$callback = Context::get('callback');
|
||||
$module_srl = $this->module_srl;
|
||||
$upload_target_srl = intval(Context::get('uploadTargetSrl'));
|
||||
if(!$upload_target_srl) $upload_target_srl = intval(Context::get('upload_target_srl'));
|
||||
|
||||
// Exit a session if there is neither upload permission nor information
|
||||
if(!$_SESSION['upload_info'][$editor_sequence]->enabled) exit();
|
||||
// Extract from session information if upload_target_srl is not specified
|
||||
if(!$upload_target_srl) $upload_target_srl = $_SESSION['upload_info'][$editor_sequence]->upload_target_srl;
|
||||
// Create if upload_target_srl is not defined in the session information
|
||||
if(!$upload_target_srl) $_SESSION['upload_info'][$editor_sequence]->upload_target_srl = $upload_target_srl = getNextSequence();
|
||||
// Validate editor_sequence and module_srl.
|
||||
$editor_sequence = Context::get('editor_sequence');
|
||||
$module_srl = $this->module_srl;
|
||||
if (empty($_SESSION['upload_info'][$editor_sequence]->enabled))
|
||||
{
|
||||
throw new Rhymix\Framework\Exceptions\InvalidRequest(sprintf(lang('file.msg_invalid_upload_info'), 'editor_sequence'));
|
||||
}
|
||||
if ($_SESSION['upload_info'][$editor_sequence]->module_srl !== $module_srl)
|
||||
{
|
||||
throw new Rhymix\Framework\Exceptions\InvalidRequest(sprintf(lang('file.msg_invalid_upload_info'), 'module_srl'));
|
||||
}
|
||||
|
||||
// Get upload_target_srl
|
||||
$upload_target_srl = $_SESSION['upload_info'][$editor_sequence]->upload_target_srl;
|
||||
$submitted_upload_target_srl = intval(Context::get('uploadTargetSrl')) ?: intval(Context::get('upload_target_srl'));
|
||||
if ($submitted_upload_target_srl && $submitted_upload_target_srl !== intval($upload_target_srl))
|
||||
{
|
||||
throw new Rhymix\Framework\Exceptions\InvalidRequest(sprintf(lang('file.msg_invalid_upload_info'), 'upload_target_srl'));
|
||||
}
|
||||
if (!$upload_target_srl)
|
||||
{
|
||||
$upload_target_srl = getNextSequence();
|
||||
$_SESSION['upload_info'][$editor_sequence]->upload_target_srl = $upload_target_srl;
|
||||
}
|
||||
|
||||
// Delete and then attempt to re-upload if file_srl is requested
|
||||
$file_srl = Context::get('file_srl');
|
||||
if($file_srl)
|
||||
{
|
||||
$file_info = FileModel::getFile($file_srl);
|
||||
if($file_info->file_srl == $file_srl && FileModel::isDeletable($file_info))
|
||||
if($file_info->file_srl == $file_srl && $file_info->upload_target_srl == $upload_target_srl && FileModel::isDeletable($file_info))
|
||||
{
|
||||
$this->deleteFile($file_srl);
|
||||
}
|
||||
|
|
@ -582,10 +600,18 @@ class FileController extends File
|
|||
$file_srl = Context::get('file_srl');
|
||||
$file_srls = Context::get('file_srls');
|
||||
if($file_srls) $file_srl = $file_srls;
|
||||
// Exit a session if there is neither upload permission nor information
|
||||
if(!$_SESSION['upload_info'][$editor_sequence]->enabled) exit();
|
||||
|
||||
// Exit a session if there is neither upload permission nor information
|
||||
if (!$_SESSION['upload_info'][$editor_sequence]->enabled)
|
||||
{
|
||||
throw new Rhymix\Framework\Exceptions\NotPermitted;
|
||||
}
|
||||
$upload_target_srl = $_SESSION['upload_info'][$editor_sequence]->upload_target_srl;
|
||||
if (!$upload_target_srl)
|
||||
{
|
||||
throw new Rhymix\Framework\Exceptions\TargetNotFound;
|
||||
}
|
||||
$module_srl = $_SESSION['upload_info'][$editor_sequence]->module_srl ?? 0;
|
||||
|
||||
$srls = explode(',',$file_srl);
|
||||
if(!count($srls)) return;
|
||||
|
|
@ -601,9 +627,10 @@ class FileController extends File
|
|||
if(!$output->toBool()) continue;
|
||||
|
||||
$file_info = $output->data;
|
||||
if(!$file_info) continue;
|
||||
if(!$file_info || $file_info->upload_target_srl != $upload_target_srl) continue;
|
||||
if($module_srl && $file_info->module_srl != $module_srl) continue;
|
||||
if(!FileModel::isDeletable($file_info)) continue;
|
||||
if($upload_target_srl && $file_srl) $output = $this->deleteFile($file_srl);
|
||||
$output = $this->deleteFile($file_srl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -709,9 +736,10 @@ class FileController extends File
|
|||
*
|
||||
* @param int $editor_sequence
|
||||
* @param int $upload_target_srl
|
||||
* @param int $module_srl
|
||||
* @return int
|
||||
*/
|
||||
function setUploadInfo($editor_sequence = 0, $upload_target_srl = 0)
|
||||
public static function setUploadInfo($editor_sequence = 0, $upload_target_srl = 0, $module_srl = 0)
|
||||
{
|
||||
if(!$editor_sequence)
|
||||
{
|
||||
|
|
@ -721,6 +749,14 @@ class FileController extends File
|
|||
}
|
||||
$editor_sequence = ++$_SESSION['_editor_sequence_'];
|
||||
}
|
||||
if(!$module_srl)
|
||||
{
|
||||
$current_module_info = Context::get('current_module_info');
|
||||
if (!empty($current_module_info->module_srl))
|
||||
{
|
||||
$module_srl = $current_module_info->module_srl;
|
||||
}
|
||||
}
|
||||
if(!isset($_SESSION['upload_info']) || !is_array($_SESSION['upload_info']))
|
||||
{
|
||||
$_SESSION['upload_info'] = array();
|
||||
|
|
@ -730,7 +766,12 @@ class FileController extends File
|
|||
$_SESSION['upload_info'][$editor_sequence] = new stdClass();
|
||||
}
|
||||
$_SESSION['upload_info'][$editor_sequence]->enabled = true;
|
||||
$_SESSION['upload_info'][$editor_sequence]->upload_target_srl = $upload_target_srl;
|
||||
$_SESSION['upload_info'][$editor_sequence]->upload_target_srl = (int)$upload_target_srl;
|
||||
$_SESSION['upload_info'][$editor_sequence]->module_srl = (int)$module_srl;
|
||||
if (!$module_srl)
|
||||
{
|
||||
trigger_error('No module_srl supplied to setUploadInfo(), and cannot determine automatically', E_USER_WARNING);
|
||||
}
|
||||
|
||||
return $editor_sequence;
|
||||
}
|
||||
|
|
@ -1740,17 +1781,32 @@ class FileController extends File
|
|||
public function procFileSetCoverImage()
|
||||
{
|
||||
$vars = Context::getRequestVars();
|
||||
$logged_info = Context::get('logged_info');
|
||||
|
||||
if(!$vars->editor_sequence) throw new Rhymix\Framework\Exceptions\InvalidRequest;
|
||||
|
||||
$upload_target_srl = $_SESSION['upload_info'][$vars->editor_sequence]->upload_target_srl;
|
||||
// Exit a session if there is neither upload permission nor information
|
||||
$editor_sequence = $vars->editor_sequence ?? 0;
|
||||
if (!$vars->editor_sequence)
|
||||
{
|
||||
throw new Rhymix\Framework\Exceptions\InvalidRequest;
|
||||
}
|
||||
if (!$_SESSION['upload_info'][$editor_sequence]->enabled)
|
||||
{
|
||||
throw new Rhymix\Framework\Exceptions\NotPermitted;
|
||||
}
|
||||
$upload_target_srl = $_SESSION['upload_info'][$editor_sequence]->upload_target_srl;
|
||||
if (!$upload_target_srl)
|
||||
{
|
||||
throw new Rhymix\Framework\Exceptions\TargetNotFound;
|
||||
}
|
||||
|
||||
$file_info = FileModel::getFile($vars->file_srl);
|
||||
|
||||
if(!$file_info) throw new Rhymix\Framework\Exceptions\TargetNotFound;
|
||||
|
||||
if(!$this->manager && !$file_info->member_srl === $logged_info->member_srl) throw new Rhymix\Framework\Exceptions\NotPermitted;
|
||||
if (!$file_info || $file_info->upload_target_srl != $upload_target_srl)
|
||||
{
|
||||
throw new Rhymix\Framework\Exceptions\TargetNotFound;
|
||||
}
|
||||
if(!$this->grant->manager && $file_info->member_srl != $this->user->member_srl)
|
||||
{
|
||||
throw new Rhymix\Framework\Exceptions\NotPermitted;
|
||||
}
|
||||
|
||||
$args = new stdClass();
|
||||
$args->file_srl = $vars->file_srl;
|
||||
|
|
@ -1769,7 +1825,6 @@ class FileController extends File
|
|||
|
||||
if($file_info->cover_image != 'Y')
|
||||
{
|
||||
|
||||
$args->cover_image = 'Y';
|
||||
$output = executeQuery('file.updateCoverImage', $args);
|
||||
if(!$output->toBool())
|
||||
|
|
@ -1777,7 +1832,6 @@ class FileController extends File
|
|||
$oDB->rollback();
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$oDB->commit();
|
||||
|
|
|
|||
|
|
@ -26,12 +26,8 @@ class FileModel extends File
|
|||
{
|
||||
$file_list = [];
|
||||
$attached_size = 0;
|
||||
$editor_sequence = Context::get('editor_sequence');
|
||||
$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;
|
||||
}
|
||||
$editor_sequence = intval(Context::get('editor_sequence'));
|
||||
$upload_target_srl = $_SESSION['upload_info'][$editor_sequence]->upload_target_srl ?? 0;
|
||||
|
||||
// Get uploaded files
|
||||
if($upload_target_srl)
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ $lang->about_save_changelog = 'Keep a log of new and deleted files in the databa
|
|||
$lang->cmd_delete_checked_file = 'Delete Selected Item(s)';
|
||||
$lang->cmd_move_to_document = 'Move to Document';
|
||||
$lang->cmd_download = 'Download';
|
||||
$lang->msg_invalid_upload_info = 'Invalid upload target information. (%s)';
|
||||
$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.';
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ $lang->about_save_changelog = '파일 저장 및 삭제 내역을 DB에 기록
|
|||
$lang->cmd_delete_checked_file = '선택항목 삭제';
|
||||
$lang->cmd_move_to_document = '문서로 이동';
|
||||
$lang->cmd_download = '다운로드';
|
||||
$lang->msg_invalid_upload_info = '업로드 대상 정보가 일치하지 않습니다. (%s)';
|
||||
$lang->msg_not_permitted_download = '다운로드할 수 있는 권한이 없습니다.';
|
||||
$lang->msg_file_cart_is_null = '삭제할 파일을 선택해주세요.';
|
||||
$lang->msg_checked_file_is_deleted = '%d개의 첨부 파일이 삭제되었습니다.';
|
||||
|
|
|
|||
|
|
@ -433,6 +433,14 @@ class MemberAdminView extends Member
|
|||
$option->editor_toolbar_hide = 'Y';
|
||||
$option->editor_skin = $member_config->signature_editor_skin;
|
||||
$option->sel_editor_colorset = $member_config->sel_editor_colorset;
|
||||
if (!$option->allow_html)
|
||||
{
|
||||
$option->editor_skin = 'textarea';
|
||||
}
|
||||
if ($option->allow_fileupload)
|
||||
{
|
||||
$option->module_srl = MemberView::getInstance()->getMemberModuleSrl();
|
||||
}
|
||||
|
||||
Context::set('editor', getModel('editor')->getEditor($member_info->member_srl, $option));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,6 +93,27 @@ class MemberView extends Member
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the module_srl for the member mid.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getMemberModuleSrl(): int
|
||||
{
|
||||
if (!$this->member_config)
|
||||
{
|
||||
$this->member_config = MemberModel::getMemberConfig();
|
||||
}
|
||||
if (!empty($this->member_config->mid))
|
||||
{
|
||||
return ModuleModel::getModuleInfoByMid($this->member_config->mid)->module_srl ?? 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Module index
|
||||
*/
|
||||
|
|
@ -334,6 +355,10 @@ class MemberView extends Member
|
|||
{
|
||||
$option->editor_skin = 'textarea';
|
||||
}
|
||||
if ($option->allow_fileupload)
|
||||
{
|
||||
$option->module_srl = $this->getMemberModuleSrl();
|
||||
}
|
||||
|
||||
Context::set('editor', getModel('editor')->getEditor(0, $option));
|
||||
}
|
||||
|
|
@ -448,6 +473,10 @@ class MemberView extends Member
|
|||
{
|
||||
$option->editor_skin = 'textarea';
|
||||
}
|
||||
if ($option->allow_fileupload)
|
||||
{
|
||||
$option->module_srl = $this->getMemberModuleSrl();
|
||||
}
|
||||
|
||||
Context::set('editor', getModel('editor')->getEditor($member_info->member_srl, $option));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ class TemplateTest extends \Codeception\Test\Unit
|
|||
public function _before()
|
||||
{
|
||||
Context::init();
|
||||
$this->baseurl = '/' . basename(dirname(dirname(dirname(__DIR__)))) . '/';
|
||||
}
|
||||
|
||||
public function testIsRelativePath()
|
||||
|
|
@ -48,7 +49,7 @@ class TemplateTest extends \Codeception\Test\Unit
|
|||
$this->assertEquals($target, $tmpl->convertPath($source));
|
||||
|
||||
$source = '^/foo/bar.gif';
|
||||
$target = '/rhymix/foo/bar.gif';
|
||||
$target = $this->baseurl . 'foo/bar.gif';
|
||||
$this->assertEquals($target, $tmpl->convertPath($source));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1145,9 +1145,9 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
|
|||
|
||||
// Check that resource is loaded
|
||||
$list = \Context::getJsFile('body');
|
||||
$this->assertStringContainsString('/rhymix/common/js/plugins/ckeditor/', array_first($list)['file']);
|
||||
$this->assertStringContainsString('/common/js/plugins/ckeditor/', array_first($list)['file']);
|
||||
$list = \Context::getCssFile();
|
||||
$this->assertStringContainsString('/rhymix/tests/_data/template/css/style.scss', array_first($list)['file']);
|
||||
$this->assertStringContainsString('/tests/_data/template/css/style.scss', array_first($list)['file']);
|
||||
}
|
||||
|
||||
public function testCompileLang()
|
||||
|
|
@ -1240,7 +1240,7 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
|
|||
);
|
||||
|
||||
$list = \Context::getJsFile();
|
||||
$this->assertStringContainsString('/rhymix/tests/_data/template/js/test.js', array_last($list)['file']);
|
||||
$this->assertStringContainsString('/tests/_data/template/js/test.js', array_last($list)['file']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1274,6 +1274,7 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
|
|||
protected function _normalizeWhitespace(string $content): string
|
||||
{
|
||||
$content = preg_replace('/<!--#Template(Start|End):.+?-->\n/', '', $content);
|
||||
$content = preg_replace('!(action|src)="' . preg_quote($this->baseurl, '!') . '!', '$1="/rhymix/', $content);
|
||||
|
||||
$result = [];
|
||||
foreach (explode("\n", $content) as $line)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue