Merge pull request #1256 from kijin/pr/download-short-url

파일 다운로드시 짧은주소 지원 #1251
This commit is contained in:
Kijin Sung 2020-03-18 10:52:27 +09:00 committed by GitHub
commit 7664987a2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 48 additions and 28 deletions

View file

@ -39,3 +39,6 @@ RewriteRule ^([a-zA-Z0-9_]+)/([0-9]+)$ ./index.php?mid=$1&document_srl=$2 [L,QSA
# mid + entry title # mid + entry title
RewriteRule ^([a-zA-Z0-9_]+)/entry/(.+)$ ./index.php?mid=$1&entry=$2 [L,QSA] RewriteRule ^([a-zA-Z0-9_]+)/entry/(.+)$ ./index.php?mid=$1&entry=$2 [L,QSA]
# file download
RewriteRule ^files/download/([0-9]+)/([a-zA-Z0-9_-]+)/(.+)$ ./index.php?act=procFileOutput&file_srl=$1&file_key=$2&filename=$3 [L]

View file

@ -228,12 +228,6 @@ class UA
return $result; return $result;
} }
} }
if ($result->os === 'Android' && preg_match('#^AndroidDownloadManager/([0-9])#', $ua, $matches))
{
$result->browser = 'Android';
$result->version = $matches[1];
return $result;
}
if (preg_match('#Edge/([0-9]+\\.)#', $ua, $matches)) if (preg_match('#Edge/([0-9]+\\.)#', $ua, $matches))
{ {
$result->browser = 'Edge'; $result->browser = 'Edge';
@ -341,14 +335,8 @@ class UA
// Get the browser name and version. // Get the browser name and version.
$browser = self::getBrowserInfo($ua); $browser = self::getBrowserInfo($ua);
// Get the Android version.
if ($browser->os === 'Android')
{
$android_version = preg_match('/Android ([0-9]+)/', $ua, $matches) ? intval($matches[1]) : 0;
}
// Find the best format that this browser supports. // Find the best format that this browser supports.
if ($browser->browser === 'Chrome' && $browser->version >= 11 && !$browser->is_webview) if ($browser->browser === 'Chrome' && $browser->version >= 11 & !$browser->is_webview)
{ {
$output_format = 'rfc5987'; $output_format = 'rfc5987';
} }
@ -374,14 +362,7 @@ class UA
} }
elseif ($browser->browser === 'Android' || $browser->browser === 'Whale' || $browser->is_webview) elseif ($browser->browser === 'Android' || $browser->browser === 'Whale' || $browser->is_webview)
{ {
if ($android_version >= 10) $output_format = 'raw';
{
$output_format = 'rfc5987';
}
else
{
$output_format = 'raw';
}
} }
elseif ($browser->browser === 'Chrome' || $browser->browser === 'Safari') elseif ($browser->browser === 'Chrome' || $browser->browser === 'Safari')
{ {

View file

@ -52,3 +52,6 @@ rewrite ^/rhymix/([a-zA-Z0-9_]+)/([0-9]+)$ /rhymix/index.php?mid=$1&document_srl
# mid + entry title # mid + entry title
rewrite ^/rhymix/([a-zA-Z0-9_]+)/entry/(.+)$ /rhymix/index.php?mid=$1&entry=$2 last; rewrite ^/rhymix/([a-zA-Z0-9_]+)/entry/(.+)$ /rhymix/index.php?mid=$1&entry=$2 last;
# file download
rewrite ^/rhymix/files/download/([0-9]+)/([a-zA-Z0-9_-]+)/(.+)$ /rhymix/index.php?act=procFileOutput&file_srl=$1&file_key=$2&filename=$3 last;

View file

@ -52,3 +52,6 @@ rewrite ^/([a-zA-Z0-9_]+)/([0-9]+)$ /index.php?mid=$1&document_srl=$2 last;
# mid + entry title # mid + entry title
rewrite ^/([a-zA-Z0-9_]+)/entry/(.+)$ /index.php?mid=$1&entry=$2 last; rewrite ^/([a-zA-Z0-9_]+)/entry/(.+)$ /index.php?mid=$1&entry=$2 last;
# file download
rewrite ^/files/download/([0-9]+)/([a-zA-Z0-9_-]+)/(.+)$ /index.php?act=procFileOutput&file_srl=$1&file_key=$2&filename=$3 last;

View file

@ -130,6 +130,7 @@ class fileAdminController extends file
$config->allow_outlink = Context::get('allow_outlink'); $config->allow_outlink = Context::get('allow_outlink');
$config->allow_outlink_format = Context::get('allow_outlink_format'); $config->allow_outlink_format = Context::get('allow_outlink_format');
$config->allow_outlink_site = Context::get('allow_outlink_site'); $config->allow_outlink_site = Context::get('allow_outlink_site');
$config->download_short_url = Context::get('download_short_url') === 'Y' ? 'Y' : 'N';
$config->inline_download_format = array_map('utf8_trim', Context::get('inline_download_format')); $config->inline_download_format = array_map('utf8_trim', Context::get('inline_download_format'));
// Save and redirect // Save and redirect

View file

@ -384,7 +384,17 @@ class fileController extends file
$file_key_data = sprintf('%d:%d:%s:%s', $file_obj->file_srl, $file_key_timestamp, $file_obj->uploaded_filename, \RX_CLIENT_IP); $file_key_data = sprintf('%d:%d:%s:%s', $file_obj->file_srl, $file_key_timestamp, $file_obj->uploaded_filename, \RX_CLIENT_IP);
$file_key_sig = \Rhymix\Framework\Security::createSignature($file_key_data); $file_key_sig = \Rhymix\Framework\Security::createSignature($file_key_data);
$file_key = dechex($file_key_timestamp) . $file_key_sig; $file_key = dechex($file_key_timestamp) . $file_key_sig;
header('Location: '.getNotEncodedUrl('', 'act', 'procFileOutput', 'file_srl', $file_srl, 'file_key', $file_key, 'force_download', Context::get('force_download') === 'Y' ? 'Y' : null));
// Use short URL or long URL
if ($file_module_config->download_short_url === 'Y' && config('use_rewrite'))
{
$url = RX_BASEURL . sprintf('files/download/%d/%s/%s', $file_srl, $file_key, rawurlencode($filename));
}
else
{
$url = getNotEncodedUrl('', 'act', 'procFileOutput', 'file_srl', $file_srl, 'file_key', $file_key, 'force_download', Context::get('force_download') === 'Y' ? 'Y' : null);
}
header('Location: ' . $url);
Context::close(); Context::close();
exit(); exit();
} }
@ -395,7 +405,8 @@ class fileController extends file
$oFileModel = getModel('file'); $oFileModel = getModel('file');
$file_srl = Context::get('file_srl'); $file_srl = Context::get('file_srl');
$file_key = Context::get('file_key'); $file_key = Context::get('file_key');
$filename_arg = Context::get('filename');
$columnList = array('source_filename', 'uploaded_filename', 'file_size'); $columnList = array('source_filename', 'uploaded_filename', 'file_size');
$file_obj = $oFileModel->getFile($file_srl, $columnList); $file_obj = $oFileModel->getFile($file_srl, $columnList);
$file_config = $oFileModel->getFileConfig($file_obj->module_srl ?: null); $file_config = $oFileModel->getFileConfig($file_obj->module_srl ?: null);
@ -441,7 +452,14 @@ class fileController extends file
} }
// Encode the filename. // Encode the filename.
$filename_param = Rhymix\Framework\UA::encodeFilenameForDownload($filename); if ($filename_arg && $filename_arg === $filename)
{
$filename_param = '';
}
else
{
$filename_param = '; ' . Rhymix\Framework\UA::encodeFilenameForDownload($filename);
}
// Close context to prevent blocking the session // Close context to prevent blocking the session
Context::close(); Context::close();
@ -508,7 +526,7 @@ class fileController extends file
// Set filename headers // Set filename headers
header('Content-Type: ' . ($download_type === 'inline' ? $mime_type : 'application/octet-stream')); header('Content-Type: ' . ($download_type === 'inline' ? $mime_type : 'application/octet-stream'));
header('Content-Disposition: ' . $download_type . '; ' . $filename_param); header('Content-Disposition: ' . $download_type . $filename_param);
// Set cache headers // Set cache headers
header('Cache-Control: private; max-age=3600'); header('Cache-Control: private; max-age=3600');

