diff --git a/classes/file/FileHandler.class.php b/classes/file/FileHandler.class.php index 7bf59e4b8..aa5f6aaba 100644 --- a/classes/file/FileHandler.class.php +++ b/classes/file/FileHandler.class.php @@ -467,7 +467,7 @@ class FileHandler { $K64 = 65536; $TWEAKFACTOR = 2.0; - $channels = $imageInfo['channels']; + $channels = $imageInfo['channels'] ?? 6; if(!$channels) { $channels = 6; //for png diff --git a/common/framework/Image.php b/common/framework/Image.php index 4b814abc7..0cad986e2 100644 --- a/common/framework/Image.php +++ b/common/framework/Image.php @@ -15,7 +15,7 @@ class Image */ public static function isImage(string $filename): bool { - return array_shift(explode('/', MIME::getContentType($filename))) === 'image'; + return preg_match('!^image/!', MIME::getContentType($filename)); } /** diff --git a/common/framework/parsers/BaseParser.php b/common/framework/parsers/BaseParser.php index 37fbcb0bb..a70cda735 100644 --- a/common/framework/parsers/BaseParser.php +++ b/common/framework/parsers/BaseParser.php @@ -110,9 +110,10 @@ abstract class BaseParser * @param \SimpleXMLElement $extra_vars * @param string $lang * @param string $type + * @param array $options * @return object */ - protected static function _getExtraVars(\SimpleXMLElement $extra_vars, string $lang, string $type = ''): \stdClass + protected static function _getExtraVars(\SimpleXMLElement $extra_vars, string $lang, string $type = '', array $options = []): \stdClass { $result = new \stdClass; @@ -120,7 +121,7 @@ abstract class BaseParser $group_name = $extra_vars->getName() === 'group' ? self::_getChildrenByLang($extra_vars, 'title', $lang) : null; foreach ($extra_vars->group ?: [] as $group) { - $group_result = self::_getExtraVars($group, $lang, $type); + $group_result = self::_getExtraVars($group, $lang, $type, $options); foreach ($group_result as $key => $val) { $result->{$key} = $val; @@ -172,13 +173,36 @@ abstract class BaseParser { $item->default = self::_getChildrenByLang($var, 'default', $lang); } - $item->value = null; + if ($type === 'skin') + { + $item->value = trim($var['value'] ?? '') ?: null; + if ($item->value && preg_match('/(,|\|@\|)/', $item->value ?? '', $delimiter)) + { + $item->value = explode($delimiter[1], $item->value); + } + if ($item->type === 'mid_list' && !is_array($item->value)) + { + $item->value = [$item->value]; + } + } + else + { + $item->value = null; + } // Options - if ($var->options) + if ($type === 'skin' && $options['version'] === '0.1') { - $item->options = array(); - foreach ($var->options as $option) + $xml_options = $var->default ?? null; + } + else + { + $xml_options = $var->options ?? null; + } + if ($xml_options) + { + $item->options = []; + foreach ($xml_options as $option) { if ($type === 'widget' || $type === 'widgetstyle') { @@ -193,16 +217,58 @@ abstract class BaseParser $item->init_options[$value] = true; } } + elseif ($type === 'layout') + { + $option_item = new \stdClass; + if (!empty($option['src'])) + { + $thumbnail_path = $options['layout_path'] . $option['src']; + if (file_exists($thumbnail_path)) + { + $option_item->thumbnail = $thumbnail_path; + $item->thumbnail_exist = true; + } + } + $title = self::_getChildrenByLang($option, 'title', $lang); + $value = trim($option['value'] ?? ''); + $option_item->val = $title; + $item->options[$value] = $option_item; + } + elseif ($type === 'skin' && $options['version'] === '0.1') + { + $option_item = new \stdClass; + $option_item->title = trim($option); + $option_item->value = trim($option); + $item->options[] = $option_item; // Numeric keys only + } + elseif ($type === 'skin' && $options['version'] === '0.2') + { + $option_item = new \stdClass; + $option_item->title = self::_getChildrenByLang($option, 'title', $lang); + $option_item->value = trim($option['value'] ?? ''); + $item->options[] = $option_item; // Numeric keys only + } else { $option_item = new \stdClass; $option_item->title = self::_getChildrenByLang($option, 'title', $lang); $option_item->value = trim($option['value'] ?? '') ?: trim($option->value ?? ''); - $item->options[$option_item->value] = $option_item; + $item->options[trim($option_item->value ?? '')] = $option_item; } } } + // Other attributes + if ($type === 'skin' && $options['version'] === '0.1') + { + $item->width = intval($var['width'] ?? 0) ?: null; + $item->height = intval($var['height'] ?? 0) ?: null; + if (isset($item->options) && count($item->options)) + { + $item->default = reset($item->options)->value; + } + } + // Add to list of variables if ($type === 'widget' || $type === 'widgetstyle') { diff --git a/common/framework/parsers/DBQueryParser.php b/common/framework/parsers/DBQueryParser.php index 674648682..ecbf7d958 100644 --- a/common/framework/parsers/DBQueryParser.php +++ b/common/framework/parsers/DBQueryParser.php @@ -286,6 +286,7 @@ class DBQueryParser extends BaseParser $group->conditions = self::_parseConditions($tag); $group->pipe = strtoupper($attribs['pipe'] ?? '') ?: 'AND'; $group->ifvar = $attribs['if'] ?? null; + $group->not_null = ($attribs['notnull'] ?? false) ? true : false; $result[] = $group; } elseif ($name === 'query') diff --git a/common/framework/parsers/LayoutInfoParser.php b/common/framework/parsers/LayoutInfoParser.php new file mode 100644 index 000000000..a7d20919a --- /dev/null +++ b/common/framework/parsers/LayoutInfoParser.php @@ -0,0 +1,128 @@ +layout = $layout_name; + $info->type = trim($xml['type'] ?? ''); + $info->path = $layout_path; + + // Get the XML schema version. + $version = strval($xml['version']) ?: '0.1'; + + // Parse version 0.2 + if ($version === '0.2') + { + $info->title = self::_getChildrenByLang($xml, 'title', $lang) ?: $layout_name; + $info->description = self::_getChildrenByLang($xml, 'description', $lang); + $info->version = trim($xml->version); + $info->date = ($xml->date === 'RX_CORE') ? '' : date('Ymd', strtotime($xml->date . 'T12:00:00Z')); + $info->homepage = trim($xml->link); + $info->license = trim($xml->license); + $info->license_link = trim($xml->license['link'] ?? ''); + $info->author = array(); + + foreach ($xml->author as $author) + { + $author_info = new \stdClass; + $author_info->name = self::_getChildrenByLang($author, 'name', $lang); + $author_info->email_address = trim($author['email_address'] ?? ''); + $author_info->homepage = trim($author['link'] ?? ''); + $info->author[] = $author_info; + } + } + + // Parse version 0.1 + else + { + $info->title = self::_getChildrenByLang($xml, 'title', $lang) ?: $layout_name; + $info->description = self::_getChildrenByLang($xml->author, 'description', $lang); + $info->version = trim($xml['version'] ?? ''); + $info->date = date('Ymd', strtotime($xml->author['date'] . 'T12:00:00Z')); + $info->homepage = trim($xml->link); + $info->license = trim($xml->license); + $info->license_link = trim($xml->license['link'] ?? ''); + $info->author = array(); + + $author_info = new \stdClass; + $author_info->name = self::_getChildrenByLang($xml->author, 'name', $lang); + $author_info->email_address = trim($xml->author['email_address']); + $author_info->homepage = trim($xml->author['link'] ?? ''); + $info->author[] = $author_info; + } + + // Get extra_vars. + $info->extra_var_count = 0; + if ($xml->extra_vars) + { + $info->extra_var = self::_getExtraVars($xml->extra_vars, $lang, 'layout', ['layout_path' => $layout_path]); + } + else + { + $info->extra_var = new \stdClass; + } + + // Count extra vars. + $info->extra_var_count = count(get_object_vars($info->extra_var)); + + // Get menus. + $info->menu_count = 0; + if (isset($xml->menus->menu)) + { + $info->menu = new \stdClass; + foreach ($xml->menus->menu as $menu) + { + $menu_item = new \stdClass; + $menu_item->name = trim($menu['name'] ?? ''); + $menu_item->title = self::_getChildrenByLang($menu, 'title', $lang); + $menu_item->maxdepth = intval($menu['maxdepth'] ?? 0); + $menu_item->menu_srl = null; + $menu_item->xml_file = ''; + $menu_item->php_file = ''; + $info->menu->{$menu_item->name} = $menu_item; + $info->menu_count++; + } + } + else + { + $info->menu = null; + } + $info->menu_name_list = null; + + // Prepare additional fields that will be filled in later. + $info->site_srl = 0; + $info->layout_srl = 0; + $info->layout_title = ''; + $info->header_script = ''; + + // Return the complete result. + return $info; + } +} diff --git a/common/framework/parsers/SkinInfoParser.php b/common/framework/parsers/SkinInfoParser.php new file mode 100644 index 000000000..88b75e963 --- /dev/null +++ b/common/framework/parsers/SkinInfoParser.php @@ -0,0 +1,122 @@ +skin = $skin_name; + $info->path = $skin_path; + + // Get the XML schema version. + $version = strval($xml['version']) ?: '0.1'; + + // Parse version 0.2 + if ($version === '0.2') + { + $info->title = self::_getChildrenByLang($xml, 'title', $lang) ?: $skin_name; + $info->description = self::_getChildrenByLang($xml, 'description', $lang); + $info->version = trim($xml->version); + $info->date = ($xml->date === 'RX_CORE') ? '' : date('Ymd', strtotime($xml->date . 'T12:00:00Z')); + $info->homepage = trim($xml->link); + $info->license = trim($xml->license); + $info->license_link = trim($xml->license['link'] ?? ''); + $info->author = array(); + + foreach ($xml->author as $author) + { + $author_info = new \stdClass; + $author_info->name = self::_getChildrenByLang($author, 'name', $lang); + $author_info->email_address = trim($author['email_address'] ?? ''); + $author_info->homepage = trim($author['link'] ?? ''); + $info->author[] = $author_info; + } + } + + // Parse version 0.1 + else + { + $info->title = self::_getChildrenByLang($xml, 'title', $lang) ?: $skin_name; + $info->description = self::_getChildrenByLang($xml->maker, 'description', $lang); + $info->version = trim($xml['version'] ?? ''); + $info->date = date('Ymd', strtotime($xml->maker['date'] . 'T12:00:00Z')); + $info->homepage = trim($xml->link); + $info->license = trim($xml->license); + $info->license_link = trim($xml->license['link'] ?? ''); + $info->author = array(); + + $author_info = new \stdClass; + $author_info->name = self::_getChildrenByLang($xml->maker, 'name', $lang); + $author_info->email_address = trim($xml->maker['email_address']); + $author_info->homepage = trim($xml->maker['link'] ?? ''); + $info->author[] = $author_info; + } + + // Get extra_vars. + if ($xml->extra_vars) + { + $info->extra_vars = get_object_vars(self::_getExtraVars($xml->extra_vars, $lang, 'skin', ['version' => $version])); + } + else + { + $info->extra_vars = []; + } + + // Get colorsets. + if ($xml->colorset && $xml->colorset->color) + { + $info->colorset = []; + foreach ($xml->colorset->color as $color) + { + $color_item = new \stdClass; + $color_item->name = trim($color['name'] ?? ''); + $color_item->title = self::_getChildrenByLang($color, 'title', $lang); + $screenshot = trim($color['src'] ?? ''); + if ($screenshot) + { + $screenshot = $info->path . $screenshot; + } + $color_item->screenshot = $screenshot; + $info->colorset[] = $color_item; + } + } + + // Get thumbnail path. + if (file_exists($info->path . 'thumbnail.png')) + { + $info->thumbnail = $info->path . 'thumbnail.png'; + } + else + { + $info->thumbnail = ''; + } + + // Return the complete result. + return $info; + } +} diff --git a/common/framework/parsers/dbquery/ConditionGroup.php b/common/framework/parsers/dbquery/ConditionGroup.php index c234582f4..6fde2fc16 100644 --- a/common/framework/parsers/dbquery/ConditionGroup.php +++ b/common/framework/parsers/dbquery/ConditionGroup.php @@ -10,4 +10,5 @@ class ConditionGroup public $conditions = array(); public $pipe = 'AND'; public $ifvar; + public $not_null; } diff --git a/common/framework/parsers/dbquery/Query.php b/common/framework/parsers/dbquery/Query.php index bde3cda9d..a1b18d20b 100644 --- a/common/framework/parsers/dbquery/Query.php +++ b/common/framework/parsers/dbquery/Query.php @@ -580,6 +580,10 @@ class Query extends VariableBase { $result .= ($result === '' ? '' : (' ' . $condition->pipe . ' ')) . '(' . $condition_string . ')'; } + elseif ($condition->not_null) + { + throw new \Rhymix\Framework\Exceptions\QueryError('Condition group marked as NOT NULL must contain at least one valid condition'); + } } // Simple condition diff --git a/common/js/common.js b/common/js/common.js index ee59e72d3..e4c9602f4 100644 --- a/common/js/common.js +++ b/common/js/common.js @@ -403,11 +403,18 @@ Rhymix.modal.close = function(id) { */ Rhymix.ajax = function(action, params, success, error) { - // Extract action info + // Extract module and act + let isFormData = params instanceof FormData; + let module, act; if (!action) { - if (params instanceof FormData) { - action = (params.get('module') || params.get('mid')) + '.' + params.get('act'); - if (action === '.') { + if (isFormData) { + module = params.get('module'); + act = params.get('act'); + if (module && act) { + action = module + '.' + act; + } else if (act) { + action = act; + } else { action = null; } } else { @@ -416,13 +423,16 @@ Rhymix.ajax = function(action, params, success, error) { } else { action = action.split('.'); params = params || {}; - params.module = action[0]; - params.act = action[1]; + params.module = module = action[0]; + params.act = act = action[1]; action = action.join('.'); } // Add action to URL if the current rewrite level supports it - let url = this.URI(window.request_uri).pathname(); + let url = this.URI(window.request_uri).pathname() + 'index.php'; + if (act) { + url = url + '?act=' + act; + } /* if (this.getRewriteLevel() >= 2 && action !== null) { url = url + action.replace('.', '/'); @@ -431,31 +441,36 @@ Rhymix.ajax = function(action, params, success, error) { } */ - // Add a CSRF token. - const headers = {}; - if (action !== null) { - headers['X-CSRF-Token'] = getCSRFToken(); + // Add a CSRF token to the header, and remove it from the parameters + const headers = { + 'X-CSRF-Token': getCSRFToken() + }; + if (isFormData && params.has('_rx_csrf_token') && params.get('_rx_csrf_token') === headers['X-CSRF-Token']) { + params.delete('_rx_csrf_token'); + } + if (typeof params._rx_csrf_token !== 'undefined' && params._rx_csrf_token === headers['X-CSRF-Token']) { + delete params._rx_csrf_token; + } + + // Generate AJAX parameters + const args = { + type: 'POST', + dataType: 'json', + url: url, + data: isFormData ? params : JSON.stringify(params), + contentType: isFormData ? false : 'application/json; charset=UTF-8', + processData: false, + headers: headers, + success: function(data, textStatus, xhr) { + Rhymix._ajaxSuccessHandler(xhr, textStatus, action, data, params, success, error); + }, + error: function(xhr, textStatus, errorThrown) { + Rhymix._ajaxErrorHandler(xhr, textStatus, action, url, params, success, error); + } }; // Send the AJAX request try { - const args = { - type: 'POST', - dataType: 'json', - url: url, - data: params, - processData: (action !== null && !(params instanceof FormData)), - headers : headers, - success : function(data, textStatus, xhr) { - Rhymix.ajaxSuccessHandler(xhr, textStatus, action, data, params, success, error); - }, - error : function(xhr, textStatus, errorThrown) { - Rhymix.ajaxErrorHandler(xhr, textStatus, action, url, params, success, error); - } - }; - if (params instanceof FormData) { - args.contentType = false; - } $.ajax(args); } catch(e) { alert(e); @@ -474,7 +489,7 @@ Rhymix.ajax = function(action, params, success, error) { * @param function errror * @return void */ -Rhymix.ajaxSuccessHandler = function(xhr, textStatus, action, data, params, success, error) { +Rhymix._ajaxSuccessHandler = function(xhr, textStatus, action, data, params, success, error) { // Add debug information. if (data._rx_debug) { @@ -541,7 +556,7 @@ Rhymix.ajaxSuccessHandler = function(xhr, textStatus, action, data, params, succ * @param function errror * @return void */ -Rhymix.ajaxErrorHandler = function(xhr, textStatus, action, url, params, success, error) { +Rhymix._ajaxErrorHandler = function(xhr, textStatus, action, url, params, success, error) { // If the user is navigating away, don't do anything. if (xhr.status == 0 && this.unloading) { @@ -555,7 +570,7 @@ Rhymix.ajaxErrorHandler = function(xhr, textStatus, action, url, params, success data = JSON.parse(xhr.responseText); } catch (e) { } if (data && typeof data.error !== 'undefined') { - this.ajaxSuccessHandler(xhr, textStatus, action, data, params, success, error); + this._ajaxSuccessHandler(xhr, textStatus, action, data, params, success, error); return; } } diff --git a/common/legacy.php b/common/legacy.php index e254d38eb..f236ae67b 100644 --- a/common/legacy.php +++ b/common/legacy.php @@ -574,7 +574,7 @@ function zgap($timestamp = null): int */ function ztime($str): ?int { - $len = strlen($str); + $len = strlen($str ?? ''); if (!$len) { return null; diff --git a/modules/admin/controllers/Dashboard.php b/modules/admin/controllers/Dashboard.php index 365244a13..c05116469 100644 --- a/modules/admin/controllers/Dashboard.php +++ b/modules/admin/controllers/Dashboard.php @@ -185,8 +185,8 @@ class Dashboard extends Base $params["act"] = "getResourceapiLastupdate"; $body = \XmlGenerater::generate($params); $buff = FileHandler::getRemoteResource($config->download_server, $body, 3, "POST", "application/xml"); - $lUpdateDoc = \Rhymix\Framework\Parsers\XEXMLParser::loadXMLString($buff); - $updateDate = $lUpdateDoc->response->updatedate->body; + $lUpdateDoc = simplexml_load_string($buff); + $updateDate = trim($lUpdateDoc->updatedate); if(!$updateDate) { diff --git a/modules/admin/controllers/ServerEnv.php b/modules/admin/controllers/ServerEnv.php index 79a393aa2..c233c1fe3 100644 --- a/modules/admin/controllers/ServerEnv.php +++ b/modules/admin/controllers/ServerEnv.php @@ -175,13 +175,12 @@ class ServerEnv extends Base // Widgets $info[] = '[Widgets]'; $info['widget'] = array(); - $oWidgetModel = WidgetModel::getInstance(); - $widget_list = $oWidgetModel->getDownloadedWidgetList() ?: array(); + $widget_list = WidgetModel::getDownloadedWidgetList() ?: array(); foreach ($widget_list as $widget) { if (!in_array($widget->widget, $skip['widget'])) { - $widgetInfo = $oWidgetModel->getWidgetInfo($widget->widget); + $widgetInfo = WidgetModel::getWidgetInfo($widget->widget); if ($widgetInfo->version === 'RX_VERSION') { $info['widget'][] = $widget->widget; @@ -198,13 +197,12 @@ class ServerEnv extends Base // Widgetstyles $info[] = '[Widgetstyles]'; $info['widgetstyle'] = array(); - $oWidgetModel = WidgetModel::getInstance(); - $widgetstyle_list = $oWidgetModel->getDownloadedWidgetStyleList() ?: array(); + $widgetstyle_list = WidgetModel::getDownloadedWidgetStyleList() ?: array(); foreach ($widgetstyle_list as $widgetstyle) { if (!in_array($widgetstyle->widgetStyle, $skip['widgetstyle'])) { - $widgetstyleInfo = $oWidgetModel->getWidgetStyleInfo($widgetstyle->widgetStyle); + $widgetstyleInfo = WidgetModel::getWidgetStyleInfo($widgetstyle->widgetStyle); if ($widgetstyleInfo->version === 'RX_VERSION') { $info['widgetstyle'][] = $widgetstyle->widgetStyle; diff --git a/modules/admin/controllers/maintenance/Cleanup.php b/modules/admin/controllers/maintenance/Cleanup.php index d1ed217cc..15df3c529 100644 --- a/modules/admin/controllers/maintenance/Cleanup.php +++ b/modules/admin/controllers/maintenance/Cleanup.php @@ -300,16 +300,32 @@ class Cleanup extends Base 'classes/db/DBSqlite3_pdo.class.php' => 'deleted:xe', 'classes/db/queryparts/' => 'deleted:xe', 'classes/object/BaseObject.class.php' => 'deleted:xe', + 'classes/security/conf/' => 'deleted:xe', + 'classes/security/htmlpurifier/' => 'deleted:xe', + 'classes/security/phphtmlparser/' => 'deleted:xe', 'classes/xml/XmlQueryParser.class.php' => 'deleted:xe', 'classes/xml/xmlquery/' => 'deleted:xe', + 'common/css/mobile.css' => 'deleted', + 'common/css/mobile.min.css' => 'deleted', 'common/css/rhymix.less' => 'deleted', + 'common/css/xe.css' => 'deleted:xe', + 'common/css/xe.min.css' => 'deleted:xe', 'common/framework/drivers/cache/wincache.php' => 'deleted', 'common/framework/drivers/cache/xcache.php' => 'deleted', 'common/img/flvplayer.swf' => 'deleted:xe', + 'common/js/URI.js' => 'moved:common/js/plugins/uri/URI.min.js', + 'common/js/blankshield.min.js' => 'moved:common/js/plugins/blankshield/blankshield.min.js', 'common/js/html5.js' => 'deleted', 'common/js/jquery-1.12.4.min.js' => 'deleted', 'common/js/jquery-1.12.4.js' => 'deleted', + 'common/js/jquery-1.x.js' => 'deleted', + 'common/js/jquery-1.x.min.js' => 'deleted', + 'common/js/jquery.js' => 'deleted', + 'common/js/jquery.min.js' => 'deleted', 'common/js/respond.min.js' => 'deleted', + 'common/js/x.min.js' => 'deleted', + 'common/js/xe.js' => 'deleted:xe', + 'common/js/xe.min.js' => 'deleted:xe', 'common/js/plugins/jquery.migrate/jquery-migrate-1.4.1.js' => 'deleted', 'common/js/plugins/spectrum/bower.json' => 'deleted', 'common/js/plugins/spectrum/Gruntfile.js' => 'deleted', @@ -319,12 +335,22 @@ class Cleanup extends Base 'common/js/plugins/spectrum/docs/' => 'deleted', 'common/js/plugins/spectrum/example/' => 'deleted', 'common/js/plugins/spectrum/test/' => 'deleted', + 'common/lang/lang.info' => 'deleted:xe', 'common/libraries/bmp.php' => 'deleted', 'common/manual/server_config/rhymix-nginx-help.md' => 'deleted', + 'common/tpl/mobile_layout.html' => 'deleted:xe', 'common/tpl/redirect.html' => 'deleted:xe', + 'common/tpl/sitelock.html' => 'deleted:xe', 'config/func.inc.php' => 'deleted:xe', 'config/package.inc.php' => 'deleted:xe', 'doxygen/' => 'deleted:xe', + 'layouts/xedition/css/layout.min.css' => 'deleted', + 'layouts/xedition/css/webfont.min.css' => 'deleted', + 'layouts/xedition/css/welcome.min.css' => 'deleted', + 'layouts/xedition/css/widget.login.min.css' => 'deleted', + 'layouts/xedition/css/xeicon.min.css' => 'deleted', + 'layouts/xedition/js/layout.min.js' => 'deleted', + 'layouts/xedition/js/welcome.min.js' => 'deleted', 'libs/' => 'deleted:xe', 'modules/admin/ruleset/toggleFavorite.xml' => 'deleted', 'modules/admin/tpl/config_ftp.html' => 'deleted', @@ -335,6 +361,12 @@ class Cleanup extends Base 'modules/admin/tpl/img/bgDragable.gif' => 'deleted', 'modules/admin/tpl/img/faviconSample.png' => 'deleted', 'modules/admin/tpl/img/mobiconSample.png' => 'deleted', + 'modules/admin/tpl/check_env.html' => 'deleted', + 'modules/admin/tpl/config_general.html' => 'deleted', + 'modules/admin/tpl/css/admin.bootstrap.min.css' => 'deleted', + 'modules/admin/tpl/css/admin_en.css' => 'deleted:xe', + 'modules/admin/tpl/css/admin_jp.css' => 'deleted:xe', + 'modules/admin/tpl/css/admin_ko.css' => 'deleted:xe', 'modules/autoinstall/ruleset/' => 'deleted:xe', 'modules/autoinstall/tpl/filter/uninstall_package.xml' => 'deleted:xe', 'modules/board/board.wap.php' => 'deleted:xe', @@ -349,6 +381,13 @@ class Cleanup extends Base 'modules/counter/queries/updateSiteCounterUnique.xml' => 'deleted:xe', 'modules/counter/queries/updateSiteTotalCounterUnique.xml' => 'deleted:xe', 'modules/editor/components/emoticon/tpl/popup.less' => 'deleted', + 'modules/editor/components/emoticon/tpl/popup.css' => 'deleted', + 'modules/editor/components/image_gallery/tpl/gallery.min.js' => 'deleted', + 'modules/editor/components/image_gallery/tpl/list_gallery.min.js' => 'deleted', + 'modules/editor/components/image_gallery/tpl/popup.min.css' => 'deleted', + 'modules/editor/components/image_gallery/tpl/popup.min.js' => 'deleted', + 'modules/editor/components/image_gallery/tpl/slide_gallery.min.css' => 'deleted', + 'modules/editor/components/image_gallery/tpl/slide_gallery.min.js' => 'deleted', 'modules/editor/skins/ckeditor/js/default.js' => 'deleted', 'modules/editor/skins/ckeditor/js/default.min.js' => 'deleted', 'modules/editor/skins/ckeditor/js/xe_interface.js' => 'deleted', @@ -357,13 +396,65 @@ class Cleanup extends Base 'modules/editor/skins/simpleeditor/css/simpleeditor.less' => 'deleted', 'modules/editor/skins/xpresseditor/' => 'deleted:xe', 'modules/editor/styles/' => 'deleted:xe', + 'modules/editor/tpl/js/editor.js' => 'deleted:xe', + 'modules/editor/tpl/js/editor.min.js' => 'deleted:xe', + 'modules/editor/tpl/js/swfupload.js' => 'deleted:xe', + 'modules/editor/tpl/js/swfupload.min.js' => 'deleted:xe', + 'modules/editor/tpl/js/uploader.js' => 'deleted:xe', + 'modules/editor/tpl/js/uploader.min.js' => 'deleted:xe', 'modules/editor/tpl/preview.html' => 'deleted', 'modules/file/ruleset/imageResize.xml' => 'deleted', + 'modules/importer/tpl/js/importer_admin.min.js' => 'deleted', + 'modules/install/ruleset/config.xml' => 'deleted:xe', + 'modules/install/ruleset/cubrid.xml' => 'deleted:xe', + 'modules/install/ruleset/firebird.xml' => 'deleted:xe', + 'modules/install/ruleset/installFtpInfo.xml' => 'deleted:xe', + 'modules/install/ruleset/mssql.xml' => 'deleted:xe', + 'modules/install/ruleset/mysql.xml' => 'deleted:xe', + 'modules/install/ruleset/postgresql.xml' => 'deleted:xe', + 'modules/install/ruleset/sqlite.xml' => 'deleted:xe', + 'modules/install/script/welcome_content/welcome_content_de.html' => 'deleted', + 'modules/install/script/welcome_content/welcome_content_en.html' => 'deleted', + 'modules/install/script/welcome_content/welcome_content_es.html' => 'deleted', + 'modules/install/script/welcome_content/welcome_content_fr.html' => 'deleted', + 'modules/install/script/welcome_content/welcome_content_jp.html' => 'deleted', + 'modules/install/script/welcome_content/welcome_content_ko.html' => 'deleted', + 'modules/install/script/welcome_content/welcome_content_mn.html' => 'deleted', + 'modules/install/script/welcome_content/welcome_content_ru.html' => 'deleted', + 'modules/install/script/welcome_content/welcome_content_tr.html' => 'deleted', + 'modules/install/script/welcome_content/welcome_content_vi.html' => 'deleted', + 'modules/install/script/welcome_content/welcome_content_zh-CN.html' => 'deleted', + 'modules/install/script/welcome_content/welcome_content_zh-TW.html' => 'deleted', + 'modules/install/tpl/admin_form.html' => 'deleted:xe', + 'modules/install/tpl/after_upload_config_image.html' => 'deleted:xe', + 'modules/install/tpl/config_form.html' => 'deleted:xe', + 'modules/install/tpl/form.cubrid.html' => 'deleted:xe', + 'modules/install/tpl/form.mssql.html' => 'deleted:xe', + 'modules/install/tpl/form.mysql.html' => 'deleted:xe', + 'modules/install/tpl/form.mysql_innodb.html' => 'deleted:xe', + 'modules/install/tpl/form.mysqli.html' => 'deleted:xe', + 'modules/install/tpl/form.mysqli_innodb.html' => 'deleted:xe', + 'modules/install/tpl/ftp.html' => 'deleted:xe', + 'modules/install/tpl/select_db.html' => 'deleted:xe', + 'modules/install/tpl/js/install_admin.js' => 'deleted:xe', 'modules/integration_search/skins/default/trackback.html' => 'deleted', + 'modules/member/skins/default/filter/find_member_account_by_question.xml' => 'deleted:xe', 'modules/module/schemas/site_admin.xml' => 'deleted', 'modules/module/tpl/css/module_admin.less' => 'deleted', 'modules/page/page.wap.php' => 'deleted:xe', 'modules/page/tpl/css/mpage.css' => 'deleted', + 'modules/poll/skins/default/css/poll.min.css' => 'deleted', + 'modules/poll/skins/simple/css/poll.min.css' => 'deleted', + 'modules/poll/tpl/css/poll.min.css' => 'deleted', + 'modules/poll/tpl/js/poll.min.js' => 'deleted', + 'modules/poll/tpl/js/poll_admin.min.js' => 'deleted', + 'modules/rss/tpl/atom10.html' => 'deleted', + 'modules/rss/tpl/display.html' => 'deleted', + 'modules/rss/tpl/index.html' => 'deleted', + 'modules/rss/tpl/rss10.html' => 'deleted', + 'modules/rss/tpl/rss20.html' => 'deleted', + 'modules/rss/tpl/top_refresh.html' => 'deleted', + 'modules/rss/tpl/xe_rss.html' => 'deleted', 'modules/spamfilter/spamfilter.lib.php' => 'deleted', 'modules/spamfilter/ruleset/' => 'deleted', 'phpDoc/' => 'deleted:xe', diff --git a/modules/board/board.admin.view.php b/modules/board/board.admin.view.php index 6c86b0b90..654c4347e 100644 --- a/modules/board/board.admin.view.php +++ b/modules/board/board.admin.view.php @@ -142,6 +142,9 @@ class BoardAdminView extends Board { return $this->alertMessage('msg_invalid_request'); } + // Fix missing module configuration values + BoardModel::fixModuleConfig($this->module_info); + // get the skins list $oModuleModel = getModel('module'); $skin_list = $oModuleModel->getSkins($this->module_path); @@ -199,6 +202,10 @@ class BoardAdminView extends Board { * additonal setup panel is for connecting the service modules with other modules **/ function dispBoardAdminBoardAdditionSetup() { + + // Fix missing module configuration values + BoardModel::fixModuleConfig($this->module_info); + // sice content is obtained from other modules via call by reference, declare it first $content = ''; diff --git a/modules/board/board.controller.php b/modules/board/board.controller.php index e8bc4aec4..766535f41 100644 --- a/modules/board/board.controller.php +++ b/modules/board/board.controller.php @@ -20,6 +20,9 @@ class BoardController extends Board throw new Rhymix\Framework\Exceptions\NotPermitted; } + // Fix any missing module configurations + BoardModel::fixModuleConfig($this->module_info); + // setup variables $obj = Context::getRequestVars(); $obj->module_srl = $this->module_srl; @@ -27,7 +30,7 @@ class BoardController extends Board unset($obj->extra_vars); // Remove disallowed Unicode symbols. - if ($this->module_info->filter_specialchars !== 'N') + if ($this->module_info->filter_specialchars === 'Y') { if (isset($obj->title)) { @@ -50,15 +53,15 @@ class BoardController extends Board } // Return error if content is too large. - $document_length_limit = ($this->module_info->document_length_limit ?: 1024) * 1024; + $document_length_limit = $this->module_info->document_length_limit * 1024; if (strlen($obj->content) > $document_length_limit && !$this->grant->manager) { throw new Rhymix\Framework\Exception('msg_content_too_long'); } // Return error if content conains excessively large data URLs. - $inline_data_url_limit = ($this->module_info->inline_data_url_limit ?: 64) * 1024; - preg_match_all('!src="\s*(data:[^,]*,[a-z0-9+/=%$!._-]+)!i', (string)$obj->content, $matches); + $inline_data_url_limit = $this->module_info->inline_data_url_limit * 1024; + preg_match_all('!src="\s*(data:[^,]*,[a-z0-9+/=\%\$\!._-]+)!i', (string)$obj->content, $matches); foreach ($matches[1] as $match) { if (strlen($match) > $inline_data_url_limit) @@ -85,7 +88,7 @@ class BoardController extends Board $obj->category_srl = 0; } } - if (!$obj->category_srl && ($this->module_info->allow_no_category ?? 'N') !== 'Y') + if (!$obj->category_srl && $this->module_info->allow_no_category !== 'Y') { if (!$this->grant->manager) { @@ -113,7 +116,7 @@ class BoardController extends Board $use_status = explode('|@|', $this->module_info->use_status); // Set status - if(($obj->is_secret == 'Y' || $obj->status == $secret_status) && is_array($use_status) && in_array($secret_status, $use_status)) + if((($obj->is_secret ?? 'N') == 'Y' || $obj->status == $secret_status) && is_array($use_status) && in_array($secret_status, $use_status)) { $obj->status = $secret_status; } @@ -135,7 +138,7 @@ class BoardController extends Board $oDocument = DocumentModel::getDocument($obj->document_srl); // Set anonymous information when insert mode or status is temp - if($this->module_info->use_anonymous == 'Y' && (!$this->grant->manager || ($this->module_info->anonymous_except_admin ?? 'N') !== 'Y') && (!$oDocument->isExists() || $oDocument->get('status') == DocumentModel::getConfigStatus('temp'))) + if($this->module_info->use_anonymous == 'Y' && (!$this->grant->manager || $this->module_info->anonymous_except_admin === 'N') && (!$oDocument->isExists() || $oDocument->get('status') == DocumentModel::getConfigStatus('temp'))) { if(!$obj->document_srl) { @@ -143,7 +146,7 @@ class BoardController extends Board } $manual = true; - $anonymous_name = $this->module_info->anonymous_name ?: 'anonymous'; + $anonymous_name = $this->module_info->anonymous_name ?: BoardModel::DEFAULT_MODULE_CONFIG['anonymous_name']; $anonymous_name = $this->createAnonymousName($anonymous_name, $logged_info->member_srl, $obj->document_srl); $obj->notify_message = 'N'; @@ -172,7 +175,7 @@ class BoardController extends Board } // Protect admin document - if ($this->module_info->protect_admin_content_update !== 'N') + if ($this->module_info->protect_admin_content_update === 'Y') { $member_info = MemberModel::getMemberInfo($oDocument->get('member_srl')); if($member_info->is_admin == 'Y' && $logged_info->is_admin != 'Y') @@ -221,7 +224,14 @@ class BoardController extends Board $obj->title_bold = $oDocument->get('title_bold'); } - $obj->reason_update = escape($obj->reason_update); + if (isset($obj->reason_update)) + { + $obj->reason_update = escape($obj->reason_update); + } + else + { + $obj->reason_update = ''; + } } // Update @@ -361,6 +371,9 @@ class BoardController extends Board throw new Rhymix\Framework\Exceptions\NotPermitted; } + // Fix any missing module configurations + BoardModel::fixModuleConfig($this->module_info); + // check protect content if($this->module_info->protect_content == 'Y' || $this->module_info->protect_delete_content == 'Y') { @@ -370,7 +383,7 @@ class BoardController extends Board } } - if ($this->module_info->protect_admin_content_delete !== 'N' && $this->user->is_admin !== 'Y') + if ($this->module_info->protect_admin_content_delete === 'Y' && $this->user->is_admin !== 'Y') { $member_info = MemberModel::getMemberInfo($oDocument->get('member_srl')); if($member_info->is_admin === 'Y') @@ -462,8 +475,11 @@ class BoardController extends Board // Comments belong in the same module_srl as the document. $obj->module_srl = $oDocument->get('module_srl'); + // Fix any missing module configurations + BoardModel::fixModuleConfig($this->module_info); + // Remove disallowed Unicode symbols. - if ($this->module_info->filter_specialchars !== 'N') + if ($this->module_info->filter_specialchars === 'Y') { if (isset($obj->content)) { @@ -486,7 +502,7 @@ class BoardController extends Board // Return error if content conains excessively large data URLs. $inline_data_url_limit = ($this->module_info->inline_data_url_limit ?: 64) * 1024; - preg_match_all('!src="\s*(data:[^,]*,[a-z0-9+/=%$!._-]+)!i', (string)$obj->content, $matches); + preg_match_all('!src="\s*(data:[^,]*,[a-z0-9+/=\%\$\!._-]+)!i', (string)$obj->content, $matches); foreach ($matches[1] as $match) { if (strlen($match) > $inline_data_url_limit) @@ -495,12 +511,14 @@ class BoardController extends Board } } - if(!$this->module_info->use_status) $this->module_info->use_status = 'PUBLIC'; + if(!$this->module_info->use_status) + { + $this->module_info->use_status = 'PUBLIC'; + } if(!is_array($this->module_info->use_status)) { $this->module_info->use_status = explode('|@|', $this->module_info->use_status); } - if(in_array('SECRET', $this->module_info->use_status)) { $this->module_info->secret = 'Y'; @@ -512,7 +530,7 @@ class BoardController extends Board } // For anonymous use, remove writer's information and notifying information - if($this->module_info->use_anonymous == 'Y' && (!$this->grant->manager || ($this->module_info->anonymous_except_admin ?? 'N') !== 'Y')) + if($this->module_info->use_anonymous == 'Y' && (!$this->grant->manager || $this->module_info->anonymous_except_admin === 'N')) { $obj->notify_message = 'N'; $obj->member_srl = -1*$logged_info->member_srl; @@ -547,7 +565,7 @@ class BoardController extends Board } } - if ($this->module_info->protect_admin_content_update !== 'N') + if ($this->module_info->protect_admin_content_update === 'Y') { $member_info = MemberModel::getMemberInfo($comment->member_srl); if($member_info->is_admin == 'Y' && $logged_info->is_admin != 'Y') @@ -563,7 +581,7 @@ class BoardController extends Board $update_document = $this->module_info->update_order_on_comment === 'N' ? false : true; // Check parent comment. - if($obj->parent_srl) + if (!empty($obj->parent_srl)) { $parent_comment = CommentModel::getComment($obj->parent_srl); if(!$parent_comment->comment_srl || $parent_comment->get('document_srl') != $oDocument->get('document_srl')) @@ -651,6 +669,9 @@ class BoardController extends Board throw new Rhymix\Framework\Exceptions\NotPermitted; } + // Fix any missing module configurations + BoardModel::fixModuleConfig($this->module_info); + $childs = null; if($this->module_info->protect_delete_comment === 'Y' && $this->grant->manager == false) { @@ -661,7 +682,7 @@ class BoardController extends Board } } - if ($this->module_info->protect_admin_content_delete !== 'N' && $this->user->is_admin !== 'Y') + if ($this->module_info->protect_admin_content_delete === 'Y' && $this->user->is_admin !== 'Y') { $member_info = MemberModel::getMemberInfo($comment->get('member_srl')); if($member_info->is_admin === 'Y') diff --git a/modules/board/board.model.php b/modules/board/board.model.php index 3e271fef8..4a43dcd29 100644 --- a/modules/board/board.model.php +++ b/modules/board/board.model.php @@ -8,6 +8,101 @@ */ class BoardModel extends Board { + /** + * Default cofiguration for each module instance. + */ + public const DEFAULT_MODULE_CONFIG = [ + + // Title and SEO settings + 'browser_title' => '', + 'meta_keywords' => '', + 'meta_description' => '', + 'robots_tag' => 'all', + + // PC and common display settings + 'layout_srl' => -1, + 'skin' => '/USE_DEFAULT/', + 'list_count' => 20, + 'search_list_count' => 20, + 'page_count' => 10, + 'header_text' => '', + 'footer_text' => '', + + // Mobile display settings + 'use_mobile' => 'N', + 'mlayout_srl' => -2, + 'mskin' => '/USE_DEFAULT/', + 'mobile_list_count' => 20, + 'mobile_search_list_count' => 20, + 'mobile_page_count' => 5, + 'mobile_header_text' => '', + 'mobile_footer_text' => '', + + // List settings + 'order_target' => 'list_order', + 'order_type' => 'asc', + 'except_notice' => 'Y', + 'use_bottom_list' => 'Y', + 'skip_bottom_list_for_olddoc' => 'N', + 'skip_bottom_list_days' => 30, + 'skip_bottom_list_for_robot' => 'Y', + + // Feature settings + 'consultation' => 'N', + 'use_anonymous' => 'N', + 'anonymous_except_admin' => 'N', + 'anonymous_name' => 'anonymous', + 'update_log' => 'N', + 'update_order_on_comment' => 'N', + 'comment_delete_message' => 'no', + 'trash_use' => 'N', + 'use_status' => 'PUBLIC', + 'use_category' => 'N', + 'allow_no_category' => 'N', + + // Limits and protections + 'document_length_limit' => 1024, + 'comment_length_limit' => 128, + 'inline_data_url_limit' => 64, + 'filter_specialchars' => 'Y', + 'protect_delete_content' => 'N', + 'protect_update_content' => 'N', + 'protect_delete_comment' => 'N', + 'protect_update_comment' => 'N', + 'protect_admin_content_delete' => 'Y', + 'protect_admin_content_update' => 'Y', + 'protect_document_regdate' => '', + 'protect_comment_regdate' => '', + + // Extra settings + 'admin_mail' => '', + 'module_category_srl' => 0, + 'description' => '', + ]; + + /** + * Fix module configuration so that there are no missing values. + * + * The return value will be set to true if any values were added. + * The object will be modified in place. + * + * @param object $module_info + * @return bool + */ + public static function fixModuleConfig(object $module_info): bool + { + $fixed = false; + foreach (self::DEFAULT_MODULE_CONFIG as $key => $value) + { + if (!isset($module_info->{$key})) + { + $module_info->{$key} = $value; + $fixed = true; + } + } + return $fixed; + } + /** * @brief get the list configuration */ diff --git a/modules/board/board.view.php b/modules/board/board.view.php index 101fc2c05..144a055d8 100644 --- a/modules/board/board.view.php +++ b/modules/board/board.view.php @@ -853,10 +853,13 @@ class BoardView extends Board return $this->dispBoardMessage($this->user->isMember() ? 'msg_not_permitted' : 'msg_not_logged'); } + // Fix any missing module configurations + BoardModel::fixModuleConfig($this->module_info); + /** * check if the category option is enabled not not */ - if($this->module_info->use_category=='Y') + if ($this->module_info->use_category === 'Y') { // get the user group information if(Context::get('is_logged')) @@ -867,7 +870,6 @@ class BoardView extends Board { $group_srls = array(); } - $group_srls_count = count($group_srls); // check the grant after obtained the category list $category_list = array(); @@ -917,9 +919,9 @@ class BoardView extends Board $oDocument->add('origin_module_srl', $oDocument->get('module_srl')); $oDocument->add('module_srl', $this->module_srl); - if($oDocument->isExists()) + if ($oDocument->isExists()) { - if(($this->module_info->protect_document_regdate ?? 0) > 0 && $this->grant->manager == false) + if ($this->module_info->protect_document_regdate > 0 && $this->grant->manager == false) { if($oDocument->get('regdate') < date('YmdHis', strtotime('-'.$this->module_info->protect_document_regdate.' day'))) { @@ -928,7 +930,7 @@ class BoardView extends Board throw new Rhymix\Framework\Exception($massage); } } - if(($this->module_info->protect_content ?? 'N') === 'Y' || ($this->module_info->protect_update_content ?? 'N') == 'Y') + if ($this->module_info->protect_content === 'Y' || $this->module_info->protect_update_content === 'Y') { if($oDocument->get('comment_count') > 0 && $this->grant->manager == false) { @@ -936,7 +938,7 @@ class BoardView extends Board } } - if (($this->module_info->protect_admin_content_update ?? 'N') !== 'N') + if ($this->module_info->protect_admin_content_update === 'Y') { $member_info = MemberModel::getMemberInfo($oDocument->get('member_srl')); if(isset($member_info->is_admin) && $member_info->is_admin == 'Y' && $this->user->is_admin != 'Y') @@ -1082,6 +1084,9 @@ class BoardView extends Board } } + // Fix any missing module configurations + BoardModel::fixModuleConfig($this->module_info); + if($this->module_info->protect_document_regdate > 0 && $this->grant->manager == false) { if($oDocument->get('regdate') < date('YmdHis', strtotime('-'.$this->module_info->protect_document_regdate.' day'))) @@ -1276,6 +1281,9 @@ class BoardView extends Board } } + // Fix any missing module configurations + BoardModel::fixModuleConfig($this->module_info); + if($this->module_info->protect_comment_regdate > 0 && $this->grant->manager == false) { if($oComment->get('regdate') < date('YmdHis', strtotime('-'.$this->module_info->protect_document_regdate.' day'))) @@ -1360,6 +1368,9 @@ class BoardView extends Board } } + // Fix any missing module configurations + BoardModel::fixModuleConfig($this->module_info); + if($this->module_info->protect_comment_regdate > 0 && $this->grant->manager == false) { if($oComment->get('regdate') < date('YmdHis', strtotime('-'.$this->module_info->protect_document_regdate.' day'))) diff --git a/modules/board/tpl/addition_setup.html b/modules/board/tpl/addition_setup.html index 78b6214e4..954d0c56e 100644 --- a/modules/board/tpl/addition_setup.html +++ b/modules/board/tpl/addition_setup.html @@ -28,15 +28,15 @@
{$lang->about_board_include_days}
{$lang->about_list_count}
{$lang->about_search_list_count}
{$lang->about_page_count}
{$lang->about_list_count}
{$lang->about_search_list_count}
{$lang->about_mobile_page_count}
{$lang->about_list_config}
{$lang->about_board}
+{$lang->about_board}
{$lang->about_image_autoconv}
+ {@ $source_types = ['bmp', 'jpg', 'png', 'webp', 'avif', 'heic']} + +
+ {$lang->about_image_autoconv}
+ {$lang->msg_need_magick}
+
-