From 3c3e510c2eca8ae6dd0283ffdeb0de2ce645714b Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 9 Sep 2025 15:24:54 +0900 Subject: [PATCH 01/19] Fix double escaping of document and comment summary --- modules/comment/comment.item.php | 15 ++++++++++----- modules/document/document.item.php | 31 +++++++++++++++++++----------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/modules/comment/comment.item.php b/modules/comment/comment.item.php index a372bc029..30508fc69 100644 --- a/modules/comment/comment.item.php +++ b/modules/comment/comment.item.php @@ -466,10 +466,12 @@ class CommentItem extends BaseObject $content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content)))); if($strlen) { - $content = cut_str($content, $strlen, '...'); + $content = escape(cut_str($content, $strlen, '...'), false); + } + else + { + $content = escape($content); } - - $content = escape($content); if ($content === '') { @@ -511,9 +513,12 @@ class CommentItem extends BaseObject $content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content)))); if($strlen) { - $content = cut_str($content, $strlen, '...'); + return escape(cut_str($content, $strlen, '...'), false); + } + else + { + return escape($content); } - return escape($content); } /** diff --git a/modules/document/document.item.php b/modules/document/document.item.php index dcf90e8d7..b183c43a2 100644 --- a/modules/document/document.item.php +++ b/modules/document/document.item.php @@ -634,10 +634,12 @@ class DocumentItem extends BaseObject $content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content)))); if($strlen) { - $content = cut_str($content, $strlen, '...'); + return escape(cut_str($content, $strlen, '...'), false); + } + else + { + return escape($content); } - - return escape($content); } function getContentText($strlen = 0) @@ -653,17 +655,22 @@ class DocumentItem extends BaseObject } $content = preg_replace('!(

||get('content')); - $content = preg_replace_callback('/<(object|param|embed)[^>]*/is', array($this, '_checkAllowScriptAccess'), $content); - $content = preg_replace_callback('/]*>/is', array($this, '_addAllowScriptAccess'), $content); + //$content = preg_replace_callback('/<(object|param|embed)[^>]*/is', array($this, '_checkAllowScriptAccess'), $content); + //$content = preg_replace_callback('/]*>/is', array($this, '_addAllowScriptAccess'), $content); + $content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content)))); if($strlen) { - $content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content)))); - $content = cut_str($content, $strlen, '...'); + return escape(cut_str($content, $strlen, '...'), false); + } + else + { + return escape($content); } - - return escape($content); } + /** + * @deprecated + */ function _addAllowScriptAccess($m) { if($this->allowscriptaccessList[$this->allowscriptaccessKey] == 1) @@ -674,6 +681,9 @@ class DocumentItem extends BaseObject return $m[0]; } + /** + * @deprecated + */ function _checkAllowScriptAccess($m) { if($m[1] == 'object') @@ -806,8 +816,7 @@ class DocumentItem extends BaseObject // Truncate string $content = cut_str($content, $str_size, $tail); - - return escape($content); + return escape($content, false); } function getRegdate($format = 'Y.m.d H:i:s', $conversion = true) From 9734473b49ffdcc1eb63d84e44ef8e2ddf6d8e86 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 9 Sep 2025 15:25:24 +0900 Subject: [PATCH 02/19] Initialize $_SESSION to an empty array even in CLI, to prevent spurious warnings later on --- classes/context/Context.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php index 0a2eb1f35..f4498857b 100644 --- a/classes/context/Context.class.php +++ b/classes/context/Context.class.php @@ -338,7 +338,11 @@ class Context } // start session - if (\PHP_SAPI !== 'cli') + if (\PHP_SAPI === 'cli') + { + $_SESSION = []; + } + else { if (self::$_current_request->getRouteOption('enable_session')) { From 5e4b48f19b2203d501831f11d42353d00b85b5e7 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 9 Sep 2025 15:30:29 +0900 Subject: [PATCH 03/19] Prevent direct access to cron.php on CLI --- common/scripts/cron.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/common/scripts/cron.php b/common/scripts/cron.php index 5d3ff146d..954d6a062 100644 --- a/common/scripts/cron.php +++ b/common/scripts/cron.php @@ -4,14 +4,18 @@ * This script runs the task queue. * * Unlike other scripts provided with Rhymix, it can be called - * both on the command line and over the network. + * both on the CLI (through index.php) and over the network (directly). */ define('RXQUEUE_CRON', true); // If called on the CLI, run additional checks. if (PHP_SAPI === 'cli') { - require_once __DIR__ . '/common.php'; + if (!defined('RX_VERSION')) + { + echo "Error: This script must not be called directly.\n"; + exit(1); + } } else { From 40067c0b53020ef6317b957ec3c83457bf68ce2c Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 9 Sep 2025 17:18:31 +0900 Subject: [PATCH 04/19] Support generated columns #2596 --- common/framework/parsers/DBTableParser.php | 15 ++++++- .../parsers/dbtable/GeneratedColumn.php | 12 ++++++ common/framework/parsers/dbtable/Table.php | 43 ++++++++++++------- tests/_data/dbtable/generated.xml | 9 ++++ .../framework/parsers/DBTableParserTest.php | 10 +++++ 5 files changed, 73 insertions(+), 16 deletions(-) create mode 100644 common/framework/parsers/dbtable/GeneratedColumn.php create mode 100644 tests/_data/dbtable/generated.xml diff --git a/common/framework/parsers/DBTableParser.php b/common/framework/parsers/DBTableParser.php index 50874a7d8..93e6ddb66 100644 --- a/common/framework/parsers/DBTableParser.php +++ b/common/framework/parsers/DBTableParser.php @@ -70,8 +70,21 @@ class DBTableParser extends BaseParser // Load columns. foreach ($xml->column as $column_info) { + // Is this column generated? + $is_generated = strval($column_info['generated'] ?? '') !== ''; + if ($is_generated) + { + $column = new DBTable\GeneratedColumn; + $column->generated = strtolower($column_info['generated']); + $column->is_stored = strtolower($column_info['stored'] ?? ''); + $column->is_stored = $column->is_stored !== 'virtual' && toBool($column->is_stored); + } + else + { + $column = new DBTable\Column; + } + // Get the column name and type. - $column = new DBTable\Column; $column->name = strval($column_info['name']); list($column->type, $column->xetype, $column->size) = self::getTypeAndSize(strval($column_info['type']), strval($column_info['size'])); diff --git a/common/framework/parsers/dbtable/GeneratedColumn.php b/common/framework/parsers/dbtable/GeneratedColumn.php new file mode 100644 index 000000000..60a9726fb --- /dev/null +++ b/common/framework/parsers/dbtable/GeneratedColumn.php @@ -0,0 +1,12 @@ +charset . ' COLLATE ' . $column->charset . '_general_ci'; } } + if ($column instanceof GeneratedColumn) + { + $columndef .= ' GENERATED ' . strtoupper($column->generated ?: 'always'); + $columndef .= ' AS (' . $column->default_value . ')'; + if ($column->is_stored) + { + $columndef .= ' STORED'; + } + } + else + { + if ($column->default_value !== null) + { + if (preg_match('/(?:int|float|double|decimal|number)/i', $column->type) && is_numeric($column->default_value)) + { + $columndef .= ' DEFAULT ' . $column->default_value; + } + elseif (preg_match('/^\w+\(\)$/', $column->default_value)) + { + $columndef .= ' DEFAULT ' . $column->default_value; + } + else + { + $columndef .= ' DEFAULT \'' . $column->default_value . '\''; + } + } + } if ($column->not_null) { $columndef .= ' NOT NULL'; } - if ($column->default_value !== null) - { - if (preg_match('/(?:int|float|double|decimal|number)/i', $column->type) && is_numeric($column->default_value)) - { - $columndef .= ' DEFAULT ' . $column->default_value; - } - elseif (preg_match('/^\w+\(\)$/', $column->default_value)) - { - $columndef .= ' DEFAULT ' . $column->default_value; - } - else - { - $columndef .= ' DEFAULT \'' . $column->default_value . '\''; - } - } if ($column->auto_increment) { $columndef .= ' AUTO_INCREMENT'; } + $columns[] = $columndef; } diff --git a/tests/_data/dbtable/generated.xml b/tests/_data/dbtable/generated.xml new file mode 100644 index 000000000..0c136faa3 --- /dev/null +++ b/tests/_data/dbtable/generated.xml @@ -0,0 +1,9 @@ + + + + + + + + +
diff --git a/tests/unit/framework/parsers/DBTableParserTest.php b/tests/unit/framework/parsers/DBTableParserTest.php index ab8b00d47..4c7b2e9ec 100644 --- a/tests/unit/framework/parsers/DBTableParserTest.php +++ b/tests/unit/framework/parsers/DBTableParserTest.php @@ -63,4 +63,14 @@ class DBTableParserTest extends \Codeception\Test\Unit $this->assertStringContainsString('CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci', $sql); $this->assertStringContainsString('ENGINE = InnoDB', $sql); } + + public function testGeneratedColumn() + { + $table = Rhymix\Framework\Parsers\DBTableParser::loadXML(\RX_BASEDIR . 'tests/_data/dbtable/generated.xml'); + $sql = $table->getCreateQuery('rx_'); + $this->assertStringContainsString('CREATE TABLE `rx_generated`', $sql); + $this->assertStringContainsString('`gentest1` BIGINT GENERATED ALWAYS AS (document_srl + member_srl) STORED NOT NULL,', $sql); + $this->assertStringContainsString('`gentest2` BIGINT GENERATED ALWAYS AS (MAX(module_srl, document_srl)),', $sql); + $this->assertStringContainsString('`gentest3` VARCHAR(40) GENERATED ALWAYS AS (CONCAT(module_srl, \'_\', document_srl)) NOT NULL,', $sql); + } } From c3102da73f87e6633bddf154aecf282e924e003b Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Wed, 10 Sep 2025 07:42:38 +0900 Subject: [PATCH 05/19] Fix #2600 misplaced decoding line --- modules/document/document.item.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/document/document.item.php b/modules/document/document.item.php index b183c43a2..1fdf94d8f 100644 --- a/modules/document/document.item.php +++ b/modules/document/document.item.php @@ -657,9 +657,9 @@ class DocumentItem extends BaseObject $content = preg_replace('!(