View file

@ -300,6 +300,7 @@ class fileModel extends file
$config->allowed_filetypes = $config->allowed_filetypes ?? '*.*'; $config->allowed_filetypes = $config->allowed_filetypes ?? '*.*';
$config->allow_outlink = $config->allow_outlink ?? 'Y'; $config->allow_outlink = $config->allow_outlink ?? 'Y';
$config->download_grant = $config->download_grant ?? []; $config->download_grant = $config->download_grant ?? [];
$config->download_short_url = $config->download_short_url ?? 'N';
$config->inline_download_format = $config->inline_download_format ?? []; $config->inline_download_format = $config->inline_download_format ?? [];
$config->image_autoconv = $config->image_autoconv ?? []; $config->image_autoconv = $config->image_autoconv ?? [];
$config->image_quality_adjustment = $config->image_quality_adjustment ?? 75; $config->image_quality_adjustment = $config->image_quality_adjustment ?? 75;

View file

@ -18,6 +18,7 @@ $lang->allow_outlink_format = 'Allowed Formats';
$lang->allowed_filesize = 'Maximum File Size'; $lang->allowed_filesize = 'Maximum File Size';
$lang->allowed_attach_size = 'Maximum Attachments'; $lang->allowed_attach_size = 'Maximum Attachments';
$lang->allowed_filetypes = 'Allowed extentsions'; $lang->allowed_filetypes = 'Allowed extentsions';
$lang->download_short_url = 'Use short URL';
$lang->inline_download_format = 'Open in current window'; $lang->inline_download_format = 'Open in current window';
$lang->inline_download_image = 'Image'; $lang->inline_download_image = 'Image';
$lang->inline_download_audio = 'Audio'; $lang->inline_download_audio = 'Audio';
@ -27,6 +28,7 @@ $lang->inline_download_pdf = 'PDF';
$lang->file_save_changelog = 'Save changelog'; $lang->file_save_changelog = 'Save changelog';
$lang->use_default_file_config = 'Use Default Settings'; $lang->use_default_file_config = 'Use Default Settings';
$lang->about_use_default_file_config = 'Follow the default settings from the File module.'; $lang->about_use_default_file_config = 'Follow the default settings from the File module.';
$lang->about_download_short_url = 'Using short URLs can fix broken filenames in Android and some other platforms.<br />Short URLs must be enabled, and rewrite rules must be updated to the latest version if you use nginx.';
$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->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->enable_download_group = 'Downloadable Groups';
$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 = '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.';
@ -101,4 +103,4 @@ $lang->about_video_mp4_gif_time = 'treat silent MP4 videos with duration less th
$lang->ffmpeg_path = 'FFmpeg path'; $lang->ffmpeg_path = 'FFmpeg path';
$lang->ffprobe_path = 'FFprobe path'; $lang->ffprobe_path = 'FFprobe path';
$lang->msg_cannot_use_ffmpeg = 'FFmpeg and FFprobe must can be executed by PHP.'; $lang->msg_cannot_use_ffmpeg = 'FFmpeg and FFprobe must can be executed by PHP.';
$lang->msg_cannot_use_exif = 'PHP Exif module is required.'; $lang->msg_cannot_use_exif = 'PHP Exif module is required.';