||get('content')); //$content = preg_replace_callback('/<(object|param|embed)[^>]*/is', array($this, '_checkAllowScriptAccess'), $content); //$content = preg_replace_callback('/]*>/is', array($this, '_addAllowScriptAccess'), $content); - $content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content)))); if($strlen) { + $content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content)))); return escape(cut_str($content, $strlen, '...'), false); } else From 85be8b76691b1addac047975e6cee662361cc60c Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 15 Sep 2025 00:27:41 +0900 Subject: [PATCH 06/19] Fix fatal error if getUnlinkedMenu() fails during module insert --- modules/module/module.controller.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/module/module.controller.php b/modules/module/module.controller.php index 7831e9f72..c7916f4cc 100644 --- a/modules/module/module.controller.php +++ b/modules/module/module.controller.php @@ -443,6 +443,10 @@ class ModuleController extends Module { $oMenuAdminController = getAdminController('menu'); $menuSrl = $oMenuAdminController->getUnlinkedMenu(); + if ($menuSrl instanceof BaseObject && !$menuSrl->toBool()) + { + return $menuSrl; + } $menuArgs->menu_srl = $menuSrl; $menuArgs->menu_item_srl = getNextSequence(); From 60552ba96bc116c67193579432e561dd0348616e Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 15 Sep 2025 00:30:00 +0900 Subject: [PATCH 07/19] Throw error in filterValue() if an unstringable object is given --- common/framework/parsers/dbquery/VariableBase.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/framework/parsers/dbquery/VariableBase.php b/common/framework/parsers/dbquery/VariableBase.php index 0c5f984dd..f4e29a0c5 100644 --- a/common/framework/parsers/dbquery/VariableBase.php +++ b/common/framework/parsers/dbquery/VariableBase.php @@ -398,7 +398,11 @@ class VariableBase // Don't apply a filter if there is no variable. $column = $this instanceof ColumnWrite ? $this->name : $this->column; $filter = isset($this->filter) ? $this->filter : ''; - if (!is_array($value) && strval($value) === '') + if (is_object($value) && !method_exists($value, '__toString')) + { + throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $column . ' is not stringable'); + } + if (is_scalar($value) && strval($value) === '') { $filter = ''; } From 146ff27801dfa689ae91891f5f5833f4ae0ff015 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 15 Sep 2025 00:34:38 +0900 Subject: [PATCH 08/19] Fix error when editing a domain whose index module has been deleted --- modules/module/queries/getDomainInfo.xml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/module/queries/getDomainInfo.xml b/modules/module/queries/getDomainInfo.xml index 09801fd88..29c00c7ec 100644 --- a/modules/module/queries/getDomainInfo.xml +++ b/modules/module/queries/getDomainInfo.xml @@ -1,7 +1,11 @@ -
+
+ + + +
@@ -9,7 +13,6 @@ - From 5d52df9c9aff150aaeb68bcc18990aa5a5b8196c Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 16 Sep 2025 14:26:34 +0900 Subject: [PATCH 09/19] Use empty() instead of simple ! to check superglobals --- classes/context/Context.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php index f4498857b..0c9f71190 100644 --- a/classes/context/Context.class.php +++ b/classes/context/Context.class.php @@ -1218,7 +1218,7 @@ class Context else { // Set HTTP_RAW_POST_DATA for third-party apps that look for it. - if (!$_POST && !isset($GLOBALS['HTTP_RAW_POST_DATA'])) + if (empty($_POST) && empty($_FILES) && !isset($GLOBALS['HTTP_RAW_POST_DATA'])) { $GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents('php://input'); } @@ -1234,7 +1234,7 @@ class Context } // Decide whether it's JSON or XMLRPC by looking at the first character of the POST data. - if (!$_POST && !empty($GLOBALS['HTTP_RAW_POST_DATA'])) + if (empty($_POST) && !empty($GLOBALS['HTTP_RAW_POST_DATA'])) { self::$_instance->request_method = substr($GLOBALS['HTTP_RAW_POST_DATA'], 0, 1) === '<' ? 'XMLRPC' : 'JSON'; return; @@ -1262,7 +1262,7 @@ class Context } // Set JSON and XMLRPC arguments. - if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' && !$_POST && !empty($GLOBALS['HTTP_RAW_POST_DATA'])) + if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' && empty($_POST) && !empty($GLOBALS['HTTP_RAW_POST_DATA'])) { $params = array(); $request_method = self::getRequestMethod(); From 6d25f663b199b578515952b5f2e7d5b08fa9b533 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 16 Sep 2025 14:35:47 +0900 Subject: [PATCH 10/19] Fix double escape of summary in RSS --- modules/rss/tpl/format/rss10.html | 2 +- modules/rss/tpl/format/rss20.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/rss/tpl/format/rss10.html b/modules/rss/tpl/format/rss10.html index d04b25392..d829d1bd9 100644 --- a/modules/rss/tpl/format/rss10.html +++ b/modules/rss/tpl/format/rss10.html @@ -28,7 +28,7 @@ {$oDocument->getTitleText()} {$oDocument->getPermanentUrl()} - {$oDocument->getSummary(400)|escape} + {$oDocument->getSummary(400)} {$oDocument->getNickName()} {date('c', ztime($oDocument->get('regdate')))} diff --git a/modules/rss/tpl/format/rss20.html b/modules/rss/tpl/format/rss20.html index 0343a938c..b88e42a09 100644 --- a/modules/rss/tpl/format/rss20.html +++ b/modules/rss/tpl/format/rss20.html @@ -22,7 +22,7 @@ {\Rhymix\Framework\Filters\HTMLFilter::fixRelativeUrls(utf8_trim(utf8_normalize_spaces($oDocument->get('content'))))|escape} - {$oDocument->getSummary(400)|escape} + {$oDocument->getSummary(400)} {Context::replaceUserLang($oDocument->getModuleName())} {Context::replaceUserLang($category_name)} From 61ea93064a8087be95ae8286ec396c39096e0981 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 16 Sep 2025 20:33:54 +0900 Subject: [PATCH 11/19] Remove deprecated exec_xml() from signup value check function --- modules/member/tpl/js/signup_check.js | 31 ++++++++++++++------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/modules/member/tpl/js/signup_check.js b/modules/member/tpl/js/signup_check.js index 5c4d2e1a4..7b0ff1585 100644 --- a/modules/member/tpl/js/signup_check.js +++ b/modules/member/tpl/js/signup_check.js @@ -19,31 +19,32 @@ function memberSetEvent() { // 실제 서버에 특정 필드의 value check를 요청하고 이상이 있으면 메세지를 뿌려주는 함수 function memberCheckValue(event) { var field = event.target; - var _name = field.name; - var _value = field.value; - if(!_name || !_value) return; + if(!field.name || !field.value) { + return; + } - var params = {name:_name, value:_value}; - var response_tags = ['error','message']; - - exec_xml('member','procMemberCheckValue', params, completeMemberCheckValue, response_tags, field); + exec_json('member.procMemberCheckValue', { + name: field.name, + value: field.value + }, function(data) { + completeMemberCheckValue(data, null, field); + }); } // 서버에서 응답이 올 경우 이상이 있으면 메세지를 출력 -function completeMemberCheckValue(ret_obj, response_tags, field) { +function completeMemberCheckValue(data, unused, field) { var _id = 'dummy_check'+field.name; var dummy = jQuery('#'+_id); - - if(ret_obj['message']=='success') { - dummy.html('').hide(); - return; - } - if (!dummy.length) { dummy = jQuery('

').attr('id', _id).appendTo(field.parentNode); } - dummy.html(ret_obj['message']).show(); + if(data.message == 'success') { + dummy.html('').hide(); + return; + } else { + dummy.html(data.message).show(); + } } // 결과 메세지를 정리하는 함수 From dcd84033cf9263973cffd23e23324b30075dc5a5 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Thu, 18 Sep 2025 19:39:37 +0900 Subject: [PATCH 12/19] Set default layout_file depending on the current layout_path --- classes/display/HTMLDisplayHandler.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/classes/display/HTMLDisplayHandler.php b/classes/display/HTMLDisplayHandler.php index 4f9a09bce..609fe787a 100644 --- a/classes/display/HTMLDisplayHandler.php +++ b/classes/display/HTMLDisplayHandler.php @@ -151,13 +151,20 @@ class HTMLDisplayHandler Context::loadFile(array($edited_layout_css, 'all', '', 100)); } } - if(!$layout_path) + if (!$layout_path) { $layout_path = './common/tpl'; } - if(!$layout_file) + if (!$layout_file) { - $layout_file = 'default_layout'; + if ($layout_path === './common/tpl') + { + $layout_file = 'default_layout'; + } + else + { + $layout_file = 'layout'; + } } $oTemplate = new Rhymix\Framework\Template; From 16b6544f9dc66e76ca23ae7c3780d6a2732cf5d4 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Sat, 20 Sep 2025 11:34:54 +0900 Subject: [PATCH 13/19] Fix null return value when regexp replace fails on invalid input --- common/functions.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/functions.php b/common/functions.php index 84b923681..2e2080687 100644 --- a/common/functions.php +++ b/common/functions.php @@ -671,7 +671,7 @@ function utf8_mbencode($str): string $bytes = array(ord($m[0][0]), ord($m[0][1]), ord($m[0][2]), ord($m[0][3])); $codepoint = ((0x07 & $bytes[0]) << 18) + ((0x3F & $bytes[1]) << 12) + ((0x3F & $bytes[2]) << 6) + (0x3F & $bytes[3]); return '&#x' . dechex($codepoint) . ';'; - }, (string)$str); + }, (string)$str) ?? ''; } /** @@ -686,11 +686,11 @@ function utf8_normalize_spaces($str, bool $multiline = false): string { if ($multiline) { - return preg_replace(['/((?!\x0A)[\pZ\pC])+/u', '/\x20*\x0A\x20*/'], [' ', "\n"], (string)$str); + return preg_replace(['/((?!\x0A)[\pZ\pC])+/u', '/\x20*\x0A\x20*/'], [' ', "\n"], (string)$str) ?? ''; } else { - return preg_replace('/[\pZ\pC]+/u', ' ', (string)$str); + return preg_replace('/[\pZ\pC]+/u', ' ', (string)$str) ?? ''; } } From 847415f1af41c60c67a1ba0214b390fa8ae6f8af Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 30 Sep 2025 20:49:40 +0900 Subject: [PATCH 14/19] Fix warning when domain is not given --- modules/admin/admin.admin.model.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/admin/admin.admin.model.php b/modules/admin/admin.admin.model.php index cdaaed1dc..b45f9f457 100644 --- a/modules/admin/admin.admin.model.php +++ b/modules/admin/admin.admin.model.php @@ -56,11 +56,7 @@ class AdminAdminModel extends Admin */ public function getSiteAllList() { - if(Context::get('domain')) - { - $domain = Context::get('domain'); - } - $siteList = $this->getAllSitesThatHaveModules($domain); + $siteList = $this->getAllSitesThatHaveModules(Context::get('domain')); $this->add('site_list', $siteList); } From 4869d4384d87c11fea404288c30d2a0aebc758d5 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 30 Sep 2025 22:07:57 +0900 Subject: [PATCH 15/19] Remove unnecessary
tag from uploader error messages --- common/js/plugins/jquery.fileupload/js/main.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/js/plugins/jquery.fileupload/js/main.js b/common/js/plugins/jquery.fileupload/js/main.js index 6d7be5095..40a94dba2 100644 --- a/common/js/plugins/jquery.fileupload/js/main.js +++ b/common/js/plugins/jquery.fileupload/js/main.js @@ -145,7 +145,7 @@ chunkfail: function(e, res) { lastUploadTime = Date.now(); if (chunkStatus) { - alert(window.xe.lang.msg_file_upload_error + " (Type 3)" + "
\n" + res.errorThrown + "
\n" + res.textStatus); + alert(window.xe.lang.msg_file_upload_error + " (Type 3)" + "\n" + res.errorThrown + "\n" + res.textStatus); return chunkStatus = false; } }, @@ -169,7 +169,7 @@ result = jQuery.parseJSON(result); } if (!result) { - alert(window.xe.lang.msg_file_upload_error + " (Type 5)" + "
\n" + res.response().result); + alert(window.xe.lang.msg_file_upload_error + " (Type 5)" + "\n" + res.response().result); return false; } @@ -215,7 +215,7 @@ return false; } else { $container.data('editorStatus', null); - alert(window.xe.lang.msg_file_upload_error + " (Type 6)" + "
\n" + res.response().result); + alert(window.xe.lang.msg_file_upload_error + " (Type 6)" + "\n" + res.response().result); return false; } }, @@ -229,7 +229,7 @@ } }, 1000); if (chunkStatus) { - alert(window.xe.lang.msg_file_upload_error + " (Type 7)" + "
\n" + res.errorThrown + "
\n" + res.textStatus); + alert(window.xe.lang.msg_file_upload_error + " (Type 7)" + "\n" + res.errorThrown + "\n" + res.textStatus); return false; } }, From 5dcc0f92a467515b4052244d7babb5c3b064dddc Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 30 Sep 2025 22:16:35 +0900 Subject: [PATCH 16/19] Fix incorrect request_uri and other JS variables if accessed on an unconfigured domain --- classes/module/ModuleHandler.class.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/classes/module/ModuleHandler.class.php b/classes/module/ModuleHandler.class.php index 5b910d223..e0faee25e 100644 --- a/classes/module/ModuleHandler.class.php +++ b/classes/module/ModuleHandler.class.php @@ -151,7 +151,16 @@ class ModuleHandler extends Handler $site_module_info->domain = Rhymix\Framework\URL::getCurrentDomain(); $site_module_info->is_default_domain = 'N'; $site_module_info->is_default_replaced = true; + + // Reset context variables if the domain was replaced. Context::set('site_module_info', $site_module_info); + Context::set('_default_url', null); + Context::set('request_uri', $current_url = Context::getRequestUri()); + if ($query_string = http_build_query(Context::getCurrentRequest()->args)) + { + $current_url .= '?' . $query_string; + } + Context::set('current_url', $current_url); } } } From 653ca4f697dadcd75401e86a892ca771d677b697 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 30 Sep 2025 22:27:36 +0900 Subject: [PATCH 17/19] Add "TABLE" to list of keywords to recognize in addPrefixes() --- common/framework/DB.php | 6 +++--- tests/unit/framework/DBTest.php | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/common/framework/DB.php b/common/framework/DB.php index b436ce9e8..0f30246e8 100644 --- a/common/framework/DB.php +++ b/common/framework/DB.php @@ -1126,17 +1126,17 @@ class DB } else { - $exceptions = []; + $exceptions = ['TABLE']; } // Add prefixes to all other table names in the query string. - return preg_replace_callback('/\b((?:DELETE\s+)?FROM|JOIN|INTO|(?assertEquals($target, $oDB->addPrefixes($source)); + $source = "LOAD DATA LOCAL INFILE '/tmp/foo.csv' INTO TABLE foo_table FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n' (a, b, c)"; + $target = "LOAD DATA LOCAL INFILE '/tmp/foo.csv' INTO TABLE `" . $prefix . "foo_table` FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n' (a, b, c)"; + $this->assertEquals($target, $oDB->addPrefixes($source)); + + $source = 'ALTER TABLE documents ADD INDEX idx_foo (a, b)'; + $target = 'ALTER TABLE `' . $prefix . 'documents` ADD INDEX idx_foo (a, b)'; + $this->assertEquals($target, $oDB->addPrefixes($source)); + + $source = 'TRUNCATE TABLE documents'; + $target = 'TRUNCATE TABLE `' . $prefix . 'documents`'; + $this->assertEquals($target, $oDB->addPrefixes($source)); + + $source = 'DROP TABLE documents'; + $target = 'DROP TABLE `' . $prefix . 'documents`'; + $this->assertEquals($target, $oDB->addPrefixes($source)); + $source = 'update documents set a = ?, b = ? where c = ?'; $this->assertEquals($source, $oDB->addPrefixes($source)); From 32c9c91b825747a215b45f672df407d0994a3e81 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 30 Sep 2025 22:35:10 +0900 Subject: [PATCH 18/19] Fix stretching of image on mobile --- addons/photoswipe/rx_photoswipe.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/addons/photoswipe/rx_photoswipe.js b/addons/photoswipe/rx_photoswipe.js index dc06dc4be..d21fbabce 100644 --- a/addons/photoswipe/rx_photoswipe.js +++ b/addons/photoswipe/rx_photoswipe.js @@ -25,7 +25,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) { // CSS selector for photoswipe items. var ps_find_selector = 'img:not(' + ps_skip_elements + ps_skip_class + '), img' + ps_enroll_class; - // parse slide data (url, title, size ...) from DOM elements + // parse slide data (url, title, size ...) from DOM elements // (children of gallerySelector) var parseThumbnailElements = function(el) { var imgElements = $(el).find(ps_find_selector), @@ -39,7 +39,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) { imgEl = imgElements.get(i); // element - // include only element nodes + // include only element nodes if (imgEl.nodeType !== 1 || !imgEl.src || !$(imgEl).attr('data-pswp-pid')) { continue; } @@ -56,11 +56,11 @@ var initPhotoSwipeFromDOM = function(gallerySelector) { var ps_skip_alt_class = '.photoswipe-no-caption'; if(imgEl.alt && !$(imgEl).is(ps_skip_alt_class)) { - item.title = imgEl.alt; + item.title = imgEl.alt; } if(imgEl.title && !$(imgEl).is(ps_skip_alt_class)) { - item.title = imgEl.title; + item.title = imgEl.title; } item.el = imgEl; // save link to element for getThumbBoundsFn @@ -87,7 +87,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) { if(!clickedListItem) { return; } - + e = e || window.event; e.preventDefault ? e.preventDefault() : e.returnValue = false; @@ -108,8 +108,8 @@ var initPhotoSwipeFromDOM = function(gallerySelector) { }*/ for (var i = 0; i < numChildNodes; i++) { - if(childNodes[i].nodeType !== 1 || !$(childNodes[i]).attr('data-pswp-pid')) { - continue; + if(childNodes[i].nodeType !== 1 || !$(childNodes[i]).attr('data-pswp-pid')) { + continue; } if(childNodes[i] === clickedListItem) { @@ -140,7 +140,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) { if(!vars[i]) { continue; } - var pair = vars[i].split('='); + var pair = vars[i].split('='); if(pair.length < 2) { continue; } @@ -172,7 +172,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) { // See Options -> getThumbBoundsFn section of documentation for more info var thumbnail = items[index].el, pageYScroll = window.pageYOffset || document.documentElement.scrollTop, - rect = thumbnail.getBoundingClientRect(); + rect = thumbnail.getBoundingClientRect(); return {x:rect.left, y:rect.top + pageYScroll, w:rect.width}; }, @@ -191,7 +191,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) { // PhotoSwipe opened from URL if(fromURL) { if(options.galleryPIDs) { - // parse real index when custom PIDs are used + // parse real index when custom PIDs are used // http://photoswipe.com/documentation/faq.html#custom-pid-in-url for(var j = 0; j < items.length; j++) { if(items[j].pid == index) { @@ -232,6 +232,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) { var regx_skip = /(?:(modules|addons|classes|common|layouts|libs|widgets|widgetstyles)\/)/i; var regx_allow_i6pngfix = /(?:common\/tpl\/images\/blank\.gif$)/i; + var isMobile = String(navigator.userAgent).match(/mobile/i); var galleryImgEls = $(galleryElements[i]).find(ps_find_selector); for(var j = 0, jl = galleryImgEls.length; j < jl; j++) { // skip components @@ -240,6 +241,11 @@ var initPhotoSwipeFromDOM = function(gallerySelector) { //$(galleryImgEls[j]).attr('data-pswp-uid', i+1); $(galleryImgEls[j]).attr('data-pswp-pid', j+1); + // Fix stretching of image on mobile + if (isMobile) { + galleryImgEls[j].style.height = 'auto'; + galleryImgEls[j].height = null; + } } } From 8671c058d57b57614730d78df069693e917e0182 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 30 Sep 2025 22:45:28 +0900 Subject: [PATCH 19/19] Fix incorrect page range when there are not enough pages #2602 --- classes/page/PageHandler.class.php | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/classes/page/PageHandler.class.php b/classes/page/PageHandler.class.php index 82d45e97f..0a74fcd0f 100644 --- a/classes/page/PageHandler.class.php +++ b/classes/page/PageHandler.class.php @@ -44,24 +44,23 @@ class PageHandler extends Handler implements Iterator $this->page_count = $page_count; $this->point = 0; - $first_page = $cur_page - (int) ($page_count / 2); - if($first_page < 1) + if ($this->cur_page > $total_page) { - $first_page = 1; + $this->cur_page = $total_page; + } + if ($this->page_count > $total_page) + { + $this->page_count = $total_page; } - if($total_page > $page_count && $first_page + $page_count - 1 > $total_page) + $first_page = max(1, $this->cur_page - floor($this->page_count / 2)); + if (($first_page + $this->page_count - 1) > $total_page) { - $first_page -= $first_page + $page_count - 1 - $total_page; + $first_page = max(1, $total_page - $this->page_count + 1); } $this->first_page = $first_page; $this->last_page = $total_page; - - if($total_page < $this->page_count) - { - $this->page_count = $total_page; - } } /**