View file

@ -18,6 +18,7 @@ $lang->allow_outlink_format = '외부 접근 허용 확장자';
$lang->allowed_filesize = '파일 용량 제한'; $lang->allowed_filesize = '파일 용량 제한';
$lang->allowed_attach_size = '문서 첨부 제한'; $lang->allowed_attach_size = '문서 첨부 제한';
$lang->allowed_filetypes = '허용 확장자'; $lang->allowed_filetypes = '허용 확장자';
$lang->download_short_url = '다운로드시 짧은주소 사용';
$lang->inline_download_format = '다운로드시 현재 창 사용'; $lang->inline_download_format = '다운로드시 현재 창 사용';
$lang->inline_download_image = '이미지'; $lang->inline_download_image = '이미지';
$lang->inline_download_audio = '오디오'; $lang->inline_download_audio = '오디오';
@ -27,6 +28,7 @@ $lang->inline_download_pdf = 'PDF';
$lang->file_save_changelog = '변경 내역 기록'; $lang->file_save_changelog = '변경 내역 기록';
$lang->use_default_file_config = '기본 파일 설정 사용'; $lang->use_default_file_config = '기본 파일 설정 사용';
$lang->about_use_default_file_config = '파일 모듈의 기본 설정을 따릅니다.'; $lang->about_use_default_file_config = '파일 모듈의 기본 설정을 따릅니다.';
$lang->about_download_short_url = '안드로이드 등 일부 환경에서 첨부파일 다운로드시 파일명이 깨지는 문제를 해결할 수 있습니다.<br />짧은주소 사용이 활성화되어 있어야 하며, nginx 사용시 rewrite 규칙을 최신 버전으로 업데이트하여야 합니다.';
$lang->about_inline_download_format = '선택한 종류의 파일은 다운로드 링크를 클릭하더라도 다운로드 창을 열지 않고 현재 창에 표시합니다.'; $lang->about_inline_download_format = '선택한 종류의 파일은 다운로드 링크를 클릭하더라도 다운로드 창을 열지 않고 현재 창에 표시합니다.';
$lang->enable_download_group = '다운로드 가능 그룹'; $lang->enable_download_group = '다운로드 가능 그룹';
$lang->about_allow_outlink = '다른 사이트에서 파일 다운로드 링크에 직접 접근하는 것을 허용합니다.<br />본문에 바로 삽입할 수 있는 이미지 파일은 라이믹스에서 접근을 통제할 수 없으며, 이를 차단하려면 웹서버 설정이 필요합니다.'; $lang->about_allow_outlink = '다른 사이트에서 파일 다운로드 링크에 직접 접근하는 것을 허용합니다.<br />본문에 바로 삽입할 수 있는 이미지 파일은 라이믹스에서 접근을 통제할 수 없으며, 이를 차단하려면 웹서버 설정이 필요합니다.';

View file

@ -30,6 +30,14 @@
<p class="x_help-block">{$lang->about_allow_outlink_site}</p> <p class="x_help-block">{$lang->about_allow_outlink_site}</p>
</div> </div>
</div> </div>
<div class="x_control-group">
<label class="x_control-label">{$lang->download_short_url}</label>
<div class="x_controls">
<label class="x_inline"><input type="radio" name="download_short_url" value="Y" checked="checked"|cond="$config->download_short_url === 'Y' && config('use_rewrite')" disabled="disabled"|cond="!config('use_rewrite')" /> {$lang->cmd_yes}</label>
<label class="x_inline"><input type="radio" name="download_short_url" value="N" checked="checked"|cond="$config->download_short_url !== 'Y' || !config('use_rewrite')" disabled="disabled"|cond="!config('use_rewrite')" /> {$lang->cmd_no}</label>
<p class="x_help-block">{$lang->about_download_short_url}</p>
</div>
</div>
<div class="x_control-group"> <div class="x_control-group">
<label class="x_control-label">{$lang->inline_download_format}</label> <label class="x_control-label">{$lang->inline_download_format}</label>
<div class="x_controls"> <div class="x_controls">

View file

@ -310,8 +310,6 @@ class UATest extends \Codeception\TestCase\Test
$this->assertEquals('filename*=UTF-8\'\'%ED%95%9C%EA%B8%80%20filename.jpg', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'Edge/12.10240')); $this->assertEquals('filename*=UTF-8\'\'%ED%95%9C%EA%B8%80%20filename.jpg', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'Edge/12.10240'));
$this->assertEquals('filename*=UTF-8\'\'%ED%95%9C%EA%B8%80%20filename.jpg', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'MSIE/7.0 Trident/7.0')); $this->assertEquals('filename*=UTF-8\'\'%ED%95%9C%EA%B8%80%20filename.jpg', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'MSIE/7.0 Trident/7.0'));
$this->assertEquals('filename*=UTF-8\'\'%ED%95%9C%EA%B8%80%20filename.jpg', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko')); $this->assertEquals('filename*=UTF-8\'\'%ED%95%9C%EA%B8%80%20filename.jpg', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko'));
$this->assertEquals('filename*=UTF-8\'\'%ED%95%9C%EA%B8%80%20filename.jpg', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'Mozilla/5.0 (Linux; Android 10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.92 Mobile Safari/537.36'));
$this->assertEquals('filename*=UTF-8\'\'%ED%95%9C%EA%B8%80%20filename.jpg', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'AndroidDownloadManager/10 (Linux; U; Android 10)'));
$this->assertEquals('filename="%ED%95%9C%EA%B8%80%20filename.jpg"', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'MSIE 8.0')); $this->assertEquals('filename="%ED%95%9C%EA%B8%80%20filename.jpg"', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'MSIE 8.0'));
$this->assertEquals('filename="%ED%95%9C%EA%B8%80%20filename.jpg"', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'Unknown Browser')); $this->assertEquals('filename="%ED%95%9C%EA%B8%80%20filename.jpg"', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'Unknown Browser'));
$this->assertEquals('filename="한글 filename.jpg"', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'Chrome/69.0.3497.128 Whale/1.0.0.0 Crosswalk/23.69.590.31 Mobile Safari/537.36 NAVER(inapp; search; 660; 10.7.2)')); $this->assertEquals('filename="한글 filename.jpg"', Rhymix\Framework\UA::encodeFilenameForDownload('한글 filename.jpg', 'Chrome/69.0.3497.128 Whale/1.0.0.0 Crosswalk/23.69.590.31 Mobile Safari/537.36 NAVER(inapp; search; 660; 10.7.2)'));