diff --git a/.htaccess b/.htaccess index 792ea9532..c0ea1b7bb 100644 --- a/.htaccess +++ b/.htaccess @@ -2,9 +2,8 @@ RewriteEngine On # block direct access to templates, XML schema files, config files, dotfiles, environment, etc. RewriteCond %{REQUEST_URI} !/modules/editor/(skins|styles)/ -RewriteCond %{REQUEST_URI} !/common/manual/ RewriteRule ^(addons|common/tpl|files/ruleset|(m\.)?layouts|modules|plugins|themes|widgets|widgetstyles)/.+\.(html|xml)$ - [L,F] -RewriteRule ^files/(attach|config|cache/store)/.+\.php$ - [L,F] +RewriteRule ^files/(attach|config|cache/store)/.+\.(ph(p|t|ar)?[0-9]?|p?html?|cgi|pl|exe|[aj]spx?|inc|bak)$ - [L,F] RewriteRule ^files/(env|member_extra_info/(new_message_flags|point))/ - [L,F] RewriteRule ^(\.git|\.ht|\.travis|codeception\.|composer\.|Gruntfile\.js|package\.json|CONTRIBUTING|COPYRIGHT|LICENSE|README) - [L,F] diff --git a/.travis.yml b/.travis.yml index bf48be3e3..438a2011b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,18 +5,15 @@ php: - 7.0 - 7.1 - 7.2 - - nightly -matrix: - allow_failures: - - php: nightly + - 7.3 services: - mysql before_script: - npm install grunt grunt-cli grunt-contrib-jshint grunt-contrib-csslint grunt-phplint --save-dev - mysql -u root -e "CREATE DATABASE rhymix CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci" - mysql -u root -e "GRANT ALL PRIVILEGES ON rhymix.* TO travis@localhost" - - mysql -u root -e "UPDATE mysql.user SET Password = PASSWORD('travis') WHERE User = 'travis'; FLUSH PRIVILEGES" - - if [[ $TRAVIS_PHP_VERSION != "nightly" ]]; then phpenv config-rm xdebug.ini; fi + - mysql -u root -e "SET PASSWORD FOR travis@localhost = PASSWORD('travis'); FLUSH PRIVILEGES" + - if [[ $TRAVIS_PHP_VERSION != "7.3" ]]; then phpenv config-rm xdebug.ini; fi - wget https://codeception.com/releases/2.3.9/codecept.phar - php -S localhost:8000 & script: diff --git a/README.md b/README.md index 4cece3e7f..9f043be7f 100644 --- a/README.md +++ b/README.md @@ -47,11 +47,11 @@ devops@rhymix.org로 알려 주시면 감사하겠습니다. ### 공식 홈페이지 -- Rhymix : https://www.rhymix.org +- Rhymix : https://rhymix.org ### 커뮤니티 -- XETOWN : https://www.xetown.com +- XETOWN : https://xetown.com ### 저작권 및 라이선스 @@ -118,11 +118,11 @@ If you have found a security vulnerability, please let us know at devops@rhymix. ### Official Website -- Rhymix : https://www.rhymix.org +- Rhymix : https://rhymix.org ### Community -- XETOWN (Korean) : https://www.xetown.com +- XETOWN (Korean) : https://xetown.com ### Copyright and License diff --git a/addons/photoswipe/conf/info.xml b/addons/photoswipe/conf/info.xml index c48bf732f..82d6b2a96 100644 --- a/addons/photoswipe/conf/info.xml +++ b/addons/photoswipe/conf/info.xml @@ -20,4 +20,16 @@ Rhymix contributors Rhymix contributors - \ No newline at end of file + + + 파일이름 출력 설정 + 넘겨보기 실행시 하단에 파일이름을 출력할 것인지 여부를 선택합니다. 기본값은 사용하도록 되어있습니다. + + 사용 + + + 사용 안함 + + + + diff --git a/addons/photoswipe/photoswipe.addon.php b/addons/photoswipe/photoswipe.addon.php index 4a1afbf86..87ebe03ed 100644 --- a/addons/photoswipe/photoswipe.addon.php +++ b/addons/photoswipe/photoswipe.addon.php @@ -21,7 +21,10 @@ if($called_position == 'after_module_proc' && Context::getResponseMethod() == "H Context::loadFile(array('./addons/photoswipe/rx_photoswipe.js', 'body', '', null), true); $footer = FileHandler::readFile('./addons/photoswipe/PhotoSwipe/pswp.html'); - Context::addHtmlFooter($footer); + + $style_display = isset($addon_info->display_name) ? "" : ''; + + Context::addHtmlFooter($style_display . $footer); } /* End of file photoswipe.addon.php */ diff --git a/addons/recaptcha/recaptcha.class.php b/addons/recaptcha/recaptcha.class.php index dbf2bf86c..11177627b 100644 --- a/addons/recaptcha/recaptcha.class.php +++ b/addons/recaptcha/recaptcha.class.php @@ -18,7 +18,7 @@ class reCAPTCHA $response = Context::get('g-recaptcha-response'); if (!$response) { - return new BaseObject(-1, 'recaptcha.msg_recaptcha_invalid_response'); + throw new Rhymix\Framework\Exception('recaptcha.msg_recaptcha_invalid_response'); } try @@ -31,17 +31,17 @@ class reCAPTCHA } catch (\Requests_Exception $e) { - return new BaseObject(-1, 'recaptcha.msg_recaptcha_connection_error'); + throw new Rhymix\Framework\Exception('recaptcha.msg_recaptcha_connection_error'); } $verify = @json_decode($verify_request->body, true); if ($verify && isset($verify['error-codes']) && in_array('invalid-input-response', $verify['error-codes'])) { - return new BaseObject(-1, 'recaptcha.msg_recaptcha_invalid_response'); + throw new Rhymix\Framework\Exception('recaptcha.msg_recaptcha_invalid_response'); } elseif (!$verify || !$verify['success'] || (isset($verify['error-codes']) && $verify['error-codes'])) { - return new BaseObject(-1, 'recaptcha.msg_recaptcha_server_error'); + throw new Rhymix\Framework\Exception('recaptcha.msg_recaptcha_server_error'); } else { diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php index ee68ccb23..7377cecf1 100644 --- a/classes/context/Context.class.php +++ b/classes/context/Context.class.php @@ -117,10 +117,10 @@ class Context public $is_site_locked = FALSE; /** - * Check init - * @var bool FALSE if init fail + * Result of initial security check + * @var string|bool */ - public $isSuccessInit = TRUE; + public $security_check = 'OK'; /** * Singleton instance @@ -173,8 +173,9 @@ class Context * @var array */ private static $_check_patterns = array( - '@<(?:\?|%)@', - '@ 'DENY ALL', + '@ 'DENY ALL', + '@ 'ALLOW ADMIN ONLY', ); /** @@ -256,14 +257,6 @@ class Context // If Rhymix is installed, get virtual site information. if(self::isInstalled()) { - $oModuleModel = getModel('module'); - $site_module_info = $oModuleModel->getDefaultMid() ?: new stdClass; - self::set('site_module_info', $site_module_info); - self::set('_default_timezone', ($site_module_info->settings && $site_module_info->settings->timezone) ? $site_module_info->settings->timezone : null); - self::set('_default_url', self::$_instance->db_info->default_url = self::getDefaultUrl($site_module_info)); - self::set('_http_port', self::$_instance->db_info->http_port = $site_module_info->http_port ?: null); - self::set('_https_port', self::$_instance->db_info->https_port = $site_module_info->https_port ?: null); - self::set('_use_ssl', self::$_instance->db_info->use_ssl = $site_module_info->security ?: 'none'); if (PHP_SAPI === 'cli') { self::set('_default_url', $default_url = config('url.default')); @@ -272,6 +265,14 @@ class Context define('RX_BASEURL', parse_url($default_url, PHP_URL_PATH)); } } + $oModuleModel = getModel('module'); + $site_module_info = $oModuleModel->getDefaultMid() ?: new stdClass; + self::set('site_module_info', $site_module_info); + self::set('_default_timezone', ($site_module_info->settings && $site_module_info->settings->timezone) ? $site_module_info->settings->timezone : null); + self::set('_default_url', self::$_instance->db_info->default_url = self::getDefaultUrl($site_module_info)); + self::set('_http_port', self::$_instance->db_info->http_port = $site_module_info->http_port ?: null); + self::set('_https_port', self::$_instance->db_info->https_port = $site_module_info->https_port ?: null); + self::set('_use_ssl', self::$_instance->db_info->use_ssl = $site_module_info->security ?: 'none'); } else { @@ -294,13 +295,14 @@ class Context // Load language support. $enabled_langs = self::loadLangSelected(); + $set_lang_cookie = false; self::set('lang_supported', $enabled_langs); if($lang_type = self::get('l')) { if($_COOKIE['lang_type'] !== $lang_type) { - setcookie('lang_type', $lang_type, time() + 86400 * 365, '/', null, !!config('session.use_ssl_cookies')); + $set_lang_cookie = true; } } elseif($_COOKIE['lang_type']) @@ -316,12 +318,18 @@ class Context if(!strncasecmp($lang_code, $_SERVER['HTTP_ACCEPT_LANGUAGE'], strlen($lang_code))) { $lang_type = $lang_code; - setcookie('lang_type', $lang_type, time() + 86400 * 365, '/', null, !!config('session.use_ssl_cookies')); + $set_lang_cookie = true; } } } } + $lang_type = preg_replace('/[^a-zA-Z0-9_-]/', '', $lang_type); + if ($set_lang_cookie) + { + setcookie('lang_type', $lang_type, time() + 86400 * 365, '/', null, !!config('session.use_ssl_cookies')); + } + if(!$lang_type || !isset($enabled_langs[$lang_type])) { if($site_module_info->settings->language) @@ -351,6 +359,7 @@ class Context { $oSessionModel = getModel('session'); $oSessionController = getController('session'); + ini_set('session.serialize_handler', 'php'); session_set_save_handler( array(&$oSessionController, 'open'), array(&$oSessionController, 'close'), array(&$oSessionModel, 'read'), array(&$oSessionController, 'write'), array(&$oSessionController, 'destroy'), array(&$oSessionController, 'gc') ); @@ -794,7 +803,7 @@ class Context return ''; } getController('module')->replaceDefinedLangCode(self::$_instance->browser_title); - return htmlspecialchars(self::$_instance->browser_title, ENT_COMPAT | ENT_HTML401, 'UTF-8', FALSE); + return htmlspecialchars(self::$_instance->browser_title, ENT_QUOTES, 'UTF-8', FALSE); } /** @@ -885,6 +894,7 @@ class Context { self::$_instance->db_info = new stdClass; } + self::$_instance->db_info->lang_type = $lang_type; self::$_instance->lang_type = $lang_type; self::set('lang_type', $lang_type); @@ -1070,7 +1080,7 @@ class Context { if (!self::_recursiveCheckVar($_SERVER['HTTP_HOST']) || preg_match("/[\,\"\'\{\}\[\]\(\);$]/", $_SERVER['HTTP_HOST'])) { - self::$_instance->isSuccessInit = FALSE; + self::$_instance->security_check = 'DENY ALL'; } } @@ -1205,7 +1215,7 @@ class Context { if(self::getRequestMethod() === 'XMLRPC') { - if(!Rhymix\Framework\Security::checkXEE($GLOBALS['HTTP_RAW_POST_DATA'])) + if(!Rhymix\Framework\Security::checkXXE($GLOBALS['HTTP_RAW_POST_DATA'])) { header("HTTP/1.0 400 Bad Request"); exit; @@ -1261,10 +1271,16 @@ class Context $tmp_name = $val['tmp_name']; if(!is_array($tmp_name)) { - if(!$tmp_name || !is_uploaded_file($tmp_name) || $val['size'] <= 0) + if($val['name'] === '' && $val['size'] == 0) { continue; } + if(!UploadFileFilter::check($tmp_name, $val['name'])) + { + self::$_instance->security_check = 'DENY ALL'; + unset($_FILES[$key]); + continue; + } $val['name'] = escape($val['name'], false); self::set($key, $val, true); self::set('is_uploaded', true); @@ -1275,16 +1291,24 @@ class Context $files = array(); foreach ($tmp_name as $i => $j) { - if($val['size'][$i] > 0) + if($val['name'][$i] === '' && $val['size'][$i] == 0) { - $file = array(); - $file['name'] = $val['name'][$i]; - $file['type'] = $val['type'][$i]; - $file['tmp_name'] = $val['tmp_name'][$i]; - $file['error'] = $val['error'][$i]; - $file['size'] = $val['size'][$i]; - $files[] = $file; + continue; } + if(!UploadFileFilter::check($val['tmp_name'][$i], $val['name'][$i])) + { + self::$_instance->security_check = 'DENY ALL'; + $files = array(); + unset($_FILES[$key]); + break; + } + $file = array(); + $file['name'] = $val['name'][$i]; + $file['type'] = $val['type'][$i]; + $file['tmp_name'] = $val['tmp_name'][$i]; + $file['error'] = $val['error'][$i]; + $file['size'] = $val['size'][$i]; + $files[] = $file; } if(count($files)) { @@ -1304,12 +1328,15 @@ class Context { if(is_string($val)) { - foreach(self::$_check_patterns as $pattern) + foreach(self::$_check_patterns as $pattern => $status) { if(preg_match($pattern, $val)) { - self::$_instance->isSuccessInit = false; - return false; + self::$_instance->security_check = $status; + if($status === 'DENY ALL') + { + return false; + } } } } @@ -1403,20 +1430,17 @@ class Context } elseif($_val = trim($_val)) { - if(in_array($key, array('page', 'cpage')) || ends_with('srl', $key, false)) + if(in_array($key, array('page', 'cpage')) || ends_with('srl', $key, false) && preg_match('/[^0-9,]/', $_val)) { - if(preg_match('/[^0-9,]/', $_val)) - { - $_val = (int)$_val; - } + $_val = (int)$_val; } - elseif(in_array($key, array('mid', 'search_keyword', 'xe_validator_id'))) + elseif(in_array($key, array('mid', 'vid', 'search_target', 'search_keyword', 'xe_validator_id')) || $_SERVER['REQUEST_METHOD'] === 'GET') { $_val = escape($_val, false); - } - elseif($key === 'vid') - { - $_val = urlencode($_val); + if(ends_with('url', $key, false)) + { + $_val = strtr($_val, array('&' => '&')); + } } } $result[escape($_key)] = $_val; @@ -1699,23 +1723,41 @@ class Context // If using SSL always if($site_module_info->security == 'always') { - $query = self::getRequestUri(ENFORCE_SSL, $domain) . $query; + if(!$domain && RX_SSL) + { + $query = RX_BASEURL . $query; + } + else + { + $query = self::getRequestUri(ENFORCE_SSL, $domain) . $query; + } } // optional SSL use elseif($site_module_info->security == 'optional') { $ssl_mode = ((self::get('module') === 'admin') || ($get_vars['module'] === 'admin') || (isset($get_vars['act']) && self::isExistsSSLAction($get_vars['act']))) ? ENFORCE_SSL : RELEASE_SSL; - $query = self::getRequestUri($ssl_mode, $domain) . $query; + if(!$domain && (RX_SSL && ENFORCE_SSL) || (!RX_SSL && RELEASE_SSL)) + { + $query = RX_BASEURL . $query; + } + else + { + $query = self::getRequestUri($ssl_mode, $domain) . $query; + } } // no SSL else { // currently on SSL but target is not based on SSL - if(RX_SSL) + if(!$domain && RX_SSL) + { + $query = RX_BASEURL . $query; + } + elseif(RX_SSL) { $query = self::getRequestUri(ENFORCE_SSL, $domain) . $query; } - else if($domain) // if $domain is set + elseif($domain) { $query = self::getRequestUri(FOLLOW_REQUEST_SSL, $domain) . $query; } @@ -1732,7 +1774,7 @@ class Context if(!$autoEncode) { - return htmlspecialchars($query, ENT_COMPAT | ENT_HTML401, 'UTF-8', FALSE); + return htmlspecialchars($query, ENT_QUOTES, 'UTF-8', FALSE); } $output = array(); @@ -1748,7 +1790,7 @@ class Context $encode_queries[] = $key . '=' . $value; } - return htmlspecialchars($parsedUrl['path'] . '?' . join('&', $encode_queries), ENT_COMPAT | ENT_HTML401, 'UTF-8', FALSE); + return htmlspecialchars($parsedUrl['path'] . '?' . join('&', $encode_queries), ENT_QUOTES, 'UTF-8', FALSE); } /** @@ -1810,6 +1852,12 @@ class Context */ public static function set($key, $val, $set_to_get_vars = false) { + if(empty($key)) + { + trigger_error('Called Context::set() with an empty key', \E_USER_WARNING); + return; + } + self::$_tpl_vars->{$key} = $val; if($set_to_get_vars || isset(self::$_get_vars->{$key})) @@ -1833,6 +1881,12 @@ class Context */ public static function get($key) { + if(empty($key)) + { + trigger_error('Called Context::get() with an empty key', \E_USER_WARNING); + return; + } + if(isset(self::$_tpl_vars->{$key})) { return self::$_tpl_vars->{$key}; diff --git a/classes/db/DB.class.php b/classes/db/DB.class.php index 2d0a3e6af..244f73f1d 100644 --- a/classes/db/DB.class.php +++ b/classes/db/DB.class.php @@ -122,7 +122,8 @@ class DB } if(!$db_type && Context::isInstalled()) { - return new BaseObject(-1, 'msg_db_not_setted'); + Rhymix\Framework\Debug::displayError(lang('msg_db_not_setted')); + exit; } if(!strncmp($db_type, 'mysql', 5)) { @@ -139,7 +140,8 @@ class DB $class_file = RX_BASEDIR . "classes/db/$class_name.class.php"; if(!file_exists($class_file)) { - return new BaseObject(-1, 'msg_db_not_setted'); + Rhymix\Framework\Debug::displayError(sprintf('DB type "%s" is not supported.', $db_type)); + exit; } // get a singletone instance of the database driver class diff --git a/classes/db/DBMysql.class.php b/classes/db/DBMysql.class.php index 533cba998..ac6a978a6 100644 --- a/classes/db/DBMysql.class.php +++ b/classes/db/DBMysql.class.php @@ -73,16 +73,16 @@ class DBMySQL extends DB // Check connection error if($mysqli->connect_errno) { - $this->setError($mysqli->connect_errno, $mysqli->connect_error()); - return; + Rhymix\Framework\Debug::displayError(sprintf('DB ERROR %d : %s', $mysqli->connect_errno, $mysqli->connect_error)); + exit; } // Check DB version $this->db_version = $mysqli->server_info; if (version_compare($this->db_version, '5.0.7', '<')) { - $this->setError(-1, 'Rhymix requires MySQL 5.0.7 or later. Current MySQL version is ' . $this->db_version); - return; + Rhymix\Framework\Debug::displayError('Rhymix requires MySQL 5.0.7 or later. Current MySQL version is ' . $this->db_version); + exit; } // Set DB charset diff --git a/classes/db/queryparts/Query.class.php b/classes/db/queryparts/Query.class.php index 681c5f5d9..229a3b8fc 100644 --- a/classes/db/queryparts/Query.class.php +++ b/classes/db/queryparts/Query.class.php @@ -157,7 +157,7 @@ class Query extends BaseObject foreach($this->columnList as $columnName) { - $columnName = $dbParser->escapeColumn($columnName); + $columnName = $dbParser->escapeColumnExpression($columnName); $selectColumns[] = new SelectExpression($columnName); } unset($this->columns); @@ -586,6 +586,11 @@ class Query extends BaseObject */ function getHavingString($with_values = TRUE) { + if(!is_array($this->having)) + { + return ''; + } + $having = ''; $condition_count = 0; diff --git a/classes/display/DisplayHandler.class.php b/classes/display/DisplayHandler.class.php index 005dfe8db..674750681 100644 --- a/classes/display/DisplayHandler.class.php +++ b/classes/display/DisplayHandler.class.php @@ -157,16 +157,22 @@ class DisplayHandler extends Handler } // Do not display debugging information if there is no output. - $display_type = config('debug.display_type'); - if ($output === null && $display_type !== 'file') + $display_types = config('debug.display_type'); + if (!is_array($display_types)) + { + $display_types = array($display_types); + } + if ($output === null && !in_array('file', $display_types)) { return; } // Print debug information. - switch ($display_type) + $debug_output = ''; + foreach ($display_types as $display_type) { - case 'panel': + if ($display_type === 'panel') + { $data = Rhymix\Framework\Debug::getDebugData(); $display_content = array_fill_keys(config('debug.display_content'), true); if (count($display_content) && !isset($display_content['entries'])) @@ -220,7 +226,7 @@ class DisplayHandler extends Handler $panel_script .= "\n"; $body_end_position = strrpos($output, '') ?: strlen($output); $output = substr($output, 0, $body_end_position) . "\n$panel_script\n" . substr($output, $body_end_position); - return; + break; case 'JSON': if (RX_POST && preg_match('/^proc/', Context::get('act'))) { @@ -236,17 +242,16 @@ class DisplayHandler extends Handler { $output = $matches[1] . ',"_rx_debug":' . json_encode($data) . '}'; } - return; + break; default: - return; + break; } - - case 'comment': - case 'file': - default: + } + else + { if ($display_type === 'comment' && Context::getResponseMethod() !== 'HTML') { - return; + break; } ob_start(); $data = Rhymix\Framework\Debug::getDebugData(); @@ -272,13 +277,16 @@ class DisplayHandler extends Handler $phpheader = ''; } FileHandler::writeFile($log_filename, $phpheader . $content . PHP_EOL, 'a'); - return ''; + $debug_output .= ''; } else { - return ''; + $debug_output .= '' . PHP_EOL; } + } } + + return $debug_output; } /** diff --git a/classes/display/HTMLDisplayHandler.php b/classes/display/HTMLDisplayHandler.php index 3df435402..6eb810ec9 100644 --- a/classes/display/HTMLDisplayHandler.php +++ b/classes/display/HTMLDisplayHandler.php @@ -19,7 +19,7 @@ class HTMLDisplayHandler * List of scripts to block loading */ public static $blockedScripts = array( - '@(?:^|/)j[Qq]uery(?:-[0-9]+(?:\.[0-9x]+)*)?(?:\.min)?\.js$@', + '@(?:^|/)j[Qq]uery(?:-[0-9]+(?:\.[0-9x]+)*|-latest)?(?:\.min)?\.js$@', ); /** @@ -157,6 +157,21 @@ class HTMLDisplayHandler } } } + + // Add OpenGraph metadata + if (config('seo.og_enabled') && Context::get('module') !== 'admin') + { + $this->_addOpenGraphMetadata(); + } + + // set icon + $site_module_info = Context::get('site_module_info'); + $oAdminModel = getAdminModel('admin'); + $favicon_url = $oAdminModel->getFaviconUrl($site_module_info->domain_srl); + $mobicon_url = $oAdminModel->getMobileIconUrl($site_module_info->domain_srl); + Context::set('favicon_url', $favicon_url); + Context::set('mobicon_url', $mobicon_url); + return $output; } @@ -220,20 +235,6 @@ class HTMLDisplayHandler // Remove unnecessary information $output = preg_replace('/member\_\-([0-9]+)/s', 'member_0', $output); - - // Add OpenGraph metadata - if (config('seo.og_enabled') && Context::get('module') !== 'admin') - { - $this->_addOpenGraphMetadata(); - } - - // set icon - $site_module_info = Context::get('site_module_info'); - $oAdminModel = getAdminModel('admin'); - $favicon_url = $oAdminModel->getFaviconUrl($site_module_info->domain_srl); - $mobicon_url = $oAdminModel->getMobileIconUrl($site_module_info->domain_srl); - Context::set('favicon_url', $favicon_url); - Context::set('mobicon_url', $mobicon_url); // convert the final layout Context::set('content', $output); @@ -581,6 +582,7 @@ class HTMLDisplayHandler Context::loadFile(array('./common/css/rhymix.less', '', '', -1600000000), true); $original_file_list = array( 'plugins/jquery.migrate/jquery-migrate-1.4.1.min.js', + 'plugins/cookie/js.cookie.min.js', 'plugins/blankshield/blankshield.min.js', 'plugins/uri/URI.min.js', 'x.js', diff --git a/classes/extravar/Extravar.class.php b/classes/extravar/Extravar.class.php index 803c77bf3..ae7751652 100644 --- a/classes/extravar/Extravar.class.php +++ b/classes/extravar/Extravar.class.php @@ -209,7 +209,7 @@ class ExtraItem { $value = 'http://' . $value; } - return htmlspecialchars($value, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + return escape($value, false); case 'tel' : if(is_array($value)) @@ -232,7 +232,7 @@ class ExtraItem $values = array_values($values); for($i = 0, $c = count($values); $i < $c; $i++) { - $values[$i] = trim(htmlspecialchars($values[$i], ENT_COMPAT | ENT_HTML401, 'UTF-8', false)); + $values[$i] = trim(escape($values[$i], false)); } return $values; @@ -259,7 +259,7 @@ class ExtraItem $values = array_values($values); for($i = 0, $c = count($values); $i < $c; $i++) { - $values[$i] = trim(htmlspecialchars($values[$i], ENT_COMPAT | ENT_HTML401, 'UTF-8', false)); + $values[$i] = trim(escape($values[$i], false)); } return $values; @@ -280,7 +280,7 @@ class ExtraItem $values = array_values($values); for($i = 0, $c = count($values); $i < $c; $i++) { - $values[$i] = trim(htmlspecialchars($values[$i], ENT_COMPAT | ENT_HTML401, 'UTF-8', false)); + $values[$i] = trim(escape($values[$i], false)); } return $values; @@ -290,7 +290,7 @@ class ExtraItem //case 'textarea' : //case 'password' : default : - return htmlspecialchars($value, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + return escape($value, false); } } @@ -404,7 +404,7 @@ class ExtraItem // Temporary ID for labeling $tmp_id = $column_name . '-' . $id_num++; - $buff[] ='
  • '; + $buff[] ='
  • '; } $buff[] = ''; break; @@ -485,7 +485,7 @@ class ExtraItem { $oModuleController = getController('module'); $oModuleController->replaceDefinedLangCode($this->desc); - $buff[] = '

    ' . htmlspecialchars($this->desc, ENT_COMPAT | ENT_HTML401, 'UTF-8', false) . '

    '; + $buff[] = '

    ' . escape($this->desc, false) . '

    '; } return join(PHP_EOL, $buff); diff --git a/classes/mail/Mail.class.php b/classes/mail/Mail.class.php index 347434786..b7058ec23 100644 --- a/classes/mail/Mail.class.php +++ b/classes/mail/Mail.class.php @@ -217,7 +217,9 @@ class Mail extends Rhymix\Framework\Mail */ public static function isVaildMailAddress($email_address) { - if(preg_match("/([a-z0-9\_\-\.]+)@([a-z0-9\_\-\.]+)/i", $email_address)) + $validator = new \Egulias\EmailValidator\EmailValidator; + $rfc = new \Egulias\EmailValidator\Validation\RFCValidation; + if($validator->isValid($email_address, $rfc)) { return $email_address; } diff --git a/classes/module/ModuleHandler.class.php b/classes/module/ModuleHandler.class.php index 9f59bd6ca..c32074e32 100644 --- a/classes/module/ModuleHandler.class.php +++ b/classes/module/ModuleHandler.class.php @@ -42,15 +42,23 @@ class ModuleHandler extends Handler return; } + // Check security check status $oContext = Context::getInstance(); - if($oContext->isSuccessInit == FALSE) + switch($oContext->security_check) { - $logged_info = Context::get('logged_info'); - if($logged_info->is_admin != "Y") - { - $this->error = 'msg_invalid_request'; + case 'OK': + break; + case 'ALLOW ADMIN ONLY': + if(!Context::get('logged_info')->isAdmin()) + { + $this->error = 'msg_security_violation'; + return; + } + break; + case 'DENY ALL': + default: + $this->error = 'msg_security_violation'; return; - } } // Set variables from request arguments @@ -70,26 +78,23 @@ class ModuleHandler extends Handler } // Validate variables to prevent XSS - $isInvalid = NULL; - if($this->module && !preg_match("/^([a-z0-9\_\-]+)$/i", $this->module)) + $isInvalid = false; + if($this->module && !preg_match('/^[a-zA-Z0-9_-]+$/', $this->module)) { - $isInvalid = TRUE; + $isInvalid = true; } - if($this->mid && !preg_match("/^([a-z0-9\_\-]+)$/i", $this->mid)) + if($this->mid && !preg_match('/^[a-zA-Z0-9_-]+$/', $this->mid)) { - $isInvalid = TRUE; + $isInvalid = true; } - if($this->act && !preg_match("/^([a-z0-9\_\-]+)$/i", $this->act)) + if($this->act && !preg_match('/^[a-zA-Z0-9_-]+$/', $this->act)) { - $isInvalid = TRUE; + $isInvalid = true; } if($isInvalid) { - htmlHeader(); - echo lang("msg_invalid_request"); - htmlFooter(); - Context::close(); - exit; + $this->error = 'msg_security_violation'; + return; } if(isset($this->act) && (strlen($this->act) >= 4 && substr_compare($this->act, 'disp', 0, 4) === 0)) @@ -442,7 +447,13 @@ class ModuleHandler extends Handler // get type, kind $type = $xml_info->action->{$this->act}->type; $ruleset = $xml_info->action->{$this->act}->ruleset; + $meta_noindex = $xml_info->action->{$this->act}->meta_noindex; $kind = stripos($this->act, 'admin') !== FALSE ? 'admin' : ''; + if ($meta_noindex === 'true') + { + Context::addMetaTag('robots', 'noindex'); + } + if(!$kind && $this->module == 'admin') { $kind = 'admin'; @@ -464,7 +475,7 @@ class ModuleHandler extends Handler if(!in_array(strtoupper($_SERVER['REQUEST_METHOD']), $allowedMethodList)) { - $this->error = "msg_invalid_request"; + $this->error = 'msg_invalid_request'; $oMessageObject = self::getModuleInstance('message', $display_mode); $oMessageObject->setError(-1); $oMessageObject->setMessage($this->error); @@ -559,6 +570,7 @@ class ModuleHandler extends Handler $forward->module = $module; $forward->type = $xml_info->action->{$this->act}->type; $forward->ruleset = $xml_info->action->{$this->act}->ruleset; + $forward->meta_noindex = $xml_info->action->{$this->act}->meta_noindex; $forward->act = $this->act; } else @@ -585,6 +597,10 @@ class ModuleHandler extends Handler $ruleset = $forward->ruleset; $tpl_path = $oModule->getTemplatePath(); $orig_module = $oModule; + if($forward->meta_noindex === 'true') + { + Context::addMetaTag('robots', 'noindex'); + } $xml_info = $oModuleModel->getModuleActionXml($forward->module); @@ -620,7 +636,7 @@ class ModuleHandler extends Handler if(!in_array(strtoupper($_SERVER['REQUEST_METHOD']), $allowedMethodList)) { - $this->error = "msg_invalid_request"; + $this->error = 'msg_security_violation'; $oMessageObject = self::getModuleInstance('message', $display_mode); $oMessageObject->setError(-1); $oMessageObject->setMessage($this->error); @@ -635,7 +651,7 @@ class ModuleHandler extends Handler if($xml_info->action->{$this->act} && $xml_info->action->{$this->act}->check_csrf !== 'false' && !checkCSRF()) { $this->_setInputErrorToContext(); - $this->error = 'msg_invalid_request'; + $this->error = 'msg_security_violation'; $oMessageObject = ModuleHandler::getModuleInstance('message', $display_mode); $oMessageObject->setError(-1); $oMessageObject->setMessage($this->error); @@ -781,6 +797,10 @@ class ModuleHandler extends Handler } } + if ($kind === 'admin') { + Context::addMetaTag('robots', 'noindex'); + } + // if failed message exists in session, set context self::_setInputErrorToContext(); @@ -1017,39 +1037,47 @@ class ModuleHandler extends Handler // Set menus into context if($layout_info->menu_count) { + $oMenuAdminController = getAdminController('menu'); + $homeMenuCacheFile = null; + foreach($layout_info->menu as $menu_id => $menu) - { - // set default menu set(included home menu) - if(!$menu->menu_srl || $menu->menu_srl == -1) + { // No menu selected + if($menu->menu_srl == 0) { - $oMenuAdminController = getAdminController('menu'); - $homeMenuCacheFile = $oMenuAdminController->getHomeMenuCacheFile(); - - $homeMenuSrl = 0; - if(FileHandler::exists($homeMenuCacheFile)) + $menu->list = array(); + } + else + { + if($menu->menu_srl == -1) { - include($homeMenuCacheFile); + if ($homeMenuCacheFile === null) + { + $homeMenuCacheFile = $oMenuAdminController->getHomeMenuCacheFile(); + } + + $homeMenuSrl = 0; + if(FileHandler::exists($homeMenuCacheFile)) + { + include($homeMenuCacheFile); + } + + $menu->xml_file = './files/cache/menu/' . $homeMenuSrl . '.xml.php'; + $menu->php_file = './files/cache/menu/' . $homeMenuSrl . '.php'; + $menu->menu_srl = $homeMenuSrl; } - $menu->xml_file = './files/cache/menu/' . $homeMenuSrl . '.xml.php'; - $menu->php_file = './files/cache/menu/' . $homeMenuSrl . '.php'; - if(!$menu->menu_srl) + $php_file = FileHandler::exists($menu->php_file); + if(!$php_file) { - $layout_info->menu->{$menu_id}->menu_srl = $homeMenuSrl; + $oMenuAdminController->makeXmlFile($menu->menu_srl); + $php_file = FileHandler::exists($menu->php_file); + } + if($php_file) + { + include($php_file); } } - - $php_file = FileHandler::exists($menu->php_file); - if(!$php_file) - { - $oMenuAdminController = $oMenuAdminController ?: getAdminController('menu'); - $oMenuAdminController->makeXmlFile((isset($homeMenuSrl) && $homeMenuSrl) ? $homeMenuSrl : $menu->menu_srl); - $php_file = FileHandler::exists($menu->php_file); - } - if($php_file) - { - include($php_file); - } + Context::set($menu_id, $menu); } } @@ -1267,9 +1295,16 @@ class ModuleHandler extends Handler continue; } - $before_each_trigger_time = microtime(true); - $output = $oModule->{$called_method}($obj); - $after_each_trigger_time = microtime(true); + try + { + $before_each_trigger_time = microtime(true); + $output = $oModule->{$called_method}($obj); + $after_each_trigger_time = microtime(true); + } + catch (Rhymix\Framework\Exception $e) + { + $output = new BaseObject(-2, $e->getMessage()); + } if ($trigger_name !== 'common.flushDebugInfo') { @@ -1293,9 +1328,16 @@ class ModuleHandler extends Handler $trigger_functions = $oModuleModel->getTriggerFunctions($trigger_name, $called_position); foreach($trigger_functions as $item) { - $before_each_trigger_time = microtime(true); - $output = $item($obj); - $after_each_trigger_time = microtime(true); + try + { + $before_each_trigger_time = microtime(true); + $output = $item($obj); + $after_each_trigger_time = microtime(true); + } + catch (Rhymix\Framework\Exception $e) + { + $output = new BaseObject(-2, $e->getMessage()); + } if ($trigger_name !== 'common.writeSlowlog') { diff --git a/classes/module/ModuleObject.class.php b/classes/module/ModuleObject.class.php index 58e22fc32..4cddf51af 100644 --- a/classes/module/ModuleObject.class.php +++ b/classes/module/ModuleObject.class.php @@ -136,14 +136,36 @@ class ModuleObject extends BaseObject // Set privileges(granted) information if($this->setPrivileges() !== true) { - $this->stop('msg_invalid_request'); + $this->stop('msg_not_permitted'); return; } + // Set admin layout + if(preg_match('/^disp[A-Z][a-z0-9\_]+Admin/', $this->act)) + { + if(config('view.manager_layout') === 'admin') + { + $this->setLayoutPath('modules/admin/tpl'); + $this->setLayoutFile('layout'); + } + else + { + $oTemplate = TemplateHandler::getInstance(); + $oTemplate->compile('modules/admin/tpl', '_admin_common.html'); + } + } + // Execute init if(method_exists($this, 'init')) { - $this->init(); + try + { + $this->init(); + } + catch (Rhymix\Framework\Exception $e) + { + $this->stop($e->getMessage()); + } } } @@ -441,9 +463,7 @@ class ModuleObject extends BaseObject * */ function setLayoutFile($filename) { - if(!$filename) return; - - if(substr_compare($filename, '.html', -5) !== 0) + if($filename && substr_compare($filename, '.html', -5) !== 0) { $filename .= '.html'; } @@ -530,34 +550,54 @@ class ModuleObject extends BaseObject return FALSE; } - // integrate skin information of the module(change to sync skin info with the target module only by seperating its table) - $oModuleModel = getModel('module'); - $default_skin = ((!$is_mobile && $this->module_info->is_skin_fix == 'N') || ($is_mobile && $this->module_info->is_mskin_fix == 'N')); - $disable_skin = ($this->module == 'page' && ($this->module_info->page_type == 'OUTSIDE' || $this->module_info->page_type == 'WIDGET')); - if(!$disable_skin && $default_skin && $this->module != 'admin' && strpos($this->act, 'Admin') === false && $this->module == $this->module_info->module) + // Set module skin + if(isset($this->module_info->skin) && $this->module_info->module === $this->module && strpos($this->act, 'Admin') === false) { - $skinType = ($is_mobile && $this->module_info->mskin !== '/USE_RESPONSIVE/') ? 'M' : 'P'; - $dir = $skinType === 'M' ? 'm.skins' : 'skins'; - $valueName = $skinType === 'M' ? 'mskin' : 'skin'; - $skinName = $this->module_info->{$valueName} === '/USE_DEFAULT/' ? $oModuleModel->getModuleDefaultSkin($this->module, $skinType) : $this->module_info->{$valueName}; - if($this->module == 'page') + $oModuleModel = getModel('module'); + $skin_type = $is_mobile ? 'M' : 'P'; + $skin_key = $is_mobile ? 'mskin' : 'skin'; + $skin_dir = $is_mobile ? 'm.skins' : 'skins'; + $module_skin = $this->module_info->{$skin_key} ?: '/USE_DEFAULT/'; + $use_default_skin = $this->module_info->{'is_' . $skin_key . '_fix'} === 'N'; + + // Set default skin + if(!$this->getTemplatePath() || $use_default_skin) { - $this->module_info->{$valueName} = $skinName; - } - else - { - $isTemplatPath = (strpos($this->getTemplatePath(), '/tpl/') !== FALSE); - if(!$isTemplatPath) + if($module_skin === '/USE_DEFAULT/') { - $this->setTemplatePath(sprintf('%s%s/%s/', $this->module_path, $dir, $skinName)); + $module_skin = $oModuleModel->getModuleDefaultSkin($this->module, $skin_type); + $this->module_info->{$skin_key} = $module_skin; } + if($module_skin === '/USE_RESPONSIVE/') + { + $skin_dir = 'skins'; + $module_skin = $this->module_info->skin ?: '/USE_DEFAULT/'; + if($module_skin === '/USE_DEFAULT/') + { + $module_skin = $oModuleModel->getModuleDefaultSkin($this->module, 'P'); + } + } + if(!is_dir(sprintf('%s%s/%s', $this->module_path, $skin_dir, $module_skin))) + { + $module_skin = 'default'; + } + $this->setTemplatePath(sprintf('%s%s/%s', $this->module_path, $skin_dir, $module_skin)); } + + // Set skin variable + $oModuleModel->syncSkinInfoToModuleInfo($this->module_info); + Context::set('module_info', $this->module_info); } - - $oModuleModel->syncSkinInfoToModuleInfo($this->module_info); - Context::set('module_info', $this->module_info); + // Run - $output = $this->{$this->act}(); + try + { + $output = $this->{$this->act}(); + } + catch (Rhymix\Framework\Exception $e) + { + $output = new BaseObject(-2, $e->getMessage()); + } } else { diff --git a/classes/object/Object.class.php b/classes/object/Object.class.php index bf3763cde..f56bc3306 100644 --- a/classes/object/Object.class.php +++ b/classes/object/Object.class.php @@ -45,6 +45,22 @@ class BaseObject $this->setError($error); $this->setMessage($message); } + + /** + * Set state for var_export() + * + * @param array $vars + * @return object + */ + public static function __set_state(array $vars) + { + $instance = new static; + foreach ($vars as $key => $val) + { + $instance->{$key} = $val; + } + return $instance; + } /** * Setter to set error code or message diff --git a/classes/security/Security.class.php b/classes/security/Security.class.php index 092c92c30..995e6b812 100644 --- a/classes/security/Security.class.php +++ b/classes/security/Security.class.php @@ -115,7 +115,7 @@ class Security { if(strncmp('$user_lang->', $var, 12) !== 0) { - $var = htmlspecialchars($var, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + $var = escape($var, false); } return $var; @@ -185,7 +185,7 @@ class Security */ public static function detectingXEE($xml) { - return !Rhymix\Framework\Security::checkXEE($xml); + return !Rhymix\Framework\Security::checkXXE($xml); } } /* End of file : Security.class.php */ diff --git a/classes/security/UploadFileFilter.class.php b/classes/security/UploadFileFilter.class.php index b19bd6889..18bfdadb7 100644 --- a/classes/security/UploadFileFilter.class.php +++ b/classes/security/UploadFileFilter.class.php @@ -1,11 +1,24 @@ */ class UploadFileFilter { - public function check($file) + /** + * Generic checker + * + * @param string $file + * @param string $filename + * @return bool + */ + public static function check($file, $filename = null) { - return true; + // Return error if the file is not uploaded. + if (!$file || !file_exists($file) || !is_uploaded_file($file)) + { + return false; + } + + // Call Rhymix framework filter. + return Rhymix\Framework\Filters\FileContentFilter::check($file, $filename); } } diff --git a/classes/template/TemplateHandler.class.php b/classes/template/TemplateHandler.class.php index 5d671980d..ed05eeeec 100644 --- a/classes/template/TemplateHandler.class.php +++ b/classes/template/TemplateHandler.class.php @@ -327,7 +327,7 @@ class TemplateHandler { preg_match('/]*name="error_return_url"[^>]*>/is', $matches[2], $m3); if(!$m3[0]) - $matches[2] = '' . $matches[2]; + $matches[2] = '' . $matches[2]; } else { @@ -557,6 +557,14 @@ class TemplateHandler { $escape_option = 'noescape'; } + elseif(preg_match('/^\$(?:user_)?lang->[a-zA-Z0-9\_]+$/', $m[1])) + { + $escape_option = 'noescape'; + } + elseif(preg_match('/^lang\(.+\)$/', $m[1])) + { + $escape_option = 'noescape'; + } else { $escape_option = $this->config->autoescape !== null ? 'auto' : 'noescape'; @@ -603,6 +611,7 @@ class TemplateHandler { case 'auto': case 'autoescape': + case 'autolang': case 'escape': case 'noescape': $escape_option = $filter; @@ -655,6 +664,11 @@ class TemplateHandler case 'number_format': $var = $filter_option ? "number_format({$var}, {$filter_option})" : "number_format({$var})"; break; + + case 'shorten': + case 'number_shorten': + $var = $filter_option ? "number_shorten({$var}, {$filter_option})" : "number_shorten({$var})"; + break; case 'link': $var = $this->_applyEscapeOption($var, $escape_option); @@ -894,14 +908,16 @@ class TemplateHandler switch($escape_option) { case 'escape': - return "htmlspecialchars({$str}, ENT_COMPAT, 'UTF-8', true)"; + return "htmlspecialchars({$str}, ENT_QUOTES, 'UTF-8', true)"; case 'noescape': return "{$str}"; case 'autoescape': - return "htmlspecialchars({$str}, ENT_COMPAT, 'UTF-8', false)"; + return "htmlspecialchars({$str}, ENT_QUOTES, 'UTF-8', false)"; + case 'autolang': + return "(preg_match('/^\\$(?:user_)?lang->[a-zA-Z0-9\_]+$/', {$str}) ? ({$str}) : htmlspecialchars({$str}, ENT_QUOTES, 'UTF-8', false))"; case 'auto': default: - return "(\$this->config->autoescape === 'on' ? htmlspecialchars({$str}, ENT_COMPAT, 'UTF-8', false) : {$str})"; + return "(\$this->config->autoescape === 'on' ? htmlspecialchars({$str}, ENT_QUOTES, 'UTF-8', false) : ({$str}))"; } } diff --git a/classes/xml/xmlquery/DBParser.class.php b/classes/xml/xmlquery/DBParser.class.php index b9aa80cc2..0fd4d46ee 100644 --- a/classes/xml/xmlquery/DBParser.class.php +++ b/classes/xml/xmlquery/DBParser.class.php @@ -264,7 +264,7 @@ class DBParser } if($brackets == $total_brackets) { - if(!is_numeric($match) && !in_array(strtoupper($match), array('UNSIGNED', 'INTEGER', 'AS'))) + if(!is_numeric($match) && !in_array(strtoupper($match), array('UNSIGNED', 'INTEGER', 'AS')) && !preg_match('/^[A-Z]+$/', $match)) { $match = $this->escapeColumnExpression($match); } diff --git a/common/constants.php b/common/constants.php index 9ccbb094a..94653f9cd 100644 --- a/common/constants.php +++ b/common/constants.php @@ -3,7 +3,7 @@ /** * RX_VERSION is the version number of the Rhymix CMS. */ -define('RX_VERSION', '1.9.8'); +define('RX_VERSION', '1.9.9.2'); /** * RX_MICROTIME is the startup time of the current script, in microseconds since the Unix epoch. @@ -129,8 +129,8 @@ define('__XE_VERSION_ALPHA__', false); define('__XE_VERSION_BETA__', false); define('__XE_VERSION_RC__', false); define('__XE_VERSION_STABLE__', true); -define('__XE_MIN_PHP_VERSION__', '5.5.9'); -define('__XE_RECOMMEND_PHP_VERSION__', '5.5.9'); +define('__XE_MIN_PHP_VERSION__', '7.0.0'); +define('__XE_RECOMMEND_PHP_VERSION__', '7.2.0'); define('__ZBXE__', true); define('__ZBXE_VERSION__', RX_VERSION); define('_XE_PATH_', RX_BASEDIR); @@ -165,6 +165,8 @@ define('LOWER', 'abcdefghijklmnopqrstuvwxyz'); define('CR', "\r"); define('CRLF', "\r\n"); define('LF', "\n"); +define('Y', 'Y'); +define('N', 'N'); define('FOLLOW_REQUEST_SSL', 0); define('ENFORCE_SSL', 1); define('RELEASE_SSL', 2); diff --git a/common/defaults/blacklist.php b/common/defaults/blacklist.php index b24da7a0d..a9b6e54f1 100644 --- a/common/defaults/blacklist.php +++ b/common/defaults/blacklist.php @@ -18,4 +18,7 @@ return array( 'session_shield' => true, 'smartphone' => true, 'zipperupper' => true, + 'elkha_www' => true, + 'autowww' => true, + 'fix_domain' => true, ); diff --git a/common/defaults/config.php b/common/defaults/config.php index 0441b0c53..269858871 100644 --- a/common/defaults/config.php +++ b/common/defaults/config.php @@ -63,12 +63,14 @@ return array( 'refresh' => 300, ), 'file' => array( + 'folder_structure' => 2, 'umask' => '0022', ), 'mail' => array( 'type' => 'mailfunction', ), 'view' => array( + 'manager_layout' => 'module', 'minify_scripts' => 'common', 'concat_scripts' => 'none', 'server_push' => false, @@ -91,7 +93,7 @@ return array( 'log_slow_widgets' => 0, 'log_slow_remote_requests' => 0, 'log_filename' => null, - 'display_type' => 'comment', + 'display_type' => array('comment'), 'display_content' => array(), 'display_to' => 'admin', 'write_error_log' => 'fatal', @@ -112,6 +114,10 @@ return array( 'object' => array(), 'classes' => array(), ), + 'security' => array( + 'check_csrf_token' => false, + 'nofollow' => false, + ), 'mobile' => array( 'enabled' => true, 'tablets' => false, diff --git a/common/defaults/korea.ipv4.php b/common/defaults/korea.ipv4.php index b5591faff..3129de32e 100644 --- a/common/defaults/korea.ipv4.php +++ b/common/defaults/korea.ipv4.php @@ -2,7 +2,7 @@ /** * Source: https://mirror.oops.org/pub/oops/libkrisp/data/v2/ - * Last Updated: 2018-03-07 + * Last Updated: 2019-05-04 */ return array ( 0 => @@ -628,7 +628,7 @@ return array ( 124 => array ( 0 => '1039708160', - 1 => '1039720447', + 1 => '1039712255', ), 125 => array ( @@ -1091,2986 +1091,3036 @@ return array ( 1 => '1735214079', ), 217 => + array ( + 0 => '1735540224', + 1 => '1735540479', + ), + 218 => + array ( + 0 => '1735556096', + 1 => '1735557119', + ), + 219 => + array ( + 0 => '1735720960', + 1 => '1735721983', + ), + 220 => + array ( + 0 => '1736095744', + 1 => '1736096767', + ), + 221 => + array ( + 0 => '1736205312', + 1 => '1736206335', + ), + 222 => + array ( + 0 => '1736272896', + 1 => '1736273919', + ), + 223 => + array ( + 0 => '1736327168', + 1 => '1736328191', + ), + 224 => + array ( + 0 => '1736430592', + 1 => '1736431615', + ), + 225 => + array ( + 0 => '1736554496', + 1 => '1736555519', + ), + 226 => + array ( + 0 => '1736712192', + 1 => '1736714239', + ), + 227 => array ( 0 => '1740794880', 1 => '1740795903', ), - 218 => + 228 => array ( 0 => '1740831744', 1 => '1740832767', ), - 219 => + 229 => array ( 0 => '1741572608', 1 => '1741573119', ), - 220 => + 230 => array ( 0 => '1741794304', 1 => '1741795327', ), - 221 => + 231 => array ( 0 => '1741978624', 1 => '1741979647', ), - 222 => + 232 => array ( 0 => '1742009344', 1 => '1742011391', ), - 223 => + 233 => array ( 0 => '1742084096', 1 => '1742085119', ), - 224 => + 234 => array ( 0 => '1742100480', 1 => '1742101503', ), - 225 => + 235 => array ( 0 => '1742180352', 1 => '1742181375', ), - 226 => + 236 => array ( 0 => '1742182400', 1 => '1742183423', ), - 227 => + 237 => array ( 0 => '1742260736', 1 => '1742261247', ), - 228 => + 238 => array ( 0 => '1742380032', 1 => '1742382079', ), - 229 => + 239 => array ( 0 => '1742437376', 1 => '1742439423', ), - 230 => + 240 => array ( 0 => '1742882816', 1 => '1742884863', ), - 231 => + 241 => array ( 0 => '1742888960', 1 => '1742889983', ), - 232 => + 242 => array ( 0 => '1743100928', 1 => '1743101951', ), - 233 => + 243 => array ( 0 => '1743155200', 1 => '1743156223', ), - 234 => + 244 => array ( 0 => '1743224832', 1 => '1743225855', ), - 235 => + 245 => array ( 0 => '1743389696', 1 => '1743390719', ), - 236 => + 246 => array ( 0 => '1743460352', 1 => '1743461375', ), - 237 => + 247 => array ( 0 => '1743590400', 1 => '1743591423', ), - 238 => + 248 => array ( 0 => '1743714304', 1 => '1743715327', ), - 239 => + 249 => array ( 0 => '1743745024', 1 => '1743746047', ), - 240 => + 250 => array ( 0 => '1743776768', 1 => '1743778815', ), - 241 => + 251 => array ( 0 => '1743789056', 1 => '1743790079', ), - 242 => + 252 => array ( 0 => '1743794176', 1 => '1743795199', ), - 243 => + 253 => array ( 0 => '1744029696', 1 => '1744030719', ), - 244 => + 254 => array ( 0 => '1744054272', 1 => '1744055295', ), - 245 => + 255 => array ( 0 => '1744071680', 1 => '1744072703', ), - 246 => + 256 => array ( 0 => '1744189440', 1 => '1744190463', ), - 247 => + 257 => array ( 0 => '1744219136', 1 => '1744220159', ), - 248 => + 258 => array ( 0 => '1744235520', 1 => '1744236543', ), - 249 => + 259 => array ( 0 => '1744296960', 1 => '1744297983', ), - 250 => + 260 => array ( 0 => '1744300032', 1 => '1744301055', ), - 251 => + 261 => array ( 0 => '1744332800', 1 => '1744333823', ), - 252 => + 262 => array ( 0 => '1744378880', 1 => '1744379903', ), - 253 => + 263 => array ( 0 => '1744529408', 1 => '1744530431', ), - 254 => + 264 => array ( 0 => '1744695296', 1 => '1744696319', ), - 255 => + 265 => array ( 0 => '1744762880', 1 => '1744763903', ), - 256 => + 266 => array ( 0 => '1779040256', 1 => '1779073023', ), - 257 => + 267 => array ( 0 => '1784676352', 1 => '1785200639', ), - 258 => + 268 => array ( 0 => '1794113536', 1 => '1795162111', ), - 259 => + 269 => array ( 0 => '1845772288', 1 => '1845788671', ), - 260 => + 270 => array ( 0 => '1845854208', 1 => '1845886975', ), - 261 => + 271 => array ( 0 => '1846018048', 1 => '1846542335', ), - 262 => + 272 => array ( 0 => '1847738368', 1 => '1847754751', ), - 263 => + 273 => array ( 0 => '1847787520', 1 => '1847803903', ), - 264 => + 274 => array ( 0 => '1847812096', 1 => '1847853055', ), - 265 => + 275 => array ( 0 => '1848385536', 1 => '1848393727', ), - 266 => + 276 => array ( 0 => '1848426496', 1 => '1848639487', ), - 267 => + 277 => array ( 0 => '1849950208', 1 => '1850212351', ), - 268 => + 278 => array ( 0 => '1850490880', 1 => '1850507263', ), - 269 => + 279 => array ( 0 => '1850510336', 1 => '1850511359', ), - 270 => + 280 => array ( 0 => '1851528192', 1 => '1851528959', ), - 271 => + 281 => array ( 0 => '1851555840', 1 => '1851588607', ), - 272 => + 282 => array ( 0 => '1851594752', 1 => '1851596799', ), - 273 => + 283 => array ( 0 => '1851617280', 1 => '1851637759', ), - 274 => + 284 => array ( 0 => '1856307200', 1 => '1856315391', ), - 275 => + 285 => array ( 0 => '1856323584', 1 => '1856339967', ), - 276 => + 286 => array ( 0 => '1856791552', 1 => '1856798719', ), - 277 => + 287 => array ( 0 => '1860722688', 1 => '1860723711', ), - 278 => + 288 => array ( 0 => '1866563584', 1 => '1866579967', ), - 279 => + 289 => array ( 0 => '1866715136', 1 => '1866727423', ), - 280 => + 290 => array ( 0 => '1868267520', 1 => '1868283903', ), - 281 => + 291 => array ( 0 => '1868348416', 1 => '1868349439', ), - 282 => + 292 => array ( 0 => '1870004224', 1 => '1870036991', ), - 283 => + 293 => array ( 0 => '1873477632', 1 => '1873510399', ), - 284 => + 294 => array ( 0 => '1876557824', 1 => '1876688895', ), - 285 => + 295 => array ( 0 => '1876762624', 1 => '1876764671', ), - 286 => + 296 => array ( 0 => '1883799552', 1 => '1883832319', ), - 287 => + 297 => array ( 0 => '1884028928', 1 => '1884159999', ), - 288 => + 298 => array ( 0 => '1885995008', 1 => '1886191615', ), - 289 => + 299 => array ( 0 => '1886199808', 1 => '1886207999', ), - 290 => + 300 => array ( 0 => '1886978048', 1 => '1886986239', ), - 291 => + 301 => array ( 0 => '1887027200', 1 => '1887043583', ), - 292 => + 302 => array ( 0 => '1887764480', 1 => '1887813631', ), - 293 => + 303 => array ( 0 => '1887993856', 1 => '1888026623', ), - 294 => + 304 => array ( 0 => '1888071680', 1 => '1888073727', ), - 295 => + 305 => array ( 0 => '1888239616', 1 => '1888255999', ), - 296 => + 306 => array ( 0 => '1888260096', 1 => '1888264191', ), - 297 => + 307 => array ( 0 => '1888272384', 1 => '1888288767', ), - 298 => + 308 => array ( 0 => '1888485376', 1 => '1891631103', ), - 299 => + 309 => array ( 0 => '1891942400', 1 => '1891950591', ), - 300 => + 310 => array ( 0 => '1892941824', 1 => '1893015551', ), - 301 => + 311 => array ( 0 => '1893072896', 1 => '1893138431', ), - 302 => + 312 => array ( 0 => '1893203968', 1 => '1893669375', ), - 303 => + 313 => array ( 0 => '1893210624', 1 => '1893728255', ), - 304 => + 314 => array ( 0 => '1896480768', 1 => '1896497151', ), - 305 => + 315 => array ( 0 => '1897201664', 1 => '1897209855', ), - 306 => + 316 => array ( 0 => '1897758720', 1 => '1897779199', ), - 307 => + 317 => array ( 0 => '1897791488', 1 => '1897824255', ), - 308 => + 318 => array ( 0 => '1899268096', 1 => '1899270143', ), - 309 => + 319 => array ( 0 => '1899282432', 1 => '1899290623', ), - 310 => + 320 => array ( 0 => '1899724800', 1 => '1899741183', ), - 311 => + 321 => array ( 0 => '1899757568', 1 => '1899831295', ), - 312 => + 322 => array ( 0 => '1899849728', 1 => '1899850751', ), - 313 => + 323 => array ( 0 => '1904361472', 1 => '1904369663', ), - 314 => + 324 => array ( 0 => '1904377856', 1 => '1904476159', ), - 315 => + 325 => array ( 0 => '1908424704', 1 => '1908441087', ), - 316 => + 326 => array ( 0 => '1908756480', 1 => '1908760575', ), - 317 => + 327 => array ( 0 => '1908801536', 1 => '1908899839', ), - 318 => + 328 => array ( 0 => '1909981184', 1 => '1910112255', ), - 319 => + 329 => array ( 0 => '1914503168', 1 => '1914544127', ), - 320 => + 330 => array ( 0 => '1914568704', 1 => '1914576895', ), - 321 => + 331 => array ( 0 => '1914580992', 1 => '1914585087', ), - 322 => + 332 => array ( 0 => '1914601472', 1 => '1914634239', ), - 323 => + 333 => array ( 0 => '1914642432', 1 => '1914650623', ), - 324 => + 334 => array ( 0 => '1914662912', 1 => '1914667007', ), - 325 => + 335 => array ( 0 => '1916010496', 1 => '1916141567', ), - 326 => + 336 => array ( 0 => '1917190144', 1 => '1917321215', ), - 327 => + 337 => array ( 0 => '1919680512', 1 => '1919729663', ), - 328 => + 338 => array ( 0 => '1919844352', 1 => '1919877119', ), - 329 => + 339 => array ( 0 => '1919885312', 1 => '1919893503', ), - 330 => + 340 => array ( 0 => '1919926272', 1 => '1919942655', ), - 331 => + 341 => array ( 0 => '1921073152', 1 => '1921089535', ), - 332 => + 342 => array ( 0 => '1921105920', 1 => '1921122303', ), - 333 => + 343 => array ( 0 => '1921843200', 1 => '1921851391', ), - 334 => + 344 => array ( 0 => '1921853440', 1 => '1921855487', ), - 335 => + 345 => array ( 0 => '1921900544', 1 => '1921908735', ), - 336 => + 346 => array ( 0 => '1925644288', 1 => '1925660671', ), - 337 => + 347 => array ( 0 => '1925677056', 1 => '1926234111', ), - 338 => + 348 => array ( 0 => '1929379840', 1 => '1930952703', ), - 339 => + 349 => array ( 0 => '1931436032', 1 => '1931444223', ), - 340 => + 350 => array ( 0 => '1932001280', 1 => '1932132351', ), - 341 => + 351 => array ( 0 => '1933836288', 1 => '1933901823', ), - 342 => + 352 => array ( 0 => '1933926400', 1 => '1933934591', ), - 343 => + 353 => array ( 0 => '1934032896', 1 => '1934098431', ), - 344 => + 354 => array ( 0 => '1934925824', 1 => '1934927871', ), - 345 => + 355 => array ( 0 => '1934991360', 1 => '1934999551', ), - 346 => + 356 => array ( 0 => '1935015936', 1 => '1935081471', ), - 347 => + 357 => array ( 0 => '1935147008', 1 => '1935671295', ), - 348 => + 358 => array ( 0 => '1937686528', 1 => '1937702911', ), - 349 => + 359 => array ( 0 => '1938292736', 1 => '1938948095', ), - 350 => + 360 => array ( 0 => '1939865600', 1 => '1939898367', ), - 351 => + 361 => array ( 0 => '1939931136', 1 => '1939996671', ), - 352 => + 362 => array ( 0 => '1940238336', 1 => '1940240383', ), - 353 => + 363 => array ( 0 => '1941053440', 1 => '1941057535', ), - 354 => + 364 => array ( 0 => '1941061632', 1 => '1941069823', ), - 355 => + 365 => array ( 0 => '1941655552', 1 => '1941657599', ), - 356 => + 366 => array ( 0 => '1948254208', 1 => '1949302783', ), - 357 => + 367 => array ( 0 => '1950547968', 1 => '1950580735', ), - 358 => + 368 => array ( 0 => '1950621696', 1 => '1950629887', ), - 359 => + 369 => array ( 0 => '1951662080', 1 => '1951727615', ), - 360 => + 370 => array ( 0 => '1952030720', 1 => '1952038911', ), - 361 => + 371 => array ( 0 => '1952110592', 1 => '1952112639', ), - 362 => + 372 => array ( 0 => '1952292864', 1 => '1952317439', ), - 363 => + 373 => array ( 0 => '1954021376', 1 => '1954545663', ), - 364 => + 374 => array ( 0 => '1958825984', 1 => '1958830079', ), - 365 => + 375 => array ( 0 => '1959239680', 1 => '1959241727', ), - 366 => + 376 => array ( 0 => '1959264256', 1 => '1959395327', ), - 367 => + 377 => array ( 0 => '1960050688', 1 => '1960058879', ), - 368 => + 378 => array ( 0 => '1962885120', 1 => '1962901503', ), - 369 => + 379 => array ( 0 => '1963982848', 1 => '1964113919', ), - 370 => + 380 => array ( 0 => '1964265472', 1 => '1964269567', ), - 371 => + 381 => array ( 0 => '1964294144', 1 => '1964310527', ), - 372 => + 382 => array ( 0 => '1966342144', 1 => '1966407679', ), - 373 => + 383 => array ( 0 => '1966424064', 1 => '1966440447', ), - 374 => + 384 => array ( 0 => '1966456832', 1 => '1966473215', ), - 375 => + 385 => array ( 0 => '1966571520', 1 => '1966587903', ), - 376 => + 386 => array ( 0 => '1966768128', 1 => '1966772223', ), - 377 => + 387 => array ( 0 => '1970143232', 1 => '1970210303', ), - 378 => + 388 => array ( 0 => '1970144768', 1 => '1970211071', ), - 379 => + 389 => array ( 0 => '1970145536', 1 => '1970274303', ), - 380 => + 390 => array ( 0 => '1970995200', 1 => '1971060735', ), - 381 => + 391 => array ( 0 => '1981808640', 1 => '1983905791', ), - 382 => + 392 => array ( 0 => '1984135168', 1 => '1984151551', ), - 383 => + 393 => array ( 0 => '1985675264', 1 => '1985708031', ), - 384 => + 394 => array ( 0 => '1985712128', 1 => '1985716223', ), - 385 => + 395 => array ( 0 => '1986510848', 1 => '1986519039', ), - 386 => + 396 => array ( 0 => '1986764800', 1 => '1986768895', ), - 387 => + 397 => array ( 0 => '1988083712', 1 => '1988362239', ), - 388 => + 398 => array ( 0 => '1988870144', 1 => '1988886527', ), - 389 => + 399 => array ( 0 => '1991245824', 1 => '1991311359', ), - 390 => + 400 => array ( 0 => '1993867264', 1 => '1994391551', ), - 391 => + 401 => array ( 0 => '1995046912', 1 => '1995177983', ), - 392 => + 402 => array ( 0 => '1997602816', 1 => '1997611007', ), - 393 => + 403 => array ( 0 => '1997619200', 1 => '1997635583', ), - 394 => + 404 => array ( 0 => '1997684736', 1 => '1997701119', ), - 395 => + 405 => array ( 0 => '1998487552', 1 => '1998503935', ), - 396 => + 406 => array ( 0 => '1998581760', 1 => '1998585855', ), - 397 => + 407 => array ( 0 => '1999282176', 1 => '1999290367', ), - 398 => + 408 => array ( 0 => '2000191488', 1 => '2000224255', ), - 399 => + 409 => array ( 0 => '2000355328', 1 => '2000371711', ), - 400 => + 410 => array ( 0 => '2000674816', 1 => '2001207295', ), - 401 => + 411 => array ( 0 => '2001420288', 1 => '2001453055', ), - 402 => + 412 => array ( 0 => '2001559552', 1 => '2001567743', ), - 403 => + 413 => array ( 0 => '2001870848', 1 => '2001879039', ), - 404 => + 414 => array ( 0 => '2006216704', 1 => '2006228991', ), - 405 => + 415 => array ( 0 => '2006253568', 1 => '2006319103', ), - 406 => + 416 => array ( 0 => '2007040000', 1 => '2007048191', ), - 407 => + 417 => array ( 0 => '2009071616', 1 => '2011168767', ), - 408 => + 418 => array ( 0 => '2011951104', 1 => '2011953151', ), - 409 => + 419 => array ( 0 => '2015199232', 1 => '2015203327', ), - 410 => + 420 => array ( 0 => '2016559104', 1 => '2016583679', ), - 411 => + 421 => array ( 0 => '2018050048', 1 => '2018115583', ), - 412 => + 422 => array ( 0 => '2022195200', 1 => '2022211583', ), - 413 => + 423 => array ( 0 => '2022572032', 1 => '2022637567', ), - 414 => + 424 => array ( 0 => '2022678528', 1 => '2022703103', ), - 415 => + 425 => array ( 0 => '2030059520', 1 => '2030108671', ), - 416 => + 426 => array ( 0 => '2030125056', 1 => '2030141439', ), - 417 => + 427 => array ( 0 => '2033324032', 1 => '2033328127', ), - 418 => + 428 => array ( 0 => '2033336320', 1 => '2033352703', ), - 419 => + 429 => array ( 0 => '2033377280', 1 => '2033385471', ), - 420 => + 430 => array ( 0 => '2033516544', 1 => '2033582079', ), - 421 => + 431 => array ( 0 => '2033631232', 1 => '2033647615', ), - 422 => + 432 => array ( 0 => '2033664000', 1 => '2033696767', ), - 423 => + 433 => array ( 0 => '2034237440', 1 => '2034499583', ), - 424 => + 434 => array ( 0 => '2035154944', 1 => '2035220479', ), - 425 => + 435 => array ( 0 => '2035810304', 1 => '2035875839', ), - 426 => + 436 => array ( 0 => '2036613120', 1 => '2036629503', ), - 427 => + 437 => array ( 0 => '2036711424', 1 => '2036715519', ), - 428 => + 438 => array ( 0 => '2036719616', 1 => '2036727807', ), - 429 => + 439 => array ( 0 => '2038169600', 1 => '2038366207', ), - 430 => + 440 => array ( 0 => '2038382592', 1 => '2038415359', ), - 431 => + 441 => array ( 0 => '2038431744', 1 => '2042626047', ), - 432 => + 442 => array ( 0 => '2043166720', 1 => '2043183103', ), - 433 => + 443 => array ( 0 => '2046558208', 1 => '2046705663', ), - 434 => + 444 => array ( 0 => '2046722048', 1 => '2046754815', ), - 435 => + 445 => array ( 0 => '2046822400', 1 => '2046824447', ), - 436 => + 446 => array ( 0 => '2046828544', 1 => '2046836735', ), - 437 => + 447 => array ( 0 => '2048917504', 1 => '2049966079', ), - 438 => + 448 => array ( 0 => '2050048000', 1 => '2050064383', ), - 439 => + 449 => array ( 0 => '2053341184', 1 => '2053373951', ), - 440 => - array ( - 0 => '2053382144', - 1 => '2053390335', - ), - 441 => + 450 => array ( 0 => '2053439488', 1 => '2053505023', ), - 442 => + 451 => array ( 0 => '2055217152', 1 => '2055229439', ), - 443 => + 452 => array ( 0 => '2055241728', 1 => '2055274495', ), - 444 => + 453 => array ( 0 => '2055327744', 1 => '2055329791', ), - 445 => + 454 => array ( 0 => '2055335936', 1 => '2055340031', ), - 446 => + 455 => array ( 0 => '2056806400', 1 => '2056814591', ), - 447 => + 456 => array ( 0 => '2056847360', 1 => '2056912895', ), - 448 => + 457 => array ( 0 => '2059878400', 1 => '2059927551', ), - 449 => + 458 => array ( 0 => '2060066816', 1 => '2060075007', ), - 450 => + 459 => array ( 0 => '2060091392', 1 => '2060189695', ), - 451 => + 460 => array ( 0 => '2063351808', 1 => '2063368191', ), - 452 => + 461 => array ( 0 => '2063384576', 1 => '2063392767', ), - 453 => + 462 => array ( 0 => '2063499264', 1 => '2063532031', ), - 454 => + 463 => array ( 0 => '2063597568', 1 => '2063601663', ), - 455 => + 464 => array ( 0 => '2065694720', 1 => '2066743295', ), - 456 => + 465 => array ( 0 => '2070061056', 1 => '2070077439', ), - 457 => + 466 => array ( 0 => '2070102016', 1 => '2070118399', ), - 458 => + 467 => array ( 0 => '2070192128', 1 => '2070200319', ), - 459 => + 468 => array ( 0 => '2070679552', 1 => '2070683647', ), - 460 => + 469 => array ( 0 => '2070716416', 1 => '2070724607', ), - 461 => + 470 => array ( 0 => '2070740992', 1 => '2070806527', ), - 462 => + 471 => array ( 0 => '2070872064', 1 => '2070937599', ), - 463 => + 472 => array ( 0 => '2072772608', 1 => '2073034751', ), - 464 => + 473 => array ( 0 => '2076639232', 1 => '2076671999', ), - 465 => + 474 => array ( 0 => '2076721152', 1 => '2076737535', ), - 466 => + 475 => array ( 0 => '2077491200', 1 => '2077753343', ), - 467 => + 476 => array ( 0 => '2078539776', 1 => '2078670847', ), - 468 => + 477 => array ( 0 => '2079850496', 1 => '2079916031', ), - 469 => + 478 => array ( 0 => '2079981568', 1 => '2080112639', ), - 470 => + 479 => array ( 0 => '2080260096', 1 => '2080268287', ), - 471 => + 480 => array ( 0 => '2080276480', 1 => '2080309247', ), - 472 => + 481 => array ( 0 => '2080374784', 1 => '2080636927', ), - 473 => + 482 => array ( 0 => '2080702464', 1 => '2080767999', ), - 474 => + 483 => array ( 0 => '2082209792', 1 => '2082258943', ), - 475 => + 484 => array ( 0 => '2083389440', 1 => '2083454975', ), - 476 => + 485 => array ( 0 => '2083520512', 1 => '2084569087', ), - 477 => + 486 => array ( 0 => '2084745216', 1 => '2084749311', ), - 478 => + 487 => array ( 0 => '2084753408', 1 => '2084757503', ), - 479 => + 488 => array ( 0 => '2085617664', 1 => '2085683199', ), - 480 => + 489 => array ( 0 => '2087649280', 1 => '2087714815', ), - 481 => + 490 => array ( 0 => '2089287680', 1 => '2089549823', ), - 482 => + 491 => array ( 0 => '2089943040', 1 => '2089959423', ), - 483 => + 492 => array ( 0 => '2090434560', 1 => '2090467327', ), - 484 => + 493 => array ( 0 => '2093088768', 1 => '2093154303', ), - 485 => + 494 => array ( 0 => '2093195264', 1 => '2093203455', ), - 486 => + 495 => array ( 0 => '2093211648', 1 => '2093219839', ), - 487 => + 496 => array ( 0 => '2093318144', 1 => '2093342719', ), - 488 => + 497 => array ( 0 => '2093350912', 1 => '2093383679', ), - 489 => + 498 => array ( 0 => '2093416448', 1 => '2093432831', ), - 490 => + 499 => array ( 0 => '2093449216', 1 => '2093481983', ), - 491 => + 500 => array ( 0 => '2094530560', 1 => '2094596095', ), - 492 => + 501 => array ( 0 => '2094645248', 1 => '2094653439', ), - 493 => + 502 => array ( 0 => '2096300032', 1 => '2096332799', ), - 494 => + 503 => array ( 0 => '2097053696', 1 => '2097086463', ), - 495 => + 504 => array ( 0 => '2097643520', 1 => '2097676287', ), - 496 => + 505 => array ( 0 => '2099216384', 1 => '2099232767', ), - 497 => + 506 => array ( 0 => '2100876800', 1 => '2100877055', ), - 498 => + 507 => array ( 0 => '2100887552', 1 => '2100953087', ), - 499 => + 508 => array ( 0 => '2101084160', 1 => '2101108735', ), - 500 => + 509 => array ( 0 => '2101149696', 1 => '2101182463', ), - 501 => + 510 => array ( 0 => '2101270528', 1 => '2101272575', ), - 502 => + 511 => array ( 0 => '2105540608', 1 => '2107637759', ), - 503 => + 512 => array ( 0 => '2108686336', 1 => '2109734911', ), - 504 => + 513 => array ( 0 => '2110799872', 1 => '2110816255', ), - 505 => + 514 => array ( 0 => '2110832640', 1 => '2110865407', ), - 506 => + 515 => array ( 0 => '2110898176', 1 => '2110914559', ), - 507 => + 516 => array ( 0 => '2112880640', 1 => '2113683455', ), - 508 => + 517 => array ( 0 => '2156265472', 1 => '2156331007', ), - 509 => + 518 => array ( 0 => '2180907008', 1 => '2180972543', ), - 510 => + 519 => array ( 0 => '2253062144', 1 => '2253127679', ), - 511 => + 520 => array ( 0 => '2302935040', 1 => '2303000575', ), - 512 => + 521 => array ( 0 => '2332418048', 1 => '2332419071', ), - 513 => + 522 => array ( 0 => '2341863424', 1 => '2341928959', ), - 514 => + 523 => array ( 0 => '2380201984', 1 => '2380267519', ), - 515 => + 524 => array ( 0 => '2415394816', 1 => '2415460351', ), - 516 => + 525 => array ( 0 => '2419075072', 1 => '2419077119', ), - 517 => + 526 => array ( 0 => '2419088384', 1 => '2419089407', ), - 518 => + 527 => array ( 0 => '2419090432', 1 => '2419091455', ), - 519 => + 528 => array ( 0 => '2466643968', 1 => '2466709503', ), - 520 => + 529 => array ( 0 => '2469068800', 1 => '2469134335', ), - 521 => + 530 => array ( 0 => '2469265408', 1 => '2469396479', ), - 522 => + 531 => array ( 0 => '2523612160', 1 => '2523613183', ), - 523 => + 532 => array ( 0 => '2523615232', 1 => '2523617279', ), - 524 => + 533 => array ( 0 => '2525093888', 1 => '2525094911', ), - 525 => + 534 => array ( 0 => '2526412800', 1 => '2526478335', ), - 526 => + 535 => array ( 0 => '2528575488', 1 => '2528641023', ), - 527 => + 536 => array ( 0 => '2529492992', 1 => '2529558527', ), - 528 => + 537 => array ( 0 => '2532475904', 1 => '2532476927', ), - 529 => + 538 => array ( 0 => '2532478976', 1 => '2532479999', ), - 530 => + 539 => array ( 0 => '2556624896', 1 => '2556690431', ), - 531 => + 540 => array ( 0 => '2559901696', 1 => '2559967231', ), - 532 => + 541 => array ( 0 => '2584346624', 1 => '2584412159', ), - 533 => + 542 => array ( 0 => '2615541760', 1 => '2615607295', ), - 534 => + 543 => array ( 0 => '2626879488', 1 => '2626945023', ), - 535 => + 544 => array ( 0 => '2641829888', 1 => '2641831935', ), - 536 => + 545 => array ( 0 => '2646933504', 1 => '2646999039', ), - 537 => + 546 => array ( 0 => '2653683712', 1 => '2653749247', ), - 538 => + 547 => array ( 0 => '2697636864', 1 => '2697638911', ), - 539 => + 548 => array ( 0 => '2709127168', 1 => '2709192703', ), - 540 => + 549 => array ( 0 => '2738199552', 1 => '2738200575', ), - 541 => + 550 => array ( 0 => '2744647680', 1 => '2744713215', ), - 542 => + 551 => array ( 0 => '2746482688', 1 => '2746548223', ), - 543 => + 552 => array ( 0 => '2748645376', 1 => '2748710911', ), - 544 => + 553 => array ( 0 => '2749235200', 1 => '2749300735', ), - 545 => + 554 => array ( 0 => '2749693952', 1 => '2749759487', ), - 546 => + 555 => array ( 0 => '2750349312', 1 => '2750414847', ), - 547 => + 556 => array ( 0 => '2751397888', 1 => '2751463423', ), - 548 => + 557 => array ( 0 => '2759589888', 1 => '2759720959', ), - 549 => + 558 => array ( 0 => '2776891392', 1 => '2777022463', ), - 550 => + 559 => array ( 0 => '2777481216', 1 => '2777546751', ), - 551 => + 560 => array ( 0 => '2780430336', 1 => '2780495871', ), - 552 => + 561 => array ( 0 => '2780954624', 1 => '2781020159', ), - 553 => + 562 => array ( 0 => '2782199808', 1 => '2782265343', ), - 554 => + 563 => array ( 0 => '2783248384', 1 => '2783313919', ), - 555 => + 564 => array ( 0 => '2784165888', 1 => '2784296959', ), - 556 => + 565 => array ( 0 => '2784362496', 1 => '2784428031', ), - 557 => + 566 => array ( 0 => '2790195200', 1 => '2790260735', ), - 558 => + 567 => array ( 0 => '2791768064', 1 => '2791899135', ), - 559 => + 568 => array ( 0 => '2793209856', 1 => '2793275391', ), - 560 => + 569 => array ( 0 => '2823684096', 1 => '2823749631', ), - 561 => + 570 => array ( 0 => '2826108928', 1 => '2826174463', ), - 562 => + 571 => array ( 0 => '2826829824', 1 => '2826895359', ), - 563 => + 572 => array ( 0 => '2827157504', 1 => '2827223039', ), - 564 => + 573 => array ( 0 => '2828664832', 1 => '2828730367', ), - 565 => + 574 => array ( 0 => '2830893056', 1 => '2830958591', ), - 566 => + 575 => array ( 0 => '2832924672', 1 => '2832990207', ), - 567 => + 576 => array ( 0 => '2834825216', 1 => '2834956287', ), - 568 => + 577 => array ( 0 => '2844524544', 1 => '2844590079', ), - 569 => + 578 => array ( 0 => '2848980992', 1 => '2850029567', ), - 570 => + 579 => array ( 0 => '2937856000', 1 => '2937860095', ), - 571 => + 580 => array ( 0 => '2938699776', 1 => '2938703871', ), - 572 => + 581 => array ( 0 => '2939002880', 1 => '2939004927', ), - 573 => + 582 => array ( 0 => '2939011072', 1 => '2939027455', ), - 574 => + 583 => array ( 0 => '2942976000', 1 => '2942992383', ), - 575 => + 584 => array ( 0 => '2943041536', 1 => '2943057919', ), - 576 => + 585 => array ( 0 => '2943291392', 1 => '2943295487', ), - 577 => + 586 => array ( 0 => '2943352832', 1 => '2944401407', ), - 578 => + 587 => array ( 0 => '2946367488', 1 => '2946375679', ), - 579 => + 588 => array ( 0 => '2947579904', 1 => '2947583999', ), - 580 => + 589 => array ( 0 => '2948595712', 1 => '2952790015', ), - 581 => + 590 => array ( 0 => '3024093184', 1 => '3024617471', ), - 582 => + 591 => array ( 0 => '3025141760', 1 => '3025403903', ), - 583 => + 592 => array ( 0 => '3025944576', 1 => '3025960959', ), - 584 => + 593 => array ( 0 => '3025989632', 1 => '3025993727', ), - 585 => + 594 => array ( 0 => '3028484096', 1 => '3028500479', ), - 586 => + 595 => array ( 0 => '3028549632', 1 => '3028811775', ), - 587 => + 596 => array ( 0 => '3029644288', 1 => '3029645311', ), - 588 => + 597 => array ( 0 => '3029778432', 1 => '3029788671', ), - 589 => + 598 => array ( 0 => '3031826432', 1 => '3031891967', ), - 590 => + 599 => array ( 0 => '3032301568', 1 => '3032317951', ), - 591 => + 600 => array ( 0 => '3032330240', 1 => '3032334335', ), - 592 => + 601 => array ( 0 => '3033661440', 1 => '3033694207', ), - 593 => + 602 => array ( 0 => '3033710592', 1 => '3033712639', ), - 594 => + 603 => array ( 0 => '3033726976', 1 => '3033743359', ), - 595 => + 604 => array ( 0 => '3034578944', 1 => '3035103231', ), - 596 => + 605 => array ( 0 => '3035217920', 1 => '3035234303', ), - 597 => + 606 => array ( 0 => '3035365376', 1 => '3035627519', ), - 598 => + 607 => array ( 0 => '3055484928', 1 => '3055550463', ), - 599 => + 608 => array ( 0 => '3056734208', 1 => '3056746495', ), - 600 => + 609 => array ( 0 => '3064029184', 1 => '3064135679', ), - 601 => + 610 => array ( 0 => '3064168448', 1 => '3064201215', ), - 602 => + 611 => array ( 0 => '3064725504', 1 => '3064791039', ), - 603 => + 612 => array ( 0 => '3064811520', 1 => '3064823807', ), - 604 => + 613 => array ( 0 => '3064832000', 1 => '3064840191', ), - 605 => + 614 => array ( 0 => '3066036224', 1 => '3066560511', ), - 606 => + 615 => array ( 0 => '3067084800', 1 => '3068657663', ), - 607 => + 616 => array ( 0 => '3068993536', 1 => '3069018111', ), - 608 => + 617 => array ( 0 => '3069034496', 1 => '3069050879', ), - 609 => + 618 => array ( 0 => '3069968384', 1 => '3069984767', ), - 610 => + 619 => array ( 0 => '3070001152', 1 => '3070033919', ), - 611 => + 620 => array ( 0 => '3070197760', 1 => '3070230527', ), - 612 => + 621 => array ( 0 => '3075375104', 1 => '3075383295', ), - 613 => + 622 => array ( 0 => '3075391488', 1 => '3075407871', ), - 614 => + 623 => array ( 0 => '3075915776', 1 => '3075932159', ), - 615 => + 624 => array ( 0 => '3076161536', 1 => '3076169727', ), - 616 => + 625 => array ( 0 => '3076243456', 1 => '3076259839', ), - 617 => + 626 => array ( 0 => '3076521984', 1 => '3078619135', ), - 618 => + 627 => array ( 0 => '3221576192', 1 => '3221576447', ), - 619 => + 628 => array ( 0 => '3227779584', 1 => '3227779839', ), - 620 => + 629 => array ( 0 => '3228045056', 1 => '3228045311', ), - 621 => + 630 => array ( 0 => '3234014976', 1 => '3234015487', ), - 622 => + 631 => array ( 0 => '3234564608', 1 => '3234566911', ), - 623 => + 632 => array ( 0 => '3237345536', 1 => '3237346303', ), - 624 => + 633 => array ( 0 => '3237548032', 1 => '3237552127', ), - 625 => + 634 => array ( 0 => '3389198336', 1 => '3389202431', ), - 626 => + 635 => array ( 0 => '3389562880', 1 => '3389571071', ), - 627 => + 636 => array ( 0 => '3389938176', 1 => '3389938687', ), - 628 => + 637 => array ( 0 => '3389941504', 1 => '3389941759', ), - 629 => + 638 => array ( 0 => '3389957376', 1 => '3389957631', ), - 630 => + 639 => array ( 0 => '3390329600', 1 => '3390330111', ), - 631 => + 640 => array ( 0 => '3390333696', 1 => '3390333951', ), - 632 => + 641 => array ( 0 => '3390338816', 1 => '3390339071', ), - 633 => + 642 => array ( 0 => '3390341120', 1 => '3390375935', ), - 634 => + 643 => array ( 0 => '3390963712', 1 => '3390972671', ), - 635 => + 644 => array ( 0 => '3390972928', 1 => '3390973695', ), - 636 => + 645 => array ( 0 => '3390973952', 1 => '3390977023', ), - 637 => + 646 => array ( 0 => '3390977536', 1 => '3390978047', ), - 638 => + 647 => array ( 0 => '3390978560', 1 => '3390978815', ), - 639 => + 648 => array ( 0 => '3390979072', 1 => '3391068671', ), - 640 => + 649 => array ( 0 => '3391068928', 1 => '3391069183', ), - 641 => + 650 => array ( 0 => '3391074304', 1 => '3391075583', ), - 642 => + 651 => array ( 0 => '3391075840', 1 => '3391082495', ), - 643 => + 652 => array ( 0 => '3391083520', 1 => '3391085567', ), - 644 => + 653 => array ( 0 => '3391086592', 1 => '3391094783', ), - 645 => + 654 => array ( 0 => '3391827968', 1 => '3391832063', ), - 646 => + 655 => array ( 0 => '3392919552', 1 => '3392921599', ), - 647 => + 656 => array ( 0 => '3393511424', 1 => '3393519615', ), - 648 => + 657 => array ( 0 => '3393815552', 1 => '3393816575', ), - 649 => + 658 => array ( 0 => '3394635776', 1 => '3394637823', ), - 650 => + 659 => array ( 0 => '3394862080', 1 => '3394863103', ), - 651 => + 660 => array ( 0 => '3394893824', 1 => '3394894847', ), - 652 => + 661 => array ( 0 => '3394960384', 1 => '3394961407', ), - 653 => + 662 => array ( 0 => '3397283840', 1 => '3397285887', ), - 654 => + 663 => array ( 0 => '3397411840', 1 => '3397412351', ), - 655 => + 664 => array ( 0 => '3397588992', 1 => '3397591039', ), - 656 => + 665 => array ( 0 => '3397718016', 1 => '3397722111', ), - 657 => + 666 => array ( 0 => '3397939200', 1 => '3397951487', ), - 658 => + 667 => array ( 0 => '3398709248', 1 => '3398710271', ), - 659 => + 668 => array ( 0 => '3398873088', 1 => '3398877183', ), - 660 => + 669 => array ( 0 => '3399389184', 1 => '3399393279', ), - 661 => + 670 => array ( 0 => '3399712768', 1 => '3399720959', ), - 662 => + 671 => array ( 0 => '3399825408', 1 => '3399826431', ), - 663 => + 672 => array ( 0 => '3399995392', 1 => '3399999487', ), - 664 => + 673 => array ( 0 => '3400267776', 1 => '3400268799', ), - 665 => + 674 => array ( 0 => '3400423424', 1 => '3400424447', ), - 666 => + 675 => array ( 0 => '3400766464', 1 => '3400767487', ), - 667 => + 676 => array ( 0 => '3400773632', 1 => '3400775679', ), - 668 => + 677 => array ( 0 => '3406946816', 1 => '3406947071', ), - 669 => + 678 => array ( 0 => '3411085312', 1 => '3411086335', ), - 670 => + 679 => array ( 0 => '3411116032', 1 => '3411124223', ), - 671 => + 680 => array ( 0 => '3411204864', 1 => '3411205631', ), - 672 => + 681 => array ( 0 => '3411210240', 1 => '3411212287', ), - 673 => + 682 => array ( 0 => '3411247104', 1 => '3411249151', ), - 674 => + 683 => array ( 0 => '3411254784', 1 => '3411255295', ), - 675 => + 684 => array ( 0 => '3411341312', 1 => '3411345407', ), - 676 => + 685 => array ( 0 => '3411681280', 1 => '3411689471', ), - 677 => + 686 => array ( 0 => '3412369408', 1 => '3412377599', ), - 678 => + 687 => array ( 0 => '3412918272', 1 => '3412926463', ), - 679 => + 688 => array ( 0 => '3413884928', 1 => '3413893119', ), - 680 => + 689 => array ( 0 => '3414204416', 1 => '3414220799', ), - 681 => + 690 => array ( 0 => '3414223872', 1 => '3414224895', ), - 682 => + 691 => array ( 0 => '3414230528', 1 => '3414231039', ), - 683 => + 692 => array ( 0 => '3414310912', 1 => '3414327295', ), - 684 => + 693 => array ( 0 => '3414339584', 1 => '3414343679', ), - 685 => + 694 => array ( 0 => '3414466560', 1 => '3414474751', ), - 686 => + 695 => array ( 0 => '3414532096', 1 => '3414540287', ), - 687 => + 696 => array ( 0 => '3415121920', 1 => '3415130111', ), - 688 => + 697 => array ( 0 => '3415136256', 1 => '3415136767', ), - 689 => + 698 => array ( 0 => '3415568384', 1 => '3415572479', ), - 690 => + 699 => array ( 0 => '3415777280', 1 => '3415785471', ), - 691 => + 700 => array ( 0 => '3415838720', 1 => '3415842815', ), - 692 => + 701 => array ( 0 => '3416707072', 1 => '3416709119', ), - 693 => + 702 => array ( 0 => '3416851456', 1 => '3416851967', ), - 694 => + 703 => array ( 0 => '3416940544', 1 => '3416948735', ), - 695 => + 704 => array ( 0 => '3417022464', 1 => '3417030655', ), - 696 => + 705 => array ( 0 => '3417137152', 1 => '3417145343', ), - 697 => + 706 => array ( 0 => '3417251840', 1 => '3417260031', ), - 698 => + 707 => array ( 0 => '3417291776', 1 => '3417292799', ), - 699 => + 708 => array ( 0 => '3418227712', 1 => '3418228735', ), - 700 => + 709 => array ( 0 => '3418233344', 1 => '3418233855', ), - 701 => + 710 => array ( 0 => '3419344896', 1 => '3419348991', ), - 702 => + 711 => array ( 0 => '3419541504', 1 => '3419553791', ), - 703 => + 712 => array ( 0 => '3419693056', 1 => '3419701247', ), - 704 => + 713 => array ( 0 => '3419709440', 1 => '3419717631', ), - 705 => + 714 => array ( 0 => '3419914240', 1 => '3419922431', ), - 706 => + 715 => array ( 0 => '3419971584', 1 => '3419979775', ), - 707 => + 716 => array ( 0 => '3420048384', 1 => '3420061695', ), - 708 => + 717 => array ( 0 => '3420413952', 1 => '3420422143', ), - 709 => + 718 => array ( 0 => '3420434688', 1 => '3420434943', ), - 710 => + 719 => array ( 0 => '3420454912', 1 => '3421077503', ), - 711 => + 720 => array ( 0 => '3421084160', 1 => '3421084927', ), - 712 => + 721 => array ( 0 => '3421093888', 1 => '3421227007', ), - 713 => + 722 => array ( 0 => '3421227520', 1 => '3421228031', ), - 714 => + 723 => array ( 0 => '3421229056', 1 => '3421503487', ), - 715 => + 724 => array ( 0 => '3421536256', 1 => '3421544447', ), - 716 => + 725 => array ( 0 => '3421552640', 1 => '3421611519', ), - 717 => + 726 => array ( 0 => '3421611776', 1 => '3421613823', ), - 718 => + 727 => array ( 0 => '3421614080', 1 => '3421624319', ), - 719 => + 728 => array ( 0 => '3421625344', 1 => '3421663231', ), - 720 => + 729 => array ( 0 => '3421665280', 1 => '3421716479', ), - 721 => + 730 => array ( 0 => '3421703168', 1 => '3421705215', ), - 722 => + 731 => array ( 0 => '3421732864', 1 => '3422296063', ), - 723 => + 732 => array ( 0 => '3422296832', 1 => '3422367743', ), - 724 => + 733 => array ( 0 => '3422371840', 1 => '3422415103', ), - 725 => + 734 => array ( 0 => '3422415360', 1 => '3422420991', ), - 726 => + 735 => array ( 0 => '3422421248', 1 => '3422421503', ), - 727 => + 736 => array ( 0 => '3422429184', 1 => '3422429695', ), - 728 => + 737 => array ( 0 => '3422431232', 1 => '3422431487', ), - 729 => + 738 => array ( 0 => '3422433792', 1 => '3422435583', ), - 730 => + 739 => array ( 0 => '3422445568', 1 => '3422543359', ), - 731 => + 740 => array ( 0 => '3422543872', 1 => '3422546687', ), - 732 => + 741 => array ( 0 => '3422546944', 1 => '3422552063', ), - 733 => + 742 => array ( 0 => '3523223552', 1 => '3523231743', ), - 734 => + 743 => array ( 0 => '3523354624', 1 => '3523362815', ), - 735 => + 744 => array ( 0 => '3523500032', 1 => '3523502079', ), - 736 => + 745 => array ( 0 => '3523532800', 1 => '3523534847', ), - 737 => + 746 => array ( 0 => '3524313088', 1 => '3524329471', ), - 738 => + 747 => array ( 0 => '3527008256', 1 => '3527016447', ), - 739 => + 748 => array ( 0 => '3528966144', 1 => '3528974335', ), - 740 => + 749 => array ( 0 => '3529089024', 1 => '3529097215', ), - 741 => + 750 => array ( 0 => '3529113600', 1 => '3529622527', ), - 742 => + 751 => array ( 0 => '3529629696', 1 => '3529834495', ), - 743 => + 752 => array ( 0 => '3529850880', 1 => '3530506239', ), - 744 => + 753 => array ( 0 => '3530510336', 1 => '3530518527', ), - 745 => + 754 => array ( 0 => '3530522624', 1 => '3530702847', ), - 746 => + 755 => array ( 0 => '3530708992', 1 => '3530711039', ), - 747 => + 756 => array ( 0 => '3530713088', 1 => '3530715135', ), - 748 => + 757 => array ( 0 => '3530727424', 1 => '3530735615', ), - 749 => + 758 => array ( 0 => '3530739712', 1 => '3531538431', ), - 750 => + 759 => array ( 0 => '3531546624', 1 => '3531603967', ), - 751 => + 760 => array ( 0 => '3534880768', 1 => '3535273983', ), - 752 => + 761 => array ( 0 => '3535814656', 1 => '3535822847', ), - 753 => + 762 => array ( 0 => '3536584704', 1 => '3536846847', ), - 754 => + 763 => array ( 0 => '3537027072', 1 => '3537047551', ), - 755 => + 764 => array ( 0 => '3537059840', 1 => '3537068031', ), - 756 => + 765 => array ( 0 => '3537371136', 1 => '3537526783', ), - 757 => + 766 => array ( 0 => '3537534976', 1 => '3537739775', ), - 758 => + 767 => array ( 0 => '3537743872', 1 => '3537895423', ), - 759 => + 768 => array ( 0 => '3542089728', 1 => '3542306815', ), - 760 => + 769 => array ( 0 => '3542310912', 1 => '3542311935', ), - 761 => + 770 => array ( 0 => '3542315008', 1 => '3542376447', ), - 762 => + 771 => array ( 0 => '3542384640', 1 => '3543114751', ), - 763 => + 772 => array ( 0 => '3543117824', 1 => '3543134207', ), - 764 => + 773 => array ( 0 => '3543138304', 1 => '3544014847', ), - 765 => + 774 => array ( 0 => '3544018944', 1 => '3544145919', ), - 766 => + 775 => array ( 0 => '3544154112', 1 => '3544186879', ), - 767 => + 776 => array ( 0 => '3546808320', 1 => '3547856895', ), - 768 => + 777 => array ( 0 => '3551002624', 1 => '3551313919', ), - 769 => + 778 => array ( 0 => '3551318016', + 1 => '3552317439', + ), + 779 => + array ( + 0 => '3552321536', 1 => '3552456703', ), - 770 => + 780 => array ( 0 => '3552473088', 1 => '3552481279', ), - 771 => + 781 => array ( 0 => '3552501760', 1 => '3552514047', ), - 772 => + 782 => array ( 0 => '3552518144', 1 => '3552522239', ), - 773 => + 783 => array ( 0 => '3552526336', 1 => '3552534527', ), - 774 => + 784 => array ( 0 => '3552538624', 1 => '3552546815', ), - 775 => + 785 => array ( 0 => '3552550912', 1 => '3552559103', ), - 776 => + 786 => array ( 0 => '3552571392', 1 => '3555287039', ), - 777 => + 787 => array ( 0 => '3555295232', 1 => '3555389439', ), - 778 => + 788 => array ( 0 => '3555390464', 1 => '3555393535', ), - 779 => + 789 => array ( 0 => '3555401728', 1 => '3555561471', ), - 780 => + 790 => array ( 0 => '3555565568', 1 => '3556696063', ), - 781 => + 791 => array ( 0 => '3556703232', 1 => '3556769791', ), - 782 => + 792 => array ( 0 => '3659792384', 1 => '3659890687', ), - 783 => + 793 => array ( 0 => '3659907072', 1 => '3660054527', ), - 784 => + 794 => array ( 0 => '3660578816', 1 => '3661103103', ), - 785 => + 795 => array ( 0 => '3664084992', 1 => '3664117759', ), - 786 => + 796 => array ( 0 => '3666870272', 1 => '3667918847', ), - 787 => + 797 => array ( 0 => '3671130112', 1 => '3671195647', ), - 788 => + 798 => array ( 0 => '3672637440', 1 => '3673161727', ), - 789 => + 799 => array ( 0 => '3689938944', 1 => '3690070015', ), - 790 => + 800 => array ( 0 => '3690463232', 1 => '3690987519', ), - 791 => + 801 => array ( 0 => '3695181824', 1 => '3697278975', ), - 792 => + 802 => array ( 0 => '3697737728', 1 => '3697803263', ), - 793 => + 803 => array ( 0 => '3698589696', 1 => '3699376127', ), - 794 => + 804 => array ( 0 => '3700752384', 1 => '3700817919', ), - 795 => + 805 => array ( 0 => '3706060800', 1 => '3706126335', ), - 796 => + 806 => array ( 0 => '3716431872', 1 => '3716440063', ), - 797 => + 807 => array ( 0 => '3716493312', 1 => '3716497407', ), - 798 => + 808 => array ( 0 => '3716513792', 1 => '3716530175', ), - 799 => + 809 => array ( 0 => '3716808704', 1 => '3718840319', ), - 800 => + 810 => array ( 0 => '3730833408', 1 => '3732602879', ), - 801 => + 811 => array ( 0 => '3739680768', 1 => '3739697151', ), - 802 => + 812 => array ( 0 => '3739746304', 1 => '3740270591', ), - 803 => + 813 => array ( 0 => '3741024256', 1 => '3741057023', ), - 804 => + 814 => array ( 0 => '3743055872', 1 => '3743088639', ), - 805 => + 815 => array ( 0 => '3743186944', 1 => '3743219711', ), - 806 => + 816 => array ( 0 => '3743416320', 1 => '3745513471', ), - 807 => + 817 => array ( 0 => '3749855232', 1 => '3749969919', ), - 808 => + 818 => array ( 0 => '3752165376', 1 => '3752198143', ), - 809 => + 819 => array ( 0 => '3752329216', 1 => '3752853503', ), - 810 => + 820 => array ( 0 => '3754033152', 1 => '3754164223', ), - 811 => + 821 => array ( 0 => '3755868160', 1 => '3755933695', ), - 812 => + 822 => array ( 0 => '3757899776', 1 => '3757965311', ), - 813 => + 823 => array ( 0 => '3758080000', 1 => '3758088191', diff --git a/common/defaults/korea.ipv6.php b/common/defaults/korea.ipv6.php index f4af382a4..e0345968f 100644 --- a/common/defaults/korea.ipv6.php +++ b/common/defaults/korea.ipv6.php @@ -2,7 +2,7 @@ /** * Source: https://xn--3e0bx5euxnjje69i70af08bea817g.xn--3e0b707e/jsp/infoboard/stats/inProCurIpv6Add.jsp - * Last Updated: 2018-03-07 + * Last Updated: 2019-05-04 */ return array ( 0 => @@ -171,361 +171,366 @@ return array ( 1 => '24021a00ffffffff', ), 33 => + array ( + 0 => '2402bcc000000000', + 1 => '2402bcc0ffffffff', + ), + 34 => array ( 0 => '2402be0000000000', 1 => '2402be00ffffffff', ), - 34 => + 35 => array ( 0 => '2402de0000000000', 1 => '2402de00ffffffff', ), - 35 => + 36 => array ( 0 => '2402f40000000000', 1 => '2402f400ffffffff', ), - 36 => + 37 => array ( 0 => '24033e0000000000', 1 => '24033e00ffffffff', ), - 37 => + 38 => array ( 0 => '24053d0000000000', 1 => '24053d00ffffffff', ), - 38 => + 39 => array ( 0 => '24055f0000000000', 1 => '24055f00ffffffff', ), - 39 => + 40 => array ( 0 => '24057b0000000000', 1 => '24057b00ffffffff', ), - 40 => + 41 => array ( 0 => '2405c00000000000', 1 => '2405c000ffffffff', ), - 41 => + 42 => array ( 0 => '2405d88000000000', 1 => '2405d880ffffffff', ), - 42 => + 43 => array ( 0 => '24066a0000000000', 1 => '24066a00ffffffff', ), - 43 => + 44 => array ( 0 => '2406ad0000000000', 1 => '2406ad00ffffffff', ), - 44 => + 45 => array ( 0 => '2406b00000000000', 1 => '2406b000ffffffff', ), - 45 => + 46 => array ( 0 => '2406d00000000000', 1 => '2406d000ffffffff', ), - 46 => + 47 => array ( 0 => '2406d70000000000', 1 => '2406d700ffffffff', ), - 47 => + 48 => array ( 0 => '24070b0000000000', 1 => '24070b00ffffffff', ), - 48 => + 49 => array ( 0 => '24079b8000000000', 1 => '24079b80ffffffff', ), - 49 => + 50 => array ( 0 => '2407b20000000000', 1 => '2407b200ffffffff', ), - 50 => + 51 => array ( 0 => '2407b80000000000', 1 => '2407b800ffffffff', ), - 51 => + 52 => array ( 0 => '2407c00000000000', 1 => '2407c000ffffffff', ), - 52 => + 53 => array ( 0 => '2407c70000000000', 1 => '2407c700ffffffff', ), - 53 => + 54 => array ( 0 => '2001022000000000', 1 => '20010220ffffffff', ), - 54 => + 55 => array ( 0 => '2001023000000000', 1 => '20010230ffffffff', ), - 55 => + 56 => array ( 0 => '2001027000000000', 1 => '20010270ffffffff', ), - 56 => + 57 => array ( 0 => '2001028000000000', 1 => '20010280ffffffff', ), - 57 => + 58 => array ( 0 => '2001029000000000', 1 => '20010290ffffffff', ), - 58 => + 59 => array ( 0 => '2001032000000000', 1 => '20010320ffffffff', ), - 59 => + 60 => array ( 0 => '2001033000000000', 1 => '20010330ffffffff', ), - 60 => + 61 => array ( 0 => '2001037800000000', 1 => '20010378ffffffff', ), - 61 => + 62 => array ( 0 => '2001039000000000', 1 => '20010390ffffffff', ), - 62 => + 63 => array ( 0 => '2001443000000000', 1 => '20014430ffffffff', ), - 63 => + 64 => array ( 0 => '2400000000000000', 1 => '24000fffffffffff', ), - 64 => + 65 => array ( 0 => '2400180000000000', 1 => '24001800ffffffff', ), - 65 => + 66 => array ( 0 => '2400330000000000', 1 => '24003300ffffffff', ), - 66 => + 67 => array ( 0 => '2400478000000000', 1 => '24004780ffffffff', ), - 67 => + 68 => array ( 0 => '2400498000000000', 1 => '24004980ffffffff', ), - 68 => + 69 => array ( 0 => '2401270000000000', 1 => '24012700ffffffff', ), - 69 => + 70 => array ( 0 => '2401400000000000', 1 => '24014000ffffffff', ), - 70 => + 71 => array ( 0 => '2402000000000000', 1 => '240200ffffffffff', ), - 71 => + 72 => array ( 0 => '2402310000000000', 1 => '24023100ffffffff', ), - 72 => + 73 => array ( 0 => '2402580000000000', 1 => '24025800ffffffff', ), - 73 => + 74 => array ( 0 => '2402610000000000', 1 => '24026100ffffffff', ), - 74 => + 75 => array ( 0 => '2402700000000000', 1 => '24027000ffffffff', ), - 75 => + 76 => array ( 0 => '2403370000000000', 1 => '24033700ffffffff', ), - 76 => + 77 => array ( 0 => '2403630000000000', 1 => '24036300ffffffff', ), - 77 => + 78 => array ( 0 => '2403650000000000', 1 => '24036500ffffffff', ), - 78 => + 79 => array ( 0 => '2404018000000000', 1 => '2404018fffffffff', ), - 79 => + 80 => array ( 0 => '2404080000000000', 1 => '24040800ffffffff', ), - 80 => + 81 => array ( 0 => '2404230000000000', 1 => '24042300ffffffff', ), - 81 => + 82 => array ( 0 => '2404460000000000', 1 => '24044600ffffffff', ), - 82 => + 83 => array ( 0 => '2405350000000000', 1 => '24053500ffffffff', ), - 83 => + 84 => array ( 0 => '2405430000000000', 1 => '24054300ffffffff', ), - 84 => + 85 => array ( 0 => '2405580000000000', 1 => '24055800ffffffff', ), - 85 => + 86 => array ( 0 => '2405860000000000', 1 => '24058600ffffffff', ), - 86 => + 87 => array ( 0 => '2405950000000000', 1 => '24059500ffffffff', ), - 87 => + 88 => array ( 0 => '2406400000000000', 1 => '24064000ffffffff', ), - 88 => + 89 => array ( 0 => '2406590000000000', 1 => '24065900ffffffff', ), - 89 => + 90 => array ( 0 => '2406660000000000', 1 => '24066600ffffffff', ), - 90 => + 91 => array ( 0 => '2406680000000000', 1 => '24066800ffffffff', ), - 91 => + 92 => array ( 0 => '2407200000000000', 1 => '24072000ffffffff', ), - 92 => + 93 => array ( 0 => '2407350000000000', 1 => '24073500ffffffff', ), - 93 => + 94 => array ( 0 => '2407508000000000', 1 => '24075080ffffffff', ), - 94 => + 95 => array ( 0 => '2407518000000000', 1 => '24075180ffffffff', ), - 95 => + 96 => array ( 0 => '2407650000000000', 1 => '24076500ffffffff', ), - 96 => + 97 => array ( 0 => '2407670000000000', 1 => '24076700ffffffff', ), - 97 => + 98 => array ( 0 => '2407910000000000', 1 => '24079100ffffffff', ), - 98 => + 99 => array ( 0 => '20010e6000000000', 1 => '20010e60ffffffff', ), - 99 => + 100 => array ( 0 => '20010e7000000000', 1 => '20010e70ffffffff', ), - 100 => + 101 => array ( 0 => '20010e7800000000', 1 => '20010e78ffffffff', ), - 101 => + 102 => array ( 0 => '20010e9800000000', 1 => '20010e98ffffffff', ), - 102 => + 103 => array ( 0 => '24009e8000000000', 1 => '24009e80ffffffff', ), - 103 => + 104 => array ( 0 => '2400e18000000000', 1 => '2400e180ffffffff', ), - 104 => + 105 => array ( 0 => '2401e20000000000', 1 => '2401e200ffffffff', diff --git a/common/framework/debug.php b/common/framework/debug.php index 04836b6b5..f9ce31076 100644 --- a/common/framework/debug.php +++ b/common/framework/debug.php @@ -650,7 +650,7 @@ class Debug } // Localize the error message. - $display_error_message = ini_get('display_errors') || Session::isAdmin(); + $display_error_message = ini_get('display_errors') || !\Context::isInstalled() || Session::isAdmin(); $message = $display_error_message ? $message : lang('msg_server_error_see_log'); if ($message === 'msg_server_error_see_log') { @@ -658,7 +658,35 @@ class Debug } // Display a generic error page. - \Context::displayErrorPage($title, $message, 500); + try + { + \Context::displayErrorPage($title, $message, 500); + } + catch (\Error $e) + { + self::displayError($message); + } + } + + /** + * Display a default error. + * + * @param string $message + * @return void + */ + public static function displayError($message) + { + header('HTTP/1.1 500 Internal Server Error'); + if ($_SERVER['REQUEST_METHOD'] === 'GET' || !isset($_SERVER['HTTP_X_REQUESTED_WITH'])) + { + header('Content-Type: text/html; charset=UTF-8'); + echo sprintf('Server Error%s', escape($message, false)); + } + else + { + header('Content-Type: application/json; charset=UTF-8'); + echo json_encode(array('error' => -1, 'message' => escape($message, false)), \JSON_UNESCAPED_UNICODE); + } } /** diff --git a/common/framework/drivers/cache/apc.php b/common/framework/drivers/cache/apc.php index e92da38cf..b25dc888d 100644 --- a/common/framework/drivers/cache/apc.php +++ b/common/framework/drivers/cache/apc.php @@ -49,7 +49,7 @@ class APC implements \Rhymix\Framework\Drivers\CacheInterface */ public static function isSupported() { - return function_exists('apc_exists'); + return function_exists('apcu_exists'); } /** @@ -75,7 +75,7 @@ class APC implements \Rhymix\Framework\Drivers\CacheInterface */ public function get($key) { - $value = apc_fetch($key); + $value = apcu_fetch($key); return $value === false ? null : $value; } @@ -93,7 +93,7 @@ class APC implements \Rhymix\Framework\Drivers\CacheInterface */ public function set($key, $value, $ttl = 0, $force = false) { - return apc_store($key, $value, $ttl); + return apcu_store($key, $value, $ttl); } /** @@ -107,7 +107,7 @@ class APC implements \Rhymix\Framework\Drivers\CacheInterface */ public function delete($key) { - return apc_delete($key); + return apcu_delete($key); } /** @@ -120,7 +120,7 @@ class APC implements \Rhymix\Framework\Drivers\CacheInterface */ public function exists($key) { - return apc_exists($key); + return apcu_exists($key); } /** @@ -135,10 +135,10 @@ class APC implements \Rhymix\Framework\Drivers\CacheInterface */ public function incr($key, $amount) { - $result = apc_inc($key, $amount); + $result = apcu_inc($key, $amount); if ($result === false) { - apc_store($key, $amount); + apcu_store($key, $amount); $result = $amount; } return $result; @@ -156,10 +156,10 @@ class APC implements \Rhymix\Framework\Drivers\CacheInterface */ public function decr($key, $amount) { - $result = apc_dec($key, $amount); + $result = apcu_dec($key, $amount); if ($result === false) { - apc_store($key, 0 - $amount); + apcu_store($key, 0 - $amount); $result = 0 - $amount; } return $result; @@ -174,6 +174,6 @@ class APC implements \Rhymix\Framework\Drivers\CacheInterface */ public function clear() { - return apc_clear_cache('user'); + return apcu_clear_cache(); } } diff --git a/common/framework/drivers/mail/mailfunction.php b/common/framework/drivers/mail/mailfunction.php index cdf835fd1..f803abc5b 100644 --- a/common/framework/drivers/mail/mailfunction.php +++ b/common/framework/drivers/mail/mailfunction.php @@ -12,7 +12,7 @@ class MailFunction extends Base implements \Rhymix\Framework\Drivers\MailInterfa */ protected function __construct() { - $this->mailer = \Swift_Mailer::newInstance(\Swift_MailTransport::newInstance()); + $this->mailer = new \Swift_Mailer(new \Swift_MailTransport); } /** diff --git a/common/framework/drivers/mail/ses.php b/common/framework/drivers/mail/ses.php index 21dddc0ba..947aa3f1a 100644 --- a/common/framework/drivers/mail/ses.php +++ b/common/framework/drivers/mail/ses.php @@ -17,10 +17,10 @@ class SES extends Base implements \Rhymix\Framework\Drivers\MailInterface */ protected function __construct(array $config) { - $transport = \Swift_AWSTransport::newInstance($config['api_key'] ?: $config['api_user'], $config['api_secret'] ?: $config['api_pass']); + $transport = new \Swift_AWSTransport($config['api_key'] ?: $config['api_user'], $config['api_secret'] ?: $config['api_pass']); $transport->setDebug(array($this, 'debugCallback')); $transport->setEndpoint('https://email.' . strtolower($config['api_type']) . '.amazonaws.com/'); - $this->mailer = \Swift_Mailer::newInstance($transport); + $this->mailer = new \Swift_Mailer($transport); } /** diff --git a/common/framework/drivers/mail/smtp.php b/common/framework/drivers/mail/smtp.php index 49de5ab35..926ab2ecc 100644 --- a/common/framework/drivers/mail/smtp.php +++ b/common/framework/drivers/mail/smtp.php @@ -12,7 +12,7 @@ class SMTP extends Base implements \Rhymix\Framework\Drivers\MailInterface */ protected function __construct(array $config) { - $transport = \Swift_SmtpTransport::newInstance($config['smtp_host'], $config['smtp_port'], $config['smtp_security']); + $transport = new \Swift_SmtpTransport($config['smtp_host'], $config['smtp_port'], $config['smtp_security']); $transport->setUsername($config['smtp_user']); $transport->setPassword($config['smtp_pass']); $local_domain = $transport->getLocalDomain(); @@ -20,7 +20,7 @@ class SMTP extends Base implements \Rhymix\Framework\Drivers\MailInterface { $transport->setLocalDomain($matches[1]); } - $this->mailer = \Swift_Mailer::newInstance($transport); + $this->mailer = new \Swift_Mailer($transport); } /** diff --git a/common/framework/exceptions/featuredisabled.php b/common/framework/exceptions/featuredisabled.php new file mode 100644 index 000000000..2c22f992b --- /dev/null +++ b/common/framework/exceptions/featuredisabled.php @@ -0,0 +1,18 @@ + 0) + { + if (preg_match($regexp, $content)) + { + return true; + } + fseek($fp, min($to, $position += $block_size)); + } + return false; + } + + /** + * Attempt to detect the MIME type of a file. + * + * @param string $file Path of file to check + * @param bool $trim_subtype Whether to remove the subtype from the return value + * @return string|false + */ + protected static function _getMimetype($file, $trim_subtype = false) + { + if (!class_exists('finfo')) + { + return false; + } + if (!self::$_finfo) + { + self::$_finfo = new \finfo(FILEINFO_MIME_TYPE); + } + $mime_type = self::$_finfo->file($file); + if ($trim_subtype) + { + $mime_type = strstr($mime_type, '/', true); + } + return $mime_type; + } +} diff --git a/common/framework/filters/htmlfilter.php b/common/framework/filters/htmlfilter.php index 7ee1fa77e..c880a2e6a 100644 --- a/common/framework/filters/htmlfilter.php +++ b/common/framework/filters/htmlfilter.php @@ -149,6 +149,7 @@ class HTMLFilter $config->set('Core.Encoding', 'UTF-8'); $config->set('HTML.Doctype', 'XHTML 1.0 Transitional'); $config->set('HTML.FlashAllowFullScreen', true); + $config->set('HTML.Nofollow', config('security.nofollow') ? true : false); $config->set('HTML.MaxImgLength', null); $config->set('CSS.MaxImgLength', null); $config->set('CSS.Proprietary', true); diff --git a/common/framework/formatter.php b/common/framework/formatter.php index dc3cf3313..eaf157d77 100644 --- a/common/framework/formatter.php +++ b/common/framework/formatter.php @@ -129,7 +129,6 @@ class Formatter { $converter = new \League\HTMLToMarkdown\HtmlConverter(); $converter->getConfig()->setOption('bold_style', '**'); - $converter->getConfig()->setOption('italic_style', '_'); $converter->getConfig()->setOption('strip_tags', true); return trim($converter->convert($html)) . "\n"; } diff --git a/common/framework/korea.php b/common/framework/korea.php index 5996decb5..20f234150 100644 --- a/common/framework/korea.php +++ b/common/framework/korea.php @@ -47,7 +47,14 @@ class Korea default: if (substr($num, 0, 4) === '0303' || substr($num, 0, 3) === '050') { - return substr($num, 0, 4) . '-' . substr($num, 4, 3) . '-' . substr($num, 7); + if (strlen($num) === 12) + { + return substr($num, 0, 4) . '-' . substr($num, 4, 4) . '-' . substr($num, 8); + } + else + { + return substr($num, 0, 4) . '-' . substr($num, 4, 3) . '-' . substr($num, 7); + } } else { @@ -77,6 +84,10 @@ class Korea { return true; } + if (preg_match('/^0(?:303|505)[2-9][0-9]{6,7}$/', $num)) + { + return true; + } return false; } diff --git a/common/framework/mail.php b/common/framework/mail.php index fb39a4aeb..962bc8900 100644 --- a/common/framework/mail.php +++ b/common/framework/mail.php @@ -112,7 +112,7 @@ class Mail */ public function __construct() { - $this->message = \Swift_Message::newInstance(); + $this->message = new \Swift_Message; $this->driver = self::getDefaultDriver(); } diff --git a/common/framework/parsers/configparser.php b/common/framework/parsers/configparser.php index a07bc6b1c..df4396246 100644 --- a/common/framework/parsers/configparser.php +++ b/common/framework/parsers/configparser.php @@ -247,6 +247,7 @@ class ConfigParser } // Convert miscellaneous configuration. + $config['file']['folder_structure'] = 1; $config['file']['umask'] = Storage::recommendUmask(); $config['mobile']['enabled'] = $db_info->use_mobile_view === 'N' ? false : true; $config['use_prepared_statements'] = $db_info->use_prepared_statements === 'Y' ? true : false; diff --git a/common/framework/security.php b/common/framework/security.php index b674b7615..29de721d4 100644 --- a/common/framework/security.php +++ b/common/framework/security.php @@ -64,7 +64,14 @@ class Security } // Otherwise, use the CryptoCompat class. - return base64_encode(\CryptoCompat::encrypt($plaintext, $key)); + if (function_exists('mcrypt_encrypt')) + { + return base64_encode(\CryptoCompat::encrypt($plaintext, $key)); + } + else + { + throw new Exception('msg_crypto_not_available'); + } } /** @@ -102,7 +109,14 @@ class Security } // Otherwise, use the CryptoCompat class. - return \CryptoCompat::decrypt($ciphertext, $key); + if (function_exists('mcrypt_decrypt')) + { + return \CryptoCompat::decrypt($ciphertext, $key); + } + else + { + throw new Exception('msg_crypto_not_available'); + } } /** @@ -292,6 +306,11 @@ class Security */ public static function compareStrings($a, $b) { + if(function_exists('hash_equals')) + { + return hash_equals($a, $b); + } + $diff = strlen($a) ^ strlen($b); $maxlen = min(strlen($a), strlen($b)); for($i = 0; $i < $maxlen; $i++) @@ -326,13 +345,14 @@ class Security } else { - if (Session::getMemberSrl()) + $is_logged = Session::getMemberSrl(); + if ($is_logged) { trigger_error('CSRF token missing in POST request: ' . (\Context::get('act') ?: '(no act)'), \E_USER_WARNING); } $referer = strval($referer ?: $_SERVER['HTTP_REFERER']); - if ($referer !== '') + if ($referer !== '' && (!config('security.check_csrf_token') || !$is_logged)) { return URL::isInternalURL($referer); } @@ -344,16 +364,17 @@ class Security } /** - * Check if the current request seems to be an XEE attack. + * Check if the current request seems to be an XXE (XML external entity) attack. * * This method returns true if the request seems to be innocent, - * and false if it seems to be an XEE attack. - * This is the opposite of XE's Security::detectXEE() method. + * and false if it seems to be an XXE attack. + * This is the opposite of XE's Security::detectingXEE() method. + * The name has also been changed to the more accurate acronym XXE. * * @param string $xml (optional) * @return bool */ - public static function checkXEE($xml = null) + public static function checkXXE($xml = null) { // Stop if there is no XML content. if (!$xml) diff --git a/common/functions.php b/common/functions.php index 078c280e5..34ea24d23 100644 --- a/common/functions.php +++ b/common/functions.php @@ -381,6 +381,35 @@ function base64_decode_urlsafe($str) return @base64_decode(str_pad(strtr($str, '-_', '+/'), ceil(strlen($str) / 4) * 4, '=', STR_PAD_RIGHT)); } +/** + * This function shortens a number using common suffixes. + * + * @param int $number The number to shorten + * @param int $significant_digits The number of significant digits to retain + * @return string + */ +function number_shorten($number, $significant_digits = 2) +{ + $length = strlen(abs(intval($number))); + switch ($length) + { + case 0: case 1: case 2: case 3: return strval(intval($number)); + case 4: return number_format($number / 1000, max(0, $significant_digits - 1)) . 'K'; + case 5: return number_format($number / 1000, max(0, $significant_digits - 2)) . 'K'; + case 6: return number_format($number / 1000, max(0, $significant_digits - 3)) . 'K'; + case 7: return number_format($number / 1000000, max(0, $significant_digits - 1)) . 'M'; + case 8: return number_format($number / 1000000, max(0, $significant_digits - 2)) . 'M'; + case 9: return number_format($number / 1000000, max(0, $significant_digits - 3)) . 'M'; + case 10: return number_format($number / 1000000000, max(0, $significant_digits - 1)) . 'G'; + case 11: return number_format($number / 1000000000, max(0, $significant_digits - 2)) . 'G'; + case 12: return number_format($number / 1000000000, max(0, $significant_digits - 3)) . 'G'; + case 13: return number_format($number / 1000000000000, max(0, $significant_digits - 1)) . 'T'; + case 14: return number_format($number / 1000000000000, max(0, $significant_digits - 2)) . 'T'; + case 15: return number_format($number / 1000000000000, max(0, $significant_digits - 3)) . 'T'; + default: return floor($number / 1000000000000) . 'T'; + } +} + /** * Convert a server-side path to a URL. * diff --git a/common/js/common.js b/common/js/common.js index 29d75687d..e435d1f4e 100644 --- a/common/js/common.js +++ b/common/js/common.js @@ -71,7 +71,7 @@ if (token) { return $(this).each(function() { if ($(this).data("csrf-token-checked") === "Y") return; - if (!isSameOrigin(location.href, $(this).attr("action"))) { + if ($(this).attr("action") && !isSameOrigin(location.href, $(this).attr("action"))) { return $(this).data("csrf-token-checked", "Y"); } $("").attr({ type: "hidden", name: "_rx_csrf_token", value: token }).appendTo($(this)); @@ -92,6 +92,7 @@ window.XE = { loaded_popup_menus : [], addedDocument : [], + cookie : window.Cookies, URI : window.URI, URITemplate : window.URITemplate, SecondLevelDomains : window.SecondLevelDomains, @@ -224,16 +225,20 @@ window.XE.baseurl = window.XE.baseurl.hostname() + window.XE.baseurl.directory(); } - var target_url = window.XE.URI(url).normalizePort().normalizeHostname().normalizePathname(); - if (target_url.is("urn")) { + try { + var target_url = window.XE.URI(url).normalizePort().normalizeHostname().normalizePathname(); + if (target_url.is("urn")) { + return false; + } + if (!target_url.hostname()) { + target_url = target_url.absoluteTo(window.request_uri); + } + target_url = target_url.hostname() + target_url.directory(); + return target_url.indexOf(window.XE.baseurl) === 0; + } + catch(err) { return false; } - if (!target_url.hostname()) { - target_url = target_url.absoluteTo(window.request_uri); - } - target_url = target_url.hostname() + target_url.directory(); - - return target_url.indexOf(window.XE.baseurl) === 0; } }; @@ -280,6 +285,10 @@ jQuery(function($) { if (!rel.match(/\bnoopener\b/)) { $this.attr('rel', $.trim(rel + ' noopener')); } + var isChrome = navigator.userAgent.match(/Chrome\/([0-9]+)/); + if (isChrome && parseInt(isChrome[1], 10) >= 72) { + return; + } event.preventDefault(); blankshield.open(href); } @@ -621,22 +630,21 @@ function setFixedPopupSize() { offset = $pc.css({overflow:'scroll'}).offset(); w = $pc.width(10).height(10000).get(0).scrollWidth + offset.left*2; - h = $pc.height(10).width(10000).get(0).scrollHeight + offset.top*2; if(w < 800) w = 800 + offset.left*2; + // Window 의 너비나 높이는 스크린의 너비나 높이보다 클 수 없다. 스크린의 너비나 높이와 내용의 너비나 높이를 비교해서 최소값을 이용한다. + w = Math.min(w, window.screen.availWidth); + + h = $pc.width(w - offset.left*2).height(10).get(0).scrollHeight + offset.top*2; dw = $win.width(); dh = $win.height(); - // Window 의 너비나 높이는 스크린의 너비나 높이보다 클 수 없다. 스크린의 너비나 높이와 내용의 너비나 높이를 비교해서 최소값을 이용한다. - w = Math.min(w, window.screen.availWidth); h = Math.min(h, window.screen.availHeight - 100); window.resizeBy(w - dw, h - dh); - $pc.width(w - offset.left*2).css({overflow:'',height:''}); - if(h === window.screen.availHeight - 100) { - $pc.width(w - offset.left*2-scbw).css({overflow:'',height:''}); - } + $pc.width('100%').css({overflow:'',height:'','box-sizing':'border-box'}); + } /** @@ -674,9 +682,7 @@ function doChangeLangType(obj) { location.href = location.href.setQuery('l', ''); } function setLangType(lang_type) { - var expire = new Date(); - expire.setTime(expire.getTime()+ (7000 * 24 * 3600000)); - setCookie('lang_type', lang_type, expire, '/'); + XE.cookie.set("lang_type", lang_type, { path: "/", expires: 3650 }); } /* 미리보기 */ @@ -1052,18 +1058,16 @@ function getOuterHTML(obj) { return jQuery(obj).html().trim(); } -function setCookie(name, value, expire, path) { - var s_cookie = name + "=" + escape(value) + - ((!expire) ? "" : ("; expires=" + expire.toGMTString())) + - "; path=" + ((!path) ? "/" : path) + - ((cookies_ssl) ? ";secure" : ""); - - document.cookie = s_cookie; +function setCookie(name, value, expires, path) { + XE.cookie.set(name, value, { + expires: expires ? expires : 0, + path: path ? path : "/", + secure: cookies_ssl ? true : false + }); } function getCookie(name) { - var match = document.cookie.match(new RegExp(name+'=(.*?)(?:;|$)')); - if(match) return unescape(match[1]); + return XE.cookie.get(name); } function is_def(v) { diff --git a/common/js/plugins/cookie/js.cookie.js b/common/js/plugins/cookie/js.cookie.js new file mode 100644 index 000000000..9a0945ed8 --- /dev/null +++ b/common/js/plugins/cookie/js.cookie.js @@ -0,0 +1,165 @@ +/*! + * JavaScript Cookie v2.2.0 + * https://github.com/js-cookie/js-cookie + * + * Copyright 2006, 2015 Klaus Hartl & Fagner Brack + * Released under the MIT license + */ +;(function (factory) { + var registeredInModuleLoader = false; + if (typeof define === 'function' && define.amd) { + define(factory); + registeredInModuleLoader = true; + } + if (typeof exports === 'object') { + module.exports = factory(); + registeredInModuleLoader = true; + } + if (!registeredInModuleLoader) { + var OldCookies = window.Cookies; + var api = window.Cookies = factory(); + api.noConflict = function () { + window.Cookies = OldCookies; + return api; + }; + } +}(function () { + function extend () { + var i = 0; + var result = {}; + for (; i < arguments.length; i++) { + var attributes = arguments[ i ]; + for (var key in attributes) { + result[key] = attributes[key]; + } + } + return result; + } + + function init (converter) { + function api (key, value, attributes) { + var result; + if (typeof document === 'undefined') { + return; + } + + // Write + + if (arguments.length > 1) { + attributes = extend({ + path: '/' + }, api.defaults, attributes); + + if (typeof attributes.expires === 'number') { + var expires = new Date(); + expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); + attributes.expires = expires; + } + + // We're using "expires" because "max-age" is not supported by IE + attributes.expires = attributes.expires ? attributes.expires.toUTCString() : ''; + + try { + result = JSON.stringify(value); + if (/^[\{\[]/.test(result)) { + value = result; + } + } catch (e) {} + + if (!converter.write) { + value = encodeURIComponent(String(value)) + .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); + } else { + value = converter.write(value, key); + } + + key = encodeURIComponent(String(key)); + key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); + key = key.replace(/[\(\)]/g, escape); + + var stringifiedAttributes = ''; + + for (var attributeName in attributes) { + if (!attributes[attributeName]) { + continue; + } + stringifiedAttributes += '; ' + attributeName; + if (attributes[attributeName] === true) { + continue; + } + stringifiedAttributes += '=' + attributes[attributeName]; + } + return (document.cookie = key + '=' + value + stringifiedAttributes); + } + + // Read + + if (!key) { + result = {}; + } + + // To prevent the for loop in the first place assign an empty array + // in case there are no cookies at all. Also prevents odd result when + // calling "get()" + var cookies = document.cookie ? document.cookie.split('; ') : []; + var rdecode = /(%[0-9A-Z]{2})+/g; + var i = 0; + + for (; i < cookies.length; i++) { + var parts = cookies[i].split('='); + var cookie = parts.slice(1).join('='); + + if (!this.json && cookie.charAt(0) === '"') { + cookie = cookie.slice(1, -1); + } + + try { + var name = parts[0].replace(rdecode, decodeURIComponent); + cookie = converter.read ? + converter.read(cookie, name) : converter(cookie, name) || + cookie.replace(rdecode, decodeURIComponent); + + if (this.json) { + try { + cookie = JSON.parse(cookie); + } catch (e) {} + } + + if (key === name) { + result = cookie; + break; + } + + if (!key) { + result[name] = cookie; + } + } catch (e) {} + } + + return result; + } + + api.set = api; + api.get = function (key) { + return api.call(api, key); + }; + api.getJSON = function () { + return api.apply({ + json: true + }, [].slice.call(arguments)); + }; + api.defaults = {}; + + api.remove = function (key, attributes) { + api(key, '', extend(attributes, { + expires: -1 + })); + }; + + api.withConverter = init; + + return api; + } + + return init(function () {}); +})); diff --git a/common/js/plugins/cookie/js.cookie.min.js b/common/js/plugins/cookie/js.cookie.min.js new file mode 100644 index 000000000..795bf361b --- /dev/null +++ b/common/js/plugins/cookie/js.cookie.min.js @@ -0,0 +1 @@ +!function(e){var n=!1;if("function"==typeof define&&define.amd&&(define(e),n=!0),"object"==typeof exports&&(module.exports=e(),n=!0),!n){var o=window.Cookies,t=window.Cookies=e();t.noConflict=function(){return window.Cookies=o,t}}}(function(){function e(){for(var e=0,n={};e1){if("number"==typeof(i=e({path:"/"},t.defaults,i)).expires){var a=new Date;a.setMilliseconds(a.getMilliseconds()+864e5*i.expires),i.expires=a}i.expires=i.expires?i.expires.toUTCString():"";try{/^[\{\[]/.test(c=JSON.stringify(r))&&(r=c)}catch(e){}r=o.write?o.write(r,n):encodeURIComponent(String(r)).replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,decodeURIComponent),n=(n=(n=encodeURIComponent(String(n))).replace(/%(23|24|26|2B|5E|60|7C)/g,decodeURIComponent)).replace(/[\(\)]/g,escape);var s="";for(var f in i)i[f]&&(s+="; "+f,!0!==i[f]&&(s+="="+i[f]));return document.cookie=n+"="+r+s}n||(c={});for(var p=document.cookie?document.cookie.split("; "):[],d=/(%[0-9A-Z]{2})+/g,u=0;u').prop('href', options.postMessage)[0], target = loc.protocol + '//' + loc.host, xhrUpload = options.xhr().upload; + // IE always includes the port for the host property of a link + // element, but not in the location.host or origin property for the + // default http port 80 and https port 443, so we strip it: + if (/^(http:\/\/.+:80)|(https:\/\/.+:443)$/.test(target)) { + target = target.replace(/:(80|443)$/, ''); + } return { send: function (_, completeCallback) { counter += 1; diff --git a/common/js/plugins/jquery.fileupload/js/cors/jquery.xdr-transport.js b/common/js/plugins/jquery.fileupload/js/cors/jquery.xdr-transport.js index 2dfd0faf8..a4e2699c6 100644 --- a/common/js/plugins/jquery.fileupload/js/cors/jquery.xdr-transport.js +++ b/common/js/plugins/jquery.fileupload/js/cors/jquery.xdr-transport.js @@ -1,12 +1,12 @@ /* - * jQuery XDomainRequest Transport Plugin 1.1.4 + * jQuery XDomainRequest Transport Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2011, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT + * https://opensource.org/licenses/MIT * * Based on Julian Aubourg's ajaxHooks xdr.js: * https://github.com/jaubourg/ajaxHooks/ @@ -14,7 +14,7 @@ /* global define, require, window, XDomainRequest */ -(function (factory) { +;(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: diff --git a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-angular.js b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-angular.js index e4ef3926b..1c2055276 100644 --- a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-angular.js +++ b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-angular.js @@ -1,18 +1,18 @@ /* - * jQuery File Upload AngularJS Plugin 2.2.0 + * jQuery File Upload AngularJS Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2013, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT + * https://opensource.org/licenses/MIT */ /* jshint nomen:false */ -/* global define, angular */ +/* global define, angular, require */ -(function (factory) { +;(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: @@ -24,6 +24,16 @@ './jquery.fileupload-video', './jquery.fileupload-validate' ], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory( + require('jquery'), + require('angular'), + require('./jquery.fileupload-image'), + require('./jquery.fileupload-audio'), + require('./jquery.fileupload-video'), + require('./jquery.fileupload-validate') + ); } else { factory(); } @@ -91,7 +101,7 @@ angular.forEach(data.files, function (file) { filesCopy.push(file); }); - scope.$apply(function () { + scope.$parent.$applyAsync(function () { addFileMethods(scope, data); var method = scope.option('prependFiles') ? 'unshift' : 'push'; @@ -100,7 +110,7 @@ data.process(function () { return scope.process(data); }).always(function () { - scope.$apply(function () { + scope.$parent.$applyAsync(function () { addFileMethods(scope, data); scope.replace(filesCopy, data.files); }); @@ -112,12 +122,6 @@ } }); }, - progress: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - data.scope.$apply(); - }, done: function (e, data) { if (e.isDefaultPrevented()) { return false; @@ -197,8 +201,8 @@ // The FileUploadController initializes the fileupload widget and // provides scope methods to control the File Upload functionality: .controller('FileUploadController', [ - '$scope', '$element', '$attrs', '$window', 'fileUpload', - function ($scope, $element, $attrs, $window, fileUpload) { + '$scope', '$element', '$attrs', '$window', 'fileUpload','$q', + function ($scope, $element, $attrs, $window, fileUpload, $q) { var uploadMethods = { progress: function () { return $element.fileupload('progress'); @@ -260,19 +264,21 @@ $scope.applyOnQueue = function (method) { var list = this.queue.slice(0), i, - file; + file, + promises = []; for (i = 0; i < list.length; i += 1) { file = list[i]; if (file[method]) { - file[method](); + promises.push(file[method]()); } } + return $q.all(promises); }; $scope.submit = function () { - this.applyOnQueue('$submit'); + return this.applyOnQueue('$submit'); }; $scope.cancel = function () { - this.applyOnQueue('$cancel'); + return this.applyOnQueue('$cancel'); }; // Add upload methods to the scope: angular.extend($scope, uploadMethods); @@ -320,9 +326,11 @@ 'fileuploadprocessalways', 'fileuploadprocessstop' ].join(' '), function (e, data) { - if ($scope.$emit(e.type, data).defaultPrevented) { - e.preventDefault(); - } + $scope.$parent.$applyAsync(function () { + if ($scope.$emit(e.type, data).defaultPrevented) { + e.preventDefault(); + } + }); }).on('remove', function () { // Remove upload methods from the scope, // when the widget is removed: diff --git a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-audio.js b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-audio.js index 1e3d05de4..a25377619 100644 --- a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-audio.js +++ b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-audio.js @@ -1,18 +1,18 @@ /* - * jQuery File Upload Audio Preview Plugin 1.0.4 + * jQuery File Upload Audio Preview Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2013, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT + * https://opensource.org/licenses/MIT */ /* jshint nomen:false */ /* global define, require, window, document */ -(function (factory) { +;(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: @@ -25,7 +25,8 @@ // Node/CommonJS: factory( require('jquery'), - require('load-image') + require('blueimp-load-image/js/load-image'), + require('./jquery.fileupload-process') ); } else { // Browser globals: diff --git a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-image.js b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-image.js index 266b088de..65fc6d7b8 100644 --- a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-image.js +++ b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-image.js @@ -1,18 +1,18 @@ /* - * jQuery File Upload Image Preview & Resize Plugin 1.7.3 + * jQuery File Upload Image Preview & Resize Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2013, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT + * https://opensource.org/licenses/MIT */ /* jshint nomen:false */ /* global define, require, window, Blob */ -(function (factory) { +;(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: @@ -20,8 +20,8 @@ 'jquery', 'load-image', 'load-image-meta', + 'load-image-scale', 'load-image-exif', - 'load-image-ios', 'canvas-to-blob', './jquery.fileupload-process' ], factory); @@ -29,7 +29,12 @@ // Node/CommonJS: factory( require('jquery'), - require('load-image') + require('blueimp-load-image/js/load-image'), + require('blueimp-load-image/js/load-image-meta'), + require('blueimp-load-image/js/load-image-scale'), + require('blueimp-load-image/js/load-image-exif'), + require('blueimp-canvas-to-blob'), + require('./jquery.fileupload-process') ); } else { // Browser globals: diff --git a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-jquery-ui.js b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-jquery-ui.js index e6cf5c722..7b136b379 100644 --- a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-jquery-ui.js +++ b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-jquery-ui.js @@ -1,25 +1,31 @@ /* - * jQuery File Upload jQuery UI Plugin 8.7.2 + * jQuery File Upload jQuery UI Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2013, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT + * https://opensource.org/licenses/MIT */ /* jshint nomen:false */ /* global define, require, window */ -(function (factory) { +;(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: - define(['jquery', './jquery.fileupload-ui'], factory); + define([ + 'jquery', + './jquery.fileupload-ui' + ], factory); } else if (typeof exports === 'object') { // Node/CommonJS: - factory(require('jquery')); + factory( + require('jquery'), + require('./jquery.fileupload-ui') + ); } else { // Browser globals: factory(window.jQuery); diff --git a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-process.js b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-process.js index da78fa033..638f0d26b 100644 --- a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-process.js +++ b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-process.js @@ -1,18 +1,18 @@ /* - * jQuery File Upload Processing Plugin 1.3.1 + * jQuery File Upload Processing Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2012, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT + * https://opensource.org/licenses/MIT */ /* jshint nomen:false */ /* global define, require, window */ -(function (factory) { +;(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: @@ -22,7 +22,10 @@ ], factory); } else if (typeof exports === 'object') { // Node/CommonJS: - factory(require('jquery')); + factory( + require('jquery'), + require('./jquery.fileupload') + ); } else { // Browser globals: factory( @@ -84,7 +87,7 @@ settings ); }; - chain = chain.pipe(func, settings.always && func); + chain = chain.then(func, settings.always && func); }); chain .done(function () { @@ -151,7 +154,7 @@ }; opts.index = index; that._processing += 1; - that._processingQueue = that._processingQueue.pipe(func, func) + that._processingQueue = that._processingQueue.then(func, func) .always(function () { that._processing -= 1; if (that._processing === 0) { diff --git a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-ui.js b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-ui.js index 1a8e36cc1..5058084b4 100644 --- a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-ui.js +++ b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-ui.js @@ -1,24 +1,24 @@ /* - * jQuery File Upload User Interface Plugin 9.6.1 + * jQuery File Upload User Interface Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2010, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT + * https://opensource.org/licenses/MIT */ /* jshint nomen:false */ /* global define, require, window */ -(function (factory) { +;(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: define([ 'jquery', - 'tmpl', + 'blueimp-tmpl', './jquery.fileupload-image', './jquery.fileupload-audio', './jquery.fileupload-video', @@ -28,7 +28,11 @@ // Node/CommonJS: factory( require('jquery'), - require('tmpl') + require('blueimp-tmpl'), + require('./jquery.fileupload-image'), + require('./jquery.fileupload-audio'), + require('./jquery.fileupload-video'), + require('./jquery.fileupload-validate') ); } else { // Browser globals: @@ -68,10 +72,10 @@ // The expected data type of the upload response, sets the dataType // option of the $.ajax upload requests: dataType: 'json', - + // Error and info messages: messages: { - unknownError: 'Unknown error' + unknownError: 'Unknown error' }, // Function returning the current number of files, diff --git a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-validate.js b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-validate.js index cb0d9f8b6..eebeb3733 100644 --- a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-validate.js +++ b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-validate.js @@ -1,17 +1,17 @@ /* - * jQuery File Upload Validation Plugin 1.1.3 + * jQuery File Upload Validation Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2013, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT + * https://opensource.org/licenses/MIT */ /* global define, require, window */ -(function (factory) { +;(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: @@ -21,7 +21,10 @@ ], factory); } else if (typeof exports === 'object') { // Node/CommonJS: - factory(require('jquery')); + factory( + require('jquery'), + require('./jquery.fileupload-process') + ); } else { // Browser globals: factory( @@ -36,7 +39,7 @@ { action: 'validate', // Always trigger this action, - // even if the previous action was rejected: + // even if the previous action was rejected: always: true, // Options taken from the global options map: acceptFileTypes: '@', diff --git a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-video.js b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-video.js index db5f24800..aedcec2ba 100644 --- a/common/js/plugins/jquery.fileupload/js/jquery.fileupload-video.js +++ b/common/js/plugins/jquery.fileupload/js/jquery.fileupload-video.js @@ -1,18 +1,18 @@ /* - * jQuery File Upload Video Preview Plugin 1.0.4 + * jQuery File Upload Video Preview Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2013, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT + * https://opensource.org/licenses/MIT */ /* jshint nomen:false */ /* global define, require, window, document */ -(function (factory) { +;(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: @@ -25,7 +25,8 @@ // Node/CommonJS: factory( require('jquery'), - require('load-image') + require('blueimp-load-image/js/load-image'), + require('./jquery.fileupload-process') ); } else { // Browser globals: diff --git a/common/js/plugins/jquery.fileupload/js/jquery.fileupload.js b/common/js/plugins/jquery.fileupload/js/jquery.fileupload.js index ab0748fc0..daf1459d4 100644 --- a/common/js/plugins/jquery.fileupload/js/jquery.fileupload.js +++ b/common/js/plugins/jquery.fileupload/js/jquery.fileupload.js @@ -1,24 +1,24 @@ /* - * jQuery File Upload Plugin 5.42.3 + * jQuery File Upload Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2010, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT + * https://opensource.org/licenses/MIT */ /* jshint nomen:false */ /* global define, require, window, document, location, Blob, FormData */ -(function (factory) { +;(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: define([ 'jquery', - 'jquery.ui.widget' + 'jquery-ui/ui/widget' ], factory); } else if (typeof exports === 'object') { // Node/CommonJS: @@ -43,7 +43,7 @@ '|(Kindle/(1\\.0|2\\.[05]|3\\.0))' ).test(window.navigator.userAgent) || // Feature detection for all other devices: - $('').prop('disabled')); + $('').prop('disabled')); // The FileReader API is not actually used, but works as feature detection, // as some Safari versions (5?) support XHR file uploads via the FormData API, @@ -453,7 +453,7 @@ } if (!multipart || options.blob || !this._isInstanceOf('File', file)) { options.headers['Content-Disposition'] = 'attachment; filename="' + - encodeURI(file.name) + '"'; + encodeURI(file.uploadName || file.name) + '"'; } if (!multipart) { options.contentType = file.type || 'application/octet-stream'; @@ -489,7 +489,11 @@ }); } if (options.blob) { - formData.append(paramName, options.blob, file.name); + formData.append( + paramName, + options.blob, + file.uploadName || file.name + ); } else { $.each(options.files, function (index, file) { // This check allows the tests to run with @@ -652,7 +656,7 @@ data.process = function (resolveFunc, rejectFunc) { if (resolveFunc || rejectFunc) { data._processQueue = this._processQueue = - (this._processQueue || getPromise([this])).pipe( + (this._processQueue || getPromise([this])).then( function () { if (data.errorThrown) { return $.Deferred() @@ -660,7 +664,7 @@ } return getPromise(arguments); } - ).pipe(resolveFunc, rejectFunc); + ).then(resolveFunc, rejectFunc); } return this._processQueue || getPromise([this]); }; @@ -730,7 +734,7 @@ promise = dfd.promise(), jqXHR, upload; - if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) || + if (!(this._isXHRUpload(options) && slice && (ub || ($.type(mcs) === 'function' ? mcs(options) : mcs) < fs)) || options.data) { return false; } @@ -753,7 +757,7 @@ o.blob = slice.call( file, ub, - ub + mcs, + ub + ($.type(mcs) === 'function' ? mcs(o) : mcs), file.type ); // Store the current chunk size, as the blob itself @@ -945,9 +949,9 @@ if (this.options.limitConcurrentUploads > 1) { slot = $.Deferred(); this._slots.push(slot); - pipe = slot.pipe(send); + pipe = slot.then(send); } else { - this._sequence = this._sequence.pipe(send, send); + this._sequence = this._sequence.then(send, send); pipe = this._sequence; } // Return the piped Promise object, enhanced with an abort method, @@ -1046,13 +1050,19 @@ _replaceFileInput: function (data) { var input = data.fileInput, - inputClone = input.clone(true); + inputClone = input.clone(true), + restoreFocus = input.is(document.activeElement); // Add a reference for the new cloned file input to the data argument: data.fileInputClone = inputClone; $('
    ').append(inputClone)[0].reset(); // Detaching allows to insert the fileInput on another form // without loosing the file input value: input.after(inputClone).detach(); + // If the fileInput had focus before it was detached, + // restore focus to the inputClone. + if (restoreFocus) { + inputClone.focus(); + } // Avoid memory leaks with the detached file input: $.cleanData(input.unbind('remove')); // Replace the original file input element in the fileInput @@ -1074,6 +1084,8 @@ _handleFileTreeEntry: function (entry, path) { var that = this, dfd = $.Deferred(), + entries = [], + dirReader, errorHandler = function (e) { if (e && !e.entry) { e.entry = entry; @@ -1101,8 +1113,7 @@ readEntries(); } }, errorHandler); - }, - dirReader, entries = []; + }; path = path || ''; if (entry.isFile) { if (entry._file) { @@ -1119,7 +1130,7 @@ dirReader = entry.createReader(); readEntries(); } else { - // Return an empy list for file system items + // Return an empty list for file system items // other than files or directories: dfd.resolve([]); } @@ -1133,7 +1144,7 @@ $.map(entries, function (entry) { return that._handleFileTreeEntry(entry, path); }) - ).pipe(function () { + ).then(function () { return Array.prototype.concat.apply( [], arguments @@ -1168,16 +1179,9 @@ _getSingleFileInputFiles: function (fileInput) { fileInput = $(fileInput); - var entries = fileInput.prop('webkitEntries') || - fileInput.prop('entries'), - files, - value; - if (entries && entries.length) { - return this._handleFileTreeEntries(entries); - } - files = $.makeArray(fileInput.prop('files')); + var files = $.makeArray(fileInput.prop('files')); if (!files.length) { - value = fileInput.prop('value'); + var value = fileInput.prop('value'); if (!value) { return $.Deferred().resolve([]).promise(); } @@ -1202,10 +1206,10 @@ return $.when.apply( $, $.map(fileInput, this._getSingleFileInputFiles) - ).pipe(function () { + ).then(function (files) { return Array.prototype.concat.apply( [], - arguments + files ); }); }, @@ -1217,7 +1221,7 @@ form: $(e.target.form) }; this._getFileInputFiles(data.fileInput).always(function (files) { - data.files = files; + data.files = $.makeArray(files); if (that.options.replaceFileInput) { that._replaceFileInput(data); } @@ -1305,6 +1309,10 @@ this._off(this.options.fileInput, 'change'); }, + _destroy: function () { + this._destroyEventHandlers(); + }, + _setOption: function (key, value) { var reinit = $.inArray(key, this._specialOptions) !== -1; if (reinit) { diff --git a/common/js/plugins/jquery.fileupload/js/jquery.iframe-transport.js b/common/js/plugins/jquery.fileupload/js/jquery.iframe-transport.js index b7581f23f..8d25c4641 100644 --- a/common/js/plugins/jquery.fileupload/js/jquery.iframe-transport.js +++ b/common/js/plugins/jquery.fileupload/js/jquery.iframe-transport.js @@ -1,17 +1,17 @@ /* - * jQuery Iframe Transport Plugin 1.8.3 + * jQuery Iframe Transport Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2011, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT + * https://opensource.org/licenses/MIT */ -/* global define, require, window, document */ +/* global define, require, window, document, JSON */ -(function (factory) { +;(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: @@ -27,7 +27,14 @@ 'use strict'; // Helper variable to create unique names for the transport iframes: - var counter = 0; + var counter = 0, + jsonAPI = $, + jsonParse = 'parseJSON'; + + if ('JSON' in window && 'parse' in JSON) { + jsonAPI = JSON; + jsonParse = 'parse'; + } // The iframe transport accepts four additional options: // options.fileInput: a jQuery collection of file input fields @@ -197,7 +204,7 @@ return iframe && $(iframe[0].body).text(); }, 'iframe json': function (iframe) { - return iframe && $.parseJSON($(iframe[0].body).text()); + return iframe && jsonAPI[jsonParse]($(iframe[0].body).text()); }, 'iframe html': function (iframe) { return iframe && $(iframe[0].body).html(); diff --git a/common/js/plugins/jquery.fileupload/js/main.js b/common/js/plugins/jquery.fileupload/js/main.js index 67bb8227f..696ab7569 100644 --- a/common/js/plugins/jquery.fileupload/js/main.js +++ b/common/js/plugins/jquery.fileupload/js/main.js @@ -52,6 +52,7 @@ var self = this; var $container = containerEl; var data = $container.data(); + var lastUploadTime = 0; $.extend(data, { files: {}, @@ -93,15 +94,16 @@ }, submit: function(e, item) { item.formData = defaultFormData; - item.formData.nonce = "T" + new Date().getTime() + "." + Math.random(); chunkStatus = true; }, chunksend: function(e, res) { + lastUploadTime = Date.now(); if (!chunkStatus) { return false; } }, chunkdone: function(e, res) { + lastUploadTime = Date.now(); if (res.result) { if (res.result.error != 0) { if (res.result.message) { @@ -117,16 +119,22 @@ } }, chunkfail: function(e, res) { + lastUploadTime = Date.now(); if (chunkStatus) { alert(window.xe.msg_file_upload_error + " (Type 3)" + "
    \n" + res.errorThrown + "
    \n" + res.textStatus); return chunkStatus = false; } }, done: function(e, res) { + lastUploadTime = Date.now(); data.settings.progressbarGraph.width('100%'); data.settings.progressPercent.text('100%'); - data.settings.progressbar.delay(1000).slideUp(); - data.settings.progressStatus.delay(1000).slideUp(); + setTimeout(function() { + if (lastUploadTime < Date.now() - 800) { + data.settings.progressbar.slideUp(); + data.settings.progressStatus.slideUp(); + } + }, 1000); var result = res.response().result; var temp_code = ''; if (!result) { @@ -159,22 +167,30 @@ } }, fail: function(e, res) { - data.settings.progressbar.delay(1000).slideUp(); - data.settings.progressStatus.delay(1000).slideUp(); + lastUploadTime = Date.now(); + setTimeout(function() { + if (lastUploadTime < Date.now() - 800) { + data.settings.progressbar.slideUp(); + data.settings.progressStatus.slideUp(); + } + }, 1000); if (chunkStatus) { alert(window.xe.msg_file_upload_error + " (Type 7)" + "
    \n" + res.errorThrown + "
    \n" + res.textStatus); return false; } }, stop: function() { + lastUploadTime = Date.now(); self.loadFilelist($container); }, start: function() { + lastUploadTime = Date.now(); data.settings.progressbarGraph.width(0); data.settings.progressStatus.show(); data.settings.progressbar.show(); }, progressall: function (e, res) { + lastUploadTime = Date.now(); var progress = Math.round(res.loaded / res.total * 999) / 10; data.settings.progressbarGraph.width(progress+'%'); data.settings.progressPercent.text(progress+'%'); @@ -203,6 +219,7 @@ // 본문 삽입 data.settings.actSelectedInsertContent.on('click', function() { self.insertToContent($container); + data.settings.fileList.finderSelect('unHighlightAll'); }); // 파일 삭제 diff --git a/common/js/plugins/jquery.fileupload/js/vendor/jquery.ui.widget.js b/common/js/plugins/jquery.fileupload/js/vendor/jquery.ui.widget.js index 5ac2ed5a5..914b8ffb8 100644 --- a/common/js/plugins/jquery.fileupload/js/vendor/jquery.ui.widget.js +++ b/common/js/plugins/jquery.fileupload/js/vendor/jquery.ui.widget.js @@ -1,562 +1,751 @@ -/*! jQuery UI - v1.11.1+CommonJS - 2014-09-17 -* http://jqueryui.com -* Includes: widget.js -* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ +/*! jQuery UI - v1.12.1+CommonJS - 2018-02-10 + * http://jqueryui.com + * Includes: widget.js + * Copyright jQuery Foundation and other contributors; Licensed MIT */ (function( factory ) { - if ( typeof define === "function" && define.amd ) { + if ( typeof define === "function" && define.amd ) { - // AMD. Register as an anonymous module. - define([ "jquery" ], factory ); + // AMD. Register as an anonymous module. + define([ "jquery" ], factory ); + } else if ( typeof exports === "object" ) { - } else if (typeof exports === "object") { - // Node/CommonJS: - factory(require("jquery")); + // Node/CommonJS + factory( require( "jquery" ) ); + } else { - } else { - - // Browser globals - factory( jQuery ); - } + // Browser globals + factory( jQuery ); + } }(function( $ ) { -/*! - * jQuery UI Widget 1.11.1 - * http://jqueryui.com - * - * Copyright 2014 jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/jQuery.widget/ - */ + + $.ui = $.ui || {}; + + var version = $.ui.version = "1.12.1"; -var widget_uuid = 0, - widget_slice = Array.prototype.slice; + /*! + * jQuery UI Widget 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ -$.cleanData = (function( orig ) { - return function( elems ) { - var events, elem, i; - for ( i = 0; (elem = elems[i]) != null; i++ ) { - try { + //>>label: Widget + //>>group: Core + //>>description: Provides a factory for creating stateful widgets with a common API. + //>>docs: http://api.jqueryui.com/jQuery.widget/ + //>>demos: http://jqueryui.com/widget/ - // Only trigger remove when necessary to save time - events = $._data( elem, "events" ); - if ( events && events.remove ) { - $( elem ).triggerHandler( "remove" ); - } - // http://bugs.jquery.com/ticket/8235 - } catch( e ) {} - } - orig( elems ); - }; -})( $.cleanData ); -$.widget = function( name, base, prototype ) { - var fullName, existingConstructor, constructor, basePrototype, - // proxiedPrototype allows the provided prototype to remain unmodified - // so that it can be used as a mixin for multiple widgets (#8876) - proxiedPrototype = {}, - namespace = name.split( "." )[ 0 ]; + var widgetUuid = 0; + var widgetSlice = Array.prototype.slice; - name = name.split( "." )[ 1 ]; - fullName = namespace + "-" + name; + $.cleanData = ( function( orig ) { + return function( elems ) { + var events, elem, i; + for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) { + try { - if ( !prototype ) { - prototype = base; - base = $.Widget; - } + // Only trigger remove when necessary to save time + events = $._data( elem, "events" ); + if ( events && events.remove ) { + $( elem ).triggerHandler( "remove" ); + } - // create selector for plugin - $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { - return !!$.data( elem, fullName ); - }; + // Http://bugs.jquery.com/ticket/8235 + } catch ( e ) {} + } + orig( elems ); + }; + } )( $.cleanData ); - $[ namespace ] = $[ namespace ] || {}; - existingConstructor = $[ namespace ][ name ]; - constructor = $[ namespace ][ name ] = function( options, element ) { - // allow instantiation without "new" keyword - if ( !this._createWidget ) { - return new constructor( options, element ); - } + $.widget = function( name, base, prototype ) { + var existingConstructor, constructor, basePrototype; - // allow instantiation without initializing for simple inheritance - // must use "new" keyword (the code above always passes args) - if ( arguments.length ) { - this._createWidget( options, element ); - } - }; - // extend with the existing constructor to carry over any static properties - $.extend( constructor, existingConstructor, { - version: prototype.version, - // copy the object used to create the prototype in case we need to - // redefine the widget later - _proto: $.extend( {}, prototype ), - // track widgets that inherit from this widget in case this widget is - // redefined after a widget inherits from it - _childConstructors: [] - }); + // ProxiedPrototype allows the provided prototype to remain unmodified + // so that it can be used as a mixin for multiple widgets (#8876) + var proxiedPrototype = {}; - basePrototype = new base(); - // we need to make the options hash a property directly on the new instance - // otherwise we'll modify the options hash on the prototype that we're - // inheriting from - basePrototype.options = $.widget.extend( {}, basePrototype.options ); - $.each( prototype, function( prop, value ) { - if ( !$.isFunction( value ) ) { - proxiedPrototype[ prop ] = value; - return; - } - proxiedPrototype[ prop ] = (function() { - var _super = function() { - return base.prototype[ prop ].apply( this, arguments ); - }, - _superApply = function( args ) { - return base.prototype[ prop ].apply( this, args ); - }; - return function() { - var __super = this._super, - __superApply = this._superApply, - returnValue; + var namespace = name.split( "." )[ 0 ]; + name = name.split( "." )[ 1 ]; + var fullName = namespace + "-" + name; - this._super = _super; - this._superApply = _superApply; + if ( !prototype ) { + prototype = base; + base = $.Widget; + } - returnValue = value.apply( this, arguments ); + if ( $.isArray( prototype ) ) { + prototype = $.extend.apply( null, [ {} ].concat( prototype ) ); + } - this._super = __super; - this._superApply = __superApply; + // Create selector for plugin + $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { + return !!$.data( elem, fullName ); + }; - return returnValue; - }; - })(); - }); - constructor.prototype = $.widget.extend( basePrototype, { - // TODO: remove support for widgetEventPrefix - // always use the name + a colon as the prefix, e.g., draggable:start - // don't prefix for widgets that aren't DOM-based - widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name - }, proxiedPrototype, { - constructor: constructor, - namespace: namespace, - widgetName: name, - widgetFullName: fullName - }); + $[ namespace ] = $[ namespace ] || {}; + existingConstructor = $[ namespace ][ name ]; + constructor = $[ namespace ][ name ] = function( options, element ) { - // If this widget is being redefined then we need to find all widgets that - // are inheriting from it and redefine all of them so that they inherit from - // the new version of this widget. We're essentially trying to replace one - // level in the prototype chain. - if ( existingConstructor ) { - $.each( existingConstructor._childConstructors, function( i, child ) { - var childPrototype = child.prototype; + // Allow instantiation without "new" keyword + if ( !this._createWidget ) { + return new constructor( options, element ); + } - // redefine the child widget using the same prototype that was - // originally used, but inherit from the new version of the base - $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); - }); - // remove the list of existing child constructors from the old constructor - // so the old child constructors can be garbage collected - delete existingConstructor._childConstructors; - } else { - base._childConstructors.push( constructor ); - } + // Allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) + if ( arguments.length ) { + this._createWidget( options, element ); + } + }; - $.widget.bridge( name, constructor ); + // Extend with the existing constructor to carry over any static properties + $.extend( constructor, existingConstructor, { + version: prototype.version, - return constructor; -}; + // Copy the object used to create the prototype in case we need to + // redefine the widget later + _proto: $.extend( {}, prototype ), -$.widget.extend = function( target ) { - var input = widget_slice.call( arguments, 1 ), - inputIndex = 0, - inputLength = input.length, - key, - value; - for ( ; inputIndex < inputLength; inputIndex++ ) { - for ( key in input[ inputIndex ] ) { - value = input[ inputIndex ][ key ]; - if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { - // Clone objects - if ( $.isPlainObject( value ) ) { - target[ key ] = $.isPlainObject( target[ key ] ) ? - $.widget.extend( {}, target[ key ], value ) : - // Don't extend strings, arrays, etc. with objects - $.widget.extend( {}, value ); - // Copy everything else by reference - } else { - target[ key ] = value; - } - } - } - } - return target; -}; + // Track widgets that inherit from this widget in case this widget is + // redefined after a widget inherits from it + _childConstructors: [] + } ); -$.widget.bridge = function( name, object ) { - var fullName = object.prototype.widgetFullName || name; - $.fn[ name ] = function( options ) { - var isMethodCall = typeof options === "string", - args = widget_slice.call( arguments, 1 ), - returnValue = this; + basePrototype = new base(); - // allow multiple hashes to be passed on init - options = !isMethodCall && args.length ? - $.widget.extend.apply( null, [ options ].concat(args) ) : - options; + // We need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from + basePrototype.options = $.widget.extend( {}, basePrototype.options ); + $.each( prototype, function( prop, value ) { + if ( !$.isFunction( value ) ) { + proxiedPrototype[ prop ] = value; + return; + } + proxiedPrototype[ prop ] = ( function() { + function _super() { + return base.prototype[ prop ].apply( this, arguments ); + } - if ( isMethodCall ) { - this.each(function() { - var methodValue, - instance = $.data( this, fullName ); - if ( options === "instance" ) { - returnValue = instance; - return false; - } - if ( !instance ) { - return $.error( "cannot call methods on " + name + " prior to initialization; " + - "attempted to call method '" + options + "'" ); - } - if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { - return $.error( "no such method '" + options + "' for " + name + " widget instance" ); - } - methodValue = instance[ options ].apply( instance, args ); - if ( methodValue !== instance && methodValue !== undefined ) { - returnValue = methodValue && methodValue.jquery ? - returnValue.pushStack( methodValue.get() ) : - methodValue; - return false; - } - }); - } else { - this.each(function() { - var instance = $.data( this, fullName ); - if ( instance ) { - instance.option( options || {} ); - if ( instance._init ) { - instance._init(); - } - } else { - $.data( this, fullName, new object( options, this ) ); - } - }); - } + function _superApply( args ) { + return base.prototype[ prop ].apply( this, args ); + } - return returnValue; - }; -}; + return function() { + var __super = this._super; + var __superApply = this._superApply; + var returnValue; -$.Widget = function( /* options, element */ ) {}; -$.Widget._childConstructors = []; + this._super = _super; + this._superApply = _superApply; -$.Widget.prototype = { - widgetName: "widget", - widgetEventPrefix: "", - defaultElement: "
    ", - options: { - disabled: false, + returnValue = value.apply( this, arguments ); - // callbacks - create: null - }, - _createWidget: function( options, element ) { - element = $( element || this.defaultElement || this )[ 0 ]; - this.element = $( element ); - this.uuid = widget_uuid++; - this.eventNamespace = "." + this.widgetName + this.uuid; - this.options = $.widget.extend( {}, - this.options, - this._getCreateOptions(), - options ); + this._super = __super; + this._superApply = __superApply; - this.bindings = $(); - this.hoverable = $(); - this.focusable = $(); + return returnValue; + }; + } )(); + } ); + constructor.prototype = $.widget.extend( basePrototype, { - if ( element !== this ) { - $.data( element, this.widgetFullName, this ); - this._on( true, this.element, { - remove: function( event ) { - if ( event.target === element ) { - this.destroy(); - } - } - }); - this.document = $( element.style ? - // element within the document - element.ownerDocument : - // element is window or document - element.document || element ); - this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); - } + // TODO: remove support for widgetEventPrefix + // always use the name + a colon as the prefix, e.g., draggable:start + // don't prefix for widgets that aren't DOM-based + widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name + }, proxiedPrototype, { + constructor: constructor, + namespace: namespace, + widgetName: name, + widgetFullName: fullName + } ); - this._create(); - this._trigger( "create", null, this._getCreateEventData() ); - this._init(); - }, - _getCreateOptions: $.noop, - _getCreateEventData: $.noop, - _create: $.noop, - _init: $.noop, + // If this widget is being redefined then we need to find all widgets that + // are inheriting from it and redefine all of them so that they inherit from + // the new version of this widget. We're essentially trying to replace one + // level in the prototype chain. + if ( existingConstructor ) { + $.each( existingConstructor._childConstructors, function( i, child ) { + var childPrototype = child.prototype; - destroy: function() { - this._destroy(); - // we can probably remove the unbind calls in 2.0 - // all event bindings should go through this._on() - this.element - .unbind( this.eventNamespace ) - .removeData( this.widgetFullName ) - // support: jquery <1.6.3 - // http://bugs.jquery.com/ticket/9413 - .removeData( $.camelCase( this.widgetFullName ) ); - this.widget() - .unbind( this.eventNamespace ) - .removeAttr( "aria-disabled" ) - .removeClass( - this.widgetFullName + "-disabled " + - "ui-state-disabled" ); + // Redefine the child widget using the same prototype that was + // originally used, but inherit from the new version of the base + $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, + child._proto ); + } ); - // clean up events and states - this.bindings.unbind( this.eventNamespace ); - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - }, - _destroy: $.noop, + // Remove the list of existing child constructors from the old constructor + // so the old child constructors can be garbage collected + delete existingConstructor._childConstructors; + } else { + base._childConstructors.push( constructor ); + } - widget: function() { - return this.element; - }, + $.widget.bridge( name, constructor ); - option: function( key, value ) { - var options = key, - parts, - curOption, - i; + return constructor; + }; - if ( arguments.length === 0 ) { - // don't return a reference to the internal hash - return $.widget.extend( {}, this.options ); - } + $.widget.extend = function( target ) { + var input = widgetSlice.call( arguments, 1 ); + var inputIndex = 0; + var inputLength = input.length; + var key; + var value; - if ( typeof key === "string" ) { - // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } - options = {}; - parts = key.split( "." ); - key = parts.shift(); - if ( parts.length ) { - curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); - for ( i = 0; i < parts.length - 1; i++ ) { - curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; - curOption = curOption[ parts[ i ] ]; - } - key = parts.pop(); - if ( arguments.length === 1 ) { - return curOption[ key ] === undefined ? null : curOption[ key ]; - } - curOption[ key ] = value; - } else { - if ( arguments.length === 1 ) { - return this.options[ key ] === undefined ? null : this.options[ key ]; - } - options[ key ] = value; - } - } + for ( ; inputIndex < inputLength; inputIndex++ ) { + for ( key in input[ inputIndex ] ) { + value = input[ inputIndex ][ key ]; + if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { - this._setOptions( options ); + // Clone objects + if ( $.isPlainObject( value ) ) { + target[ key ] = $.isPlainObject( target[ key ] ) ? + $.widget.extend( {}, target[ key ], value ) : - return this; - }, - _setOptions: function( options ) { - var key; + // Don't extend strings, arrays, etc. with objects + $.widget.extend( {}, value ); - for ( key in options ) { - this._setOption( key, options[ key ] ); - } + // Copy everything else by reference + } else { + target[ key ] = value; + } + } + } + } + return target; + }; - return this; - }, - _setOption: function( key, value ) { - this.options[ key ] = value; + $.widget.bridge = function( name, object ) { + var fullName = object.prototype.widgetFullName || name; + $.fn[ name ] = function( options ) { + var isMethodCall = typeof options === "string"; + var args = widgetSlice.call( arguments, 1 ); + var returnValue = this; - if ( key === "disabled" ) { - this.widget() - .toggleClass( this.widgetFullName + "-disabled", !!value ); + if ( isMethodCall ) { - // If the widget is becoming disabled, then nothing is interactive - if ( value ) { - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - } - } + // If this is an empty collection, we need to have the instance method + // return undefined instead of the jQuery instance + if ( !this.length && options === "instance" ) { + returnValue = undefined; + } else { + this.each( function() { + var methodValue; + var instance = $.data( this, fullName ); - return this; - }, + if ( options === "instance" ) { + returnValue = instance; + return false; + } - enable: function() { - return this._setOptions({ disabled: false }); - }, - disable: function() { - return this._setOptions({ disabled: true }); - }, + if ( !instance ) { + return $.error( "cannot call methods on " + name + + " prior to initialization; " + + "attempted to call method '" + options + "'" ); + } - _on: function( suppressDisabledCheck, element, handlers ) { - var delegateElement, - instance = this; + if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) { + return $.error( "no such method '" + options + "' for " + name + + " widget instance" ); + } - // no suppressDisabledCheck flag, shuffle arguments - if ( typeof suppressDisabledCheck !== "boolean" ) { - handlers = element; - element = suppressDisabledCheck; - suppressDisabledCheck = false; - } + methodValue = instance[ options ].apply( instance, args ); - // no element argument, shuffle and use this.element - if ( !handlers ) { - handlers = element; - element = this.element; - delegateElement = this.widget(); - } else { - element = delegateElement = $( element ); - this.bindings = this.bindings.add( element ); - } + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue && methodValue.jquery ? + returnValue.pushStack( methodValue.get() ) : + methodValue; + return false; + } + } ); + } + } else { - $.each( handlers, function( event, handler ) { - function handlerProxy() { - // allow widgets to customize the disabled handling - // - disabled as an array instead of boolean - // - disabled class as method for disabling individual parts - if ( !suppressDisabledCheck && - ( instance.options.disabled === true || - $( this ).hasClass( "ui-state-disabled" ) ) ) { - return; - } - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } + // Allow multiple hashes to be passed on init + if ( args.length ) { + options = $.widget.extend.apply( null, [ options ].concat( args ) ); + } - // copy the guid so direct unbinding works - if ( typeof handler !== "string" ) { - handlerProxy.guid = handler.guid = - handler.guid || handlerProxy.guid || $.guid++; - } + this.each( function() { + var instance = $.data( this, fullName ); + if ( instance ) { + instance.option( options || {} ); + if ( instance._init ) { + instance._init(); + } + } else { + $.data( this, fullName, new object( options, this ) ); + } + } ); + } - var match = event.match( /^([\w:-]*)\s*(.*)$/ ), - eventName = match[1] + instance.eventNamespace, - selector = match[2]; - if ( selector ) { - delegateElement.delegate( selector, eventName, handlerProxy ); - } else { - element.bind( eventName, handlerProxy ); - } - }); - }, + return returnValue; + }; + }; - _off: function( element, eventName ) { - eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; - element.unbind( eventName ).undelegate( eventName ); - }, + $.Widget = function( /* options, element */ ) {}; + $.Widget._childConstructors = []; - _delay: function( handler, delay ) { - function handlerProxy() { - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - var instance = this; - return setTimeout( handlerProxy, delay || 0 ); - }, + $.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + defaultElement: "
    ", - _hoverable: function( element ) { - this.hoverable = this.hoverable.add( element ); - this._on( element, { - mouseenter: function( event ) { - $( event.currentTarget ).addClass( "ui-state-hover" ); - }, - mouseleave: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-hover" ); - } - }); - }, + options: { + classes: {}, + disabled: false, - _focusable: function( element ) { - this.focusable = this.focusable.add( element ); - this._on( element, { - focusin: function( event ) { - $( event.currentTarget ).addClass( "ui-state-focus" ); - }, - focusout: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-focus" ); - } - }); - }, + // Callbacks + create: null + }, - _trigger: function( type, event, data ) { - var prop, orig, - callback = this.options[ type ]; + _createWidget: function( options, element ) { + element = $( element || this.defaultElement || this )[ 0 ]; + this.element = $( element ); + this.uuid = widgetUuid++; + this.eventNamespace = "." + this.widgetName + this.uuid; - data = data || {}; - event = $.Event( event ); - event.type = ( type === this.widgetEventPrefix ? - type : - this.widgetEventPrefix + type ).toLowerCase(); - // the original event may come from any element - // so we need to reset the target on the new event - event.target = this.element[ 0 ]; + this.bindings = $(); + this.hoverable = $(); + this.focusable = $(); + this.classesElementLookup = {}; - // copy original event properties over to the new event - orig = event.originalEvent; - if ( orig ) { - for ( prop in orig ) { - if ( !( prop in event ) ) { - event[ prop ] = orig[ prop ]; - } - } - } + if ( element !== this ) { + $.data( element, this.widgetFullName, this ); + this._on( true, this.element, { + remove: function( event ) { + if ( event.target === element ) { + this.destroy(); + } + } + } ); + this.document = $( element.style ? - this.element.trigger( event, data ); - return !( $.isFunction( callback ) && - callback.apply( this.element[0], [ event ].concat( data ) ) === false || - event.isDefaultPrevented() ); - } -}; + // Element within the document + element.ownerDocument : -$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { - $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { - if ( typeof options === "string" ) { - options = { effect: options }; - } - var hasOptions, - effectName = !options ? - method : - options === true || typeof options === "number" ? - defaultEffect : - options.effect || defaultEffect; - options = options || {}; - if ( typeof options === "number" ) { - options = { duration: options }; - } - hasOptions = !$.isEmptyObject( options ); - options.complete = callback; - if ( options.delay ) { - element.delay( options.delay ); - } - if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { - element[ method ]( options ); - } else if ( effectName !== method && element[ effectName ] ) { - element[ effectName ]( options.duration, options.easing, callback ); - } else { - element.queue(function( next ) { - $( this )[ method ](); - if ( callback ) { - callback.call( element[ 0 ] ); - } - next(); - }); - } - }; -}); + // Element is window or document + element.document || element ); + this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow ); + } + + this.options = $.widget.extend( {}, + this.options, + this._getCreateOptions(), + options ); + + this._create(); + + if ( this.options.disabled ) { + this._setOptionDisabled( this.options.disabled ); + } + + this._trigger( "create", null, this._getCreateEventData() ); + this._init(); + }, + + _getCreateOptions: function() { + return {}; + }, + + _getCreateEventData: $.noop, + + _create: $.noop, + + _init: $.noop, + + destroy: function() { + var that = this; + + this._destroy(); + $.each( this.classesElementLookup, function( key, value ) { + that._removeClass( value, key ); + } ); + + // We can probably remove the unbind calls in 2.0 + // all event bindings should go through this._on() + this.element + .off( this.eventNamespace ) + .removeData( this.widgetFullName ); + this.widget() + .off( this.eventNamespace ) + .removeAttr( "aria-disabled" ); + + // Clean up events and states + this.bindings.off( this.eventNamespace ); + }, + + _destroy: $.noop, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key; + var parts; + var curOption; + var i; + + if ( arguments.length === 0 ) { + + // Don't return a reference to the internal hash + return $.widget.extend( {}, this.options ); + } + + if ( typeof key === "string" ) { + + // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } + options = {}; + parts = key.split( "." ); + key = parts.shift(); + if ( parts.length ) { + curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); + for ( i = 0; i < parts.length - 1; i++ ) { + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; + curOption = curOption[ parts[ i ] ]; + } + key = parts.pop(); + if ( arguments.length === 1 ) { + return curOption[ key ] === undefined ? null : curOption[ key ]; + } + curOption[ key ] = value; + } else { + if ( arguments.length === 1 ) { + return this.options[ key ] === undefined ? null : this.options[ key ]; + } + options[ key ] = value; + } + } + + this._setOptions( options ); + + return this; + }, + + _setOptions: function( options ) { + var key; + + for ( key in options ) { + this._setOption( key, options[ key ] ); + } + + return this; + }, + + _setOption: function( key, value ) { + if ( key === "classes" ) { + this._setOptionClasses( value ); + } + + this.options[ key ] = value; + + if ( key === "disabled" ) { + this._setOptionDisabled( value ); + } + + return this; + }, + + _setOptionClasses: function( value ) { + var classKey, elements, currentElements; + + for ( classKey in value ) { + currentElements = this.classesElementLookup[ classKey ]; + if ( value[ classKey ] === this.options.classes[ classKey ] || + !currentElements || + !currentElements.length ) { + continue; + } + + // We are doing this to create a new jQuery object because the _removeClass() call + // on the next line is going to destroy the reference to the current elements being + // tracked. We need to save a copy of this collection so that we can add the new classes + // below. + elements = $( currentElements.get() ); + this._removeClass( currentElements, classKey ); + + // We don't use _addClass() here, because that uses this.options.classes + // for generating the string of classes. We want to use the value passed in from + // _setOption(), this is the new value of the classes option which was passed to + // _setOption(). We pass this value directly to _classes(). + elements.addClass( this._classes( { + element: elements, + keys: classKey, + classes: value, + add: true + } ) ); + } + }, + + _setOptionDisabled: function( value ) { + this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value ); + + // If the widget is becoming disabled, then nothing is interactive + if ( value ) { + this._removeClass( this.hoverable, null, "ui-state-hover" ); + this._removeClass( this.focusable, null, "ui-state-focus" ); + } + }, + + enable: function() { + return this._setOptions( { disabled: false } ); + }, + + disable: function() { + return this._setOptions( { disabled: true } ); + }, + + _classes: function( options ) { + var full = []; + var that = this; + + options = $.extend( { + element: this.element, + classes: this.options.classes || {} + }, options ); + + function processClassString( classes, checkOption ) { + var current, i; + for ( i = 0; i < classes.length; i++ ) { + current = that.classesElementLookup[ classes[ i ] ] || $(); + if ( options.add ) { + current = $( $.unique( current.get().concat( options.element.get() ) ) ); + } else { + current = $( current.not( options.element ).get() ); + } + that.classesElementLookup[ classes[ i ] ] = current; + full.push( classes[ i ] ); + if ( checkOption && options.classes[ classes[ i ] ] ) { + full.push( options.classes[ classes[ i ] ] ); + } + } + } + + this._on( options.element, { + "remove": "_untrackClassesElement" + } ); + + if ( options.keys ) { + processClassString( options.keys.match( /\S+/g ) || [], true ); + } + if ( options.extra ) { + processClassString( options.extra.match( /\S+/g ) || [] ); + } + + return full.join( " " ); + }, + + _untrackClassesElement: function( event ) { + var that = this; + $.each( that.classesElementLookup, function( key, value ) { + if ( $.inArray( event.target, value ) !== -1 ) { + that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); + } + } ); + }, + + _removeClass: function( element, keys, extra ) { + return this._toggleClass( element, keys, extra, false ); + }, + + _addClass: function( element, keys, extra ) { + return this._toggleClass( element, keys, extra, true ); + }, + + _toggleClass: function( element, keys, extra, add ) { + add = ( typeof add === "boolean" ) ? add : extra; + var shift = ( typeof element === "string" || element === null ), + options = { + extra: shift ? keys : extra, + keys: shift ? element : keys, + element: shift ? this.element : element, + add: add + }; + options.element.toggleClass( this._classes( options ), add ); + return this; + }, + + _on: function( suppressDisabledCheck, element, handlers ) { + var delegateElement; + var instance = this; + + // No suppressDisabledCheck flag, shuffle arguments + if ( typeof suppressDisabledCheck !== "boolean" ) { + handlers = element; + element = suppressDisabledCheck; + suppressDisabledCheck = false; + } + + // No element argument, shuffle and use this.element + if ( !handlers ) { + handlers = element; + element = this.element; + delegateElement = this.widget(); + } else { + element = delegateElement = $( element ); + this.bindings = this.bindings.add( element ); + } + + $.each( handlers, function( event, handler ) { + function handlerProxy() { + + // Allow widgets to customize the disabled handling + // - disabled as an array instead of boolean + // - disabled class as method for disabling individual parts + if ( !suppressDisabledCheck && + ( instance.options.disabled === true || + $( this ).hasClass( "ui-state-disabled" ) ) ) { + return; + } + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + + // Copy the guid so direct unbinding works + if ( typeof handler !== "string" ) { + handlerProxy.guid = handler.guid = + handler.guid || handlerProxy.guid || $.guid++; + } + + var match = event.match( /^([\w:-]*)\s*(.*)$/ ); + var eventName = match[ 1 ] + instance.eventNamespace; + var selector = match[ 2 ]; + + if ( selector ) { + delegateElement.on( eventName, selector, handlerProxy ); + } else { + element.on( eventName, handlerProxy ); + } + } ); + }, + + _off: function( element, eventName ) { + eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) + + this.eventNamespace; + element.off( eventName ).off( eventName ); + + // Clear the stack to avoid memory leaks (#10056) + this.bindings = $( this.bindings.not( element ).get() ); + this.focusable = $( this.focusable.not( element ).get() ); + this.hoverable = $( this.hoverable.not( element ).get() ); + }, + + _delay: function( handler, delay ) { + function handlerProxy() { + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + var instance = this; + return setTimeout( handlerProxy, delay || 0 ); + }, + + _hoverable: function( element ) { + this.hoverable = this.hoverable.add( element ); + this._on( element, { + mouseenter: function( event ) { + this._addClass( $( event.currentTarget ), null, "ui-state-hover" ); + }, + mouseleave: function( event ) { + this._removeClass( $( event.currentTarget ), null, "ui-state-hover" ); + } + } ); + }, + + _focusable: function( element ) { + this.focusable = this.focusable.add( element ); + this._on( element, { + focusin: function( event ) { + this._addClass( $( event.currentTarget ), null, "ui-state-focus" ); + }, + focusout: function( event ) { + this._removeClass( $( event.currentTarget ), null, "ui-state-focus" ); + } + } ); + }, + + _trigger: function( type, event, data ) { + var prop, orig; + var callback = this.options[ type ]; + + data = data || {}; + event = $.Event( event ); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + + // The original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // Copy original event properties over to the new event + orig = event.originalEvent; + if ( orig ) { + for ( prop in orig ) { + if ( !( prop in event ) ) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger( event, data ); + return !( $.isFunction( callback ) && + callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false || + event.isDefaultPrevented() ); + } + }; + + $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { + $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { + if ( typeof options === "string" ) { + options = { effect: options }; + } + + var hasOptions; + var effectName = !options ? + method : + options === true || typeof options === "number" ? + defaultEffect : + options.effect || defaultEffect; + + options = options || {}; + if ( typeof options === "number" ) { + options = { duration: options }; + } + + hasOptions = !$.isEmptyObject( options ); + options.complete = callback; + + if ( options.delay ) { + element.delay( options.delay ); + } + + if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { + element[ method ]( options ); + } else if ( effectName !== method && element[ effectName ] ) { + element[ effectName ]( options.duration, options.easing, callback ); + } else { + element.queue( function( next ) { + $( this )[ method ](); + if ( callback ) { + callback.call( element[ 0 ] ); + } + next(); + } ); + } + }; + } ); + + var widget = $.widget; -var widget = $.widget; diff --git a/common/lang/en.php b/common/lang/en.php index fd557c7dd..aa8d20759 100644 --- a/common/lang/en.php +++ b/common/lang/en.php @@ -231,6 +231,8 @@ $lang->msg_input_password = 'Please type the password.'; $lang->msg_invalid_document = 'Invalid Article Number'; $lang->msg_invalid_request = 'Invalid Request'; $lang->msg_invalid_password = 'The password you entered is incorrect.'; +$lang->msg_security_violation = 'Security Violation'; +$lang->msg_feature_disabled = 'This feature is disabled.'; $lang->msg_error_occured = 'An error has occured.'; $lang->msg_not_founded = 'Cannot find the target.'; $lang->msg_no_result = 'No results found.'; @@ -244,6 +246,7 @@ $lang->msg_empty_search_keyword = 'Cannot find the Keyword.'; $lang->msg_empty_content = 'The content is empty.'; $lang->msg_server_error = 'Server Error'; $lang->msg_server_error_see_log = 'Your server is configured to hide error messages. Please see your server\'s error log for details.'; +$lang->msg_crypto_not_available = 'OpenSSL extension is not installed.'; $lang->comment_to_be_approved = 'Your comment must be approved by admin before being published.'; $lang->success_registed = 'Registered successfully.'; $lang->success_declared = 'Reported successfully.'; @@ -266,7 +269,9 @@ $lang->fail_to_update = 'Fail to update.'; $lang->fail_to_delete = 'Failed to delete.'; $lang->fail_to_move = 'Failed to move.'; $lang->failed_voted = 'No permission to upvote.'; +$lang->failed_voted_canceled = 'You cannot cancel an upvote that you did\'t make.'; $lang->failed_blamed = 'No permission to downvote.'; +$lang->failed_blamed_canceled = 'You cannot cancel a downvote that you did\'t make.'; $lang->failed_declared = 'No permission to Report.'; $lang->fail_to_delete_have_children = 'Cannot delete the article with comments.'; $lang->confirm_submit = 'Are you sure you want to submit?'; diff --git a/common/lang/ko.php b/common/lang/ko.php index b5571ba87..d536cca5f 100644 --- a/common/lang/ko.php +++ b/common/lang/ko.php @@ -231,6 +231,8 @@ $lang->msg_input_password = '비밀번호를 입력하세요.'; $lang->msg_invalid_document = '잘못된 문서번호입니다.'; $lang->msg_invalid_request = '잘못된 요청입니다.'; $lang->msg_invalid_password = '비밀번호가 올바르지 않습니다.'; +$lang->msg_security_violation = '보안정책상 허용되지 않습니다.'; +$lang->msg_feature_disabled = '사용할 수 없는 기능입니다.'; $lang->msg_error_occured = '오류가 발생했습니다.'; $lang->msg_not_founded = '대상을 찾을 수 없습니다.'; $lang->msg_no_result = '검색 결과가 없습니다.'; @@ -244,6 +246,7 @@ $lang->msg_empty_search_keyword = '검색어가 없습니다.'; $lang->msg_empty_content = '내용이 없습니다.'; $lang->msg_server_error = '서버 오류'; $lang->msg_server_error_see_log = '오류 메시지를 표시하지 않도록 설정되어 있습니다. 서버의 에러 로그에서 자세한 내용을 확인해 주십시오.'; +$lang->msg_crypto_not_available = 'openssl 확장모듈이 설치되어 있지 않습니다.'; $lang->comment_to_be_approved = '관리자의 확인이 필요한 댓글입니다.'; $lang->success_registed = '등록했습니다.'; $lang->success_declared = '신고했습니다.'; @@ -266,7 +269,9 @@ $lang->fail_to_update = '수정하지 못했습니다.'; $lang->fail_to_delete = '삭제 실패했습니다.'; $lang->fail_to_move = '이동 실패했습니다.'; $lang->failed_voted = '추천할 수 없습니다.'; +$lang->failed_voted_canceled = '추천한 적이 없으므로 취소할 수 없습니다.'; $lang->failed_blamed = '비추천할 수 없습니다.'; +$lang->failed_blamed_canceled = '비추천한 적이 없으므로 취소할 수 없습니다.'; $lang->failed_declared = '신고할 수 없습니다.'; $lang->fail_to_delete_have_children = '댓글이 있어서 삭제할 수 없습니다.'; $lang->confirm_submit = '등록하시겠습니까?'; diff --git a/common/legacy.php b/common/legacy.php index 0f7644065..78f3f7d83 100644 --- a/common/legacy.php +++ b/common/legacy.php @@ -868,7 +868,7 @@ function removeSrcHack($match) * @param string $file Taget file path * @return bool */ -function checkUploadedFile($file) +function checkUploadedFile($file, $filename = null) { return true; } diff --git a/common/manual/admin/img/admin/dashboard.png b/common/manual/admin/img/admin/dashboard.png deleted file mode 100644 index 281cc86f2..000000000 Binary files a/common/manual/admin/img/admin/dashboard.png and /dev/null differ diff --git a/common/manual/admin/img/admin/easyinstall_for_textyle.png b/common/manual/admin/img/admin/easyinstall_for_textyle.png deleted file mode 100644 index c73f829fa..000000000 Binary files a/common/manual/admin/img/admin/easyinstall_for_textyle.png and /dev/null differ diff --git a/common/manual/admin/img/admin/ftp_config.png b/common/manual/admin/img/admin/ftp_config.png deleted file mode 100644 index 75b3f142d..000000000 Binary files a/common/manual/admin/img/admin/ftp_config.png and /dev/null differ diff --git a/common/manual/admin/img/admin/installed_module.png b/common/manual/admin/img/admin/installed_module.png deleted file mode 100644 index edc18b29b..000000000 Binary files a/common/manual/admin/img/admin/installed_module.png and /dev/null differ diff --git a/common/manual/admin/img/faq/add_multilingual.png b/common/manual/admin/img/faq/add_multilingual.png deleted file mode 100644 index a13b67323..000000000 Binary files a/common/manual/admin/img/faq/add_multilingual.png and /dev/null differ diff --git a/common/manual/admin/img/faq/admin_ip_band.png b/common/manual/admin/img/faq/admin_ip_band.png deleted file mode 100644 index 8c082d52c..000000000 Binary files a/common/manual/admin/img/faq/admin_ip_band.png and /dev/null differ diff --git a/common/manual/admin/img/faq/apply_multilingual.png b/common/manual/admin/img/faq/apply_multilingual.png deleted file mode 100644 index 564928259..000000000 Binary files a/common/manual/admin/img/faq/apply_multilingual.png and /dev/null differ diff --git a/common/manual/admin/img/faq/board_basic_setup.png b/common/manual/admin/img/faq/board_basic_setup.png deleted file mode 100644 index 078e5c592..000000000 Binary files a/common/manual/admin/img/faq/board_basic_setup.png and /dev/null differ diff --git a/common/manual/admin/img/faq/comment_publish.png b/common/manual/admin/img/faq/comment_publish.png deleted file mode 100644 index 50f238173..000000000 Binary files a/common/manual/admin/img/faq/comment_publish.png and /dev/null differ diff --git a/common/manual/admin/img/faq/defence_login_limit.png b/common/manual/admin/img/faq/defence_login_limit.png deleted file mode 100644 index a2045dcd7..000000000 Binary files a/common/manual/admin/img/faq/defence_login_limit.png and /dev/null differ diff --git a/common/manual/admin/img/faq/deny_admin_by_ip.png b/common/manual/admin/img/faq/deny_admin_by_ip.png deleted file mode 100644 index f890c2444..000000000 Binary files a/common/manual/admin/img/faq/deny_admin_by_ip.png and /dev/null differ diff --git a/common/manual/admin/img/faq/export1.png b/common/manual/admin/img/faq/export1.png deleted file mode 100644 index 69be7d178..000000000 Binary files a/common/manual/admin/img/faq/export1.png and /dev/null differ diff --git a/common/manual/admin/img/faq/export2.png b/common/manual/admin/img/faq/export2.png deleted file mode 100644 index 91f999f76..000000000 Binary files a/common/manual/admin/img/faq/export2.png and /dev/null differ diff --git a/common/manual/admin/img/faq/export3.png b/common/manual/admin/img/faq/export3.png deleted file mode 100644 index ea3629485..000000000 Binary files a/common/manual/admin/img/faq/export3.png and /dev/null differ diff --git a/common/manual/admin/img/faq/exposure_target.png b/common/manual/admin/img/faq/exposure_target.png deleted file mode 100644 index a9a929d97..000000000 Binary files a/common/manual/admin/img/faq/exposure_target.png and /dev/null differ diff --git a/common/manual/admin/img/faq/file_status.png b/common/manual/admin/img/faq/file_status.png deleted file mode 100644 index ca08c8bb7..000000000 Binary files a/common/manual/admin/img/faq/file_status.png and /dev/null differ diff --git a/common/manual/admin/img/faq/import1.png b/common/manual/admin/img/faq/import1.png deleted file mode 100644 index 8558fc6f1..000000000 Binary files a/common/manual/admin/img/faq/import1.png and /dev/null differ diff --git a/common/manual/admin/img/faq/import2.png b/common/manual/admin/img/faq/import2.png deleted file mode 100644 index c187e68d4..000000000 Binary files a/common/manual/admin/img/faq/import2.png and /dev/null differ diff --git a/common/manual/admin/img/faq/import_complete.png b/common/manual/admin/img/faq/import_complete.png deleted file mode 100644 index 9c6955e1a..000000000 Binary files a/common/manual/admin/img/faq/import_complete.png and /dev/null differ diff --git a/common/manual/admin/img/faq/joinform_manage.png b/common/manual/admin/img/faq/joinform_manage.png deleted file mode 100644 index 35e42fa55..000000000 Binary files a/common/manual/admin/img/faq/joinform_manage.png and /dev/null differ diff --git a/common/manual/admin/img/faq/joinform_type.png b/common/manual/admin/img/faq/joinform_type.png deleted file mode 100644 index 5f48e9dad..000000000 Binary files a/common/manual/admin/img/faq/joinform_type.png and /dev/null differ diff --git a/common/manual/admin/img/faq/login_config.png b/common/manual/admin/img/faq/login_config.png deleted file mode 100644 index 5e35130bc..000000000 Binary files a/common/manual/admin/img/faq/login_config.png and /dev/null differ diff --git a/common/manual/admin/img/faq/menu_name_modify.png b/common/manual/admin/img/faq/menu_name_modify.png deleted file mode 100644 index 24b779dfb..000000000 Binary files a/common/manual/admin/img/faq/menu_name_modify.png and /dev/null differ diff --git a/common/manual/admin/img/faq/search_multilingual.png b/common/manual/admin/img/faq/search_multilingual.png deleted file mode 100644 index abd8c1d1a..000000000 Binary files a/common/manual/admin/img/faq/search_multilingual.png and /dev/null differ diff --git a/common/manual/admin/img/faq/use_multilingual.png b/common/manual/admin/img/faq/use_multilingual.png deleted file mode 100644 index d796e4a8f..000000000 Binary files a/common/manual/admin/img/faq/use_multilingual.png and /dev/null differ diff --git a/common/manual/admin/img/faq/user_defined_joinform.png b/common/manual/admin/img/faq/user_defined_joinform.png deleted file mode 100644 index 167e9292b..000000000 Binary files a/common/manual/admin/img/faq/user_defined_joinform.png and /dev/null differ diff --git a/common/manual/admin/img/image001.png b/common/manual/admin/img/image001.png deleted file mode 100644 index 78b32a669..000000000 Binary files a/common/manual/admin/img/image001.png and /dev/null differ diff --git a/common/manual/admin/img/image002.jpg b/common/manual/admin/img/image002.jpg deleted file mode 100644 index 4fe8521ff..000000000 Binary files a/common/manual/admin/img/image002.jpg and /dev/null differ diff --git a/common/manual/admin/img/image003.jpg b/common/manual/admin/img/image003.jpg deleted file mode 100644 index 086233cbe..000000000 Binary files a/common/manual/admin/img/image003.jpg and /dev/null differ diff --git a/common/manual/admin/img/image004.jpg b/common/manual/admin/img/image004.jpg deleted file mode 100644 index 6424676f2..000000000 Binary files a/common/manual/admin/img/image004.jpg and /dev/null differ diff --git a/common/manual/admin/img/image005.jpg b/common/manual/admin/img/image005.jpg deleted file mode 100644 index d9ac609c2..000000000 Binary files a/common/manual/admin/img/image005.jpg and /dev/null differ diff --git a/common/manual/admin/img/image006.jpg b/common/manual/admin/img/image006.jpg deleted file mode 100644 index c1e357782..000000000 Binary files a/common/manual/admin/img/image006.jpg and /dev/null differ diff --git a/common/manual/admin/img/image007.jpg b/common/manual/admin/img/image007.jpg deleted file mode 100644 index d2a6f4163..000000000 Binary files a/common/manual/admin/img/image007.jpg and /dev/null differ diff --git a/common/manual/admin/img/image008.jpg b/common/manual/admin/img/image008.jpg deleted file mode 100644 index 371269c37..000000000 Binary files a/common/manual/admin/img/image008.jpg and /dev/null differ diff --git a/common/manual/admin/img/image009.jpg b/common/manual/admin/img/image009.jpg deleted file mode 100644 index ee8bdbcac..000000000 Binary files a/common/manual/admin/img/image009.jpg and /dev/null differ diff --git a/common/manual/admin/img/image010.jpg b/common/manual/admin/img/image010.jpg deleted file mode 100644 index 160404ba7..000000000 Binary files a/common/manual/admin/img/image010.jpg and /dev/null differ diff --git a/common/manual/admin/img/image011.jpg b/common/manual/admin/img/image011.jpg deleted file mode 100644 index 5a4810ca8..000000000 Binary files a/common/manual/admin/img/image011.jpg and /dev/null differ diff --git a/common/manual/admin/img/image012.jpg b/common/manual/admin/img/image012.jpg deleted file mode 100644 index 05fa09bfd..000000000 Binary files a/common/manual/admin/img/image012.jpg and /dev/null differ diff --git a/common/manual/admin/img/image013.jpg b/common/manual/admin/img/image013.jpg deleted file mode 100644 index 614996b47..000000000 Binary files a/common/manual/admin/img/image013.jpg and /dev/null differ diff --git a/common/manual/admin/img/image014.jpg b/common/manual/admin/img/image014.jpg deleted file mode 100644 index 937510998..000000000 Binary files a/common/manual/admin/img/image014.jpg and /dev/null differ diff --git a/common/manual/admin/img/image015.jpg b/common/manual/admin/img/image015.jpg deleted file mode 100644 index 37e9b8e8d..000000000 Binary files a/common/manual/admin/img/image015.jpg and /dev/null differ diff --git a/common/manual/admin/img/image016.jpg b/common/manual/admin/img/image016.jpg deleted file mode 100644 index 9860aae20..000000000 Binary files a/common/manual/admin/img/image016.jpg and /dev/null differ diff --git a/common/manual/admin/img/image017.jpg b/common/manual/admin/img/image017.jpg deleted file mode 100644 index 3eacb35c5..000000000 Binary files a/common/manual/admin/img/image017.jpg and /dev/null differ diff --git a/common/manual/admin/img/image018.jpg b/common/manual/admin/img/image018.jpg deleted file mode 100644 index 21bb1d475..000000000 Binary files a/common/manual/admin/img/image018.jpg and /dev/null differ diff --git a/common/manual/admin/img/image019.jpg b/common/manual/admin/img/image019.jpg deleted file mode 100644 index fa9b8f4e1..000000000 Binary files a/common/manual/admin/img/image019.jpg and /dev/null differ diff --git a/common/manual/admin/img/image020.jpg b/common/manual/admin/img/image020.jpg deleted file mode 100644 index 41f916672..000000000 Binary files a/common/manual/admin/img/image020.jpg and /dev/null differ diff --git a/common/manual/admin/img/image021.jpg b/common/manual/admin/img/image021.jpg deleted file mode 100644 index 1b464737b..000000000 Binary files a/common/manual/admin/img/image021.jpg and /dev/null differ diff --git a/common/manual/admin/img/image022.jpg b/common/manual/admin/img/image022.jpg deleted file mode 100644 index 0fcc785cb..000000000 Binary files a/common/manual/admin/img/image022.jpg and /dev/null differ diff --git a/common/manual/admin/img/image023.png b/common/manual/admin/img/image023.png deleted file mode 100644 index 907668242..000000000 Binary files a/common/manual/admin/img/image023.png and /dev/null differ diff --git a/common/manual/admin/img/image024.jpg b/common/manual/admin/img/image024.jpg deleted file mode 100644 index b953fbc94..000000000 Binary files a/common/manual/admin/img/image024.jpg and /dev/null differ diff --git a/common/manual/admin/img/image025.jpg b/common/manual/admin/img/image025.jpg deleted file mode 100644 index 6ff7ff38f..000000000 Binary files a/common/manual/admin/img/image025.jpg and /dev/null differ diff --git a/common/manual/admin/img/image026.png b/common/manual/admin/img/image026.png deleted file mode 100644 index 39116970f..000000000 Binary files a/common/manual/admin/img/image026.png and /dev/null differ diff --git a/common/manual/admin/img/image027.jpg b/common/manual/admin/img/image027.jpg deleted file mode 100644 index f5ba29062..000000000 Binary files a/common/manual/admin/img/image027.jpg and /dev/null differ diff --git a/common/manual/admin/img/image028.png b/common/manual/admin/img/image028.png deleted file mode 100644 index d3e66bb48..000000000 Binary files a/common/manual/admin/img/image028.png and /dev/null differ diff --git a/common/manual/admin/img/image029.jpg b/common/manual/admin/img/image029.jpg deleted file mode 100644 index b6b17ff8c..000000000 Binary files a/common/manual/admin/img/image029.jpg and /dev/null differ diff --git a/common/manual/admin/img/image030.png b/common/manual/admin/img/image030.png deleted file mode 100644 index 4a917f4c9..000000000 Binary files a/common/manual/admin/img/image030.png and /dev/null differ diff --git a/common/manual/admin/img/image031.jpg b/common/manual/admin/img/image031.jpg deleted file mode 100644 index 281a9836e..000000000 Binary files a/common/manual/admin/img/image031.jpg and /dev/null differ diff --git a/common/manual/admin/img/image032.jpg b/common/manual/admin/img/image032.jpg deleted file mode 100644 index 230497e42..000000000 Binary files a/common/manual/admin/img/image032.jpg and /dev/null differ diff --git a/common/manual/admin/img/image033.jpg b/common/manual/admin/img/image033.jpg deleted file mode 100644 index 2c09dc077..000000000 Binary files a/common/manual/admin/img/image033.jpg and /dev/null differ diff --git a/common/manual/admin/img/image034.jpg b/common/manual/admin/img/image034.jpg deleted file mode 100644 index d8e0ad8fe..000000000 Binary files a/common/manual/admin/img/image034.jpg and /dev/null differ diff --git a/common/manual/admin/img/image035.jpg b/common/manual/admin/img/image035.jpg deleted file mode 100644 index c9dee384a..000000000 Binary files a/common/manual/admin/img/image035.jpg and /dev/null differ diff --git a/common/manual/admin/img/image036.jpg b/common/manual/admin/img/image036.jpg deleted file mode 100644 index 59291d2cc..000000000 Binary files a/common/manual/admin/img/image036.jpg and /dev/null differ diff --git a/common/manual/admin/img/image037.jpg b/common/manual/admin/img/image037.jpg deleted file mode 100644 index 5afd600f7..000000000 Binary files a/common/manual/admin/img/image037.jpg and /dev/null differ diff --git a/common/manual/admin/img/image038.jpg b/common/manual/admin/img/image038.jpg deleted file mode 100644 index 7b9cbf146..000000000 Binary files a/common/manual/admin/img/image038.jpg and /dev/null differ diff --git a/common/manual/admin/img/image039.jpg b/common/manual/admin/img/image039.jpg deleted file mode 100644 index 842d26fcd..000000000 Binary files a/common/manual/admin/img/image039.jpg and /dev/null differ diff --git a/common/manual/admin/img/image040.jpg b/common/manual/admin/img/image040.jpg deleted file mode 100644 index 4b45af1ad..000000000 Binary files a/common/manual/admin/img/image040.jpg and /dev/null differ diff --git a/common/manual/admin/img/image041.jpg b/common/manual/admin/img/image041.jpg deleted file mode 100644 index 5208722e3..000000000 Binary files a/common/manual/admin/img/image041.jpg and /dev/null differ diff --git a/common/manual/admin/img/image042.jpg b/common/manual/admin/img/image042.jpg deleted file mode 100644 index 9987e8b56..000000000 Binary files a/common/manual/admin/img/image042.jpg and /dev/null differ diff --git a/common/manual/admin/img/image043.jpg b/common/manual/admin/img/image043.jpg deleted file mode 100644 index 88d3bcbbe..000000000 Binary files a/common/manual/admin/img/image043.jpg and /dev/null differ diff --git a/common/manual/admin/img/image044.jpg b/common/manual/admin/img/image044.jpg deleted file mode 100644 index f98b20b0f..000000000 Binary files a/common/manual/admin/img/image044.jpg and /dev/null differ diff --git a/common/manual/admin/img/image045.jpg b/common/manual/admin/img/image045.jpg deleted file mode 100644 index d9f48299a..000000000 Binary files a/common/manual/admin/img/image045.jpg and /dev/null differ diff --git a/common/manual/admin/img/image046.png b/common/manual/admin/img/image046.png deleted file mode 100644 index f5380d07c..000000000 Binary files a/common/manual/admin/img/image046.png and /dev/null differ diff --git a/common/manual/admin/img/image047.png b/common/manual/admin/img/image047.png deleted file mode 100644 index 46cbdca36..000000000 Binary files a/common/manual/admin/img/image047.png and /dev/null differ diff --git a/common/manual/admin/img/image048.jpg b/common/manual/admin/img/image048.jpg deleted file mode 100644 index 6b03733e8..000000000 Binary files a/common/manual/admin/img/image048.jpg and /dev/null differ diff --git a/common/manual/admin/img/image049.jpg b/common/manual/admin/img/image049.jpg deleted file mode 100644 index 6af34b06f..000000000 Binary files a/common/manual/admin/img/image049.jpg and /dev/null differ diff --git a/common/manual/admin/img/image050.jpg b/common/manual/admin/img/image050.jpg deleted file mode 100644 index e9b893e4d..000000000 Binary files a/common/manual/admin/img/image050.jpg and /dev/null differ diff --git a/common/manual/admin/img/image051.jpg b/common/manual/admin/img/image051.jpg deleted file mode 100644 index 89704552d..000000000 Binary files a/common/manual/admin/img/image051.jpg and /dev/null differ diff --git a/common/manual/admin/img/image052.png b/common/manual/admin/img/image052.png deleted file mode 100644 index ab6953b2f..000000000 Binary files a/common/manual/admin/img/image052.png and /dev/null differ diff --git a/common/manual/admin/img/image053.jpg b/common/manual/admin/img/image053.jpg deleted file mode 100644 index eb70c9558..000000000 Binary files a/common/manual/admin/img/image053.jpg and /dev/null differ diff --git a/common/manual/admin/img/image054.jpg b/common/manual/admin/img/image054.jpg deleted file mode 100644 index a81c4199b..000000000 Binary files a/common/manual/admin/img/image054.jpg and /dev/null differ diff --git a/common/manual/admin/img/image055.jpg b/common/manual/admin/img/image055.jpg deleted file mode 100644 index 7ac0b11ac..000000000 Binary files a/common/manual/admin/img/image055.jpg and /dev/null differ diff --git a/common/manual/admin/img/image056.jpg b/common/manual/admin/img/image056.jpg deleted file mode 100644 index 10df87d15..000000000 Binary files a/common/manual/admin/img/image056.jpg and /dev/null differ diff --git a/common/manual/admin/img/image057.jpg b/common/manual/admin/img/image057.jpg deleted file mode 100644 index 64161dce2..000000000 Binary files a/common/manual/admin/img/image057.jpg and /dev/null differ diff --git a/common/manual/admin/img/image058.jpg b/common/manual/admin/img/image058.jpg deleted file mode 100644 index 03de6d96b..000000000 Binary files a/common/manual/admin/img/image058.jpg and /dev/null differ diff --git a/common/manual/admin/img/image059.jpg b/common/manual/admin/img/image059.jpg deleted file mode 100644 index ed54b5a07..000000000 Binary files a/common/manual/admin/img/image059.jpg and /dev/null differ diff --git a/common/manual/admin/img/image060.jpg b/common/manual/admin/img/image060.jpg deleted file mode 100644 index edb2abd3e..000000000 Binary files a/common/manual/admin/img/image060.jpg and /dev/null differ diff --git a/common/manual/admin/img/image061.png b/common/manual/admin/img/image061.png deleted file mode 100644 index 2c3153835..000000000 Binary files a/common/manual/admin/img/image061.png and /dev/null differ diff --git a/common/manual/admin/img/image062.png b/common/manual/admin/img/image062.png deleted file mode 100644 index a4a71d08f..000000000 Binary files a/common/manual/admin/img/image062.png and /dev/null differ diff --git a/common/manual/admin/img/image063.png b/common/manual/admin/img/image063.png deleted file mode 100644 index 6985914ed..000000000 Binary files a/common/manual/admin/img/image063.png and /dev/null differ diff --git a/common/manual/admin/img/install/complete_install.png b/common/manual/admin/img/install/complete_install.png deleted file mode 100644 index fa4119fd7..000000000 Binary files a/common/manual/admin/img/install/complete_install.png and /dev/null differ diff --git a/common/manual/admin/img/install/db_select.png b/common/manual/admin/img/install/db_select.png deleted file mode 100644 index 44efabe2b..000000000 Binary files a/common/manual/admin/img/install/db_select.png and /dev/null differ diff --git a/common/manual/admin/img/install/environment_setting.png b/common/manual/admin/img/install/environment_setting.png deleted file mode 100644 index dd3c28369..000000000 Binary files a/common/manual/admin/img/install/environment_setting.png and /dev/null differ diff --git a/common/manual/admin/img/install/insert_admin_info.png b/common/manual/admin/img/install/insert_admin_info.png deleted file mode 100644 index ed6f9a3a5..000000000 Binary files a/common/manual/admin/img/install/insert_admin_info.png and /dev/null differ diff --git a/common/manual/admin/img/install/insert_db_info.png b/common/manual/admin/img/install/insert_db_info.png deleted file mode 100644 index b9bf66727..000000000 Binary files a/common/manual/admin/img/install/insert_db_info.png and /dev/null differ diff --git a/common/manual/admin/img/install/install_condition_check.png b/common/manual/admin/img/install/install_condition_check.png deleted file mode 100644 index 7c73b7a90..000000000 Binary files a/common/manual/admin/img/install/install_condition_check.png and /dev/null differ diff --git a/common/manual/admin/img/install/install_condition_check_error.png b/common/manual/admin/img/install/install_condition_check_error.png deleted file mode 100644 index defa66b85..000000000 Binary files a/common/manual/admin/img/install/install_condition_check_error.png and /dev/null differ diff --git a/common/manual/admin/img/install/language_select.png b/common/manual/admin/img/install/language_select.png deleted file mode 100644 index d0704d9ad..000000000 Binary files a/common/manual/admin/img/install/language_select.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/add_home.png b/common/manual/admin/img/make_general_site/add_home.png deleted file mode 100644 index 6690463bd..000000000 Binary files a/common/manual/admin/img/make_general_site/add_home.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/board_install.png b/common/manual/admin/img/make_general_site/board_install.png deleted file mode 100644 index 1c5df0500..000000000 Binary files a/common/manual/admin/img/make_general_site/board_install.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/change_start_page.png b/common/manual/admin/img/make_general_site/change_start_page.png deleted file mode 100644 index b67063791..000000000 Binary files a/common/manual/admin/img/make_general_site/change_start_page.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/default_layout_setting.png b/common/manual/admin/img/make_general_site/default_layout_setting.png deleted file mode 100644 index 9492149e2..000000000 Binary files a/common/manual/admin/img/make_general_site/default_layout_setting.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/delete_menu1.png b/common/manual/admin/img/make_general_site/delete_menu1.png deleted file mode 100644 index c5b74a6bd..000000000 Binary files a/common/manual/admin/img/make_general_site/delete_menu1.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/ftp_password_confirm.png b/common/manual/admin/img/make_general_site/ftp_password_confirm.png deleted file mode 100644 index 8debe9de7..000000000 Binary files a/common/manual/admin/img/make_general_site/ftp_password_confirm.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/home_page1.png b/common/manual/admin/img/make_general_site/home_page1.png deleted file mode 100644 index 0b4ed1c33..000000000 Binary files a/common/manual/admin/img/make_general_site/home_page1.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/home_page2.png b/common/manual/admin/img/make_general_site/home_page2.png deleted file mode 100644 index d7a3f3be4..000000000 Binary files a/common/manual/admin/img/make_general_site/home_page2.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/home_page3.png b/common/manual/admin/img/make_general_site/home_page3.png deleted file mode 100644 index 747295876..000000000 Binary files a/common/manual/admin/img/make_general_site/home_page3.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/home_page4.png b/common/manual/admin/img/make_general_site/home_page4.png deleted file mode 100644 index aa4043081..000000000 Binary files a/common/manual/admin/img/make_general_site/home_page4.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/home_page5.png b/common/manual/admin/img/make_general_site/home_page5.png deleted file mode 100644 index 155c98a5f..000000000 Binary files a/common/manual/admin/img/make_general_site/home_page5.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/home_page6.png b/common/manual/admin/img/make_general_site/home_page6.png deleted file mode 100644 index 2105c0021..000000000 Binary files a/common/manual/admin/img/make_general_site/home_page6.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/home_page7.png b/common/manual/admin/img/make_general_site/home_page7.png deleted file mode 100644 index 0fcd7265d..000000000 Binary files a/common/manual/admin/img/make_general_site/home_page7.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/home_page8.png b/common/manual/admin/img/make_general_site/home_page8.png deleted file mode 100644 index 79f04e994..000000000 Binary files a/common/manual/admin/img/make_general_site/home_page8.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/home_page_completed.png b/common/manual/admin/img/make_general_site/home_page_completed.png deleted file mode 100644 index 1347d8764..000000000 Binary files a/common/manual/admin/img/make_general_site/home_page_completed.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/menu_delete_confirm.png b/common/manual/admin/img/make_general_site/menu_delete_confirm.png deleted file mode 100644 index e830722c8..000000000 Binary files a/common/manual/admin/img/make_general_site/menu_delete_confirm.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/notice01_add.png b/common/manual/admin/img/make_general_site/notice01_add.png deleted file mode 100644 index f039b2bdf..000000000 Binary files a/common/manual/admin/img/make_general_site/notice01_add.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/other_mentype_install.png b/common/manual/admin/img/make_general_site/other_mentype_install.png deleted file mode 100644 index 6b5c74b77..000000000 Binary files a/common/manual/admin/img/make_general_site/other_mentype_install.png and /dev/null differ diff --git a/common/manual/admin/img/make_general_site/progress.png b/common/manual/admin/img/make_general_site/progress.png deleted file mode 100644 index 76e7f6970..000000000 Binary files a/common/manual/admin/img/make_general_site/progress.png and /dev/null differ diff --git a/common/manual/admin/index.html b/common/manual/admin/index.html deleted file mode 100644 index 3939811b8..000000000 --- a/common/manual/admin/index.html +++ /dev/null @@ -1,1683 +0,0 @@ - - - - - - -XE Admin Help - - - - - - -
    -

    메뉴건너뛰기

    -
    -

    XE Admin Help

    -
    -
    -
    - -
    - -
    -

    XE 소개

    -
    -

    XE란 무엇인가?

    -

    XE는 'eXpress'와 'Engine'이라는 두 단어를 합쳐 만든 이름으로, '사람들이 자신의 생각이나 느낌을 표현할 수 있도록 도와주는 장치'라는 의미를 담았습니다.

    -

    XE는 서버 컴퓨터에 설치해서 쓰는 웹 사이트 제작 프로그램입니다. 웹 사이트를 만들기 위해서는 HTML, CSS, PHP, SQL 등과 같은 프로그래밍 언어를 기본적으로 알아야 합니다. 하지만 XE를 사용하면 프로그래밍 언어를 잘 모르더라도 웹 사이트를 쉽게 만들 수 있습니다.

    -

    XE는 XE core라는 핵심 프로그램을 기반으로 다양한 추가 기능을 조합하여 사용자가 원하는 웹 사이트를 제작할 수 있습니다.

    -
    - XE 개요 -
    XE 개요
    -
    -
    참고 -

    XE에 관한 자세한 정보는 XE 공식 사이트를 참조하십시오.

    -

    https://www.xpressengine.com

    -
    -
    -
    -

    XE 기능 및 특징

    -

    XE의 기능 및 특징은 다음과 같습니다.

    -

    손쉬운 사이트 구축

    -

    XE는 Textyle(블로그형), CafeXE(카페형), PlanetXE(마이크로 블로그형) 등 다양한 모듈을 제공합니다. 사용자는 만들고자 하는 사이트에 적합한 모듈을 선택하여 편리하게 사이트를 구축할 수 있습니다.

    -

    모듈형 구조

    -

    XE에서 모듈은 하나의 프로그램을 의미합니다. XE는 기능의 제작과 추가, 사용이 쉽도록 레고 블록과 같은 모듈 구조로 제작되었습니다. 사용자는 XE에서 제공하는 기본 모듈과 커뮤니티를 통해 공유되는 확장 기능을 자유롭게 조합하여 다양한 웹 사이트를 제작할 수 있습니다. 개발자는 XE에 추가할 수 있는 새로운 기능의 모듈을 쉽게 개발하고 커뮤니티를 통해 공유할 수 있습니다.

    -

    오픈 커뮤니티

    -

    XE는 오픈 커뮤니티를 통해 다양한 정보를 제공합니다. XE 커뮤니티에는 제로보드 시절부터 사용해 온 사용자와 자유/오픈 소스 프로젝트 멤버가 많습니다. 사용자는 커뮤니티 내에서 원하는 정보를 찾거나, 다른 사용자들에게 자유롭게 문의할 수 있습니다.

    -

    다국어 지원

    -

    XE는 여러 나라의 언어를 지원합니다. 사용자는 웹 사이트를 언어별로 분리하지 않고도 한국어뿐 아니라 영어, 일본어, 중국어, 러시아어 등의 웹 사이트를 쉽게 제작할 수 있습니다.

    -
    -
    -

    용어 정리

    -
    -
    APMsetup
    -
    XE를 설치하는 데 필요한 구성 요소인 아파치 웹 서버, PHP, MySQL 데이터베이스를 한 번에 설치하고, 사용에 필요한 연동 설정을 자동으로 해 주는 프로그램. 공식 사이트는 http://www.apmsetup.com/입니다.
    -
    FileZilla
    -
    무료 FTP(File Transfer Protocol) 접속 프로그램. 공식 사이트는 https://filezilla-project.org/입니다.
    -
    mod_rewrite
    -
    URL을 기억하기 쉽게 줄여 주는 기능. 예를 들어, http://example.com/index.php?module=admin을 http://example.com/admin과 같이 줄여 쓸 수 있습니다. 웹 서버에서 해당 기능을 지원해야 사용할 수 있습니다.
    -
    PuTTY
    -
    텔넷(telnet)이나 SSH(Secure Shell) 프로토콜을 지원하는 원격 접속 프로그램. 공식 사이트는 http://www.putty.nl/이며, 한글 버전은 https://www.kldp.net/projects/iputty/download에서 다운로드할 수 있습니다.
    -
    WPI
    -
    Web Platform Installer의 약어. 마이크로소프트 사에서 웹 플랫폼 제품을 편리하게 사용할 수 있도록 만든 도구이며, 공식 사이트는 https://www.microsoft.com/web/입니다.
    -
    XE core
    -
    XE의 설치와 운영을 담당하는 핵심 프로그램. XE core가 있어야 모듈, 레이아웃, 스킨 등의 추가 기능을 설치하고 실행할 수 있습니다.
    -
    XE 추가 기능
    -
    사용자가 사이트를 더 편리하게 운영하도록 XE core에 추가할 수 있는 구성 요소. XE 추가 기능에는 모듈, 애드온, 위젯, 스킨, 위젯 스타일, 레이아웃이 있습니다.
    -
    XE
    -
    XpressEngine의 약어. 서버 컴퓨터에 설치해서 쓰는 오픈 소스 웹 사이트 제작 프로그램이며, 공식 사이트는 https://www.xpressengine.com/입니다.
    -
    가상 사이트
    -
    XE에서 만들어진 웹 페이지를 XE의 기본 사이트와 다른 별개의 사이트처럼 사용할 수 있는 기능.
    -
    레이아웃
    -
    사이트에 설치한 추가 기능의 배치를 담당하는 구성 요소.
    -
    모듈
    -
    XE에 추가해서 사용할 수 있는 하나의 프로그램.
    -
    쉬운 설치
    -
    XE에서 모듈, 스킨 등의 추가 기능을 설치할 때 XE 공식 사이트에서 소스를 다운로드해서 서버에 업로드할 필요 없이 사이트에서 XE 공식 사이트와 연동하여 선택한 추가 기능을 설치할 수 있는 기능.
    -
    스킨
    -
    사이트에 설치된 프로그램의 디자인.
    -
    애드온
    -
    모듈 기능의 동작 사이에 끼어들어 자신의 기능을 수행하는 작은 프로그램.
    -
    위젯 스타일
    -
    위젯의 외관을 꾸미는 구성 요소.
    -
    위젯
    -
    레이아웃이나 페이지 모듈에 삽입되어 동작하는 구성 요소.
    -
    제로보드
    -
    1999년 개발된 게시판 소프트웨어. 제로보드 XE를 거쳐 현재의 XE로 발전되었습니다.
    -
    사이트맵
    -
    각 메뉴를 그룹핑하여 모아놓은 것으로 사이트맵을 사이트의 상단, 좌측, 우측, 하단 등에 배치하여 사용할 수 있습니다.
    -
    -
    -
    -
    -

    설치 및 제거

    -
    -

    설치 전 준비

    -

    XE는 설치형 웹 응용프로그램입니다. XE를 사용하여 사이트를 만들기 위해서는 XE가 설치될 웹 서버가 필요합니다. XE를 설치할 서버의 공간을 확보하는 방법에는 여러 가지가 있지만, 크게 나누어 직접 서버로 사용할 컴퓨터를 확보하는 방법과 비용을 지불하고 웹 호스팅 업체가 제공하는 웹 서버의 공간 일부를 임대하는 방법이 있습니다.

    -
    -

    설치 프로그램 목록

    -

    웹 서버가 구축된 환경에서 XE 설치를 위해 필요한 프로그램 목록은 다음과 같습니다. WPI(Microsoft Web Platform Installer)나 APMsetup을 사용해서 XE를 설치할 경우에는 아래 프로그램이 자동으로 설치됩니다. 그렇지 않은 경우에는 필요한 프로그램과 라이브러리를 미리 확인하여 설치해야 합니다.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - 설치 프로그램 목록 -
    프로그램필수/선택
    PHPPHP 5.3 이상필수
    PHP 5.5 이상권장
    PHP 라이브러리XML 라이브러리필수
    GD 라이브러리필수
    ICONV필수
    DBMS(Database Management System) - CUBRID, MySQL 4.1 이상, MS-SQL - 택1
    -
    -
    -

    XE core 설치 파일 다운로드

    -

    XE를 사용하여 사이트를 생성하려면 XE core를 설치해야 합니다. XE core는 XE의 설치와 운영을 담당하는 핵심 프로그램입니다. XE core에는 사이트 관리에 사용되는 기능이 없습니다. 하지만 XE core가 있어야 사용자가 추가 기능(모듈, 레이아웃, 스킨 등)을 설치하고 실행할 수 있습니다.

    -

    최신 XE core 설치 파일은 https://www.xpressengine.com/index.php?mid=download&package_srl=18325662에서 무료로 다운로드할 수 있습니다.

    -
    참고 -

    Windows 환경에서 WPI를 사용해 XE를 설치할 때는 XE core 설치 파일을 다운로드할 필요가 없습니다.

    -
    -

    다운로드 받은 XE core 설치 파일의 압축을 해제한 후 서버에 업로드하려면 zip 파일을, 압축 파일을 서버에 업로드한 후 압축을 해제하려면 tgz 파일을 다운로드합니다. 각 형식의 파일 업로드 방식은 "XE core 설치 파일 형식별 업로드 방법"을 참조하십시오.

    -
    -
    -
    -

    서버 환경 설정

    -

    XE는 서버 OS 종류에 상관없이 "설치 프로그램 목록"이 설치된 모든 환경에서 설치할 수 있습니다. 사용자는 XE를 설치하기 전에 필요한 웹 서버 환경을 구축해야 합니다.

    -

    Windows 환경에서는 WPI나 APMsetup 중 하나를 선택해서 필요한 설치 프로그램과 XE를 함께 설치할 수 있습니다. 자세한 내용은 "Windows 환경 설정"을 참조하십시오.

    -

    Linux 환경에서는 XE를 설치하기 전에 "설치 프로그램 목록"의 프로그램을 수동으로 설치해야 합니다. 각 프로그램의 자세한 설치 과정은 이 문서에서 설명하지 않습니다. Linux 환경에서 계정을 설정하거나 원격으로 서버에 접속하는 방법, XE core 설치 파일을 업로드하는 방법은 "Linux 환경 설정"을 참조하십시오.

    -
    -
    -

    XE core 설치

    -

    XE core를 설치하는 과정은 다음과 같습니다.

    -
      -
    1. 웹 브라우저를 통해 XE core 설치 파일을 업로드한 경로(www.example.com 또는 www.example.com/xe)로 접근합니다.
    2. -
    3. 다음과 같이 사용할 언어를 선택하는 화면에서 원하는 언어를 선택하시고 '다음' 버튼을 누릅니다. -
      설치 언어 선택
      -
      참고 -

      페이지에 접근은 되지만 이미지가 제대로 보이지 않거나 내용이 비어 있으면, XE core 설치 파일을 다시 업로드해야 합니다.

      -
      -
    4. -
    5. 필수 설치 조건이 모두 가능으로 표시된 것을 확인하고 '설치를 진행합니다'를 클릭합니다. -

      이 화면에서 '자세히'를 클릭하면 XE core를 설치할 때 최소 PHP 버전과 필수 라이브러리 설치 여부를 자동으로 확인할 수 있습니다. 필수 설치 조건에 가능으로 표시되지 않은 항목이 있으면 오류 메시지를 확인하여 해결합니다.

      -

      짧은 주소를 사용할 수 없을 경우 경고창이 나타납니다. 짧은 주소를 사용하길 원치 않을 경우에는 그대로 설치를 진행합니다.

      -
      설치 조건 확인
      -
      참고 -

      파일 권한 설정 오류 때문에 퍼미션이 불가능으로 표시될 때는 "XE 설치 시 권한 설정 누락 오류"를 참조하십시오.

      -
      -
    6. -
    7. XE에서 사용할 DBMS를 선택하고 아래의 설치를 진행합니다를 클릭합니다. 이 문서에서는 mysqli를 선택합니다. -
      DB 선택
      -
      참고 -

      XE에서 사용 가능한 DBMS가 없으면 모든 항목이 비활성화됩니다. 이때는 사용할 DBMS를 직접 설치하거나, 호스팅 업체에 설치를 요청합니다.

      -
      -
    8. -
    9. 다음과 같이 DB 정보를 입력하고, 다음을 클릭합니다. 추가적인 설정의 변경이 필요할 경우에는 '고급 설정'을 클릭해서 수정할 수 있습니다. -
      DB 정보 입력
      -
      참고 -

      DB 정보를 입력할 때 문제가 발생하면, "DB 계정 정보 오류"를 참조하십시오.

      -
      -
    10. -
    11. 사이트 표준 시간대를 설정한 후 다음을 클릭합니다.
    12. -
      환경 설정
      -
    13. 관리자 정보를 입력합니다. XE 1.5부터는 이메일 주소가 로그인 계정이므로 실제 관리자가 사용할 이메일 주소를 입력하시기 바랍니다. -
      관리자 정보 입력
      -
    14. -
    15. 설치가 완료되면 다음과 같이 XE Home(시작 페이지)이 나타납니다. -
      XE 초기 페이지
      -
    16. -
    -
    -
    -

    제거

    -

    XE를 더 이상 사용하지 않는다면 XE가 설치되어 있는 폴더의 하위 내용을 모두 삭제합니다.

    -

    XE를 사용해서 제작한 사이트를 운영하는 데 사용된 모든 데이터는 DB에 저장됩니다. 데이터를 모두 삭제하려면 사이트 운영에 사용된 모든 DB 테이블을 삭제합니다. XE를 재설치하거나 서버를 이전할 때는 데이터를 이관하여 재사용할 수 있습니다.

    -

    자세한 데이터 삭제 및 이관 방법은 사이트 운영에 사용한 DBMS의 사용법을 참조하십시오.

    -
    -
    -
    -

    XE core 둘러보기

    -
    -

    관리자 페이지 시작

    -

    다음과 같이 XE 관리자 페이지를 열고 관리자 계정 정보를 입력하여 로그인합니다. 아래 주소에서 'example.com'은 XE가 설치된 도메인 주소를 의미합니다.

    -
    -
    짧은 주소(mod_rewrite)를 사용할 경우: -
    http://example.com/admin
    -
    짧은 주소(mod_rewrite)를 사용하지 않는 경우: -
    http://example.com/index.php?module=admin
    -
    -
    XE 관리자 페이지 -
    XE 관리자 페이지
    -
    -
    -
    -

    XE 관리자 메뉴

    -

    이 절에서는 관리자가 사용 가능한 기본 메뉴를 설명합니다.

    -
    -

    대시보드

    -

    XE 관리자 홈입니다. 통계 및 사이트 현황, 최근 글, 댓글, 엮인글, 공지 등을 보여 줍니다.

    -
    -
    -

    사이트 제작/편집

    -

    사이트 메뉴 편집

    -

    사이트에서 사용되는 메뉴를 타입별로 쉽게 생성, 수정, 삭제할 수 있게 도와줍니다. 기본적으로 설치가 되지 않은 메뉴 타입이 있을 경우에는 손쉽게 설치할 수 있습니다. 또한 메뉴의 디자인 및 설정 정보도 손쉽게 수정이 가능합니다. 디자인 정보를 별도로 설정하지 않는다면 '사이트 디자인 설정'에서 설정한 내용이 적용 됩니다.

    -

    사이트 디자인 설정

    -

    사이트에서 사용되는 기본 디자인 설정을 할 수 있도록 도와 줍니다. 기본적으로 제공하는 디자인 설정 뿐 아니라 직접 html, css를 수정할 수 도 있습니다. 이곳에서 수정한 내용은 각 메뉴에서 별도로 설정하지 않는이상 모두 적용 됩니다.

    -
    -
    -

    회원

    -
    -
    회원 목록
    -
    사이트에 가입된 사용자 목록을 보여줍니다. 사용자의 소속 그룹을 변경하거나, 로그인 차단 등 사용자 정보를 확인, 수정, 삭제할 수 있습니다.
    -
    회원 설정
    -
    사이트 회원 가입 허가, 회원 가입 시 입력 양식 등 회원 관리에 필요한 다양한 설정을 할 수 있습니다.
    -
    회원 그룹
    -
    - 사이트에서 사용하는 회원 그룹을 관리합니다. 새로운 그룹을 생성하거나, 기존 그룹을 수정, 삭제할 수 있습니다. -
    - 참고 -

    회원 그룹 내 '관리그룹'과 '관리자'의 차이는 "관리그룹, 관리자"를 참고하시기 바랍니다.

    -
    -
    -
    포인트
    -
    회원이 글, 댓글을 작성하거나 업로드, 다운로드할 때 포인트를 부여할 수 있습니다. 또한 그룹의 레벨을 설정하여 포인트를 통한 레벨 업그레이드 기능을 설정할 수 있습니다.
    -
    -
    -
    -

    콘텐츠

    -
    -
    문서
    -
    사이트에 등록된 문서를 관리합니다. 문서 내용을 확인하고 삭제할 수 있으며, 회원이 신고, 삭제한 문서를 확인할 수 있습니다.
    -
    댓글
    -
    사이트에 등록된 댓글을 관리합니다. 댓글 내용을 확인하고 삭제할 수 있으며, 신고된 댓글을 확인할 수 있습니다.
    -
    엮인글
    -
    외부에서 링크했거나 엮인글의 목록을 볼 수 있습니다. 엮인글의 허용 여부를 선택할 수 있으며, 엮인글을 허용하지 않으면 글을 엮을 수 없고 링크하더라도 표시되지 않습니다.
    -
    파일
    -
    사이트에 등록된 글과 댓글에 첨부된 파일을 관리합니다. 등록된 파일을 삭제할 수 있습니다.
    -
    설문
    -
    사이트에 등록된 설문 콘텐츠를 관리합니다.
    -
    RSS
    -
    XE를 통해 생성된 다양한 모듈의 RSS(Rich Site Summary) 피드를 하나로 묶어서 제공할 수 있습니다. 기본값은 통합피드 사용입니다. 사이트 초기 화면을 통해 통합 피드가 제공되며, 피드 공개가 허용되지 않은 개별 모듈은 피드 목록에서 제외됩니다. 일부 모듈은 피드 공개의 기본값이 공개하지 않음으로 되어 있으므로, 모든 피드를 공개하려면 반드시 개별 모듈의 추가 설정 메뉴에서 피드 공개 항목이 전문 공개 또는 요약 공개로 되어 있는지 확인해야 합니다.
    -
    다국어
    -
    - XE는 글로벌 사이트를 별도로 생성하지 않고 하나의 사이트에서 다국어를 지원합니다. 다국어에 추가한 단어/문장에 연동된 목록은 사이트 언어 설정을 변경하면 자동으로 해당 언어의 내용으로 변환되어 표시됩니다. 다국어 메뉴는 사이트에 사용된 다국어 목록을 관리합니다. 등록된 다국어 목록을 확인할 수 있으며, 새로운 단어 또는 문장을 추가할 수 있습니다. -
    - 참고 -

    다국어의 자세한 사용법은 FAQ의 "다국어"를 참고하시기 바랍니다.

    -
    -
    -
    데이터 들여오기
    -
    - 제로보드4, zb5beta 또는 다른 프로그램의 데이터를 XE 데이터로 이전할 수 있습니다. -
    - 참고 -

    데이터 들여오기의 자세한 사용법은 FAQ의 "데이터 들여오기"를 참고하시기 바랍니다.

    -
    -
    -
    휴지통
    -
    문서나 댓글을 삭제하면 DB에서 바로 제거하지 않고 휴지통으로 이동합니다. 관리자가 내용을 다시 확인한 후 삭제된 문서나 댓글을 복구하거나 완전히 삭제할 수 있습니다.
    -
    스팸필터
    -
    글, 댓글 등이 등록될 때 스팸 여부를 확인하여 등록을 금지할 수 있습니다. 스팸필터 관리 메뉴에서 금지 IP와 금지 단어 목록을 설정할 수 있습니다.
    -
    -
    -
    -

    즐겨찾기

    -

    '고급 > 설치된 모듈'에서 자주 사용하는 모듈의 별 모양을 클릭하면 즐겨찾기에 추가할 수 있습니다. 추가 된 즐겨찾기는 '즐겨찾기' 메뉴에 노출됩니다.

    -
    -
    -

    설정

    -
    -
    일반
    -
    -

    사이트 시작 화면을 결정하는 기본 모듈 설정, 기본 언어 등 사이트를 운영하기 위해 필요한 기본 설정을 할 수 있습니다. 또한, 보안을 위한 관리자 페이지 접근 가능 IP 대역 지정 등 다양한 고급 설정이 가능합니다.

    -
      -
    • 사이트 제목: XE Core 1.7 이상에서 새롭게 추가된 값입니다. 레이아웃에서 {Context::getSiteTitle()} 변수로 표시할 수 있습니다. default 레이아웃에 적용되어 있습니다.
    • -
    • 홈페이지: 사이트 접속 시 기본으로 호출될 페이지 지정할 수 있습니다.
    • -
    • 모바일 뷰 사용: 모바일 기기로 접속시 모바일 페이지를 보여줍니다.
    • -
    • 관리자 IP대역: 관리자 페이지로 접근가능한 IP대역을 지정합니다. 해당 IP에 대해서만 관리자 페이지로 접근이 가능하므로 주의 바랍니다. IP대역 정보는 /files/config/db.config.php 파일에 저장됩니다. 여러개의 항목은 줄을 바꾸어 입력하세요.
    • -
    • 기본 URL: 여러 사이트를 운영할 때 기본 URL이 필요합니다. XE 설치 경로를 포함한 URL을 입력하세요. (예: http://도메인/설치경로)
    • -
    • SSL(Secure Socket Layer) 사용: '선택적으로'는 회원가입, 정보수정 등의 지정된 동작(action)에서 보안접속(SSL)을 사용합니다. '항상 사용'은 모든 서비스에 SSL을 사용 합니다. SSL 환경이 갖춰지지 않은 상태에서 SSL을 사용할 경우 접속이 되지 않을 수 있으니 주의 바랍니다. -
      - 참고 -

      SSL 은 서버와 클라이언트 사이에 보안통신을 하기 위한 규격입니다. 페이지가 클라이언트에 전달되는 중에 제3자에 의해서 내용이 변조되는 것을 어렵게 하고, 제3자가 훔쳐보는 것을 어렵게 합니다. 인증서 종류에 따라 서버 운영 주체에 대한 인증이 포함되기도 합니다. SSL 사용을 위해서는 서버에 SSL 인증서가 설치되어 있어야 합니다.

      -

      SSL 을 사용하는 페이지에 SSL 전송을 지원하지 않는 일반 HTTP 컨텐츠가 포함되어 있을 경우, 페이지가 변조될 가능성이 있기 때문에 '안전하지 않은 페이지' 경고가 뜰 수 있습니다. SSL '선택적으로' 사용을 할 경우 SSL 연결이 아닌 페이지가 변조되어서 SSL 으로 전송되어야 할 정보가 SSL 이 아닌 일반 HTTP 전송 양식으로 전송되거나 제3자에 의해서 탈취될 가능성이 있습니다.

      -
      -
    • -
    • SSO 사용: 사용자가 한 번만 로그인하면 기본 사이트와 가상 사이트에 동시에 로그인이 됩니다. 가상 사이트를 사용할 때만 필요합니다.
    • -
    • 인증 세션 DB 사용: 인증 시 사용되는 PHP 세션을 DB로 사용하는 기능입니다. 웹서버의 사용률이 낮은 사이트에서는 비활성화시 사이트 응답 속도가 향상될 수 있습니다. 단, 현재 접속자를 구할 수 없어 관련된 기능을 사용할 수 없게 됩니다.
    • -
    • Qmail 호환: Qmail등 CRLF를 줄 구분자로 인식하지 못하는 MTA에서 메일이 발송되도록 합니다.
    • -
    • 사이트 잠금: 지정한 IP 외 접근을 차단할 수 있습니다.
    • -
    • 접근 허용 IP: 이곳에 관리자의 IP가 반드시 포함되어야 합니다. 만약 접근이 차단된 경우 './files/config/db.config.php' 파일에서 `'use_sitelock' => 'Y'`를 `'use_sitelock' => 'N'`으로 변경하여 차단을 해제할 수 있습니다.
    • -
    -
    -
    FTP 설정
    -
    쉬운 설치 사용을 위한 FTP 계정을 설정합니다.
    -
    관리자 설정
    -
    관리자 화면의 제목과 로고, 메뉴를 설정할 수 있습니다.
    -
    파일 업로드 -
    -

    사이트에 등록할 수 있는 파일의 종류와 크기 등을 설정할 수 있습니다.

    -
      - -
    • 파일 크기 제한: 하나의 파일에 대해 최고 용량을 지정할 수 있습니다.(관리자는 제외)
    • -
    • 문서 첨부 제한: 하나의 문서에 첨부할 수 있는 최고 용량을 지정할 수 있습니다.(관리자는 제외)
    • -
    -
    - -
    파일박스
    -
    파일박스를 관리할 수 있습니다. 파일박스는 관리자가 재사용할 수 있는 이미지 파일을 관리하는 기능입니다. 회원 그룹 아이콘을 등록하면 이미지 파일은 파일박스에 업로드됩니다.
    -
    -
    -
    -

    embed Filter

    -

    <iframe> 또는 <object>, <embed> 태그에 허용 할 URL을 지정할 수 있습니다.
    주로 domain을 포함한 URL을 지정하여 허용 URL을 지정할 수 있습니다.

    -

    domain을 포함하지 않은 짧거나 단순한 단어('video', 'swf' 등)만을 지정할 경우 손쉽게 악의적인 접근을 시도할 수 있으니 주의해야 합니다.

    -
    -
    iFrame
    -
    -

    <iframe> 태그에 허용 할 URL을 지정할 수 있습니다.

    -

    예시 : 'http://www.youtube.com/v/...'와 같은 URL을 <iframe>에 허용 하려면 'http://www.youtube.com/v/'처럼 입력하면 됩니다.

    -
    -
    object / embed
    -
    -

    <object>, <embed> 태그에 허용 할 URL을 지정할 수 있습니다.

    -

    주로 domain을 포함한 URL을 지정하여 허용 URL을 지정할 수 있습니다.
    예시 : 'http://www.youtube.com/v/...'와 같은 URL을 <object>, <embed>에 허용 하려면 'http://www.youtube.com/v/'처럼 입력하면 됩니다.

    -
    -
    -
    -
    -

    고급

    -
    -
    쉬운 설치
    -
    모듈, 스킨, 레이아웃, 위젯 등을 추가로 설치할 때, XE 공식 사이트에서 해당 소스를 다운로드해서 서버에 업로드할 필요 없이 사이트에서 XE 공식 사이트와 연동하여 선택한 추가 기능을 바로 설치합니다.
    -
    설치된 레이아웃
    -
    사이트에 설치된 레이아웃을 관리합니다. 각 레이아웃의 관리자 화면을 통해 인스턴스를 추가, 수정, 삭제할 수 있습니다.
    -
    설치된 모듈
    -
    사이트에 설치된 모듈을 출력합니다. 각 모듈의 관리자 화면에 접근하여 모듈을 관리할 수 있습니다. 목록의 즐겨찾기 버튼을 이용해서 자주 사용하는 모듈 관리자 링크를 화면 오른쪽 위에 즐겨찾기로 추가할 수 있습니다.
    -
    설치된 위젯
    -
    사이트에 설치된 위젯을 출력합니다. 각 위젯의 코드를 생성할 수 있습니다.
    -
    설치된 애드온
    -
    사이트에 설치된 애드온을 출력합니다. 각 애드온을 PC와 모바일 환경에서 사용하거나 사용하지 않도록 설정할 수 있습니다. -
    - 참고 -

    1.5 버전부터는 쉬운 설치를 통해 설치된 레이아웃과 모듈, 위젯, 애드온을 '확장기능(v1.7에서는 고급) > 설치된 레이아웃, 설치된 모듈, 설치된 위젯, 설치된 애드온' 관리자 화면에서 삭제할 수 있습니다.

    -
    -
    -
    에디터
    -
    사이트의 기본 위지윅 에디터 설정과 확장 기능인 에디터 컴포넌트를 관리할 수 있습니다.
    -
    -
    -
    -
    -
    -

    XE 추가 기능

    -
    -

    XE 추가 기능의 종류

    -

    XE의 가장 큰 장점은 사용자가 원하는 다양한 기능을 추가하여 사이트를 좀 더 편리하게 운영할 수 있다는 것입니다. 다음과 같은 XE 추가 기능을 사용할 수 있습니다. 각 추가 기능의 설치 방법은 "추가 기능 설치 방법"을 참조하십시오.

    -

    모듈

    -

    XE에서 모듈은 하나의 프로그램을 의미합니다. 여러 개의 모듈이 모여서 하나의 큰 모듈을 구성하기도 하고, 모듈이 개별적으로 동작하기도 합니다. 즉, 모듈은 사이트에 특정 기능을 구현하기 위해 추가로 설치한 프로그램입니다.

    -

    XE에서 제공하는 대표적인 모듈에는 게시판, CafeXE, Textyle 등이 있습니다.

    -
    - 모듈 -
    모듈
    -
    -

    애드온

    -

    애드온은 모듈의 기능이 동작하는 사이사이에 끼어들어 자신의 기능을 수행하는 작은 프로그램입니다. 애드온은 모듈과 같이 스스로 기능을 수행하기는 하지만, 기능 수행 결과를 외부로 제공하지는 못한다는 점에서 모듈과 다릅니다.

    -

    XE에서 제공하고 있는 대표적인 애드온에는 기본 카운터, 모바일 XE 등이 있습니다.

    -

    위젯

    -

    위젯은 레이아웃 또는 페이지 모듈에 삽입되어 동작합니다. 모듈에서 이미 생성된 데이터를 표시하거나, 일부 데이터를 생산할 수도 있습니다. 예를 들어, 게시판 모듈에서 작성된 최신 글 목록을 사이트의 시작 페이지에 나타내고 싶을 때 위젯을 사용합니다. XE에서 제공하는 대표적인 위젯에는 언어 선택, 로그인 정보 출력 위젯 등이 있습니다.

    -

    위젯 스타일

    -

    위젯 스타일은 위젯의 외관을 꾸미는 역할을 합니다. 스킨이 위젯의 출력 부분을 꾸며준다면, 위젯 스타일은 위젯의 외곽부분에 대한 스킨이라고 생각할 수 있습니다. 위젯 스타일을 적용하면 외관 변경 외에도 위젯 블록에 제목이나 더보기 링크 등의 내용을 추가할 수 있습니다.

    -
    위젯과 위젯 스타일 -
    위젯과 위젯 스타일
    -
    -

    스킨

    -

    스킨은 사이트에 설치된 프로그램의 디자인을 의미합니다. 즉, 스킨은 프로그램(모듈, 위젯)의 옷이라고 할 수 있습니다.

    -

    XE 공식 사이트에서는 프로그램별로 다양한 스킨을 제공하고 있습니다. 이를 잘 활용하면 본인만의 개성이 담긴 사이트를 운영할 수 있습니다.

    -

    레이아웃

    -

    사이트에 여러 가지 추가 기능을 설치한 후에는 이들을 화면에 적절하게 배치해야 합니다. 이렇게 화면 배치를 담당하는 것이 레이아웃입니다. 레이아웃과 추가 기능(모듈, 위젯)은 매우 긴밀한 관계를 유지합니다. 추가 기능이 없으면 레이아웃은 아무런 내용도 출력할 수 없기 때문에 화면에 표시되지 않습니다. 반대로 프로그램은 설치되어 있으나 레이아웃이 없으면 각 요소가 출력될 위치를 알 수 없기 때문에 역시 화면에 표시되지 않습니다.

    -
    레이아웃 -
    레이아웃
    -
    -
    -
    -

    추가 기능 설치 방법

    -

    XE의 다양한 추가 기능을 설치 하는 방법에는 2가지가 있습니다. XE 공식 사이트에서 소스 파일을 다운로드해서 XE 설치 서버에 업로드하는 방법과 XE core에서 제공하는 쉬운 설치 기능을 사용하는 방법입니다.

    -
    참고 -

    XE에서 추가 기능을 설치하는 것은 추가 기능의 소스 코드를 운영하고 있는 서버에 옮기는 것을 의미합니다. 즉, 추가 기능 설치 과정만으로는 실제 사이트에 표시할 콘텐츠를 제작할 수 없습니다. 추가 기능을 생성하여 사이트와 연동하는 과정은 "사이트 만들기"를 참조하시기 바랍니다.

    -
    -
    -

    소스 파일 업로드로 추가 기능 설치

    -

    XE 공식 사이트에서 추가 기능 소스 파일을 다운로드해서 XE 설치 서버에 업로드하는 방법입니다.

    -

    예를 들어, 소스 파일 업로드로 게시판 모듈을 설치하는 방법은 다음과 같습니다.

    -
      -
    1. XE 공식 사이트 자료실(https://www.xpressengine.com/download)에 접속합니다.
    2. -
    3. 게시판 모듈을 하나 선택해서 내 컴퓨터에 다운로드합니다. -
      게시판 모듈 다운로드 화면
      -
    4. -
    5. 다운로드한 게시판 모듈(zip 파일)의 압축을 해제합니다. 압축 해제가 완료되면 board라는 디렉터리가 생성됩니다.
    6. -
    7. 압축 해제한 board 디렉터리를 XE 설치 경로의 ./modules 디렉터리로 옮깁니다. 모든 모듈은 XE 설치 경로의 ./modules 디렉터리에 설치됩니다.
    8. -
    9. '고급 > 설치된 모듈' 목록에 다음 그림과 같이 게시판 모듈이 추가되었는지 확인합니다. -
      항목 업데이트 화면
      -
    10. -
    11. '이 항목 업데이트가 가능합니다. 업데이트하시겠습니까' 링크가 있을 경우에는 해당 링크를 클릭하면 설치가 완료됩니다.
    12. -
    -
    -
    -

    쉬운 설치로 추가 기능 설치

    -

    FTP 설정

    -

    쉬운 설치로 추가 기능을 설치하려면 쉬운 설치 사용을 위한 계정을 설정해야 합니다. 방법은 다음과 같습니다.

    -
      -
    1. 관리자 메뉴의 '설정 > FTP 설정'을 클릭합니다.
    2. -
    3. 다음과 같이 웹 서버의 FTP 계정 정보를 입력합니다. -
      -
      아이디:
      -
      서버에 접근 가능한 아이디
      -
      비밀번호:
      -
      서버에 접근 가능한 비밀번호
      -
      -
    4. -
    5. 아이디, 비밀번호 외에 추가정보의 수정이 필요한 경우에는 '고급'에서 수정할 수 있습니다. -
      -
      FTP 서버 주소:
      -
      서버 주소는 XE가 설치된 서버로부터 접근하기 위한 주소입니다. 특별한 경우가 아니라면 XE는 자신이 설치된 서버에 구성 요소를 설치합니다. 따라서 자기 자신을 나타내는 주소인 localhost, 혹은 127.0.0.1을 입력합니다.
      -
      FTP port:
      -
      FTP 포트 번호의 경우 기본적으로 21을 쓰도록 되어 있으나, 서버에 따라 설정이 다를 수도 있습니다. 21이 아닐 때에는 서버 관리자에게 문의합니다.
      -
      Passive 모드를 사용:
      -
      클라이언트(사용할 웹 서버)가 방화벽 환경에 있어도 FTP 서비스를 정상적으로 사용할 수 있게 하는 기능입니다. 예를 선택해야 방화벽이 설치된 환경에서 FTP를 사용할 수 있습니다. 따라서 쉬운 설치 기능을 사용하려면 서버에서 FTP Passive mode를 지원해야 합니다.
      -
      SFTP를 사용:
      -
      FTP 프로토콜을 통해 주고받는 데이터는 암호화되어 있지 않습니다. SFTP(SSH File Transfer Protocol)를 사용하면 쉬운 설치 기능을 더 안전하게 사용할 수 있습니다. SFTP는 관련 PHP 모듈이 설치되어 있어야 사용할 수 있습니다.
      -
      -
      FTP 설정
      -
    6. -
    7. 모든 정보를 입력했으면 '저장'을 클릭합니다.
    8. -
    -

    쉬운 설치 사용을 위한 계정 설정을 완료하였습니다.

    -
    참고 -

    쉬운 설치 진행 중에 FTP 홈 디렉터리 설정 관련 오류가 발생하면 "쉬운 설치 진행 시 FTP 홈 디렉터리 설정 오류"를 참조하십시오.

    -
    -

    쉬운 설치 사용

    -

    예를 들어, 쉬운 설치로 Textyle 모듈을 설치하는 방법은 다음과 같습니다.

    -
      -
    1. 관리자 메뉴의 '고급 > 쉬운 설치'를 클릭합니다.
    2. -
    3. Textyle 모듈을 찾아서 모듈 설명 오른쪽에 있는 설치를 클릭합니다. 설치가 완료되면 오른쪽에 있는 설치 버튼이 사라집니다. -
      쉬운 설치
      -
    4. -
    -
    -
    -
    -
    -

    사이트 만들기

    -
    -

    일반 사이트 만들기

    -

    이 절에서는 3개의 게시판과 각 게시판과 링크된 메뉴, 게시판의 최신 글을 메인 페이지에 출력하는 간단한 일반 사이트를 만들어 보겠습니다.

    -

    이 절에서 만들 사이트의 완성된 모습은 다음과 같습니다.

    -
    일반 사이트 완성 -
    일반 사이트 완성 화면
    -
    -
    -

    사이트 제목 바꾸기

    -

    '설정 > 일반 > 기본 > 사이트 제목' 항목을 작성 또는 변경합니다. '생성된 레이아웃'에서 사이트 제목을 설정하지 않았을 때 이 제목이 노출됩니다.

    -
    -
    -

    사이트 메뉴 편집

    -

    홈 만들기

    -

    사이트의 시작 페이지로 사용될 '홈'을 만듭니다.

    -
      -
    1. '사이트 제작/편집' > '사이트 메뉴 편집' 메뉴로 이동합니다.
    2. -
    3. XE를 설치하면 자동으로 만들어지는 welcome_menu를 그대로 활용하도록 하겠습니다. welcome_menu를 클릭하면 나오는 메뉴에서 '메뉴 추가'를 클릭합니다.
    4. -
    5. '메뉴 추가'의 서브 메뉴에서 '위젯 페이지'를 클릭합니다.
    6. -
    7. 위젯 페이지 대화상자에서 '메뉴이름'은 '홈'이라고 적고, '메뉴 ID'는 'home'이라고 적습니다. ('메뉴 ID'를 입력하지 않게 되면 임의의 값으로 자동 생성 됩니다.) -
      '홈' 메뉴 추가
      -
    8. -
    -

    기본페이지 지정

    -

    사이트에 접속 시 처음 보여질 메뉴로 지정합니다.

    -
      -
    1. '사이트맵'에서 '홈' 메뉴를 클릭하면 나오는 메뉴 가운데 '사이트 접속 시 기본 페이지로 사용'을 클릭합니다.
    2. -
      시작 페이지 변경
      -
    3. 기존에 기본페이지로 사용되었던 'menu1' 메뉴를 삭제 합니다.
    4. -
      'menu1' 메뉴 삭제
      -
    5. 메뉴를 삭제할 때 나오는 checkbox에 check한 후 '확인' 버튼을 눌러 삭제합니다.
    6. -
      메뉴 삭제 확인
      -
    -

    게시판 만들기

    -

    3개의 게시판 중 '공지사항'을 먼저 만듭니다.

    -
      -
    1. '사이트맵'의 'welcome_menu'를 클릭하여 나오는 메뉴에서 '메뉴 추가'를 클릭합니다.
    2. -
    3. '메뉴 추가'에 '게시판'타입의 메뉴가 없기 때문에 하단에 있는 '다른 메뉴타입 설치'를 클릭합니다.
    4. -
      다른 메뉴타입 설치
      -
      참고 -

      '다른 메뉴타입 설치'를 하기 위해서는 ftp 설정이 필요합니다. ftp 설정은 "FTP 설정"을 참고하시기 바랍니다.

      -
      -
    5. '다른 메뉴타입 설치'에서 'board'로 검색을 하면 나오는 '게시판'의 우측 설치 아이콘을 클릭합니다. -
      board 설치
      -
    6. -
    7. FTP 비밀번호를 묻는 창이 뜨는 경우에는 비밀번호를 입력하고 '확인' 버튼을 누릅니다. -
      ftp 비밀번호 입력
      -
    8. -
    9. 설치가 진행되는 동안 기다립니다. 설치가 완료 되기 전에 다른 곳으로 이동하거나 페이지를 새로고침하시면 안됩니다. -
      설치 진행 중
      -
    10. -
    11. 설치가 완료되면 다시 '사이트맵'의 'welcome_menu > 메뉴 추가 > 게시판'을 클릭한 후 아래와 같이 입력합니다. 입력 후 '확인' 버튼을 눌르면 공지사항이 생성됩니다. -
      공지사항 추가
      -
    12. -
    13. 공지사항과 마찬가지로 '자유게시판'과 '등업게시판'을 생성합니다. '자유게시판'의 '메뉴 ID'는 'freeboard01'로 , '등업게시판'의 '메뉴 ID'는 'levelup01'로 입력합니다.
    14. -
    -
    -
    -

    사이트 디자인 설정

    -

    사이트에 사용할 메뉴들을 모두 생성하였으면, 전체적인 디자인을 설정해야 합니다. 먼저 레이아웃 설정을 합니다.

    -
      -
    1. 관리자 화면에서 '사이트 제작/편집 > 사이트 디자인 설정 > 레이아웃'을 클릭합니다.
    2. -
    3. 레이아웃 목록에서 'Bootstrap.Layout'을 선택합니다.
    4. -
    5. 선택 후 'PC 설정 저장' 버튼을 눌러 내용을 저장합니다. -
      레이아웃 설정
      -
    6. -
    7. 이곳에서 선택한 레이아웃은 위에서 생성한 '홈', '공지사항', '자유게시판', '등업게시판' 모두에 적용 됩니다. 단 각 메뉴별로 별도의 레이아웃을 적용할 수도 있습니다. 각 메뉴별 별도 레이아웃을 적용하고자 하는 경우에는 '사이트맵 > 디자인 > 레이아웃' 에서 '사이트 기본 레이아웃 사용'을 체크 해제한 후 원하는 레이아웃을 선택하면 됩니다.
    8. -
    -
    -
    -

    페이지 수정

    -

    이 절에서는 각 게시판에 최신 글을 볼 수 있도록 홈페이지를 수정해 보겠습니다.

    -
      -
    1. XE가 설치된 도메인 주소를 브라우져 창에 입력하고 들어갑니다. (ex: http://example.com/) 또는 관리자 페이지 상단 로고 우측에 있는 도메인을 클릭해도 됩니다.
    2. -
    3. 아래와 같은 페이지가 표시되면 화면 오른쪽에 있는 '페이지 수정...'을 클릭합니다. -
      페이지 수정버튼
      -
      참고 -

      페이지에 관리자 권한으로 접근하면 페이지의 콘텐츠를 편집하거나 설정할 수 있는 '캐시파일 재생성', '설정', '페이지 수정'이 표시됩니다. 이 버튼들이 보이지 않는다면 관리자 아이디로 로그인했는지 확인하시기 바랍니다.

      -
      -

      각 게시판의 최신 글을 페이지에 출력하려면 콘텐츠를 출력할 수 있는 위젯이 필요합니다. 우선, 자유게시판 내용을 나타내기 위한 위젯을 생성합니다.

      -
    4. -
    5. 다음과 같이 페이지 수정 화면이 나타나면 Content 위젯을 선택하고 추가를 클릭합니다. -
      Content 위젯 선택
      -
    6. -
    7. 위젯 코드 생성 창이 나타나면 다음과 같이 필요한 항목을 입력하고 코드생성을 클릭합니다. -
      -
      위젯:
      -
      Content 위젯 ver 0.1
      -
      스킨:
      -
      Content 위젯 기본 스킨(default)
      -
      캐시:
      -
      5분
      -
      추출대상:
      -
      변경하지 않음
      -
      내용형태:
      -
      이미지+제목+내용
      -
      탭형태:
      -
      없음
      -
      표시항목 및 순서:
      -
      제목, 등록일, 글쓴이, 내용
      -
      게시판 이름 표시:
      -
      출력하지 않음
      -
      댓글수 표시:
      -
      출력
      -
      엮인글수 표시:
      -
      출력
      -
      분류 표시:
      -
      출력
      -
      아이콘 표시:
      -
      출력
      -
      정렬 대상:
      -
      최신 등록순
      -
      정렬 방법:
      -
      내림차순
      -
      썸네일 생성 방법:
      -
      Crop(채우기)
      -
      이미지 가로 크기:
      -
      100
      -
      이미지 세로 크기:
      -
      75
      -
      가로 이미지수:
      -
      5
      -
      목록수:
      -
      5
      -
      페이지수:
      -
      1
      -
      new 표시 시간 (hours):
      -
      12
      -
      제목 글자수:
      -
      0
      -
      내용 글자수:
      -
      100
      -
      대상 모듈:
      -
      추가를 클릭하고 모듈 선택 팝업에서 모듈에 게시판으로 검색하여 자유게시판을 선택
      -
      HTML 출력방식:
      -
      Table
      -
      -

      위젯이 생성되면 다음 그림과 같은 화면을 확인할 수 있습니다.

      -
      위젯 생성된 화면
      -
      참고 -

      게시판에 작성된 글이 없는 경우 위젯에 내용이 나타나지 않습니다. 위젯의 내용을 확인하기 위해서는 각 게시판에 테스트를 위한 게시물을 미리 작성해 두어야 합니다.

      -
      -

      위젯 윗부분에 위젯과 연동되어 있는 게시판 이름과 게시판으로 이동할 수 있는 링크를 삽입하기 위해 위젯 스타일을 적용해 보겠습니다.

      -
    8. -
    9. 추가된 위젯 영역 위로 마우스 커서를 움직여서 위젯 영역 왼쪽 윗부분에 표시되는 아이콘 메뉴 중 위젯 스타일 추가(위젯 스타일 추가 버튼)를 클릭합니다.
    10. -
    11. 위젯 스타일 팝업 창이 나타나면 적용할 위젯 스타일로 심플 스트롱을 선택하고 설정을 클릭합니다.
    12. -
    13. 위젯 스타일을 설정하는 화면이 나타나면 다음과 같이 설정합니다. -
      -
      컬러셋:
      -
      하얀색
      -
      제목:
      -
      자유게시판
      -
      더보기 URL:
      -
      해당 게시판의 URL을 입력합니다. 자유게시판의 모듈 이름은 freeboard01이므로, http://xe설치경로/freeboard01을 입력합니다.
      -
      더보기 텍스트:
      -
      위젯과 연동된 게시판으로 이동하기 위한 링크의 텍스트입니다. 이 예제에서는 more로 지정합니다.
      -
      -
    14. -
    15. 자유게시판 위젯에 위젯 스타일이 다음과 같이 적용되었는지 확인합니다. -
      위젯 스타일 적용 화면
      -
    16. -
    17. 나머지 두 게시판과 연동되는 위젯을 생성하고 위젯 스타일을 적용합니다. -

      공지사항 코드를 생성할 때 아래의 설정 정보 외에 다른 내용은 모두 자유게시판 위젯을 생성할 때 입력한 내용과 동일하므로, 자유게시판 위젯 생성 과정을 참고하여 진행합니다.

      -
      -
      내용형태:
      -
      제목
      -
      표시항목 및 순서:
      -
      제목, 등록일, 글쓴이
      -
      대상 모듈:
      -
      추가를 클릭하고 모듈 선택 팝업에서 모듈에 공지사항을 선택
      -
      -

      등업게시판 코드를 생성할 때도 아래의 설정 정보 외에 다른 내용은 모두 자유게시판 위젯을 생성할 때 입력한 내용과 동일합니다.

      -
      -
      내용형태:
      -
      제목
      -
      표시항목 및 순서:
      -
      제목, 등록일, 글쓴이
      -
      대상 모듈:
      -
      추가를 클릭하고 모듈 선택 팝업에서 모듈에 등업게시판을 선택
      -
      -
    18. -
    19. 다음과 같이 3가지 위젯이 모두 추가되었는지 확인합니다. 단, 게시판에 게시된 글에 따라 위젯의 내용은 다를 수 있습니다. -
      추가된 위젯 확인
      -

      위젯 생성이 완료되었으면 이를 재배치합니다. 자유게시판 위젯은 그대로 두고 그 아래에 공지사항과 등업게시판 위젯을 가로로 나란히 배치하겠습니다.

      -
    20. -
    21. 등업게시판 위젯 영역 위로 마우스 커서를 움직여 위젯 영역 왼쪽 위에 나타나는 아이콘 메뉴 중 화살표(화살표 아이콘)를 클릭합니다.
    22. -
    23. 다음과 같은 위젯 설정 화면이 나타나면 등업게시판 위젯 왼쪽에 공지사항 위젯을 나란히 둘 공간을 만들기 위해 위젯 정렬 속성을 오른쪽으로 변경하고 저장을 클릭합니다. -
      위젯 설정 화면
      -
    24. -
    25. 등업게시판 위젯의 왼쪽 아래에 있는 크기 변경 핸들(크기 변경 핸들)을 마우스로 끌어서 오른쪽으로 이동시켜 위젯의 가로 크기를 반 정도로 줄입니다. -
      줄어든 위젯
      -
    26. -
    27. 공지사항 위젯의 오른쪽 아래에 있는 크기 변경 핸들(크기 변경 핸들)을 왼쪽으로 끌어서 가로 크기를 줄입니다. 공지사항 위젯의 가로 폭이 등업게시판 왼쪽의 빈 공간보다 작아지면 등업게시판 위젯과 나란히 정렬됩니다
    28. -
    29. 다음과 같이 정렬이 완료되면 오른쪽 아래에 있는 메뉴의 저장을 클릭합니다. -
      홈페이지 저장
      -
    30. -
    -
    -
    -
    -

    시작 메뉴 설정

    -

    설정한 메뉴들 중에 하나의 메뉴를 접속 시 기본페이지로 사용할 수 있습니다. XE 최초 설치시에는 자동으로 'welcome_menu' 메뉴의 'menu1이 '접속 시 기본페이지'로 지정되어 있습니다.

    -

    접속 시 기본 페이지는 아래와 같이 변경할 수 있습니다.

    -
      -
    1. '사이트 제작/편집' > '사이트 메뉴 편집'으로 이동합니다.
    2. -
    3. 원하는 메뉴를 클릭하면 나오는 서브메뉴에서 '사이트 접속 시 기본 페이지로 사용'을 클릭합니다. -
      시작 페이지 변경
      -
    4. -
    5. XE 최초 설치시 기본페이지로 지정되어 있던 'menu1'이 '홈'으로 변경된 것을 확인할 수 있습니다.
    6. -
    -
    -
    -

    아이디 또는 이메일 로그인 설정

    -

    회원이 사이트에 로그인 할 때 '이메일+비밀번호' 또는 '아이디+비밀번호' 형식으로 로그인 하는것을 관리자가 선택할 수 있습니다.

    -
      -
    1. '회원 > 회원 설정 > 회원가입 > 가입 폼 관리' 항목으로 이동합니다. -
      - 가입 폼 관리 -
      회원 > 회원 설정 > 회원가입 > 가입 폼 관리
      -
      -
    2. -
    3. '아이디' 또는 '이메일 주소' 가운데 회원이 로그인 할 때 사용할 항목을 선택합니다.
    4. -
    5. '아이디'를 선택하면 사용자 로그인 화면에 '아이디' 입력 인풋이 표시됩니다. -
      - 아이디 입력 인풋 -
      '아이디' 입력 인풋
      -
      -
    6. -
    7. '이메일 주소'를 선택하면 사용자 로그인 화면에 '이메일 주소' 입력 인풋이 표시됩니다. -
      - 이메일 주소 입력 인풋 -
      '이메일 주소' 입력 인풋
      -
      -
    8. -
    -
    -
    -
    -

    FAQ

    -
    -

    회원설정 가입폼 관리

    -

    회원 가입폼을 커스터마이징 해서 사용할 수 있습니다. 원하는 폼 형식을 사용해서 회원 가입폼을 만들기 위해서는 다음과 같이 설정하면 됩니다.

    -
      -
    1. '회원 > 회원설정 > 회원가입 > 가입 폼 관리'로 이동합니다. 아래와 같은 모습을 볼 수 있습니다. -
      - 가입 폼 관리 -
      '가입 폼 관리' 설정 화면
      -
      -
    2. -
    3. '사용' 컬럼에 있는 체크박스를 이용해서 회원 가입시 노출시키고 싶은 대상을 선택할 수 있습니다.
    4. -
    5. 최초 설정된 내용 이외의 것을 회원 가입 시 받고 싶다면 '사용자 정의 항목 추가'를 클릭해서 새로운 form을 추가할 수 있습니다. -
      - 회원 정의 입력 -
      '회원 정의 입력' 화면
      -
      -
    6. -
    7. 입력항목 ID는 프로그램에서 사용하는 값으로 영문, 숫자로 입력하면 됩니다. 화면에 표시 될 항목 이름은 '입력항목 제목'란에 입력하면 됩니다. 해당 form을 필수로 입력받길 원한다면 '필수/선택'란에서 '필수' 라디오에 체크를 합니다.
    8. -
    9. 입력 형식은 매우 다양한 형태를 지원합니다. 원하는 형식을 선택하면 됩니다. -
      - 입력 형식 -
      다양한 form 형식 지원
      -
      -
    10. -
    -
    -
    -

    계정 무한 대입 방지

    -

    악의적인 목적을 가지고 로그인을 시도하는 경우를 방지하고자 로그인 실패 횟수를 제한하는 장치입니다. '계정 무한 대입 방지'를 사용하고자 할 경우에는 다음과 같이 하면 됩니다.

    -
      -
    1. '회원 > 회원설정 > 로그인'으로 이동합니다. 아래와 같은 모습을 볼 수 있습니다. -
      - 로그인 설정 -
      로그인 설정
      -
      -
    2. -
    3. '계정 무한 대입 방지 사용'에 '예'를 선택합니다.
    4. -
    5. '로그인 시도 횟수 제한 횟수'에 몇번의 로그인 시도를 허용할지 원하는 숫자를 입력합니다.
    6. -
    7. '로그인 시도 횟수 제한 시간'에는 제한 횟수를 넘겼을 경우 로그인을 허용하지 않을 시간을 입력합니다.
    8. -
    9. 위에서 설정한 휫수 이상 로그인이 실패할 경우 아래와 같이 표시 됩니다. -
      - 로그인 제한 초과 -
      로그인 제한 초과
      -
      -
    10. -
    -
    -
    -

    관리그룹, 관리자

    -

    관리그룹과 관리자와의 이름이 유사하여 혼동이 생길 수 있습니다. 관리그룹과 관리자의 차이는 아래와 같습니다.

    -
      -
    • 관리그룹: '회원 > 회원 그룹'에 기본적으로 생성되는 그룹으로서 실질적 관리권한이 있는 것이 아닙니다. 각 모듈 별 '권한 관리'에서 관리권한을 '관리그룹'에게 줄 경우 해당 그룹에 속해있는 회원에게 권한이 부여됩니다.
    • -
    • 관리자: XE를 최초 설치할 때 입력한 정보의 회원을 말하는 것입니다. 사이트의 모든 실절적 권한은 '관리자'에게 있습니다.
    • -
    -
    -
    -

    '임시' 문서

    -

    '콘텐츠 > 문서 > 임시'에 보면 문서목록이 보입니다. 여기에 보이게 되는 문서는 회원들이 글을 작성하는 도중 '임시 저장' 버튼을 눌러 저장한 문서입니다.

    -

    임시 저장한 문서는 다른 회원들에게 보여지지 않습니다.

    -

    임시 저장한 문서는 추후 글쓰기 화면에서 '불러오기'를 통해 다시 불러 쓸 수 있습니다.

    -

    임시 저장과 비슷한 개념으로 '자동 저장'이 있습니다. 자동 저장은 임시저장과는 달리 글쓴이가 직접 저장하는 행동을 취하지 않아도 저장되며, 글쓰기를 시작할 때 자동저장 된 글이 있으면 자동저장된 글을 불러올 것인지 물어보게 됩니다.

    -
    -
    -

    파일 목록의 '유효', '대기'

    -

    '콘텐츠 > 파일'에 보면 파일의 상태가 '유효'와 '대기'로 나누어 집니다. 각 상태는 아래와 같습니다.

    -
      -
    • 유효: 문서를 작성하면서 파일을 등록한 후 문서 작성을 완료한 상태
    • -
    • 대기: 문서를 작성하면서 파일을 등록하였지만 아직 문서 작성을 완료하지 않은 상태 또는 작성을 취소한 상태에서 남아있는 파일
    • -
    -
    -
    -

    다국어

    -

    XE는 하나의 사이트에서 여러 언어로 된 콘텐츠를 제공할 수 있도록 다국어를 지원합니다.

    -

    또한 관리자가 정의한 다국어를 등록한 다음 등록된 다국어를 사이트에서 사용할 수도 있습니다. 관리자 정의 다국어는 아래와 같은 방법으로 사용합니다.

    -
      -
    1. '콘텐츠 > 다국어'로 이동합니다.
    2. -
    3. '추가'탭에서 원하는 다국어를 입력한 후 '저장' 버튼을 눌러 저장합니다. -
      - 다국어 추가 -
      다국어 추가
      -
      -
    4. -
    5. 이미 추가 된 다국어는 '검색' 탭에서 검색할 수 있습니다. -
      - 다국어 검색 -
      다국어 검색
      -
      -
    6. -
    7. 추가된 다국어는 XE의 곳곳에서 사용 가능합니다. 하나의 예로 위에서 추가한 '한국어'란 다국어를 다음과 같이 활용할 수 있습니다. -
        -
      1. '사이트 제작/편집 > 사이트 메뉴 편집'으로 이동합니다.
      2. -
      3. 특정 메뉴를 선택 후 '메뉴 수정'을 클릭합니다.
      4. -
      5. 메뉴 수정 화면에서 '메뉴 이름' 옆에 나오는 지구본 모양 아이콘을 클릭합니다. -
        - 메뉴 이름 수정 -
        메뉴 이름 수정
        -
        -
      6. -
      7. 다국어 추가, 검색 대화창이 열립니다. 여기서 '검색' 탭을 클릭하고 바로 전에 입력한 '한국어'를 클릭합니다. 다국어가 많을 경우에는 검색을 활용합니다. 검색 입력 폼 앞의 select 옵션을 선택하면 각 언어별로 검색할 수 있습니다. '한국어'가 다국어로 어떻게 쓰일지 보여지고 확인을 하였다면 우측 하단의 '사용' 버튼을 누릅니다. -
        - 다국어 사용 -
        다국어 사용
        -
        -
      8. -
      9. 아래와 같이 적용 된 것을 볼 수 있습니다. 적용된 다국어를 사용하고 싶지 않을 경우에는 X 버튼을 눌러 적용 해제할 수 있습니다. -
        - 다국어 적용된 모습 -
        다국어 적용된 모습
        -
        -
      10. -
      11. 위와 같이 설정을 마치고 나면 해당 메뉴는 한국어와 영어 모두 지원 됩니다. 한국어로 설정하면 '한국어'라는 메뉴가, 영어로 설정하면 'English'라는 메뉴가 노출되게 됩니다.
      12. -
      -
    8. -
    -
    -
    -

    관리자 접속 아이피 대역 관리

    -

    관리자의 아이디와 비밀번호만 알게 되면 관리자로 어느 곳에서나 로그인이 가능합니다. 따라서 관리자 아이디로 접속할 수 있는 아이피 대역을 제한해 두면 보안에 유리합니다.

    -

    관리자의 아이디로 접속할 수 있는 아이피 대역을 설정하기 위해서는 다음과 같이 하면 됩니다.

    -
      -
    1. '설정 > 일반'을 접속합니다.
    2. -
    3. '고급'의 '관리자 IP대역'에 원하는 IP를 입력합니다. -
      - 관리자 IP 대역 입력 -
      관리자 IP 대역 입력
      -
      -
    4. -
    5. ip를 직접 수정하고 싶으신 분은 'XE설치폴더/files/db.config.php'의 "$db_info->admin_ip_list = '127.0.0.1,127.0.0.2';" 부분을 수정해 주면 됩니다.
    6. -
    7. 관리자 아이디로 로그인 하였지만 ip 제한에 걸린 경우에는 다음과 같은 모습을 보게 됩니다. -
      - 관리자 접속 제한 -
      관리자 접속 제한
      -
      -
    8. -
    -
    -
    -

    SSL 접속

    -

    일반 접속은 사용자와 서버간에 전송되는 내용이 암호화되지 않아 중요한 정보가 악의적인 사용자에 의해 탈취당할 수 있습니다. 이를 방지하기 위해 SSL 접속을 사용할 수 있습니다.

    -

    XE에서는 SSL 접속을 '선택적'으로 또는 '항상' 사용할 수 있습니다.

    -

    선택적으로 사용할 경우에는 '회원가입', '정보 수정' 등에서만 SSL 접속을 유지합니다.

    -

    관련 설정은 '설정 > 일반 > 고급 > SSL(Secure Sockets Layer) 사용'에서 선택할 수 있습니다.

    -
    참고 -

    서버에 SSL이 설치되어 있지 않은 경우에는 접속 기능이 동작하지 않습니다. 먼저 SSL이 설치되어 있는지 확인 후 사용하시기 바랍니다.

    -
    -
    -
    -

    짧은 주소

    -

    짧은 주소는 복잡하고 어려운 XE의 주소를 간단하게 사용할 수 있도록 줄여주는 기능입니다. 짧은 주소를 사용하게 되면 아래와 같은 이점이 있습니다.

    -
      -
    • 짧은 주소: http://xemanual.com/freeboard/123
    • -
    • 원래 주소: http://xemanual.com/index.php?mid=freeboard&document_srl=123
    • -
    -

    짧은 주소를 사용하길 원할 경우에는 '설정 > 일반 > 고급 > 짧은 주소 사용'에 '예'를 선택한 후 '저장'하면 됩니다.

    -
    -
    -

    데이터 들여오기

    -

    제로보드4, zb5beta 또는 다른 프로그램의 데이터를 XE 데이터로 이전할 수 있습니다. 데이터의 추출은 공식사이트의 자료실에서 다운로드 받으시거나 Git을 통해 migration tool 저장소를 clone 하시면 됩니다.

    -

    XE의 '게시물 정보'를 다른 XE사이트 게시물로 이전하는 작업을 예로 들어 설명해 드리도록 하겠습니다.

    -
      -
    1. 공식사이트의 자료실에서 "XpressEngine 데이터 추출 Ver 0.3"을 다운로드 받거나 migration tool 저장소에서 소스를 clone 하시면 됩니다.
    2. -
    3. 다운로드 받은 소스를 URL로 접근 가능한 곳에 압축을 풉니다. 이 예제에서는 XE의 URL이 http://example.com/xe/라면 http://example.com/migration/ 아래로 하겠습니다.
    4. -
    5. 브라우져로 http://example.com/migration/index.php으로 접근하면 아래와 같은 모습을 볼 수 있습니다. -
      - XE data export 초기화면 -
      XE data export 초기화면
      -
      -
    6. -
    7. 2번에서 이야기한 url에 근거해 '설치 경로 입력'란에 "../xe" 라고 입력합니다. 절대 경로로 입력해도 됩니다. 사용자에 따라 입력 경로가 달라질 수 있습니다.
    8. -
    9. 설치 경로 입력 후 '설치 경로 입력' 버튼을 누르면 아래와 같은 모습을 볼 수 있습니다. -
      - 추출 대상 선택 -
      추출 대상 선택
      -
      -
    10. -
    11. 이 예제에서는 게시물 정보를 이전할 예정이니 '게시판'을 선택 후 '자유게시판'을 선택합니다. 선택 후 '추출 대상 선택' 버튼을 누릅니다.
    12. -
    13. 아래와 같은 결과가 나옵니다. -
      - 추출 옵션 선택 및 다운로드 -
      추출 옵션 선택 및 다운로드
      -
      -
    14. -
    15. 분할 수는 추출하는 데이터를 몇개의 파일로 나누어서 받을 지 결정하는 것입니다. 여기서는 게시물의 수가 많지 않으므로 1개로 받도록 하겠습니다.
    16. -
    17. 첨부파일을 포함하고 싶지 않을 경우에는 '첨부파일 미포함'에 체크를 합니다.
    18. -
    19. 데이터 들여오기 시 실제 xml 파일을 서버에 올려놓아 사용하거나 URL을 복사해서 사용할 수 있습니다. 여기서는 실제 xml 파일을 다운로드 받아 사용하도록 하겠습니다.
    20. -
    21. 옵션을 모두 결정했다면 파일명(module_57395.000001.xml)을 눌러 다운로드를 받습니다.
    22. -
    23. 다운로드 받은 파일을 xe가 설치된 위치에 업로드 합니다.
    24. -
    25. 관리자의 '콘텐츠 > 데이터 들여오기'로 들어갑니다.
    26. -
    27. '게시물 정보'의 xml 파일 입력 폼에 파일 명을 아래와 같이 입력한 후 '경로 확인' 버튼을 누릅니다. -
      - 경로 확인 -
      경로 확인
      -
      -
      참고 -

      실제 파일이 아니라 export에서 복사한 url을 입력해도 됩니다.

      ex) http://example.com/migration/export.php?filename=module_57395.000001.xml&path=..%2Fmaserati&target_module=module&module_id=57395&start=0&limit_count=1232&exclude_attach=

      -
      -
    28. -
    29. 'XML 파일을 찾았습니다.'란 메시지가 뜨면서 추가 입력상자가 보이게 됩니다. 'XML 파일을 찾을 수 없습니다.'라는 메시지가 보이게 되면 경로가 잘못 입력한 것이니 경로를 위치가 맞는지 확인해 보아야 합니다.
    30. -
    31. '찾기' 버튼을 통해 어떤 메뉴로 데이터를 이전할 것인지 선택합니다.
    32. -
    33. 회원 아이디 기반으로 회원정보를 동기화 시키고 싶다면 '회원정보 동기화' 체크박스에 체크합니다.
    34. -
    35. 필요한 내용을 모두 입력하였으면, '데이터 들여오기' 버튼을 클릭합니다. 아래와 같이 '데이터 이전중입니다'라는 프로그레스바가 보이면서 데이터가 이전 됩니다. -
      - 데이터 이전 중 -
      데이터 이전 중
      -
      -
      참고 -

      데이터 이전에는 오랜 시간이 걸릴 수 있으므로, 게시물의 수가 많을 경우에는 분할하여 이전하시고 프로그레스바가 표시 중일때는 브라우져를 새로고침하지 말고 기다려 주시기 바랍니다.

      -
      -
    36. -
    37. 데이터 이전이 완료되면 아래와 같이 메시지가 나타납니다. -
      - 데이터 이전 완료 -
      데이터 이전 완료
      -
      -
    38. -
    -
    -
    -

    관리자 메뉴 초기화

    -

    관리자 메뉴는 "설정 > 관리자 설정"에서 추가, 삭제할 수 있습니다. 추가, 삭제후 최초의 관리자 메뉴로 되돌리고 싶을 경우 '관리자 메뉴 초기화'를 할 수 있습니다. 관리자 메뉴 초기화를 하게 되면 XE 최초 설치시 설정 된 관리자 메뉴로 복원 됩니다.

    -
    -
    -

    캐시파일 재생성

    -

    - XE는 최적의 성능을 내기 위해 각종 캐시 파일을 사용합니다. 하지만 캐시 파일이 최신 내용의 적용되지 않음으로 인해 문제가 발생할 수 있습니다. 이럴 경우에는 관리자 하단에 있는 '캐시파일 재생성'을 통해 캐시파일을 새롭게 만들어 줄 수 있습니다. -

    참고 -

    XE의 모든 기능에 캐시 기능이 들어 있는 것이 아니며, 캐시파일 재생성 역시 모든 기능에서 지원하는 것이 아닙니다. 따라서 캐시파일 재생성을 지원하는 기능에 한해 동작하게 됩니다.

    -
    -

    -
    -
    -

    세션 정리

    -

    오랜기간 사이트를 운영하다 보면 사용자의 정보 등을 담고 있는 세션들 중 일부 데이터가 가비지(찌꺼기) 데이터가 되는 경우가 있습니다. 이로 인해 사이트 자체가 느려지게 될 수 있습니다. 이럴 경우 '세션 정리'를 하게 되면 사이트의 속도 향상에 도움이 됩니다. 세션 정리의 경우 사이트에 부하가 발생할 수 있으므로 접속자가 적은 시간 또는 사이트의 운영을 중지한 상태로 진행하시기 바랍니다.

    -
    -
    -

    문서 페이지

    -

    '회사 소개'와 같이 거의 갱신할 필요가 없는 정적인 문서입니다. 관리자는 '글, 이미지, 멀티미디어' 등을 문서 페이지에 직접 작성하거나 수정할 수 있습니다. 만약 프로그램에 의해 동적으로 갱신되는 콘텐츠를 문서에 삽입하고 싶다면 '문서 페이지' 대신 '위젯 페이지'를 사용하세요.

    -
    -
    -

    위젯 페이지

    -

    '초기 화면'과 같이 수시로 갱신할 필요가 있는 동적인 문서입니다. '문서 페이지'와 같이 정적인 내용을 추가할 수도 있지만 각종 '위젯'을 삽입하면 동적인 내용을 출력할 수 있습니다. 위젯 페이지에 '콘텐츠 위젯'을 삽입함으로써 초기 화면에 최근 게시물을 표시할 수 있습니다.

    -
    -
    -

    외부 페이지

    -

    '사이트 제작/편집 > 사이트 메뉴 편집'에서 메뉴 추가 시 '외부 페이지' 타입이 있습니다. 여기서 말하는 '외부 페이지'란 XE의 모듈을 이용하지 않고 별도로 개발자가 작성한 페이지를 말합니다.
    외부 페이지는 3rd party 개발자가 작성한 프로그램 소스가 들어가 있을 수 있으며, 아니면 순수 html로만 만들어진 경우도 있습니다.

    -

    외부 페이지에서도 XE의 모듈 개발시 사용되는 기본적인 라이브러리 사용이 가능합니다. -

    참고 -

    메뉴 추가의 '바로가기' 타입에서 URL링크를 통해 추가할 수 있는 것과는 다른 개념입니다.

    -
    -

    -
    -
    -

    바로가기

    -

    '사이트 제작/편집 > 사이트 메뉴 편집'에서 메뉴 추가 시 '바로가기'가 있습니다. 여기서 말하는 '바로가기'란 이미 만들어져 있는 메뉴 또는 외부 링크를 연결하는 메뉴입니다. 윈도우의 바로가기와 비슷한 메뉴라고 보면 됩니다.

    -

    윈도우의 '바로가기' 삭제 시 원본이 삭제 되지 않는 것처럼, XE에서도 바로가기 메뉴 삭제시 원본 메뉴에는 영향을 미치치 않습니다.

    -
    -
    -

    메뉴 노출 대상

    -

    '사이트 제작/편집 > 사이트 메뉴 편집 > 권한'에 '메뉴 노출 대상'이 있습니다. '메뉴 노출 대상'은 다른 권한과는 달리 접근 자체를 제한하는 기능은 없습니다. 다만 메뉴를 보여주고 싶지 않은 대상일 경우 노출을 제한할 수 있습니다.

    -

    - 예를 들어 아래와 같이 노출 대상은 '로그인 사용자', 접근 권한은 '모든 사용자'로 설정을 하게 될 경우, 로그인을 안한 사용자에게 메뉴는 보이지 않지만 접근 URL을 알고 있다면 해당 메뉴에 접근할 수 있습니다. -

    - 권한 설정 -
    권한 설정
    -
    -

    -
    -
    -
    -

    부록

    -
    -

    Windows 환경 설정

    -

    Windows 환경에서 XE를 설치하는 방법에는 크게 두 가지가 있습니다. WPI를 사용하는 방법과 APMsetup을 사용하는 방법입니다. 두 가지 방법 모두 웹 서버인 IIS(Internet Information Server)를 설치할 때 포트 번호로 80을 사용하도록 설정하기 때문에, 한 컴퓨터에 두 가지 방법을 모두 사용할 수 없습니다. 사용자의 설치 환경에 따라 두 가지 방법 중 하나를 선택해서 사용합니다.

    -
    참고 -

    Windows XP에서 WPI를 사용하여 XE를 설치하면 URL을 기억하기 쉽게 줄여주는 mod_rewrite를 사용할 수 없습니다. mod_rewrite를 사용하려면 APMsetup을 사용해서 XE를 설치해야 합니다.

    -

    WPI로 패키징된 XE는 1.4.0.5 버전입니다. 최신 버전의 XE를 설치하려면 APMsetup을 사용하거나, WPI를 사용해서 설치한 후에 XE core를 별도로 업데이트해야 합니다.

    -
    -
    -

    계정 설정

    -

    Windows 계열 서버에 XE를 설치하려면 서버에 접근할 수 있는 계정이 필요합니다. 서버 계정은 서버 관리자에게 문의하여 얻습니다. 서버를 직접 관리하는 경우에는 기존 계정을 사용하거나 새로운 계정을 생성하여 사용합니다.

    -

    계정 이름을 정하고 나면 계정 유형을 선택할 수 있습니다. 서버 보안을 유지하기 위해 가능하면 제한된 계정을 선택하여 해당 계정의 권한을 최소화하는 것을 권장합니다.

    -
    -
    -

    원격 데스크톱 연결

    -

    서버를 직접 조작할 수 없을 경우 원격에서 서버에 접속하여 조작할 수 있는 방법이 필요합니다. Windows 시스템은 다른 컴퓨터에 접속하여 조작할 수 있게 하는 '원격 데스크톱 연결' 프로그램을 제공합니다.

    -

    원격 데스크톱 연결을 사용하려면 서버의 도메인 주소나 IP 주소가 필요합니다. 이미 도메인 설정이 되어 있으면 설정된 도메인을 사용하여 접속하면 되지만, 그렇지 않은 경우 IP 주소를 사용해야 합니다. 서버의 IP 주소를 확인하고 원격 데스크톱 연결로 그 주소에 접속하는 방법은 다음과 같습니다.

    -
      -
    1. Windows 서버의 명령 프롬프트를 실행합니다.
    2. -
    3. ipconfig 명령어를 입력해서 서버의 IP 주소를 확인합니다. -
      CMD Prompt 화면
      -
    4. -
    5. 내 컴퓨터에서 시작 > 보조프로그램 > 원격 데스크톱 연결을 실행하거나, 명령 프롬프트에서 mstsc를 실행합니다.
    6. -
    7. 원격 데스크톱 연결 창이 나타나면 컴퓨터에 연결할 서버의 주소를 입력하고 연결을 클릭합니다. -
      원격 테스크톱 연결 창
      -
    8. -
    9. 서버의 계정과 암호를 입력하는 화면이 나타나면, "계정 설정"에서 생성한 계정 정보를 입력하여 서버에 로그인합니다.
    10. -
    -
    -
    -

    WPI 사용

    -

    WPI는 마이크로소프트 사에서 웹 플랫폼 제품을 편리하게 사용할 수 있도록 만든 도구입니다. 서버에 필요한 구성 요소나 웹 응용프로그램을 자동으로 설치 및 설정합니다.

    -

    WPI는 웹 응용프로그램을 설치할 때 그 웹 응용프로그램에 필요한 구성 요소를 한꺼번에 설치합니다. 따라서 WPI를 사용하여 XE를 설치할 때 XE 설치에 필요한 프로그램도 함께 설치됩니다.

    -

    마이크로소프트 웹 플랫폼 공식 사이트(https://www.microsoft.com/web/)에서 WPI 실행기를 다운로드합니다.

    -

    WPI 실행기 실행 및 XE 설치 시작

    -
      -
    1. WPI 실행기를 실행하고, 웹 응용 프로그램 탭에서 콘텐츠 관리를 선택합니다.
    2. -
    3. 콘텐츠 관리 탭의 응용 프로그램 목록 중에서 XpressEngine을 찾아 선택하고 설치를 누릅니다. -
      콘텐츠 관리 탭
      -
    4. -
    5. XE core를 설치하기 위해 추가로 설치 및 설정되는 구성 요소 정보를 확인하고 동의함을 클릭하여 설치합니다.
    6. -
    -

    추가 구성 요소의 설치

    -

    추가로 설치되는 구성 요소 중에 MySQL DBMS가 포함되어 있으면 MySQL DBMS을 설치하면서 관리자 암호를 지정해야 합니다. 관리자 암호를 지정하는 화면이 나타나면 암호를 지정하고 계속을 클릭합니다.

    -
    참고 -

    WPI에서 MySQL 관리자 암호를 처음 지정할 때, 영소문자, 영대문자, 숫자, 기호가 모두 포함된 암호를 지정해야 합니다. MySQL 관리자 암호는 XE를 설치할 때 반드시 필요한 정보이므로 꼭 기억해 두어야 합니다.

    -
    -

    계정 설정이 완료되면 구성 요소가 설치됩니다.

    -

    XE 설치에 필요한 정보 입력

    -

    XE 설치에 필요한 구성 요소의 설치가 끝나면 XE 설치가 시작됩니다.

    -
      -
    1. 다음과 같이 XE를 설치할 사이트 정보를 입력하고 계속을 클릭합니다. -

      특별히 추가로 설정할 내용이 없다면 기본 설정을 그대로 사용합니다.

      -
      웹 플랫폼 설치 화면
      -
    2. -
    3. 다음과 같이 XE core 설치 정보를 입력하고 계속을 클릭합니다. -
      -
      데이터베이스:
      -
      XE에서 사용할 DBMS의 종류. 이 문서에서는 MySQL을 선택합니다.
      -
      새 데이터베이스 만들기 또는 기존 데이터베이스 사용:
      -
      기존의 데이터베이스를 사용하여 XE를 운영할 것인지, 새 데이터베이스를 사용할 것인지 선택. 가능하면 새 데이터베이스 만들기를 권장합니다.
      -
      데이터베이스 관리자:
      -
      선택된 DBMS의 관리자 ID. 이 문서에서 사용된 MySQL의 관리자 ID는 root입니다.
      -
      데이터베이스 관리자 암호:
      -
      선택된 DBMS의 관리자 암호. "추가 구성 요소의 설치"에서 지정한 MySQL 관리자 암호를 입력합니다.
      -
      데이터베이스 사용자 이름:
      -
      XE에서 데이터베이스에 접근할 때 사용할 사용자 이름
      -
      데이터베이스 암호:
      -
      XE에서 데이터베이스에 접근할 때 사용할 사용자 암호
      -
      데이터베이스 서버:
      -
      DBMS가 설치된 위치를 URL 형식으로 지정. 이 문서에서는 서버와 DBMS가 같은 컴퓨터에서 동작하므로 localhost를 입력합니다.
      -
      데이터베이스 이름:
      -
      XE에서 사용할 기존 혹은 새 데이터베이스의 이름
      -
      데이터베이스 테이블 접두사:
      -
      XE에서 생성한 테이블 이름에 사용할 머리말
      -
      XE 관리자 ID:
      -
      XE 관리자 ID
      -
      XE 관리자 이름:
      -
      XE 관리자 이름
      -
      XE 관리자 닉네임:
      -
      XE 관리자 계정의 별명
      -
      XE 관리자 패스워드:
      -
      XE 관리자 계정의 패스워드
      -
      XE 관리자 e-mail 주소:
      -
      XE 관리자 계정의 e-mail 주소
      -
      URL Rewrite 사용 여부:
      -
      mod_rewrite 사용 여부. 이 항목을 활성화하면 URL을 기억하기 쉽게 줄여서 사용할 수 있습니다.
      -
      GMT Timezone:
      -
      XE가 서비스할 지역의 표준시
      -
      -
    4. -
    -

    설치 확인

    -

    모든 설치 과정이 완료되면 웹 브라우저를 사용하여 사이트에 접속합니다. 정상적으로 설치가 완료되었으면 다음과 같은 화면이 나타납니다.

    -
    XE 설치 완료 화면 -
    XE 설치 완료 화면
    -
    -
    참고 -

    WPI를 사용해서 XE를 설치하면 최신 버전의 XE core가 설치되지 않습니다. XE core를 최신 버전으로 업데이트하려면 공식사이트에서 제공하는 XE core 최신 버전 파일을 다운로드해서 압축을 해제한 후 XE 설치 사이트 최상위 폴더(C:\Inetpub\wwwroot\xe)에 덮어 쓰도록 합니다.

    -
    -
    -
    -

    APMsetup 사용

    -

    APMsetup은 XE를 설치하는 데 필요한 구성 요소인 아파치 웹 서버, PHP, MySQL 데이터베이스를 한 번에 설치하고, 사용에 필요한 연동 설정을 자동으로 해 주는 프로그램입니다.

    -

    APMsetup 설치

    -

    다음과 같이 APMsetup을 설치합니다.

    -
      -
    1. APMsetup 공식 사이트(http://www.apmsetup.com)에서 최신 APMsetup 설치 파일을 다운로드합니다. 문서 작성 시점에 배포되어 있는 최신 버전은 APMsetup 7입니다.
    2. -
    3. 다운로드한 설치 파일을 실행합니다. 특별한 설정이 필요 없으면 기본 설정 상태로 설치를 진행하여 완료합니다. -
      참고 -

      APMsetup은 아파치 웹 서버를 설치할 때 포트 번호로 80을 사용하도록 설정합니다. 그러므로 시스템에 이미 포트 번호로 80을 사용하는 소프트웨어가 있을 경우에는 APMsetup을 정상적으로 설치할 수 없습니다.

      -
      -
    4. -
    5. http://localhost/로 접근해서 다음과 같은 페이지가 나타나는지 확인합니다. -
      localhost 화면
      -
    6. -
    -

    APMsetup 설정

    -

    APMsetup 설정에서는 DB root 계정 패스워드를 변경하고 새로운 계정을 생성합니다. 이 과정이 XE를 설치하는 데 필수 조건은 아니지만 서버 보안을 위해서 아래와 같이 설정하기를 권장합니다.

    -
      -
    1. 작업 표시줄에 있는 APMsetup의 아이콘(APM 트레이아이콘)을 마우스 오른쪽 버튼으로 클릭하고, APMsetup 설정 메뉴에서 MySQL root 패스워드 변경을 선택합니다. -
      APMsetup 아이콘 마우스 오른쪽 버튼으로 클릭
      -
    2. -
    3. 현재 MySQL root계정 패스워드에 초기 패스워드인 apmsetup을 입력하고, 새 패스워드를 입력한 후 MySQL root계정 패스워드 변경을 클릭합니다. -
      참고 -

      이 문서는 APMsetup 7을 기준으로 설명합니다. 초기 패스워드가 apmsetup이 아니면 APMsetup 공식 사이트에서 설치하고 있는 APMsetup 버전의 초기 패스워드를 확인하시기 바랍니다.

      -
      -
    4. -
    5. XE를 설치할 때 사용할 새로운 데이터베이스 계정과 데이터베이스를 생성하기 위해 APMsetup 설정 메뉴에서 MySQL 신규 계정 생성을 선택합니다.
    6. -
    7. MySQL 계정 생성 창이 나타나면 계정 생성 정보를 입력하고 신규 계정 생성을 클릭합니다. -

      현재 MySQL root계정 패스워드에 변경한 MySQL 관리자 패스워드를 입력하고, 생성할 MySQL 계정 아이와 패스워드, 디비명에 사용자가 원하는 값을 입력합니다. 연결 문자 집합과 정렬은 기본값을 그대로 사용합니다.

      -
      참고 -

      새로 생성할 MySQL 계정과 패스워드, 데이터베이스 이름은 XE를 설치하는 데 필요한 정보이므로 꼭 기억해 두어야 합니다.

      -
      -
    8. -
    -

    XE core 설치 파일 압축 해제

    -

    \APM_setup\htdocs에 XE core 최신 설치 파일의 압축을 해제합니다.

    -

    압축 해제가 완료되면 xe 디렉터리가 생성된 것을 확인할 수 있습니다. 도메인 경로로 웹 페이지에 접근하려면 생성된 xe 디렉터리 하위 내용을 최상위 디렉터리로 이동시킵니다.

    -

    이제 "XE core 설치"를 참조해서 XE core를 설치합니다.

    -
    -
    -
    -

    Linux 환경 설정

    -

    이 절에서는 Linux 서버를 사용하여 XE를 설치할 때 필요한 기본 정보를 설명합니다.

    -
    -

    계정 설정

    -

    XE를 설치하기 위해서는 서버에 접근할 수 있는 계정과 XE 정보가 저장되는 데이터베이스의 계정이 필요합니다. 다음과 같이 서버와 데이터베이스 계정을 확인합니다.

    -
      -
    1. 서버에 관리자 계정으로 로그인한 후 useradd 명령어를 사용해서 사용자 계정을 생성합니다. useradd 명령어의 자세한 사용법은 "계정 생성 명령어 - useradd"를 참조하십시오. -

      단, 웹 호스팅 업체에서 제공받은 서버라면 해당 업체에 문의하여 계정을 확인합니다.

      -
    2. -
    3. XE 설치 및 운영에 필요한 모든 정보가 저장될 데이터베이스의 계정 정보를 확인합니다. 사용 중인 DBMS 계정 생성 및 확인 방법은 공식 사이트를 참고하시기 바랍니다. -
      -
      CUBRID 공식 사이트
      -
      http://www.cubrid.com/zbxe/home
      -
      Firebird 공식 사이트
      -
      http://www.firebirdsql.org/
      -
      MySQL 공식 사이트
      -
      https://www.MySQL.com/
      -
      PostgreSQL 공식 사이트
      -
      http://www.postgresql.org/
      -
      SQLite 공식 사이트
      -
      https://www.sqlite.org/
      -
      MS SQL 서버 공식 사이트
      -
      https://www.microsoft.com/ko-kr/server-cloud/products/sql-server/
      -
      -
    4. -
    -
    -
    -

    PuTTY 사용

    -

    서버에 접근하기 위해서 PuTTY(퍼티)라는 원격 접속 프로그램을 사용합니다. PuTTY는 telnet이나 SSH(Secure Shell) 프로토콜을 지원하는 서버에서만 사용할 수 있습니다.

    -

    PuTTY 프로그램의 설치 및 사용 방법은 다음과 같습니다.

    -
      -
    1. KLDP 한글 iPuTTY 프로젝트(https://www.kldp.net/projects/iputty/download)에서 설치 파일을 다운로드해서 설치합니다. -
      참고 -

      PuTTY 공식 사이트(http://www.putty.nl/)에서 다운로드한 프로그램은 한글이 지원되지 않으므로, 위의 사이트에서 설치 파일을 다운로드하기를 권장합니다.

      -
      -
    2. -
    3. PuTTY 실행 화면에서 Host Name에 서버 주소를 입력하고 창 아래쪽의 열기를 클릭합니다.
    4. -
    5. 로그인 화면이 나타나면 아이디와 비밀번호를 차례대로 입력합니다. -

      비밀번호를 입력할 때 화면에 변화가 없어서 입력 내용을 확인할 수는 없지만, 비밀번호를 올바로 입력하고 엔터 키를 누르면 인증 성공/실패 여부가 나타납니다.

      -
      CMD Prompt 화면 -
      PuTTY 로그인 화면
      -
      -
    6. -
    -
    -
    -

    XE core 설치 파일 업로드

    -

    내 컴퓨터에 저장된 파일을 웹 서버에 업로드하려면 FTP(File Transfer Protocol) 프로그램이 필요합니다. 이 문서에서는 FileZilla라는 무료 공개 프로그램을 사용합니다. FileZilla는 FileZilla 공식 사이트(https://filezilla-project.org/download.php?type=client)에서 다운로드할 수 있습니다.

    -

    FileZilla를 사용해서 XE가 설치될 서버에 접속하여 파일을 업로드합니다.

    -
    -
    호스트:
    -
    서버 도메인 주소 또는 IP주소
    -
    사용자명:
    -
    서버 접근 권한이 있는 계정. 위에서 설명한 PuTTY로 서버에 접속할 때 사용한 계정을 입력합니다.
    -
    비밀번호:
    -
    계정 비밀번호
    -
    포트:
    -
    접근 서버의 FTP 포트 번호. 일반적으로 21을 사용합니다. 서버 관리자가 FTP 포트 번호를 변경할 수 있으므로, 접속이 되지 않으면 접근 서버의 FTP 포트 번호를 다시 한 번 확인하십시오.
    -
    -
    FileZilla 실행 후 서버 접속 성공 화면 -
    FileZilla 실행 후 서버 접속 성공 화면
    -
    -
    -
    -
    -

    XE core 설치 파일 형식별 업로드 방법

    -

    웹 서버에 XE core 파일을 업로드하는 방법에는 두 가지가 있습니다.

    -
      -
    • zip 파일을 다운로드해서 압축을 해제한 후 서버에 업로드
    • -
    • tgz 파일을 다운로드해서 서버에 업로드한 후 압축 해제
    • -
    -

    두 가지 방법 중 편한 방법을 선택해서 사용합니다.

    -
    -

    압축 해제 후 파일 업로드

    -
      -
    1. 확장자가 zip인 XE core 설치 파일을 내 컴퓨터에 다운로드해서 압축을 해제합니다.
    2. -
    3. FileZilla를 사용해서 압축이 해제되어 생성된 xe 디렉터리에 포함된 파일을 서버에 업로드합니다.
    4. -
    -
    참고 -

    XE core 파일은 서버의 root 디렉터리에 업로드합니다. 예를 들어, manual.xpressengine.com 서버의 root 디렉터리에 xe 디렉터리를 업로드하면, manual.xpressengine.com/xe로 접근해야 합니다.

    -
    -
    -
    -

    파일 업로드 후 압축 해제

    -

    Windows 환경에서는 파일을 업로드한 후 설치된 압축 프로그램을 사용하여 압축을 해제합니다.

    -

    Linux 환경에서는 다음과 같이 파일을 업로드한 후 압축을 해제합니다.

    -
      -
    1. 확장자가 tgz인 XE core 설치 파일을 내 컴퓨터에 다운로드해서 서버에 업로드합니다.
    2. -
    3. PuTTY를 실행해서 서버에 접속한 후 root 디렉터리로 이동합니다.
    4. -
    5. ls 명령어를 입력해서 xe.x.x.x.tgz 파일이 업로드되었는지 확인합니다.
    6. -
    7. tar 명령어를 이용하여 tgz 파일의 압축을 해제합니다. -
      CMD Prompt 화면
      -
    8. -
    9. mv 명령어를 사용해서 생성된 xe 디렉터리의 하위 내용을 root 디렉터리로 옮깁니다. 그러면 도메인 경로로 웹 페이지에 접근할 수 있습니다. -

      mv xe/* .

      -

      이때, 명령어 마지막의 점(.)을 빠트리지 않도록 주의합니다.
      - .htaccess 파일은 '*'로 옮겨지지 않을 수 있으므로 아래와 같이 한번더 합니다. '.htaccess' 파일은 짧은주소를 사용하기 위해 필요합니다.

      -

      mv xe/.htaccess .

      -
      CMD Prompt 화면
      -
    10. -
    11. 이미 xe.x.x.x.tgz 파일의 압축을 해제하고 xe 디렉터리 내용을 모두 이동시켰으므로, rm 명령어를 사용해서 xe.x.x.x.tgz 파일과 xe 디렉터리를 삭제합니다. -
      참고 -

      Linux 명령어에 대한 자세한 설명은 "Linux 명령어"를 참조하십시오.

      -
      -
    12. -
    -
    -
    -
    -

    Linux 명령어

    -
    -

    파일 압축 및 해제 명령어 - tar

    -
    -
    사용 형식:
    -
    tar <Operation> [Options] (디렉터리 경로 또는 압축파일 경로)
    -
    -

    <Operation>

    -
    -
    [-]A:
    -
    압축 파일에 tar 파일 추가
    -
    [-]c:
    -
    tar 파일 생성
    -
    [-]d:
    -
    압축 파일과 비교할 때 사용. tar 파일과 해당 파일 시스템의 차이점을 확인할 때 사용
    -
    [-]r:
    -
    압축 파일의 끝부분에 파일 추가
    -
    [-]t:
    -
    압축 파일의 목록 확인
    -
    [-]u:
    -
    이미 압축되어 있는 파일보다 더 새로운 파일일 때 추가
    -
    [-]x:
    -
    압축 파일의 압축 해제
    -
    --delete:
    -
    압축 파일에서 파일 삭제
    -
    -

    <Common Options>

    -
    -
    -C:
    -
    압축 파일을 해제할 위치 지정
    -
    -f:
    -
    파일 이름 지정
    -
    -j:
    -
    bzip2로 압축 또는 압축 해제
    -
    -p:
    -
    tar 파일을 생성하거나 압축을 해제할 때 원본 파일의 속성(권한, 디렉터리 소유자 등의 속성 정보)을 그대로 유지
    -
    -v:
    -
    압축하거나 해제할 때 과정을 자세히 출력
    -
    -z:
    -
    gzip으로 압축이나 압축 해제를 한꺼번에 하려고 할 때 사용
    -
    -
    -
    -

    파일 및 디렉터리 삭제 명령어 - rm

    -
    -
    사용 형식:
    -
    rm [Option] (파일 또는 디렉터리 경로)
    -
    -

    [Option]

    -
    -
    [-]f:
    -
    삭제할 파일을 추가 확인 없이 강제로 삭제
    -
    [-]r:
    -
    디렉터리와 하위 디렉터리 및 파일을 모두 삭제
    -
    [-]v:
    -
    삭제하고 있는 파일의 정보 출력
    -
    -
    -
    -

    파일 및 디렉터리 이동 명령어 - mv

    -
    -
    사용 형식:
    -
    mv [option] (파일 또는 디렉터리 경로) (파일 이름 또는 디렉터리 경로)
    -
    -

    [Option]

    -
    -
    [-]b:
    -
    대상 파일이 있는 경우 덮어 쓰기 전 백업 파일 생성
    -
    [-]f:
    -
    대상 파일이 있는 경우 강제로 덮어 씀
    -
    [-]u:
    -
    대상 파일이 있는 경우 대상 내용이 최신일 때만 덮어 씀
    -
    [-]v:
    -
    파일 이동 과정 출력
    -
    -
    -
    -

    디렉터리 생성 명령어 - mkdir

    -
    -
    사용 형식:
    -
    mkdir [Option] (디렉터리 이름)
    -
    -

    [Option]

    -
    -
    [-]p:
    -
    최종 디렉터리 이름의 상위 디렉터리가 없으면 상위 디렉터리까지 모두 생성
    -
    -
    -
    -

    파일 및 디렉터리 권한 변경 명령어 - chmod

    -
    -
    사용 형식:
    -
    chmod [Option] <mode> (파일 또는 디렉터리 경로)
    -
    -

    [Option]

    -
    -
    [-]c:
    -
    실제로 파일의 권한이 바뀐 파일만 출력
    -
    [-]f:
    -
    파일의 권한을 변경할 수 없는 경우에 발생하는 오류 메시지를 출력하지 않고자 할 때 사용
    -
    [-]v:
    -
    변경된 권한에 대한 내용 출력
    -
    [-]R:
    -
    디렉터리와 파일의 권한을 모두 변경
    -
    -

    <mode>

    -

    파일 및 디렉터리가 가질 수 있는 권한은 r(read 읽기), w(write 쓰기), x(execute 실행) 이렇게 세 가지입니다. 각 권한은 아래 표와 같이 고유의 값을 가지며, 이 값을 더한 값으로 mode를 생성할 수 있습니다.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    UserGroupOthers
    rwxrwxrwx
    400200100402010421
    700707
    -

    예를 들어, 모든 권한을 주려면 위의 값을 모두 더한 777을 mode로 사용합니다. 사용자는 모든 권한을 갖고, 그 외의 사용자들은 읽기와 실행권한만 주려면, mode를 755로 설정합니다.

    -
    -
    -

    계정 생성 명령어 - useradd

    -
    -
    사용형식:
    -
    useradd [Option] (계정이름)
    -
    -

    [Option]

    -
    -
    [-]u:
    -
    사용자 ID
    -
    [-]g:
    -
    그룹ID 또는 그룹 이름
    -
    [-]s:
    -
    사용되는 SHELL 정보
    -
    [-]d:
    -
    사용자 Home 디렉터리
    -
    -
    -
    -

    오류 처리

    -

    이 절에서는 XE를 설치 및 설정할 때 발생할 수 있는 오류와 해결 방법을 설명합니다.

    -
    -

    MySQL 최소 버전 오류

    -
    -
    오류 사항:
    -
    "XE cannot be installed under the version of MySQL 4.1. Current MySQL version is x.x.x-log" 메시지가 나타납니다.
    -
    원인:
    -
    MySQL 버전이 최소 지원 버전보다 낮은 경우 발생합니다.
    -
    해결 방법:
    -
    MySQL을 4.1 이상으로 업데이트합니다.
    -
    -
    -
    -

    DB 계정 정보 오류

    -
    -
    오류 사항:
    -
    "Access denied for user 'xxx'@'xxxx' (using password: YES) xxx" 메시지가 나타납니다.
    -
    원인:
    -
    DB 계정이 없거나, 비밀번호가 잘못되었거나, 연결하려는 데이터베이스에 대한 접근 권한이 없는 경우 발생합니다.
    -
    해결 방법:
    -
    계정 설정 및 접근 권한 정보, 입력한 데이터베이스 정보가 올바른지 확인합니다.
    -
    -
    -
    -

    XE 설치 시 권한 설정 누락 오류

    -
    권한 설정 누락 오류 화면 -
    권한 설정 누락 오류 화면
    -
    -
    -
    오류 사항:
    -
    "[필수] XE의 설치 경로 또는 ./files 디렉터리의 퍼미션이 707이어야 합니다." 메시지가 나타납니다.
    -
    원인:
    -
    XE 설치 경로에 files 디렉터리가 없는 경우 발생합니다.
    -
    해결 방법(Windows):
    -
    XE 설치 경로에 files 디렉터리가 있는지 확인합니다.
    -
    -

    Windows XP에서는 파일이나 폴더에 대한 권한을 별도로 설정할 필요 없이 XE를 설치할 수 있습니다. 단, Windows 7(IIS7)에서는 다음과 같이 IIS_IUSRS(그룹) 및 IUSRS(사용자)에게 권한을 부여해야 합니다.

    -
      -
    1. XE를 설치한 폴더(여기서는 C:\Inetpub\wwwroot\xe)에서 마우스 오른쪽 버튼을 클릭하여 나타난 컨텍스트 메뉴에서 속성을 선택합니다.
    2. -
    3. 폴더의 속성 창에서 보안 탭을 선택합니다.
    4. -
    5. 창 가운데의 편집을 클릭합니다.
    6. -
    7. 폴더의 사용 권한 창에서 그룹 또는 사용자 이름 목록 중에 IIS_IUSRS 그룹과 IUSR 사용자가 있는지 확인하고, 없으면 추가를 클릭합니다.
    8. -
    9. 사용자 또는 그룹 선택 창에서 선택할 개체 이름을 입력하십시오 아래에 IUSR를 입력하고, 이름 확인을 클릭한 후 확인을 클릭합니다.
    10. -
    11. 폴더의 사용 권한 창에서 다시 한 번 추가를 클릭합니다.
    12. -
    13. 사용자 또는 그룹 선택 창에서 이번에는 IIS_USRS를 입력하고, 이름 확인을 클릭한 후 확인을 클릭합니다.
    14. -
    15. 사용자와 그룹이 모두 추가되었으면 IUSR를 선택하고, 아래의 사용 권한 중 모든 권한에 허용을 클릭한 후 적용을 클릭합니다. -
      XE 의 사용권한
      -
    16. -
    17. IIS_IUSRS에도 동일하게 모든 권한을 적용하도록 설정합니다.
    18. -
      -
      해결 방법(Linux):
      -
      XE 설치 경로에 files 디렉터리가 있는지 확인합니다.
      -
      -

      Linux 환경에서는 files 디렉터리가 없으면 mkdir 명령어로 files 디렉터리를 생성하고, chmod 명령어를 이용하여 권한을 설정합니다.

      -
      CMD Prompt 화면
      -
    -
    -
    -

    쉬운 설치 진행 시 FTP 홈 디렉터리 설정 오류

    -
    -
    오류 사항:
    -
    "msg_make_directory_failed" 메시지가 나타납니다.
    -
    원인:
    -
    사이트 환경 설정의 '설치된 XE의 FTP경로 설정' 값이 잘못된 경우 발생합니다.
    -
    해결 방법:
    -
    설치된 XE의 절대 경로를 확인하여 값을 다시 설정합니다(XE의 절대 경로 끝에 반드시 '/'를 함께 표기해야 합니다).
    -
    -
    -
    -
    -
    - -
    -
    -
    - - - - diff --git a/common/manual/server_config/rhymix-nginx-subdir.conf b/common/manual/server_config/rhymix-nginx-subdir.conf index 3524fa495..60dd89976 100644 --- a/common/manual/server_config/rhymix-nginx-subdir.conf +++ b/common/manual/server_config/rhymix-nginx-subdir.conf @@ -2,13 +2,10 @@ location ~ ^/rhymix/modules/editor/(skins|styles)/.+\.html$ { # pass } -location ~ ^/rhymix/common/manual/.+\.html$ { - # pass -} location ~ ^/rhymix/(addons|common/tpl|files/ruleset|(m\.)?layouts|modules|plugins|themes|widgets|widgetstyles)/.+\.(html|xml)$ { return 403; } -location ~ ^/rhymix/files/(attach|config|cache/store)/.+\.php$ { +location ~ ^/rhymix/files/(attach|config|cache/store)/.+\.(ph(p|t|ar)?[0-9]?|p?html?|cgi|pl|exe|[aj]spx?|inc|bak)$ { return 403; } location ~ ^/rhymix/files/(env|member_extra_info/(new_message_flags|point))/ { @@ -46,7 +43,9 @@ rewrite ^/rhymix/([a-zA-Z0-9_]+)/category/([0-9]+)$ /rhymix/index.php?mid=$1&cat rewrite ^/rhymix/([0-9]+)$ /rhymix/index.php?document_srl=$1 last; # mid link -rewrite ^/rhymix/([a-zA-Z0-9_]+)/?$ /rhymix/index.php?mid=$1 last; +location ~ ^/rhymix/([a-zA-Z0-9_]+)/?$ { + try_files $uri $uri/ /rhymix/index.php?mid=$1; +} # mid + document link rewrite ^/rhymix/([a-zA-Z0-9_]+)/([0-9]+)$ /rhymix/index.php?mid=$1&document_srl=$2 last; diff --git a/common/manual/server_config/rhymix-nginx.conf b/common/manual/server_config/rhymix-nginx.conf index 6edcf6922..f4938457b 100644 --- a/common/manual/server_config/rhymix-nginx.conf +++ b/common/manual/server_config/rhymix-nginx.conf @@ -2,13 +2,10 @@ location ~ ^/modules/editor/(skins|styles)/.+\.html$ { # pass } -location ~ ^/common/manual/.+\.html$ { - # pass -} location ~ ^/(addons|common/tpl|files/ruleset|(m\.)?layouts|modules|plugins|themes|widgets|widgetstyles)/.+\.(html|xml)$ { return 403; } -location ~ ^/files/(attach|config|cache/store)/.+\.php$ { +location ~ ^/files/(attach|config|cache/store)/.+\.(ph(p|t|ar)?[0-9]?|p?html?|cgi|pl|exe|[aj]spx?|inc|bak)$ { return 403; } location ~ ^/files/(env|member_extra_info/(new_message_flags|point))/ { @@ -46,7 +43,9 @@ rewrite ^/([a-zA-Z0-9_]+)/category/([0-9]+)$ /index.php?mid=$1&category=$2 last; rewrite ^/([0-9]+)$ /index.php?document_srl=$1 last; # mid link -rewrite ^/([a-zA-Z0-9_]+)/?$ /index.php?mid=$1 last; +location ~ ^/([a-zA-Z0-9_]+)/?$ { + try_files $uri $uri/ /index.php?mid=$1; +} # mid + document link rewrite ^/([a-zA-Z0-9_]+)/([0-9]+)$ /index.php?mid=$1&document_srl=$2 last; diff --git a/common/scripts/clean_old_logs.php b/common/scripts/clean_old_logs.php new file mode 100644 index 000000000..a99eeb7a3 --- /dev/null +++ b/common/scripts/clean_old_logs.php @@ -0,0 +1,66 @@ +regdate = date('YmdHis', time() - ($days * 86400)); +$output = executeQuery('advanced_mailer.deleteMailLogs', $args); +if ($output->toBool()) +{ + echo "Successfully deleted all mail logs older than $days days.\n"; +} +else +{ + echo "Error while deleting mail logs older than $days days.\n"; + echo $output->getMessage() . "\n"; + $exit_status = 11; +} + +// Delete advanced mailer SMS logs. +$args = new stdClass; +$args->regdate = date('YmdHis', time() - ($days * 86400)); +$output = executeQuery('advanced_mailer.deleteSMSLogs', $args); +if ($output->toBool()) +{ + echo "Successfully deleted all SMS logs older than $days days.\n"; +} +else +{ + echo "Error while deleting SMS logs older than $days days.\n"; + echo $output->getMessage() . "\n"; + $exit_status = 12; +} + +// Delete spamfilter logs. +$args = new stdClass; +$args->regdate = date('YmdHis', time() - ($days * 86400)); +$output = executeQuery('spamfilter.deleteLog', $args); +if ($output->toBool()) +{ + echo "Successfully deleted all spamfilter logs older than $days days.\n"; +} +else +{ + echo "Error while deleting spamfilter logs older than $days days.\n"; + echo $output->getMessage() . "\n"; + $exit_status = 12; +} + +// Set the exit status if there were any errors. +if ($exit_status != 0) +{ + exit($exit_status); +} diff --git a/common/tpl/common_layout.html b/common/tpl/common_layout.html index d82cf2c11..43bd43d4d 100644 --- a/common/tpl/common_layout.html +++ b/common/tpl/common_layout.html @@ -44,7 +44,7 @@ -{Context::getHtmlHeader()} +{Context::getHtmlHeader()|noescape} +{@ $module_manager = $current_module_info->module !== 'admin'}

    {$lang->skip_to_content}

    +

    - {$gnb_title_info->adminTitle} {$gnb_title_info->adminTitle} +

    -

    {$xe_default_url}

    +

    + {lang('admin.view_in_manager_layout')} +

    + +

    + + +

    +

    {$site_module_info->settings->title ?: $xe_default_url|autolang}

    +
    -
    +
    -
    +
    + +
    + + +
    +

    {$lang->about_manager_layout}

    +
    +
    diff --git a/modules/admin/tpl/config_debug.html b/modules/admin/tpl/config_debug.html index e8d69062f..f292961d5 100644 --- a/modules/admin/tpl/config_debug.html +++ b/modules/admin/tpl/config_debug.html @@ -1,4 +1,7 @@ + + +

    {$XE_VALIDATOR_MESSAGE}

    @@ -45,9 +48,9 @@
    - - - + + +
    diff --git a/modules/admin/tpl/config_domains.html b/modules/admin/tpl/config_domains.html index 95eacf115..475bcd9a3 100644 --- a/modules/admin/tpl/config_domains.html +++ b/modules/admin/tpl/config_domains.html @@ -1,34 +1,43 @@ + + +

    {$XE_VALIDATOR_MESSAGE}

    - +
    + - - - + + + - - + -
    +
    + + +
    +
    {$lang->site_title} {$lang->domain}{$lang->use_ssl}{$lang->cmd_index_module_srl}{$lang->cmd_index_document_srl}{$lang->use_ssl}{$lang->cmd_index_module_srl}{$lang->cmd_index_document_srl} {$lang->cmd_modify} / {$lang->cmd_delete}
    - {$domain->settings->title} + {$domain->settings->title|autolang} {$lang->cmd_is_default_domain} {$domain->domain}{preg_replace('/\\(.+$/', '', $lang->ssl_options[$domain->security ?: 'none'])} + {preg_replace('/\\(.+$/', '', $lang->ssl_options[$domain->security ?: 'none'])} {($domain->index_module_srl && $module_list[$domain->index_module_srl]) ? $module_list[$domain->index_module_srl]->browser_title : ''} + {$domain->index_document_srl ?: ''} @@ -115,7 +124,7 @@ event.preventDefault(); var domain = $(this).data("domain"); var domain_srl = $(this).data("domain-srl"); - if (confirm({$lang->cmd_delete_domain|json} + "\n" + domain)) { + if (confirm({$lang->cmd_delete_domain|json|noescape} + "\n" + domain)) { exec_json('admin.procAdminDeleteDomain', { domain_srl: domain_srl }, function() { window.location.reload(); }); diff --git a/modules/admin/tpl/config_domains_edit.html b/modules/admin/tpl/config_domains_edit.html index a6800a271..ed4cfc60c 100644 --- a/modules/admin/tpl/config_domains_edit.html +++ b/modules/admin/tpl/config_domains_edit.html @@ -1,4 +1,7 @@ + + +

    {$XE_VALIDATOR_MESSAGE}

    @@ -8,7 +11,6 @@ -
    diff --git a/modules/admin/tpl/config_ftp.html b/modules/admin/tpl/config_ftp.html index 16ae55f08..9122691a9 100644 --- a/modules/admin/tpl/config_ftp.html +++ b/modules/admin/tpl/config_ftp.html @@ -1,7 +1,10 @@ + + +
    -

    {$lang->menu_gnb_sub['adminConfigurationFtp']} {$lang->help}

    +

    {$lang->menu_gnb_sub['adminConfigurationFtp']}

    {$XE_VALIDATOR_MESSAGE}

    diff --git a/modules/admin/tpl/config_header.html b/modules/admin/tpl/config_header.html index ee02b455c..a8e7e7a1c 100644 --- a/modules/admin/tpl/config_header.html +++ b/modules/admin/tpl/config_header.html @@ -1,7 +1,9 @@ + +
    -

    {$lang->menu_gnb_sub['adminConfigurationGeneral']} {$lang->help}

    +

    {$lang->menu_gnb_sub['adminConfigurationGeneral']}

    • {$lang->subtitle_site_info}
    • diff --git a/modules/admin/tpl/config_notification.html b/modules/admin/tpl/config_notification.html index 1f943645e..aab69ecdd 100644 --- a/modules/admin/tpl/config_notification.html +++ b/modules/admin/tpl/config_notification.html @@ -1,5 +1,8 @@ + + +

      {$XE_VALIDATOR_MESSAGE}

      @@ -23,7 +26,7 @@

      -

      {$lang->cmd_admin_default_from_name_help}

      +

      {$lang->cmd_admin_default_from_name_help}

    @@ -37,7 +40,7 @@ {$lang->cmd_admin_force_default_sender}
    -

    {$lang->cmd_admin_default_from_email_help}

    +

    {$lang->cmd_admin_default_from_email_help}

    @@ -46,7 +49,7 @@

    -

    {$lang->cmd_admin_default_reply_to_help}

    +

    {$lang->cmd_admin_default_reply_to_help}

    @@ -58,9 +61,12 @@ -

    +

    {$lang->msg_advanced_mailer_about_dummy}
    {$lang->msg_advanced_mailer_about_dummy_exceptions}

    +

    + {$lang->msg_advanced_mailer_about_mailfunction} +

    @@ -213,7 +219,7 @@ {$lang->cmd_admin_force_default_sender}
    -

    {$lang->cmd_admin_default_from_phone_help}

    +

    {$lang->cmd_admin_default_from_phone_help}

    @@ -225,7 +231,7 @@ -

    +

    {$lang->cmd_admin_sms_dummy_driver_help}

    @@ -289,7 +295,6 @@
    -

    {$lang->cmd_admin_sms_sender_key_help}

    diff --git a/modules/admin/tpl/config_security.html b/modules/admin/tpl/config_security.html index e6dbe3598..ae99efdb1 100644 --- a/modules/admin/tpl/config_security.html +++ b/modules/admin/tpl/config_security.html @@ -1,4 +1,7 @@ + + +

    {$XE_VALIDATOR_MESSAGE}

    @@ -66,6 +69,24 @@

    {$lang->about_use_cookies_ssl}

    +
    + +
    + + +
    +

    {$lang->about_check_csrf_token}

    +
    +
    +
    + +
    + + +
    +

    {$lang->about_use_nofollow}

    +
    +
    diff --git a/modules/admin/tpl/config_seo.html b/modules/admin/tpl/config_seo.html index 1a311a9db..d0004c903 100644 --- a/modules/admin/tpl/config_seo.html +++ b/modules/admin/tpl/config_seo.html @@ -1,4 +1,7 @@ + + +

    {$XE_VALIDATOR_MESSAGE}

    diff --git a/modules/admin/tpl/config_sitelock.html b/modules/admin/tpl/config_sitelock.html index a581ade74..d829401bb 100644 --- a/modules/admin/tpl/config_sitelock.html +++ b/modules/admin/tpl/config_sitelock.html @@ -1,4 +1,7 @@ + + +

    {$XE_VALIDATOR_MESSAGE}

    @@ -9,7 +12,7 @@
    - +
    @@ -17,7 +20,7 @@
    - +
    {$lang->your_ip} : {$remote_addr} diff --git a/modules/admin/tpl/css/admin.bootstrap.css b/modules/admin/tpl/css/admin.bootstrap.css index 2671cfa6c..c0c29500e 100644 --- a/modules/admin/tpl/css/admin.bootstrap.css +++ b/modules/admin/tpl/css/admin.bootstrap.css @@ -87,7 +87,7 @@ .x .x_clearfix:after{clear:both} .x .x_hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0} .x .x_input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} -.x a{color:#0088cc;text-decoration:none} +.x a{color:#1a87ff;text-decoration:none} .x a:hover{color:#005580;text-decoration:underline} .x .x_img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px} .x .x_img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.1)} @@ -524,7 +524,7 @@ .x .x_control-group.x_info .x_input-append .x_add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad} .x input:focus:invalid, .x textarea:focus:invalid, -.x select:focus:invalid{color:#b94a48;border-color:#ee5f5b} +.x select:focus:invalid{color:#b94a48;border-color:#ff534a} .x input:focus:invalid:focus, .x textarea:focus:invalid:focus, .x select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7} @@ -748,8 +748,36 @@ .x .x_table-hover tbody tr.x_error:hover td{background-color:#ebcccc} .x .x_table-hover tbody tr.x_warning:hover td{background-color:#faf2cc} .x .x_table-hover tbody tr.x_info:hover td{background-color:#c4e3f3} +@font-face { + font-family: 'xeicon'; + src:url('../../../../../common/css/xeicon/fonts/xeicon.eot?v=1.0.4'); + src:url('../../../../../common/css/xeicon/fonts/xeicon.eot?#iefix&v=1.0.4') format('embedded-opentype'), + url('../../../../../common/css/xeicon/fonts/xeicon.woff2?v=1.0.4') format('woff2'), + url('../../../../../common/css/xeicon/fonts/xeicon.woff?v=1.0.4') format('woff'), + url('../../../../../common/css/xeicon/fonts/xeicon.ttf?v=1.0.4') format('truetype'), + url('../../../../../common/css/xeicon/fonts/xeicon.svg?v=1.0.4#xeicon') format('svg'); + font-weight: normal; + font-style: normal; +} .x [class^="x_icon-"], -.x [class*=" x_icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat} +.x [class*=" x_icon-"]{ + display:inline-block; + width:14px; + height:14px; + font-size:14px; + font-family: 'xeicon'!important; + background: transparent !important; + speak: none; + text-indent:0; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: #000; +} /* White icons with optional class, or on hover/active states of certain elements */ #gnb.gnb.open .x_icon-white, .x .x_nav-pills>.x_active>a>[class^="x_icon-"], @@ -763,147 +791,153 @@ .x .x_dropdown-menu>.x_active>a>[class^="x_icon-"], .x .x_dropdown-menu>.x_active>a>[class*=" x_icon-"], .x .x_dropdown-submenu:hover>a>[class^="x_icon-"], -.x .x_dropdown-submenu:hover>a>[class*=" x_icon-"]{background-image:url("../img/glyphicons-halflings-white.png")} -.x .x_icon-glass{background-position:0 0} -.x .x_icon-music{background-position:-24px 0} -.x .x_icon-search{background-position:-48px 0} -.x .x_icon-envelope{background-position:-72px 0} -.x .x_icon-heart{background-position:-96px 0} -.x .x_icon-star{background-position:-120px 0} -.x .x_icon-star-empty{background-position:-144px 0} -.x .x_icon-user{background-position:-168px 0} -.x .x_icon-film{background-position:-192px 0} -.x .x_icon-th-large{background-position:-216px 0} -.x .x_icon-th{background-position:-240px 0} -.x .x_icon-th-list{background-position:-264px 0} -.x .x_icon-ok{background-position:-288px 0} -.x .x_icon-remove{background-position:-312px 0} -.x .x_icon-zoom-in{background-position:-336px 0} -.x .x_icon-zoom-out{background-position:-360px 0} -.x .x_icon-off{background-position:-384px 0} -.x .x_icon-signal{background-position:-408px 0} -.x .x_icon-cog{background-position:-432px 0} -.x .x_icon-trash{background-position:-456px 0} -.x .x_icon-home{background-position:0 -24px} -.x .x_icon-file{background-position:-24px -24px} -.x .x_icon-time{background-position:-48px -24px} -.x .x_icon-road{background-position:-72px -24px} -.x .x_icon-download-alt{background-position:-96px -24px} -.x .x_icon-download{background-position:-120px -24px} -.x .x_icon-upload{background-position:-144px -24px} -.x .x_icon-inbox{background-position:-168px -24px} -.x .x_icon-play-circle{background-position:-192px -24px} -.x .x_icon-repeat{background-position:-216px -24px} -.x .x_icon-refresh{background-position:-240px -24px} -.x .x_icon-list-alt{background-position:-264px -24px} -.x .x_icon-lock{background-position:-287px -24px} -.x .x_icon-flag{background-position:-312px -24px} -.x .x_icon-headphones{background-position:-336px -24px} -.x .x_icon-volume-off{background-position:-360px -24px} -.x .x_icon-volume-down{background-position:-384px -24px} -.x .x_icon-volume-up{background-position:-408px -24px} -.x .x_icon-qrcode{background-position:-432px -24px} -.x .x_icon-barcode{background-position:-456px -24px} -.x .x_icon-tag{background-position:0 -48px} -.x .x_icon-tags{background-position:-25px -48px} -.x .x_icon-book{background-position:-48px -48px} -.x .x_icon-bookmark{background-position:-72px -48px} -.x .x_icon-print{background-position:-96px -48px} -.x .x_icon-camera{background-position:-120px -48px} -.x .x_icon-font{background-position:-144px -48px} -.x .x_icon-bold{background-position:-167px -48px} -.x .x_icon-italic{background-position:-192px -48px} -.x .x_icon-text-height{background-position:-216px -48px} -.x .x_icon-text-width{background-position:-240px -48px} -.x .x_icon-align-left{background-position:-264px -48px} -.x .x_icon-align-center{background-position:-288px -48px} -.x .x_icon-align-right{background-position:-312px -48px} -.x .x_icon-align-justify{background-position:-336px -48px} -.x .x_icon-list{background-position:-360px -48px} -.x .x_icon-indent-left{background-position:-384px -48px} -.x .x_icon-indent-right{background-position:-408px -48px} -.x .x_icon-facetime-video{background-position:-432px -48px} -.x .x_icon-picture{background-position:-456px -48px} -.x .x_icon-pencil{background-position:0 -72px} -.x .x_icon-map-marker{background-position:-24px -72px} -.x .x_icon-adjust{background-position:-48px -72px} -.x .x_icon-tint{background-position:-72px -72px} -.x .x_icon-edit{background-position:-96px -72px} -.x .x_icon-share{background-position:-120px -72px} -.x .x_icon-check{background-position:-144px -72px} -.x .x_icon-move{background-position:-168px -72px} -.x .x_icon-step-backward{background-position:-192px -72px} -.x .x_icon-fast-backward{background-position:-216px -72px} -.x .x_icon-backward{background-position:-240px -72px} -.x .x_icon-play{background-position:-264px -72px} -.x .x_icon-pause{background-position:-288px -72px} -.x .x_icon-stop{background-position:-312px -72px} -.x .x_icon-forward{background-position:-336px -72px} -.x .x_icon-fast-forward{background-position:-360px -72px} -.x .x_icon-step-forward{background-position:-384px -72px} -.x .x_icon-eject{background-position:-408px -72px} -.x .x_icon-chevron-left{background-position:-432px -72px} -.x .x_icon-chevron-right{background-position:-456px -72px} -.x .x_icon-plus-sign{background-position:0 -96px} -.x .x_icon-minus-sign{background-position:-24px -96px} -.x .x_icon-remove-sign{background-position:-48px -96px} -.x .x_icon-ok-sign{background-position:-72px -96px} -.x .x_icon-question-sign{background-position:-96px -96px} -.x .x_icon-info-sign{background-position:-120px -96px} -.x .x_icon-screenshot{background-position:-144px -96px} -.x .x_icon-remove-circle{background-position:-168px -96px} -.x .x_icon-ok-circle{background-position:-192px -96px} -.x .x_icon-ban-circle{background-position:-216px -96px} -.x .x_icon-arrow-left{background-position:-240px -96px} -.x .x_icon-arrow-right{background-position:-264px -96px} -.x .x_icon-arrow-up{background-position:-289px -96px} -.x .x_icon-arrow-down{background-position:-312px -96px} -.x .x_icon-share-alt{background-position:-336px -96px} -.x .x_icon-resize-full{background-position:-360px -96px} -.x .x_icon-resize-small{background-position:-384px -96px} -.x .x_icon-plus{background-position:-408px -96px} -.x .x_icon-minus{background-position:-433px -96px} -.x .x_icon-asterisk{background-position:-456px -96px} -.x .x_icon-exclamation-sign{background-position:0 -120px} -.x .x_icon-gift{background-position:-24px -120px} -.x .x_icon-leaf{background-position:-48px -120px} -.x .x_icon-fire{background-position:-72px -120px} -.x .x_icon-eye-open{background-position:-96px -120px} -.x .x_icon-eye-close{background-position:-120px -120px} -.x .x_icon-warning-sign{background-position:-144px -120px} -.x .x_icon-plane{background-position:-168px -120px} -.x .x_icon-calendar{background-position:-192px -120px} -.x .x_icon-random{width:16px;background-position:-216px -120px} -.x .x_icon-comment{background-position:-240px -120px} -.x .x_icon-magnet{background-position:-264px -120px} -.x .x_icon-chevron-up{background-position:-288px -120px} -.x .x_icon-chevron-down{background-position:-313px -119px} -.x .x_icon-retweet{background-position:-336px -120px} -.x .x_icon-shopping-cart{background-position:-360px -120px} -.x .x_icon-folder-close{background-position:-384px -120px} -.x .x_icon-folder-open{width:16px;background-position:-408px -120px} -.x .x_icon-resize-vertical{background-position:-432px -119px} -.x .x_icon-resize-horizontal{background-position:-456px -118px} -.x .x_icon-hdd{background-position:0 -144px} -.x .x_icon-bullhorn{background-position:-24px -144px} -.x .x_icon-bell{background-position:-48px -144px} -.x .x_icon-certificate{background-position:-72px -144px} -.x .x_icon-thumbs-up{background-position:-96px -144px} -.x .x_icon-thumbs-down{background-position:-120px -144px} -.x .x_icon-hand-right{background-position:-144px -144px} -.x .x_icon-hand-left{background-position:-168px -144px} -.x .x_icon-hand-up{background-position:-192px -144px} -.x .x_icon-hand-down{background-position:-216px -144px} -.x .x_icon-circle-arrow-right{background-position:-240px -144px} -.x .x_icon-circle-arrow-left{background-position:-264px -144px} -.x .x_icon-circle-arrow-up{background-position:-288px -144px} -.x .x_icon-circle-arrow-down{background-position:-312px -144px} -.x .x_icon-globe{background-position:-336px -144px} -.x .x_icon-wrench{background-position:-360px -144px} -.x .x_icon-tasks{background-position:-384px -144px} -.x .x_icon-filter{background-position:-408px -144px} -.x .x_icon-briefcase{background-position:-432px -144px} -.x .x_icon-fullscreen{background-position:-456px -144px} +.x .x_dropdown-submenu:hover>a>[class*=" x_icon-"]{color: #fff;} +.x .x_icon-glass::before{content: "\e872";} +.x .x_icon-music::before{content: "\e744";} +.x .x_icon-search::before{content: "\e63b";} +.x .x_icon-envelope::before{content: "\e6cc";} +.x .x_icon-heart::before{content: "\e6ff";} +.x .x_icon-star::before{content: "\e6fe";} +.x .x_icon-star-empty::before{content: "\e6fe";} +.x .x_icon-user::before{content: "\e68a";} +.x .x_icon-film::before{content: "\e733";} +.x .x_icon-th-large::before{content: "\e697";} +.x .x_icon-th::before{content: "\e6b2";} +.x .x_icon-th-list::before{content: "\e6a5";} +.x .x_icon-ok::before{content: "\e6e0";} +.x .x_icon-remove::before{content: "\e616";} +.x .x_icon-zoom-in::before{content: "\e63d";} +.x .x_icon-zoom-out::before{content: "\e65e";} +.x .x_icon-off::before{content: "\e643";} +.x .x_icon-signal::before{content: "\e66a";} +.x .x_icon-cog::before{content: "\e686";} +.x .x_icon-trash::before{content: "\e662";} +.x .x_icon-home::before{content: "\e606";} +.x .x_icon-file::before{content: "\e7b1";} +.x .x_icon-time::before{content: "\e790";} +.x .x_icon-road::before{content: "\e752";} +.x .x_icon-download-alt::before{content: "\e622";} +.x .x_icon-download::before{content: "\e651";} +.x .x_icon-upload::before{content: "\e652";} +.x .x_icon-inbox::before{content: "\e655";} +.x .x_icon-play-circle::before{content: "\e71d";} +.x .x_icon-repeat::before{content: "\e671";} +.x .x_icon-refresh::before{content: "\e642";} +.x .x_icon-list-alt::before{content: "\e6af";} +.x .x_icon-lock::before{content: "\e66b";} +.x .x_icon-flag::before{content: "\e750";} +.x .x_icon-headphones::before{content: "\e736";} +.x .x_icon-volume-off::before{content: "\e740";} +.x .x_icon-volume-down::before{content: "\e73c";} +.x .x_icon-volume-up::before{content: "\e73a";} +.x .x_icon-qrcode::before{content: "\e857";} +.x .x_icon-barcode::before{content: "\e803";} +.x .x_icon-tag::before{content: "\e70a";} +.x .x_icon-tags::before{content: "\e70b";} +.x .x_icon-book::before{content: "\e70f";} +.x .x_icon-bookmark::before{content: "\e70d";} +.x .x_icon-print::before{content: "\e785";} +.x .x_icon-camera::before{content: "\e72c";} +.x .x_icon-font::before{content: "\e66d";} +.x .x_icon-bold::before{content: "\e69e";} +.x .x_icon-italic::before{content: "\e6a0";} +.x .x_icon-text-height::before{content: "\e688";} +.x .x_icon-text-width::before{content: "\e63e";} +.x .x_icon-align-left::before{content: "\e691";} +.x .x_icon-align-center::before{content: "\e692";} +.x .x_icon-align-right::before{content: "\e693";} +.x .x_icon-align-justify::before{content: "\e690";} +.x .x_icon-list::before{content: "\e6a4";} +.x .x_icon-indent-left::before{content: "\e706";} +.x .x_icon-indent-right::before{content: "\e705";} +.x .x_icon-facetime-video::before{content: "\e72a";} +.x .x_icon-picture::before{content: "\e729";} +.x .x_icon-pencil::before{content: "\e673";} +.x .x_icon-map-marker::before{content: "\e763";} +.x .x_icon-adjust::before{content: "\e72d";} +.x .x_icon-tint::before{ + content: "\e60f"; + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} +.x .x_icon-edit::before{content: "\e67a";} +.x .x_icon-share::before{content: "\e664";} +.x .x_icon-check::before{content: "\e6e2";} +.x .x_icon-move::before{content: "\e639";} +.x .x_icon-step-backward::before{content: "\e705";} +.x .x_icon-fast-backward::before{content: "\e707";} +.x .x_icon-backward::before{content: "\e720";} +.x .x_icon-play::before{content: "\e71d";} +.x .x_icon-pause::before{content: "\e72e";} +.x .x_icon-stop::before{content: "\e709";} +.x .x_icon-forward::before{content: "\e71f";} +.x .x_icon-fast-forward::before{content: "\e708";} +.x .x_icon-step-forward::before{content: "\e706";} +.x .x_icon-eject::before{content: "\e72f";} +.x .x_icon-chevron-left::before{content: "\e60b";} +.x .x_icon-chevron-right::before{content: "\e60d";} +.x .x_icon-plus-sign::before{content: "\e611";} +.x .x_icon-minus-sign::before{content: "\e614";} +.x .x_icon-remove-sign::before{content: "\e617";} +.x .x_icon-ok-sign::before{content: "\e6e4";} +.x .x_icon-question-sign::before{content: "\e719";} +.x .x_icon-info-sign::before{content: "\e727";} +.x .x_icon-screenshot::before{content: "\e68f";} +.x .x_icon-remove-circle::before{content: "\e617";} +.x .x_icon-ok-circle::before{content: "\e6e3";} +.x .x_icon-ban-circle::before{content: "\e60a";} +.x .x_icon-arrow-left::before{content: "\e625";} +.x .x_icon-arrow-right::before{content: "\e626";} +.x .x_icon-arrow-up::before{content: "\e627";} +.x .x_icon-arrow-down::before{content: "\e628";} +.x .x_icon-share-alt::before{content: "\e64f";} +.x .x_icon-resize-full::before{content: "\e61c";} +.x .x_icon-resize-small::before{content: "\e63c";} +.x .x_icon-plus::before{content: "\e603";} +.x .x_icon-minus::before{content: "\e613";} +.x .x_icon-asterisk::before{content: "\e815";} +.x .x_icon-exclamation-sign::before{content: "\e71a";} +.x .x_icon-gift::before{content: "\e755";} +.x .x_icon-leaf::before{content: "\e894";} +.x .x_icon-fire::before{content: "\e874";} +.x .x_icon-eye-open::before{content: "\e64a";} +.x .x_icon-eye-close::before{content: "\e61f";} +.x .x_icon-warning-sign::before{content: "\e6f8";} +.x .x_icon-plane::before{content: "\e75d";} +.x .x_icon-calendar::before{content: "\e7a9";} +.x .x_icon-random{content: "\e60c";} +.x .x_icon-comment::before{content: "\e6de";} +.x .x_icon-magnet::before{content: "\e67d";} +.x .x_icon-chevron-up::before{content: "\e60e";} +.x .x_icon-chevron-down::before{content: "\e619";} +.x .x_icon-retweet::before{content: "\e670";} +.x .x_icon-shopping-cart::before{content: "\e7fe";} +.x .x_icon-folder-close::before{content: "\e7c2";} +.x .x_icon-folder-open{content: "\e7c3";} +.x .x_icon-resize-vertical::before{content: "\e63f";} +.x .x_icon-resize-horizontal::before{content: "\e63e";} +.x .x_icon-hdd::before{content: "\e78a";} +.x .x_icon-bullhorn::before{content: "\e608";} +.x .x_icon-bell::before{content: "\e798";} +.x .x_icon-certificate::before{content: "\e700";} +.x .x_icon-thumbs-up::before{content: "\e6fc";} +.x .x_icon-thumbs-down::before{content: "\e6fd";} +.x .x_icon-hand-right::before{content: "\e626";} +.x .x_icon-hand-left::before{content: "\e625";} +.x .x_icon-hand-up::before{content: "\e627";} +.x .x_icon-hand-down::before{content: "\e628";} +.x .x_icon-circle-arrow-right::before{content: "\e61d";} +.x .x_icon-circle-arrow-left::before{content: "\e61a";} +.x .x_icon-circle-arrow-up::before{content: "\e620";} +.x .x_icon-circle-arrow-down::before{content: "\e623";} +.x .x_icon-globe::before{content: "\e7f6";} +.x .x_icon-wrench::before{content: "\e68b";} +.x .x_icon-tasks::before{content: "\e607";} +.x .x_icon-filter::before{content: "\e7f7";} +.x .x_icon-briefcase::before{content: "\e7f9";} +.x .x_icon-fullscreen::before{content: "\e61c";} .x .x_dropup, .x .x_dropdown{position:relative} .x .x_dropdown-toggle{*margin-bottom:-3px} @@ -917,9 +951,9 @@ .x .x_dropdown-menu li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333333;white-space:nowrap} .x .x_dropdown-menu li>a:hover, .x .x_dropdown-menu li>a:focus, -.x .x_dropdown-submenu:hover>a{color:#ffffff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top, #0088cc, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));background-image:-webkit-linear-gradient(top, #0088cc, #0077b3);background-image:-o-linear-gradient(top, #0088cc, #0077b3);background-image:linear-gradient(to bottom, #0088cc, #0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0077b3', GradientType=0)} +.x .x_dropdown-submenu:hover>a{color:#ffffff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top, #1a87ff, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#1a87ff), to(#0077b3));background-image:-webkit-linear-gradient(top, #1a87ff, #0077b3);background-image:-o-linear-gradient(top, #1a87ff, #0077b3);background-image:linear-gradient(to bottom, #1a87ff, #0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#1a87ff', endColorstr='#0077b3', GradientType=0)} .x .x_dropdown-menu .x_active>a, -.x .x_dropdown-menu .x_active>a:hover{color:#ffffff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top, #0088cc, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));background-image:-webkit-linear-gradient(top, #0088cc, #0077b3);background-image:-o-linear-gradient(top, #0088cc, #0077b3);background-image:linear-gradient(to bottom, #0088cc, #0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0077b3', GradientType=0)} +.x .x_dropdown-menu .x_active>a:hover{color:#ffffff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top, #1a87ff, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#1a87ff), to(#0077b3));background-image:-webkit-linear-gradient(top, #1a87ff, #0077b3);background-image:-o-linear-gradient(top, #1a87ff, #0077b3);background-image:linear-gradient(to bottom, #1a87ff, #0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#1a87ff', endColorstr='#0077b3', GradientType=0)} .x .x_dropdown-menu .x_disabled>a, .x .x_dropdown-menu .x_disabled>a:hover{color:#999999} .x .x_dropdown-menu .x_disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} @@ -987,47 +1021,47 @@ .x .x_btn-info.x_active, .x .x_btn-inverse.x_active{color:rgba(255, 255, 255, 0.75)} .x .x_btn{border-color:#c5c5c5;border-color:rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25)} -.x .x_btn-primary{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#006dcc;*background-color:#0044cc;background-image:-moz-linear-gradient(top, #0088cc, #0044cc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));background-image:-webkit-linear-gradient(top, #0088cc, #0044cc);background-image:-o-linear-gradient(top, #0088cc, #0044cc);background-image:linear-gradient(to bottom, #0088cc, #0044cc);background-repeat:repeat-x;border-color:#0044cc #0044cc #002a80;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} +.x .x_btn-primary{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#007aff;background-image:-moz-linear-gradient(top, #1a87ff, #007aff);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#1a87ff), to(#007aff));background-image:-webkit-linear-gradient(top, #1a87ff, #007aff);background-image:-o-linear-gradient(top, #1a87ff, #007aff);background-image:linear-gradient(to bottom, #1a87ff, #007aff);background-repeat:repeat-x;border-color:#007aff #007aff #002a80;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#1a87ff', endColorstr='#007aff', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} .x .x_btn-primary:hover, .x .x_btn-primary:active, .x .x_btn-primary.x_active, .x .x_btn-primary.x_disabled, -.x .x_btn-primary[disabled]{color:#ffffff;background-color:#0044cc;*background-color:#003bb3} +.x .x_btn-primary[disabled]{color:#ffffff;background-color:#007aff;*background-color:#003bb3} .x .x_btn-primary:active, .x .x_btn-primary.x_active{background-color:#003399 \9} -.x .x_btn-warning{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(to bottom, #fbb450, #f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} +.x .x_btn-warning{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#ff9500;background-image:-moz-linear-gradient(top, #ffa01a, #ff9500);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffa01a), to(#ff9500));background-image:-webkit-linear-gradient(top, #ffa01a, #ff9500);background-image:-o-linear-gradient(top, #ffa01a, #ff9500);background-image:linear-gradient(to bottom, #ffa01a, #ff9500);background-repeat:repeat-x;border-color:#ff9500 #ff9500 #ad6704;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffa01a', endColorstr='#ff9500', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} .x .x_btn-warning:hover, .x .x_btn-warning:active, .x .x_btn-warning.x_active, .x .x_btn-warning.x_disabled, -.x .x_btn-warning[disabled]{color:#ffffff;background-color:#f89406;*background-color:#df8505} +.x .x_btn-warning[disabled]{color:#ffffff;background-color:#ff9500;*background-color:#df8505} .x .x_btn-warning:active, .x .x_btn-warning.x_active{background-color:#c67605 \9} -.x .x_btn-danger{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top, #ee5f5b, #bd362f);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));background-image:-webkit-linear-gradient(top, #ee5f5b, #bd362f);background-image:-o-linear-gradient(top, #ee5f5b, #bd362f);background-image:linear-gradient(to bottom, #ee5f5b, #bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} +.x .x_btn-danger{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#ff3b30;background-image:-moz-linear-gradient(top, #ff534a, #ff3b30);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ff534a), to(#ff3b30));background-image:-webkit-linear-gradient(top, #ff534a, #ff3b30);background-image:-o-linear-gradient(top, #ff534a, #ff3b30);background-image:linear-gradient(to bottom, #ff534a, #ff3b30);background-repeat:repeat-x;border-color:#ff3b30 #ff3b30 #802420;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff534a', endColorstr='#ff3b30', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} .x .x_btn-danger:hover, .x .x_btn-danger:active, .x .x_btn-danger.x_active, .x .x_btn-danger.x_disabled, -.x .x_btn-danger[disabled]{color:#ffffff;background-color:#bd362f;*background-color:#a9302a} +.x .x_btn-danger[disabled]{color:#ffffff;background-color:#ff3b30;*background-color:#a9302a} .x .x_btn-danger:active, .x .x_btn-danger.x_active{background-color:#942a25 \9} -.x .x_btn-success{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top, #62c462, #51a351);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));background-image:-webkit-linear-gradient(top, #62c462, #51a351);background-image:-o-linear-gradient(top, #62c462, #51a351);background-image:linear-gradient(to bottom, #62c462, #51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} +.x .x_btn-success{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#4cd964;background-image:-moz-linear-gradient(top, #61dd76, #4cd964);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#61dd76), to(#4cd964));background-image:-webkit-linear-gradient(top, #61dd76, #4cd964);background-image:-o-linear-gradient(top, #61dd76, #4cd964);background-image:linear-gradient(to bottom, #61dd76, #4cd964);background-repeat:repeat-x;border-color:#4cd964 #4cd964 #387038;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#61dd76', endColorstr='#4cd964', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} .x .x_btn-success:hover, .x .x_btn-success:active, .x .x_btn-success.x_active, .x .x_btn-success.x_disabled, -.x .x_btn-success[disabled]{color:#ffffff;background-color:#51a351;*background-color:#499249} +.x .x_btn-success[disabled]{color:#ffffff;background-color:#4cd964;*background-color:#499249} .x .x_btn-success:active, .x .x_btn-success.x_active{background-color:#408140 \9} -.x .x_btn-info{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top, #5bc0de, #2f96b4);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));background-image:-webkit-linear-gradient(top, #5bc0de, #2f96b4);background-image:-o-linear-gradient(top, #5bc0de, #2f96b4);background-image:linear-gradient(to bottom, #5bc0de, #2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} +.x .x_btn-info{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#0277BD;background-image:-moz-linear-gradient(top, #0288D1, #0277BD);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0288D1), to(#0277BD));background-image:-webkit-linear-gradient(top, #0288D1, #0277BD);background-image:-o-linear-gradient(top, #0288D1, #0277BD);background-image:linear-gradient(to bottom, #0288D1, #0277BD);background-repeat:repeat-x;border-color:#0277BD #0277BD #1f6377;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0288D1', endColorstr='#0277BD', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} .x .x_btn-info:hover, .x .x_btn-info:active, .x .x_btn-info.x_active, .x .x_btn-info.x_disabled, -.x .x_btn-info[disabled]{color:#ffffff;background-color:#2f96b4;*background-color:#2a85a0} +.x .x_btn-info[disabled]{color:#ffffff;background-color:#0277BD;*background-color:#2a85a0} .x .x_btn-info:active, .x .x_btn-info.x_active{background-color:#24748c \9} -.x .x_btn-inverse{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#363636;*background-color:#222222;background-image:-moz-linear-gradient(top, #444444, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));background-image:-webkit-linear-gradient(top, #444444, #222222);background-image:-o-linear-gradient(top, #444444, #222222);background-image:linear-gradient(to bottom, #444444, #222222);background-repeat:repeat-x;border-color:#222222 #222222 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#444444', endColorstr='#222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} +.x .x_btn-inverse{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#222222;background-image:-moz-linear-gradient(top, #444444, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));background-image:-webkit-linear-gradient(top, #444444, #222222);background-image:-o-linear-gradient(top, #444444, #222222);background-image:linear-gradient(to bottom, #444444, #222222);background-repeat:repeat-x;border-color:#222222 #222222 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#444444', endColorstr='#222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} .x .x_btn-inverse:hover, .x .x_btn-inverse:active, .x .x_btn-inverse.x_active, @@ -1048,7 +1082,7 @@ .x .x_btn-link, .x .x_btn-link:active, .x .x_btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none} -.x .x_btn-link{color:#0088cc;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} +.x .x_btn-link{color:#1a87ff;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} .x .x_btn-link:hover{color:#005580;text-decoration:underline;background-color:transparent} .x .x_btn-link[disabled]:hover{color:#333333;text-decoration:none} .x .x_btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1} @@ -1084,11 +1118,11 @@ .x .x_btn-group>.x_btn-large+.x_dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px} .x .x_btn-group.x_open .x_dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)} .x .x_btn-group.x_open .x_btn.x_dropdown-toggle{background-color:#e6e6e6} -.x .x_btn-group.x_open .x_btn-primary.x_dropdown-toggle{background-color:#0044cc} -.x .x_btn-group.x_open .x_btn-warning.x_dropdown-toggle{background-color:#f89406} -.x .x_btn-group.x_open .x_btn-danger.x_dropdown-toggle{background-color:#bd362f} -.x .x_btn-group.x_open .x_btn-success.x_dropdown-toggle{background-color:#51a351} -.x .x_btn-group.x_open .x_btn-info.x_dropdown-toggle{background-color:#2f96b4} +.x .x_btn-group.x_open .x_btn-primary.x_dropdown-toggle{background-color:#007aff} +.x .x_btn-group.x_open .x_btn-warning.x_dropdown-toggle{background-color:#ff9500} +.x .x_btn-group.x_open .x_btn-danger.x_dropdown-toggle{background-color:#ff3b30} +.x .x_btn-group.x_open .x_btn-success.x_dropdown-toggle{background-color:#4cd964} +.x .x_btn-group.x_open .x_btn-info.x_dropdown-toggle{background-color:#0277BD} .x .x_btn-group.x_open .x_btn-inverse.x_dropdown-toggle{background-color:#222222} .x .x_btn .x_caret{margin-top:8px;margin-left:0} .x .x_btn-mini .x_caret, @@ -1109,7 +1143,7 @@ .x .x_btn-group-vertical>.x_btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px} .x .x_btn-group-vertical>.x_btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0} .x .x_btn-group-vertical>.x_btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px} -.x .x_alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} +.x .x_alert{padding:6px 30px 6px 10px;margin-top:6px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} .x .x_alert, .x .x_alert h4{color:#c09853} .x .x_alert h4{margin:0} @@ -1138,7 +1172,7 @@ .x .x_nav-list .x_nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5)} .x .x_nav-list>li>a{padding:3px 15px} .x .x_nav-list>.x_active>a, -.x .x_nav-list>.x_active>a:hover{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.2);background-color:#0088cc} +.x .x_nav-list>.x_active>a:hover{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.2);background-color:#1a87ff} .x .x_nav-list [class^="x_icon-"], .x .x_nav-list [class*=" x_icon-"]{margin-right:2px} .x .x_nav-list .x_divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #ffffff} @@ -1162,7 +1196,7 @@ .x .x_nav-tabs>.x_active>a:hover{color:#555555;cursor:default;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent} .x .x_nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px} .x .x_nav-pills>.x_active>a, -.x .x_nav-pills>.x_active>a:hover{color:#ffffff;background-color:#0088cc} +.x .x_nav-pills>.x_active>a:hover{color:#ffffff;background-color:#1a87ff} .x .x_nav-stacked>li{float:none} .x .x_nav-stacked>li>a{margin-right:0} .x .x_nav-tabs.x_nav-stacked{border-bottom:0} @@ -1174,7 +1208,7 @@ .x .x_nav-pills.x_nav-stacked>li:last-child>a{margin-bottom:1px} .x .x_nav-tabs .x_dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px} .x .x_nav-pills .x_dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px} -.x .x_nav .x_dropdown-toggle .x_caret{margin-top:6px;border-top-color:#0088cc;border-bottom-color:#0088cc} +.x .x_nav .x_dropdown-toggle .x_caret{margin-top:6px;border-top-color:#1a87ff;border-bottom-color:#1a87ff} .x .x_nav .x_dropdown-toggle:hover .x_caret{border-top-color:#005580;border-bottom-color:#005580} /* move down carets for tabs */ .x .x_nav-tabs .x_dropdown-toggle .x_caret{margin-top:8px} @@ -1422,7 +1456,7 @@ .x .x_modal-header h3{margin:0;line-height:30px} .x .x_modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto} .x .x_modal-form{margin-bottom:0} -.x .x_modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff} +.x .x_modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff} .x .x_modal-footer:before, .x .x_modal-footer:after{display:table;line-height:0;content:""} .x .x_modal-footer:after{clear:both} @@ -1467,7 +1501,7 @@ .x .x_row-fluid .x_thumbnails{margin-left:0} .x .x_thumbnails>li{float:left;margin-bottom:20px;margin-left:20px} .x .x_thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.055);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.055);box-shadow:0 1px 3px rgba(0, 0, 0, 0.055);-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-o-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out} -.x a.x_thumbnail:hover{border-color:#0088cc;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25)} +.x a.x_thumbnail:hover{border-color:#1a87ff;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25)} .x .x_thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto} .x .x_thumbnail .x_caption{padding:9px;color:#555555} .x .x_media, @@ -1493,7 +1527,7 @@ .x .x_label-important[href], .x .x_badge-important[href]{background-color:#953b39} .x .x_label-warning, -.x .x_badge-warning{background-color:#f89406} +.x .x_badge-warning{background-color:#ff9500} .x .x_label-warning[href], .x .x_badge-warning[href]{background-color:#c67605} .x .x_label-success, @@ -1538,21 +1572,21 @@ to{background-position:0 0} .x .x_progress-striped .x_bar{background-color:#149bdf;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px} .x .x_progress.x_active .x_bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite} .x .x_progress-danger .x_bar, -.x .x_progress .x_bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(to bottom, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0)} +.x .x_progress .x_bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top, #ff534a, #c43c35);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ff534a), to(#c43c35));background-image:-webkit-linear-gradient(top, #ff534a, #c43c35);background-image:-o-linear-gradient(top, #ff534a, #c43c35);background-image:linear-gradient(to bottom, #ff534a, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff534a', endColorstr='#c43c35', GradientType=0)} .x .x_progress-danger.x_progress-striped .x_bar, -.x .x_progress-striped .x_bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent)} +.x .x_progress-striped .x_bar-danger{background-color:#ff534a;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent)} .x .x_progress-success .x_bar, -.x .x_progress .x_bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(to bottom, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0)} +.x .x_progress .x_bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top, #61dd76, #57a957);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#61dd76), to(#57a957));background-image:-webkit-linear-gradient(top, #61dd76, #57a957);background-image:-o-linear-gradient(top, #61dd76, #57a957);background-image:linear-gradient(to bottom, #61dd76, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#61dd76', endColorstr='#57a957', GradientType=0)} .x .x_progress-success.x_progress-striped .x_bar, -.x .x_progress-striped .x_bar-success{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent)} +.x .x_progress-striped .x_bar-success{background-color:#61dd76;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent)} .x .x_progress-info .x_bar, -.x .x_progress .x_bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(to bottom, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0)} +.x .x_progress .x_bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top, #0288D1, #339bb9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0288D1), to(#339bb9));background-image:-webkit-linear-gradient(top, #0288D1, #339bb9);background-image:-o-linear-gradient(top, #0288D1, #339bb9);background-image:linear-gradient(to bottom, #0288D1, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0288D1', endColorstr='#339bb9', GradientType=0)} .x .x_progress-info.x_progress-striped .x_bar, -.x .x_progress-striped .x_bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent)} +.x .x_progress-striped .x_bar-info{background-color:#0288D1;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent)} .x .x_progress-warning .x_bar, -.x .x_progress .x_bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(to bottom, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0)} +.x .x_progress .x_bar-warning{background-color:#E64A19;background-image:-moz-linear-gradient(top, #ffa01a, #ff9500);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffa01a), to(#ff9500));background-image:-webkit-linear-gradient(top, #ffa01a, #ff9500);background-image:-o-linear-gradient(top, #ffa01a, #ff9500);background-image:linear-gradient(to bottom, #ffa01a, #ff9500);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffa01a', endColorstr='#ff9500', GradientType=0)} .x .x_progress-warning.x_progress-striped .x_bar, -.x .x_progress-striped .x_bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent)} +.x .x_progress-striped .x_bar-warning{background-color:#ffa01a;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent)} .x .x_accordion{margin-bottom:20px} .x .x_accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} .x .x_accordion-heading{border-bottom:0} diff --git a/modules/admin/tpl/css/admin.css b/modules/admin/tpl/css/admin.css index d27ecc967..06689a5d1 100644 --- a/modules/admin/tpl/css/admin.css +++ b/modules/admin/tpl/css/admin.css @@ -3,6 +3,8 @@ /* Reset */ html, body { + margin:0; + padding:0; min-height: 100%; } body { @@ -37,15 +39,18 @@ body>.x, display: none; } .x a[target="_blank"]:after { - content: ""; - display: inline-block; - width: 14px; - height: 14px; - vertical-align: middle; - margin: -2px 0 0 2px; - background-position: -120px -72px; - opacity: .3; - filter: alpha(opacity=30); + display:inline-block; + font-family: 'xeicon'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\e665"; + padding: 0px 5px; } .x a[target="_blank"]:hover:after, .x a[target="_blank"]:focus:after { @@ -60,7 +65,7 @@ body>.x, .x .x_page-header { margin-top: 10px; padding-bottom: 0; - border-bottom: 2px solid #ddd; + border-bottom: 2px solid #e0e0e0; } .x .x_page-header>h1 { position: relative; @@ -109,13 +114,17 @@ body>.x, padding: 0 0 0 14px; width: 0; background-color: transparent; - overflow: hidden; font-size: 0; } +.x [class^="x_icon-"]::before, +.x [class*=" x_icon-"]::before { + width: auto; + margin:0 0 0 -14px; + font-size: 14px; +} .x .x_close { width: 32px; height: 32px; - font-size: 17px; opacity: .5; filter: alpha(opacity=50); } @@ -146,8 +155,6 @@ body>.x, color: #fff; font-weight: bold; font-size: 18px; - font-family: Arial, Helvetica, sans-serif; - border-radius: 2px; } .x .x_pagination [id^="goTo"] { display: none; @@ -173,7 +180,6 @@ body>.x, color: #333; } .x .x_btn { - border-radius: 2px; overflow: visible; font-size: 14px; line-height: 18px; @@ -203,6 +209,9 @@ body>.x, .x .x_btn-group { zoom: 1; } +.x .x_btn-group.margin_after { + margin-right: 10px; +} .x .x_btn-group:after { content: ""; display: block; @@ -211,15 +220,6 @@ body>.x, .x .x_btn-group>.x_btn { border-radius: 0; } -.x .x_btn-group>.x_btn:last-child, -.x .x_btn-group>.x_dropdown-toggle { - border-top-right-radius: 2px; - border-bottom-right-radius: 2px; -} -.x .x_btn-group>.x_btn:first-child { - border-bottom-left-radius: 2px; - border-top-left-radius: 2px; -} .x .x_btn-group>.x_btn-inverse+.x_btn-inverse { border-left-color: #555; } @@ -256,8 +256,8 @@ body>.x, } .x .x_table { margin: 10px 0; - border-top: 2px solid #ddd; - border-bottom: 1px solid #ddd; + border-top: 2px solid #e0e0e0; + border-bottom: 1px solid #e0e0e0; } .x h1+.x_table { border-top: 0; @@ -333,12 +333,7 @@ body>.x, .x .x_modal-header { padding: 10px 15px; border-bottom: 1px solid #aaa; - background-color: #333; - border-radius: 5px 5px 0 0; - background-image: -webkit-linear-gradient(top, #666, #333 50%, #000 50%, #333 100%); - background-image: -moz-linear-gradient(top, #666, #333 50%, #000 50%, #333 100%); - background-image: -o-linear-gradient(top, #666, #333 50%, #000 50%, #333 100%); - background-image: linear-gradient(top, #666, #333 50%, #000 50%, #333 100%); + background-color: #78909C; } .x .x_modal-header>h1, .x .x_modal-header>h2, @@ -347,7 +342,6 @@ body>.x, line-height: 30px; margin: 0; color: #fff; - text-shadow: 0 -1px 0 #000; } .x .x_modal-body { overflow-y: visible; @@ -369,7 +363,6 @@ body>.x, width: 90%; margin: 0 0 0 -45%; max-width: none; - border-radius: 6px; } .x_modal>form { margin: 0 !important; @@ -394,7 +387,7 @@ body>.x, } .x .x_control-group { padding-top: 8px; - border-top: 1px dotted #ddd; + border-top: 1px dotted #e0e0e0; clear: both; } .x .x_control-group:before { @@ -504,7 +497,7 @@ margin-bottom: 10px; } .x .section>h1 { position: relative; - border-bottom: 1px solid #ddd; + border-bottom: 1px solid #e0e0e0; cursor: pointer; } .x .section>h1>.snToggle { @@ -516,15 +509,9 @@ margin-bottom: 10px; opacity: .5; filter: alpha(opacity=50); } -.x .section>h1>.snToggle.x_icon-chevron-up { - background-position: -279px -112px; -} -.x .section>h1>.snToggle.x_icon-chevron-down { - background-position: -303px -111px; -} .x .section>h2 { position: relative; - border-bottom: 1px dotted #ddd; + border-bottom: 1px dotted #e0e0e0; } .x .section>h2+.x_control-group { border-top: 0; @@ -614,14 +601,14 @@ margin-bottom: 10px; .x td>form, .x td>p:only-of-type, .x td>p:last-of-type { - margin: 0; + margin-bottom: 0; } .x [data-display="none"] { display: none; } .x .x_page-header .path { font-size: 14px; - display: inline-block; + /* display: inline-block; */ } .x .x_page-header .path:first-letter { color: #ccc; @@ -688,10 +675,6 @@ margin-bottom: 10px; .x_modal._common._type_alert ._cancel { display: none; } -.x_modal._common._type_alert .x_modal-body { - border-radius: 6px 6px 0 0; -; -} .x_modal._common._nobody .x_modal-footer { border-top: 0; } @@ -707,7 +690,7 @@ margin-bottom: 10px; .x_modal-body.showTree .moveTree>h1 { font-size: 13px; color: #333; - border-bottom: 2px solid #ddd; + border-bottom: 2px solid #e0e0e0; padding: 10px 0 7px 0; } @media all and (max-width: 960px) { @@ -720,6 +703,7 @@ margin-bottom: 10px; } /* Image Sprite */ +/* .x a[target="_blank"]:after, .x>.body>.gnb>ul>li>a>i, .x .dashboard>div>section>h2:before { @@ -741,6 +725,7 @@ margin-bottom: 10px; } } +*/ /* Layout */ .x>.skipNav { margin: 0; @@ -749,24 +734,25 @@ margin-bottom: 10px; display: block; height: 1px; text-align: center; - border-radius: 4px; overflow: hidden; color: #333; text-decoration: none; + position: absolute; } .x>.skipNav>a:focus { height: auto; margin: 5px 0; padding: 8px 0; background: #fff; + position: static; } .x>.header { position: relative; z-index: 2; padding: 10px 15px; zoom: 1; - border-bottom: 1px solid #ddd; - background-color: #fff; + box-shadow: 0 2px 3px rgba(0,0,0,0.19), 0 1px 1px rgba(0,0,0,0.23); + background-color: #263238; } .x>.header:after { content: ""; @@ -780,16 +766,15 @@ margin-bottom: 10px; left: 1px; right: 1px; height: 1px; - box-shadow: 0 2px 3px #ddd; } .x>.body { position: relative; zoom: 1; - padding: 0 0 50px 215px; + padding: 0 0 50px 200px; z-index: 1; } .x>.body.wide { - padding-left: 70px; + padding-left: 60px; } .x>.body:after { content: ""; @@ -797,8 +782,9 @@ margin-bottom: 10px; clear: both; } .x>.body>.content { + box-sizing:border-box; width: 100%; - padding: 1px 0 0 0; + padding: 10px 15px 0 15px; float: right; margin: 0 0 0 -100%; outline: none; @@ -809,13 +795,18 @@ margin-bottom: 10px; .x>.body>.gnb { width: 180px; position: relative; - margin: 15px 0 0 -215px; + margin: 0 0 0 -200px; float: left; display: inline; } .x>.body.wide>.gnb { - width: 38px; - margin-left: -70px; + width: 40px; + margin-left: -60px; +} +@media all and (min-width: 800px) { + .active_clone { + display: none; + } } @media all and (max-width: 800px) { @@ -831,7 +822,6 @@ margin-bottom: 10px; } .x>.body>.content { width: auto; - padding: 1px 10px 0 10px; float: none; margin: 0 0 30px 0; } @@ -840,7 +830,6 @@ margin-bottom: 10px; display: block; width: auto; margin: 0 !important; - border-radius: 0; position: relative; top: auto; left: auto; @@ -853,41 +842,64 @@ margin-bottom: 10px; /* Header */ .x>.header>h1 { display: inline-block; - *display: inline; - zoom: 1; - margin: 0 15px 0 0; + margin: 0 10px 0 0; white-space: nowrap; } .x>.header>h1>a { + display: block; text-decoration: none; - color: #333; - font-size: 24px; - line-height: 40px; + color: #fff; + font-size: 22px; + line-height: 33px; + margin-top: -11px; + position: relative; + top: 5px; font-family: Arial, Helvetica, sans-serif; } .x>.header>h1>a>img { vertical-align: middle; } +@media all and (max-width: 799px) { + .x>.header>h1>a { + display: none; + } + .x>.header>h1>a.mobile_menu_open { + display: block; + } +} +@media all and (min-width: 800px) { + .x>.header>h1>a { + display: block; + } + .x>.header>h1>a.mobile_menu_open { + display: none; + } +} .x>.header>.site { display: inline-block; - *display: inline; - zoom: 1; - margin: 14px 0 0 0; - font-size: 11px; + margin: 1px 0 0 0; + font-size: 12px; + line-height: 22px; } .x>.header>.site>a { text-decoration: none; - color: #666; - font-family: Tahoma, Geneva, sans-serif; + color: #F5F5F5; } .x>.header>.site>a:hover, .x>.header>.site>a:focus { text-decoration: underline; } +@media all and (max-width: 799px) { + .x>.header>.site { + display: none; + } +} .x>.header>.account { float: right; position: relative; - margin: 13px 0 0 0; + margin: 1px 0 0 0; + font-size: 12px; + line-height: 22px !important; } .x>.header>.account>ul { list-style: none; @@ -899,14 +911,14 @@ margin-bottom: 10px; } .x>.header>.account>ul>li:before { content: "| "; - color: #ddd; + color: #e0e0e0; } .x>.header>.account>ul>li:first-child:before { content: normal; } .x>.header>.account>ul>li>a { text-decoration: none; - color: #666; + color: #f5f5f5; } .x>.header>.account>ul>li>a:hover, .x>.header>.account>ul>li>a:focus { @@ -926,10 +938,7 @@ margin-bottom: 10px; } .x>.header>.account .lang+#lang .x_active>a { color: #fff; - background-color: #0081c2; - background: -webkit-linear-gradient(top, #0088cc, #0077b3); - background: -moz-linear-gradient(top, #0088cc, #0077b3); - background: -o-linear-gradient(top, #0088cc, #0077b3); + background-color: #007aff; } @media all and (max-width: 480px) { @@ -937,17 +946,10 @@ margin-bottom: 10px; margin-top: 0; } -} -@media all and (max-width: 800px) { - -.x>.header>.account { - margin-top: 0; -} - } /* Footer */ .x>.footer { - border-top: 1px solid #ddd; + border-top: 1px solid #e0e0e0; padding: 10px 15px; zoom: 1; } @@ -981,12 +983,10 @@ margin-bottom: 10px; .x>.body>.gnb>ul { position: relative; z-index: 1; - box-shadow: 0 0 4px #ccc; - border: 2px solid #fff; + box-shadow: 0 3px 5px rgba(0,0,0,0.19), 0 2px 2px rgba(0,0,0,0.23); } .x>.body>.gnb a { text-decoration: none; - text-shadow: 0 1px 0 #fff; color: #000; display: block; white-space: nowrap; @@ -1001,19 +1001,18 @@ margin-bottom: 10px; font-size: 0; top: 50%; right: -14px; - background: #eee; + background: #ECEFF1; width: 12px; height: 50px; - border-radius: 0 3px 3px 0; margin: -25px 0 0 0; - border: 1px solid #ddd; + border: 1px solid #CFD8DC; border-left: 0; overflow: hidden; text-indent: 20px; } .x>.body.wide>.gnb>a[href="#gnbNav"]>b { border-color: transparent; - border-left-color: #666; + border-left-color: #78909C; margin: -4px 0 0 -2px; } .x>.body>.gnb>a[href="#gnbNav"]>b { @@ -1025,7 +1024,7 @@ margin-bottom: 10px; margin: -4px 0 0 -6px; border: 4px solid; border-color: transparent; - border-right-color: #666; + border-right-color: #78909C; } .x>.body>.gnb>a>i { display: none; @@ -1059,97 +1058,45 @@ margin-bottom: 10px; .x>.body>.gnb>.ex .exMenu .x_icon-chevron-up { display: inline-block; } -.x>.body>.gnb>ul>li[data-index="1"] { - border-top-color: #eee; -} -.x>.body>.gnb>ul>li[data-index="5"] { - margin-bottom: 1px; -} -.x>.body>.gnb>ul>li[data-index="6"] { - border-top-color: #eee; -} -.x>.body>.gnb>ul>li[data-index="6"], -.x>.body>.gnb>ul>li[data-index="7"] { - display: none; -} -.x>.body>.gnb>.ex>li[data-index="6"], -.x>.body>.gnb>.ex>li[data-index="7"] { - display: block; -} .x>.body>.gnb>ul>li[data-index].active_ { display: none; } @media all and (max-width: 800px) { - -.x>.body>.gnb>ul { - border: 0; -} -.x>.body>.gnb>ul>li { - display: none; -} -.x>.body>.gnb.open>ul>li { - display: block; -} -.x>.body>.gnb.open>ul>li[data-index="6"], -.x>.body>.gnb.open>ul>li[data-index="7"], -.x>.body>.gnb>.ex>li[data-index="6"], -.x>.body>.gnb>.ex>li[data-index="7"] { - display: none; -} -.x>.body>.gnb.open>.ex>li[data-index="6"], -.x>.body>.gnb.open>.ex>li[data-index="7"] { - display: block; -} -.x>.body>.gnb>ul>li:first-child { - display: block !important; -} -.x>.body>.gnb>a[href="#gnbNav"], -.x>.body.wide>.gnb>a[href="#gnbNav"] { - top: 0; - right: 0; - line-height: 37px; - width: 44px; - height: auto; - background: none; - border-radius: 0; - margin: 0; - border: 0; -} -.x>.body>.gnb>a[href="#gnbNav"] { - opacity: .5; - filter: alpha(opacity=50); -} -.x>.body>.gnb>a[href="#gnbNav"]:before { - content: ""; - position: absolute; - top: 1px; - left: 0; - width: 1px; - height: 100%; - border-left: 1px solid #999; -} -.x>.body>.gnb>a[href="#gnbNav"]>b { - display: none; -} -.x>.body>.gnb>a>i { - display: block; - position: absolute; - top: 50%; - left: 50%; - margin: -7px 0 0 -7px; -} - + .x>.body>.gnb>ul { + border: 0; + } + .x>.body>.gnb>ul>li { + display: none; + } + .x>.body>.gnb.open>ul>li { + display: block; + } + .x>.body>.gnb>ul>li:first-child { + display: block !important; + } + .x>.body>.gnb>a>i { + display: block; + position: absolute; + top: 50%; + left: 50%; + margin: -7px 0 0 -7px; + } + .x>.body>.gnb>a[href="#gnbNav"] { + display: none; + } } /* li */ .x>.body>.gnb>ul>li { - background: #3886d0; - border-top: 1px solid #fff; - border-bottom: 1px solid #ddd; + background: #546E7A; + border-bottom: 1px solid #CFD8DC; vertical-align: top; white-space: nowrap; } +.x>.body>.gnb>ul>li:last-child { + border-bottom: none; +} .x>.body>.gnb>ul>li.active { - background: #222; + background: #CFD8DC; } .x>.body>.gnb>ul>li.open, .x>.body>.gnb>ul>li.active { @@ -1159,23 +1106,23 @@ margin-bottom: 10px; /* li>a */ .x>.body>.gnb>ul>li>a { position: relative; - padding: 8px 5px 8px 10px; - background: #f1f1f1; - background: -webkit-linear-gradient(top,#F1F1F1,#E8E8E8); - background: -moz-linear-gradient(top,#F1F1F1,#E8E8E8); - background: -o-linear-gradient(top,#F1F1F1,#E8E8E8); - background: -ms-linear-gradient(top,#F1F1F1,#E8E8E8); - background: linear-gradient(top,#F1F1F1,#E8E8E8); + padding: 10px 10px 10px 8px; + background: #ECEFF1; } .x>.body>.gnb>ul>li>a>i { display: inline-block; width: 14px; height: 14px; - margin: -4px 4px 0 0; + margin: -4px 6px 0 0; vertical-align: middle; opacity: .75; filter: alpha(opacity=75); } +@media all and (min-width: 800px) { + .x>.body.wide>.gnb>ul>li>a>i { + margin-left: 4px; + } +} .x>.body>.gnb>ul>li>a>b { position: absolute; width: 0; @@ -1184,7 +1131,7 @@ margin-bottom: 10px; right: 10px; margin: -2px 0 0 0; border: 4px solid transparent; - border-top-color: #999; + border-top-color: #78909C; } .x>.body>.gnb>ul>li.open>a>b { border-top: 0; @@ -1193,67 +1140,84 @@ margin-bottom: 10px; .x>.body.wide>.gnb>ul>li>a>b { display: none; } +.x>.body>.gnb>ul>li>a>i::before { + display:inline-block; + font-family: 'xeicon'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} .x>.body>.gnb>ul>li[data-index="1"]>a>i { - background-position: -384px -144px; + background-image: none; } .x>.body>.gnb>ul>li[data-index="2"]>a>i { - background-position: 0 -24px; + background-image: none; } .x>.body>.gnb>ul>li[data-index="3"]>a>i { - background-position: -168px 0; + background-image: none; } + .x>.body>.gnb>ul>li[data-index="4"]>a>i { - background-position: -48px -48px; + background-image: none; } + .x>.body>.gnb>ul>li>a[href="#favorite"]>i { - background-position: -120px 0; + background-image: none; } + .x>.body>.gnb>ul>li[data-index="6"]>a>i { - background-position: -360px -144px; + background-image: none; } .x>.body>.gnb>ul>li[data-index="7"]>a>i { - background-position: -432px 0; + background-image: none; +} +.x>.body>.gnb>ul>li[data-index="1"]>a>i::before { + content: "\e607"; +} +.x>.body>.gnb>ul>li[data-index="2"]>a>i::before { + content: "\e606"; +} + +.x>.body>.gnb>ul>li[data-index="3"]>a>i::before { + content: "\e6c0"; +} + +.x>.body>.gnb>ul>li[data-index="4"]>a>i::before { + content: "\e7b5"; +} +.x>.body>.gnb>ul>li>a[href="#favorite"]>i::before { + content: "\e6fe"; +} +.x>.body>.gnb>ul>li[data-index="6"]>a>i::before { + content: "\e686"; +} +.x>.body>.gnb>ul>li[data-index="7"]>a>i::before { + content: "\e86e"; } .x>.body>.gnb>ul>li>a:hover, .x>.body>.gnb>ul>li>a:focus { - background: #f6f6f6; - background: -webkit-linear-gradient(top,#f6f6f6,#F1F1F1); - background: -moz-linear-gradient(top,#f6f6f6,#F1F1F1); - background: -o-linear-gradient(top,#f6f6f6,#F1F1F1); - background: -ms-linear-gradient(top,#f6f6f6,#F1F1F1); - background: linear-gradient(top,#f6f6f6,#F1F1F1); + background: #FAFAFA; } .x>.body>.gnb>ul>li.open>a { font-weight: bold; color: #fff; - text-shadow: 0 -1px 0 #333; - background: #3886d0; - background: -webkit-linear-gradient(top,#6ebcea,#3886d0); - background: -moz-linear-gradient(top,#6ebcea,#3886d0); - background: -o-linear-gradient(top,#6ebcea,#3886d0); - background: -ms-linear-gradient(top,#6ebcea,#3886d0); - background: linear-gradient(top,#6ebcea,#3886d0); + background: #546E7A; } .x>.body>.gnb>ul>li.active>a { font-weight: bold; - color: #fff; - text-shadow: none; - background: #222; - background: -webkit-linear-gradient(top,#555, #222); - background: -moz-linear-gradient(top,#555,#222); - background: -o-linear-gradient(top,#555,#222); + color: #E65100; + background: #FFF8E1; } @media all and (max-width: 800px) { .x>.body>.gnb>ul>li:first-child>a { font-weight: bold; color: #fff; - text-shadow: none; - border-radius: 3px; - background-color: #222; - background-image: -webkit-linear-gradient(top, #555, #222); - background-image: -moz-linear-gradient(top, #555, #222); - background-image: -o-linear-gradient(top, #555, #222); - background-image: linear-gradient(top, #555, #222); + background-color: #78909C; } } /* li>a>span */ @@ -1262,12 +1226,17 @@ margin-bottom: 10px; width: 1px; height: 1px; overflow: hidden; + line-height: 13px; +} +@media all and (min-width: 800px) { + .x>.body.wide>.gnb>ul>li>a>.tx { + display: none; + } } /* li>ul */ .x>.body>.gnb>ul>li>ul { display: none; - margin: 0 10px 10px 10px; - border-radius: 4px; + margin: 0 1px 0; } .x>.body>.gnb>ul>li.active>ul { display: block!important; @@ -1277,69 +1246,38 @@ margin-bottom: 10px; } /* li>ul>li */ .x>.body>.gnb>ul>li>ul>li { - border-top: 1px solid #ddd; + border-top: 1px solid #e0e0e0; position: relative; } .x>.body>.gnb>ul>li>ul>li:first-child { border: 0; } .x>.body>.gnb>ul>li>ul>li.active_ { - box-shadow: 0 0 3px #999; z-index: 99; - border: 1px solid #666; - border-left: 0; - border-right: 0; } /* li>ul>li>a */ .x>.body>.gnb>ul>li>ul>li>a { - padding: 4px 5px 4px 15px; - background: #e8e8e8; - background: -webkit-linear-gradient(top,#f1f1f1,#e8e8e8); - background: -moz-linear-gradient(top,#f1f1f1,#e8e8e8); - background: -o-linear-gradient(top,#f1f1f1,#e8e8e8); - background: -ms-linear-gradient(top,#f1f1f1,#e8e8e8); - background: linear-gradient(top,#f1f1f1,#e8e8e8); + padding: 7px 7px 7px 27px; + background: #fff; } .x>.body>.gnb>ul>li>ul#favorite>li>a { - padding: 4px 25px 4px 15px; -} -.x>.body>.gnb>ul>li>ul>li:first-child>a { - border-radius: 4px 4px 0 0; -} -.x>.body>.gnb>ul>li>ul>li:last-child>a { - border-radius: 0 0 4px 4px; -} -.x>.body>.gnb>ul>li>ul>li:only-child>a { - border-radius: 4px; + padding: 7px 25px 7px 27px; } .x>.body>.gnb>ul>li>ul>li>a:hover, .x>.body>.gnb>ul>li>ul>li>a:active, .x>.body>.gnb>ul>li>ul>li.active_>a { font-weight: bold; - background: -webkit-linear-gradient(top,#F6F6F6,#F1F1F1); - background: -moz-linear-gradient(top,#F6F6F6,#F1F1F1); - background: -o-linear-gradient(top,#F6F6F6,#F1F1F1); - background: -ms-linear-gradient(top,#F6F6F6,#F1F1F1); - background: linear-gradient(top,#F6F6F6,#F1F1F1); -} -.x>.body>.gnb>ul>li>ul>li.active_>a:after { - content: ""; - position: absolute; - top: 8px; - right: -12px; - border: 6px solid transparent; - border-left-color: #f3f3f3; - width: 0; - height: 0; - overflow: hidden; + color: #E65100; + background: #FFF8E1; } /* li>ul>li>.action */ .x>.body>.gnb>ul>li>ul>li>.remove { position: absolute; - top: 4px; - right: 5px; + top: 7px; + right: 3px; } .x>.body>.gnb>ul>li>ul>li>.remove>.x_close { + font-size: 12px; width: 20px; height: 20px; } @@ -1368,37 +1306,24 @@ margin-bottom: 10px; } .x .dashboard>div>section { position: relative; - height: 196px; - border: 1px solid #ddd; - border-radius: 4px; + height: 240px; margin: 0 0 25px 0; overflow: hidden; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.25); + border:1px solid #e0e0e0; } .x .dashboard>div>section>h2 { font-size: 14px; margin: 0; - padding: 6px 15px; - border-bottom: 1px solid #ddd; - background: #e8e8e8; - background: -webkit-linear-gradient(top,#F1F1F1,#E8E8E8); - background: -moz-linear-gradient(top,#F1F1F1,#E8E8E8); - background: -o-linear-gradient(top,#F1F1F1,#E8E8E8); - background: -ms-linear-gradient(top,#F1F1F1,#E8E8E8); - background: linear-gradient(top,#F1F1F1,#E8E8E8); - text-shadow: 0 1px 0 #fff; + padding:13px 15px 10px; + overflow:auto; + border-bottom:1px solid #e0e0e0; } .x .dashboard>div>section>h2:before { - content: ""; - display: inline-block; width: 14px; height: 14px; margin: 0 4px 0 0; vertical-align: middle; - opacity: .5; - filter: alpha(opacity=50); -} -.x .dashboard>div>.status>h2:before { - background-position: -408px 0; } .x .dashboard>div>.status dl { color: #767676; @@ -1409,8 +1334,7 @@ margin-bottom: 10px; padding: 1px 8px 0; font: 11px/1 돋움, Dotum, Arial, Helvetica, sans-serif; background: #fff; - box-shadow: 0 0 3px #999 inset; - border-radius: 3px; + box-shadow: 0 0 3px #9E9E9E inset; min-width: 60px; text-align: center; } @@ -1425,38 +1349,42 @@ margin-bottom: 10px; .x .dashboard>div>.status dl a { color: #767676; } + +.x .dashboard>div h2:before { + display:inline-block; + font-family: 'xeicon'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} .x .dashboard>div>.member>h2:before { - background-position: -168px 0; + content: "\e6c0"; } .x .dashboard>div>.document>h2:before { - background-position: -264px -48px; + content: "\e7b5"; } .x .dashboard>div>.reply>h2:before { - background-position: -240px -120px; + content: "\e6ec"; } .x .dashboard>div>.trackback>h2:before { - background-position: -216px -120px; + content: "\e6d5"; } .x .dashboard>div>section>.more { position: absolute; - top: 7px; + top: 10px; right: 15px; - text-shadow: 0 1px 0 #fff; -} -.x .dashboard>div>section>.more i { - font: 12px Tahoma, Geneva, sans-serif; } .x .dashboard>div>section>.more dl { color: #767676; display: inline-block; - *display: inline; - zoom: 1; margin: 0 8px 0 0; padding: 1px 8px 0; - font: 11px/1 돋움, Dotum, Arial, Helvetica, sans-serif; - background: #fff; - box-shadow: 0 0 3px #999 inset; - border-radius: 3px; + font-size: 11px; min-width: 60px; text-align: center; } @@ -1471,7 +1399,12 @@ margin-bottom: 10px; .x .dashboard>div>section>.more dl a { color: #767676; } - +.x .dashboard>div>section>.more>a>span { + display:inline-block; + overflow:hidden; + width:0; + height:0; +} .x .dashboard>div>section ul { list-style: none; margin: 10px; @@ -1481,9 +1414,9 @@ margin-bottom: 10px; } .x .dashboard>div>section li { position: relative; - height: 28px; - line-height: 28px; - padding: 0 70px 0 5px; + height: 25px; + line-height: 25px; + padding: 5px 70px 5px 5px; white-space: nowrap; overflow: hidden; zoom: 1; @@ -1491,7 +1424,6 @@ margin-bottom: 10px; } .x .dashboard>div>section li.hover { background: #f4f4f4; - border-radius: 4px; } .x .dashboard>div>section li>a { display: block; @@ -1575,10 +1507,10 @@ margin-bottom: 10px; overflow-x: hidden; } #g11n #lang_search .list { - border-top: 2px solid #ddd; + border-top: 2px solid #e0e0e0; } #g11n #lang_search .item { - border-bottom: 1px solid #ddd; + border-bottom: 1px solid #e0e0e0; margin: 0; } #g11n #lang_search .item>a { @@ -1697,7 +1629,6 @@ html[lang="mn"] .x .g11n.active>[disabled], width: 100%; padding-top: 6px; padding-bottom: 6px; - border-radius: 3px 3px 0 0; margin-bottom: 0; } .x .moduleWindow .siteList>ul { @@ -1715,7 +1646,7 @@ html[lang="mn"] .x .g11n.active>[disabled], } /* Text List */ .x .textList { - border: 1px solid #ddd !important; + border: 1px solid #e0e0e0 !important; line-height: 1.5em; height: 125px; overflow: auto; @@ -1828,7 +1759,6 @@ html[lang="mn"] .x .g11n.active>[disabled], padding: 0; white-space: nowrap; position: relative; - border-radius: 3px; vertical-align: top; } .tree li>ul { @@ -1864,15 +1794,8 @@ html[lang="mn"] .x .g11n.active>[disabled], } .tree>ul>li>a { font-weight: bold; - text-shadow: 0 1px 0 #fff; vertical-align: middle; } -.tree>ul>li>a:hover, -.tree>ul>li>a:focus, -.tree>ul>li>a.jstree-clicked, -.tree>ul>li>a.jstree-hovered { - text-shadow: none; -} .tree>ul>li>ul { margin: 0 0 0 18px; } @@ -1884,7 +1807,6 @@ html[lang="mn"] .x .g11n.active>[disabled], border: 0 !important; padding: 0 8px !important; margin: 0 0 1px 0; - border-radius: 3px; position: relative; z-index: 2; height: 23px; @@ -1901,6 +1823,8 @@ html[lang="mn"] .x .g11n.active>[disabled], opacity: .5; filter: alpha(opacity=50); } +.tree a.jstree-hovered:hover{background:#616161;color:#fff;} +.tree .jstree-clicked{background:#000;color:#fff} .tree .jstree-hovered>i, .tree .jstree-clicked>i { opacity: 1; @@ -1932,7 +1856,6 @@ html[lang="mn"] .x .g11n.active>[disabled], } .x .h1 { background: #444; - border-radius: 4px; color: #fff; margin: 0 0 1em 0; font-size: 16px; @@ -2007,13 +1930,13 @@ html[lang="mn"] .x .g11n.active>[disabled], padding: 8px; vertical-align: top; text-align: left; - border-bottom: 1px solid #ddd; + border-bottom: 1px solid #e0e0e0; } .x .table th { background: #f8f8f8; } .x .table thead th { - border-bottom: 1px solid #999; + border-bottom: 1px solid #9E9E9E; } .x .table tfoot td { font-weight: bold; @@ -2050,7 +1973,6 @@ html[lang="mn"] .x .g11n.active>[disabled], .x .form.search fieldset { border: 1px solid #ccc; padding: 5px 15px; - border-radius: 3px; } .x .form em { font-style: normal; @@ -2080,7 +2002,7 @@ html[lang="mn"] .x .g11n.active>[disabled], } .x .form li { list-style: none; - border: 1px solid #ddd; + border: 1px solid #e0e0e0; border-left: 0; border-right: 0; margin: -1px 0; @@ -2140,8 +2062,7 @@ html[lang="mn"] .x .g11n.active>[disabled], .x .form input[type="checkbox"][disabled="disabled"], .x .form select[disabled="disabled"], .x .form textarea[disabled="disabled"] { - background: #ddd; - text-shadow: 1px 1px 0 #fff; + background: #e0e0e0; } .x .form textarea { padding: 3px 4px; @@ -2226,7 +2147,7 @@ html[lang="mn"] .x .g11n.active>[disabled], .x .pagination a:hover, .x .pagination a:active, .x .pagination a:focus { - border: 1px solid #ddd; + border: 1px solid #e0e0e0; margin: 0 -1px; } .x .pagination strong { @@ -2276,7 +2197,6 @@ html[lang="mn"] .x .g11n.active>[disabled], left: 0; top: 0; text-align: center; - text-shadow: 1px 1px 0 #fff; } .x .prgrs.prgrsSmall { font-size: 14px; @@ -2339,10 +2259,9 @@ html[lang="mn"] .x .g11n.active>[disabled], background: #fff; padding: 0 1em; *padding: 1em; - border: 8px solid #ddd; + border: 8px solid #e0e0e0; z-index: 3; zoom: 1; - border-radius: 5px; box-shadow: 0 0 6px #000; } .modal ul, @@ -2367,15 +2286,14 @@ html[lang="mn"] .x .g11n.active>[disabled], right: -8px; top: -8px; border: 0; - background: #ddd; + background: #e0e0e0; padding: 0; width: 28px; height: 28px; font-size: 14px; font-weight: bold; cursor: pointer; - color: #999; - border-radius: 5px; + color: #9E9E9E; } .modalBlur { position: absolute; diff --git a/modules/admin/tpl/favicon_upload.html b/modules/admin/tpl/favicon_upload.html index 8b2a37fe9..ca7b3650f 100644 --- a/modules/admin/tpl/favicon_upload.html +++ b/modules/admin/tpl/favicon_upload.html @@ -1,3 +1,5 @@ + + diff --git a/modules/admin/tpl/server_env.html b/modules/admin/tpl/server_env.html index 2a2b81a64..0a73dd30d 100644 --- a/modules/admin/tpl/server_env.html +++ b/modules/admin/tpl/server_env.html @@ -1,4 +1,7 @@ + + +

    {$lang->server_env}

    diff --git a/modules/adminlogging/adminlogging.controller.php b/modules/adminlogging/adminlogging.controller.php index 2b6b330fb..98269664f 100644 --- a/modules/adminlogging/adminlogging.controller.php +++ b/modules/adminlogging/adminlogging.controller.php @@ -23,7 +23,7 @@ class adminloggingController extends adminlogging $logged_info = $oMemberModel->getLoggedInfo(); if($logged_info->is_admin != 'Y') { - return $this->stop("admin.msg_is_not_administrator"); + throw new Rhymix\Framework\Exceptions\NotPermitted('admin.msg_is_not_administrator'); } } diff --git a/modules/advanced_mailer/advanced_mailer.admin.controller.php b/modules/advanced_mailer/advanced_mailer.admin.controller.php index 66de18923..3e575e3fe 100644 --- a/modules/advanced_mailer/advanced_mailer.admin.controller.php +++ b/modules/advanced_mailer/advanced_mailer.admin.controller.php @@ -61,7 +61,7 @@ class Advanced_MailerAdminController extends Advanced_Mailer { if ($method !== 'default' && !isset($sending_methods[$method])) { - return $this->setError('msg_advanced_mailer_sending_method_is_invalid'); + throw new Rhymix\Framework\Exception('msg_advanced_mailer_sending_method_is_invalid'); } if ($method !== 'default') { @@ -69,7 +69,7 @@ class Advanced_MailerAdminController extends Advanced_Mailer { if (!Rhymix\Framework\Config::get("mail.$method.$conf_name")) { - return $this->setError('msg_advanced_mailer_sending_method_is_not_configured', lang('cmd_advanced_mailer_sending_method_' . $method)); + throw new Rhymix\Framework\Exception(sprintf('msg_advanced_mailer_sending_method_is_not_configured', lang('cmd_advanced_mailer_sending_method_' . $method))); } } } @@ -155,11 +155,11 @@ class Advanced_MailerAdminController extends Advanced_Mailer $clear_before_days = intval(Context::get('clear_before_days')); if (!in_array($status, array('success', 'error'))) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } if ($clear_before_days < 0) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $obj = new stdClass(); @@ -186,11 +186,11 @@ class Advanced_MailerAdminController extends Advanced_Mailer $clear_before_days = intval(Context::get('clear_before_days')); if (!in_array($status, array('success', 'error'))) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } if ($clear_before_days < 0) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $obj = new stdClass(); diff --git a/modules/advanced_mailer/lang/en.php b/modules/advanced_mailer/lang/en.php index 168a52cd6..96917f3e4 100644 --- a/modules/advanced_mailer/lang/en.php +++ b/modules/advanced_mailer/lang/en.php @@ -78,8 +78,9 @@ $lang->cmd_advanced_mailer_exception_group = 'Exception Group'; $lang->cmd_advanced_mailer_use_exceptions = 'Exception domains'; $lang->cmd_advanced_mailer_use_exceptions_yes = 'Test with exceptions as configured'; $lang->cmd_advanced_mailer_use_exceptions_no = 'Ignore exceptions and only test the default sending method'; -$lang->msg_advanced_mailer_about_dummy = 'Dummy does not actually send any email. It only records them. Use this option for testing.'; -$lang->msg_advanced_mailer_about_dummy_exceptions = 'Caution: if you have set up exception domains, email will be sent to those domains.'; +$lang->msg_advanced_mailer_about_dummy = 'Dummy does not actually send any email, but logs them. Use this option for testing.'; +$lang->msg_advanced_mailer_about_dummy_exceptions = 'Caution: if you have set up exception domains, unwanted email may be sent using other methods.'; +$lang->msg_advanced_mailer_about_mailfunction = 'This method uses the mail() function that comes with PHP itself. It has very low deliverability.
    This option may be deprecated in the future, so please use a different sending method if at all possible.'; $lang->msg_advanced_mailer_sending_method_is_invalid = 'Please select a valid sending method.'; $lang->msg_advanced_mailer_sending_method_is_not_configured = 'The selected sending method (%s) has not been fully configured. Please return to General Settings and finish configuring it.'; $lang->msg_advanced_mailer_smtp_host_is_invalid = 'Please enter a valid SMTP server name.'; @@ -125,4 +126,5 @@ $lang->cmd_advanced_mailer_country_code_help = 'Please leave the country code em $lang->cmd_advanced_mailer_test_content = 'This is an SMS test from Rhymix.'; $lang->msg_advanced_mailer_recipient_number_is_empty = 'Please enter a phone number for the recipient.'; $lang->msg_advanced_mailer_content_is_empty = 'Please enter the content for your test SMS.'; -$lang->msg_advanced_mailer_test_success_sms = 'The test was successful. Please check your SMS.'; \ No newline at end of file +$lang->msg_advanced_mailer_test_success_sms = 'The test was successful. Please check your SMS.'; +$lang->cmd_advanced_mailer_not_rhymix = 'This module is for XE. It is incompatible with Rhymix. Please use the version included with Rhymix.'; diff --git a/modules/advanced_mailer/lang/ko.php b/modules/advanced_mailer/lang/ko.php index db607462e..9dd01c943 100644 --- a/modules/advanced_mailer/lang/ko.php +++ b/modules/advanced_mailer/lang/ko.php @@ -78,8 +78,9 @@ $lang->cmd_advanced_mailer_exception_group = '예외 그룹'; $lang->cmd_advanced_mailer_use_exceptions = '예외 도메인 설정'; $lang->cmd_advanced_mailer_use_exceptions_yes = '예외 설정을 적용하여 테스트'; $lang->cmd_advanced_mailer_use_exceptions_no = '무시하고 기본 발송 방법만 테스트'; -$lang->msg_advanced_mailer_about_dummy = '더미는 실제로 메일을 발송하지 않고 기록만 하는 옵션입니다. 테스트에 사용하십시오.'; -$lang->msg_advanced_mailer_about_dummy_exceptions = '더미를 선택하더라도 예외 도메인을 지정한 경우 메일이 발송될 수 있으니 주의하십시오.'; +$lang->msg_advanced_mailer_about_dummy = '메일을 발송하지 않고 로그 기록만 하도록 강제합니다. 테스트 중 원치 않는 메일이 발송되는 것을 막기 위해 사용할 수 있습니다.'; +$lang->msg_advanced_mailer_about_dummy_exceptions = '이 옵션을 선택하더라도 예외 도메인을 지정한 경우 메일이 발송될 수 있으니 주의하십시오.'; +$lang->msg_advanced_mailer_about_mailfunction = 'PHP에 내장된 mail() 함수를 사용합니다. 발송 성공률이 매우 낮습니다.
    이 옵션은 추후 지원되지 않을 수 있으니, 가능하면 다른 방식을 선택하시기 바랍니다.'; $lang->msg_advanced_mailer_sending_method_is_invalid = '올바른 발송 방법을 선택해 주십시오.'; $lang->msg_advanced_mailer_sending_method_is_not_configured = '선택한 발송 방법(%s)이 완전히 설정되지 않았습니다. 기본 설정 페이지로 돌아가서 설정을 마쳐 주십시오.'; $lang->msg_advanced_mailer_smtp_host_is_invalid = '올바른 SMTP 서버 이름을 입력해 주십시오.'; @@ -125,4 +126,5 @@ $lang->cmd_advanced_mailer_country_code_help = '국내 번호로 발송하실 $lang->cmd_advanced_mailer_test_content = '라이믹스 SMS 발송 테스트입니다.'; $lang->msg_advanced_mailer_recipient_number_is_empty = '받는이 전화번호를 입력해 주십시오.'; $lang->msg_advanced_mailer_content_is_empty = 'SMS 내용을 입력해 주십시오.'; -$lang->msg_advanced_mailer_test_success_sms = '테스트에 성공하였습니다. SMS를 확인해 보시기 바랍니다.'; \ No newline at end of file +$lang->msg_advanced_mailer_test_success_sms = '테스트에 성공하였습니다. SMS를 확인해 보시기 바랍니다.'; +$lang->cmd_advanced_mailer_not_rhymix = '이 모듈은 XE용으로, 라이믹스와는 호환되지 않습니다. 라이믹스에 기본 포함된 버전을 사용하시기 바랍니다.'; diff --git a/modules/autoinstall/autoinstall.admin.view.php b/modules/autoinstall/autoinstall.admin.view.php index 77f660fee..0f9cb7ec4 100644 --- a/modules/autoinstall/autoinstall.admin.view.php +++ b/modules/autoinstall/autoinstall.admin.view.php @@ -414,7 +414,7 @@ class autoinstallAdminView extends autoinstall if(!$updateDate) { - return $this->stop('msg_connection_fail'); + throw new Rhymix\Framework\Exception('msg_connection_fail'); } $oModel = getModel('autoinstall'); @@ -535,13 +535,13 @@ class autoinstallAdminView extends autoinstall if(!$type || $type == "core") { - return $this->stop("msg_invalid_request"); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $config_file = $oModel->getConfigFilePath($type); if(!$config_file) { - return $this->stop("msg_invalid_request"); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $output = $oAdminModel->checkUseDirectModuleInstall($installedPackage); @@ -579,7 +579,7 @@ class autoinstallAdminView extends autoinstall } else { - return $this->stop('msg_connection_fail'); + throw new Rhymix\Framework\Exception('msg_connection_fail'); } } diff --git a/modules/autoinstall/tpl/category.html b/modules/autoinstall/tpl/category.html index 3acf517ab..d1cb9b7b5 100644 --- a/modules/autoinstall/tpl/category.html +++ b/modules/autoinstall/tpl/category.html @@ -1,5 +1,5 @@ diff --git a/modules/autoinstall/tpl/header.html b/modules/autoinstall/tpl/header.html index fa1c466c5..7e44735cc 100644 --- a/modules/autoinstall/tpl/header.html +++ b/modules/autoinstall/tpl/header.html @@ -1,4 +1,4 @@
    -

    {$lang->autoinstall} {$lang->help}

    +

    {$lang->autoinstall}

    diff --git a/modules/board/board.admin.controller.php b/modules/board/board.admin.controller.php index 58d7709b8..112cb9c47 100644 --- a/modules/board/board.admin.controller.php +++ b/modules/board/board.admin.controller.php @@ -168,7 +168,7 @@ class boardAdminController extends board { $module_info = $oModuleModel->getModuleInfoByModuleSrl($module_srl); if($module_info->mid != $mid) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $module_info->hide_category = Context::get('hide_category') == 'Y' ? 'Y' : 'N'; diff --git a/modules/board/board.admin.view.php b/modules/board/board.admin.view.php index 2a0c7f130..75cf3ce11 100644 --- a/modules/board/board.admin.view.php +++ b/modules/board/board.admin.view.php @@ -39,7 +39,10 @@ class boardAdminView extends board { } } - if($module_info && $module_info->module != 'board') return $this->stop("msg_invalid_request"); + if($module_info && $module_info->module != 'board') + { + throw new Rhymix\Framework\Exceptions\InvalidRequest; + } // get the module category list $module_category = $oModuleModel->getModuleCategories(); diff --git a/modules/board/board.controller.php b/modules/board/board.controller.php index 671a1dbbc..d0775c016 100644 --- a/modules/board/board.controller.php +++ b/modules/board/board.controller.php @@ -24,7 +24,7 @@ class boardController extends board // check grant if(!$this->grant->write_document) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } // setup variables @@ -35,14 +35,14 @@ class boardController extends board // Return error if content is empty. if (is_empty_html_content($obj->content)) { - return $this->setError('msg_empty_content'); + throw new Rhymix\Framework\Exception('msg_empty_content'); } // Return error if content is too large. $document_length_limit = ($this->module_info->document_length_limit ?: 1024) * 1024; if (strlen($obj->content) > $document_length_limit && !$this->grant->manager) { - return $this->setError('msg_content_too_long'); + throw new Rhymix\Framework\Exception('msg_content_too_long'); } // unset document style if not manager @@ -107,14 +107,14 @@ class boardController extends board { if(!$oDocument->isGranted()) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } // Protect admin document $member_info = getModel('member')->getMemberInfoByMemberSrl($oDocument->get('member_srl')); if($member_info->is_admin == 'Y' && $logged_info->is_admin != 'Y') { - return $this->setError('msg_admin_document_no_modify'); + throw new Rhymix\Framework\Exception('msg_admin_document_no_modify'); } // if document status is temp @@ -138,7 +138,7 @@ class boardController extends board { if($oDocument->get('comment_count') > 0 && !$this->grant->manager) { - return $this->setError('msg_protect_update_content'); + throw new Rhymix\Framework\Exception('msg_protect_update_content'); } } @@ -147,7 +147,7 @@ class boardController extends board { if($oDocument->get('regdate') < date('YmdHis', strtotime('-' . $this->module_info->protect_document_regdate . ' day'))) { - return $this->setError(sprintf(lang('msg_protect_regdate_document'), $this->module_info->protect_document_regdate)); + throw new Rhymix\Framework\Exception(sprintf(lang('msg_protect_regdate_document'), $this->module_info->protect_document_regdate)); } } @@ -235,7 +235,7 @@ class boardController extends board $logged_info = Context::get('logged_info'); if(!$update_id) { - return $this->setError('msg_no_update_id'); + throw new Rhymix\Framework\Exception('msg_no_update_id'); } $oDocumentModel = getModel('document'); @@ -247,13 +247,13 @@ class boardController extends board $Exists_log = $oDocumentModel->getUpdateLogAdminisExists($update_log->document_srl); if($Exists_log === true) { - return $this->setError('msg_admin_update_log'); + throw new Rhymix\Framework\Exception('msg_admin_update_log'); } } if(!$update_log) { - return $this->setError('msg_no_update_log'); + throw new Rhymix\Framework\Exception('msg_no_update_log'); } $oDocument = $oDocumentModel->getDocument($update_log->document_srl); @@ -282,7 +282,7 @@ class boardController extends board // if the document is not existed if(!$document_srl) { - return $this->setError('msg_invalid_document'); + throw new Rhymix\Framework\Exception('msg_invalid_document'); } $oDocumentModel = &getModel('document'); @@ -292,7 +292,7 @@ class boardController extends board { if($oDocument->get('comment_count') > 0 && $this->grant->manager == false) { - return $this->setError('msg_protect_delete_content'); + throw new Rhymix\Framework\Exception('msg_protect_delete_content'); } } @@ -302,7 +302,7 @@ class boardController extends board { $format = lang('msg_protect_regdate_document'); $massage = sprintf($format, $this->module_info->protect_document_regdate); - return $this->setError($massage); + throw new Rhymix\Framework\Exception($massage); } } // generate document module controller object @@ -356,7 +356,7 @@ class boardController extends board // check grant if(!$this->grant->write_comment) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $logged_info = Context::get('logged_info'); @@ -367,14 +367,14 @@ class boardController extends board // Return error if content is empty. if (is_empty_html_content($obj->content)) { - return $this->setError('msg_empty_content'); + throw new Rhymix\Framework\Exception('msg_empty_content'); } // Return error if content is too large. $comment_length_limit = ($this->module_info->comment_length_limit ?: 128) * 1024; if (strlen($obj->content) > $comment_length_limit && !$this->grant->manager) { - return $this->setError('msg_content_too_long'); + throw new Rhymix\Framework\Exception('msg_content_too_long'); } if(!$this->module_info->use_status) $this->module_info->use_status = 'PUBLIC'; @@ -398,7 +398,7 @@ class boardController extends board $oDocument = $oDocumentModel->getDocument($obj->document_srl); if(!$oDocument->isExists()) { - return $this->setError('msg_not_founded'); + throw new Rhymix\Framework\Exceptions\TargetNotFound; } // For anonymous use, remove writer's information and notifying information @@ -436,7 +436,7 @@ class boardController extends board $childs = $oCommentModel->getChildComments($obj->comment_srl); if(count($childs) > 0) { - return $this->setError('msg_board_update_protect_comment'); + throw new Rhymix\Framework\Exception('msg_board_update_protect_comment'); } } } @@ -446,7 +446,7 @@ class boardController extends board if($member_info->is_admin == 'Y' && $logged_info->is_admin != 'Y') { - return $this->setError('msg_admin_comment_no_modify'); + throw new Rhymix\Framework\Exception('msg_admin_comment_no_modify'); } // INSERT if comment_srl does not exist. @@ -461,7 +461,7 @@ class boardController extends board $parent_comment = $oCommentModel->getComment($obj->parent_srl); if(!$parent_comment->comment_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\TargetNotFound; } if($parent_comment->isSecret() && $this->module_info->secret === 'Y') { @@ -490,13 +490,13 @@ class boardController extends board { $format = lang('msg_protect_regdate_comment'); $massage = sprintf($format, $this->module_info->protect_document_regdate); - return $this->setError($massage); + throw new Rhymix\Framework\Exception($massage); } } // check the grant if(!$comment->isGranted()) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $obj->parent_srl = $comment->parent_srl; $output = $oCommentController->updateComment($obj, $this->grant->manager); @@ -530,7 +530,7 @@ class boardController extends board if(!$comment_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $oCommentModel = getModel('comment'); @@ -540,7 +540,7 @@ class boardController extends board $childs = $oCommentModel->getChildComments($comment_srl); if(count($childs) > 0) { - return $this->setError('msg_board_delete_protect_comment'); + throw new Rhymix\Framework\Exception('msg_board_delete_protect_comment'); } } $comment = $oCommentModel->getComment($comment_srl, $this->grant->manager); @@ -550,7 +550,7 @@ class boardController extends board { $format = lang('msg_protect_regdate_comment'); $massage = sprintf($format, $this->module_info->protect_document_regdate); - return $this->setError($massage); + throw new Rhymix\Framework\Exception($massage); } } // generate comment controller object @@ -662,13 +662,13 @@ class boardController extends board $oComment = $oCommentModel->getComment($comment_srl); if(!$oComment->isExists()) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\TargetNotFound; } // compare the comment password and the user input password if(!$oMemberModel->isValidPassword($oComment->get('password'),$password)) { - return $this->setError('msg_invalid_password'); + throw new Rhymix\Framework\Exception('msg_invalid_password'); } $oComment->setGrantForSession(); @@ -678,13 +678,13 @@ class boardController extends board $oDocument = $oDocumentModel->getDocument($document_srl); if(!$oDocument->isExists()) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\TargetNotFound; } // compare the document password and the user input password if(!$oMemberModel->isValidPassword($oDocument->get('password'),$password)) { - return $this->setError('msg_invalid_password'); + throw new Rhymix\Framework\Exception('msg_invalid_password'); } $oDocument->setGrantForSession(); diff --git a/modules/board/board.mobile.php b/modules/board/board.mobile.php index cc768f70f..b89c7d6fa 100644 --- a/modules/board/board.mobile.php +++ b/modules/board/board.mobile.php @@ -61,27 +61,9 @@ class boardMobile extends boardView $this->consultation = false; } - $oDocumentModel = getModel('document'); $extra_keys = $oDocumentModel->getExtraKeys($this->module_info->module_srl); Context::set('extra_keys', $extra_keys); - if($this->module_info->mskin === '/USE_RESPONSIVE/') - { - $template_path = sprintf("%sskins/%s/",$this->module_path, $this->module_info->skin); - if(!is_dir($template_path)||!$this->module_info->skin) - { - $template_path = sprintf("%sskins/%s/",$this->module_path, 'default'); - } - } - else - { - $template_path = sprintf("%sm.skins/%s/",$this->module_path, $this->module_info->mskin); - if(!is_dir($template_path)||!$this->module_info->mskin) - { - $template_path = sprintf("%sm.skins/%s/",$this->module_path, 'default'); - } - } - $this->setTemplatePath($template_path); Context::addJsFilter($this->module_path.'tpl/filter', 'input_password.xml'); } diff --git a/modules/board/board.view.php b/modules/board/board.view.php index ea6b5f1be..178e2dac1 100644 --- a/modules/board/board.view.php +++ b/modules/board/board.view.php @@ -90,17 +90,6 @@ class boardView extends board $this->consultation = FALSE; } - /** - * setup the template path based on the skin - * the default skin is default - **/ - $template_path = sprintf("%sskins/%s/",$this->module_path, $this->module_info->skin); - if(!is_dir($template_path)||!$this->module_info->skin) - { - $template_path = sprintf("%sskins/%s/",$this->module_path, 'default'); - } - $this->setTemplatePath($template_path); - /** * use context::set to setup extra variables **/ @@ -262,7 +251,7 @@ class boardView extends board // if the module srl is not consistent if($oDocument->get('module_srl')!=$this->module_info->module_srl ) { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\TargetNotFound; } // check the manage grant @@ -383,7 +372,11 @@ class boardView extends board if(is_array($file_module_config->download_grant) && $downloadGrantCount>0) { - if(!Context::get('is_logged')) return $this->stop('msg_not_permitted_download'); + if(!Context::get('is_logged')) + { + throw new Rhymix\Framework\Exceptions\NotPermitted('msg_not_permitted_download'); + } + $logged_info = Context::get('logged_info'); if($logged_info->is_admin != 'Y') { @@ -406,7 +399,10 @@ class boardView extends board break; } } - if(!$is_permitted) return $this->stop('msg_not_permitted_download'); + if(!$is_permitted) + { + throw new Rhymix\Framework\Exceptions\NotPermitted('msg_not_permitted_download'); + } } } } @@ -672,18 +668,18 @@ class boardView extends board $document_srl = Context::get('document_srl'); if(!$document_srl) { - return $this->setError("msg_invalid_request"); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } if($this->grant->view == false || ($this->module_info->consultation == 'Y' && !$this->grant->manager && !$this->grant->consultation_read)) { - return $this->setError("msg_not_permitted"); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $oDocument = getModel('document')->getDocument($document_srl); if(!$oDocument->isExists()) { - return $this->setError("msg_invalid_request"); + throw new Rhymix\Framework\Exceptions\TargetNotFound; } Context::set('oDocument', $oDocument); @@ -780,20 +776,20 @@ class boardView extends board { $format = lang('msg_protect_regdate_document'); $massage = sprintf($format, $this->module_info->protect_document_regdate); - return $this->setError($massage); + throw new Rhymix\Framework\Exception($massage); } } if($this->module_info->protect_content == "Y" || $this->module_info->protect_update_content == 'Y') { if($oDocument->get('comment_count') > 0 && $this->grant->manager == false) { - return $this->setError('msg_protect_update_content'); + throw new Rhymix\Framework\Exception('msg_protect_update_content'); } } } if($member_info->is_admin == 'Y' && $logged_info->is_admin != 'Y') { - return $this->setError('msg_admin_document_no_modify'); + throw new Rhymix\Framework\Exception('msg_admin_document_no_modify'); } // if the document is not granted, then back to the password input form @@ -913,7 +909,7 @@ class boardView extends board { $format = lang('msg_protect_regdate_document'); $massage = sprintf($format, $this->module_info->protect_document_regdate); - return $this->setError($massage); + throw new Rhymix\Framework\Exception($massage); } } @@ -921,7 +917,7 @@ class boardView extends board { if($oDocument->get('comment_count')>0 && $this->grant->manager == false) { - return $this->setError('msg_protect_delete_content'); + throw new Rhymix\Framework\Exception('msg_protect_delete_content'); } } @@ -953,7 +949,7 @@ class boardView extends board $oDocument = $oDocumentModel->getDocument($document_srl); if(!$oDocument->isExists()) { - return $this->dispBoardMessage('msg_invalid_request'); + return $this->dispBoardMessage('msg_not_founded'); } // Check allow comment @@ -998,7 +994,7 @@ class boardView extends board // if the parent comment is not existed if(!$parent_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // get the comment @@ -1008,11 +1004,11 @@ class boardView extends board // if the comment is not existed, opoup an error message if(!$oSourceComment->isExists()) { - return $this->dispBoardMessage('msg_invalid_request'); + return $this->dispBoardMessage('msg_not_founded'); } if(Context::get('document_srl') && $oSourceComment->get('document_srl') != Context::get('document_srl')) { - return $this->dispBoardMessage('msg_invalid_request'); + return $this->dispBoardMessage('msg_not_founded'); } // Check allow comment @@ -1060,7 +1056,7 @@ class boardView extends board // if the comment is not existed if(!$comment_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // get comment information @@ -1075,7 +1071,7 @@ class boardView extends board { $format = lang('msg_protect_regdate_comment'); $massage = sprintf($format, $this->module_info->protect_document_regdate); - return $this->setError($massage); + throw new Rhymix\Framework\Exception($massage); } } if($this->module_info->protect_update_comment === 'Y' && $this->grant->manager == false) @@ -1083,19 +1079,19 @@ class boardView extends board $childs = $oCommentModel->getChildComments($comment_srl); if(count($childs) > 0) { - return $this->setError('msg_board_update_protect_comment'); + throw new Rhymix\Framework\Exception('msg_board_update_protect_comment'); } } if($member_info->is_admin == 'Y' && $logged_info->is_admin != 'Y') { - return $this->setError('msg_admin_comment_no_modify'); + throw new Rhymix\Framework\Exception('msg_admin_comment_no_modify'); } // if the comment is not exited, alert an error message if(!$oComment->isExists()) { - return $this->dispBoardMessage('msg_invalid_request'); + return $this->dispBoardMessage('msg_not_founded'); } // if the comment is not granted, then back to the password input form @@ -1143,7 +1139,7 @@ class boardView extends board { $format = lang('msg_protect_regdate_comment'); $massage = sprintf($format, $this->module_info->protect_document_regdate); - return $this->setError($massage); + throw new Rhymix\Framework\Exception($massage); } } @@ -1153,7 +1149,7 @@ class boardView extends board $childs = $oCommentModel->getChildComments($comment_srl); if(count($childs) > 0) { - return $this->setError('msg_board_delete_protect_comment'); + throw new Rhymix\Framework\Exception('msg_board_delete_protect_comment'); } } @@ -1233,7 +1229,7 @@ class boardView extends board if($this->grant->update_view !== true) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $updatelog = $oDocumentModel->getDocumentUpdateLog($document_srl); @@ -1253,7 +1249,7 @@ class boardView extends board if($this->grant->update_view !== true) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $update_log = $oDocumentModel->getUpdateLog($update_id); @@ -1289,7 +1285,7 @@ class boardView extends board { iF($this->grant->vote_log_view !== true) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $oMemberModel = getModel('member'); @@ -1310,7 +1306,7 @@ class boardView extends board } else { - return $this->setError('msg_not_target'); + throw new Rhymix\Framework\Exception('msg_not_target'); } $output = executeQueryArray($queryId, $args); diff --git a/modules/board/conf/module.xml b/modules/board/conf/module.xml index e8850f127..8bd36c9cd 100644 --- a/modules/board/conf/module.xml +++ b/modules/board/conf/module.xml @@ -57,13 +57,13 @@ - - - - - - - + + + + + + + diff --git a/modules/board/skins/xedition/_read.html b/modules/board/skins/xedition/_read.html index 776a0ac22..73c472ead 100644 --- a/modules/board/skins/xedition/_read.html +++ b/modules/board/skins/xedition/_read.html @@ -88,8 +88,8 @@
    {$lang->cmd_vote} {$oDocument->get('voted_count')}
  • -
    {$lang->cmd_vote_down} {$oDocument->get('blamed_count')}
    -
    {$lang->cmd_vote_down} {$oDocument->get('blamed_count')}
    +
    {$lang->cmd_vote_down} {$oDocument->get('blamed_count')}
    +
    {$lang->cmd_vote_down} {$oDocument->get('blamed_count')}
  • diff --git a/modules/board/tpl/board_insert.html b/modules/board/tpl/board_insert.html index 08198b380..615130e13 100644 --- a/modules/board/tpl/board_insert.html +++ b/modules/board/tpl/board_insert.html @@ -1,3 +1,4 @@ +
    @@ -24,7 +25,7 @@
    - + {$lang->help}
    @@ -32,13 +33,13 @@
    - +
    - +
    @@ -84,14 +85,14 @@
    - +

    {$lang->about_header_text}

    - +
    @@ -149,14 +150,14 @@
    - +

    {$lang->about_mobile_header_text}

    - +
    @@ -358,7 +359,7 @@
    - + {$lang->help}
    diff --git a/modules/board/tpl/board_setup_basic.html b/modules/board/tpl/board_setup_basic.html index 5acc34c02..2ba5e8c50 100644 --- a/modules/board/tpl/board_setup_basic.html +++ b/modules/board/tpl/board_setup_basic.html @@ -64,7 +64,7 @@
    - diff --git a/modules/comment/comment.admin.controller.php b/modules/comment/comment.admin.controller.php index 9ad5709eb..c84b64e00 100644 --- a/modules/comment/comment.admin.controller.php +++ b/modules/comment/comment.admin.controller.php @@ -56,7 +56,7 @@ class commentAdminController extends comment $cart = Context::get('cart'); if(!$cart) { - return $this->stop('msg_cart_is_null'); + throw new Rhymix\Framework\Exception('msg_cart_is_null'); } if(!is_array($cart)) { @@ -96,7 +96,7 @@ class commentAdminController extends comment $comment = $oCommentModel->getComment($comment_srl); if($comment->comment_srl != $comment_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $document_srl = $comment->document_srl; if(!in_array($document_srl, $updated_documents_arr)) @@ -171,7 +171,7 @@ class commentAdminController extends comment $cart = Context::get('cart'); if(!$cart) { - return $this->stop('msg_cart_is_null'); + throw new Rhymix\Framework\Exception('msg_cart_is_null'); } if(!is_array($cart)) { @@ -184,7 +184,7 @@ class commentAdminController extends comment $comment_count = count($comment_srl_list); if(!$comment_count) { - return $this->stop('msg_cart_is_null'); + throw new Rhymix\Framework\Exception('msg_cart_is_null'); } $oCommentController = getController('comment'); @@ -220,7 +220,7 @@ class commentAdminController extends comment continue; } - $output = $oCommentController->deleteComment($comment_srl, TRUE, $isTrash); + $output = $oCommentController->deleteComment($comment_srl, TRUE, toBool($isTrash)); if(!$output->toBool()) { $oDB->rollback(); @@ -310,6 +310,16 @@ class commentAdminController extends comment $oDB->rollback(); return $output; } + + $obj = new stdClass; + $obj->comment_srl = $oComment->get('comment_srl'); + $obj->module_srl = $oComment->get('module_srl'); + $obj->document_srl = $oComment->get('document_srl'); + $obj->parent_srl = $oComment->get('parent_srl'); + $obj->member_srl = $oComment->get('member_srl'); + $obj->regdate = $oComment->get('regdate'); + $obj->last_update = $oComment->get('last_update'); + ModuleHandler::triggerCall('comment.moveCommentToTrash', 'after', $obj); } } } @@ -329,7 +339,7 @@ class commentAdminController extends comment $oCommentController = getController('comment'); $oComment = $oCommentModel->getComment($comment_srl, false); - if(!$oComment->isGranted()) return $this->stop('msg_not_permitted'); + if(!$oComment->isGranted()) throw new Rhymix\Framework\Exceptions\NotPermitted; $message_content = ""; $this->_moveCommentToTrash(array($comment_srl), $oCommentController, $oDB, $message_content); @@ -425,33 +435,18 @@ class commentAdminController extends comment { $originObject = (object) $originObject; } - - $obj = new stdClass(); - $obj->document_srl = $originObject->document_srl; - $obj->comment_srl = $originObject->comment_srl; - $obj->parent_srl = $originObject->parent_srl; - $obj->content = $originObject->content; - $obj->password = $originObject->password; - $obj->nick_name = $originObject->nick_name; - $obj->member_srl = $originObject->member_srl; - $obj->email_address = $originObject->email_address; - $obj->homepage = $originObject->homepage; - $obj->is_secret = $originObject->is_secret; - $obj->notify_message = $originObject->notify_message; - $obj->module_srl = $originObject->module_srl; - + $oCommentController = getController('comment'); $oCommentModel = getModel('comment'); $oComment = $oCommentModel->getComment($originObject->comment_srl); - if($oComment->isExists()) { - $output = $oCommentController->updateCommentByRestore($obj); + $output = $oCommentController->updateCommentByRestore($originObject); } else { - $output = $oCommentController->insertComment($obj, true); + $output = $oCommentController->insertComment($originObject, true); } return $output; diff --git a/modules/comment/comment.controller.php b/modules/comment/comment.controller.php index 67a234a8f..2dc2fb651 100644 --- a/modules/comment/comment.controller.php +++ b/modules/comment/comment.controller.php @@ -27,15 +27,18 @@ class commentController extends comment */ function procCommentVoteUp() { - if(!Context::get('is_logged')) + if($this->module_info->non_login_vote !== 'Y') { - return $this->setError('msg_invalid_request'); + if(!Context::get('is_logged')) + { + throw new Rhymix\Framework\Exceptions\NotPermitted; + } } $comment_srl = Context::get('target_srl'); if(!$comment_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $oCommentModel = getModel('comment'); @@ -43,14 +46,14 @@ class commentController extends comment $module_srl = $oComment->get('module_srl'); if(!$module_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $oModuleModel = getModel('module'); $comment_config = $oModuleModel->getModulePartConfig('comment', $module_srl); if($comment_config->use_vote_up == 'N') { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\FeatureDisabled; } $point = 1; @@ -61,16 +64,22 @@ class commentController extends comment function procCommentVoteUpCancel() { - if(!Context::get('logged_info')) return $this->setError('msg_invalid_request'); + if($this->module_info->non_login_vote !== 'Y') + { + if(!Context::get('is_logged')) + { + throw new Rhymix\Framework\Exceptions\NotPermitted; + } + } $comment_srl = Context::get('target_srl'); - if(!$comment_srl) return $this->setError('msg_invalid_request'); + if(!$comment_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; $oCommentModel = getModel('comment'); $oComment = $oCommentModel->getComment($comment_srl, FALSE, FALSE); if($oComment->get('voted_count') <= 0) { - return $this->setError('msg_comment_voted_cancel_not'); + throw new Rhymix\Framework\Exception('failed_voted_canceled'); } $point = 1; $output = $this->updateVotedCountCancel($comment_srl, $oComment, $point); @@ -88,15 +97,18 @@ class commentController extends comment */ function procCommentVoteDown() { - if(!Context::get('is_logged')) + if($this->module_info->non_login_vote !== 'Y') { - return $this->setError('msg_invalid_request'); + if(!Context::get('is_logged')) + { + throw new Rhymix\Framework\Exceptions\NotPermitted; + } } $comment_srl = Context::get('target_srl'); if(!$comment_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $oCommentModel = getModel('comment'); @@ -104,14 +116,14 @@ class commentController extends comment $module_srl = $oComment->get('module_srl'); if(!$module_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $oModuleModel = getModel('module'); $comment_config = $oModuleModel->getModulePartConfig('comment', $module_srl); if($comment_config->use_vote_down == 'N') { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\FeatureDisabled; } $point = -1; @@ -122,16 +134,22 @@ class commentController extends comment function procCommentVoteDownCancel() { - if(!Context::get('logged_info')) return $this->setError('msg_invalid_request'); + if($this->module_info->non_login_vote !== 'Y') + { + if(!Context::get('is_logged')) + { + throw new Rhymix\Framework\Exceptions\NotPermitted; + } + } $comment_srl = Context::get('target_srl'); - if(!$comment_srl) return $this->setError('msg_invalid_request'); + if(!$comment_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; $oCommentModel = getModel('comment'); $oComment = $oCommentModel->getComment($comment_srl, FALSE, FALSE); if($oComment->get('blamed_count') >= 0) { - return $this->setError('msg_comment_blamed_cancel_not'); + throw new Rhymix\Framework\Exception('failed_blamed_canceled'); } $point = -1; $output = $this->updateVotedCountCancel($comment_srl, $oComment, $point); @@ -145,19 +163,58 @@ class commentController extends comment function updateVotedCountCancel($comment_srl, $oComment, $point) { $logged_info = Context::get('logged_info'); + + // Check if the current user has voted previously. + $args = new stdClass; + $args->comment_srl = $comment_srl; + $args->point = $point; + if($logged_info->member_srl) + { + $args->member_srl = $logged_info->member_srl; + } + else + { + $args->ipaddress = $_SERVER['REMOTE_ADDR']; + } + $output = executeQuery('comment.getCommentVotedLogInfo', $args); + if(!$output->data->count) + { + return new BaseObject(-1, $point > 0 ? 'failed_voted_canceled' : 'failed_blamed_canceled'); + } + + // Call a trigger (before) + $trigger_obj = new stdClass; + $trigger_obj->member_srl = $oComment->get('member_srl'); + $trigger_obj->module_srl = $oComment->get('module_srl'); + $trigger_obj->document_srl = $oComment->get('document_srl'); + $trigger_obj->comment_srl = $oComment->get('comment_srl'); + $trigger_obj->update_target = ($point < 0) ? 'blamed_count' : 'voted_count'; + $trigger_obj->point = $point; + $trigger_obj->before_point = ($point < 0) ? $oComment->get('blamed_count') : $oComment->get('voted_count'); + $trigger_obj->after_point = $trigger_obj->before_point - $point; + $trigger_obj->cancel = true; + $trigger_output = ModuleHandler::triggerCall('comment.updateVotedCountCancel', 'before', $trigger_obj); + if(!$trigger_output->toBool()) + { + return $trigger_output; + } + + // begin transaction + $oDB = DB::getInstance(); + $oDB->begin(); $args = new stdClass(); $d_args = new stdClass(); $args->comment_srl = $d_args->comment_srl = $comment_srl; $d_args->member_srl = $logged_info->member_srl; - if($point > 0) + if ($trigger_obj->update_target === 'voted_count') { - $args->voted_count = $oComment->get('voted_count') - $point; + $args->voted_count = $trigger_obj->after_point; $output = executeQuery('comment.updateVotedCount', $args); } else { - $args->blamed_count = $oComment->get('blamed_count') - $point; + $args->blamed_count = $trigger_obj->after_point; $output = executeQuery('comment.updateBlamedCount', $args); } $d_output = executeQuery('comment.deleteCommentVotedLog', $d_args); @@ -165,22 +222,10 @@ class commentController extends comment //session reset $_SESSION['voted_comment'][$comment_srl] = false; - - // begin transaction - $oDB = DB::getInstance(); - $oDB->begin(); - - $obj = new stdClass(); - $obj->member_srl = $oComment->get('member_srl'); - $obj->module_srl = $oComment->get('module_srl'); - $obj->comment_srl = $oComment->get('comment_srl'); - $obj->update_target = ($point < 0) ? 'blamed_count' : 'voted_count'; - $obj->point = $point; - $obj->before_point = ($point < 0) ? $oComment->get('blamed_count') : $oComment->get('voted_count'); - $obj->after_point = ($point < 0) ? $args->blamed_count : $args->voted_count; - $obj->cancel = 1; - ModuleHandler::triggerCall('comment.updateVotedCountCancel', 'after', $obj); + // Call a trigger (after) + ModuleHandler::triggerCall('comment.updateVotedCountCancel', 'after', $trigger_obj); + $oDB->commit(); return $output; } @@ -193,13 +238,13 @@ class commentController extends comment { if(!Context::get('is_logged')) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $comment_srl = Context::get('target_srl'); if(!$comment_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // if an user select message from options, message would be the option. @@ -297,7 +342,7 @@ class commentController extends comment { if(!$manual_inserted && !checkCSRF()) { - return new BaseObject(-1, 'msg_invalid_request'); + return new BaseObject(-1, 'msg_security_violation'); } if(!is_object($obj)) @@ -348,6 +393,12 @@ class commentController extends comment // Remove manual member info to prevent forgery. This variable can be set by triggers only. unset($obj->manual_member_info); + // Sanitize variables + $obj->comment_srl = intval($obj->comment_srl); + $obj->module_srl = intval($obj->module_srl); + $obj->document_srl = intval($obj->document_srl); + $obj->parent_srl = intval($obj->parent_srl); + // call a trigger (before) $output = ModuleHandler::triggerCall('comment.insertComment', 'before', $obj); if(!$output->toBool()) @@ -389,7 +440,7 @@ class commentController extends comment if($obj->homepage) { - $obj->homepage = removeHackTag($obj->homepage); + $obj->homepage = escape($obj->homepage); if(!preg_match('/^[a-z]+:\/\//i',$obj->homepage)) { $obj->homepage = 'http://'.$obj->homepage; @@ -494,7 +545,7 @@ class commentController extends comment // return if no parent comment exists if(!$parent_output->toBool() || !$parent_output->data) { - return $parent_output; + return new BaseObject(-1, 'parent comment does not exist'); } $parent = $parent_output->data; @@ -544,14 +595,12 @@ class commentController extends comment return $output; } - // get the number of all comments in the posting - $comment_count = $oCommentModel->getCommentCount($document_srl); - // create the controller object of the document $oDocumentController = getController('document'); // Update the number of comments in the post - if(!$using_validation || $is_admin) + $comment_count = $oCommentModel->getCommentCount($document_srl); + if($comment_count && (!$using_validation || $is_admin)) { $output = $oDocumentController->updateCommentCount($document_srl, $comment_count, $obj->nick_name, $update_document); } @@ -701,7 +750,7 @@ class commentController extends comment { if(!$manual_updated && !checkCSRF()) { - return new BaseObject(-1, 'msg_invalid_request'); + return new BaseObject(-1, 'msg_security_violation'); } if(!is_object($obj)) @@ -713,7 +762,13 @@ class commentController extends comment // Remove manual member info to prevent forgery. This variable can be set by triggers only. unset($obj->manual_member_info); - + + // Sanitize variables + $obj->comment_srl = intval($obj->comment_srl); + $obj->module_srl = intval($obj->module_srl); + $obj->document_srl = intval($obj->document_srl); + $obj->parent_srl = intval($obj->parent_srl); + // call a trigger (before) $output = ModuleHandler::triggerCall('comment.updateComment', 'before', $obj); if(!$output->toBool()) @@ -748,7 +803,7 @@ class commentController extends comment if($obj->homepage) { - $obj->homepage = removeHackTag($obj->homepage); + $obj->homepage = escape($obj->homepage); if(!preg_match('/^[a-z]+:\/\//i',$obj->homepage)) { $obj->homepage = 'http://'.$obj->homepage; @@ -973,6 +1028,7 @@ class commentController extends comment $document_srl = $comment->document_srl; // call a trigger (before) + $comment->isMoveToTrash = $isMoveToTrash ? true : false; $output = ModuleHandler::triggerCall('comment.deleteComment', 'before', $comment); if(!$output->toBool()) { @@ -1080,7 +1136,6 @@ class commentController extends comment } // call a trigger (after) - $comment->isMoveToTrash = $isMoveToTrash; ModuleHandler::triggerCall('comment.deleteComment', 'after', $comment); unset($comment->isMoveToTrash); @@ -1136,9 +1191,8 @@ class commentController extends comment return new BaseObject(-1, 'msg_admin_comment_no_move_to_trash'); } - $trash_args->module_srl = $oComment->variables['module_srl']; - $obj->module_srl = $oComment->variables['module_srl']; - + $obj->module_srl = $oComment->get('module_srl'); + $trash_args->module_srl = $obj->module_srl; if($trash_args->module_srl === 0) { return new BaseObject(-1, 'msg_module_srl_not_exists'); @@ -1214,6 +1268,11 @@ class commentController extends comment executeQuery('file.updateFileValid', $args); } + $obj->document_srl = $oComment->get('document_srl'); + $obj->parent_srl = $oComment->get('parent_srl'); + $obj->member_srl = $oComment->get('member_srl'); + $obj->regdate = $oComment->get('regdate'); + $obj->last_update = $oComment->get('last_update'); ModuleHandler::triggerCall('comment.moveCommentToTrash', 'after', $obj); $oDB->commit(); @@ -1341,12 +1400,10 @@ class commentController extends comment if($point > 0) { $failed_voted = 'failed_voted'; - $success_message = 'success_voted'; } else { $failed_voted = 'failed_blamed'; - $success_message = 'success_blamed'; } // invalid vote if vote info exists in the session info. @@ -1355,23 +1412,24 @@ class commentController extends comment return new BaseObject(-1, $failed_voted); } + // Get the original comment $oCommentModel = getModel('comment'); $oComment = $oCommentModel->getComment($comment_srl, FALSE, FALSE); - // invalid vote if both ip addresses between author's and the current user are same. + // Pass if the author's IP address is as same as visitor's. if($oComment->get('ipaddress') == $_SERVER['REMOTE_ADDR']) { $_SESSION['voted_comment'][$comment_srl] = false; return new BaseObject(-1, $failed_voted); } + // Create a member model object + $oMemberModel = getModel('member'); + $member_srl = $oMemberModel->getLoggedMemberSrl(); + // if the comment author is a member if($oComment->get('member_srl')) { - // create the member model object - $oMemberModel = getModel('member'); - $member_srl = $oMemberModel->getLoggedMemberSrl(); - // session registered if the author information matches to the current logged-in user's. if($member_srl && $member_srl == abs($oComment->get('member_srl'))) { @@ -1380,9 +1438,8 @@ class commentController extends comment } } - $args = new stdClass(); - // If logged-in, use the member_srl. otherwise use the ipaddress. + $args = new stdClass(); if($member_srl) { $args->member_srl = $member_srl; @@ -1391,61 +1448,72 @@ class commentController extends comment { $args->ipaddress = $_SERVER['REMOTE_ADDR']; } - $args->comment_srl = $comment_srl; $output = executeQuery('comment.getCommentVotedLogInfo', $args); - // session registered if log info contains recommendation vote log. + // Pass after registering a session if log information has vote-up logs if($output->data->count) { $_SESSION['voted_comment'][$comment_srl] = false; return new BaseObject(-1, $failed_voted); } + // Call a trigger (before) + $trigger_obj = new stdClass; + $trigger_obj->member_srl = $oComment->get('member_srl'); + $trigger_obj->module_srl = $oComment->get('module_srl'); + $trigger_obj->document_srl = $oComment->get('document_srl'); + $trigger_obj->comment_srl = $oComment->get('comment_srl'); + $trigger_obj->update_target = ($point < 0) ? 'blamed_count' : 'voted_count'; + $trigger_obj->point = $point; + $trigger_obj->before_point = ($point < 0) ? $oComment->get('blamed_count') : $oComment->get('voted_count'); + $trigger_obj->after_point = $trigger_obj->before_point + $point; + $trigger_obj->cancel = false; + $trigger_output = ModuleHandler::triggerCall('comment.updateVotedCount', 'before', $trigger_obj); + if(!$trigger_output->toBool()) + { + return $trigger_output; + } + // begin transaction $oDB = DB::getInstance(); $oDB->begin(); - // update the number of votes - if($point < 0) + // Update the voted count + if($trigger_obj->update_target === 'blamed_count') { // leave into session information - $_SESSION['voted_comment'][$comment_srl] = $point; - $args->blamed_count = $oComment->get('blamed_count') + $point; + $args->blamed_count = $trigger_obj->after_point; $output = executeQuery('comment.updateBlamedCount', $args); } else { - $_SESSION['voted_comment'][$comment_srl] = $point; - $args->voted_count = $oComment->get('voted_count') + $point; + $args->voted_count = $trigger_obj->after_point; $output = executeQuery('comment.updateVotedCount', $args); } // leave logs - $args->point = $point; + $args->point = $trigger_obj->point; $output = executeQuery('comment.insertCommentVotedLog', $args); - $obj = new stdClass(); - $obj->member_srl = $oComment->get('member_srl'); - $obj->module_srl = $oComment->get('module_srl'); - $obj->comment_srl = $oComment->get('comment_srl'); - $obj->update_target = ($point < 0) ? 'blamed_count' : 'voted_count'; - $obj->point = $point; - $obj->before_point = ($point < 0) ? $oComment->get('blamed_count') : $oComment->get('voted_count'); - $obj->after_point = ($point < 0) ? $args->blamed_count : $args->voted_count; - - ModuleHandler::triggerCall('comment.updateVotedCount', 'after', $obj); + // Leave in the session information + $_SESSION['voted_comment'][$comment_srl] = $trigger_obj->point; + + // Call a trigger (after) + ModuleHandler::triggerCall('comment.updateVotedCount', 'after', $trigger_obj); $oDB->commit(); // Return the result - $output = new BaseObject(0, $success_message); - if($point > 0) + $output = new BaseObject(); + if($trigger_obj->update_target === 'voted_count') { - $output->add('voted_count', $obj->after_point); + $output->setMessage('success_voted'); + $output->add('voted_count', $trigger_obj->after_point); } else { - $output->add('blamed_count', $obj->after_point); + $output->setMessage('success_blamed'); + $output->add('blamed_count', $trigger_obj->after_point); } return $output; @@ -1500,13 +1568,12 @@ class commentController extends comment return new BaseObject(-1, 'failed_declared'); } + // Get currently logged in user. + $member_srl = intval($this->user->member_srl); + // if the comment author is a member if($oComment->get('member_srl')) { - // create the member model object - $oMemberModel = getModel('member'); - $member_srl = $oMemberModel->getLoggedMemberSrl(); - // session registered if the author information matches to the current logged-in user's. if($member_srl && $member_srl == abs($oComment->get('member_srl'))) { @@ -1515,29 +1582,31 @@ class commentController extends comment } } - // If logged-in, use the member_srl. otherwise use the ipaddress. + // Pass after registering a sesson if reported/declared documents are in the logs. + $args = new stdClass; + $args->comment_srl = $comment_srl; if($member_srl) { $args->member_srl = $member_srl; } else { - $args->ipaddress = $_SERVER['REMOTE_ADDR']; + $args->ipaddress = \RX_CLIENT_IP; } - - $args->comment_srl = $comment_srl; - $args->declare_message = $declare_message; $log_output = executeQuery('comment.getCommentDeclaredLogInfo', $args); - - // session registered if log info contains report log. if($log_output->data->count) { $_SESSION['declared_comment'][$comment_srl] = TRUE; return new BaseObject(-1, 'failed_declared'); } - + + // Fill in remaining information for logging. + $args->member_srl = $member_srl; + $args->ipaddress = \RX_CLIENT_IP; + $args->declare_message = $declare_message; + // begin transaction - $oDB = &DB::getInstance(); + $oDB = DB::getInstance(); $oDB->begin(); // execute insert @@ -1655,13 +1724,13 @@ class commentController extends comment $module_info = $oModuleModel->getModuleInfoByModuleSrl($srl); if (!$module_info->module_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $module_grant = $oModuleModel->getGrant($module_info, $logged_info); if (!$module_grant->manager) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $module_srl[] = $srl; @@ -1729,7 +1798,7 @@ class commentController extends comment { if(!Context::get('is_logged')) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $commentSrls = Context::get('comment_srls'); diff --git a/modules/comment/comment.item.php b/modules/comment/comment.item.php index 48c0505c4..927a1a767 100644 --- a/modules/comment/comment.item.php +++ b/modules/comment/comment.item.php @@ -287,12 +287,12 @@ class commentItem extends BaseObject return; } - if(strncasecmp('http://', $url, 7) !== 0) + if(!preg_match('@^[a-z]+://@i', $url)) { - $url = "http://" . $url; + $url = 'http://' . $url; } - return htmlspecialchars($url, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + return escape($url, false); } function getMemberSrl() @@ -302,17 +302,17 @@ class commentItem extends BaseObject function getUserID() { - return htmlspecialchars($this->get('user_id'), ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + return escape($this->get('user_id'), false); } function getUserName() { - return htmlspecialchars($this->get('user_name'), ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + return escape($this->get('user_name'), false); } function getNickName() { - return htmlspecialchars($this->get('nick_name'), ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + return escape($this->get('nick_name'), false); } function getVote() @@ -388,7 +388,7 @@ class commentItem extends BaseObject { $content = $this->get('content'); } - + if($strlen) { $content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content)))); diff --git a/modules/comment/comment.model.php b/modules/comment/comment.model.php index 2db5e9084..127454b10 100644 --- a/modules/comment/comment.model.php +++ b/modules/comment/comment.model.php @@ -977,7 +977,7 @@ class commentModel extends comment $comment_srl = Context::get('comment_srl'); if(!$comment_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $point = Context::get('point'); @@ -991,7 +991,7 @@ class commentModel extends comment $module_srl = $oComment->get('module_srl'); if(!$module_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $oModuleModel = getModel('module'); @@ -1003,7 +1003,7 @@ class commentModel extends comment { if($comment_config->use_vote_down != 'S') { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\FeatureDisabled; } $args->below_point = 0; @@ -1012,7 +1012,7 @@ class commentModel extends comment { if($comment_config->use_vote_up != 'S') { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\FeatureDisabled; } $args->more_point = 0; diff --git a/modules/comment/comment.view.php b/modules/comment/comment.view.php index c19d142cf..85052b8f9 100644 --- a/modules/comment/comment.view.php +++ b/modules/comment/comment.view.php @@ -73,7 +73,7 @@ class commentView extends comment // A message appears if the user is not logged-in if(!$oMemberModel->isLogged()) { - return $this->stop('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } // Create the comment object. @@ -82,12 +82,12 @@ class commentView extends comment $oComment = $oCommentModel->getComment($comment_srl); if(!$oComment->isExists()) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\TargetNotFound; } // Check permissions if(!$oComment->isAccessible()) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } // Browser title settings diff --git a/modules/comment/lang/ko.php b/modules/comment/lang/ko.php index 6feb1e192..e4c71190c 100644 --- a/modules/comment/lang/ko.php +++ b/modules/comment/lang/ko.php @@ -7,8 +7,6 @@ $lang->trash = '휴지통'; $lang->cmd_trash = '휴지통으로 이동'; $lang->comment_count = '댓글 수'; $lang->about_comment_count = '댓글을 정해진 수 만큼만 표시하고, 그 이상일 경우 페이지 번호를 표시해서 이동할 수 있게 합니다.'; -$lang->msg_comment_voted_cancel_not = '추천수가 0이하일 경우 추천캔슬을 사용할 수 없습니다.'; -$lang->msg_comment_blamed_cancel_not = '추천수가 0이하일 경우 비추천캔슬을 사용할 수 없습니다.'; $lang->msg_cart_is_null = '삭제할 글을 선택해주세요.'; $lang->msg_checked_comment_is_deleted = '%d개의 댓글을 삭제했습니다.'; $lang->search_target_list['content'] = '내용'; diff --git a/modules/comment/queries/getCommentVotedLogInfo.xml b/modules/comment/queries/getCommentVotedLogInfo.xml index edc95e514..6bb3cd9c7 100644 --- a/modules/comment/queries/getCommentVotedLogInfo.xml +++ b/modules/comment/queries/getCommentVotedLogInfo.xml @@ -7,6 +7,7 @@ + diff --git a/modules/comment/queries/getTotalCommentCountByGroupStatus.xml b/modules/comment/queries/getTotalCommentCountByGroupStatus.xml index c9a3f8f9b..6516a1f64 100644 --- a/modules/comment/queries/getTotalCommentCountByGroupStatus.xml +++ b/modules/comment/queries/getTotalCommentCountByGroupStatus.xml @@ -12,8 +12,8 @@ - - + + diff --git a/modules/comment/queries/getTotalCommentCountWithinMemberByGroupStatus.xml b/modules/comment/queries/getTotalCommentCountWithinMemberByGroupStatus.xml index 1e6257bdd..dabd55ab1 100644 --- a/modules/comment/queries/getTotalCommentCountWithinMemberByGroupStatus.xml +++ b/modules/comment/queries/getTotalCommentCountWithinMemberByGroupStatus.xml @@ -13,8 +13,8 @@ - - + + diff --git a/modules/comment/queries/getTotalCommentList.xml b/modules/comment/queries/getTotalCommentList.xml index 8c26a8319..13dfa0dd5 100644 --- a/modules/comment/queries/getTotalCommentList.xml +++ b/modules/comment/queries/getTotalCommentList.xml @@ -13,8 +13,8 @@ - - + + diff --git a/modules/comment/queries/getTotalCommentListWithinMember.xml b/modules/comment/queries/getTotalCommentListWithinMember.xml index 042547c89..820f1ab27 100644 --- a/modules/comment/queries/getTotalCommentListWithinMember.xml +++ b/modules/comment/queries/getTotalCommentListWithinMember.xml @@ -14,8 +14,8 @@ - - + + diff --git a/modules/comment/tpl/comment_list.html b/modules/comment/tpl/comment_list.html index 4ce9ff983..b93b21850 100644 --- a/modules/comment/tpl/comment_list.html +++ b/modules/comment/tpl/comment_list.html @@ -7,7 +7,7 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}';

    {$XE_VALIDATOR_MESSAGE}

    - +
    - + - - - + + + @@ -58,11 +62,14 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}'; ({$member_nick_name[abs($val->get('member_srl'))]}){$val->getNickName()} - - - - - + + + + + diff --git a/modules/comment/tpl/comment_module_config.html b/modules/comment/tpl/comment_module_config.html index 70dbac403..8181eb570 100644 --- a/modules/comment/tpl/comment_module_config.html +++ b/modules/comment/tpl/comment_module_config.html @@ -45,8 +45,8 @@
    - - + +
    diff --git a/modules/comment/tpl/header.html b/modules/comment/tpl/header.html index 8a9d09881..76a1e8cbd 100644 --- a/modules/comment/tpl/header.html +++ b/modules/comment/tpl/header.html @@ -1,4 +1,4 @@
    -

    {$lang->comment} {$lang->cmd_management} {$lang->help}

    +

    {$lang->comment} {$lang->cmd_management}

    diff --git a/modules/communication/communication.controller.php b/modules/communication/communication.controller.php index ebd7b382c..a1c228db7 100644 --- a/modules/communication/communication.controller.php +++ b/modules/communication/communication.controller.php @@ -24,7 +24,7 @@ class communicationController extends communication { if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $args = new stdClass(); @@ -54,7 +54,7 @@ class communicationController extends communication // Check login information if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -63,25 +63,19 @@ class communicationController extends communication $receiver_srl = Context::get('receiver_srl'); if(!$receiver_srl) { - return $this->setError('msg_not_exists_member'); + throw new Rhymix\Framework\Exception('msg_not_exists_member'); } - $title = trim(Context::get('title')); + $title = trim(escape(Context::get('title'))); if(!$title) { - return $this->setError('msg_title_is_null'); + throw new Rhymix\Framework\Exception('msg_title_is_null'); } $content = trim(Context::get('content')); if(!$content) { - return $this->setError('msg_content_is_null'); - } - - $send_mail = Context::get('send_mail'); - if($send_mail != 'Y') - { - $send_mail = 'N'; + throw new Rhymix\Framework\Exception('msg_content_is_null'); } // Check if there is a member to receive a message @@ -91,13 +85,13 @@ class communicationController extends communication if(!$oCommunicationModel->checkGrant($config->grant_send)) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $receiver_member_info = $oMemberModel->getMemberInfoByMemberSrl($receiver_srl); if($receiver_member_info->member_srl != $receiver_srl) { - return $this->setError('msg_not_exists_member'); + throw new Rhymix\Framework\Exception('msg_not_exists_member'); } // check whether to allow to receive the message(pass if a top-administrator) @@ -107,12 +101,12 @@ class communicationController extends communication { if(!$oCommunicationModel->isFriend($receiver_member_info->member_srl)) { - return $this->setError('msg_allow_message_to_friend'); + throw new Rhymix\Framework\Exception('msg_allow_message_to_friend'); } } else if($receiver_member_info->allow_message == 'N') { - return $this->setError('msg_disallow_message'); + throw new Rhymix\Framework\Exception('msg_disallow_message'); } } @@ -124,21 +118,6 @@ class communicationController extends communication return $output; } - // send an e-mail - if($send_mail == 'Y') - { - $view_url = Context::getRequestUri(); - $content = sprintf("%s

    From : %s", $content, $view_url, $view_url); - - $oMail = new \Rhymix\Framework\Mail(); - $oMail->setSubject($title); - $oMail->setBody(utf8_mbencode(removeHackTag($content))); - $oMail->setFrom(config('mail.default_from') ?: $logged_info->email_address, $logged_info->nick_name); - $oMail->setReplyTo($logged_info->email_address); - $oMail->addTo($receiver_member_info->email_address, $receiver_member_info->nick_name); - $oMail->send(); - } - if(!in_array(Context::getRequestMethod(), array('XMLRPC', 'JSON'))) { if(Context::get('is_popup') != 'Y') @@ -174,7 +153,7 @@ class communicationController extends communication function sendMessage($sender_srl, $receiver_srl, $title, $content, $sender_log = TRUE) { // Encode the title and content. - $title = htmlspecialchars($title, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + $title = escape($title, false); $content = removeHackTag($content); $title = utf8_mbencode($title); $content = utf8_mbencode($content); @@ -269,7 +248,7 @@ class communicationController extends communication // Check login information if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -277,7 +256,7 @@ class communicationController extends communication $message_srl = Context::get('message_srl'); if(!$message_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // get the message @@ -285,7 +264,7 @@ class communicationController extends communication $message = $oCommunicationModel->getSelectedMessage($message_srl); if(!$message || $message->message_type != 'R') { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $args = new stdClass(); @@ -309,7 +288,7 @@ class communicationController extends communication // Check login information if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -319,7 +298,7 @@ class communicationController extends communication $message_srl = Context::get('message_srl'); if(!$message_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Get the message @@ -327,7 +306,7 @@ class communicationController extends communication $message = $oCommunicationModel->getSelectedMessage($message_srl); if(!$message) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Check the grant @@ -336,14 +315,14 @@ class communicationController extends communication case 'S': if($message->sender_srl != $member_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } break; case 'R': if($message->receiver_srl != $member_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } break; } @@ -369,7 +348,7 @@ class communicationController extends communication // Check login information if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -378,7 +357,7 @@ class communicationController extends communication // check variables if(!Context::get('message_srl_list')) { - return $this->setError('msg_cart_is_null'); + throw new Rhymix\Framework\Exception('msg_cart_is_null'); } $message_srl_list = Context::get('message_srl_list'); @@ -389,13 +368,13 @@ class communicationController extends communication if(!count($message_srl_list)) { - return $this->setError('msg_cart_is_null'); + throw new Rhymix\Framework\Exception('msg_cart_is_null'); } $message_type = Context::get('message_type'); if(!$message_type || !in_array($message_type, array('R', 'S', 'T', 'N'))) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $message_count = count($message_srl_list); @@ -412,7 +391,7 @@ class communicationController extends communication } if(!count($target)) { - return $this->setError('msg_cart_is_null'); + throw new Rhymix\Framework\Exception('msg_cart_is_null'); } // Delete @@ -458,7 +437,7 @@ class communicationController extends communication // Check login information if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -466,11 +445,11 @@ class communicationController extends communication $target_srl = (int) trim(Context::get('target_srl')); if(!$target_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } if($target_srl == $logged_info->member_srl) { - return $this->setError('msg_no_self_friend'); + throw new Rhymix\Framework\Exception('msg_no_self_friend'); } // Check duplicate friend @@ -480,7 +459,7 @@ class communicationController extends communication $output = executeQuery('communication.isAddedFriend', $args); if($output->data->count) { - return $this->setError('msg_already_friend'); + throw new Rhymix\Framework\Exception('msg_already_friend'); } // Variable @@ -520,7 +499,7 @@ class communicationController extends communication // Check login information if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -529,7 +508,7 @@ class communicationController extends communication $friend_srl_list = Context::get('friend_srl_list'); if(!$friend_srl_list) { - return $this->setError('msg_cart_is_null'); + throw new Rhymix\Framework\Exception('msg_cart_is_null'); } if(!is_array($friend_srl_list)) @@ -539,7 +518,7 @@ class communicationController extends communication if(!count($friend_srl_list)) { - return $this->setError('msg_cart_is_null'); + throw new Rhymix\Framework\Exception('msg_cart_is_null'); } $friend_count = count($friend_srl_list); @@ -557,7 +536,7 @@ class communicationController extends communication if(!count($target)) { - return $this->setError('msg_cart_is_null'); + throw new Rhymix\Framework\Exception('msg_cart_is_null'); } // Variables @@ -587,7 +566,7 @@ class communicationController extends communication // Check login information if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -603,7 +582,7 @@ class communicationController extends communication if(!count($friend_srl_list)) { - return $this->setError('msg_cart_is_null'); + throw new Rhymix\Framework\Exception('msg_cart_is_null'); } $friend_count = count($friend_srl_list); @@ -622,7 +601,7 @@ class communicationController extends communication if(!count($target)) { - return $this->setError('msg_cart_is_null'); + throw new Rhymix\Framework\Exception('msg_cart_is_null'); } // Delete @@ -650,7 +629,7 @@ class communicationController extends communication // Check login information if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -659,12 +638,11 @@ class communicationController extends communication $args = new stdClass(); $args->friend_group_srl = trim(Context::get('friend_group_srl')); $args->member_srl = $logged_info->member_srl; - $args->title = Context::get('title'); - $args->title = htmlspecialchars($args->title, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + $args->title = escape(Context::get('title')); if(!$args->title) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // modify if friend_group_srl exists. @@ -726,7 +704,7 @@ class communicationController extends communication // Check login information if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -735,12 +713,11 @@ class communicationController extends communication $args = new stdClass(); $args->friend_group_srl = Context::get('friend_group_srl'); $args->member_srl = $logged_info->member_srl; - $args->title = Context::get('title'); - $args->title = htmlspecialchars($args->title, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + $args->title = escape(Context::get('title')); if(!$args->title) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $output = executeQuery('communication.renameFriendGroup', $args); @@ -761,7 +738,7 @@ class communicationController extends communication // Check login information if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); diff --git a/modules/communication/communication.model.php b/modules/communication/communication.model.php index 976e2d902..5cc34f982 100644 --- a/modules/communication/communication.model.php +++ b/modules/communication/communication.model.php @@ -163,7 +163,7 @@ class communicationModel extends communication $member_info = $oMemberModel->getMemberInfoByMemberSrl($message->sender_srl); } - if($member_info) + if($member_info->member_srl) { foreach($member_info as $key => $val) { @@ -176,6 +176,13 @@ class communicationModel extends communication $message->{$key} = $val; } } + else + { + $message->member_srl = ($message->sender_srl == $logged_info->member_srl) ? $message->receiver_srl : $message->sender_srl; + $message->user_id = ''; + $message->nick_name = lang('communication.cmd_message_from_non_member'); + $message->user_name = $message->nick_name; + } // change the status if is a received and not yet read message if($message->message_type == 'R' && $message->readed != 'Y') @@ -210,6 +217,14 @@ class communicationModel extends communication $oCommunicationController = getController('communication'); $oCommunicationController->setMessageReaded($message->message_srl); + + if (!$message->member_srl) + { + $message->member_srl = $message->sender_srl; + $message->user_id = ''; + $message->nick_name = lang('communication.cmd_message_from_non_member'); + $message->user_name = $message->nick_name; + } return $message; } @@ -274,7 +289,22 @@ class communicationModel extends communication $args->list_count = 20; $args->page_count = 10; - return executeQueryArray($query_id, $args, $columnList); + // Get messages from DB + $output = executeQueryArray($query_id, $args, $columnList); + + // Add placeholder for non-members + foreach ($output->data as $message) + { + if (!$message->member_srl) + { + $message->member_srl = ($message->sender_srl == $logged_info->member_srl) ? $message->receiver_srl : $message->sender_srl; + $message->user_id = ''; + $message->nick_name = lang('communication.cmd_message_from_non_member'); + $message->user_name = $message->nick_name; + } + } + + return $output; } /** diff --git a/modules/communication/communication.view.php b/modules/communication/communication.view.php index e447e8543..8a43b1c48 100644 --- a/modules/communication/communication.view.php +++ b/modules/communication/communication.view.php @@ -52,13 +52,13 @@ class communicationView extends communication { if($this->config->enable_message == 'N') { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Error appears if not logged-in if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -86,28 +86,28 @@ class communicationView extends communication case 'R': if($message->receiver_srl != $logged_info->member_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } break; case 'S': if($message->sender_srl != $logged_info->member_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } break; case 'T': if($message->receiver_srl != $logged_info->member_srl && $message->sender_srl != $logged_info->member_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } break; case 'N': if($message->receiver_srl != $logged_info->member_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } break; } @@ -151,13 +151,13 @@ class communicationView extends communication if($this->config->enable_message == 'N') { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Error appears if not logged-in if(!Context::get('is_logged')) { - return $this->stop('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -190,17 +190,17 @@ class communicationView extends communication if($this->config->enable_message == 'N') { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } if(!getModel('communication')->checkGrant($this->config->grant_send)) { - return $this->stop('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } // Error appears if not logged-in if(!Context::get('is_logged')) { - return $this->stop('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -210,13 +210,13 @@ class communicationView extends communication $receiver_srl = Context::get('receiver_srl'); if(!$receiver_srl) { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // check receiver and sender are same if($logged_info->member_srl == $receiver_srl) { - return $this->stop('msg_cannot_send_to_yourself'); + throw new Rhymix\Framework\Exception('msg_cannot_send_to_yourself'); } $oCommunicationModel = getModel('communication'); @@ -241,7 +241,7 @@ class communicationView extends communication $receiver_info = $oMemberModel->getMemberInfoByMemberSrl($receiver_srl); if(!$receiver_info) { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } Context::set('receiver_info', $receiver_info); @@ -275,13 +275,13 @@ class communicationView extends communication { if($this->config->enable_friend == 'N') { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Error appears if not logged-in if(!Context::get('is_logged')) { - return $this->stop('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $oCommunicationModel = getModel('communication'); @@ -339,13 +339,13 @@ class communicationView extends communication if($this->config->enable_friend == 'N') { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // error appears if not logged-in if(!Context::get('is_logged')) { - return $this->stop('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -353,11 +353,11 @@ class communicationView extends communication if(!$target_srl) { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } if($target_srl == $logged_info->member_srl) { - return $this->stop('msg_no_self_friend'); + throw new Rhymix\Framework\Exception('msg_no_self_friend'); } // get information of the member @@ -367,7 +367,7 @@ class communicationView extends communication if($communication_info->member_srl != $target_srl) { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } Context::set('target_info', $communication_info); @@ -390,13 +390,13 @@ class communicationView extends communication if($this->config->enable_friend == 'N') { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // error apprears if not logged-in if(!Context::get('is_logged')) { - return $this->stop('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); diff --git a/modules/communication/conf/module.xml b/modules/communication/conf/module.xml index aa4d13f61..51fe0c009 100644 --- a/modules/communication/conf/module.xml +++ b/modules/communication/conf/module.xml @@ -2,13 +2,13 @@ - - - - - - - + + + + + + + diff --git a/modules/communication/lang/en.php b/modules/communication/lang/en.php index 6299e2912..2394e894c 100644 --- a/modules/communication/lang/en.php +++ b/modules/communication/lang/en.php @@ -14,6 +14,7 @@ $lang->sender = 'From'; $lang->receiver = 'To'; $lang->friend_group = 'Friend Group'; $lang->default_friend_group = 'Unassigned Group'; +$lang->cmd_message_from_non_member = 'Not a Member'; $lang->cmd_send_message = 'Send Message'; $lang->cmd_reply_message = 'Reply Message'; $lang->cmd_view_friend = 'Friends'; diff --git a/modules/communication/lang/ko.php b/modules/communication/lang/ko.php index 35e7db54c..05267f8e8 100644 --- a/modules/communication/lang/ko.php +++ b/modules/communication/lang/ko.php @@ -14,6 +14,7 @@ $lang->sender = '보낸이'; $lang->receiver = '받는이'; $lang->friend_group = '친구 그룹'; $lang->default_friend_group = '그룹 미지정'; +$lang->cmd_message_from_non_member = '탈퇴한 회원'; $lang->cmd_send_message = '쪽지 보내기'; $lang->cmd_reply_message = '답장 보내기'; $lang->cmd_view_friend = '친구 보기'; diff --git a/modules/communication/m.skins/default/read_message.html b/modules/communication/m.skins/default/read_message.html index 9a7d68407..baa758265 100644 --- a/modules/communication/m.skins/default/read_message.html +++ b/modules/communication/m.skins/default/read_message.html @@ -4,7 +4,7 @@

    {$message->title}

    {$message->nick_name} | {zdate($message->regdate, "Y.m.d H:i")}
    -
    {$message->content}
    +
    {$message->content|noescape}
    {$lang->cmd_list} diff --git a/modules/communication/m.skins/default/send_message.html b/modules/communication/m.skins/default/send_message.html index bf65f38ae..125f3c295 100644 --- a/modules/communication/m.skins/default/send_message.html +++ b/modules/communication/m.skins/default/send_message.html @@ -35,15 +35,12 @@
  • - {$source_message->content} + {$source_message->content|noescape}
  • -
  • - {$lang->cmd_send_mail} -
  • {$lang->cmd_back} diff --git a/modules/communication/m.skins/rx_prn/new_message.html b/modules/communication/m.skins/rx_prn/new_message.html index 74cde0577..24ea7870e 100644 --- a/modules/communication/m.skins/rx_prn/new_message.html +++ b/modules/communication/m.skins/rx_prn/new_message.html @@ -7,7 +7,7 @@ {$message->nick_name} / {zdate($message->regdate, "Y-m-d H:i")}
    - {$message->content} + {$message->content|noescape}
    {$lang->cmd_reply_message} diff --git a/modules/communication/m.skins/rx_prn/send_message.html b/modules/communication/m.skins/rx_prn/send_message.html index 378c35b22..019bbf969 100644 --- a/modules/communication/m.skins/rx_prn/send_message.html +++ b/modules/communication/m.skins/rx_prn/send_message.html @@ -27,14 +27,12 @@ {$receiver_info->nick_name} - -
    {$lang->msg_send_mail_privacy}
    - {$editor} + {$editor|noescape}
    - \ No newline at end of file + diff --git a/modules/communication/queries/getNewMessage.xml b/modules/communication/queries/getNewMessage.xml index 8f233094c..213690279 100644 --- a/modules/communication/queries/getNewMessage.xml +++ b/modules/communication/queries/getNewMessage.xml @@ -1,7 +1,11 @@
    {$lang->all}({number_format($total_count)}) | @@ -22,7 +22,7 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}'; {$lang->cmd_declared_list} | {$lang->ipaddress}:{$search_keyword}({number_format($total_count)}) - +
    {$lang->trash} {$lang->delete} @@ -31,16 +31,20 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}'; {$lang->cmd_unpublish} {$lang->cmd_publish}
    +
    + + +
    {$lang->comment} {$lang->writer}{$lang->cmd_vote}(+/-){$lang->cmd_vote}(+/-) {$lang->date}{$lang->ipaddress}{$lang->status}{$lang->published}{$lang->ipaddress}{$lang->status}{$lang->published}
    {number_format($val->get('voted_count'))}/{number_format($val->get('blamed_count'))}{(zdate($val->regdate,"Y-m-d\nH:i:s"))}{$val->ipaddress}{$secret_name_list['Y']}{$secret_name_list['N']}{$lang->published_name_list['Y']}{$lang->published_name_list['N']}{number_format($val->get('voted_count'))}/{number_format($val->get('blamed_count'))} + {$val->getRegdate('Y-m-d H:i:s')} + {$val->getRegdate($val->getRegdateTime() > time() - 86400 ? 'H:i' : 'm-d')} + {$val->ipaddress}{$secret_name_list['Y']}{$secret_name_list['N']}{$lang->published_name_list['Y']}{$lang->published_name_list['N']}
    -
    +
    + + + +
    @@ -9,7 +13,6 @@ - diff --git a/modules/communication/queries/getNewMessageCount.xml b/modules/communication/queries/getNewMessageCount.xml index 9ef32c1e0..50df7889c 100644 --- a/modules/communication/queries/getNewMessageCount.xml +++ b/modules/communication/queries/getNewMessageCount.xml @@ -1,7 +1,6 @@ -
    @@ -9,7 +8,6 @@ - diff --git a/modules/communication/queries/getReadedMessages.xml b/modules/communication/queries/getReadedMessages.xml index 9f5607dab..e8465ebf8 100644 --- a/modules/communication/queries/getReadedMessages.xml +++ b/modules/communication/queries/getReadedMessages.xml @@ -1,7 +1,11 @@
    -
    +
    + + + +
    @@ -14,7 +18,6 @@ - diff --git a/modules/communication/queries/getReceivedMessages.xml b/modules/communication/queries/getReceivedMessages.xml index ba56c2fb0..09ea8a7be 100644 --- a/modules/communication/queries/getReceivedMessages.xml +++ b/modules/communication/queries/getReceivedMessages.xml @@ -1,7 +1,11 @@ -
    +
    + + + +
    @@ -13,7 +17,6 @@ - diff --git a/modules/communication/queries/getSendedMessages.xml b/modules/communication/queries/getSendedMessages.xml index 9fc82db39..aa7a0239b 100644 --- a/modules/communication/queries/getSendedMessages.xml +++ b/modules/communication/queries/getSendedMessages.xml @@ -1,7 +1,11 @@ -
    +
    + + + +
    @@ -13,7 +17,6 @@ - diff --git a/modules/communication/queries/getStoredMessages.xml b/modules/communication/queries/getStoredMessages.xml index 0888b7611..553d3c23a 100644 --- a/modules/communication/queries/getStoredMessages.xml +++ b/modules/communication/queries/getStoredMessages.xml @@ -1,7 +1,11 @@ -
    +
    + + + +
    @@ -13,7 +17,6 @@ - diff --git a/modules/communication/skins/default/messages.html b/modules/communication/skins/default/messages.html index 0e6d94f6a..773248ca5 100644 --- a/modules/communication/skins/default/messages.html +++ b/modules/communication/skins/default/messages.html @@ -29,7 +29,7 @@
    - {$message->content} + {$message->content|noescape}
    diff --git a/modules/communication/skins/default/new_message.html b/modules/communication/skins/default/new_message.html index 66b992d41..e5c75ac3a 100644 --- a/modules/communication/skins/default/new_message.html +++ b/modules/communication/skins/default/new_message.html @@ -14,7 +14,7 @@ {htmlspecialchars($message->title, ENT_COMPAT | ENT_HTML401, 'UTF-8', false)} - {$message->content} + {$message->content|noescape}
    diff --git a/modules/communication/skins/default/send_message.html b/modules/communication/skins/default/send_message.html index 2a9ffe14b..b64b5d094 100644 --- a/modules/communication/skins/default/send_message.html +++ b/modules/communication/skins/default/send_message.html @@ -30,12 +30,8 @@ {$lang->title} - - {$lang->cmd_option} - {$lang->cmd_send_mail} {$lang->msg_send_mail_privacy} - - {$editor} + {$editor|noescape}
    diff --git a/modules/communication/skins/simple_world/new_message.html b/modules/communication/skins/simple_world/new_message.html index 43c29a070..d1a160fa0 100644 --- a/modules/communication/skins/simple_world/new_message.html +++ b/modules/communication/skins/simple_world/new_message.html @@ -6,7 +6,7 @@ {$message->nick_name} / {zdate($message->regdate, "Y-m-d H:i")}
    - {$message->content} + {$message->content|noescape}
    - {$editor} + {$editor|noescape}
    diff --git a/modules/communication/tpl/index.html b/modules/communication/tpl/index.html index 4f3909820..9fc84762e 100644 --- a/modules/communication/tpl/index.html +++ b/modules/communication/tpl/index.html @@ -104,12 +104,9 @@
    - {$lang->help} - +

    {$lang->about_category_color}

    diff --git a/modules/document/tpl/checked_list.html b/modules/document/tpl/checked_list.html index dd32526f1..8fad65593 100644 --- a/modules/document/tpl/checked_list.html +++ b/modules/document/tpl/checked_list.html @@ -1,5 +1,6 @@ +{@Context::addMetaTag('viewport', 'width=device-width', FALSE);}
    @@ -24,7 +25,7 @@
    - + {$lang->cmd_select} @@ -33,7 +34,7 @@
    - +
    diff --git a/modules/document/tpl/declared_list.html b/modules/document/tpl/declared_list.html index ebff6d199..f5b038b47 100644 --- a/modules/document/tpl/declared_list.html +++ b/modules/document/tpl/declared_list.html @@ -19,7 +19,6 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}'; {$status_name_list['SECRET']} | {$status_name_list['TEMP']} - {$lang->help} | {$lang->cmd_declared_list}({number_format($total_count)}) @@ -141,7 +140,7 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}';

    {$lang->msg_select_menu}

    {$lang->selected_document_move}

    -
    +
    diff --git a/modules/document/tpl/document_config.html b/modules/document/tpl/document_config.html index 0f0781b40..b8a7d0137 100644 --- a/modules/document/tpl/document_config.html +++ b/modules/document/tpl/document_config.html @@ -6,17 +6,15 @@
    -
    - -
    - -

    {$lang->about_view_count_option}

    -
    + +
    + +

    {$lang->about_view_count_option}

    @@ -26,8 +24,7 @@ - {$lang->help} - +

    {$lang->about_cmd_pc_icon_setting}

    @@ -37,8 +34,7 @@ - {$lang->help} - +

    {$lang->about_cmd_mobile_icon_setting}

    diff --git a/modules/document/tpl/document_list.html b/modules/document/tpl/document_list.html index a4f6afcdc..79a682371 100644 --- a/modules/document/tpl/document_list.html +++ b/modules/document/tpl/document_list.html @@ -10,7 +10,7 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}'; - +
    - - + + - - + + @@ -48,20 +51,24 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}'; + {htmlspecialchars($oDocument->getTitleText())}{$lang->no_title_document} + + + - {$module_list[$oDocument->get('module_srl')]->browser_title} + - - - - - + + + + + @@ -159,7 +166,7 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}';

    {$lang->msg_select_menu}

    {$lang->selected_document_move}

    -
    +
    @@ -211,9 +218,6 @@ jQuery(function($){ $('#manageForm input[name=module_srl]').val(aSelected[0].module_srl); }); - $('._menuSelector').bind('site_changed', function(){ - $('#manageForm input[name=module_srl]').val(''); - }); } } }); diff --git a/modules/document/tpl/document_module_config.html b/modules/document/tpl/document_module_config.html index c0293d2b0..e578c5116 100644 --- a/modules/document/tpl/document_module_config.html +++ b/modules/document/tpl/document_module_config.html @@ -40,8 +40,8 @@
    - - + +
    diff --git a/modules/document/tpl/header.html b/modules/document/tpl/header.html index d0fe0267b..d8f0029c1 100644 --- a/modules/document/tpl/header.html +++ b/modules/document/tpl/header.html @@ -1,14 +1,14 @@
    -

    {$lang->document} {$lang->help}

    +

    {$lang->document}

    • {$lang->document_list}
    • - {$lang->cmd_module_config} + {$lang->cmd_document_module_config}
    • {$lang->cmd_declared_list} diff --git a/modules/document/tpl/preview_page.html b/modules/document/tpl/preview_page.html index eb1e0f8a3..d1eb515af 100644 --- a/modules/document/tpl/preview_page.html +++ b/modules/document/tpl/preview_page.html @@ -1,5 +1,5 @@ -{$content} +{$content|noescape}
      diff --git a/modules/document/tpl/print_page.html b/modules/document/tpl/print_page.html index 56961e537..89bd0643e 100644 --- a/modules/document/tpl/print_page.html +++ b/modules/document/tpl/print_page.html @@ -7,7 +7,7 @@ {$val->name}: {$val->getValueHtml()} -{$oDocument->getContent(false, false)} +{$oDocument->getContent(false, false)|noescape} diff --git a/modules/document/tpl/saved_list_popup.html b/modules/document/tpl/saved_list_popup.html index 0ea345a05..38823f693 100644 --- a/modules/document/tpl/saved_list_popup.html +++ b/modules/document/tpl/saved_list_popup.html @@ -1,35 +1,40 @@ -

      {$lang->cmd_view_saved_document}

      - -
    {$lang->all}({number_format($total_count)}) | @@ -19,7 +19,6 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}'; {$status_name_list['SECRET']}({number_format($total_count)}) | {$status_name_list['TEMP']}({number_format($total_count)}) - {$lang->help} | {$lang->cmd_declared_list} | @@ -31,16 +30,20 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}'; {$lang->move} {$lang->copy} +
    + + +
    {$lang->title} {$lang->writer}{$lang->readed_count}{$lang->cmd_vote}(+/-){$lang->readed_count}{$lang->cmd_vote}(+/-) {$lang->date}{$lang->ipaddress}{$lang->status}{$lang->ipaddress}{$lang->status}
    - - {$module_list[$oDocument->get('module_srl')]->browser_title} - - - {htmlspecialchars($oDocument->getTitleText())}{$lang->no_title_document} {$oDocument->getNickName()} ({$member_nick_name[abs($oDocument->get('member_srl'))]}) {$oDocument->getNickName()} {$oDocument->get('readed_count')}{$oDocument->get('voted_count')}/{$oDocument->get('blamed_count')}{$oDocument->getRegdate("Y-m-d H:i")}{$oDocument->get('ipaddress')}{$status_name_list[$oDocument->get('status')]}{$oDocument->get('readed_count')}{$oDocument->get('voted_count')}/{$oDocument->get('blamed_count')} + {$oDocument->getRegdate('Y-m-d H:i:s')} + {$oDocument->getRegdate($oDocument->getRegdateTime() > time() - 86400 ? 'H:i' : 'm-d')} + {$oDocument->get('ipaddress')}{$status_name_list[$oDocument->get('status')]}
    - - - - - - - - - - - - - - - - - -
    Total : {number_format($total_count)}, Page {number_format($page)}/{number_format($total_page)}
    {$lang->date}{$lang->title}{$lang->cmd_select}
    {$val->getRegdate("Y-m-d H:i:s")} {$val->getTitle()} - - {$lang->cmd_select}
    - -
    - +
    diff --git a/modules/editor/conf/module.xml b/modules/editor/conf/module.xml index 7a65b3342..2e6f733a0 100644 --- a/modules/editor/conf/module.xml +++ b/modules/editor/conf/module.xml @@ -2,12 +2,12 @@ - - - - - - + + + + + + diff --git a/modules/editor/editor.admin.controller.php b/modules/editor/editor.admin.controller.php index df3949fb7..674420585 100644 --- a/modules/editor/editor.admin.controller.php +++ b/modules/editor/editor.admin.controller.php @@ -250,9 +250,18 @@ class editorAdminController extends editor $args->enabled = $enabled; $args->site_srl = $site_srl; // Check if the component exists - if(!$site_srl) $output = executeQuery('editor.isComponentInserted', $args); - else $output = executeQuery('editor.isSiteComponentInserted', $args); - if($output->data->count) return $this->setError('msg_component_is_not_founded'); + if(!$site_srl) + { + $output = executeQuery('editor.isComponentInserted', $args); + } + else + { + $output = executeQuery('editor.isSiteComponentInserted', $args); + } + if($output->data->count) + { + return new BaseObject(-1, 'msg_component_is_not_founded'); + } // Inert a component $args->list_order = getNextSequence(); if(!$site_srl) $output = executeQuery('editor.insertComponent', $args); diff --git a/modules/editor/editor.admin.view.php b/modules/editor/editor.admin.view.php index 06b4eae66..a2aadde52 100644 --- a/modules/editor/editor.admin.view.php +++ b/modules/editor/editor.admin.view.php @@ -106,9 +106,9 @@ class editorAdminView extends editor $oEditorModel = getModel('editor'); $component = $oEditorModel->getComponent($component_name,$site_srl); - if(!$component->component_name) { - $this->stop('msg_invalid_request'); - return; + if(!$component->component_name) + { + throw new Rhymix\Framework\Exceptions\InvalidRequest; } Context::set('component', $component); diff --git a/modules/editor/editor.controller.php b/modules/editor/editor.controller.php index 0e9925548..eb61ad157 100644 --- a/modules/editor/editor.controller.php +++ b/modules/editor/editor.controller.php @@ -47,18 +47,23 @@ class editorController extends editor { $component = Context::get('component'); $method = Context::get('method'); - if(!$component) return $this->setError('msg_component_is_not_founded', $component); + if(!$component) + { + throw new Rhymix\Framework\Exception('msg_component_is_not_founded', $component); + } $oEditorModel = getModel('editor'); $oComponent = &$oEditorModel->getComponentObject($component); if(!$oComponent->toBool()) return $oComponent; - if(!method_exists($oComponent, $method)) return $this->setError('msg_component_is_not_founded', $component); + if(!method_exists($oComponent, $method)) + { + throw new Rhymix\Framework\Exception('msg_component_is_not_founded', $component); + } //$output = call_user_method($method, $oComponent); //$output = call_user_func(array($oComponent, $method)); - if(method_exists($oComponent, $method)) $output = $oComponent->{$method}(); - else return $this->setError('%s method is not exists', $method); + $output = $oComponent->{$method}(); if($output instanceof BaseObject && !$output->toBool()) return $output; @@ -93,13 +98,13 @@ class editorController extends editor $module_info = $oModuleModel->getModuleInfoByModuleSrl($srl); if (!$module_info->module_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $module_grant = $oModuleModel->getGrant($module_info, $logged_info); if (!$module_grant->manager) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $module_srl[] = $srl; @@ -413,19 +418,12 @@ class editorController extends editor * @brief Caching a list of editor component (editorModel::getComponentList) * For the editor component list, use a caching file because of DB query and Xml parsing */ - function makeCache($filter_enabled = true, $site_srl) + function makeCache($filter_enabled = true) { $oEditorModel = getModel('editor'); $args = new stdClass; - if($filter_enabled) $args->enabled = "Y"; - - if($site_srl) - { - $args->site_srl = $site_srl; - $output = executeQuery('editor.getSiteComponentList', $args); - } - else $output = executeQuery('editor.getComponentList', $args); + $output = executeQuery('editor.getComponentList', $args); $db_list = $output->data; // Get a list of editor component folders @@ -434,18 +432,6 @@ class editorController extends editor return is_dir(RX_BASEDIR . 'modules/editor/components/' . $component_name); }); - // Get information about log-in status and its group - $is_logged = Context::get('is_logged'); - if($is_logged) - { - $logged_info = Context::get('logged_info'); - if($logged_info->group_list && is_array($logged_info->group_list)) - { - $group_list = array_keys($logged_info->group_list); - } - else $group_list = array(); - } - // Get xml information for looping DB list if(!is_array($db_list)) $db_list = array($db_list); $component_list = new stdClass(); @@ -474,28 +460,7 @@ class editorController extends editor { $xml_info->mid_list = $extra_vars->mid_list; } - /* - // Permisshin check if you are granted - if($extra_vars->target_group) { - // Stop using if not logged-in - if(!$is_logged) continue; - // Compare a target group with the current logged-in user group - $target_group = $extra_vars->target_group; - unset($extra_vars->target_group); - - $is_granted = false; - foreach($group_list as $group_srl) { - if(in_array($group_srl, $target_group)) { - $is_granted = true; - break; - } - } - if(!$is_granted) continue; - } - // Check if the target module exists - if($extra_vars->mid_list && count($extra_vars->mid_list) && Context::get('mid')) { - if(!in_array(Context::get('mid'), $extra_vars->mid_list)) continue; - }*/ + // Check the configuration of the editor component if($xml_info->extra_vars) { @@ -507,6 +472,7 @@ class editorController extends editor } $component_list->{$component_name} = $xml_info; + // Get buttons, icons, images $icon_file = RX_BASEDIR . 'modules/editor/components/'.$component_name.'/icon.gif'; $component_icon_file = RX_BASEDIR . 'modules/editor/components/'.$component_name.'/component_icon.gif'; @@ -514,47 +480,41 @@ class editorController extends editor if(file_exists($component_icon_file)) $component_list->{$component_name}->component_icon = true; } - // Return if it checks enabled only - if($filter_enabled) - { - $cache_file = $oEditorModel->getCacheFile($filter_enabled, $site_srl); - $buff = sprintf('', str_replace('"','\\"',serialize($component_list))); - FileHandler::writeFile($cache_file, $buff); - return $component_list; - } - // Get xml_info of downloaded list - foreach($downloaded_list as $component_name) + if(!$filter_enabled) { - if(in_array($component_name, array('colorpicker_text','colorpicker_bg'))) continue; - // Pass if configured - if($component_list->{$component_name}) continue; - // Insert data into the DB - $oEditorController = getAdminController('editor'); - $oEditorController->insertComponent($component_name, false, $site_srl); - // Add to component_list - unset($xml_info); - $xml_info = $oEditorModel->getComponentXmlInfo($component_name); - $xml_info->enabled = 'N'; - - $component_list->{$component_name} = $xml_info; + foreach($downloaded_list as $component_name) + { + if(in_array($component_name, array('colorpicker_text','colorpicker_bg'))) continue; + if(!is_dir(\RX_BASEDIR.'modules/editor/components/'.$component_name)) continue; + // Pass if configured + if($component_list->{$component_name}) continue; + // Insert data into the DB + $oEditorController = getAdminController('editor'); + $oEditorController->insertComponent($component_name, false, 0); + // Add to component_list + $xml_info = $oEditorModel->getComponentXmlInfo($component_name); + $xml_info->enabled = 'N'; + $component_list->{$component_name} = $xml_info; + } + Rhymix\Framework\Cache::set('editor:components:enabled', $component_list, 0, true); } - - $cache_file = $oEditorModel->getCacheFile($filter_enabled, $site_srl); - $buff = sprintf('', str_replace('"','\\"',serialize($component_list))); - FileHandler::writeFile($cache_file, $buff); - + else + { + Rhymix\Framework\Cache::set('editor:components:all', $component_list, 0, true); + } + return $component_list; } /** * @brief Delete cache files */ - function removeCache($site_srl = 0) + function removeCache() { - $oEditorModel = getModel('editor'); - FileHandler::removeFile($oEditorModel->getCacheFile(true, $site_srl)); - FileHandler::removeFile($oEditorModel->getCacheFile(false, $site_srl)); + Rhymix\Framework\Storage::deleteDirectory(\RX_BASEDIR . 'files/cache/editor/cache'); + Rhymix\Framework\Cache::delete('editor:components:enabled'); + Rhymix\Framework\Cache::delete('editor:components:all'); } function triggerCopyModule(&$obj) diff --git a/modules/editor/editor.model.php b/modules/editor/editor.model.php index bf9082de9..b788a2309 100644 --- a/modules/editor/editor.model.php +++ b/modules/editor/editor.model.php @@ -134,6 +134,10 @@ class editorModel extends editor { $option->editor_height = $option->height ?: $this->default_editor_config['editor_height']; } + if ($option->editor_skin === 'ckeditor' && preg_match('/^(?:white|black)(_text_(?:use|no)html)?$/', $option->sel_editor_colorset)) + { + $option->sel_editor_colorset = 'moono-lisa'; + } Context::set('skin', $option->editor_skin); Context::set('editor_path', $this->module_path . 'skins/' . $option->editor_skin . '/'); Context::set('content_style', $option->content_style); @@ -174,12 +178,11 @@ class editorModel extends editor Context::set('editor_focus', toBool($option->editor_focus)); // Load editor components. - $site_srl = Context::get('site_module_info')->site_srl ?: 0; if($option->enable_component) { if(!Context::get('component_list')) { - $component_list = $this->getComponentList(true, $site_srl); + $component_list = $this->getComponentList(true); Context::set('component_list', $component_list); } } @@ -492,11 +495,11 @@ class editorModel extends editor // Create an object of the component and execute $class_path = sprintf('%scomponents/%s/', $this->module_path, $component); $class_file = sprintf('%s%s.class.php', $class_path, $component); - if(!file_exists($class_file)) return $this->setError('msg_component_is_not_founded', $component); + if(!file_exists($class_file)) return new BaseObject(-1, 'msg_component_is_not_founded', $component); // Create an object after loading the class file require_once($class_file); $oComponent = new $component($editor_sequence, $class_path); - if(!$oComponent) return $this->setError('msg_component_is_not_founded', $component); + if(!$oComponent) return new BaseObject(-1, 'msg_component_is_not_founded', $component); // Add configuration information $component_info = $this->getComponent($component, $site_srl); $oComponent->setInfo($component_info); @@ -514,35 +517,19 @@ class editorModel extends editor return FileHandler::readDir('./modules/editor/skins'); } - /** - * @brief Return the cache file name of editor component list - */ - function getCacheFile($filter_enabled= true, $site_srl = 0) - { - $lang = Context::getLangType(); - $cache_path = _XE_PATH_.'files/cache/editor/cache/'; - FileHandler::makeDir($cache_path); - $cache_file = $cache_path.'component_list.' . $lang .'.'; - if($filter_enabled) $cache_file .= 'filter.'; - if($site_srl) $cache_file .= $site_srl.'.'; - $cache_file .= 'php'; - return $cache_file; - } - /** * @brief Return a component list (DB Information included) */ - function getComponentList($filter_enabled = true, $site_srl=0, $from_db=false) + function getComponentList($filter_enabled = true, $site_srl = 0, $from_db = false) { - $cache_file = $this->getCacheFile(false, $site_srl); - if($from_db || !file_exists($cache_file)) + $cache_key = 'editor:components:' . ($filter_enabled ? 'enabled' : 'all'); + $component_list = $from_db ? null : Rhymix\Framework\Cache::get($cache_key); + if (!$component_list) { $oEditorController = getController('editor'); - $oEditorController->makeCache(false, $site_srl); + $component_list = $oEditorController->makeCache(false); } - if(!file_exists($cache_file)) return; - include($cache_file); $logged_info = Context::get('logged_info'); if($logged_info && is_array($logged_info->group_list)) { @@ -558,10 +545,9 @@ class editorModel extends editor foreach($component_list as $key => $val) { if(!trim($key)) continue; - if(!is_dir(_XE_PATH_.'modules/editor/components/'.$key)) + if(!is_dir(\RX_BASEDIR.'modules/editor/components/'.$key)) { - FileHandler::removeFile($cache_file); - return $this->getComponentList($filter_enabled, $site_srl); + return $this->getComponentList($filter_enabled, 0, true); } if(!$filter_enabled) continue; if($val->enabled == "N") @@ -569,7 +555,7 @@ class editorModel extends editor unset($component_list->{$key}); continue; } - if($logged_info->is_admin == "Y" || $logged_info->is_site_admin == "Y") continue; + if($logged_info->is_admin == "Y") continue; if($val->target_group) { if(!Context::get('is_logged')) @@ -604,20 +590,11 @@ class editorModel extends editor /** * @brief Get xml and db information of the component */ - function getComponent($component_name, $site_srl = 0) + function getComponent($component_name) { $args = new stdClass(); $args->component_name = $component_name; - - if($site_srl) - { - $args->site_srl = $site_srl; - $output = executeQuery('editor.getSiteComponent', $args); - } - else - { - $output = executeQuery('editor.getComponent', $args); - } + $output = executeQuery('editor.getComponent', $args); $component = $output->data; if(!$output->data) return false; diff --git a/modules/editor/editor.view.php b/modules/editor/editor.view.php index 4cdd7b79a..a13b84b6e 100644 --- a/modules/editor/editor.view.php +++ b/modules/editor/editor.view.php @@ -97,9 +97,9 @@ class editorView extends editor $oEditorModel = getModel('editor'); $component = $oEditorModel->getComponent($component_name, $site_srl); - if(!$component->component_name) { - $this->stop('msg_invalid_request'); - return; + if(!$component->component_name) + { + throw new Rhymix\Framework\Exceptions\InvalidRequest; } Context::set('component', $component); @@ -192,7 +192,7 @@ class editorView extends editor { Context::set('editor', getModel('editor')->getModuleEditor(Context::get('type'), 0, 0, 'dummy_key', 'dummy_content')); - $this->setLayoutFile('popup_layout'); + $this->setLayoutFile('default_layout'); $this->setTemplatePath($this->module_path.'tpl'); $this->setTemplateFile('config_preview'); } diff --git a/modules/editor/lang/zh-CN.php b/modules/editor/lang/zh-CN.php index 495259d40..91f5af9ba 100644 --- a/modules/editor/lang/zh-CN.php +++ b/modules/editor/lang/zh-CN.php @@ -182,4 +182,5 @@ $lang->edit['close_help'] = '关闭帮助'; $lang->edit['confirm_submit_without_saving'] = '尚有未保存的段落。\\n确定要提交吗?'; $lang->edit['image_align'] = '图片对齐'; $lang->edit['attached_files'] = '附件'; +$lang->edit['delete_selected'] = '删除附件'; $lang->about_dblclick_in_editor = '双击背景, 文本, 图片, 引用即可对其相关组件进行详细设置。'; diff --git a/modules/editor/skins/ckeditor/editor.html b/modules/editor/skins/ckeditor/editor.html index c41290d99..8ec1f0878 100644 --- a/modules/editor/skins/ckeditor/editor.html +++ b/modules/editor/skins/ckeditor/editor.html @@ -30,8 +30,8 @@ var auto_saved_msg = "{$lang->msg_auto_saved}"; - - + + diff --git a/modules/editor/styles/ckeditor_light/style.css b/modules/editor/styles/ckeditor_light/style.css old mode 100755 new mode 100644 index 58b9ece6b..d12a4890d --- a/modules/editor/styles/ckeditor_light/style.css +++ b/modules/editor/styles/ckeditor_light/style.css @@ -1,5 +1,7 @@ @charset "utf-8"; /* NAVER (developers@xpressengine.com) */ +html { height: 100%; } +body { min-height: 100%; } .xe_content blockquote.q1, .xe_content blockquote.q2, .xe_content blockquote.q3, diff --git a/modules/editor/tpl/admin_index.html b/modules/editor/tpl/admin_index.html index 8607fcc1c..41b54406a 100644 --- a/modules/editor/tpl/admin_index.html +++ b/modules/editor/tpl/admin_index.html @@ -1,7 +1,7 @@
    -

    {$lang->editor} {$lang->help}

    +

    {$lang->editor}

    {$XE_VALIDATOR_MESSAGE}

    @@ -272,17 +272,23 @@ - - +
    {$lang->total_count}({$component_count})
    + - - + + - + @@ -290,20 +296,20 @@ - - + - - - + + @@ -34,8 +34,8 @@ {$author->name} - - + + - - + + diff --git a/modules/layout/tpl/layout_all_instance_list.html b/modules/layout/tpl/layout_all_instance_list.html index bcc8394e3..da1a1b10c 100644 --- a/modules/layout/tpl/layout_all_instance_list.html +++ b/modules/layout/tpl/layout_all_instance_list.html @@ -4,17 +4,22 @@ xe.lang.confirm_delete = '{$lang->confirm_delete}'; -
    + {$lang->total_count}({$component_count}) + +
    {$lang->cmd_move} {$lang->component_name} {$lang->version}{$lang->author}{$lang->path}{$lang->author}{$lang->path} {$lang->use}{$lang->cmd_delete}{$lang->cmd_delete}
    -

    {$xml_info->title}

    +

    {nl2br($xml_info->description)}

    {$lang->msg_avail_easy_update}{$lang->msg_do_you_like_update}

    {$xml_info->version} + {$author->name} {$xml_info->path}{$xml_info->path} enabled=='Y')--> checked="checked" /> + {$lang->cmd_delete} diff --git a/modules/editor/tpl/config_preview.html b/modules/editor/tpl/config_preview.html index 2fbcfd03c..b5588ae6a 100644 --- a/modules/editor/tpl/config_preview.html +++ b/modules/editor/tpl/config_preview.html @@ -1,5 +1,5 @@
    -

    {$editor}

    +

    {$editor|noescape}

    diff --git a/modules/editor/tpl/editor_frame.html b/modules/editor/tpl/editor_frame.html index 3c96e7ca2..4575263e5 100644 --- a/modules/editor/tpl/editor_frame.html +++ b/modules/editor/tpl/editor_frame.html @@ -14,5 +14,5 @@
    - {$editor} + {$editor|noescape}
    diff --git a/modules/editor/tpl/popup.html b/modules/editor/tpl/popup.html index e1e981475..aa8c8f175 100644 --- a/modules/editor/tpl/popup.html +++ b/modules/editor/tpl/popup.html @@ -1,3 +1,3 @@
    -{$popup_content} +{$popup_content|noescape}
    diff --git a/modules/editor/tpl/preview.html b/modules/editor/tpl/preview.html index 151b89f55..2d996e430 100644 --- a/modules/editor/tpl/preview.html +++ b/modules/editor/tpl/preview.html @@ -1,4 +1,4 @@ -{$content} +{$content|noescape} diff --git a/modules/editor/tpl/setup_component.html b/modules/editor/tpl/setup_component.html index 2e293f37a..b8d8d0e08 100644 --- a/modules/editor/tpl/setup_component.html +++ b/modules/editor/tpl/setup_component.html @@ -43,8 +43,8 @@
    - - + + diff --git a/modules/editor/tpl/view_component.html b/modules/editor/tpl/view_component.html index 6d0dae34b..91f60518a 100644 --- a/modules/editor/tpl/view_component.html +++ b/modules/editor/tpl/view_component.html @@ -1,7 +1,9 @@ {@Context::addMetaTag('viewport', 'width=device-width', FALSE);} -
    +

    {$component->title}

    +
    +

    {$lang->component_author}

      @@ -33,4 +35,4 @@

      {$lang->component_description}

      {nl2br(trim($component->description))}

    -
    +
    \ No newline at end of file diff --git a/modules/file/file.admin.controller.php b/modules/file/file.admin.controller.php index 10f51c7df..46ba168a4 100644 --- a/modules/file/file.admin.controller.php +++ b/modules/file/file.admin.controller.php @@ -32,11 +32,11 @@ class fileAdminController extends file { // An error appears if no document is selected $cart = Context::get('cart'); - if(!$cart) return $this->stop('msg_file_cart_is_null'); + if(!$cart) throw new Rhymix\Framework\Exception('msg_file_cart_is_null'); if(!is_array($cart)) $file_srl_list= explode('|@|', $cart); else $file_srl_list = $cart; $file_count = count($file_srl_list); - if(!$file_count) return $this->stop('msg_file_cart_is_null'); + if(!$file_count) throw new Rhymix\Framework\Exception('msg_file_cart_is_null'); $oFileController = getController('file'); // Delete the post @@ -76,7 +76,7 @@ class fileAdminController extends file { if ($config->allowed_filesize > 2047 || $config->allowed_attach_size > 2047) { - return $this->setError('msg_32bit_max_2047mb'); + throw new Rhymix\Framework\Exception('msg_32bit_max_2047mb'); } } @@ -125,7 +125,7 @@ class fileAdminController extends file { if ($file_config->allowed_filesize > 2047 || $file_config->allowed_attach_size > 2047) { - return $this->setError('msg_32bit_max_2047mb'); + throw new Rhymix\Framework\Exception('msg_32bit_max_2047mb'); } } diff --git a/modules/file/file.controller.php b/modules/file/file.controller.php index 227b18499..0ede76230 100644 --- a/modules/file/file.controller.php +++ b/modules/file/file.controller.php @@ -26,7 +26,7 @@ class fileController extends file function procFileUpload() { Context::setRequestMethod('JSON'); - $file_info = $_FILES['Filedata']; + $file_info = Context::get('Filedata'); // An error appears if not a normally uploaded file if(!$file_info || !is_uploaded_file($file_info['tmp_name'])) exit(); @@ -39,7 +39,7 @@ class fileController extends file // Exit a session if there is neither upload permission nor information if(!$_SESSION['upload_info'][$editor_sequence]->enabled) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } // Get upload_target_srl @@ -63,26 +63,25 @@ class fileController extends file $total_size = intval($matches[3]); if ($chunk_start < 0 || $chunk_size < 0 || $total_size < 0 || $chunk_start + $chunk_size > $total_size || $chunk_size != $file_info['size']) { - return $this->setError('msg_upload_invalid_chunk'); + throw new Rhymix\Framework\Exception('msg_upload_invalid_chunk'); } $this->add('chunk_current_size', $chunk_size); $this->add('chunk_uploaded_size', $chunk_start); // Check existing chunks - $nonce = Context::get('nonce'); - $temp_key = hash_hmac('sha1', sprintf('%d:%d:%d:%s:%s', $editor_sequence, $upload_target_srl, $module_srl, $file_info['name'], $nonce), config('crypto.authentication_key')); + $temp_key = hash_hmac('sha1', sprintf('%d:%d:%d:%s:%s', $editor_sequence, $upload_target_srl, $module_srl, $file_info['name'], session_id()), config('crypto.authentication_key')); $temp_filename = RX_BASEDIR . 'files/attach/chunks/' . $temp_key; if ($chunk_start == 0 && Rhymix\Framework\Storage::isFile($temp_filename)) { Rhymix\Framework\Storage::delete($temp_filename); $this->add('chunk_status', 11); - return $this->setError('msg_upload_invalid_chunk'); + throw new Rhymix\Framework\Exception('msg_upload_invalid_chunk'); } if ($chunk_start != 0 && (!Rhymix\Framework\Storage::isFile($temp_filename) || Rhymix\Framework\Storage::getSize($temp_filename) != $chunk_start)) { Rhymix\Framework\Storage::delete($temp_filename); $this->add('chunk_status', 12); - return $this->setError('msg_upload_invalid_chunk'); + throw new Rhymix\Framework\Exception('msg_upload_invalid_chunk'); } // Check size limit @@ -95,13 +94,13 @@ class fileController extends file if ($total_size > $allowed_filesize) { $this->add('chunk_status', 21); - return $this->setError('msg_exceeds_limit_size'); + throw new Rhymix\Framework\Exception('msg_exceeds_limit_size'); } $output = executeQuery('file.getAttachedFileSize', (object)array('upload_target_srl' => $upload_target_srl)); if (intval($output->data->attached_size) + $total_size > $allowed_attach_size) { $this->add('chunk_status', 22); - return $this->setError('msg_exceeds_limit_size'); + throw new Rhymix\Framework\Exception('msg_exceeds_limit_size'); } } @@ -126,7 +125,7 @@ class fileController extends file { Rhymix\Framework\Storage::delete($temp_filename); $this->add('chunk_status', 40); - return $this->setError('msg_upload_invalid_chunk'); + throw new Rhymix\Framework\Exception('msg_upload_invalid_chunk'); } } else @@ -136,16 +135,26 @@ class fileController extends file // Save the file $output = $this->insertFile($file_info, $module_srl, $upload_target_srl); + if($output->error != '0') + { + throw new Rhymix\Framework\Exception($output->message); + } + // Create the response Context::setResponseMethod('JSON'); $this->add('file_srl', $output->get('file_srl')); $this->add('file_size', $output->get('file_size')); $this->add('direct_download', $output->get('direct_download')); $this->add('source_filename', $output->get('source_filename')); $this->add('upload_target_srl', $output->get('upload_target_srl')); - $this->add('download_url', $oFileModel->getDirectFileUrl($output->get('uploaded_filename'))); - - if($output->error != '0') $this->stop($output->message); + if ($output->get('direct_download') === 'Y') + { + $this->add('download_url', $oFileModel->getDirectFileUrl($output->get('uploaded_filename'))); + } + else + { + $this->add('download_url', $oFileModel->getDownloadUrl($output->get('file_srl'), $output->get('sid'), $module_srl)); + } } /** @@ -207,14 +216,14 @@ class fileController extends file if(!$file_srl || !$width) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $oFileModel = getModel('file'); $fileInfo = $oFileModel->getFile($file_srl); if(!$fileInfo || $fileInfo->direct_download != 'Y') { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $source_src = $fileInfo->uploaded_filename; @@ -230,7 +239,7 @@ class fileController extends file } else { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $this->add('resized_info',$output); @@ -271,7 +280,10 @@ class fileController extends file { $oFileModel = getModel('file'); - if(isset($this->grant->access) && $this->grant->access !== true) return $this->setError('msg_not_permitted'); + if(isset($this->grant->access) && $this->grant->access !== true) + { + throw new Rhymix\Framework\Exceptions\NotPermitted; + } $file_srl = Context::get('file_srl'); $sid = Context::get('sid'); @@ -280,9 +292,15 @@ class fileController extends file $columnList = array('file_srl', 'sid', 'isvalid', 'source_filename', 'module_srl', 'uploaded_filename', 'file_size', 'member_srl', 'upload_target_srl', 'upload_target_type'); $file_obj = $oFileModel->getFile($file_srl, $columnList); // If the requested file information is incorrect, an error that file cannot be found appears - if($file_obj->file_srl!=$file_srl || $file_obj->sid!=$sid) return $this->stop('msg_file_not_found'); + if($file_obj->file_srl != $file_srl || $file_obj->sid !== $sid) + { + throw new Rhymix\Framework\Exceptions\TargetNotFound('msg_file_not_found'); + } // Notify that file download is not allowed when standing-by(Only a top-administrator is permitted) - if($logged_info->is_admin != 'Y' && $file_obj->isvalid!='Y') return $this->stop('msg_not_permitted_download'); + if($logged_info->is_admin != 'Y' && $file_obj->isvalid != 'Y') + { + throw new Rhymix\Framework\Exceptions\NotPermitted('msg_not_permitted_download'); + } // File name $filename = $file_obj->source_filename; $file_module_config = $oFileModel->getFileModuleConfig($file_obj->module_srl); @@ -331,7 +349,10 @@ class fileController extends file } else $file_module_config->allow_outlink = 'Y'; } - if($file_module_config->allow_outlink != 'Y') return $this->stop('msg_not_allowed_outlink'); + if($file_module_config->allow_outlink != 'Y') + { + throw new Rhymix\Framework\Exceptions\NotPermitted('msg_not_allowed_outlink'); + } } // Check if a permission for file download is granted @@ -344,7 +365,11 @@ class fileController extends file if(is_array($file_module_config->download_grant) && $downloadGrantCount>0) { - if(!Context::get('is_logged')) return $this->stop('msg_not_permitted_download'); + if(!Context::get('is_logged')) + { + throw new Rhymix\Framework\Exceptions\NotPermitted('msg_not_permitted_download'); + } + $logged_info = Context::get('logged_info'); if($logged_info->is_admin != 'Y') { @@ -367,14 +392,27 @@ class fileController extends file break; } } - if(!$is_permitted) return $this->stop('msg_not_permitted_download'); + if(!$is_permitted) + { + throw new Rhymix\Framework\Exceptions\NotPermitted('msg_not_permitted_download'); + } } } } // Call a trigger (before) $output = ModuleHandler::triggerCall('file.downloadFile', 'before', $file_obj); - if(!$output->toBool()) return $this->stop(($output->message)?$output->message:'msg_not_permitted_download'); + if(!$output->toBool()) + { + if ($output->message) + { + throw new Rhymix\Framework\Exception($output->message); + } + else + { + throw new Rhymix\Framework\Exceptions\NotPermitted('msg_not_permitted_download'); + } + } // Increase download_count $args = new stdClass(); @@ -413,20 +451,20 @@ class fileController extends file // Check file key if(strlen($file_key) != 32 || !isset($_SESSION['__XE_FILE_KEY__']) || !is_string($_SESSION['__XE_FILE_KEY__'])) { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $file_key_data = $file_srl . $file_obj->file_size . $file_obj->uploaded_filename . $_SERVER['REMOTE_ADDR']; $file_key_compare = substr(hash_hmac('sha256', $file_key_data, $_SESSION['__XE_FILE_KEY__']), 0, 32); if($file_key !== $file_key_compare) { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Check if file exists $uploaded_filename = $file_obj->uploaded_filename; if(!file_exists($uploaded_filename)) { - return $this->stop('msg_file_not_found'); + throw new Rhymix\Framework\Exceptions\TargetNotFound('msg_file_not_found'); } // If client sent an If-None-Match header with the correct ETag, do not download again @@ -453,7 +491,7 @@ class fileController extends file $fp = fopen($uploaded_filename, 'rb'); if(!$fp) { - return $this->stop('msg_file_not_found'); + throw new Rhymix\Framework\Exceptions\TargetNotFound('msg_file_not_found'); } // Take care of pause and resume @@ -586,11 +624,15 @@ class fileController extends file */ function procFileGetList() { - if(!Context::get('is_logged')) return $this->setError('msg_not_permitted'); + if(!Context::get('is_logged')) + { + throw new Rhymix\Framework\Exceptions\NotPermitted; + } + $logged_info = Context::get('logged_info'); if($logged_info->is_admin !== 'Y' && !getModel('module')->isSiteAdmin($logged_info)) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $fileSrls = Context::get('file_srls'); @@ -835,35 +877,37 @@ class fileController extends file if(!in_array($uploaded_ext, $ext)) { - return $this->stop('msg_not_allowed_filetype'); + throw new Rhymix\Framework\Exception('msg_not_allowed_filetype'); } } $allowed_filesize = $config->allowed_filesize * 1024 * 1024; $allowed_attach_size = $config->allowed_attach_size * 1024 * 1024; // An error appears if file size exceeds a limit - if($allowed_filesize < filesize($file_info['tmp_name'])) return $this->setError('msg_exceeds_limit_size'); + if($allowed_filesize < filesize($file_info['tmp_name'])) throw new Rhymix\Framework\Exception('msg_exceeds_limit_size'); // Get total file size of all attachements (from DB) $size_args = new stdClass; $size_args->upload_target_srl = $upload_target_srl; $output = executeQuery('file.getAttachedFileSize', $size_args); $attached_size = (int)$output->data->attached_size + filesize($file_info['tmp_name']); - if($attached_size > $allowed_attach_size) return $this->setError('msg_exceeds_limit_size'); + if($attached_size > $allowed_attach_size) throw new Rhymix\Framework\Exception('msg_exceeds_limit_size'); } } // Sanitize filename $file_info['name'] = Rhymix\Framework\Filters\FilenameFilter::clean($file_info['name']); + + // Get file_srl + $file_srl = getNextSequence(); + $file_regdate = date('YmdHis'); // Set upload path by checking if the attachement is an image or other kinds of file if(Rhymix\Framework\Filters\FilenameFilter::isDirectDownload($file_info['name'])) { - $path = RX_BASEDIR . sprintf("files/attach/images/%s/%s", $module_srl,getNumberingPath($upload_target_srl,3)); + $path = $this->getStoragePath('images', $file_srl, $module_srl, $upload_target_srl, $file_regdate); - // special character to '_' // change to random file name. because window php bug. window php is not recognize unicode character file name - by cherryfilter $ext = substr(strrchr($file_info['name'],'.'),1); - //$_filename = preg_replace('/[#$&*?+%"\']/', '_', $file_info['name']); $filename = $path . Rhymix\Framework\Security::getRandom(32, 'hex') . '.' . $ext; while(file_exists($filename)) { @@ -873,7 +917,7 @@ class fileController extends file } else { - $path = RX_BASEDIR . sprintf("files/attach/binaries/%s/%s", $module_srl, getNumberingPath($upload_target_srl,3)); + $path = $this->getStoragePath('binaries', $file_srl, $module_srl, $upload_target_srl, $file_regdate); $filename = $path . Rhymix\Framework\Security::getRandom(32, 'hex'); while(file_exists($filename)) { @@ -885,7 +929,7 @@ class fileController extends file // Create a directory if(!Rhymix\Framework\Storage::isDirectory($path) && !Rhymix\Framework\Storage::createDirectory($path)) { - return $this->setError('msg_not_permitted_create'); + throw new Rhymix\Framework\Exception('msg_not_permitted_create'); } // Move the file @@ -897,7 +941,7 @@ class fileController extends file @copy($file_info['tmp_name'], $filename); if(!file_exists($filename)) { - return $this->setError('msg_file_upload_error'); + throw new Rhymix\Framework\Exception('msg_file_upload_error'); } } } @@ -907,7 +951,7 @@ class fileController extends file { if (!Rhymix\Framework\Storage::move($file_info['tmp_name'], $filename)) { - return $this->setError('msg_file_upload_error'); + throw new Rhymix\Framework\Exception('msg_file_upload_error'); } } } @@ -917,7 +961,7 @@ class fileController extends file { if(!@move_uploaded_file($file_info['tmp_name'], $filename)) { - return $this->setError('msg_file_upload_error'); + throw new Rhymix\Framework\Exception('msg_file_upload_error'); } } } @@ -927,7 +971,7 @@ class fileController extends file $member_srl = $oMemberModel->getLoggedMemberSrl(); // List file information $args = new stdClass; - $args->file_srl = getNextSequence(); + $args->file_srl = $file_srl; $args->upload_target_srl = $upload_target_srl; $args->module_srl = $module_srl; $args->direct_download = $direct_download; @@ -937,6 +981,7 @@ class fileController extends file $args->file_size = @filesize($filename); $args->comment = NULL; $args->member_srl = $member_srl; + $args->regdate = $file_regdate; $args->sid = Rhymix\Framework\Security::getRandom(32, 'hex'); $output = executeQuery('file.insertFile', $args); @@ -1102,16 +1147,19 @@ class fileController extends file // Determine the file path by checking if the file is an image or other kinds if (Rhymix\Framework\Filters\FilenameFilter::isDirectDownload($file_info->source_filename)) { - $path = sprintf("./files/attach/images/%s/%s", $target_module_srl, getNumberingPath($target_srl, 3)); - $new_file = $path . $file_info->source_filename; + $path = $this->getStoragePath('images', $file_info->file_srl, $target_module_srl, $target_srl, $file_info->regdate); + $ext = substr(strrchr($file_info->source_filename,'.'), 1); + $random_filename = basename($file_info->uploaded_filename) ?: Rhymix\Framework\Security::getRandom(32, 'hex') . '.' . $ext; + $new_file = $path . $random_filename; } else { - $path = sprintf("./files/attach/binaries/%s/%s", $target_module_srl, getNumberingPath($target_srl, 3)); - $new_file = $path . Rhymix\Framework\Security::getRandom(32, 'hex'); + $path = $this->getStoragePath('binaries', $file_info->file_srl, $target_module_srl, $target_srl, $file_info->regdate); + $random_filename = basename($file_info->uploaded_filename) ?: Rhymix\Framework\Security::getRandom(32, 'hex'); + $new_file = $path . $random_filename; } // Pass if a target document to move is same - if($old_file == $new_file) continue; + if($old_file === $new_file) continue; // Create a directory FileHandler::makeDir($path); // Move the file @@ -1173,16 +1221,16 @@ class fileController extends file $vars = Context::getRequestVars(); $logged_info = Context::get('logged_info'); - if(!$vars->editor_sequence) return $this->setError('msg_invalid_request'); + if(!$vars->editor_sequence) throw new Rhymix\Framework\Exceptions\InvalidRequest; $upload_target_srl = $_SESSION['upload_info'][$vars->editor_sequence]->upload_target_srl; $oFileModel = getModel('file'); $file_info = $oFileModel->getFile($vars->file_srl); - if(!$file_info) return $this->setError('msg_not_founded'); + if(!$file_info) throw new Rhymix\Framework\Exceptions\TargetNotFound; - if(!$this->manager && !$file_info->member_srl === $logged_info->member_srl) return $this->setError('msg_not_permitted'); + if(!$this->manager && !$file_info->member_srl === $logged_info->member_srl) throw new Rhymix\Framework\Exceptions\NotPermitted; $args = new stdClass(); $args->file_srl = $vars->file_srl; @@ -1220,6 +1268,45 @@ class fileController extends file $thumbnail_path = sprintf('files/thumbnails/%s', getNumberingPath($upload_target_srl, 3)); Filehandler::removeFilesInDir($thumbnail_path); } + + /** + * Determine storage path based on file.folder_structure configuration. + * + * @param string $file_type images or binary + * @param int $file_srl + * @param int $module_srl + * @param int $upload_target_srl + * @param string $regdate + * @param bool $absolute_path + * @return string + */ + public function getStoragePath($file_type, $file_srl, $module_srl = 0, $upload_target_srl = 0, $regdate = '', $absolute_path = true) + { + // 변수 확인 및 넘어오지 않은 변수 기본값 지정 + $file_srl = intval($file_srl); + $module_srl = intval($module_srl); + $upload_target_srl = $upload_target_srl ?: $file_srl; + $regdate = $regdate ?: date('YmdHis'); + + // 시스템 설정 참고 (기존 사용자는 1, 신규 설치시 2가 기본값임) + $folder_structure = config('file.folder_structure'); + + // 기본 경로 지정 + $prefix = $absolute_path ? \RX_BASEDIR : './'; + + // 2: 년월일 단위로 정리 + if ($folder_structure == 2) + { + return sprintf('%sfiles/attach/%s/%04d/%02d/%02d/', $prefix, $file_type, substr($regdate, 0, 4), substr($regdate, 4, 2), substr($regdate, 6, 2)); + } + + // 1 or 0: module_srl 및 업로드 대상 번호에 따라 3자리씩 끊어서 정리 + else + { + $components = $upload_target_srl ? getNumberingPath($upload_target_srl, 3) : ''; + return sprintf('%sfiles/attach/%s/%d/%s', $prefix, $file_type, $module_srl, $components); + } + } /** * Find the attachment where a key is upload_target_srl and then return java script code diff --git a/modules/file/file.model.php b/modules/file/file.model.php index ef667d052..f3b48d35f 100644 --- a/modules/file/file.model.php +++ b/modules/file/file.model.php @@ -45,7 +45,7 @@ class fileModel extends file $oComment = $oCommentModel->getComment($upload_target_srl); if($oComment->isExists() && !$oComment->isAccessible()) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $oDocument = $oDocumentModel->getDocument($oComment->get('document_srl')); @@ -54,7 +54,7 @@ class fileModel extends file // document 권한 확인 if($oDocument->isExists() && !$oDocument->isAccessible()) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } // 모듈 권한 확인 @@ -63,7 +63,7 @@ class fileModel extends file $grant = $oModuleModel->getGrant($oModuleModel->getModuleInfoByModuleSrl($oDocument->get('module_srl')), $logged_info); if(!$grant->access) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } } @@ -210,23 +210,6 @@ class fileModel extends file if(!$config->download_grant) $config->download_grant = array(); if(!$config->inline_download_format) $config->inline_download_format = array(); - /* - $size = ini_get('upload_max_filesize'); - $unit = strtolower($size[strlen($size) - 1]); - $size = (float)$size; - if($unit == 'g') $size *= 1024; - if($unit == 'k') $size /= 1024; - - if($config->allowed_filesize > $size) - { - $config->allowed_filesize = $size; - } - if($config->allowed_attach_size > $size) - { - $config->allowed_attach_size = $size; - } - */ - return $config; } @@ -319,13 +302,10 @@ class fileModel extends file if($logged_info->is_admin == 'Y') { - /* - $iniPostMaxSize = FileHandler::returnbytes(ini_get('post_max_size')); - $iniUploadMaxSize = FileHandler::returnbytes(ini_get('upload_max_filesize')); - $size = min($iniPostMaxSize, $iniUploadMaxSize) / 1048576; - $file_config->allowed_attach_size = $size; - $file_config->allowed_filesize = $size; - */ + $oModuleModel = getModel('module'); + $module_config = $oModuleModel->getModuleConfig('file'); + $file_config->allowed_filesize = max($file_config->allowed_filesize, $module_config->allowed_filesize); + $file_config->allowed_attach_size = max($file_config->allowed_attach_size, $module_config->allowed_attach_size); $file_config->allowed_filetypes = '*.*'; } return $file_config; diff --git a/modules/file/lang/en.php b/modules/file/lang/en.php index d1fac6871..16eb7b425 100644 --- a/modules/file/lang/en.php +++ b/modules/file/lang/en.php @@ -26,9 +26,11 @@ $lang->about_inline_download_format = 'Selected types of files will be opened in $lang->enable_download_group = 'Downloadable Groups'; $lang->about_allow_outlink = 'You can block other websites from accessing your download URLs directly.
    This does not apply to images and other files that can be embedded directly in a document.'; $lang->about_allow_outlink_format = 'These file formats will always be allowed.
    Please use a comma (,) to separate items: e.g. doc, zip, pdf'; -$lang->about_allow_outlink_site = 'These referers will alyways be allowed.
    Please enter one full address per line: e.g. https://www.rhymix.org/'; -$lang->about_allowed_filesize = 'You can limit the size of each attached file. Administrators are exempt.'; -$lang->about_allowed_attach_size = 'You can limit the total size of all attached files in one document. Administrators are exempt.'; +$lang->about_allow_outlink_site = 'These referers will always be allowed.
    Please enter one full address per line: e.g. https://www.rhymix.org/'; +$lang->about_allowed_filesize = 'You can limit the size of each attached file.
    Administrators are limited to this setting or the limit set in the file module, whichever is greater.'; +$lang->about_allowed_attach_size = 'You can limit the total size of all attached files in one document.
    Administrators are limited to this setting or the limit set in the file module, whichever is greater.'; +$lang->about_allowed_filesize_global = 'This is the global limit on the size of each attachment.'; +$lang->about_allowed_attach_size_global = 'This is the global limit on the combined size of all attachments in one document.'; $lang->about_allowed_size_limits = 'The file size will be limited to the value set in php.ini (%sB) in IE9 and below and older Android browsers.'; $lang->about_allowed_filetypes = 'To allow an extension, use "*.[extention]". To allow multiple extensions, use ";" between each extension. ex) *.* or *.jpg;*.gif; '; $lang->cmd_delete_checked_file = 'Delete Selected Item(s)'; diff --git a/modules/file/lang/ko.php b/modules/file/lang/ko.php index 85bcfe5ea..e271e80e7 100644 --- a/modules/file/lang/ko.php +++ b/modules/file/lang/ko.php @@ -27,8 +27,10 @@ $lang->enable_download_group = '다운로드 가능 그룹'; $lang->about_allow_outlink = '다른 사이트에서 파일 다운로드 링크에 직접 접근하는 것을 차단합니다.
    다운로드 링크를 사용하지 않고 본문에 바로 삽입할 수 있는 이미지 파일 등에는 적용되지 않습니다.'; $lang->about_allow_outlink_format = '파일 외부 링크 설정에 상관없이 허용하는 파일 확장자입니다.
    여러 개 입력시 쉼표(,)을 이용해서 구분해 주세요. 예) doc, zip, pdf'; $lang->about_allow_outlink_site = '파일 외부 링크 설정에 상관없이 허용하는 사이트 주소입니다.
    여러 개 입력시 줄을 바꿔서 구분해 주세요. 예) https://www.rhymix.org/'; -$lang->about_allowed_filesize = '각 파일의 용량을 제한할 수 있습니다. 관리자에게는 적용되지 않습니다.'; -$lang->about_allowed_attach_size = '하나의 문서에 첨부할 수 있는 최대 용량을 제한할 수 있습니다. 관리자에게는 적용되지 않습니다.'; +$lang->about_allowed_filesize = '각 파일의 용량을 제한할 수 있습니다.
    관리자에게는 이 게시판의 제한과 파일 모듈의 제한 중 높은 쪽이 적용됩니다.'; +$lang->about_allowed_attach_size = '하나의 문서에 첨부할 수 있는 최대 용량을 제한할 수 있습니다.
    관리자에게는 이 게시판의 제한과 파일 모듈의 제한 중 높은 쪽이 적용됩니다.'; +$lang->about_allowed_filesize_global = '관리자를 포함하여 사이트 전체에 적용되는 파일 크기 제한입니다.'; +$lang->about_allowed_attach_size_global = '관리자를 포함하여 사이트 전체에 적용되는 문서당 총 첨부 용량 제한입니다.'; $lang->about_allowed_size_limits = 'IE9 이하, 구버전 안드로이드 등에서는 php.ini에서 지정한 %sB로 제한됩니다.'; $lang->about_allowed_filetypes = '"*.확장자"로 지정할 수 있고 ";" 으로 여러 개 지정이 가능합니다. 예) *.* or *.jpg;*.gif;'; $lang->cmd_delete_checked_file = '선택항목 삭제'; diff --git a/modules/file/tpl/adminConfig.html b/modules/file/tpl/adminConfig.html index fcbe49fcb..57f8047d3 100644 --- a/modules/file/tpl/adminConfig.html +++ b/modules/file/tpl/adminConfig.html @@ -45,14 +45,14 @@
    MB -

    {$lang->about_allowed_filesize}
    {sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}

    +

    {$lang->about_allowed_filesize_global}
    {sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}

    MB -

    {$lang->about_allowed_attach_size}
    {sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}

    +

    {$lang->about_allowed_attach_size_global}
    {sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}

    diff --git a/modules/file/tpl/file_list.html b/modules/file/tpl/file_list.html index 18cc3ffd3..8179355a0 100644 --- a/modules/file/tpl/file_list.html +++ b/modules/file/tpl/file_list.html @@ -17,7 +17,6 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}'; {$lang->is_valid}({number_format($total_count)}) | {$lang->is_stand_by}({number_format($total_count)}) - {$lang->help} {$lang->delete} diff --git a/modules/file/tpl/file_module_config.html b/modules/file/tpl/file_module_config.html index 64fb9e2c8..b3a4e35a2 100644 --- a/modules/file/tpl/file_module_config.html +++ b/modules/file/tpl/file_module_config.html @@ -11,14 +11,14 @@
    MB -

    {$lang->about_allowed_filesize}
    {sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}

    +

    {sprintf($lang->about_allowed_filesize, getUrl('', 'module', 'admin', 'act', 'dispFileAdminConfig'))}
    {sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}

    MB -

    {$lang->about_allowed_attach_size}
    {sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}

    +

    {sprintf($lang->about_allowed_attach_size, getUrl('', 'module', 'admin', 'act', 'dispFileAdminConfig'))}
    {sprintf($lang->about_allowed_size_limits, ini_get('upload_max_filesize'))}

    diff --git a/modules/importer/extract.class.php b/modules/importer/extract.class.php index 0051e3c32..b179bba3d 100644 --- a/modules/importer/extract.class.php +++ b/modules/importer/extract.class.php @@ -124,7 +124,7 @@ class extract // If local file if(strncasecmp('http://', $this->filename, 7) !== 0) { - if(!file_exists($this->filename)) return $this->setError('msg_no_xml_file'); + if(!file_exists($this->filename)) return new BaseObject(-1, 'msg_no_xml_file'); $this->fd = fopen($this->filename,"r"); // If remote file } @@ -135,7 +135,7 @@ class extract if(!$url_info['path']) $url_info['path'] = '/'; $this->fd = @fsockopen($url_info['host'], $url_info['port']); - if(!$this->fd) return $this->setError('msg_no_xml_file'); + if(!$this->fd) return new BaseObject(-1, 'msg_no_xml_file'); // If the file name contains Korean, do urlencode(iconv required) $path = $url_info['path']; if(preg_match('/[\xEA-\xED][\x80-\xFF]{2}/', $path)&&function_exists('iconv')) @@ -157,7 +157,7 @@ class extract $buff .= $str = fgets($this->fd, 1024); if(!trim($str)) break; } - if(preg_match('/404 Not Found/i',$buff)) return $this->setError('msg_no_xml_file'); + if(preg_match('/404 Not Found/i',$buff)) return new BaseObject(-1, 'msg_no_xml_file'); } if($this->startTag) diff --git a/modules/importer/importer.admin.controller.php b/modules/importer/importer.admin.controller.php index 81e813367..112e50406 100644 --- a/modules/importer/importer.admin.controller.php +++ b/modules/importer/importer.admin.controller.php @@ -292,12 +292,12 @@ class importerAdminController extends importer $this->unit_count = Context::get('unit_count'); // Check if an index file exists $index_file = './files/cache/importer/'.$key.'/index'; - if(!file_exists($index_file)) return $this->setError('msg_invalid_xml_file'); + if(!file_exists($index_file)) throw new Rhymix\Framework\Exception('msg_invalid_xml_file'); switch($type) { case 'ttxml' : - if(!$target_module) return $this->setError('msg_invalid_request'); + if(!$target_module) throw new Rhymix\Framework\Exceptions\InvalidRequest; $oModuleModel = getModel('module'); $columnList = array('module_srl', 'module'); @@ -317,7 +317,7 @@ class importerAdminController extends importer break; case 'module' : // Check if the target module exists - if(!$target_module) return $this->setError('msg_invalid_request'); + if(!$target_module) throw new Rhymix\Framework\Exceptions\InvalidRequest; $cur = $this->importModule($key, $cur, $index_file, $target_module); break; } diff --git a/modules/importer/tpl/header.html b/modules/importer/tpl/header.html index 67cc8d4bc..2e9e07e48 100644 --- a/modules/importer/tpl/header.html +++ b/modules/importer/tpl/header.html @@ -1,6 +1,6 @@ {@ $type_list = array('module'=>$lang->type_module, 'ttxml'=>$lang->type_ttxml, 'member'=>$lang->type_member, 'sync'=>$lang->type_syncmember, 'message'=>$lang->type_message) }
    -

    {$lang->importer} {$lang->help}

    +

    {$lang->importer}

    {nl2br($lang->about_importer)}

    diff --git a/modules/install/conf/module.xml b/modules/install/conf/module.xml index 3e754457f..0ec77e232 100644 --- a/modules/install/conf/module.xml +++ b/modules/install/conf/module.xml @@ -2,10 +2,10 @@ - - - - + + + + diff --git a/modules/install/install.admin.controller.php b/modules/install/install.admin.controller.php index 0facedf02..931933410 100644 --- a/modules/install/install.admin.controller.php +++ b/modules/install/install.admin.controller.php @@ -20,7 +20,7 @@ class installAdminController extends install function procInstallAdminInstall() { $module_name = Context::get('module_name'); - if(!$module_name) return $this->setError('invalid_request'); + if(!$module_name) throw new Rhymix\Framework\Exceptions\InvalidRequest; $oInstallController = getController('install'); $oInstallController->installModule($module_name, './modules/'.$module_name); @@ -35,13 +35,10 @@ class installAdminController extends install { @set_time_limit(0); $module_name = Context::get('module_name'); - if(!$module_name) return $this->setError('invalid_request'); + if(!$module_name) throw new Rhymix\Framework\Exceptions\InvalidRequest; $oModule = getModule($module_name, 'class'); - if(!$oModule) - { - return $this->setError('invalid_request'); - } + if(!$oModule) throw new Rhymix\Framework\Exceptions\InvalidRequest; Rhymix\Framework\Session::close(); $output = $oModule->moduleUpdate(); diff --git a/modules/install/install.controller.php b/modules/install/install.controller.php index df2b26b16..91f1106f5 100644 --- a/modules/install/install.controller.php +++ b/modules/install/install.controller.php @@ -17,7 +17,7 @@ class installController extends install // Stop if already installed. if (Context::isInstalled()) { - $this->stop('msg_already_installed'); + throw new Rhymix\Framework\Exception('msg_already_installed'); } // Increase time limit. @@ -76,7 +76,7 @@ class installController extends install { if ($oDB->isTableExists($table_name)) { - return $this->setError('msg_table_already_exists'); + throw new Rhymix\Framework\Exception('msg_table_already_exists'); } } @@ -99,7 +99,7 @@ class installController extends install // Check if it is already installed if (Context::isInstalled()) { - return $this->setError('msg_already_installed'); + throw new Rhymix\Framework\Exception('msg_already_installed'); } // Get install parameters. @@ -227,7 +227,7 @@ class installController extends install catch(Exception $e) { $oDB->rollback(); - return $this->setError($e->getMessage()); + throw new Rhymix\Framework\Exception($e->getMessage()); } // Execute the install script. @@ -296,7 +296,7 @@ class installController extends install } // Check permission - if(is_writable('./')||is_writable('./files')) + if(is_writable(RX_BASEDIR) || is_writable(RX_BASEDIR . 'files')) { $checklist['permission'] = true; } @@ -304,11 +304,19 @@ class installController extends install { $checklist['permission'] = false; } - - // Check session.auto_start - if(ini_get('session.auto_start') != 1) + + // Check session availability + $license_agreement_time = intval(trim(FileHandler::readFile($this->flagLicenseAgreement))); + if(isset($_SESSION['license_agreement']) && (!$license_agreement_time || ($license_agreement_time == $_SESSION['license_agreement']))) { - $checklist['session'] = true; + if(ini_get('session.auto_start') == 0) + { + $checklist['session'] = true; + } + else + { + $checklist['session'] = false; + } } else { @@ -400,25 +408,15 @@ class installController extends install function procInstallLicenseAgreement() { $vars = Context::getRequestVars(); - - $license_agreement = ($vars->license_agreement == 'Y') ? true : false; - - if($license_agreement) + if($vars->license_agreement !== 'Y') { - $currentTime = $_SERVER['REQUEST_TIME']; - FileHandler::writeFile($this->flagLicenseAgreement, $currentTime); - } - else - { - FileHandler::removeFile($this->flagLicenseAgreement); - return $this->setError('msg_must_accept_license_agreement'); - } - - if(!in_array(Context::getRequestMethod(),array('XMLRPC','JSON'))) - { - $returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : getNotEncodedUrl('', 'act', 'dispInstallCheckEnv'); - $this->setRedirectUrl($returnUrl); + throw new Rhymix\Framework\Exception('msg_must_accept_license_agreement'); } + + $license_agreement_time = time(); + $_SESSION['license_agreement'] = $license_agreement_time; + FileHandler::writeFile($this->flagLicenseAgreement, $license_agreement_time . PHP_EOL); + $this->setRedirectUrl(getNotEncodedUrl('', 'act', 'dispInstallCheckEnv')); } /** diff --git a/modules/install/install.view.php b/modules/install/install.view.php index a2696ae3a..f539ddcbb 100644 --- a/modules/install/install.view.php +++ b/modules/install/install.view.php @@ -19,7 +19,7 @@ class installView extends install // Stop if already installed. if (Context::isInstalled()) { - return $this->stop('msg_already_installed'); + throw new Rhymix\Framework\Exception('msg_already_installed'); } // Set the browser title. diff --git a/modules/install/lang/en.php b/modules/install/lang/en.php index 1adbffd66..a02ecef31 100644 --- a/modules/install/lang/en.php +++ b/modules/install/lang/en.php @@ -24,13 +24,13 @@ $lang->install_checklist_title['iconv'] = 'iconv / mbstring'; $lang->install_checklist_title['json'] = 'json'; $lang->install_checklist_title['gd'] = 'gd'; $lang->install_checklist_title['mcrypt'] = 'mcrypt / openssl'; -$lang->install_checklist_title['session'] = 'session.auto_start setting'; +$lang->install_checklist_title['session'] = 'session'; $lang->install_checklist_title['db_support'] = 'DB support'; $lang->install_checklist_desc['php_version'] = '[Required] Rhymix supports only PHP Version %s or higher'; $lang->install_checklist_desc['php_version_warning'] = '[Recommend] Rhymix recommends only PHP Version %s or higher'; -$lang->install_checklist_desc['permission'] = '[Required] Rhymix installation path or ./files directory\'s permission must be 777'; +$lang->install_checklist_desc['permission'] = '[Required] Please create a \'files\' directory under the installation path and change its permissions to 777.'; $lang->install_checklist_desc['xml'] = '[Required] XML Library is needed for XML communication'; -$lang->install_checklist_desc['session'] = '[Required] PHP setting file\'s (php.ini) \'Session.auto_start\' must equal to zero in order for Rhymix to use the session'; +$lang->install_checklist_desc['session'] = '[Required] PHP Session must be available, and \'session.auto_start\' must be off in order to use the session.'; $lang->install_checklist_desc['iconv'] = 'Iconv should be installed in order to convert between UTF-8 and other language sets'; $lang->install_checklist_desc['gd'] = 'GD Library should be installed in order to use functions to convert images'; $lang->install_checklist_xml = 'Install XML Library'; @@ -45,10 +45,10 @@ $lang->cmd_install_refresh_page = 'Refresh'; $lang->cmd_install_next = 'Continue installation'; $lang->cmd_ignore = 'Ignore'; $lang->cmd_recommended = 'Recommended'; -$lang->db_desc['mysqli'] = 'Use MySQL as a database via the mysqli extension.'; -$lang->db_desc['mysql'] = 'Use MySQL as a database via mysql_* functions.'; -$lang->db_desc['cubrid'] = 'Use CUBRID as a database. See Manual for more info'; -$lang->db_desc['mssql'] = 'Use Microsoft SQL Server as a database.'; +$lang->db_desc['mysqli'] = 'Use MySQL or MariaDB. Rhymix will automatically use InnoDB if it is supported.'; +$lang->db_desc['mysql'] = 'Use MySQL or MariaDB. Rhymix will automatically use InnoDB if it is supported.'; +$lang->db_desc['cubrid'] = 'CUBRID is not supported.'; +$lang->db_desc['mssql'] = 'Microsoft SQL Server is not supported.'; $lang->can_use_when_installed = 'Not installed on this server'; $lang->form_title = 'Database & Administrator Information'; $lang->db_title = 'Please input DB information'; diff --git a/modules/install/lang/es.php b/modules/install/lang/es.php index a036550f0..dc51d1f15 100644 --- a/modules/install/lang/es.php +++ b/modules/install/lang/es.php @@ -8,10 +8,10 @@ $lang->install_checklist_title['iconv'] = 'iconv / mbstring'; $lang->install_checklist_title['json'] = 'json'; $lang->install_checklist_title['gd'] = 'gd'; $lang->install_checklist_title['mcrypt'] = 'mcrypt / openssl'; -$lang->install_checklist_title['session'] = 'Configuración session.auto_start'; +$lang->install_checklist_title['session'] = 'session'; $lang->install_checklist_desc['permission'] = '[Requerido] La ruta de la instalación de Rhymix o el directorio de ./archivos deberia tener la atribución 777'; $lang->install_checklist_desc['xml'] = '[Requerido] Libreria XML es necesario para la comunicación de XML'; -$lang->install_checklist_desc['session'] = '[Requerido] Para el uso de la sesion de Rhymix, el archivo php.ini deberia estar configurada session.auto_start=0'; +$lang->install_checklist_desc['session'] = '[Requerido] La sesión de PHP debe estar disponible y \'session.auto_start\' debe estar \'off\' para poder utilizar la sesión.'; $lang->install_checklist_desc['iconv'] = 'Para transformar UTF-8 y otra paquete del idioma deberia estar instalado el Iconv.'; $lang->install_checklist_desc['gd'] = 'Libreria GD deberia estar instalado para utilizar la funcion de convertir la imagen'; $lang->install_checklist_xml = 'Instalar Librería XML '; @@ -24,10 +24,10 @@ $lang->install_permission_denied = 'La atribución de la ruta de instalacion no $lang->cmd_install_refresh_page = 'Refrescar'; $lang->cmd_install_next = 'Continuar la instalación'; $lang->cmd_recommended = 'Recomendado'; -$lang->db_desc['mysqli'] = 'Utilizando las funciones mysqli*() de PHP usar DB mysql.'; -$lang->db_desc['mysql'] = 'Utilizando las funciones mysql_*() de PHP usar DB mysql.'; -$lang->db_desc['cubrid'] = 'Usar BD CUBRID. Manual'; -$lang->db_desc['mssql'] = 'Usar Microsoft SQL Server.'; +$lang->db_desc['mysqli'] = 'Utilizando MySQL o MariaDB. Rhymix automáticamente usará InnoDB si es compatible.'; +$lang->db_desc['mysql'] = 'Utilizando MySQL o MariaDB. Rhymix automáticamente usará InnoDB si es compatible.'; +$lang->db_desc['cubrid'] = 'CUBRID no es compatible.'; +$lang->db_desc['mssql'] = 'Microsoft SQL Server no es compatible.'; $lang->form_title = 'Ingresar BD & Información del Administrador;'; $lang->db_title = 'Por favor escribir información de BD'; $lang->db_type = 'Tipo de BD'; diff --git a/modules/install/lang/fr.php b/modules/install/lang/fr.php index 26a5e5e50..c1597358e 100644 --- a/modules/install/lang/fr.php +++ b/modules/install/lang/fr.php @@ -8,10 +8,10 @@ $lang->install_checklist_title['iconv'] = 'iconv / mbstring'; $lang->install_checklist_title['json'] = 'json'; $lang->install_checklist_title['gd'] = 'gd'; $lang->install_checklist_title['mcrypt'] = 'mcrypt / openssl'; -$lang->install_checklist_title['session'] = 'Configuration de session.auto_start'; +$lang->install_checklist_title['session'] = 'session'; $lang->install_checklist_desc['permission'] = '[Obligatoire] Chemin de l\'installation de Rhymix ou la permission de répertoire de ./files doit être 777'; $lang->install_checklist_desc['xml'] = '[Obligatoire] La bibliothèque de XML est nécessaire pour la communication de XML'; -$lang->install_checklist_desc['session'] = '[Obligatoire] \'Session.auto_start\' dans le fichier de configuration pour PHP (php.ini) doit être égal à zéro car Rhymix utilise la session'; +$lang->install_checklist_desc['session'] = '[Obligatoire] La session PHP doit être disponible, et \'session.auto_start\' dans le fichier de configuration pour PHP (php.ini) doit être \'off\' car Rhymix utilise la session'; $lang->install_checklist_desc['iconv'] = 'Iconv doit être installé afin de convertir UTF-8 et des autres assortiments des langues'; $lang->install_checklist_desc['gd'] = 'La bibliothèque de GD doit être installé afin d\'utiliser la fonction à convertir des images'; $lang->install_checklist_xml = 'Installation la bibliothèque de XML'; @@ -24,10 +24,10 @@ $lang->install_permission_denied = 'La permission du chemin d\'installation n\'e $lang->cmd_install_refresh_page = 'Rafraîchir'; $lang->cmd_install_next = 'Continuer à installer'; $lang->cmd_recommended = 'Recommandé'; -$lang->db_desc['mysqli'] = 'Utilisera fonction mysqli_*() pour utiliser la base de données de MySQL.'; -$lang->db_desc['mysql'] = 'Utilisera fonction mysql_*() pour utiliser la base de données de MySQL'; -$lang->db_desc['cubrid'] = 'Utiliser la Base de Données de CUBRID. Manual'; -$lang->db_desc['mssql'] = 'Utiliser la Base de Données de Microsoft SQL Server.'; +$lang->db_desc['mysqli'] = 'Utilisera MySQL ou MariaDB. Rhymix utilisera automatiquement InnoDB s\'il est pris en charge.'; +$lang->db_desc['mysql'] = 'Utilisera MySQL ou MariaDB. Rhymix utilisera automatiquement InnoDB s\'il est pris en charge.'; +$lang->db_desc['cubrid'] = 'CUBRID n\'est pas compatible avec Rhymix.'; +$lang->db_desc['mssql'] = 'Microsoft SQL Server n\'est pas compatible avec Rhymix.'; $lang->can_use_when_installed = 'Pas installé sur ce serveur'; $lang->form_title = 'Entrer des informations de Base de données et Administrateur'; $lang->db_title = 'Entrez l\'information de Base de Données, S.V.P.'; diff --git a/modules/install/lang/ja.php b/modules/install/lang/ja.php index 748abdf14..5162117df 100644 --- a/modules/install/lang/ja.php +++ b/modules/install/lang/ja.php @@ -24,13 +24,13 @@ $lang->install_checklist_title['iconv'] = 'iconv / mbstring'; $lang->install_checklist_title['json'] = 'json'; $lang->install_checklist_title['gd'] = 'gd'; $lang->install_checklist_title['mcrypt'] = 'mcrypt / openssl'; -$lang->install_checklist_title['session'] = 'session.auto_startの設定'; +$lang->install_checklist_title['session'] = 'session'; $lang->install_checklist_title['db_support'] = 'DBサポート'; $lang->install_checklist_desc['php_version'] = '[必修] %s以上のPHPバージョンでインストールが可能です。'; $lang->install_checklist_desc['php_version_warning'] = '[推奨] RhymixはPHP %sバージョン以上をおすすめします。'; $lang->install_checklist_desc['permission'] = '【必須】Rhymixのインストール先、または「./files」ディレクトリのパーミッションを「777」に設定してください。'; $lang->install_checklist_desc['xml'] = '【必須】XML通信のためにXMLライブラリが必要です。'; -$lang->install_checklist_desc['session'] = '【必須】Rhymixでは、セッションを使用しているため、「php.ini」の設定を「session.auto_start=0」にしてください。'; +$lang->install_checklist_desc['session'] = '【必須】PHPセッションを使用することができなければならず、php.iniの設定でsession.auto_start= offである必要があります。'; $lang->install_checklist_desc['iconv'] = 'UTF-8と多言語サポート及び文字コード変換のため、「iconv」をインストールする必要があります。'; $lang->install_checklist_desc['gd'] = 'イメージ変換機能を使用するためには、「GDライブラリ」をインストールする必要があります。'; $lang->install_checklist_xml = 'XMLライブラリのインストール'; @@ -45,10 +45,10 @@ $lang->cmd_install_refresh_page = 'リフレッシュ'; $lang->cmd_install_next = 'インストールを続けます。'; $lang->cmd_ignore = 'FTP設定を省略する'; $lang->cmd_recommended = '推奨'; -$lang->db_desc['mysqli'] = 'mysqliモジュールを使用してMySQL DBに接続します。'; -$lang->db_desc['mysql'] = 'mysql_*()関数を使用してMySQL DBに接続します。'; -$lang->db_desc['cubrid'] = 'CUBRID DBを利用します。 Manual'; -$lang->db_desc['mssql'] = 'Microsoft SQL Serverを利用します。'; +$lang->db_desc['mysqli'] = 'MySQLやMariaDBを利用します。InnoDBサポート時に自動的に使用されます。'; +$lang->db_desc['mysql'] = 'MySQLやMariaDBを利用します。InnoDBサポート時に自動的に使用されます。'; +$lang->db_desc['cubrid'] = 'CUBRIDはサポートしていません。'; +$lang->db_desc['mssql'] = 'Microsoft SQL Serverはサポートしていません。'; $lang->can_use_when_installed = 'このサーバーにインストールされていません'; $lang->form_title = 'データベース & 管理者情報入力'; $lang->db_title = 'データベース情報入力'; diff --git a/modules/install/lang/ko.php b/modules/install/lang/ko.php index 4dd913904..dfc914bd8 100644 --- a/modules/install/lang/ko.php +++ b/modules/install/lang/ko.php @@ -24,13 +24,13 @@ $lang->install_checklist_title['iconv'] = 'iconv / mbstring'; $lang->install_checklist_title['json'] = 'json'; $lang->install_checklist_title['gd'] = 'gd'; $lang->install_checklist_title['mcrypt'] = 'mcrypt / openssl'; -$lang->install_checklist_title['session'] = 'session.auto_start 설정'; +$lang->install_checklist_title['session'] = '세션 지원'; $lang->install_checklist_title['db_support'] = 'DB 지원'; $lang->install_checklist_desc['php_version'] = '[필수] Rhymix를 설치하려면 PHP 버전이 %s 이상이어야 합니다.'; $lang->install_checklist_desc['php_version_warning'] = '[권장] Rhymix는 PHP %s 이상을 권장합니다.'; -$lang->install_checklist_desc['permission'] = '[필수] Rhymix의 설치 경로 또는 ./files 디렉토리의 퍼미션이 777이어야 합니다.'; +$lang->install_checklist_desc['permission'] = '[필수] Rhymix 설치 경로에 files 디렉토리를 생성하고 퍼미션을 777로 바꾸어 주십시오.'; $lang->install_checklist_desc['xml'] = '[필수] XML통신을 위하여 XML 라이브러리가 필요합니다.'; -$lang->install_checklist_desc['session'] = '[필수] Rhymix에서 세션 사용을 위해 php.ini 설정의 session.auto_start=0 이어야 합니다.'; +$lang->install_checklist_desc['session'] = '[필수] PHP 세션을 사용할 수 있어야 하며, php.ini 설정에서 session.auto_start = off 여야 합니다.'; $lang->install_checklist_desc['iconv'] = 'UTF-8과 다른 언어셋의 변환을 위한 iconv설치가 필요합니다.'; $lang->install_checklist_desc['gd'] = '이미지변환 기능을 사용하기 위해 GD라이브러리가 설치되어 있어야 합니다.'; $lang->install_checklist_xml = 'XML 라이브러리 설치'; @@ -45,10 +45,10 @@ $lang->cmd_install_refresh_page = '새로고침'; $lang->cmd_install_next = '설치를 진행합니다.'; $lang->cmd_ignore = '무시'; $lang->cmd_recommended = '권장'; -$lang->db_desc['mysqli'] = 'mysqli 모듈을 사용하여 MySQL DB에 접속합니다.'; -$lang->db_desc['mysql'] = 'mysql_*() 함수를 사용하여 MySQL DB에 접속합니다.'; -$lang->db_desc['cubrid'] = 'CUBRID DB를 이용합니다. Manual'; -$lang->db_desc['mssql'] = 'Microsoft SQL Server를 이용합니다.'; +$lang->db_desc['mysqli'] = 'MySQL 또는 MariaDB를 이용합니다. InnoDB 지원시 자동으로 사용합니다.'; +$lang->db_desc['mysql'] = 'MySQL 또는 MariaDB를 이용합니다. InnoDB 지원시 자동으로 사용합니다.'; +$lang->db_desc['cubrid'] = 'CUBRID는 지원하지 않습니다.'; +$lang->db_desc['mssql'] = 'Microsoft SQL Server는 지원하지 않습니다.'; $lang->can_use_when_installed = '설치되어 있지 않음'; $lang->form_title = 'DB & 관리자 정보 입력'; $lang->db_title = 'DB 정보 입력'; diff --git a/modules/install/lang/ru.php b/modules/install/lang/ru.php index 213d99578..7172c8f67 100644 --- a/modules/install/lang/ru.php +++ b/modules/install/lang/ru.php @@ -8,10 +8,10 @@ $lang->install_checklist_title['iconv'] = 'iconv / mbstring'; $lang->install_checklist_title['json'] = 'json'; $lang->install_checklist_title['gd'] = 'gd'; $lang->install_checklist_title['mcrypt'] = 'mcrypt / openssl'; -$lang->install_checklist_title['session'] = 'session.auto_start настройка'; +$lang->install_checklist_title['session'] = 'session'; $lang->install_checklist_desc['permission'] = '[Требуется] Путь установки Rhymix или директория ./files должна иметь права доступа 777'; $lang->install_checklist_desc['xml'] = '[Требуется] XML Библиотека нужна для XML коммуникации'; -$lang->install_checklist_desc['session'] = '[Требуется] Файл настроек PHP (php.ini) \'Session.auto_start\' должен быть равен нулю, чтобы Rhymix могла использовать сессии'; +$lang->install_checklist_desc['session'] = '[Требуется] Сеанс PHP должен быть доступен, и \'session.auto_start\' должен быть \'off\', чтобы использовать сеанс.'; $lang->install_checklist_desc['iconv'] = 'Iconv должна быть установлена для конвертирования между UTF-8 и иными языковыми кодировками'; $lang->install_checklist_desc['gd'] = 'GD Библиотека должна быть установлена для использования функции конвертироваия изображений'; $lang->install_checklist_xml = 'Установить XML библиотеку'; @@ -24,10 +24,10 @@ $lang->install_permission_denied = 'Права доступа пути не ус $lang->cmd_install_refresh_page = 'обновление'; $lang->cmd_install_next = 'Продолжить установку'; $lang->cmd_recommended = 'рекомендуемые'; -$lang->db_desc['mysqli'] = 'Используем mysqli_*() функцию, чтобы использовать базу данных mysql.'; -$lang->db_desc['mysql'] = 'Используем mysql_*() функцию, чтобы использовать базу данных mysql.'; -$lang->db_desc['cubrid'] = 'Используем CUBRID DB. Manual'; -$lang->db_desc['mssql'] = 'Используем Microsoft SQL Server DB.'; +$lang->db_desc['mysqli'] = 'Используйте MySQL или MariaDB. Rhymix будет автоматически использовать InnoDB, если он поддерживается.'; +$lang->db_desc['mysql'] = 'Используйте MySQL или MariaDB. Rhymix будет автоматически использовать InnoDB, если он поддерживается.'; +$lang->db_desc['cubrid'] = 'CUBRID не совместим с Rhymix.'; +$lang->db_desc['mssql'] = 'Microsoft SQL Server не совместим с Rhymix.'; $lang->form_title = 'Пожалуйста, введите дазу данных & Административная Информация'; $lang->db_title = 'Пожалуйста, введите информацию базы данных'; $lang->db_type = 'Тип базы данных'; diff --git a/modules/install/lang/tr.php b/modules/install/lang/tr.php index 25792a1b1..014de2953 100644 --- a/modules/install/lang/tr.php +++ b/modules/install/lang/tr.php @@ -8,10 +8,10 @@ $lang->install_checklist_title['iconv'] = 'iconv / mbstring'; $lang->install_checklist_title['json'] = 'json'; $lang->install_checklist_title['gd'] = 'gd'; $lang->install_checklist_title['mcrypt'] = 'mcrypt / openssl'; -$lang->install_checklist_title['session'] = 'session.auto_start(otomatik.oturum_acma) ayarı'; +$lang->install_checklist_title['session'] = 'session'; $lang->install_checklist_desc['permission'] = '[Gerekli] Rhymix kurulum yolu ya da ./files directory yolunun yetkisi 777 olmalıdır'; $lang->install_checklist_desc['xml'] = '[Gerekli] XML iletişimi için XML kitaplığı gereklidir.'; -$lang->install_checklist_desc['session'] = '[Gerekli] PHP ayar dosyasındaki (php.ini) \'Session.auto_start\' Rhymix\'nin oturumu kullanabilmesi için sıfıra eşit olmalıdır'; +$lang->install_checklist_desc['session'] = '[Gerekli] PHP Oturumu kullanılabilir olmalı ve oturumu kullanmak için \'session.auto_start\' \'off\' olmalıdır.'; $lang->install_checklist_desc['iconv'] = 'Iconv, UTF-8 ve diğer dil ayarlarını değiştirebilmek için kurulmuş olmalıdır'; $lang->install_checklist_desc['gd'] = 'GD Kitaplığı, resim değiştirme özelliğini kullanabilmek için kurulmuş, olmalıdır'; $lang->install_checklist_xml = 'XML Kitaplığını Kur'; diff --git a/modules/install/lang/vi.php b/modules/install/lang/vi.php index aed604fa3..f962bbf71 100644 --- a/modules/install/lang/vi.php +++ b/modules/install/lang/vi.php @@ -3,10 +3,10 @@ $lang->introduce_title = 'Cài đặt Rhymix'; $lang->install_progress_menu['language'] = 'Chọn ngôn ngữ cài đặt'; $lang->install_checklist_title['php_version'] = 'Phiên bản PHP'; $lang->install_checklist_title['permission'] = 'Điều khoản thư mục files'; -$lang->install_checklist_title['session'] = 'Thiết lập session.auto_start'; +$lang->install_checklist_title['session'] = 'session'; $lang->install_checklist_desc['permission'] = '[Bắt buộc] Thư mục cài đặt của Rhymix hay ./files directory phải CHMOD thành 777'; $lang->install_checklist_desc['xml'] = '[Bắt buộc] XML Library cần thiết cho việc truyền thông File XML.'; -$lang->install_checklist_desc['session'] = '[Bắt buộc] File thiết lập của PHP (php.ini) \'Session.auto_start\' phải là 0 theo thứ tự số cho phiên làm việc của Rhymix hoạt động.'; +$lang->install_checklist_desc['session'] = '[Bắt buộc] Phiên PHP phải có sẵn và \'session.auto_start\' phải là \'off\' để sử dụng phiên.'; $lang->install_checklist_desc['iconv'] = 'Iconv cần phải được cài đặt cho việc chuyển đổi ngôn ngữ thàng UTFF-8 của những ngôn ngữ khác.'; $lang->install_checklist_desc['gd'] = 'GD Library cần phải được cài đặt cho việc chuyển đổi hình ảnh.'; $lang->install_checklist_xml = 'Cài đặt XML Library'; diff --git a/modules/install/lang/zh-CN.php b/modules/install/lang/zh-CN.php index b13b29b3b..56476a11f 100644 --- a/modules/install/lang/zh-CN.php +++ b/modules/install/lang/zh-CN.php @@ -16,10 +16,10 @@ $lang->install_checklist_title['iconv'] = 'iconv / mbstring'; $lang->install_checklist_title['json'] = 'json'; $lang->install_checklist_title['gd'] = 'gd'; $lang->install_checklist_title['mcrypt'] = 'mcrypt / openssl'; -$lang->install_checklist_title['session'] = 'session.auto_start 设置'; +$lang->install_checklist_title['session'] = 'session'; $lang->install_checklist_desc['permission'] = '[必须] 的安装路径或 ./files目录属性必须是777'; $lang->install_checklist_desc['xml'] = '[必须]为了 XML通讯,将需要XML库'; -$lang->install_checklist_desc['session'] = '[必须] 为了使用缓冲功能,必须在php.ini当中设置 session.auto_start=0'; +$lang->install_checklist_desc['session'] = '[必须] PHP会话必须可用,必须在php.ini当中设置 session.auto_start = off'; $lang->install_checklist_desc['iconv'] = '为了UTF-8和其他语言环境之间的互相转换,必须安装iconv'; $lang->install_checklist_desc['gd'] = '为了使用图片转换功能,必须先得安装GD库'; $lang->install_checklist_xml = '安装XML库'; @@ -33,10 +33,10 @@ $lang->cmd_install_refresh_page = '刷新屏幕'; $lang->cmd_install_next = '开始安装'; $lang->cmd_ignore = '忽略'; $lang->cmd_recommended = '推荐'; -$lang->db_desc['mysqli'] = '利用php的 mysqli*()函数使用mysql DB。'; -$lang->db_desc['mysql'] = '利用php的 mysql_*()函数使用mysql DB。'; -$lang->db_desc['cubrid'] = '使用CUBRID DB。 Manual'; -$lang->db_desc['mssql'] = '使用 Microsoft SQL Server。'; +$lang->db_desc['mysqli'] = '使用MySQL或MariaDB。 如果支持,Rhymix将自动使用InnoDB。'; +$lang->db_desc['mysql'] = '使用MySQL或MariaDB。 如果支持,Rhymix将自动使用InnoDB。'; +$lang->db_desc['cubrid'] = '不支持CUBRID。'; +$lang->db_desc['mssql'] = '不支持Microsoft SQL Server。'; $lang->can_use_when_installed = '不是这个服务器上安装'; $lang->form_title = '数据库及管理员基本信息'; $lang->db_title = '输入数据库信息'; diff --git a/modules/install/lang/zh-TW.php b/modules/install/lang/zh-TW.php index ba1cad0ba..d47b8eeed 100644 --- a/modules/install/lang/zh-TW.php +++ b/modules/install/lang/zh-TW.php @@ -16,10 +16,10 @@ $lang->install_checklist_title['iconv'] = 'iconv / mbstring'; $lang->install_checklist_title['json'] = 'json'; $lang->install_checklist_title['gd'] = 'gd'; $lang->install_checklist_title['mcrypt'] = 'mcrypt / openssl'; -$lang->install_checklist_title['session'] = 'session.auto_start設置'; +$lang->install_checklist_title['session'] = 'session'; $lang->install_checklist_desc['permission'] = '[必須] Rhymix的資料夾或『./files』資料夾權限必須是『777』。'; $lang->install_checklist_desc['xml'] = '[必須] 必須要安裝『XML Library』,才能夠使用 XML 通訊。'; -$lang->install_checklist_desc['session'] = '[必須] 在『php.ini』中必須要設定『session.auto_start=0』,才能使用暫存功能'; +$lang->install_checklist_desc['session'] = '[必須] PHP會話必須可用,在『php.ini』中必須要設定『session.auto_start = off』,才能使用暫存功能'; $lang->install_checklist_desc['iconv'] = '安裝『iconv』,才能使 UTF-8 和其他語言文字作互相轉換。'; $lang->install_checklist_desc['gd'] = '安裝『GD Library』才可以使用圖片轉換功能。'; $lang->install_checklist_xml = '安裝 XML Library'; @@ -33,10 +33,10 @@ $lang->cmd_install_refresh_page = '刷新屏幕'; $lang->cmd_install_next = '開始進行安裝'; $lang->cmd_ignore = '忽略'; $lang->cmd_recommended = '推薦'; -$lang->db_desc['mysqli'] = '利用 PHP 的『mysqli*()』函數使用 MySQL 資料庫。'; -$lang->db_desc['mysql'] = '利用 PHP 的『mysql_*()』函數使用 MySQL 資料庫。'; -$lang->db_desc['cubrid'] = '使用 CUBRID DB。 Manual'; -$lang->db_desc['mssql'] = '使用 Microsoft SQL Server。'; +$lang->db_desc['mysqli'] = '使用MySQL或MariaDB。 如果支持,Rhymix將自動使用InnoDB。'; +$lang->db_desc['mysql'] = '使用MySQL或MariaDB。 如果支持,Rhymix將自動使用InnoDB。'; +$lang->db_desc['cubrid'] = '不支持CUBRID。'; +$lang->db_desc['mssql'] = '不支持Microsoft SQL Server。'; $lang->can_use_when_installed = '不是這個服務器上安裝'; $lang->form_title = '輸入資料庫及管理員資訊'; $lang->db_title = '輸入資料庫資訊'; diff --git a/modules/install/tpl/check_env.html b/modules/install/tpl/check_env.html index e2cc54949..b61a5d7cc 100644 --- a/modules/install/tpl/check_env.html +++ b/modules/install/tpl/check_env.html @@ -9,7 +9,7 @@
    {$lang->install_checklist_title[$key]} - ({$phpversion}) + ({$phpversion}) OK diff --git a/modules/integration_search/conf/module.xml b/modules/integration_search/conf/module.xml index c4df18f19..89e20d10a 100644 --- a/modules/integration_search/conf/module.xml +++ b/modules/integration_search/conf/module.xml @@ -2,7 +2,7 @@ - + diff --git a/modules/integration_search/integration_search.admin.controller.php b/modules/integration_search/integration_search.admin.controller.php index 1c035635e..7d2ab6bb8 100644 --- a/modules/integration_search/integration_search.admin.controller.php +++ b/modules/integration_search/integration_search.admin.controller.php @@ -29,6 +29,7 @@ class integration_searchAdminController extends integration_search $config = (object)get_object_vars($config); $config->skin = Context::get('skin'); + $config->mskin = Context::get('mskin'); $config->target = Context::get('target'); $config->target_module_srl = Context::get('target_module_srl'); if(!$config->target_module_srl) $config->target_module_srl = ''; diff --git a/modules/integration_search/integration_search.admin.view.php b/modules/integration_search/integration_search.admin.view.php index daaa3c641..91136461a 100644 --- a/modules/integration_search/integration_search.admin.view.php +++ b/modules/integration_search/integration_search.admin.view.php @@ -36,12 +36,16 @@ class integration_searchAdminView extends integration_search */ function dispIntegration_searchAdminContent() { - // Get a list of skins(themes) + // Get a list of skins $oModuleModel = getModel('module'); $skin_list = $oModuleModel->getSkins($this->module_path); Context::set('skin_list',$skin_list); + $mskin_list = $oModuleModel->getSkins($this->module_path, 'm.skins'); + Context::set('mskin_list', $mskin_list); + // Get a list of module categories $module_categories = $oModuleModel->getModuleCategories(); + // Generated mid Wanted list $obj = new stdClass(); $obj->site_srl = 0; @@ -60,7 +64,7 @@ class integration_searchAdminView extends integration_search Context::set('mid_list',$module_categories);*/ $security = new Security(); - $security->encodeHTML('skin_list..title'); + $security->encodeHTML('skin_list..title', 'mskin_list..title'); // Sample Code Context::set('sample_code', htmlspecialchars('
    ', ENT_COMPAT | ENT_HTML401, 'UTF-8', false) ); diff --git a/modules/integration_search/integration_search.view.php b/modules/integration_search/integration_search.view.php index 7c9db39c3..2e3660201 100644 --- a/modules/integration_search/integration_search.view.php +++ b/modules/integration_search/integration_search.view.php @@ -49,33 +49,54 @@ class integration_searchView extends integration_search } // Check permissions - if(!$this->grant->access) return $this->setError('msg_not_permitted'); - - $config = $oModuleModel->getModuleConfig('integration_search'); - if(!$config) $config = new stdClass; - if(!$config->skin) + if(!$this->grant->access) { - $config->skin = 'default'; - $template_path = sprintf('%sskins/%s', $this->module_path, $config->skin); + throw new Rhymix\Framework\Exceptions\NotPermitted; } - else + + // Set skin path + $config = $oModuleModel->getModuleConfig('integration_search') ?: new stdClass; + if(ends_with('Mobile', get_class($this), false)) { - //check theme - $config_parse = explode('|@|', $config->skin); - if (count($config_parse) > 1) + if(!$config->mskin || $config->mskin === '/USE_RESPONSIVE/') { - $template_path = sprintf('./themes/%s/modules/integration_search/', $config_parse[0]); + $template_path = sprintf('%sskins/%s/', $this->module_path, $config->skin); + if(!is_dir($template_path) || !$config->skin) + { + $template_path = sprintf('%sskins/%s/', $this->module_path, 'default'); + $config->mskin = 'default'; + } } else { - $template_path = sprintf('%sskins/%s', $this->module_path, $config->skin); + $template_path = sprintf('%sm.skins/%s/', $this->module_path, $config->mskin); + if(!is_dir($template_path) || !$config->mskin) + { + $template_path = sprintf('%sm.skins/%s/', $this->module_path, 'default'); + $config->mskin = 'default'; + } + if(!is_dir($template_path)) + { + $template_path = sprintf('%sskins/%s/', $this->module_path, 'default'); + $config->mskin = 'default'; + } } } - // Template path + else + { + $template_path = sprintf('%sskins/%s/', $this->module_path, $config->skin); + if(!is_dir($template_path) || !$config->skin) + { + $template_path = sprintf('%sskins/%s/', $this->module_path, 'default'); + $config->skin = 'default'; + } + } + $this->setTemplatePath($template_path); $skin_vars = ($config->skin_vars) ? unserialize($config->skin_vars) : new stdClass; Context::set('module_info', $skin_vars); + // Include or exclude target modules. $target = $config->target; if(!$target) $target = 'include'; @@ -88,13 +109,7 @@ class integration_searchView extends integration_search // 검색 대상을 지정하지 않았을 때 검색 제한 if($target === 'include' && !count($module_srl_list)) { - $oMessageObject = ModuleHandler::getModuleInstance('message'); - $oMessageObject->setError(-1); - $oMessageObject->setMessage('msg_not_enabled'); - $oMessageObject->dispMessage(); - $this->setTemplatePath($oMessageObject->getTemplatePath()); - $this->setTemplateFile($oMessageObject->getTemplateFile()); - return; + throw new Rhymix\Framework\Exception('msg_not_enabled'); } // Set a variable for search keyword diff --git a/modules/integration_search/tpl/index.html b/modules/integration_search/tpl/index.html index 16f6d641d..8dc567fc7 100644 --- a/modules/integration_search/tpl/index.html +++ b/modules/integration_search/tpl/index.html @@ -23,7 +23,14 @@ -

    {$lang->about_skin}

    + + +
    + +
    +
    diff --git a/modules/krzip/conf/module.xml b/modules/krzip/conf/module.xml index 8b783749b..b773637a0 100644 --- a/modules/krzip/conf/module.xml +++ b/modules/krzip/conf/module.xml @@ -2,7 +2,7 @@ - + diff --git a/modules/krzip/krzip.model.php b/modules/krzip/krzip.model.php index 3edbd4cc1..9980f2bc3 100644 --- a/modules/krzip/krzip.model.php +++ b/modules/krzip/krzip.model.php @@ -104,7 +104,7 @@ class krzipModel extends krzip $query = trim(strval($query)); if($query === '') { - return $this->stop('msg_krzip_no_query'); + return $this->setError('msg_krzip_no_query'); } $output = $this->getEpostapiSearch($query); diff --git a/modules/krzip/tpl/config.html b/modules/krzip/tpl/config.html index ad97a8a67..6ab798034 100644 --- a/modules/krzip/tpl/config.html +++ b/modules/krzip/tpl/config.html @@ -31,16 +31,14 @@ - {$lang->help} - +

    {$lang->about_krzip_api_handler}

    - {$lang->help} - +

    {$lang->about_krzip_epostapi_regkey}

    diff --git a/modules/layout/conf/module.xml b/modules/layout/conf/module.xml index b6240195a..60b2ea8f3 100644 --- a/modules/layout/conf/module.xml +++ b/modules/layout/conf/module.xml @@ -2,8 +2,8 @@ - - + + diff --git a/modules/layout/faceoff/layout.html b/modules/layout/faceoff/layout.html index 884812871..c134b0cdd 100644 --- a/modules/layout/faceoff/layout.html +++ b/modules/layout/faceoff/layout.html @@ -18,7 +18,7 @@
    - {$content} + {$content|noescape}

    diff --git a/modules/layout/layout.admin.controller.php b/modules/layout/layout.admin.controller.php index a20943ffb..920fc2d12 100644 --- a/modules/layout/layout.admin.controller.php +++ b/modules/layout/layout.admin.controller.php @@ -23,7 +23,7 @@ class layoutAdminController extends layout */ function procLayoutAdminInsert() { - if(Context::get('layout') == 'faceoff') return $this->stop('not supported'); + if(Context::get('layout') == 'faceoff') throw new Rhymix\Framework\Exception('not supported'); // Get information to create a layout $site_module_info = Context::get('site_module_info'); @@ -130,7 +130,7 @@ class layoutAdminController extends layout $output = executeQuery('menu.getMenuItemByUrl', $tmpArgs); if(!$output->toBool()) { - return $this->setError('fail_to_update'); + throw new Rhymix\Framework\Exception('fail_to_update'); } $menu_srl = $output->data->menu_srl; @@ -186,7 +186,7 @@ class layoutAdminController extends layout } } - $tmpDir = sprintf('./files/attach/images/%s/tmp', $args->layout_srl); + $tmpDir = sprintf('./files/attach/images/%d/tmp', $args->layout_srl); // Separately handle if a type of extra_vars is an image if($layout_info->extra_var) { @@ -313,7 +313,7 @@ class layoutAdminController extends layout if(!$output->toBool()) { - return $this->setError($output->message); + throw new Rhymix\Framework\Exception($output->message); } } } @@ -356,7 +356,7 @@ class layoutAdminController extends layout if(!$layout_srl || !$code || !$is_post) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $oLayoutModel = getModel('layout'); @@ -377,7 +377,7 @@ class layoutAdminController extends layout function procLayoutAdminCodeReset() { $layout_srl = Context::get('layout_srl'); - if(!$layout_srl) return $this->setError('msg_invalid_request'); + if(!$layout_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; // delete user layout file $oLayoutModel = getModel('layout'); @@ -480,13 +480,13 @@ class layoutAdminController extends layout $oModuleModel = getModel('module'); $mid = Context::get('mid'); - if(!$mid) return $this->setError('msg_invalid_request'); + if(!$mid) throw new Rhymix\Framework\Exceptions\InvalidRequest; $site_module_info = Context::get('site_module_info'); $columnList = array('layout_srl'); $module_info = $oModuleModel->getModuleInfoByMid($mid, $site_module_info->site_srl, $columnList); $layout_srl = $module_info->layout_srl; - if(!$layout_srl) return $this->setError('msg_invalid_request'); + if(!$layout_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; $oLayoutModel = getModel('layout'); @@ -683,7 +683,7 @@ class layoutAdminController extends layout */ function procLayoutAdminUserLayoutImport() { - return $this->stop('not supported'); + throw new Rhymix\Framework\Exception('not supported'); // check upload if(!Context::isUploaded()) exit(); @@ -713,12 +713,12 @@ class layoutAdminController extends layout $sourceArgs = Context::getRequestVars(); if($sourceArgs->layout == 'faceoff') { - return $this->stop('not supported'); + throw new Rhymix\Framework\Exception('not supported'); } if(!$sourceArgs->layout_srl) { - return $this->stop('msg_empty_origin_layout'); + throw new Rhymix\Framework\Exception('msg_empty_origin_layout'); } $oLayoutModel = getModel('layout'); @@ -731,7 +731,7 @@ class layoutAdminController extends layout if(!is_array($sourceArgs->title) || count($sourceArgs->title) == 0) { - return $this->stop('msg_empty_target_layout'); + throw new Rhymix\Framework\Exception('msg_empty_target_layout'); } $output = $oLayoutModel->getLayoutRawData($sourceArgs->layout_srl, array('extra_vars')); @@ -777,7 +777,7 @@ class layoutAdminController extends layout if(is_array($image_list)) { foreach($image_list as $key=>$val) { - $new_file = sprintf("./files/attach/images/%s/%s", $args->layout_srl,$val->filename); + $new_file = sprintf("./files/attach/images/%d/%s", $args->layout_srl,$val->filename); FileHandler::copyFile($val->old_file, $new_file); $extra_vars->{$key} = $new_file; } diff --git a/modules/layout/layout.admin.model.php b/modules/layout/layout.admin.model.php index 7d6de7f67..004879a12 100644 --- a/modules/layout/layout.admin.model.php +++ b/modules/layout/layout.admin.model.php @@ -67,7 +67,7 @@ class layoutAdminModel extends layout // Error appears if there is no layout information is registered if(!$layout_info) { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Get a menu list diff --git a/modules/layout/layout.admin.view.php b/modules/layout/layout.admin.view.php index 42df0dcf1..9dc793a9b 100644 --- a/modules/layout/layout.admin.view.php +++ b/modules/layout/layout.admin.view.php @@ -140,11 +140,11 @@ class layoutAdminView extends layout $layout = Context::get('layout'); if(!in_array($type, array('P', 'M'))) $type = 'P'; - if(!$layout) return $this->stop('msg_invalid_request'); + if(!$layout) throw new Rhymix\Framework\Exceptions\InvalidRequest; $oLayoutModel = getModel('layout'); $layout_info = $oLayoutModel->getLayoutInfo($layout, null, $type); - if(!$layout_info) return $this->stop('msg_invalid_request'); + if(!$layout_info) throw new Rhymix\Framework\Exceptions\InvalidRequest; Context::set('layout_info', $layout_info); @@ -175,10 +175,10 @@ class layoutAdminView extends layout // Get layout info $layout = Context::get('layout'); - if($layout == 'faceoff') return $this->stop('not supported'); + if($layout == 'faceoff') throw new Rhymix\Framework\Exception('not supported'); $layout_info = $oModel->getLayoutInfo($layout, null, $type); - if(!$layout_info) return $this->stop('msg_invalid_request'); + if(!$layout_info) throw new Rhymix\Framework\Exceptions\InvalidRequest; // get Menu list $oMenuAdminModel = getAdminModel('menu'); @@ -295,11 +295,11 @@ class layoutAdminView extends layout $layout_srl = Context::get('layout_srl'); $code = Context::get('code'); $code_css = Context::get('code_css'); - if(!$layout_srl || !$code) return $this->setError('msg_invalid_request'); + if(!$layout_srl || !$code) throw new Rhymix\Framework\Exceptions\InvalidRequest; // Get the layout information $oLayoutModel = getModel('layout'); $layout_info = $oLayoutModel->getLayout($layout_srl); - if(!$layout_info) return $this->setError('msg_invalid_request'); + if(!$layout_info) throw new Rhymix\Framework\Exceptions\InvalidRequest; // Separately handle the layout if its type is faceoff if($layout_info && $layout_info->type == 'faceoff') $oLayoutModel->doActivateFaceOff($layout_info); // Apply CSS directly diff --git a/modules/layout/layout.view.php b/modules/layout/layout.view.php index ec8730e93..b1f24d962 100644 --- a/modules/layout/layout.view.php +++ b/modules/layout/layout.view.php @@ -55,7 +55,7 @@ class layoutView extends layout $logged_info = Context::get('logged_info'); if($logged_info->is_admin != 'Y') { - throw new Exception(lang('msg_invalid_request')); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // if module is 'ARTiCLE' and from site design setting, make content directly @@ -113,7 +113,7 @@ class layoutView extends layout if($layoutSrl == -1) { $site_srl = ($oModule) ? $oModule->module_info->site_srl : 0; - $designInfoFile = sprintf(_XE_PATH_ . 'files/site_design/design_%s.php', $site_srl); + $designInfoFile = sprintf(_XE_PATH_ . 'files/site_design/design_%d.php', $site_srl); include($designInfoFile); if($skinType == 'M') @@ -253,13 +253,13 @@ class layoutView extends layout $output = executeQuery('layout.getOneModuleInstanceByModuleName', $args); if(!$output->toBool()) { - throw new Exception($output->getMessage()); + throw new Rhymix\Framework\Exception($output->getMessage()); } // if there is no module instance, error... if(!$output->data) { - throw new Exception(lang('msg_unabled_preview')); + throw new Rhymix\Framework\Exception(lang('msg_unabled_preview')); } $mid = current($output->data)->mid; @@ -301,7 +301,7 @@ class layoutView extends layout $oModule = $oModuleHandler->procModule(); if(!$oModule->toBool()) { - throw new Exception(lang('not_support_layout_preview')); + throw new Rhymix\Framework\Exception(lang('not_support_layout_preview')); } // get module html @@ -318,23 +318,23 @@ class layoutView extends layout { if(!checkCSRF()) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // admin check // this act is admin view but in normal view because do not load admin css/js files $logged_info = Context::get('logged_info'); - if($logged_info->is_admin != 'Y') return $this->stop('msg_invalid_request'); + if($logged_info->is_admin != 'Y') throw new Rhymix\Framework\Exceptions\InvalidRequest; $layout_srl = Context::get('layout_srl'); $code = Context::get('code'); $code_css = Context::get('code_css'); - if(!$layout_srl || !$code) return $this->setError('msg_invalid_request'); + if(!$layout_srl || !$code) throw new Rhymix\Framework\Exceptions\InvalidRequest; // Get the layout information $oLayoutModel = getModel('layout'); $layout_info = $oLayoutModel->getLayout($layout_srl); - if(!$layout_info) return $this->setError('msg_invalid_request'); + if(!$layout_info) throw new Rhymix\Framework\Exceptions\InvalidRequest; // Separately handle the layout if its type is faceoff if($layout_info && $layout_info->type == 'faceoff') $oLayoutModel->doActivateFaceOff($layout_info); // Apply CSS directly diff --git a/modules/layout/tpl/faceoff_layout_edit.html b/modules/layout/tpl/faceoff_layout_edit.html index d9f1e44a0..77817d406 100644 --- a/modules/layout/tpl/faceoff_layout_edit.html +++ b/modules/layout/tpl/faceoff_layout_edit.html @@ -1 +1 @@ -{$content} +{$content|noescape} diff --git a/modules/layout/tpl/header.html b/modules/layout/tpl/header.html index 6d6518ae2..d77d05472 100644 --- a/modules/layout/tpl/header.html +++ b/modules/layout/tpl/header.html @@ -4,7 +4,7 @@

    - {$lang->installed_layout} {$lang->help} + {$lang->installed_layout} > {$layout_info->title} v{$layout_info->version} > {$selected_layout->title} v{$selected_layout->version} > {$selected_layout->layout_title} diff --git a/modules/layout/tpl/installed_layout_list.html b/modules/layout/tpl/installed_layout_list.html index 2916eb953..8cfaea6e3 100644 --- a/modules/layout/tpl/installed_layout_list.html +++ b/modules/layout/tpl/installed_layout_list.html @@ -13,8 +13,8 @@

    {$lang->layout_name} {$lang->version} {$lang->author}{$lang->path}{$lang->cmd_delete}{$lang->path}{$lang->cmd_delete}
    {$layout->path}{$lang->cmd_delete}{$layout->path}{$lang->cmd_delete} @@ -46,8 +46,8 @@ - -{$layout->path}{$lang->cmd_delete}{$layout->path}{$lang->cmd_delete}
    +
    + - - - + + - + @@ -23,14 +28,13 @@ {@$layout_name = $layout['title']} {@unset($layout['title'])} - - - + + -
    +
    + + +
    +
    {$lang->number}{$lang->layout_name}{$lang->title}{$lang->number}{$lang->title} ({$lang->layout_name}) {$lang->regdate} {$lang->cmd_setup} {$lang->cmd_edit} {$lang->cmd_copy}{$lang->cmd_delete}{$lang->cmd_delete}
    {$count++}{$layout_name}{$item->title}{$count++}{$item->title} ({$layout_name}) {zdate($item->regdate, "Y-m-d")} {$lang->cmd_setup} {$lang->cmd_edit} {$lang->cmd_copy} +
    diff --git a/modules/layout/tpl/layout_modify.html b/modules/layout/tpl/layout_modify.html index 8fdcc28d2..dc1e22014 100644 --- a/modules/layout/tpl/layout_modify.html +++ b/modules/layout/tpl/layout_modify.html @@ -1,3 +1,3 @@ -{$content} +{$content|noescape} diff --git a/modules/member/conf/module.xml b/modules/member/conf/module.xml index fc326f3b6..a09502bc5 100644 --- a/modules/member/conf/module.xml +++ b/modules/member/conf/module.xml @@ -2,23 +2,23 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/modules/member/m.skins/default/login_form.html b/modules/member/m.skins/default/login_form.html index b1ee3c9b8..b4f5d5e3a 100644 --- a/modules/member/m.skins/default/login_form.html +++ b/modules/member/m.skins/default/login_form.html @@ -6,7 +6,7 @@

    {$XE_VALIDATOR_MESSAGE}

    - + diff --git a/modules/member/m.skins/default/modify_info.html b/modules/member/m.skins/default/modify_info.html index e0dafbd1d..ff229b40f 100644 --- a/modules/member/m.skins/default/modify_info.html +++ b/modules/member/m.skins/default/modify_info.html @@ -35,7 +35,7 @@
    {$formTag->inputTag}
    - {$editor} + {$editor|noescape}
  • allow_mailing!='N')-->checked="checked" />

    {$lang->about_allow_mailing}

  • diff --git a/modules/member/m.skins/rx_prn/login_form.html b/modules/member/m.skins/rx_prn/login_form.html index 580142657..524c88a9c 100644 --- a/modules/member/m.skins/rx_prn/login_form.html +++ b/modules/member/m.skins/rx_prn/login_form.html @@ -5,7 +5,7 @@

    {$XE_VALIDATOR_MESSAGE}

    - + diff --git a/modules/member/m.skins/rx_prn/modify_info.html b/modules/member/m.skins/rx_prn/modify_info.html index ff1ead74a..db5e44f51 100644 --- a/modules/member/m.skins/rx_prn/modify_info.html +++ b/modules/member/m.skins/rx_prn/modify_info.html @@ -31,7 +31,7 @@ {$formTag->inputTag} - {$editor} + {$editor|noescape}
    diff --git a/modules/member/m.skins/rx_prn/signup_form.html b/modules/member/m.skins/rx_prn/signup_form.html index d945dc5bc..a2f6a8a42 100644 --- a/modules/member/m.skins/rx_prn/signup_form.html +++ b/modules/member/m.skins/rx_prn/signup_form.html @@ -59,7 +59,7 @@ - {$editor} + {$editor|noescape}
    {$lang->allow_mailing}
    diff --git a/modules/member/member.admin.controller.php b/modules/member/member.admin.controller.php index 0d08a6ca1..b6f865e5b 100644 --- a/modules/member/member.admin.controller.php +++ b/modules/member/member.admin.controller.php @@ -26,7 +26,7 @@ class memberAdminController extends member $logged_info = Context::get('logged_info'); if($logged_info->is_admin != 'Y' || !checkCSRF()) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $args = Context::gets('member_srl','email_address','find_account_answer', 'allow_mailing','allow_message','denied','is_admin','description','group_srl_list','limit_date'); @@ -128,21 +128,21 @@ class memberAdminController extends member $signature = Context::get('signature'); $oMemberController->putSignature($args->member_srl, $signature); - $profile_image = $_FILES['profile_image']; + $profile_image = Context::get('profile_image'); if(is_uploaded_file($profile_image['tmp_name'])) { $output = $oMemberController->insertProfileImage($args->member_srl, $profile_image['tmp_name']); if(!$output->toBool()) return $output; } - $image_mark = $_FILES['image_mark']; + $image_mark = Context::get('image_mark'); if(is_uploaded_file($image_mark['tmp_name'])) { $output = $oMemberController->insertImageMark($args->member_srl, $image_mark['tmp_name']); if(!$output->toBool()) return $output; } - $image_name = $_FILES['image_name']; + $image_name = Context::get('image_name'); if (is_uploaded_file($image_name['tmp_name'])) { $output = $oMemberController->insertImageName($args->member_srl, $image_name['tmp_name']); @@ -741,7 +741,7 @@ class memberAdminController extends member // Check ID duplicated if (Context::isReservedWord($args->column_name)) { - return $this->setError('msg_column_id_not_available'); + throw new Rhymix\Framework\Exception('msg_column_id_not_available'); } $oMemberModel = getModel('member'); $config = $oMemberModel->getMemberConfig(); @@ -750,7 +750,7 @@ class memberAdminController extends member if($item->name == $args->column_name) { if($args->member_join_form_srl && $args->member_join_form_srl == $item->member_join_form_srl) continue; - return $this->setError('msg_column_id_not_available'); + throw new Rhymix\Framework\Exception('msg_column_id_not_available'); } } // Fix if member_join_form_srl exists. Add if not exists. @@ -961,7 +961,7 @@ class memberAdminController extends member function procMemberAdminDeleteMembers() { $target_member_srls = Context::get('target_member_srls'); - if(!$target_member_srls) return $this->setError('msg_invalid_request'); + if(!$target_member_srls) throw new Rhymix\Framework\Exceptions\InvalidRequest; $member_srls = explode(',', $target_member_srls); $oMemberController = getController('member'); @@ -985,7 +985,7 @@ class memberAdminController extends member function procMemberAdminUpdateMembersGroup() { $member_srl = Context::get('member_srl'); - if(!$member_srl) return $this->setError('msg_invalid_request'); + if(!$member_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; $member_srls = explode(',',$member_srl); $group_srl = Context::get('group_srls'); @@ -1258,7 +1258,7 @@ class memberAdminController extends member function updateGroup($args) { if(!$args->site_srl) $args->site_srl = 0; - if(!$args->group_srl) return $this->setError('lang->msg_not_founded'); + if(!$args->group_srl) throw new Rhymix\Framework\Exceptions\TargetNotFound; // Call trigger (before) $trigger_output = ModuleHandler::triggerCall('member.updateGroup', 'before', $args); @@ -1302,8 +1302,8 @@ class memberAdminController extends member $columnList = array('group_srl', 'is_default'); $group_info = $oMemberModel->getGroup($group_srl, $columnList); - if(!$group_info) return $this->setError('lang->msg_not_founded'); - if($group_info->is_default == 'Y') return $this->setError('msg_not_delete_default'); + if(!$group_info) throw new Rhymix\Framework\Exceptions\TargetNotFound; + if($group_info->is_default == 'Y') throw new Rhymix\Framework\Exception('msg_not_delete_default'); // Call trigger (before) $trigger_output = ModuleHandler::triggerCall('member.deleteGroup', 'before', $group_info); diff --git a/modules/member/member.controller.php b/modules/member/member.controller.php index aef2d38d5..64afc68e7 100644 --- a/modules/member/member.controller.php +++ b/modules/member/member.controller.php @@ -30,7 +30,7 @@ class memberController extends member if(!$user_id && !$password && Context::getRequestMethod() == 'GET') { $this->setRedirectUrl(getNotEncodedUrl('')); - return $this->setError('null_user_id'); + throw new Rhymix\Framework\Exception('null_user_id'); } // Variables @@ -42,8 +42,8 @@ class memberController extends member if(!$keep_signed) $keep_signed = Context::get('keep_signed'); // Return an error when id and password doesn't exist - if(!$user_id) return $this->setError('null_user_id'); - if(!$password) return $this->setError('null_password'); + if(!$user_id) throw new Rhymix\Framework\Exception('null_user_id'); + if(!$password) throw new Rhymix\Framework\Exception('null_password'); $output = $this->doLogin($user_id, $password, $keep_signed=='Y'?true:false); if (!$output->toBool()) return $output; @@ -122,7 +122,7 @@ class memberController extends member $document_srl = (int) (Context::get('document_srl') ?: Context::get('target_srl')); if(!$document_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $oDocumentModel = getModel('document'); @@ -131,7 +131,7 @@ class memberController extends member // Check document if(!$oDocument->isAccessible()) { - return $this->setError('msg_is_secret'); + throw new Rhymix\Framework\Exception('msg_is_secret'); } $oModuleModel = getModel('module'); @@ -143,19 +143,19 @@ class memberController extends member // Check access to module of the document if(!$grant->access) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } // Check grant to module of the document if(isset($grant->list) && isset($grant->view) && (!$grant->list || !$grant->view)) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } // Check consultation option if(isset($grant->consultation_read) && $module_info->consultation == 'Y' && !$grant->consultation_read && !$oDocument->isGranted()) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } // Find default scrap folder @@ -187,7 +187,7 @@ class memberController extends member $output = executeQuery('member.getScrapDocument', $args); if($output->data->count) { - return $this->setError('msg_alreay_scrapped'); + throw new Rhymix\Framework\Exception('msg_alreay_scrapped'); } // Insert @@ -206,11 +206,12 @@ class memberController extends member function procMemberDeleteScrap() { // Check login information - if(!Context::get('is_logged')) return $this->setError('msg_not_logged'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\MustLogin; $logged_info = Context::get('logged_info'); $document_srl = (int)Context::get('document_srl'); - if(!$document_srl) return $this->setError('msg_invalid_request'); + if(!$document_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; + // Variables $args = new stdClass; $args->member_srl = $logged_info->member_srl; @@ -226,14 +227,14 @@ class memberController extends member function procMemberMoveScrapFolder() { // Check login information - if(!Context::get('is_logged')) return $this->setError('msg_not_logged'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\MustLogin; $logged_info = Context::get('logged_info'); $document_srl = (int)Context::get('document_srl'); $folder_srl = (int)Context::get('folder_srl'); if(!$document_srl || !$folder_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Check that the target folder exists and belongs to member @@ -243,7 +244,7 @@ class memberController extends member $output = executeQueryArray('member.getScrapFolderList', $args); if(!count($output->data)) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Move @@ -262,7 +263,7 @@ class memberController extends member function procMemberInsertScrapFolder() { // Check login information - if(!Context::get('is_logged')) return $this->setError('msg_not_logged'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\MustLogin; $logged_info = Context::get('logged_info'); // Get new folder name @@ -270,7 +271,7 @@ class memberController extends member $folder_name = escape(trim(utf8_normalize_spaces($folder_name))); if(!$folder_name) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Check existing folder with same name @@ -280,7 +281,7 @@ class memberController extends member $output = executeQueryArray('member.getScrapFolderList', $args); if(count($output->data) || $folder_name === lang('default_folder')) { - return $this->setError('msg_folder_alreay_exists'); + throw new Rhymix\Framework\Exception('msg_folder_alreay_exists'); } // Create folder @@ -301,7 +302,7 @@ class memberController extends member function procMemberRenameScrapFolder() { // Check login information - if(!Context::get('is_logged')) return $this->setError('msg_not_logged'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\MustLogin; $logged_info = Context::get('logged_info'); // Get new folder name @@ -310,7 +311,7 @@ class memberController extends member $folder_name = escape(trim(utf8_normalize_spaces($folder_name))); if(!$folder_srl || !$folder_name) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Check that the original folder exists and belongs to member @@ -320,11 +321,11 @@ class memberController extends member $output = executeQueryArray('member.getScrapFolderList', $args); if(!count($output->data)) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } if(array_first($output->data)->name === '/DEFAULT/') { - return $this->setError('msg_folder_is_default'); + throw new Rhymix\Framework\Exception('msg_folder_is_default'); } // Check existing folder with same name @@ -335,7 +336,7 @@ class memberController extends member $output = executeQueryArray('member.getScrapFolderList', $args); if(count($output->data) || $folder_name === lang('default_folder')) { - return $this->setError('msg_folder_alreay_exists'); + throw new Rhymix\Framework\Exception('msg_folder_alreay_exists'); } // Rename folder @@ -353,14 +354,14 @@ class memberController extends member function procMemberDeleteScrapFolder() { // Check login information - if(!Context::get('is_logged')) return $this->setError('msg_not_logged'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\MustLogin; $logged_info = Context::get('logged_info'); // Get folder_srl to delete $folder_srl = intval(Context::get('folder_srl')); if(!$folder_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Check that the folder exists and belongs to member @@ -370,11 +371,11 @@ class memberController extends member $output = executeQueryArray('member.getScrapFolderList', $args); if(!count($output->data)) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } if(array_first($output->data)->name === '/DEFAULT/') { - return $this->setError('msg_folder_is_default'); + throw new Rhymix\Framework\Exception('msg_folder_is_default'); } // Check that the folder is empty @@ -384,7 +385,7 @@ class memberController extends member $output = executeQueryArray('member.getScrapDocumentList', $args); if(count($output->data)) { - return $this->setError('msg_folder_not_empty'); + throw new Rhymix\Framework\Exception('msg_folder_not_empty'); } // Delete folder @@ -436,22 +437,22 @@ class memberController extends member function procMemberDeleteSavedDocument() { // Check login information - if(!Context::get('is_logged')) return $this->setError('msg_not_logged'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\MustLogin; $logged_info = Context::get('logged_info'); $document_srl = (int)Context::get('document_srl'); - if(!$document_srl) return $this->setError('msg_invalid_request'); + if(!$document_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; $oDocumentModel = getModel('document'); $oDocument = $oDocumentModel->getDocument($document_srl); if ($oDocument->get('member_srl') != $logged_info->member_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $configStatusList = $oDocumentModel->getStatusList(); if ($oDocument->get('status') != $configStatusList['temp']) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Variables @@ -465,14 +466,14 @@ class memberController extends member function procMemberDeleteAutologin() { // Check login information - if(!Context::get('is_logged')) return $this->setError('msg_not_logged'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\MustLogin; $logged_info = Context::get('logged_info'); $autologin_id = intval(Context::get('autologin_id')); $autologin_key = Context::get('autologin_key'); if (!$autologin_id || !$autologin_key) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $args = new stdClass; @@ -575,7 +576,11 @@ class memberController extends member */ function procMemberInsert() { - if (Context::getRequestMethod () == "GET") return new BaseObject (-1, "msg_invalid_request"); + if (Context::getRequestMethod() == 'GET') + { + throw new Rhymix\Framework\Exceptions\SecurityViolation; + } + $oMemberModel = &getModel ('member'); $config = $oMemberModel->getMemberConfig(); @@ -583,7 +588,7 @@ class memberController extends member $trigger_output = ModuleHandler::triggerCall ('member.procMemberInsert', 'before', $config); if(!$trigger_output->toBool ()) return $trigger_output; // Check if an administrator allows a membership - if($config->enable_join != 'Y') return $this->stop ('msg_signup_disabled'); + if($config->enable_join != 'Y') throw new Rhymix\Framework\Exceptions\FeatureDisabled('msg_signup_disabled'); // Check if the user accept the license terms (only if terms exist) $accept_agreement = Context::get('accept_agreement'); @@ -591,7 +596,7 @@ class memberController extends member { if($agreement->type === 'required' && $accept_agreement !== 'Y' && $accept_agreement[$i] !== 'Y') { - return $this->setError('msg_accept_agreement'); + throw new Rhymix\Framework\Exception('msg_accept_agreement'); } } @@ -646,7 +651,7 @@ class memberController extends member if(!$oMemberModel->checkPasswordStrength($args->password, $config->password_strength)) { $message = lang('about_password_strength'); - return $this->setError($message[$config->password_strength]); + throw new Rhymix\Framework\Exception($message[$config->password_strength]); } // Remove some unnecessary variables from all the vars @@ -687,19 +692,19 @@ class memberController extends member if(!$output->toBool()) return $output; // insert ProfileImage, ImageName, ImageMark - $profile_image = $_FILES['profile_image']; + $profile_image = Context::get('profile_image'); if(is_uploaded_file($profile_image['tmp_name'])) { $this->insertProfileImage($args->member_srl, $profile_image['tmp_name']); } - $image_mark = $_FILES['image_mark']; + $image_mark = Context::get('image_mark'); if(is_uploaded_file($image_mark['tmp_name'])) { $this->insertImageMark($args->member_srl, $image_mark['tmp_name']); } - $image_name = $_FILES['image_name']; + $image_name = Context::get('image_name'); if(is_uploaded_file($image_name['tmp_name'])) { $this->insertImageName($args->member_srl, $image_name['tmp_name']); @@ -779,19 +784,19 @@ class memberController extends member { if($_SESSION['rechecked_password_step'] != 'INPUT_PASSWORD') { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } if(!Context::get('is_logged')) { - return $this->stop('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $password = Context::get('password'); if(!$password) { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $oMemberModel = getModel('member'); @@ -805,7 +810,7 @@ class memberController extends member // Verify the current password if(!$oMemberModel->isValidPassword($member_info->password, $password)) { - return $this->setError('invalid_password'); + throw new Rhymix\Framework\Exception('invalid_password'); } $_SESSION['rechecked_password_step'] = 'VALIDATE_PASSWORD'; @@ -830,12 +835,12 @@ class memberController extends member { if(!Context::get('is_logged')) { - return $this->stop('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } if($_SESSION['rechecked_password_step'] != 'INPUT_DATA') { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } unset($_SESSION['rechecked_password_step']); @@ -922,19 +927,19 @@ class memberController extends member $output = $this->updateMember($args); if(!$output->toBool()) return $output; - $profile_image = $_FILES['profile_image']; + $profile_image = Context::get('profile_image'); if(is_uploaded_file($profile_image['tmp_name'])) { $this->insertProfileImage($args->member_srl, $profile_image['tmp_name']); } - $image_mark = $_FILES['image_mark']; + $image_mark = Context::get('image_mark'); if(is_uploaded_file($image_mark['tmp_name'])) { $this->insertImageMark($args->member_srl, $image_mark['tmp_name']); } - $image_name = $_FILES['image_name']; + $image_name = Context::get('image_name'); if(is_uploaded_file($image_name['tmp_name'])) { $this->insertImageName($args->member_srl, $image_name['tmp_name']); @@ -969,7 +974,7 @@ class memberController extends member */ function procMemberModifyPassword() { - if(!Context::get('is_logged')) return $this->stop('msg_not_logged'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\MustLogin; // Extract the necessary information in advance $current_password = trim(Context::get('current_password')); $password = trim(Context::get('password1')); @@ -983,10 +988,10 @@ class memberController extends member $member_info = $oMemberModel->getMemberInfoByMemberSrl($member_srl, 0, $columnList); // Verify the cuttent password - if(!$oMemberModel->isValidPassword($member_info->password, $current_password, $member_srl)) return $this->setError('invalid_password'); + if(!$oMemberModel->isValidPassword($member_info->password, $current_password, $member_srl)) throw new Rhymix\Framework\Exception('invalid_password'); // Check if a new password is as same as the previous password - if($current_password == $password) return $this->setError('invalid_new_password'); + if($current_password == $password) throw new Rhymix\Framework\Exception('invalid_new_password'); // Execute insert or update depending on the value of member_srl $args = new stdClass; @@ -1017,7 +1022,7 @@ class memberController extends member */ function procMemberLeave() { - if(!Context::get('is_logged')) return $this->stop('msg_not_logged'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\MustLogin; // Extract the necessary information in advance $password = trim(Context::get('password')); // Get information of logged-in user @@ -1029,7 +1034,7 @@ class memberController extends member $columnList = array('member_srl', 'password'); $member_info = $oMemberModel->getMemberInfoByMemberSrl($member_srl, 0, $columnList); // Verify the cuttent password - if(!$oMemberModel->isValidPassword($member_info->password, $password)) return $this->setError('invalid_password'); + if(!$oMemberModel->isValidPassword($member_info->password, $password)) throw new Rhymix\Framework\Exception('invalid_password'); $output = $this->deleteMember($member_srl); if(!$output->toBool()) return $output; @@ -1051,18 +1056,18 @@ class memberController extends member function procMemberInsertProfileImage() { // Check if the file is successfully uploaded - $file = $_FILES['profile_image']; - if(!is_uploaded_file($file['tmp_name'])) return $this->stop('msg_not_uploaded_profile_image'); + $file = Context::get('profile_image'); + if(!is_uploaded_file($file['tmp_name'])) throw new Rhymix\Framework\Exception('msg_not_uploaded_profile_image'); // Ignore if member_srl is invalid or doesn't exist. $member_srl = Context::get('member_srl'); - if(!$member_srl) return $this->stop('msg_not_uploaded_profile_image'); + if(!$member_srl) throw new Rhymix\Framework\Exception('msg_not_uploaded_profile_image'); $logged_info = Context::get('logged_info'); - if($logged_info->is_admin != 'Y' && $logged_info->member_srl != $member_srl) return $this->stop('msg_not_uploaded_profile_image'); + if($logged_info->is_admin != 'Y' && $logged_info->member_srl != $member_srl) throw new Rhymix\Framework\Exception('msg_not_uploaded_profile_image'); // Return if member module is set not to use an image name or the user is not an administrator ; $oMemberModel = getModel('member'); $config = $oMemberModel->getMemberConfig(); - if($logged_info->is_admin != 'Y' && $config->profile_image != 'Y') return $this->stop('msg_not_uploaded_profile_image'); + if($logged_info->is_admin != 'Y' && $config->profile_image != 'Y') throw new Rhymix\Framework\Exception('msg_not_uploaded_profile_image'); $output = $this->insertProfileImage($member_srl, $file['tmp_name']); if(!$output->toBool()) return $output; @@ -1099,7 +1104,7 @@ class memberController extends member elseif(IMAGETYPE_GIF == $type) $ext = 'gif'; else { - return $this->stop('msg_not_uploaded_profile_image'); + throw new Rhymix\Framework\Exception('msg_not_uploaded_profile_image'); } $target_path = sprintf('files/member_extra_info/profile_image/%s', getNumberingPath($member_srl)); @@ -1118,7 +1123,7 @@ class memberController extends member if($max_filesize && $filesize > ($max_filesize * 1024)) { FileHandler::removeFile($temp_filename); - return $this->stop(implode(' ' , array( + throw new Rhymix\Framework\Exception(implode(' ' , array( Context::getLang('msg_not_uploaded_profile_image'), Context::getLang('msg_exceeds_limit_size') ))); @@ -1134,7 +1139,7 @@ class memberController extends member $filesize = filesize($target_file); if($max_filesize && $filesize > ($max_filesize * 1024)) { - return $this->stop(implode(' ' , array( + throw new Rhymix\Framework\Exception(implode(' ' , array( Context::getLang('msg_not_uploaded_profile_image'), Context::getLang('msg_exceeds_limit_size') ))); @@ -1156,18 +1161,18 @@ class memberController extends member function procMemberInsertImageName() { // Check if the file is successfully uploaded - $file = $_FILES['image_name']; - if(!is_uploaded_file($file['tmp_name'])) return $this->stop('msg_not_uploaded_image_name'); + $file = Context::get('image_name'); + if(!is_uploaded_file($file['tmp_name'])) throw new Rhymix\Framework\Exception('msg_not_uploaded_image_name'); // Ignore if member_srl is invalid or doesn't exist. $member_srl = Context::get('member_srl'); - if(!$member_srl) return $this->stop('msg_not_uploaded_image_name'); + if(!$member_srl) throw new Rhymix\Framework\Exception('msg_not_uploaded_image_name'); $logged_info = Context::get('logged_info'); - if($logged_info->is_admin != 'Y' && $logged_info->member_srl != $member_srl) return $this->stop('msg_not_uploaded_image_name'); + if($logged_info->is_admin != 'Y' && $logged_info->member_srl != $member_srl) throw new Rhymix\Framework\Exception('msg_not_uploaded_image_name'); // Return if member module is set not to use an image name or the user is not an administrator ; $oMemberModel = getModel('member'); $config = $oMemberModel->getMemberConfig(); - if($logged_info->is_admin != 'Y' && $config->image_name != 'Y') return $this->stop('msg_not_uploaded_image_name'); + if($logged_info->is_admin != 'Y' && $config->image_name != 'Y') throw new Rhymix\Framework\Exception('msg_not_uploaded_image_name'); $output = $this->insertImageName($member_srl, $file['tmp_name']); if(!$output->toBool()) return $output; @@ -1218,7 +1223,7 @@ class memberController extends member if($max_filesize && $filesize > ($max_filesize * 1024)) { FileHandler::removeFile($temp_filename); - return $this->stop(implode(' ' , array( + throw new Rhymix\Framework\Exception(implode(' ' , array( Context::getLang('msg_not_uploaded_image_name'), Context::getLang('msg_exceeds_limit_size') ))); @@ -1234,7 +1239,7 @@ class memberController extends member $filesize = filesize($target_file); if($max_filesize && $filesize > ($max_filesize * 1024)) { - return $this->stop(implode(' ' , array( + throw new Rhymix\Framework\Exception(implode(' ' , array( Context::getLang('msg_not_uploaded_image_name'), Context::getLang('msg_exceeds_limit_size') ))); @@ -1307,18 +1312,18 @@ class memberController extends member function procMemberInsertImageMark() { // Check if the file is successfully uploaded - $file = $_FILES['image_mark']; - if(!is_uploaded_file($file['tmp_name'])) return $this->stop('msg_not_uploaded_image_mark'); + $file = Context::get('image_mark'); + if(!is_uploaded_file($file['tmp_name'])) throw new Rhymix\Framework\Exception('msg_not_uploaded_image_mark'); // Ignore if member_srl is invalid or doesn't exist. $member_srl = Context::get('member_srl'); - if(!$member_srl) return $this->stop('msg_not_uploaded_image_mark'); + if(!$member_srl) throw new Rhymix\Framework\Exception('msg_not_uploaded_image_mark'); $logged_info = Context::get('logged_info'); - if($logged_info->is_admin != 'Y' && $logged_info->member_srl != $member_srl) return $this->stop('msg_not_uploaded_image_mark'); + if($logged_info->is_admin != 'Y' && $logged_info->member_srl != $member_srl) throw new Rhymix\Framework\Exception('msg_not_uploaded_image_mark'); // Membership in the images mark the module using the ban was set by an administrator or return; $oMemberModel = getModel('member'); $config = $oMemberModel->getMemberConfig(); - if($logged_info->is_admin != 'Y' && $config->image_mark != 'Y') return $this->stop('msg_not_uploaded_image_mark'); + if($logged_info->is_admin != 'Y' && $config->image_mark != 'Y') throw new Rhymix\Framework\Exception('msg_not_uploaded_image_mark'); $this->insertImageMark($member_srl, $file['tmp_name']); if(!$output->toBool()) return $output; @@ -1365,7 +1370,7 @@ class memberController extends member if($max_filesize && $filesize > ($max_filesize * 1024)) { FileHandler::removeFile($temp_filename); - return $this->stop(implode(' ' , array( + throw new Rhymix\Framework\Exception(implode(' ' , array( Context::getLang('msg_not_uploaded_group_image_mark'), Context::getLang('msg_exceeds_limit_size') ))); @@ -1381,7 +1386,7 @@ class memberController extends member if($max_filesize && $filesize > ($max_filesize * 1024)) { FileHandler::removeFile($target_file); - return $this->stop(implode(' ' , array( + throw new Rhymix\Framework\Exception(implode(' ' , array( Context::getLang('msg_not_uploaded_group_image_mark'), Context::getLang('msg_exceeds_limit_size') ))); @@ -1428,14 +1433,14 @@ class memberController extends member function procMemberFindAccount() { $email_address = Context::get('email_address'); - if(!$email_address) return $this->setError('msg_invalid_request'); + if(!$email_address) throw new Rhymix\Framework\Exceptions\InvalidRequest; $oMemberModel = getModel('member'); $oModuleModel = getModel('module'); // Check if a member having the same email address exists $member_srl = $oMemberModel->getMemberSrlByEmailAddress($email_address); - if(!$member_srl) return $this->setError('msg_email_not_exists'); + if(!$member_srl) throw new Rhymix\Framework\Exception('msg_email_not_exists'); // Get information of the member $columnList = array('denied', 'member_srl', 'user_id', 'user_name', 'email_address', 'nick_name'); @@ -1447,7 +1452,7 @@ class memberController extends member $chk_args = new stdClass; $chk_args->member_srl = $member_info->member_srl; $output = executeQuery('member.chkAuthMail', $chk_args); - if($output->toBool() && $output->data->count != '0') return $this->setError('msg_user_not_confirmed'); + if($output->toBool() && $output->data->count != '0') throw new Rhymix\Framework\Exception('msg_user_not_confirmed'); } // Insert data into the authentication DB @@ -1528,7 +1533,7 @@ class memberController extends member */ function procMemberFindAccountByQuestion() { - return $this->setError('msg_question_not_allowed'); + throw new Rhymix\Framework\Exception('msg_question_not_allowed'); } /** @@ -1547,7 +1552,7 @@ class memberController extends member if(!$member_srl || !$auth_key) { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } // Call a trigger (before) @@ -1557,7 +1562,7 @@ class memberController extends member $trigger_output = ModuleHandler::triggerCall('member.procMemberAuthAccount', 'before', $trigger_obj); if(!$trigger_output->toBool()) { - return $this->stop($trigger_output->getMessage()); + return $trigger_output; } // Test logs for finding password by user_id and authkey @@ -1569,13 +1574,13 @@ class memberController extends member if(!$output->toBool() || $output->data->auth_key !== $auth_key) { executeQuery('member.deleteAuthMail', $args); - return $this->stop('msg_invalid_auth_key'); + throw new Rhymix\Framework\Exception('msg_invalid_auth_key'); } if(ztime($output->data->regdate) < time() - (86400 * 3)) { executeQuery('member.deleteAuthMail', $args); - return $this->stop('msg_expired_auth_key'); + throw new Rhymix\Framework\Exception('msg_expired_auth_key'); } // Back up the value of $output->data->is_register @@ -1594,7 +1599,7 @@ class memberController extends member $output = executeQuery('member.updateMemberPassword', $args); if(!$output->toBool()) { - return $this->stop($output->getMessage()); + return $output; } // Remove all values having the member_srl from authentication table @@ -1621,14 +1626,14 @@ class memberController extends member { // Get an email_address $email_address = Context::get('email_address'); - if(!$email_address) return $this->setError('msg_invalid_request'); + if(!$email_address) throw new Rhymix\Framework\Exceptions\InvalidRequest; // Log test by using email_address $oMemberModel = getModel('member'); $args = new stdClass; $args->email_address = $email_address; $memberSrl = $oMemberModel->getMemberSrlByEmailAddress($email_address); - if(!$memberSrl) return $this->setError('msg_not_exists_member'); + if(!$memberSrl) throw new Rhymix\Framework\Exception('msg_not_exists_member'); $columnList = array('member_srl', 'user_id', 'user_name', 'nick_name', 'email_address'); $member_info = $oMemberModel->getMemberInfoByMemberSrl($memberSrl, 0, $columnList); @@ -1642,12 +1647,12 @@ class memberController extends member $chk_args = new stdClass; $chk_args->member_srl = $member_info->member_srl; $output = executeQuery('member.chkAuthMail', $chk_args); - if($output->toBool() && $output->data->count == '0') return $this->setError('msg_invalid_request'); + if($output->toBool() && $output->data->count == '0') throw new Rhymix\Framework\Exceptions\InvalidRequest; $auth_args = new stdClass; $auth_args->member_srl = $member_info->member_srl; $output = executeQueryArray('member.getAuthMailInfo', $auth_args); - if(!$output->data || !$output->data[0]->auth_key) return $this->setError('msg_invalid_request'); + if(!$output->data || !$output->data[0]->auth_key) throw new Rhymix\Framework\Exceptions\InvalidRequest; $auth_info = $output->data[0]; // Update the regdate of authmail entry @@ -1711,21 +1716,37 @@ class memberController extends member if(!$memberInfo) { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $newEmail = Context::get('email_address'); if(!$newEmail) { - return $this->stop('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $oMemberModel = getModel('member'); $member_srl = $oMemberModel->getMemberSrlByEmailAddress($newEmail); if($member_srl) { - return $this->setError('msg_exists_email_address'); + throw new Rhymix\Framework\Exception('msg_exists_email_address'); + } + + // Check managed Email Host + if($oMemberModel->isDeniedEmailHost($newEmail)) + { + $config = $oMemberModel->getMemberConfig(); + $emailhost_check = $config->emailhost_check; + + $managed_email_host = lang('managed_email_host'); + $email_hosts = $oMemberModel->getManagedEmailHosts(); + foreach ($email_hosts as $host) + { + $hosts[] = $host->email_host; + } + $message = sprintf($managed_email_host[$emailhost_check], implode(', ',$hosts), 'id@' . implode(', id@', $hosts)); + throw new Rhymix\Framework\Exception($message); } // remove all key by member_srl @@ -1745,7 +1766,7 @@ class memberController extends member $output = executeQuery('member.updateMemberEmailAddress', $args); if(!$output->toBool()) { - return $this->stop($output->getMessage()); + return $output; } $this->_clearMemberCache($args->member_srl); @@ -1840,7 +1861,7 @@ class memberController extends member { $site_module_info = Context::get('site_module_info'); $logged_info = Context::get('logged_info'); - if(!$site_module_info->site_srl || !Context::get('is_logged') || count($logged_info->group_srl_list) ) return $this->setError('msg_invalid_request'); + if(!$site_module_info->site_srl || !Context::get('is_logged') || count($logged_info->group_srl_list) ) throw new Rhymix\Framework\Exceptions\InvalidRequest; $oMemberModel = getModel('member'); $columnList = array('site_srl', 'group_srl', 'title'); @@ -1859,7 +1880,7 @@ class memberController extends member { $site_module_info = Context::get('site_module_info'); $logged_info = Context::get('logged_info'); - if(!$site_module_info->site_srl || !Context::get('is_logged') || count($logged_info->group_srl_list) ) return $this->setError('msg_invalid_request'); + if(!$site_module_info->site_srl || !Context::get('is_logged') || count($logged_info->group_srl_list) ) throw new Rhymix\Framework\Exceptions\InvalidRequest; $args = new stdClass; $args->site_srl= $site_module_info->site_srl; @@ -2396,11 +2417,11 @@ class memberController extends member list($args->email_id, $args->email_host) = explode('@', $args->email_address); // Sanitize user ID, username, nickname, homepage, blog - $args->user_id = htmlspecialchars($args->user_id, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); - $args->user_name = htmlspecialchars($args->user_name, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); - $args->nick_name = htmlspecialchars($args->nick_name, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); - $args->homepage = htmlspecialchars($args->homepage, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); - $args->blog = htmlspecialchars($args->blog, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + $args->user_id = escape($args->user_id, false); + $args->user_name = escape($args->user_name, false); + $args->nick_name = escape($args->nick_name, false); + $args->homepage = escape($args->homepage, false); + $args->blog = escape($args->blog, false); if($args->homepage && !preg_match("/^[a-z]+:\/\//i",$args->homepage)) $args->homepage = 'http://'.$args->homepage; if($args->blog && !preg_match("/^[a-z]+:\/\//i",$args->blog)) $args->blog = 'http://'.$args->blog; @@ -2624,16 +2645,16 @@ class memberController extends member unset($args->denied); if($logged_info->member_srl != $args->member_srl && $is_admin == false) { - return $this->stop('msg_invalid_request'); + return new BaseObject(-1, 'msg_invalid_request'); } } // Sanitize user ID, username, nickname, homepage, blog - if($args->user_id) $args->user_id = htmlspecialchars($args->user_id, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); - $args->user_name = htmlspecialchars($args->user_name, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); - $args->nick_name = htmlspecialchars($args->nick_name, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); - $args->homepage = htmlspecialchars($args->homepage, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); - $args->blog = htmlspecialchars($args->blog, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + if($args->user_id) $args->user_id = escape($args->user_id, false); + $args->user_name = escape($args->user_name, false); + $args->nick_name = escape($args->nick_name, false); + $args->homepage = escape($args->homepage, false); + $args->blog = escape($args->blog, false); if($args->homepage && !preg_match("/^[a-z]+:\/\//is",$args->homepage)) $args->homepage = 'http://'.$args->homepage; if($args->blog && !preg_match("/^[a-z]+:\/\//is",$args->blog)) $args->blog = 'http://'.$args->blog; @@ -2696,7 +2717,7 @@ class memberController extends member } // Check managed Email Host - if($logged_info->is_admin !== 'Y' && $oMemberModel->isDeniedEmailHost($args->email_address)) + if($logged_info->is_admin !== 'Y' && $logged_info->email_address !== $args->email_address && $oMemberModel->isDeniedEmailHost($args->email_address)) { $emailhost_check = $config->emailhost_check; @@ -3041,12 +3062,12 @@ class memberController extends member function procMemberModifyEmailAddress() { - if(!Context::get('is_logged')) return $this->setError('msg_not_logged'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\MustLogin; $member_info = Context::get('logged_info'); $newEmail = Context::get('email_address'); - if(!$newEmail) return $this->setError('msg_invalid_request'); + if(!$newEmail) throw new Rhymix\Framework\Exceptions\InvalidRequest; $oMemberModel = getModel('member'); // Check managed Email Host @@ -3062,16 +3083,16 @@ class memberController extends member $hosts[] = $host->email_host; } $message = sprintf($managed_email_host[$emailhost_check],implode(', ',$hosts),'id@'.implode(', id@',$hosts)); - return $this->setError($message); + throw new Rhymix\Framework\Exception($message); } // Check if the e-mail address is already registered $member_srl = $oMemberModel->getMemberSrlByEmailAddress($newEmail); - if($member_srl) return $this->setError('msg_exists_email_address'); + if($member_srl) throw new Rhymix\Framework\Exception('msg_exists_email_address'); if($_SESSION['rechecked_password_step'] != 'INPUT_DATA') { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } unset($_SESSION['rechecked_password_step']); @@ -3129,7 +3150,7 @@ class memberController extends member { $member_srl = Context::get('member_srl'); $auth_key = Context::get('auth_key'); - if(!$member_srl || !$auth_key) return $this->stop('msg_invalid_request'); + if(!$member_srl || !$auth_key) throw new Rhymix\Framework\Exceptions\InvalidRequest; // Test logs for finding password by user_id and authkey $args = new stdClass; @@ -3139,7 +3160,7 @@ class memberController extends member if(!$output->toBool() || $output->data->auth_key != $auth_key) { if(strlen($output->data->auth_key) !== strlen($auth_key)) executeQuery('member.deleteAuthChangeEmailAddress', $args); - return $this->stop('msg_invalid_modify_email_auth_key'); + throw new Rhymix\Framework\Exception('msg_invalid_modify_email_auth_key'); } $newEmail = $output->data->user_id; @@ -3147,7 +3168,7 @@ class memberController extends member list($args->email_id, $args->email_host) = explode('@', $newEmail); $output = executeQuery('member.updateMemberEmailAddress', $args); - if(!$output->toBool()) return $this->stop($output->getMessage()); + if(!$output->toBool()) return $output; // Remove all values having the member_srl and new_password equal to 'XE_change_emaill_address' from authentication table executeQuery('member.deleteAuthChangeEmailAddress',$args); @@ -3227,7 +3248,7 @@ class memberController extends member **/ function procMemberSpammerManage() { - if(!Context::get('is_logged')) return $this->setError('msg_not_permitted'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\NotPermitted; $logged_info = Context::get('logged_info'); $member_srl = Context::get('member_srl'); @@ -3244,7 +3265,7 @@ class memberController extends member $module_info = $oModuleModel->getModuleInfoByModuleSrl($module_srl, $columnList); $grant = $oModuleModel->getGrant($module_info, $logged_info); - if(!$grant->manager) return $this->setError('msg_not_permitted'); + if(!$grant->manager) throw new Rhymix\Framework\Exceptions\NotPermitted; $proc_msg = ""; diff --git a/modules/member/member.model.php b/modules/member/member.model.php index b887f9d82..7b3f5900d 100644 --- a/modules/member/member.model.php +++ b/modules/member/member.model.php @@ -178,7 +178,7 @@ class memberModel extends member $oCommunicationModel = getModel('communication'); if($logged_info->is_admin == 'Y' || $oCommunicationModel->isFriend($member_info->member_srl)) { - $url = 'mailto:'.htmlspecialchars($member_info->email_address, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + $url = 'mailto:'.escape($member_info->email_address); $oMemberController->addMemberPopupMenu($url,'cmd_send_email',$icon_path); } } @@ -210,13 +210,13 @@ class memberModel extends member // View homepage info if($member_info->homepage && $homepage_is_public) { - $oMemberController->addMemberPopupMenu(htmlspecialchars($member_info->homepage, ENT_COMPAT | ENT_HTML401, 'UTF-8', false), 'homepage', '', 'blank'); + $oMemberController->addMemberPopupMenu(escape($member_info->homepage, false), 'homepage', '', 'blank'); } // View blog info if($member_info->blog && $blog_is_public) { - $oMemberController->addMemberPopupMenu(htmlspecialchars($member_info->blog, ENT_COMPAT | ENT_HTML401, 'UTF-8', false), 'blog', '', 'blank'); + $oMemberController->addMemberPopupMenu(escape($member_info->blog, false), 'blog', '', 'blank'); } // Call a trigger (after) @@ -330,7 +330,10 @@ class memberModel extends member } $member_info = $this->arrangeMemberInfo($output->data, $site_srl); - Rhymix\Framework\Cache::set($cache_key, $member_info); + if($output->toBool()) + { + Rhymix\Framework\Cache::set($cache_key, $member_info); + } } } @@ -364,8 +367,14 @@ class memberModel extends member { foreach($extra_vars as $key => $val) { - if(!is_array($val) && strpos($val, '|@|') !== FALSE) $val = explode('|@|', $val); - if(!$info->{$key}) $info->{$key} = $val; + if(!is_array($val) && !is_object($val) && strpos($val, '|@|') !== FALSE) + { + $val = explode('|@|', $val); + } + if(!isset($info->{$key})) + { + $info->{$key} = $val; + } } } @@ -492,7 +501,10 @@ class memberModel extends member $group_list[$default_group->group_srl] = $default_group->title; } //insert in cache - Rhymix\Framework\Cache::set($cache_key, $group_list, 0, true); + if ($output->toBool()) + { + Rhymix\Framework\Cache::set($cache_key, $group_list, 0, true); + } } if(!$group_list) return array(); @@ -539,7 +551,10 @@ class memberModel extends member $args->site_srl = $site_srl; $output = executeQuery('member.getDefaultGroup', $args); $default_group = $output->data; - Rhymix\Framework\Cache::set($cache_key, $default_group, 0, true); + if($output->toBool()) + { + Rhymix\Framework\Cache::set($cache_key, $default_group, 0, true); + } } return $default_group; @@ -590,7 +605,10 @@ class memberModel extends member $args->order_type = 'asc'; $output = executeQueryArray('member.getGroups', $args); $group_list = $output->data; - Rhymix\Framework\Cache::set("member:member_groups:site:$site_srl", $group_list, 0, true); + if($output->toBool()) + { + Rhymix\Framework\Cache::set("member:member_groups:site:$site_srl", $group_list, 0, true); + } } if(!$group_list) diff --git a/modules/member/member.view.php b/modules/member/member.view.php index 599a9ba0c..b0010ad7d 100644 --- a/modules/member/member.view.php +++ b/modules/member/member.view.php @@ -63,7 +63,7 @@ class memberView extends member $oMemberModel = getModel('member'); $logged_info = Context::get('logged_info'); // Don't display member info to non-logged user - if(!$logged_info->member_srl) return $this->stop('msg_not_permitted'); + if(!$logged_info->member_srl) throw new Rhymix\Framework\Exceptions\MustLogin; $member_srl = Context::get('member_srl'); if(!$member_srl && Context::get('is_logged')) @@ -198,12 +198,12 @@ class memberView extends member $oMemberModel = getModel('member'); // Get the member information if logged-in - if($oMemberModel->isLogged()) return $this->stop('msg_already_logged'); + if($oMemberModel->isLogged()) throw new Rhymix\Framework\Exception('msg_already_logged'); // call a trigger (before) $trigger_output = ModuleHandler::triggerCall('member.dispMemberSignUpForm', 'before', $member_config); if(!$trigger_output->toBool()) return $trigger_output; // Error appears if the member is not allowed to join - if($member_config->enable_join != 'Y') return $this->stop('msg_signup_disabled'); + if($member_config->enable_join != 'Y') throw new Rhymix\Framework\Exceptions\FeatureDisabled('msg_signup_disabled'); $formTags = getAdminView('member')->_getMemberInputTag(); Context::set('formTags', $formTags); @@ -251,7 +251,7 @@ class memberView extends member $oMemberModel = getModel('member'); if(!$oMemberModel->isLogged() || empty($logged_info)) { - return $this->stop('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $_SESSION['rechecked_password_step'] = 'INPUT_PASSWORD'; @@ -294,7 +294,7 @@ class memberView extends member $oMemberModel = getModel('member'); // A message appears if the user is not logged-in - if(!$oMemberModel->isLogged()) return $this->stop('msg_not_logged'); + if(!$oMemberModel->isLogged()) throw new Rhymix\Framework\Exceptions\MustLogin; $logged_info = Context::get('logged_info'); $member_srl = $logged_info->member_srl; @@ -349,10 +349,15 @@ class memberView extends member */ function dispMemberOwnDocument() { + if ($this->member_config->features['my_documents'] === false) + { + throw new Rhymix\Framework\Exceptions\FeatureDisabled; + } + // A message appears if the user is not logged-in if(!Context::get('is_logged')) { - return $this->setError('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $logged_info = Context::get('logged_info'); @@ -378,9 +383,14 @@ class memberView extends member */ function dispMemberOwnComment() { + if ($this->member_config->features['my_comments'] === false) + { + throw new Rhymix\Framework\Exceptions\FeatureDisabled; + } + $oMemberModel = getModel('member'); // A message appears if the user is not logged-in - if(!$oMemberModel->isLogged()) return $this->stop('msg_not_logged'); + if(!$oMemberModel->isLogged()) throw new Rhymix\Framework\Exceptions\MustLogin; $logged_info = Context::get('logged_info'); $member_srl = $logged_info->member_srl; @@ -405,9 +415,14 @@ class memberView extends member */ function dispMemberScrappedDocument() { + if ($this->member_config->features['scrapped_documents'] === false) + { + throw new Rhymix\Framework\Exceptions\FeatureDisabled; + } + $oMemberModel = getModel('member'); // A message appears if the user is not logged-in - if(!$oMemberModel->isLogged()) return $this->stop('msg_not_logged'); + if(!$oMemberModel->isLogged()) throw new Rhymix\Framework\Exceptions\MustLogin; $logged_info = Context::get('logged_info'); @@ -432,7 +447,7 @@ class memberView extends member $folder_srl = (int)Context::get('folder_srl'); if($folder_srl && !array_filter($folders, function($folder) use($folder_srl) { return $folder->folder_srl == $folder_srl; })) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } if(!$folder_srl && count($folders)) { @@ -476,9 +491,14 @@ class memberView extends member */ function dispMemberSavedDocument() { + if ($this->member_config->features['saved_documents'] === false) + { + throw new Rhymix\Framework\Exceptions\FeatureDisabled; + } + $oMemberModel = getModel('member'); // A message appears if the user is not logged-in - if(!$oMemberModel->isLogged()) return $this->stop('msg_not_logged'); + if(!$oMemberModel->isLogged()) throw new Rhymix\Framework\Exceptions\MustLogin; // Get the saved document(module_srl is set to member_srl instead) $logged_info = Context::get('logged_info'); $args = new stdClass(); @@ -502,10 +522,15 @@ class memberView extends member */ function dispMemberActiveLogins() { + if ($this->member_config->features['active_logins'] === false) + { + throw new Rhymix\Framework\Exceptions\FeatureDisabled; + } + $logged_info = Context::get('logged_info'); if (!$logged_info->member_srl) { - return $this->stop('msg_not_logged'); + throw new Rhymix\Framework\Exceptions\MustLogin; } $args = new stdClass(); @@ -558,7 +583,7 @@ class memberView extends member { $oMemberModel = getModel('member'); // A message appears if the user is not logged-in - if(!$oMemberModel->isLogged()) return $this->stop('msg_not_logged'); + if(!$oMemberModel->isLogged()) throw new Rhymix\Framework\Exceptions\MustLogin; $memberConfig = $this->member_config; @@ -590,7 +615,7 @@ class memberView extends member { $oMemberModel = getModel('member'); // A message appears if the user is not logged-in - if(!$oMemberModel->isLogged()) return $this->stop('msg_not_logged'); + if(!$oMemberModel->isLogged()) throw new Rhymix\Framework\Exceptions\MustLogin; $memberConfig = $this->member_config; @@ -643,7 +668,10 @@ class memberView extends member */ function dispMemberFindAccount() { - if(Context::get('is_logged')) return $this->stop('already_logged'); + if(Context::get('is_logged')) + { + throw new Rhymix\Framework\Exception('already_logged'); + } $config = $this->member_config; @@ -663,7 +691,7 @@ class memberView extends member if(Context::get('is_logged')) { - return $this->stop('already_logged'); + throw new Rhymix\Framework\Exception('already_logged'); } if($authMemberSrl) @@ -740,7 +768,7 @@ class memberView extends member **/ function dispMemberSpammer() { - if(!Context::get('is_logged')) return $this->setError('msg_not_permitted'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\NotPermitted; $member_srl = Context::get('member_srl'); $module_srl = Context::get('module_srl'); @@ -751,7 +779,7 @@ class memberView extends member $module_info = $oModuleModel->getModuleInfoByModuleSrl($module_srl, $columnList); $grant = $oModuleModel->getGrant($module_info, Context::get('logged_info')); - if(!$grant->manager) return $this->setError('msg_not_permitted'); + if(!$grant->manager) throw new Rhymix\Framework\Exceptions\NotPermitted; $oMemberModel = getModel('member'); @@ -773,6 +801,11 @@ class memberView extends member */ function dispMemberModifyNicknameLog() { + if ($this->member_config->features['nickname_log'] === false || $this->member_config->update_nickname_log != 'Y') + { + throw new Rhymix\Framework\Exceptions\FeatureDisabled; + } + $member_srl = Context::get('member_srl'); $logged_info = Context::get('logged_info'); if(!$member_srl) @@ -783,7 +816,7 @@ class memberView extends member { if($logged_info->is_admin != 'Y') { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } } diff --git a/modules/member/queries/getMemberListWithinGroup.xml b/modules/member/queries/getMemberListWithinGroup.xml index 25139e467..5c68e0991 100644 --- a/modules/member/queries/getMemberListWithinGroup.xml +++ b/modules/member/queries/getMemberListWithinGroup.xml @@ -1,16 +1,22 @@ - -
    +
    - - - - + + +
    + + + + + + + + @@ -32,9 +38,6 @@ - - - diff --git a/modules/member/ruleset/insert.xml b/modules/member/ruleset/insert.xml index b4e26144f..b58f36a9b 100644 --- a/modules/member/ruleset/insert.xml +++ b/modules/member/ruleset/insert.xml @@ -3,7 +3,7 @@ - + diff --git a/modules/member/skins/default/document_list.html b/modules/member/skins/default/document_list.html index ef5b48748..e4b23426a 100644 --- a/modules/member/skins/default/document_list.html +++ b/modules/member/skins/default/document_list.html @@ -21,10 +21,6 @@ [{$oDocument->getCommentCount()}] - - - [{$oDocument->getTrackbackCount()}] - diff --git a/modules/member/skins/default/login_form.html b/modules/member/skins/default/login_form.html index 84ed82d40..f11c6f40e 100644 --- a/modules/member/skins/default/login_form.html +++ b/modules/member/skins/default/login_form.html @@ -8,7 +8,7 @@

    {$XE_VALIDATOR_MESSAGE}

    - + diff --git a/modules/member/skins/default/modify_info.html b/modules/member/skins/default/modify_info.html index 52d254b1f..2eea04fbd 100644 --- a/modules/member/skins/default/modify_info.html +++ b/modules/member/skins/default/modify_info.html @@ -30,7 +30,7 @@
    {$formTag->inputTag}
    - {$editor} + {$editor|noescape}
    -

    {$lang->member_group} {$lang->help}

    +

    {$lang->member_group}

    {$XE_VALIDATOR_MESSAGE}

    @@ -53,7 +53,6 @@ - {$lang->help}
    diff --git a/modules/member/tpl/header.html b/modules/member/tpl/header.html index ec5a73030..7fb90e408 100644 --- a/modules/member/tpl/header.html +++ b/modules/member/tpl/header.html @@ -1,5 +1,5 @@
    -

    {$lang->cmd_member_config} {$lang->help}

    +

    {$lang->cmd_member_config}

    {$XE_VALIDATOR_MESSAGE}

    diff --git a/modules/member/tpl/insert_join_form.html b/modules/member/tpl/insert_join_form.html index a7e3c51e0..700d0cc6c 100644 --- a/modules/member/tpl/insert_join_form.html +++ b/modules/member/tpl/insert_join_form.html @@ -29,7 +29,7 @@
    - +

    {$lang->about_multi_type}

    diff --git a/modules/member/tpl/insert_member.html b/modules/member/tpl/insert_member.html index 100cda8f8..01c3ed8b9 100644 --- a/modules/member/tpl/insert_member.html +++ b/modules/member/tpl/insert_member.html @@ -21,14 +21,14 @@
    - +
    - +
    @@ -48,7 +48,7 @@
    {$formTag->inputTag}
    -
    {$editor}
    +
    {$editor|noescape}
    - diff --git a/modules/module/tpl/module_selector.html b/modules/module/tpl/module_selector.html index 124045d1a..12a06ed6d 100644 --- a/modules/module/tpl/module_selector.html +++ b/modules/module/tpl/module_selector.html @@ -2,26 +2,13 @@

    {$lang->module_selector}

    - + - - -
    - -
    - - - - -

    {$lang->about_search_virtual_site}

    -
    -
    -
    - + diff --git a/modules/module/tpl/module_setup.html b/modules/module/tpl/module_setup.html index 43cbc7ef2..d99fe0501 100644 --- a/modules/module/tpl/module_setup.html +++ b/modules/module/tpl/module_setup.html @@ -19,8 +19,7 @@ - {$lang->help} - +

    {$lang->about_module_category}

    @@ -31,8 +30,7 @@ - {$lang->help} - +

    {$lang->about_layout}

    @@ -42,32 +40,28 @@ - {$lang->help} - +

    {$lang->about_skin}

    - {$lang->help} - +

    {$lang->about_header_text}

    - {$lang->help} - +

    {$lang->about_footer_text}

    - {$lang->help} - +

    {$lang->about_description}

    diff --git a/modules/module/tpl/skin_config.html b/modules/module/tpl/skin_config.html index d92bb669d..26171074b 100644 --- a/modules/module/tpl/skin_config.html +++ b/modules/module/tpl/skin_config.html @@ -120,8 +120,7 @@ - {$lang->help} - +

    {nl2br(trim($val->description))}

    diff --git a/modules/ncenterlite/LICENSE b/modules/ncenterlite/LICENSE deleted file mode 100644 index 2fb57a6e4..000000000 --- a/modules/ncenterlite/LICENSE +++ /dev/null @@ -1,84 +0,0 @@ -GNU GENERAL PUBLIC LICENSE - -Version 2, June 1991 - -Copyright (C) 1989, 1991 Free Software Foundation, Inc. -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - -Everyone is permitted to copy and distribute verbatim copies -of this license document, but changing it is not allowed. -Preamble - -The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. - -When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. - -To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. - -For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. - -We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. - -Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. - -Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. - -The precise terms and conditions for copying, distribution and modification follow. - -TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - -0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. - -1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. - -You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. - -2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: - -a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. -b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. -c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) -These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. - -3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: - -a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, -b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, -c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) -The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. - -If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - -4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. - -5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. - -6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. - -7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. - -This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - -8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. - -9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. - -10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - -NO WARRANTY - -11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - -12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. \ No newline at end of file diff --git a/modules/ncenterlite/LICENSE-ko b/modules/ncenterlite/LICENSE-ko deleted file mode 100644 index f51a8569f..000000000 --- a/modules/ncenterlite/LICENSE-ko +++ /dev/null @@ -1,97 +0,0 @@ -한국어 번역에 대한 안내 - -이 문서는 GNU General Public License를 한국어로 번역된 것이며 해석의 오류 또는 해석이 달라질 수 있으므로 해석에 도움을 받는 것 외 법적 효력이 없으며, 원문의 규정을 따르도록 합니다. -원문은 http://www.gnu.org/licenses/gpl-2.0.html 에서 볼 수 있습니다. - --------------------------------------------------------------------------------- - -GNU 일반 공중 사용 허가서 - -2판, 1991년 6월 - -Copyright (C) 1989, 1991 Free Software Foundation, Inc. -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - -누구든지 본 사용 허가서를 있는 그대로 복제하고 배포할 수 -있습니다. 그러나 본문에 대한 수정은 허용되지 않습니다. - -전 문 - -소프트웨어에 적용되는 대부분의 사용 허가서(license)들은 소프트웨어에 대한 수정과 공유의 자유를 제한하려는 것을 그 목적으로 합니다. 그러나 GNU 일반 공중 사용 허가서(이하, ``GPL''이라고 칭합니다.)는 자유 소프트웨어에 대한 수정과 공유의 자유를 모든 사용자들에게 보장하기 위해서 성립된 것입니다. 자유 소프트웨어 재단이 제공하는 대부분의 소프트웨어들은 GPL에 의해서 관리되고 있으며, 몇몇 소프트웨어에는 별도의 사용 허가서인 GNU 라이브러리 일반 공중 사용 허가서(GNU Library General Public License)를 대신 적용하기도 합니다. 자유 소프트웨어란, 이를 사용하려고 하는 모든 사람에 대해서 동일한 자유와 권리가 함께 양도되는 소프트웨어를 말하며 프로그램 저작자의 의지에 따라 어떠한 종류의 프로그램에도 GPL을 적용할 수 있습니다. 따라서 여러분이 만든 프로그램에도 GPL을 적용할 수 있습니다. - -자유 소프트웨어를 언급할 때 사용되는 ``자유''라는 단어는 무료(無料)를 의미하는 금전적인 측면의 자유가 아니라 구속되지 않는다는 관점에서의 자유를 의미하며, GPL은 자유 소프트웨어를 이용한 복제와 개작, 배포와 수익 사업 등의 가능한 모든 형태의 자유를 실질적으로 보장하고 있습니다. 여기에는 원시 코드(source code)의 전부 또는 일부를 원용해서 개선된 프로그램을 만들거나 새로운 프로그램을 창작할 수 있는 자유가 포함되며, 자신에게 양도된 이러한 자유와 권리를 보다 명확하게 인식할 수 있도록 하기 위한 규정도 포함되어 있습니다. - -GPL은 GPL 안에 소프트웨어를 양도받을 사용자의 권리를 제한하는 조항과 단서를 별항으로 추가시키지 못하게 함으로써 사용자들의 자유와 권리를 실제적으로 보장하고 있습니다. 자유 소프트웨어의 개작과 배포에 관계하고 있는 사람들은 이러한 무조건적인 권리 양도 규정을 준수해야만 합니다. - -예를 들어 GPL 프로그램을 배포할 경우에는 프로그램의 유료 판매나 무료 배포에 관계없이 자신이 해당 프로그램에 대해서 가질 수 있었던 모든 권리를, 프로그램을 받게될 사람에게 그대로 양도해 주어야 합니다. 이 경우, 프로그램의 원시 코드를 함께 제공하거나 원시 코드를 구할 수 있는 방법을 확실히 알려주어야 하고 이러한 모든 사항들을 사용자들이 분명히 알 수 있도록 명시해야 합니다. - -자유 소프트웨어 재단은 다음과 같은 두 가지 단계를 통해서 사용자들을 권리를 보호합니다. (1) 소프트웨어에 저작권을 설정합니다. (2) 저작권의 양도에 관한 실정법에 의해서 유효한 법률적 효력을 갖는 GPL을 통해 소프트웨어를 복제하거나 개작 및 배포할 수 있는 권리를 사용자들에게 부여합니다. - -자유 소프트웨어를 사용하는 사람들은 반복적인 재배포 과정을 통해 소프트웨어 자체에 수정과 변형이 일어날 수도 있으며, 이는 최초의 저작자가 만든 소프트웨어가 갖고 있는 문제가 아닐 수 있다는 개연성을 인식하고 있어야 합니다. 우리는 개작과 재배포 과정에서 다른 사람에 의해 발생된 문제로 인해 프로그램 원저작자들의 신망이 훼손되는 것을 원하지 않습니다. GPL에 자유 소프트웨어에 대한 어떠한 형태의 보증도 규정하지 않는 이유는 이러한 점들이 고려되었기 때문이며, 이는 프로그램 원저작자와 자유 소프트웨어 재단의 자유로운 활동을 보장하는 현실적인 수단이기도 합니다. - -특허 제도는 자유 소프트웨어의 발전을 위협하는 요소일 수밖에 없습니다. 자유 프로그램을 재배포하는 사람들이 개별적으로 특허를 취득하게 되면, 결과적으로 그 프로그램이 독점 소프트웨어가 될 가능성이 있습니다. 자유 소프트웨어 재단은 이러한 문제에 대처하기 위해서 어떠한 특허에 대해서도 그 사용 권리를 모든 사람들(이하, ``공중(公衆)''이라고 칭합니다.)에게 자유롭게 허용하는 경우에 한해서만 자유 소프트웨어와 함께 사용할 수 있다는 것을 명확히 밝히고 있습니다. - -복제(copying)와 개작(modification) 및 배포(distribution)에 관련된 구체적인 조건과 규정은 다음과 같습니다. - -복제와 개작 및 배포에 관한 조건과 규정 - -제 0 조. 본 허가서는 GNU 일반 공중 사용 허가서의 규정에 따라 배포될 수 있다는 사항이 저작권자에 의해서 명시된 모든 컴퓨터 프로그램 저작물에 대해서 동일하게 적용됩니다. 컴퓨터 프로그램 저작물(이하, ``프로그램''이라고 칭합니다.)이란 특정한 결과를 얻기 위해서 컴퓨터 등의 정보 처리 능력을 가진 장치(이하, ``컴퓨터''라고 칭합니다.) 내에서 직접 또는 간접으로 사용되는 일련의 지시 및 명령으로 표현된 창작물을 의미하고, ``2차적 프로그램''이란 전술한 프로그램 자신 또는 저작권법의 규정에 따라 프로그램의 전부 또는 상당 부분을 원용하거나 다른 언어로의 번역을 포함할 수 있는 개작 과정을 통해서 창작된 새로운 프로그램과 이와 관련된 저작물을 의미합니다. (이후로 다른 언어로의 번역은 별다른 제한없이 개작의 범위에 포함되는 것으로 간주합니다.) ``피양도자''란 GPL의 규정에 따라 프로그램을 양도받은 사람을 의미하고, ``원(原)프로그램''이란 프로그램을 개작하거나 2차적 프로그램을 만들기 위해서 사용된 최초의 프로그램을 의미합니다. - -본 허가서는 프로그램에 대한 복제와 개작 그리고 배포 행위에 대해서만 적용됩니다. 따라서 프로그램을 실행시키는 행위에 대한 제한은 없습니다. 프로그램의 결과물(output)에는, 그것이 프로그램을 실행시켜서 생성된 것인지 아닌지의 여부에 상관없이 결과물의 내용이 원프로그램으로부터 파생된 2차적 프로그램을 구성했을 때에 한해서 본 허가서의 규정들이 적용됩니다. 2차적 프로그램의 구성 여부는 2차적 프로그램 안에서의 원프로그램의 역할을 토대로 판단합니다. - -제 1 조. 적절한 저작권 표시와 프로그램에 대한 보증이 제공되지 않는다는 사실을 각각의 복제물에 명시하는 한, 피양도자는 프로그램의 원시 코드를 자신이 양도받은 상태 그대로 어떠한 매체를 통해서도 복제하고 배포할 수 있습니다. 복제와 배포가 이루어 질 때는 본 허가서와 프로그램에 대한 보증이 제공되지 않는다는 사실에 대해서 언급되었던 모든 내용을 그대로 유지시켜야 하며, 영문판 GPL을 함께 제공해야 합니다. - -배포자는 복제물을 물리적으로 인도하는데 소요된 비용을 청구할 수 있으며, 선택 사항으로 독자적인 유료 보증을 설정할 수 있습니다. - -제 2 조. 피양도자는 자신이 양도받은 프로그램의 전부나 일부를 개작할 수 있으며, 이를 통해서 2차적 프로그램을 창작할 수 있습니다. 개작된 프로그램이나 창작된 2차적 프로그램은 다음의 사항들을 모두 만족시키는 조건에 한해서, 제1조의 규정에 따라 또다시 복제되고 배포될 수 있습니다. - -제 1 항. 파일을 개작할 때는 파일을 개작한 사실과 그 날짜를 파일 안에 명시해야 합니다. -제 2 항. 배포하거나 공표하려는 저작물의 전부 또는 일부가 양도받은 프로그램으로부터 파생된 것이라면, 저작물 전체에 대한 사용 권리를 본 허가서의 규정에 따라 공중에게 무상으로 허용해야 합니다. - -제 3 항. 개작된 프로그램의 일반적인 실행 형태가 대화형 구조로 명령어를 읽어 들이는 방식을 취하고 있을 경우에는, 적절한 저작권 표시와 프로그램에 대한 보증이 제공되지 않는다는 사실, (별도의 보증을 설정한 경우라면 해당 내용) 그리고 양도받은 프로그램을 본 규정에 따라 재배포할 수 있다는 사실과 GPL 사본을 참고할 수 있는 방법이 함께 포함된 문구가 프로그램이 대화형 구조로 평이하게 실행된 직후에 화면 또는 지면으로 출력되도록 작성되어야 합니다. (예외 규정: 양도받은 프로그램이 대화형 구조를 갖추고 있다 하더라도 통상적인 실행 환경에서 전술한 사항들이 출력되지 않는 형태였을 경우에는 이를 개작한 프로그램 또한 관련 사항들을 출력시키지 않아도 무방합니다.) - -위의 조항들은 개작된 프로그램 전체에 적용됩니다. 만약, 개작된 프로그램에 포함된 특정 부분이 원프로그램으로부터 파생된 것이 아닌 별도의 독립 저작물로 인정될 만한 상당한 이유가 있을 경우에는 해당 저작물의 개별적인 배포에는 본 허가서의 규정들이 적용되지 않습니다. 그러나 이러한 저작물이 2차적 프로그램의 일부로서 함께 배포된다면 개별적인 저작권과 배포 기준에 상관없이 저작물 모두에 본 허가서가 적용되어야 하며, 전체 저작물에 대한 사용 권리는 공중에게 무상으로 양도됩니다. - -이러한 규정은 개별적인 저작물에 대한 저작자의 권리를 침해하거나 인정하지 않으려는 것이 아니라, 원프로그램으로부터 파생된 2차적 프로그램이나 수집 저작물의 배포를 일관적으로 규제할 수 있는 권리를 행사하기 위한 것입니다. - -원프로그램이나 원프로그램으로부터 파생된 2차적 프로그램을 이들로부터 파생되지 않은 다른 저작물과 함께 단순히 저장하거나 배포할 목적으로 동일한 매체에 모아 놓은 집합물의 경우에는, 원프로그램으로부터 파생되지 않은 다른 저작물에는 본 허가서의 규정들이 적용되지 않습니다. - -제 3 조. 피양도자는 다음 중 하나의 항목을 만족시키는 조건에 한해서 제1조와 제2조의 규정에 따라 프로그램(또는 제2조에서 언급된 2차적 프로그램)을 목적 코드(object code)나 실행물(executable form)의 형태로 복제하고 배포할 수 있습니다. - -제 1 항. 목적 코드나 실행물에 상응하는 컴퓨터가 인식할 수 있는 완전한 원시 코드를 함께 제공해야 합니다. 원시 코드는 제1조와 제2조의 규정에 따라 배포될 수 있어야 하며, 소프트웨어의 교환을 위해서 일반적으로 사용되는 매체를 통해 제공되어야 합니다. -제 2 항. 배포에 필요한 최소한의 비용만을 받고 목적 코드나 실행물에 상응하는 완전한 원시 코드를 배포하겠다는, 최소한 3년간 유효한 약정서를 함께 제공해야 합니다. 이 약정서는 약정서를 갖고 있는 어떠한 사람에 대해서도 유효해야 합니다. 원시 코드는 컴퓨터가 인식할 수 있는 형태여야 하고 제1조와 제2조의 규정에 따라 배포될 수 있어야 하며, 소프트웨어의 교환을 위해서 일반적으로 사용되는 매체를 통해 제공되어야 합니다. - -제 3 항. 목적 코드나 실행물에 상응하는 원시 코드를 배포하겠다는 약정에 대해서 자신이 양도받은 정보를 함께 제공해야 합니다. (제3항은 위의 제2항에 따라 원시 코드를 배포하겠다는 약정을 프로그램의 목적 코드나 실행물과 함께 제공 받았고, 동시에 비상업적인 배포를 하고자 할 경우에 한해서만 허용됩니다.) - -저작물에 대한 원시 코드란 해당 저작물을 개작하기에 적절한 형식을 의미합니다. 실행물에 대한 완전한 원시 코드란 실행물에 포함된 모든 모듈들의 원시 코드와 이와 관련된 인터페이스 정의 파일 모두, 그리고 실행물의 컴파일과 설치를 제어하는데 사용된 스크립트 전부를 의미합니다. 그러나 특별한 예외의 하나로서, 실행물이 실행될 운영체제의 주요 부분(컴파일러나 커널 등)과 함께 (원시 코드나 바이너리의 형태로) 일반적으로 배포되는 구성 요소들은 이러한 구성 요소 자체가 실행물에 수반되지 않는 한 원시 코드의 배포 대상에서 제외되어도 무방합니다. - -목적 코드나 실행물을 지정한 장소로부터 복제해 갈 수 있게 하는 방식으로 배포할 경우, 동일한 장소로부터 원시 코드를 복제할 수 있는 동등한 접근 방법을 제공한다면 이는 원시 코드를 목적 코드와 함께 복제되도록 설정하지 않았다고 하더라도 원시 코드를 배포하는 것으로 간주됩니다. - -제 4 조. 본 허가서에 의해 명시적으로 이루어 지지 않는 한 프로그램에 대한 복제와 개작 및 하위 허가권 설정과 배포가 성립될 수 없습니다. 이와 관련된 어떠한 행위도 무효이며 본 허가서가 보장한 권리는 자동으로 소멸됩니다. 그러나 본 허가서의 규정에 따라 프로그램의 복제물이나 권리를 양도받았던 제3자는 본 허가서의 규정들을 준수하는 한, 배포자의 권리 소멸에 관계없이 사용상의 권리를 계속해서 유지할 수 있습니다. - -제 5 조. 본 허가서는 서명이나 날인이 수반되는 형식을 갖고 있지 않기 때문에 피양도자가 본 허가서의 내용을 반드시 받아들여야 할 필요는 없습니다. 그러나 프로그램이나 프로그램에 기반한 2차적 프로그램에 대한 개작 및 배포를 허용하는 것은 본 허가서에 의해서만 가능합니다. 만약 본 허가서에 동의하지 않을 경우에는 이러한 행위들이 법률적으로 금지됩니다. 따라서 프로그램(또는 프로그램에 기반한 2차적 프로그램)을 개작하거나 배포하는 행위는 이에 따른 본 허가서의 내용에 동의한다는 것을 의미하며, 복제와 개작 및 배포에 관한 본 허가서의 조건과 규정들을 모두 받아들이겠다는 의미로 간주됩니다. - -제 6 조. 피양도자에 의해서 프로그램(또는 프로그램에 기반한 2차적 프로그램)이 반복적으로 재배포될 경우, 각 단계에서의 피양도자는 본 허가서의 규정에 따른 프로그램의 복제와 개작 및 배포에 대한 권리를 최초의 양도자로부터 양도받은 것으로 자동적으로 간주됩니다. 프로그램(또는 프로그램에 기반한 2차적 프로그램)을 배포할 때는 피양도자의 권리의 행사를 제한할 수 있는 어떠한 사항도 추가할 수 없습니다. 그러나 피양도자에게, 재배포가 일어날 시점에서의 제3의 피양도자에게 본 허가서를 준수하도록 강제할 책임은 부과되지 않습니다. - -제 7 조. 법원의 판결이나 특허권 침해에 대한 주장 또는 특허 문제에 국한되지 않은 그밖의 이유들로 인해서 본 허가서의 규정에 배치되는 사항이 발생한다 하더라도 그러한 사항이 선행하거나 본 허가서의 조건과 규정들이 면제되는 것은 아닙니다. 따라서 법원의 명령이나 합의 등에 의해서 본 허가서에 위배되는 사항들이 발생한 상황이라도 양측 모두를 만족시킬 수 없다면 프로그램은 배포될 수 없습니다. 예를 들면, 특정한 특허 관련 허가가 프로그램의 복제물을 직접 또는 간접적인 방법으로 양도받은 임의의 제3자에게 해당 프로그램을 무상으로 재배포할 수 있게 허용하지 않는다면, 그러한 허가와 본 사용 허가를 동시에 만족시키면서 프로그램을 배포할 수 있는 방법은 없습니다. - -본 조항은 특정한 상황에서 본 조항의 일부가 유효하지 않거나 적용될 수 없을 경우에도 본 조항의 나머지 부분들을 적용하기 위한 의도로 만들어 졌습니다. 따라서 그 이외의 상황에서는 본 조항을 전체적으로 적용하면 됩니다. - -본 조항의 목적은 특허나 저작권 침해 등의 행위를 조장하거나 해당 권리를 인정하지 않으려는 것이 아니라, GPL을 통해서 구현되어 있는 자유 소프트웨어의 배포 체계를 통합적으로 보호하기 위한 것입니다. 많은 사람들이 배포 체계에 대한 신뢰있는 지원을 계속해 줌으로써 소프트웨어의 다양한 분야에 많은 공헌을 해 주었습니다. 소프트웨어를 어떠한 배포 체계로 배포할 것인가를 결정하는 것은 전적으로 저작자와 기증자들의 의지에 달려있는 것이지, 일반 사용자들이 강요할 수 있는 문제는 아닙니다. - -본 조항은 본 허가서의 다른 조항들에서 무엇이 중요하게 고려되어야 하는 지를 명확하게 설명하기 위한 목적으로 만들어진 것입니다. - -제 8 조. 특허나 저작권이 설정된 인터페이스로 인해서 특정 국가에서 프로그램의 배포와 사용이 함께 또는 개별적으로 제한되어 있는 경우, 본 사용 허가서를 프로그램에 적용한 최초의 저작권자는 문제가 발생하지 않는 국가에 한해서 프로그램을 배포한다는 배포상의 지역적 제한 조건을 명시적으로 설정할 수 있으며, 이러한 사항은 본 허가서의 일부로 간주됩니다. - -제 9 조. 자유 소프트웨어 재단은 때때로 본 사용 허가서의 개정판이나 신판을 공표할 수 있습니다. 새롭게 공표될 판은 당면한 문제나 현안을 처리하기 위해서 세부적인 내용에 차이가 발생할 수 있지만, 그 근본 정신에는 변함이 없을 것입니다. - -각각의 판들은 판번호를 사용해서 구별됩니다. 특정한 판번호와 그 이후 판을 따른다는 사항이 명시된 프로그램에는 해당 판이나 그 이후에 발행된 어떠한 판을 선택해서 적용해도 무방하고, 판번호를 명시하고 있지 않은 경우에는 자유 소프트웨어 재단이 공표한 어떠한 판번호의 판을 적용해도 무방합니다. - -제 10 조. 프로그램의 일부를 본 허가서와 배포 기준이 다른 자유 프로그램과 함께 결합하고자 할 경우에는 해당 프로그램의 저작자로부터 서면 승인을 받아야 합니다. 자유 소프트웨어 재단이 저작권을 갖고 있는 소프트웨어의 경우에는 자유 소프트웨어 재단의 승인을 얻어야 합니다. 우리는 이러한 요청을 수락하기 위해서 때때로 예외 기준을 만들기도 합니다. 자유 소프트웨어 재단은 일반적으로 자유 소프트웨어의 2차적 저작물들을 모두 자유로운 상태로 유지시키려는 목적과 소프트웨어의 공유와 재활용을 증진시키려는 두가지 목적을 기준으로 승인 여부를 결정할 것입니다. - - -보증의 결여 (제11조, 제12조) - -제 11 조. 본 허가서를 따르는 프로그램은 무상으로 양도되기 때문에 관련 법률이 허용하는 한도 내에서 어떠한 형태의 보증도 제공되지 않습니다. 프로그램의 저작권자와 배포자가 공동 또는 개별적으로 별도의 보증을 서면으로 제공할 때를 제외하면, 특정한 목적에 대한 프로그램의 적합성이나 상업성 여부에 대한 보증을 포함한 어떠한 형태의 보증도 명시적이나 묵시적으로 설정되지 않은 ``있는 그대로의'' 상태로 이 프로그램을 배포합니다. 프로그램과 프로그램의 실행에 따라 발생할 수 있는 모든 위험은 피양도자에게 인수되며 이에 따른 보수 및 복구를 위한 제반 경비 또한 피양도자가 모두 부담해야 합니다. - -제 12 조. 저작권자나 배포자가 프로그램의 손상 가능성을 사전에 알고 있었다 하더라도 발생된 손실이 관련 법규에 의해 보호되고 있거나 이에 대한 별도의 서면 보증이 설정된 경우가 아니라면, 저작권자나 프로그램을 원래의 상태 또는 개작한 상태로 제공한 배포자는 프로그램의 사용이나 비작동으로 인해 발생된 손실이나 프로그램 자체의 손실에 대해 책임지지 않습니다. 이러한 면책 조건은 사용자나 제3자가 프로그램을 조작함으로써 발생된 손실이나 다른 소프트웨어와 프로그램을 함께 동작시키는 것으로 인해서 발생된 데이터의 상실 및 부정확한 산출 결과에만 국한되는 것이 아닙니다. 발생된 손실의 일반성이나 특수성 뿐 아니라 원인의 우발성 및 필연성도 전혀 고려되지 않습니다. diff --git a/modules/ncenterlite/conf/module.xml b/modules/ncenterlite/conf/module.xml index df246147a..f56580f36 100644 --- a/modules/ncenterlite/conf/module.xml +++ b/modules/ncenterlite/conf/module.xml @@ -19,6 +19,7 @@ + diff --git a/modules/ncenterlite/lang/en.php b/modules/ncenterlite/lang/en.php index 8d1cc10f8..237989925 100644 --- a/modules/ncenterlite/lang/en.php +++ b/modules/ncenterlite/lang/en.php @@ -19,10 +19,12 @@ $lang->ncenterlite_userconfig_title = 'Notification Center Settings of %s'; $lang->ncenterlite_userconfig_about = 'Personalized settings of notification center can be controlled by you.'; $lang->ncenterlite_comment_noti = 'Comment notice'; $lang->ncenterlite_comment_noti_about = 'Get notice of a comment after someone replies to my documents or comments.'; -$lang->ncenterlite_mention_noti = 'Mention notice'; +$lang->ncenterlite_mention_noti = 'New Direct Message'; $lang->ncenterlite_mention_noti_about = 'Get notice of a mention after someone mention me on documents and/or comments. ( @Nickname to mention )'; -$lang->ncenterlite_message_noti = 'Message notice'; +$lang->ncenterlite_message_noti = 'New Message'; $lang->ncenterlite_message_noti_about = 'Get notice of a message after someone send the message to me.'; +$lang->ncenterlite_comment_comment_noti = 'New Comment'; +$lang->ncenterlite_vote_noti = 'New Upvote'; $lang->ncenterlite_activate = 'Activate'; $lang->ncenterlite_inactivate = 'Inactivate'; $lang->ncenterlite_userconfig_about_warning = 'Watch out! You are controlling other user\'s settings via this page.'; @@ -36,6 +38,7 @@ $lang->ncenterlite_message_string_plural = 'You have %d unread $lang->ncenterlite_message_mention = '%1$s sent you a message, "%2$s".'; $lang->ncenterlite_test_noti = 'Hello, %s! This is a test notification.'; $lang->ncenterlite_vote = '%1$s upvoted your %3$s, "%2$s".'; +$lang->ncenterlite_vote_anonymous = 'upvoted your %2$s, "%1$s".'; $lang->ncenterlite_admin_content_message = '%1$s wrote "%3$s" on %2$s.'; $lang->ncenterlite_insert_member_message = '%s! Welcome to the membership!!'; $lang->ncenterlite_content_image = '(Image)'; @@ -50,6 +53,7 @@ $lang->ncenterlite_date['5'] = 'second'; $lang->ncenterlite_sir = ' '; $lang->ncenterlite_message = 'You have %s new notification.'; $lang->ncenterlite_messages = 'You have %s new notifications.'; +$lang->ncenterlite_not_have_message = 'You have no new notifications.'; $lang->ncenterlite_thisistest = '[*] This is a test notice.'; $lang->ncenterlite_delete_all = 'delete all'; $lang->ncenterlite_more = 'More'; @@ -72,6 +76,8 @@ $lang->ncenterlite_display_pc = 'Only PC'; $lang->ncenterlite_display_mobile = 'Only Mobile'; $lang->ncenterlite_display_none = 'Not display.'; $lang->ncenterlite_display_about = 'You can hide notifications from Notification Center Lite if you are using a layout or widget that handles notifications for you.'; +$lang->ncenterlite_always_display = 'Always display notification area'; +$lang->ncenterlite_always_display_about = 'Always display the notification area, even if there are no new notifications.'; $lang->ncenterlite_mention_target = 'Mention target'; $lang->ncenterlite_mention_target_about = 'Mention target can be nicknames or IDs (@Nickname or @ID).'; $lang->ncenterlite_skin_settings = 'Skin settings'; @@ -101,3 +107,8 @@ $lang->dont_check_notify_delete = 'Unread notifications will be deleted, too.'; $lang->user_notify_setting = 'User notify setting.'; $lang->about_user_notify_setting = 'Each member can set a notify settings. Warning! If a member setting not use notifications, they will not be notified regardless of their default settings.'; $lang->msg_not_use_user_setting = 'user setting\'s not use. Please contact your administrator.'; +$lang->anonymous_voter = 'anonymous voter'; +$lang->about_anonymous_voter = 'anonymize voter in vote notification'; +$lang->highlight_effect = 'highlight effect'; +$lang->about_highlight_effect = 'it gives highlight effect to the comment when access the comment URL.'; +$lang->msg_denger_rhymix_user = 'Warning! Rhymix includes notification center by default.
    Please remove this XE-only module and reinstall the Rhymix native version.'; \ No newline at end of file diff --git a/modules/ncenterlite/lang/ko.php b/modules/ncenterlite/lang/ko.php index 7bf194d5d..35a433cb1 100644 --- a/modules/ncenterlite/lang/ko.php +++ b/modules/ncenterlite/lang/ko.php @@ -33,9 +33,15 @@ $lang->ncenterlite_mention_noti = '멘션 알림'; $lang->ncenterlite_mention_noti_about = '누군가 글, 혹은 댓글을 통해서 나를 멘션 했을 경우 알려줍니다. (멘션 방법 @닉네임 )'; $lang->ncenterlite_message_noti = '쪽지 알림'; $lang->ncenterlite_message_noti_about = '누군가에게 받은 쪽지를 알림을 받습니다.'; +$lang->ncenterlite_comment_comment_noti = '대댓글 알림'; +$lang->ncenterlite_vote_noti = '추천 알림'; $lang->ncenterlite_activate = '사용'; $lang->ncenterlite_inactivate = '사용 안함'; $lang->ncenterlite_userconfig_about_warning = '주의! 당신은 관리자 권한으로 다른 사용자의 설정창에 접속하였습니다.'; +$lang->ncenterlite_comment_all = '모든 댓글 작성자에게 알림'; +$lang->ncenterlite_comment_all_setting = '댓글 작성자 알림 설정'; +$lang->ncenterlite_comment_all_select_mid = '댓글 작성자 알림 사용 모듈'; +$lang->ncenterlite_about_comment_all_select_mid = '댓글 작성자 알림을 사용하실 모듈을 선택하세요. 모두 선택 해제시 기능이 작동하지 않습니다.'; $lang->ncenterlite_article = '%1$s님이 "%2$s"라고 글을 남겼습니다.'; $lang->ncenterlite_board = '%1$s님이 "%2$s" 게시판에 "%3$s"라고 글을 남겼습니다.'; $lang->ncenterlite_commented = '%1$s님이 회원님의 %2$s에 "%3$s"라고 댓글을 남겼습니다.'; @@ -46,6 +52,7 @@ $lang->ncenterlite_message_string_plural = '%d개의 읽지 않 $lang->ncenterlite_message_mention = '%s님이 "%s"라고 메시지를 보내셨습니다.'; $lang->ncenterlite_test_noti = '%s님! 테스트 알림입니다.'; $lang->ncenterlite_vote = '%s님이 회원님의 "%s" %s을 추천하였습니다.'; +$lang->ncenterlite_vote_anonymous = '회원님의 "%s" %s이 추천되었습니다.'; $lang->ncenterlite_admin_content_message = '%1$s님이 "%2$s" 게시판에 "%3$s"라고 글을 남겼습니다.'; $lang->ncenterlite_insert_member_message = '%s회원가입을 환영합니다!!'; $lang->ncenterlite_content_image = '(이미지)'; @@ -60,6 +67,7 @@ $lang->ncenterlite_date['5'] = '초'; $lang->ncenterlite_sir = '님'; $lang->ncenterlite_message = '%s개의 알림이 있습니다.'; $lang->ncenterlite_messages = '%s개의 알림이 있습니다.'; +$lang->ncenterlite_not_have_message = '새 알림이 없습니다.'; $lang->ncenterlite_thisistest = '[*] 시험용 알림입니다'; $lang->ncenterlite_delete_all = '모두 삭제'; $lang->ncenterlite_more = '더보기'; @@ -82,6 +90,8 @@ $lang->ncenterlite_display_pc = 'PC만 표시'; $lang->ncenterlite_display_mobile = '모바일만 표시'; $lang->ncenterlite_display_none = '표시하지 않음'; $lang->ncenterlite_display_about = '사용하는 레이아웃이나 위젯에 알림을 표시하는 기능이 있는 경우 중복을 막기 위해 알림센터의 알림을 숨길 수 있습니다.'; +$lang->ncenterlite_always_display = '알림센터 항상 표시'; +$lang->ncenterlite_always_display_about = '새 알림이 없어도 항상 알림센터를 표시합니다.'; $lang->ncenterlite_mention_target = '멘션 타겟'; $lang->ncenterlite_mention_target_about = '멘션 알림을 @아이디 소유자에게 보낼지 @닉네임 소유자에게 보낼지 선택할 수 있습니다.'; $lang->ncenterlite_skin_settings = '스킨 설정'; @@ -127,10 +137,14 @@ $lang->about_mention_suffix_always_cut = '\'알림센터님\'이라는 회원과 $lang->mention_limit = '멘션 갯수 제한'; $lang->about_mention_limit = '서버 과부하와 스팸을 방지하기 위해 한 글에서 지나치게 많은 회원들을 호출하지 못하도록 합니다.'; $lang->ncenterlite_msg_setting_error = '설정에 오류가 있습니다. 다시 설정해 주세요.'; -$lang->ncenterlite_use_help = '회원들에게 전송할 알림을 선택할 수 있습니다.'; +$lang->ncenterlite_use_help = '회원들에게 전송할 알림을 선택할 수 있습니다.
    모든 댓글 작성자에게 알림 기능은 게시글의 작성자가 댓글을 남길경우 게시글을 작성한 작성자를 제외하고 해당 글의 모든 댓글 작성자들에게 알림을 전송합니다.'; $lang->ncenterlite_dont_use_push = '푸시 알림은 현재 지원중이 아닙니다.'; $lang->member_phone_variable = '회원전화번호 변수'; $lang->member_phone_variable_about = '회원전화번호 변수를 선택합니다. 회원전화번호 변수가 1개일 경우 설치시 자동으로 설정이 저장됩니다. 이 경우 설정을 할 필요가 없어서 설정을 선택할 수 없습니다.'; +$lang->anonymous_voter = '추천인 익명'; +$lang->about_anonymous_voter = '추천 알림시 추천인을 익명으로 처리합니다.'; +$lang->highlight_effect = '하이라이트 효과'; +$lang->about_highlight_effect = '댓글 URL로 접근시 해당 댓글에 하이라이트 효과를 줍니다.'; $lang->fail_module_install = '모듈설치에 실패하였습니다.'; $lang->cmd_web_notify = '웹 알림'; $lang->cmd_mail_notify = '메일 알림'; @@ -143,3 +157,5 @@ $lang->ncenterlite_notify_type = '알림 타입 리스트'; $lang->msg_do_not_notify_type = '생성한 알림타입이 존재하지 않습니다.'; $lang->ncenterlite_custom_list = '커스텀 리스트'; $lang->msg_not_use_user_setting = '유저 세팅을 제공하지 않습니다. 관리자에게 문의하세요.'; +$lang->msg_denger_rhymix_user = '경고! 라이믹스에서는 코어에 포함된 순정 알림센터를 사용해야 합니다.
    XE용 알림센터를 삭제하고, 라이믹스 알림센터를 다시 설치해 주시기 바랍니다.'; +$lang->msg_test_notifycation_success = '테스트알림더미를 정상적으로 생성하였습니다.'; diff --git a/modules/ncenterlite/m.skins/default/ncenter.html b/modules/ncenterlite/m.skins/default/ncenter.html index f43222c58..1177a6a56 100644 --- a/modules/ncenterlite/m.skins/default/ncenter.html +++ b/modules/ncenterlite/m.skins/default/ncenter.html @@ -44,12 +44,6 @@ // {sprintf($lang->ncenterlite_messages, $ncenterlite_page_navigation->total_count)} + + {$lang->ncenterlite_not_have_message} {sprintf($lang->ncenterlite_message, $ncenterlite_page_navigation->total_count)} @@ -42,12 +44,6 @@ //admin_notify_module_srls = array(); } } + + if($obj->disp_act == 'dispNcenterliteAdminOtherComment') + { + if(!$obj->comment_all) + { + $config->comment_all = 'N'; + } + if(!$obj->comment_all_notify_module_srls) + { + $config->comment_all_notify_module_srls = array(); + } + } + $output = $oModuleController->insertModuleConfig('ncenterlite', $config); if(!$output->toBool()) { - return $this->setError('ncenterlite_msg_setting_error'); + throw new Rhymix\Framework\Exception('ncenterlite_msg_setting_error'); } $this->setMessage('success_updated'); @@ -110,11 +128,26 @@ class ncenterliteAdminController extends ncenterlite $args->type = $this->_TYPE_TEST; $args->target_type = $this->_TYPE_TEST; $args->target_url = getUrl(''); - $args->target_summary = Context::getLang('ncenterlite_thisistest') . rand(); + $args->target_summary = Context::getLang('ncenterlite_thisistest'); $args->target_nick_name = $logged_info->nick_name; $args->regdate = date('YmdHis'); $args->notify = $oNcenterliteController->_getNotifyId($args); - $oNcenterliteController->_insertNotify($args); + $output = $oNcenterliteController->_insertNotify($args); + if(!$output->toBool()) + { + return $output; + } + } + + $this->setMessage('msg_test_notifycation_success'); + + if (Context::get('success_return_url')) + { + $this->setRedirectUrl(Context::get('success_return_url')); + } + else + { + $this->setRedirectUrl(getNotEncodedUrl('', 'module', 'admin', 'act', 'dispNcenterliteAdminTest')); } } @@ -137,7 +170,22 @@ class ncenterliteAdminController extends ncenterlite $args->target_nick_name = $logged_info->nick_name; $args->regdate = date('YmdHis'); $args->notify = $oNcenterliteController->_getNotifyId($args); - $oNcenterliteController->_insertNotify($args); + $output = $oNcenterliteController->_insertNotify($args); + if(!$output->toBool()) + { + return $output; + } + + $this->setMessage('msg_test_notifycation_success'); + + if (Context::get('success_return_url')) + { + $this->setRedirectUrl(Context::get('success_return_url')); + } + else + { + $this->setRedirectUrl(getNotEncodedUrl('', 'module', 'admin', 'act', 'dispNcenterliteAdminTest')); + } } function procNcenterliteAdminDeleteNofity() diff --git a/modules/ncenterlite/ncenterlite.admin.view.php b/modules/ncenterlite/ncenterlite.admin.view.php index b601d2eae..3f159e6cb 100644 --- a/modules/ncenterlite/ncenterlite.admin.view.php +++ b/modules/ncenterlite/ncenterlite.admin.view.php @@ -41,6 +41,18 @@ class ncenterliteAdminView extends ncenterlite Context::set('mid_list', $mid_list); Context::set('config', $config); } + + function dispNcenterliteAdminOtherComment() + { + $oModuleModel = getModel('module'); + $oNcenterliteModel = getModel('ncenterlite'); + $config = $oNcenterliteModel->getConfig(); + + $mid_list = $oModuleModel->getMidList(null, array('module_srl', 'mid', 'browser_title', 'module')); + + Context::set('mid_list', $mid_list); + Context::set('config', $config); + } function dispNcenterliteAdminSkinsetting() { diff --git a/modules/ncenterlite/ncenterlite.class.php b/modules/ncenterlite/ncenterlite.class.php index f622030b0..a0e23e66d 100644 --- a/modules/ncenterlite/ncenterlite.class.php +++ b/modules/ncenterlite/ncenterlite.class.php @@ -3,6 +3,7 @@ class ncenterlite extends ModuleObject { var $_TYPE_DOCUMENT = 'D'; // 댓글 var $_TYPE_COMMENT = 'C'; // 댓글의 댓글 + var $_TYPE_COMMENT_ALL = 'G'; var $_TYPE_ADMIN_COMMENT = 'A'; // 어드민 댓글 알림 var $_TYPE_MENTION = 'M'; // 멘션 var $_TYPE_MESSAGE = 'E'; // 쪽지 mEssage diff --git a/modules/ncenterlite/ncenterlite.controller.php b/modules/ncenterlite/ncenterlite.controller.php index 19a45cbc9..70d6ffb4e 100644 --- a/modules/ncenterlite/ncenterlite.controller.php +++ b/modules/ncenterlite/ncenterlite.controller.php @@ -9,7 +9,7 @@ class ncenterliteController extends ncenterlite $config = $oNcenterliteModel->getConfig(); if($config->user_notify_setting != 'Y') { - return $this->setError('msg_not_use_user_setting'); + throw new Rhymix\Framework\Exception('msg_not_use_user_setting'); } $member_srl = Context::get('member_srl'); @@ -21,7 +21,7 @@ class ncenterliteController extends ncenterlite if($logged_info->member_srl != $member_srl && $logged_info->is_admin != 'Y') { - return $this->setError('ncenterlite_stop_no_permission_other_user_settings'); + throw new Rhymix\Framework\Exception('ncenterlite_stop_no_permission_other_user_settings'); } $user_config = $oNcenterliteModel->getUserConfig($member_srl); @@ -53,11 +53,13 @@ class ncenterliteController extends ncenterlite $this->setMessage('success_updated'); - if(!in_array(Context::getRequestMethod(), array('XMLRPC', 'JSON'))) + if (Context::get('success_return_url')) { - $returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : getNotEncodedUrl('act', 'dispNcenterliteUserConfig', 'member_srl', $member_srl); - header('location: ' . $returnUrl); - return; + $this->setRedirectUrl(Context::get('success_return_url')); + } + else + { + $this->setRedirectUrl(getNotEncodedUrl('act', 'dispNcenterliteUserConfig', 'member_srl', $member_srl)); } } @@ -80,6 +82,13 @@ class ncenterliteController extends ncenterlite { $this->removeFlagFile($args->member_srl); } + + // Delete to user setting. + $userSetOutput = executeQuery('ncenterlite.deleteNcenterliteUserSettingData', $args); + if(!$userSetOutput->toBool()) + { + return $userSetOutput; + } } function triggerAfterInsertDocument(&$obj) @@ -131,7 +140,7 @@ class ncenterliteController extends ncenterlite $args->target_srl = $obj->document_srl; $args->type = $this->_TYPE_DOCUMENT; $args->target_type = $this->_TYPE_ADMIN_DOCUMENT; - $args->target_url = getNotEncodedFullUrl('', 'document_srl', $obj->document_srl); + $args->target_url = getNotEncodedUrl('', 'document_srl', $obj->document_srl); $args->target_summary = cut_str(strip_tags($obj->title), 50); $args->regdate = date('YmdHis'); $args->target_browser = $module_info->browser_title; @@ -163,6 +172,40 @@ class ncenterliteController extends ncenterlite // 익명 노티 체크 $is_anonymous = $this->_isAnonymous($this->_TYPE_COMMENT, $obj); + $oDocumentModel = getModel('document'); + $oDocument = $oDocumentModel->getDocument($document_srl); + + if($config->comment_all == 'Y' && $obj->member_srl == $oDocument->get('member_srl') && !$obj->parent_srl && (is_array($config->comment_all_notify_module_srls) && in_array($module_info->module_srl, $config->comment_all_notify_module_srls))) + { + $comment_args = new stdClass(); + $comment_args->member_srl = $obj->member_srl; + $comment_args->document_srl = $obj->document_srl; + $other_comment = executeQueryArray('ncenterlite.getOtherCommentByMemberSrl', $comment_args); + foreach ($other_comment->data as $value) + { + $args = new stdClass(); + $args->config_type = 'comment_all'; + $args->member_srl = $value->member_srl; + $args->target_p_srl = $obj->comment_srl; + $args->srl = $obj->document_srl; + $args->target_srl = $obj->comment_srl; + $args->type = $this->_TYPE_COMMENT; + $args->target_type = $this->_TYPE_COMMENT_ALL; + $args->target_url = getNotEncodedUrl('', 'document_srl', $document_srl, '_comment_srl', $comment_srl) . '#comment_' . $comment_srl; + $args->target_summary = cut_str(trim(utf8_normalize_spaces(strip_tags($content))), 50) ?: (strpos($content, 'target_nick_name = $obj->nick_name; + $args->target_email_address = $obj->email_address; + $args->regdate = date('YmdHis'); + $args->target_browser = $module_info->browser_title; + $args->notify = $this->_getNotifyId($args); + $output = $this->_insertNotify($args, $is_anonymous); + if(!$output->toBool()) + { + return $output; + } + } + } + $obj->admin_comment_notify = false; $admin_list = $oNcenterliteModel->getMemberAdmins(); @@ -182,7 +225,7 @@ class ncenterliteController extends ncenterlite $args->target_srl = $obj->comment_srl; $args->type = $this->_TYPE_COMMENT; $args->target_type = $this->_TYPE_ADMIN_COMMENT; - $args->target_url = getNotEncodedFullUrl('', 'document_srl', $document_srl, '_comment_srl', $comment_srl) . '#comment_' . $comment_srl; + $args->target_url = getNotEncodedUrl('', 'document_srl', $document_srl, '_comment_srl', $comment_srl) . '#comment_' . $comment_srl; $args->target_summary = cut_str(trim(utf8_normalize_spaces(strip_tags($content))), 50) ?: (strpos($content, 'target_nick_name = $obj->nick_name; $args->target_email_address = $obj->email_address; @@ -194,6 +237,10 @@ class ncenterliteController extends ncenterlite { $obj->admin_comment_notify = true; } + else + { + return $output; + } } } @@ -246,23 +293,24 @@ class ncenterliteController extends ncenterlite $args->target_srl = $obj->comment_srl; $args->type = $this->_TYPE_COMMENT; $args->target_type = $this->_TYPE_COMMENT; - $args->target_url = getNotEncodedFullUrl('', 'document_srl', $document_srl, '_comment_srl', $comment_srl) . '#comment_' . $comment_srl; + $args->target_url = getNotEncodedUrl('', 'document_srl', $document_srl, '_comment_srl', $comment_srl) . '#comment_' . $comment_srl; $args->target_summary = cut_str(trim(utf8_normalize_spaces(strip_tags($content))), 50) ?: (strpos($content, 'target_nick_name = $obj->nick_name; $args->target_email_address = $obj->email_address; $args->regdate = $regdate; $args->target_browser = $module_info->browser_title; $args->notify = $this->_getNotifyId($args); - $this->_insertNotify($args, $is_anonymous); + $output = $this->_insertNotify($args, $is_anonymous); + if(!$output->toBool()) + { + return $output; + } $notify_member_srls[] = abs($member_srl); } } // 대댓글이 아니고, 게시글의 댓글을 남길 경우 if(!$parent_srl || ($parent_srl && isset($config->use['comment_comment']))) { - $oDocumentModel = getModel('document'); - $oDocument = $oDocumentModel->getDocument($document_srl); - $member_srl = $oDocument->get('member_srl'); if(is_array($admin_list) && in_array(abs($member_srl), $admin_list) && isset($config->use['admin_content']) && $obj->admin_comment_notify == true) @@ -290,14 +338,18 @@ class ncenterliteController extends ncenterlite $args->target_srl = $comment_srl; $args->type = $this->_TYPE_DOCUMENT; $args->target_type = $this->_TYPE_COMMENT; - $args->target_url = getNotEncodedFullUrl('', 'document_srl', $document_srl, '_comment_srl', $comment_srl) . '#comment_' . $comment_srl; + $args->target_url = getNotEncodedUrl('', 'document_srl', $document_srl, '_comment_srl', $comment_srl) . '#comment_' . $comment_srl; $args->target_summary = cut_str(trim(utf8_normalize_spaces(strip_tags($content))), 50) ?: (strpos($content, 'target_nick_name = $obj->nick_name; $args->target_email_address = $obj->email_address; $args->regdate = $regdate; $args->target_browser = $module_info->browser_title; $args->notify = $this->_getNotifyId($args); - $this->_insertNotify($args, $is_anonymous); + $output = $this->_insertNotify($args, $is_anonymous); + if(!$output->toBool()) + { + return $output; + } } } } @@ -331,17 +383,21 @@ class ncenterliteController extends ncenterlite $args = new stdClass(); $args->config_type = 'message'; $args->member_srl = $obj->receiver_srl; - $args->srl = $obj->related_srl; + $args->srl = $obj->message_srl; $args->target_p_srl = '1'; - $args->target_srl = $obj->message_srl; + $args->target_srl = $obj->related_srl; $args->target_member_srl = $obj->sender_srl; $args->type = $this->_TYPE_MESSAGE; $args->target_type = $this->_TYPE_MESSAGE; $args->target_summary = $obj->title; $args->regdate = date('YmdHis'); $args->notify = $this->_getNotifyId($args); - $args->target_url = getNotEncodedFullUrl('', 'act', 'dispCommunicationMessages', 'message_srl', $obj->related_srl); - $this->_insertNotify($args); + $args->target_url = getNotEncodedUrl('', 'act', 'dispCommunicationMessages', 'message_srl', $obj->related_srl); + $output = $this->_insertNotify($args); + if(!$output->toBool()) + { + return $output; + } } function triggerAfterVotedupdate(&$obj) @@ -371,8 +427,12 @@ class ncenterliteController extends ncenterlite $args->target_summary = $oDocument->get('title'); $args->regdate = date('YmdHis'); $args->notify = $this->_getNotifyId($args); - $args->target_url = getNotEncodedFullUrl('', 'document_srl', $obj->document_srl); + $args->target_url = getNotEncodedUrl('', 'document_srl', $obj->document_srl); $output = $this->_insertNotify($args); + if(!$output->toBool()) + { + return $output; + } } function triggerAfterCommentVotedCount($obj) @@ -405,7 +465,7 @@ class ncenterliteController extends ncenterlite $args->target_summary = cut_str(trim(utf8_normalize_spaces(strip_tags($content))), 50); $args->regdate = date('YmdHis'); $args->notify = $this->_getNotifyId($args); - $args->target_url = getNotEncodedFullUrl('', 'document_srl', $document_srl, '_comment_srl', $obj->comment_srl) . '#comment_' . $obj->comment_srl; + $args->target_url = getNotEncodedUrl('', 'document_srl', $document_srl, '_comment_srl', $obj->comment_srl) . '#comment_' . $obj->comment_srl; $output = $this->_insertNotify($args); if(!$output->toBool()) { @@ -539,19 +599,6 @@ class ncenterliteController extends ncenterlite { return; } - $this->_hide_ncenterlite = false; - if($oModule->module == 'beluxe' && Context::get('is_modal')) - { - $this->_hide_ncenterlite = true; - } - if($oModule->module == 'bodex' && Context::get('is_iframe')) - { - $this->_hide_ncenterlite = true; - } - if($oModule->getLayoutFile() == 'popup_layout.html') - { - $this->_hide_ncenterlite = true; - } if($oModule->act == 'dispBoardReplyComment') { @@ -635,7 +682,7 @@ class ncenterliteController extends ncenterlite } // 지식인 모듈의 의견 - // TODO: 코드 분리 + // TODO: 지식인 모듈을 사용하는지 안하는지 현재로써는 모르기 때문에 일단은 이 코드를 유지 하였다가 나중에 라이믹스용 지식인이 나온다면 변경하기 if($oModule->act == 'procKinInsertComment') { // 글, 댓글 구분 @@ -664,13 +711,17 @@ class ncenterliteController extends ncenterlite $args->target_type = $this->_TYPE_COMMENT; $args->target_srl = $vars->parent_srl; $args->target_p_srl = '1'; - $args->target_url = getNotEncodedFullUrl('', 'document_srl', $vars->document_srl, '_comment_srl', $vars->parent_srl) . '#comment_' . $vars->parent_srl; + $args->target_url = getNotEncodedUrl('', 'document_srl', $vars->document_srl, '_comment_srl', $vars->parent_srl) . '#comment_' . $vars->parent_srl; $args->target_summary = cut_str(strip_tags($vars->content), 50); $args->target_nick_name = $logged_info->nick_name; $args->target_email_address = $logged_info->email_address; $args->regdate = date('YmdHis'); $args->notify = $this->_getNotifyId($args); $output = $this->_insertNotify($args); + if(!$output->toBool()) + { + return $output; + } } } else if($oModule->act == 'dispKinView' || $oModule->act == 'dispKinIndex') @@ -711,7 +762,6 @@ class ncenterliteController extends ncenterlite function triggerBeforeDisplay(&$output_display) { - $act = Context::get('act'); // 팝업창이면 중지 if(Context::get('ncenterlite_is_popup')) { @@ -719,7 +769,7 @@ class ncenterliteController extends ncenterlite } // 자신의 알림목록을 보고 있을 경우엔 알림센터창을 띄우지 않는다. - if($act == 'dispNcenterliteNotifyList') + if(Context::get('act') == 'dispNcenterliteNotifyList') { return; } @@ -729,8 +779,8 @@ class ncenterliteController extends ncenterlite return; } - // HTML 모드가 아니면 중지 + act에 admin이 포함되어 있으면 중지 - if(Context::getResponseMethod() != 'HTML' || strpos(strtolower(Context::get('act')), 'admin') !== false) + // HTML 모드가 아니면 중지 + admin 모듈이면 중지 + if(Context::getResponseMethod() != 'HTML' || Context::get('module') == 'admin') { return; } @@ -743,13 +793,6 @@ class ncenterliteController extends ncenterlite $module_info = Context::get('module_info'); - - // admin 모듈이면 중지 - if($module_info->module == 'admin') - { - return; - } - $oNcenterliteModel = getModel('ncenterlite'); $config = $oNcenterliteModel->getConfig(); @@ -765,23 +808,27 @@ class ncenterliteController extends ncenterlite } // 노티바 제외 페이지이면 중지 - if(in_array($module_info->module_srl, $config->hide_module_srls)) + if(is_array($config->hide_module_srls) && in_array($module_info->module_srl, $config->hide_module_srls)) { return; } - + Context::set('ncenterlite_config', $config); - - $js_args = array('./modules/ncenterlite/tpl/js/ncenterlite.js', 'body', '', 100000); - Context::loadFile($js_args); - - // 알림 목록 가져오기 + + if($config->highlight_effect === 'Y') + { + Context::loadFile(array('./modules/ncenterlite/tpl/js/ncenterlite.js', 'body', '', 100000)); + } + $logged_info = Context::get('logged_info'); $_output = $oNcenterliteModel->getMyNotifyList($logged_info->member_srl); - // 알림 메시지가 없어도 항상 표시하게 하려면 이 줄을 제거 또는 주석 처리하세요. - if(!$_output->data) + + if($config->always_display !== 'Y') { - return; + if(!$_output->data) + { + return; + } } $_latest_notify_id = array_slice($_output->data, 0, 1); @@ -848,6 +895,11 @@ class ncenterliteController extends ncenterlite $target_srl = Context::get('target_srl'); $oMemberController->addMemberMenu('dispNcenterliteNotifyList', 'ncenterlite_my_list'); + } + + if($config->user_notify_setting == 'Y') + { + $oMemberController->addMemberMenu('dispNcenterliteUserConfig', 'ncenterlite_my_settings'); if($logged_info->is_admin == 'Y') { @@ -856,11 +908,6 @@ class ncenterliteController extends ncenterlite $oMemberController->addMemberPopupMenu($url, $str, ''); } } - - if($config->user_notify_setting == 'Y') - { - $oMemberController->addMemberMenu('dispNcenterliteUserConfig', 'ncenterlite_my_settings'); - } } function _addFile() @@ -922,7 +969,6 @@ class ncenterliteController extends ncenterlite $args->member_srl = $member_srl; $args->notify = $notify; $output = executeQuery('ncenterlite.updateNotifyReaded', $args); - //$output = executeQuery('ncenterlite.deleteNotify', $args); //Remove flag files $this->removeFlagFile($args->member_srl); @@ -935,7 +981,6 @@ class ncenterliteController extends ncenterlite $args->member_srl = $member_srl; $args->target_srl = $target_srl; $output = executeQuery('ncenterlite.updateNotifyReadedByTargetSrl', $args); - //$output = executeQuery('ncenterlite.deleteNotifyByTargetSrl', $args); //Remove flag files $this->removeFlagFile($args->member_srl); @@ -947,7 +992,6 @@ class ncenterliteController extends ncenterlite $args = new stdClass(); $args->member_srl = $member_srl; $output = executeQuery('ncenterlite.updateNotifyReadedAll', $args); - //$output = executeQuery('ncenterlite.deleteNotifyByMemberSrl', $args); //Remove flag files $this->removeFlagFile($args->member_srl); @@ -959,7 +1003,7 @@ class ncenterliteController extends ncenterlite $logged_info = Context::get('logged_info'); if(!Context::get('is_logged')) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $output = $this->updateNotifyReadAll($logged_info->member_srl); @@ -969,11 +1013,21 @@ class ncenterliteController extends ncenterlite function procNcenterliteRedirect() { $logged_info = Context::get('logged_info'); - $url = Context::get('url'); - $notify = Context::get('notify'); - if(!$logged_info || !$url || !$notify) + if(!$logged_info || !$logged_info->member_srl) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\MustLogin; + } + + $notify = Context::get('notify'); + if(!strlen($notify)) + { + throw new Rhymix\Framework\Exceptions\InvalidRequest; + } + + $notify_info = getModel('ncenterlite')->getNotification($notify, $logged_info->member_srl); + if (!$notify_info) + { + throw new Rhymix\Framework\Exceptions\InvalidRequest; } $output = $this->updateNotifyRead($notify, $logged_info->member_srl); @@ -982,8 +1036,7 @@ class ncenterliteController extends ncenterlite return $output; } - $url = str_replace('&', '&', $url); - header('Location: ' . $url, TRUE, 302); + header('Location: ' . $notify_info->target_url, true, 302); Context::close(); exit; } @@ -1084,24 +1137,25 @@ class ncenterliteController extends ncenterlite $args->target_email_address = ''; } - $output = executeQuery('ncenterlite.insertNotify', $args); - if(!$output->toBool()) + $trigger_output = ModuleHandler::triggerCall('ncenterlite._insertNotify', 'before', $args); + if(!$trigger_output->toBool() || $trigger_output->getMessage() === 'cancel') { - return $output; + return $trigger_output; } - else + + $output = executeQuery('ncenterlite.insertNotify', $args); + if($output->toBool()) { ModuleHandler::triggerCall('ncenterlite._insertNotify', 'after', $args); + $this->sendSmsMessage($args); + $this->sendMailMessage($args); + $this->removeFlagFile($args->member_srl); } - $this->sendSmsMessage($args); - $this->sendMailMessage($args); - $this->removeFlagFile($args->member_srl); - return $output; } - public static function updateFlagFile($member_srl = null, $output) + public static function updateFlagFile($member_srl = null, $output = null) { if(!$member_srl) { @@ -1293,14 +1347,43 @@ class ncenterliteController extends ncenterlite return false; } $content = $oNcenterliteModel->getNotificationText($args); - $content_cut = preg_replace('/<\/?(strong|)[^>]*>/', '', $content); - $mail_title = cut_str($content_cut, 20); + switch ($args->config_type) + { + case 'admin_content': + $mail_title = Context::getSiteTitle() . ' - ' . lang('ncenterlite_admin_content'); + break; + case 'comment_comment': + $mail_title = Context::getSiteTitle() . ' - ' . lang('ncenterlite_comment_comment_noti'); + break; + case 'comment': + $mail_title = Context::getSiteTitle() . ' - ' . lang('ncenterlite_comment_noti'); + break; + case 'message': + $mail_title = Context::getSiteTitle() . ' - ' . lang('ncenterlite_message_noti'); + break; + case 'vote': + $mail_title = Context::getSiteTitle() . ' - ' . lang('ncenterlite_vote_noti'); + break; + case 'mention': + $mail_title = Context::getSiteTitle() . ' - ' . lang('ncenterlite_mention_noti'); + break; + default: + return false; + } + + $target_url = $args->target_url; + if (!preg_match('!^https?://!', $target_url)) + { + $target_url = Rhymix\Framework\URL::getCurrentDomainUrl($target_url); + } + + $mail_content = sprintf("

    %s

    \n

    %s

    \n", $content, $target_url); $member_info = getModel('member')->getMemberInfoByMemberSrl($args->member_srl); $oMail = new \Rhymix\Framework\Mail(); $oMail->setSubject($mail_title); - $oMail->setBody($content); + $oMail->setBody($mail_content); $oMail->addTo($member_info->email_address, $member_info->nick_name); $oMail->send(); } @@ -1349,7 +1432,7 @@ class ncenterliteController extends ncenterlite $args->target_p_srl = $obj->document_srl; $args->target_srl = $obj->document_srl; $args->target_summary = cut_str(strip_tags($obj->title), 50); - $args->target_url = getNotEncodedFullUrl('', 'document_srl', $obj->document_srl); + $args->target_url = getNotEncodedUrl('', 'document_srl', $obj->document_srl); } elseif ($type == $this->_TYPE_COMMENT) { @@ -1364,7 +1447,7 @@ class ncenterliteController extends ncenterlite $args->srl = $obj->document_srl; $args->target_p_srl = $obj->comment_srl; $args->target_srl = $obj->comment_srl; - $args->target_url = $args->target_url = getNotEncodedFullUrl('', 'document_srl', $obj->document_srl, '_comment_srl', $obj->comment_srl) . '#comment_' . $obj->comment_srl; + $args->target_url = $args->target_url = getNotEncodedUrl('', 'document_srl', $obj->document_srl, '_comment_srl', $obj->comment_srl) . '#comment_' . $obj->comment_srl; $args->target_summary = cut_str(trim(utf8_normalize_spaces(strip_tags($obj->content))), 50) ?: (strpos($obj->content, 'config_type = 'mention'; diff --git a/modules/ncenterlite/ncenterlite.model.php b/modules/ncenterlite/ncenterlite.model.php index 6037ec8d9..360c500e4 100644 --- a/modules/ncenterlite/ncenterlite.model.php +++ b/modules/ncenterlite/ncenterlite.model.php @@ -69,6 +69,14 @@ class ncenterliteModel extends ncenterlite { $config->user_notify_setting = 'N'; } + if(!$config->anonymous_voter) + { + $config->anonymous_voter = 'N'; + } + if(!$config->highlight_effect) + { + $config->highlight_effect = 'Y'; + } self::$config = $config; } @@ -76,7 +84,7 @@ class ncenterliteModel extends ncenterlite return self::$config; } - function getNotifyTypebySrl($notify_srl='') + function getNotifyTypebySrl($notify_srl) { $args = new stdClass(); $args->notify_type_srl = $notify_srl; @@ -86,7 +94,7 @@ class ncenterliteModel extends ncenterlite return $output; } - function getNotifyTypeString($notify_srl='',$notify_args) + function getNotifyTypeString($notify_srl, $notify_args) { $this->notify_args = $notify_args; @@ -113,7 +121,7 @@ class ncenterliteModel extends ncenterlite return $this->notify_args->{$match[1]}; } - function isNotifyTypeExistsbySrl($notify_srl='') + function isNotifyTypeExistsbySrl($notify_srl) { $args = new stdClass(); $args->notify_type_srl = $notify_srl; @@ -180,21 +188,27 @@ class ncenterliteModel extends ncenterlite { $output = $this->_getMyNotifyList($member_srl, $page, $readed); } - + + $config = $this->getConfig(); $oMemberModel = getModel('member'); $list = $output->data; - + foreach($list as $k => $v) { $v->text = $this->getNotificationText($v); $v->ago = $this->getAgo($v->regdate); - $v->url = getUrl('','act','procNcenterliteRedirect', 'notify', $v->notify, 'url', $v->target_url); + $v->url = getUrl('','act','procNcenterliteRedirect', 'notify', $v->notify); + if($v->target_type === $this->_TYPE_VOTED && $config->anonymous_voter === 'Y') + { + $v->target_member_srl = $member_srl; + $v->target_nick_name = lang('anonymous'); + $v->target_user_id = $v->target_email_address = 'anonymous'; + } if($v->target_member_srl) { $profileImage = $oMemberModel->getProfileImage($v->target_member_srl); $v->profileImage = $profileImage->src; } - $list[$k] = $v; } @@ -229,6 +243,8 @@ class ncenterliteModel extends ncenterlite function _getMyNotifyList($member_srl=null, $page=1, $readed='N') { + $oNcenterliteController = getController('ncenterlite'); + if(!$member_srl) { if (!Context::get('is_logged')) @@ -262,7 +278,6 @@ class ncenterliteModel extends ncenterlite if($create_time <= $deleteOutput->regdate) { - $oNcenterliteController = getController('ncenterlite'); $oNcenterliteController->removeFlagFile($member_srl); } else @@ -292,12 +307,17 @@ class ncenterliteModel extends ncenterlite if (Rhymix\Framework\Cache::getDriverName() !== 'dummy') { - Rhymix\Framework\Cache::set($cache_key, $output); + if($page <= 1) + { + Rhymix\Framework\Cache::set($cache_key, $output); + } } - elseif($page <= 1) + else { - $oNcenterliteController = getController('ncenterlite'); - $oNcenterliteController->updateFlagFile($member_srl, $output); + if($page <= 1) + { + $oNcenterliteController->updateFlagFile($member_srl, $output); + } } return $output; @@ -399,6 +419,29 @@ class ncenterliteModel extends ncenterlite $this->add('colorset_list', $colorsets); } + /** + * Get information about a single notification. + * + * @param string $notify + * @param int $member_srl + * @return object|false + */ + public function getNotification($notify, $member_srl) + { + $args = new stdClass; + $args->notify = $notify; + $args->member_srl = $member_srl; + $output = executeQuery('ncenterlite.getNotify', $args); + if ($output->toBool() && $output->data) + { + return $output->data; + } + else + { + return false; + } + } + /** * Return the notification text. * @@ -407,29 +450,27 @@ class ncenterliteModel extends ncenterlite */ public function getNotificationText($notification) { - global $lang; - // Get the type of notification. switch ($notification->type) { // Document. case 'D': - $type = $lang->ncenterlite_document; + $type = lang('ncenterlite_document'); break; // Comment. case 'C': - $type = $lang->ncenterlite_comment; + $type = lang('ncenterlite_comment'); break; // Message. case 'E': - $type = $lang->ncenterlite_type_message; + $type = lang('ncenterlite_type_message'); break; // Test. case 'T': - $type = $lang->ncenterlite_type_test; + $type = lang('ncenterlite_type_test'); break; // Custom string. @@ -438,16 +479,16 @@ class ncenterliteModel extends ncenterlite // Insert member case 'I': - $type = $lang->cmd_signup; + $type = lang('cmd_signup'); break; // Custom language. case 'Y': - return $lang->{$notification->target_body}; + return lang($notification->target_body); // Custom language with string interpolation. case 'Z': - return vsprintf($lang->{$notification->target_body}, array( + return vsprintf(lang($notification->target_body), array( $notification->target_member_srl, // %1$d $notification->target_nick_name, // %2$s $notification->target_user_id, // %3$s @@ -462,69 +503,82 @@ class ncenterliteModel extends ncenterlite default: return $this->getNotifyTypeString($notification->notify_type, unserialize($notification->target_body)) ?: $lang->ncenterlite; } - + + $config = $this->getConfig(); + // Get the notification text. switch ($notification->target_type) { // Comment on your document. case 'C': - $str = sprintf($lang->ncenterlite_commented, $notification->target_nick_name, $type, $notification->target_summary); + $str = sprintf(lang('ncenterlite_commented'), $notification->target_nick_name, $type, $notification->target_summary); break; // Comment on a board. case 'A': - $str = sprintf($lang->ncenterlite_commented_board, $notification->target_nick_name, $notification->target_browser, $notification->target_summary); + $str = sprintf(lang('ncenterlite_commented_board'), $notification->target_nick_name, $notification->target_browser, $notification->target_summary); break; // Mentioned. case 'M': - $str = sprintf($lang->ncenterlite_mentioned, $notification->target_nick_name, $notification->target_browser, $notification->target_summary, $type); + $str = sprintf(lang('ncenterlite_mentioned'), $notification->target_nick_name, $notification->target_browser, $notification->target_summary, $type); break; // Message arrived. case 'E': - $str = sprintf($lang->ncenterlite_message_mention, $notification->target_nick_name, $notification->target_summary); + $str = sprintf(lang('ncenterlite_message_mention'), $notification->target_nick_name, $notification->target_summary); break; // Test notification. case 'T': - $str = sprintf($lang->ncenterlite_test_noti, $notification->target_nick_name); + $str = sprintf(lang('ncenterlite_test_noti'), $notification->target_nick_name); break; // New document on a board. case 'P': - $str = sprintf($lang->ncenterlite_board, $notification->target_nick_name, $notification->target_browser, $notification->target_summary); + $str = sprintf(lang('ncenterlite_board'), $notification->target_nick_name, $notification->target_browser, $notification->target_summary); break; // New document. case 'S': if($notification->target_browser) { - $str = sprintf($lang->ncenterlite_board, $notification->target_nick_name, $notification->target_browser, $notification->target_summary); + $str = sprintf(lang('ncenterlite_board'), $notification->target_nick_name, $notification->target_browser, $notification->target_summary); } else { - $str = sprintf($lang->ncenterlite_article, $notification->target_nick_name, $notification->target_summary); + $str = sprintf(lang('ncenterlite_article'), $notification->target_nick_name, $notification->target_summary); } break; // Voted. case 'V': - $str = sprintf($lang->ncenterlite_vote, $notification->target_nick_name, $notification->target_summary, $type); + if($config->anonymous_voter === 'Y') + { + $str = sprintf(lang('ncenterlite_vote_anonymous'), $notification->target_summary, $type); + } + else + { + $str = sprintf(lang('ncenterlite_vote'), $notification->target_nick_name, $notification->target_summary, $type); + } break; // Admin notification. case 'B': - $str = sprintf($lang->ncenterlite_admin_content_message, $notification->target_nick_name, $notification->target_browser, $notification->target_summary); + $str = sprintf(lang('ncenterlite_admin_content_message'), $notification->target_nick_name, $notification->target_browser, $notification->target_summary); break; case 'I': - $str = sprintf($lang->ncenterlite_insert_member_message, $notification->target_nick_name); + $str = sprintf(lang('ncenterlite_insert_member_message'), $notification->target_nick_name); + break; + + case 'G': + $str = sprintf(lang('ncenterlite_commented'), $notification->target_nick_name, $type, $notification->target_summary); break; // Other. default: - $str = $lang->ncenterlite; + $str = lang('ncenterlite'); } return $str; diff --git a/modules/ncenterlite/ncenterlite.view.php b/modules/ncenterlite/ncenterlite.view.php index 47ddc6059..aca07ec24 100644 --- a/modules/ncenterlite/ncenterlite.view.php +++ b/modules/ncenterlite/ncenterlite.view.php @@ -45,13 +45,13 @@ class ncenterliteView extends ncenterlite $config = $oNcenterliteModel->getConfig(); if($config->user_notify_setting != 'Y') { - return $this->setError('msg_not_use_user_setting'); + throw new Rhymix\Framework\Exception('msg_not_use_user_setting'); } $oMemberModel = getModel('member'); $member_srl = Context::get('member_srl'); $logged_info = Context::get('logged_info'); - if(!Context::get('is_logged')) return $this->setError('ncenterlite_stop_login_required'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exception('ncenterlite_stop_login_required'); if($logged_info->is_admin == 'Y' && $member_srl) { @@ -62,7 +62,7 @@ class ncenterliteView extends ncenterlite { if($member_srl != $logged_info->member_srl) { - return $this->setError('ncenterlite_stop_no_permission_other_user'); + throw new Rhymix\Framework\Exception('ncenterlite_stop_no_permission_other_user'); } } $output = $oNcenterliteModel->getUserConfig($member_srl); diff --git a/modules/ncenterlite/queries/deleteNcenterliteUserSettingData.xml b/modules/ncenterlite/queries/deleteNcenterliteUserSettingData.xml new file mode 100644 index 000000000..1c3784d11 --- /dev/null +++ b/modules/ncenterlite/queries/deleteNcenterliteUserSettingData.xml @@ -0,0 +1,9 @@ + + +
    {$oDocument->getRegdate("Y-m-d")} {$oDocument->get('readed_count')}
    {$mid_name}{$module_info->browser_title|autoescape}{$module_info->browser_title} {$type=='single'?$lang->cmd_select:$lang->cmd_insert}
    + + + + + + diff --git a/modules/ncenterlite/queries/deleteNotifyByTargetSrl.xml b/modules/ncenterlite/queries/deleteNotifyByTargetSrl.xml deleted file mode 100644 index 202147b77..000000000 --- a/modules/ncenterlite/queries/deleteNotifyByTargetSrl.xml +++ /dev/null @@ -1,10 +0,0 @@ - - -
    - - - - - - - diff --git a/modules/ncenterlite/queries/deleteNotify.xml b/modules/ncenterlite/queries/getNotify.xml similarity index 77% rename from modules/ncenterlite/queries/deleteNotify.xml rename to modules/ncenterlite/queries/getNotify.xml index 53f3b42a6..c0be88e16 100644 --- a/modules/ncenterlite/queries/deleteNotify.xml +++ b/modules/ncenterlite/queries/getNotify.xml @@ -1,8 +1,10 @@ - +
    - + + + diff --git a/modules/ncenterlite/queries/getOtherCommentByMemberSrl.xml b/modules/ncenterlite/queries/getOtherCommentByMemberSrl.xml new file mode 100644 index 000000000..d3e390126 --- /dev/null +++ b/modules/ncenterlite/queries/getOtherCommentByMemberSrl.xml @@ -0,0 +1,17 @@ + + +
    + + + + + + + + + + + + + + diff --git a/modules/ncenterlite/skins/default/ncenterlite.html b/modules/ncenterlite/skins/default/ncenterlite.html index 39d6ebe10..20363ed98 100644 --- a/modules/ncenterlite/skins/default/ncenterlite.html +++ b/modules/ncenterlite/skins/default/ncenterlite.html @@ -12,6 +12,8 @@ {sprintf($lang->ncenterlite_messages, $ncenterlite_page_navigation->total_count)} + + {$lang->ncenterlite_not_have_message} {sprintf($lang->ncenterlite_message, $ncenterlite_page_navigation->total_count)} @@ -42,12 +44,6 @@ // {sprintf($lang->ncenterlite_messages, $ncenterlite_page_navigation->total_count)} + + {$lang->ncenterlite_not_have_message} {sprintf($lang->ncenterlite_message, $ncenterlite_page_navigation->total_count)} @@ -41,12 +43,6 @@ //{$lang->about_mention_limit}

    +
    + +
    + + +

    {$lang->about_anonymous_voter}

    +
    +
    +
    + +
    + + +

    {$lang->about_highlight_effect}

    +
    +
    diff --git a/modules/ncenterlite/tpl/config.html b/modules/ncenterlite/tpl/config.html index e5f06c1a9..1595f1d7c 100644 --- a/modules/ncenterlite/tpl/config.html +++ b/modules/ncenterlite/tpl/config.html @@ -68,6 +68,18 @@

    {$lang->ncenterlite_display_about}

    +
    + +
    + + +

    {$lang->ncenterlite_always_display_about}

    +
    +
    diff --git a/modules/ncenterlite/tpl/header.html b/modules/ncenterlite/tpl/header.html index ec62d3f05..a560c0a3e 100644 --- a/modules/ncenterlite/tpl/header.html +++ b/modules/ncenterlite/tpl/header.html @@ -6,6 +6,7 @@
    • {$lang->ncenterlite_basic_settings}
    • {$lang->ncenterlite_advenced_config}
    • +
    • {$lang->ncenterlite_comment_all_setting}
    • {$lang->ncenterlite_mid_use}
    • {$lang->ncenterlite_skin_settings}
    • {$lang->ncenterlite_test}
    • diff --git a/modules/ncenterlite/tpl/js/ncenter_admin.js b/modules/ncenterlite/tpl/js/ncenter_admin.js index d0e656977..70a2b03a5 100644 --- a/modules/ncenterlite/tpl/js/ncenter_admin.js +++ b/modules/ncenterlite/tpl/js/ncenter_admin.js @@ -29,14 +29,3 @@ function completeGetSkinColorset(ret_obj, response_tags, params, fo_obj) sel.selectedIndex = selected_index; } - -function doDummyDataInsert() -{ - jQuery.exec_json('ncenterlite.procNcenterliteAdminInsertDummyData', {}, function completeGetDummyInfo(ret_obj){alert(ret_obj.message)}); -} - -function doDummyPushDataInsert() -{ - jQuery.exec_json('ncenterlite.procNcenterliteAdminInsertPushData', {}, function completeGetDummyPushInfo(ret_obj){alert(ret_obj.message)}); -} - diff --git a/modules/ncenterlite/tpl/othercomment.html b/modules/ncenterlite/tpl/othercomment.html new file mode 100644 index 000000000..567748528 --- /dev/null +++ b/modules/ncenterlite/tpl/othercomment.html @@ -0,0 +1,42 @@ + + + + + + + + + + +
      +
      + +
      + + +

      {$lang->ncenterlite_use_help}

      +
      +
      +
      + +
      +

      {$lang->ncenterlite_about_comment_all_select_mid}

      +
      + +
      +
      +
      +
      +
      +
      + +
      +
      + diff --git a/modules/ncenterlite/tpl/skinsetting.html b/modules/ncenterlite/tpl/skinsetting.html index 939585910..8f8ad3115 100644 --- a/modules/ncenterlite/tpl/skinsetting.html +++ b/modules/ncenterlite/tpl/skinsetting.html @@ -16,8 +16,7 @@ - {$lang->help} - +

      {$lang->about_layout}

    @@ -27,8 +26,6 @@ - {$lang->help} -
    diff --git a/modules/ncenterlite/tpl/test.html b/modules/ncenterlite/tpl/test.html index 9940af531..4952064b8 100644 --- a/modules/ncenterlite/tpl/test.html +++ b/modules/ncenterlite/tpl/test.html @@ -8,14 +8,28 @@
    - +
    +
    + + + +
    + +

    {$lang->ncenterlite_test_mention_about}

    - +
    +
    + + + +
    + +

    {$lang->ncenterlite_test_push_about}

    diff --git a/modules/page/page.admin.controller.php b/modules/page/page.admin.controller.php index b4a66f846..8835cf3b5 100644 --- a/modules/page/page.admin.controller.php +++ b/modules/page/page.admin.controller.php @@ -131,7 +131,7 @@ class pageAdminController extends page { $module_srl = Context::get('module_srl'); $content = Context::get('content'); - if(!$module_srl) return $this->setError('msg_invalid_request'); + if(!$module_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; $mcontent = Context::get('mcontent'); $type = Context::get('type'); // Guhaeom won information page @@ -301,7 +301,7 @@ class pageAdminController extends page if(!$grant->manager) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $obj = Context::getRequestVars(); diff --git a/modules/page/page.admin.view.php b/modules/page/page.admin.view.php index 3b3199f6d..511857439 100644 --- a/modules/page/page.admin.view.php +++ b/modules/page/page.admin.view.php @@ -163,7 +163,7 @@ class pageAdminView extends page { if($this->module_info->page_type == 'OUTSIDE') { - return $this->stop(-1, 'msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } if($this->module_srl) @@ -186,12 +186,13 @@ class pageAdminView extends page } else { - return $this->setError(sprintf('%s method is not exists', $method)); + throw new Rhymix\Framework\Exception(sprintf('%s method is not exists', $method)); } - + Context::set('module_info', $this->module_info); Context::set('page_content', $page_content); - + + $this->setLayoutFile(''); $this->setTemplateFile('mcontent'); } @@ -257,8 +258,13 @@ class pageAdminView extends page //Security $security = new Security(); $security->encodeHTML('widget_list..title','module_info.mid'); - + + // Load admin resources + $oTemplate = TemplateHandler::getInstance(); + $oTemplate->compile('modules/admin/tpl', '_admin_common.html'); + // Set a template file + $this->setLayoutFile(''); $this->setTemplateFile($templateFile); } @@ -294,10 +300,12 @@ class pageAdminView extends page { $oDocument->add('module_srl', $this->module_info->module_srl); } - + Context::addJsFilter($this->module_path.'tpl/filter', 'insert_article.xml'); Context::set('oDocument', $oDocument); Context::set('mid', $this->module_info->mid); + + $this->setLayoutFile(''); $this->setTemplateFile('article_content_modify'); } diff --git a/modules/page/page.mobile.php b/modules/page/page.mobile.php index 99f0d5f9c..1b4f41bf2 100644 --- a/modules/page/page.mobile.php +++ b/modules/page/page.mobile.php @@ -5,9 +5,6 @@ class pageMobile extends pageView { function init() { - // Get a template path (page in the administrative template tpl putting together) - $this->setTemplatePath($this->module_path.'tpl'); - switch($this->module_info->page_type) { case 'WIDGET' : @@ -33,12 +30,19 @@ class pageMobile extends pageView $page_type_name = strtolower($this->module_info->page_type); $method = '_get' . ucfirst($page_type_name) . 'Content'; - if (method_exists($this, $method)) $page_content = $this->{$method}(); - else return $this->setError('%s method is not exists', $method); + if (method_exists($this, $method)) + { + $page_content = $this->{$method}(); + } + else + { + throw new Rhymix\Framework\Exception(sprintf('%s method is not exists', $method)); + } Context::set('module_info', $this->module_info); Context::set('page_content', $page_content); - + + $this->setTemplatePath($this->module_path . 'tpl'); $this->setTemplateFile('mobile'); } diff --git a/modules/page/page.view.php b/modules/page/page.view.php index 6b7dbfe29..c81b839a9 100644 --- a/modules/page/page.view.php +++ b/modules/page/page.view.php @@ -19,9 +19,6 @@ class pageView extends page */ function init() { - // Get a template path (page in the administrative template tpl putting together) - $this->setTemplatePath($this->module_path.'tpl'); - switch($this->module_info->page_type) { case 'WIDGET' : @@ -50,12 +47,19 @@ class pageView extends page $page_type_name = strtolower($this->module_info->page_type); $method = '_get' . ucfirst($page_type_name) . 'Content'; - if(method_exists($this, $method)) $page_content = $this->{$method}(); - else return $this->setError('%s method is not exists', $method); + if(method_exists($this, $method)) + { + $page_content = $this->{$method}(); + } + else + { + throw new Rhymix\Framework\Exception(sprintf('%s method is not exists', $method)); + } Context::set('module_info', $this->module_info); Context::set('page_content', $page_content); - + + $this->setTemplatePath($this->module_path . 'tpl'); $this->setTemplateFile('content'); } @@ -101,15 +105,7 @@ class pageView extends page } Context::set('oDocument', $oDocument); - if ($this->module_info->skin) - { - $templatePath = (sprintf($this->module_path.'skins/%s', $this->module_info->skin)); - } - else - { - $templatePath = ($this->module_path.'skins/default'); - } - + $templatePath = sprintf('%sskins/%s', $this->module_path, $this->module_info->skin ?: 'default'); $page_content = $oTemplate->compile($templatePath, 'content'); return $page_content; diff --git a/modules/page/tpl/page_info.html b/modules/page/tpl/page_info.html index f49bddf57..b37420632 100644 --- a/modules/page/tpl/page_info.html +++ b/modules/page/tpl/page_info.html @@ -18,8 +18,7 @@
    - {$lang->help} - +

    {$lang->about_mid}

    @@ -29,8 +28,7 @@ - {$lang->help} - +

    {$lang->about_module_category}

    @@ -58,8 +56,7 @@ - {$lang->help} - +

    {$lang->about_layout}

    @@ -78,32 +75,28 @@ - {$lang->help} - +

    {$lang->about_layout}

    {$lang->unit_min} - {$lang->help} - +

    {$lang->about_page_caching_interval}

    - {$lang->help} - +

    {$lang->about_opage_path}{realpath("./")}

    - {$lang->help} - +

    {$lang->about_opage_mobile_path}{realpath("./")}

    @@ -112,8 +105,7 @@ - {$lang->help} - +

    {$lang->about_skin}

    @@ -122,8 +114,7 @@ - {$lang->help} - +

    {$lang->about_skin}

    diff --git a/modules/point/lang/en.php b/modules/point/lang/en.php index b33050adc..330d67869 100644 --- a/modules/point/lang/en.php +++ b/modules/point/lang/en.php @@ -23,6 +23,8 @@ $lang->expression = 'Please input Javascript formula by using level variable $lang->cmd_exp_calc = 'Calculate'; $lang->cmd_exp_reset = 'Reset'; $lang->cmd_point_recal = 'Reset Point'; +$lang->cmd_point_except_notice = 'Except Notice'; +$lang->cmd_point_revert_on_delete = 'Revert on Delete'; $lang->about_cmd_point_recal = 'All point will be initialized only with articles/comments/attachments/join points. Only members who do website activities will get signup points after reset. Please use this function when complete initialization is required in case of data transferring or other situations.'; $lang->default_group = 'Default Group'; $lang->point_link_group = 'Group Change by Level'; @@ -60,8 +62,8 @@ $lang->msg_disallow_by_point = 'You need more points to read the article (You ne $lang->point_recal_message = 'Adjusting Point. (%d / %d)'; $lang->point_recal_finished = 'Point recalculation is finished.'; $lang->point_update_desc = 'Insert + in front of the number to increase the point or - to decrease, and update the point. If you don\'t insert + or -, the point will be set as the value you entered.'; -$lang->give_point = 'Give the point'; -$lang->point_given_prefix = 'give'; +$lang->give_point = 'Give or Take Points'; +$lang->point_given_prefix = ''; $lang->point_given_suffix = 'points'; $lang->point_time_limit_prefix = 'until'; $lang->point_time_limit_suffix = 'days after submission'; diff --git a/modules/point/lang/ko.php b/modules/point/lang/ko.php index de0d736bc..cca0a1b18 100644 --- a/modules/point/lang/ko.php +++ b/modules/point/lang/ko.php @@ -23,6 +23,8 @@ $lang->expression = '레벨 변수 i를 사용하여 자바스크립트 $lang->cmd_exp_calc = '계산'; $lang->cmd_exp_reset = '초기화'; $lang->cmd_point_recal = '포인트 초기화'; +$lang->cmd_point_except_notice = '공지 제외'; +$lang->cmd_point_revert_on_delete = '삭제시 회수'; $lang->about_cmd_point_recal = '게시글/댓글/첨부파일/회원가입 점수만 이용하여 모든 포인트 점수를 초기화합니다. 회원 가입 점수는 초기화 후 해당 회원이 활동을 하면 부여되고 그 전에는 부여되지 않습니다. 데이터 이전 등을 하여 포인트를 완전히 초기화해야 할 경우에만 사용하세요.'; $lang->default_group = '기본 그룹'; $lang->point_link_group = '그룹 연동'; @@ -62,9 +64,9 @@ $lang->msg_disallow_by_point = '로그인하지 않았거나 포인트가 부족 $lang->point_recal_message = '포인트 적용 중입니다. (%d / %d)'; $lang->point_recal_finished = '포인트 재계산이 완료되었습니다.'; $lang->point_update_desc = '포인트를 증가시키려면 +를 감소시키려면 -를 숫자앞에 표기한 후 업데이트해 주세요. + 또는 - 표시가 없으면 입력한 값으로 설정됩니다.'; -$lang->give_point = '포인트 부여'; +$lang->give_point = '포인트 부여/차감'; $lang->point_given_prefix = ''; -$lang->point_given_suffix = '포인트 부여'; +$lang->point_given_suffix = '포인트'; $lang->point_time_limit_prefix = '작성 후'; $lang->point_time_limit_suffix = '일까지'; $lang->search_target_list['nick_name'] = '닉네임'; diff --git a/modules/point/point.admin.controller.php b/modules/point/point.admin.controller.php index f750cf855..c88d96d0e 100644 --- a/modules/point/point.admin.controller.php +++ b/modules/point/point.admin.controller.php @@ -63,6 +63,15 @@ class pointAdminController extends point $config->blamer_comment = (int)$args->blamer_comment; $config->voted_comment = (int)$args->voted_comment; $config->blamed_comment = (int)$args->blamed_comment; + + // Specify notice exceptions + $config->read_document_except_notice = ($args->read_document_except_notice === 'Y'); + $config->read_document_author_except_notice = ($args->read_document_author_except_notice === 'Y'); + + // Specify revert on delete + $config->insert_document_revert_on_delete = ($args->insert_document_revert_on_delete === 'Y'); + $config->insert_comment_revert_on_delete = ($args->insert_comment_revert_on_delete === 'Y'); + $config->upload_file_revert_on_delete = ($args->upload_file_revert_on_delete === 'Y'); // Specify time limits $config->insert_comment_limit = $config->no_point_date = (int)$args->insert_comment_limit; @@ -198,7 +207,7 @@ class pointAdminController extends point function procPointAdminInsertPointModuleConfig() { $module_srl = Context::get('target_module_srl'); - if(!$module_srl) return $this->setError('msg_invalid_request'); + if(!$module_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; // In case of batch configuration of several modules if(preg_match('/^([0-9,]+)$/',$module_srl)) $module_srl = explode(',',$module_srl); else $module_srl = array($module_srl); @@ -375,7 +384,7 @@ class pointAdminController extends point $position = (int)Context::get('position'); $total = (int)Context::get('total'); - if(!file_exists('./files/cache/pointRecal.txt')) return $this->setError('msg_invalid_request'); + if(!file_exists('./files/cache/pointRecal.txt')) throw new Rhymix\Framework\Exceptions\InvalidRequest; $idx = 0; $f = fopen("./files/cache/pointRecal.txt","r"); @@ -418,7 +427,7 @@ class pointAdminController extends point function procPointAdminReset() { $module_srl = Context::get('module_srls'); - if(!$module_srl) return $this->setError('msg_invalid_request'); + if(!$module_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; // In case of batch configuration of several modules if(preg_match('/^([0-9,]+)$/',$module_srl)) $module_srl = explode(',',$module_srl); else $module_srl = array($module_srl); diff --git a/modules/point/point.class.php b/modules/point/point.class.php index eb3130d0e..0bbf2709d 100644 --- a/modules/point/point.class.php +++ b/modules/point/point.class.php @@ -32,9 +32,11 @@ class point extends ModuleObject array('document.insertDocument', 'after', 'controller', 'triggerInsertDocument'), array('document.updateDocument', 'before', 'controller', 'triggerUpdateDocument'), array('document.deleteDocument', 'after', 'controller', 'triggerDeleteDocument'), + array('document.moveDocumentToTrash', 'after', 'controller', 'triggerTrashDocument'), array('comment.insertComment', 'after', 'controller', 'triggerInsertComment'), array('comment.updateComment', 'after', 'controller', 'triggerUpdateComment'), array('comment.deleteComment', 'after', 'controller', 'triggerDeleteComment'), + array('comment.moveCommentToTrash', 'after', 'controller', 'triggerTrashComment'), array('file.deleteFile', 'after', 'controller', 'triggerDeleteFile'), array('file.downloadFile', 'before', 'controller', 'triggerBeforeDownloadFile'), array('file.downloadFile', 'after', 'controller', 'triggerDownloadFile'), diff --git a/modules/point/point.controller.php b/modules/point/point.controller.php index b55b07263..815d49386 100644 --- a/modules/point/point.controller.php +++ b/modules/point/point.controller.php @@ -176,7 +176,7 @@ class pointController extends point } /** - * @brief A trigger to give points for deleting the post + * @brief A trigger to deduct points for deleting the post */ public function triggerDeleteDocument($obj) { @@ -186,6 +186,17 @@ class pointController extends point { return; } + if ($obj->isEmptyTrash) + { + return; + } + + // Return if disabled + $config = $this->getConfig(); + if ($config->insert_document_revert_on_delete === false) + { + return; + } // The fix to disable giving points for saving the document temporarily if ($module_srl == $member_srl) @@ -211,6 +222,14 @@ class pointController extends point $this->setPoint($member_srl, $cur_point); } + /** + * @brief A trigger to deduct points when a document is moved to Trash + */ + public function triggerTrashDocument($obj) + { + return $this->triggerDeleteDocument($obj); + } + /** * @brief A trigger which gives points for entering a comment */ @@ -275,6 +294,17 @@ class pointController extends point { return; } + if ($obj->isMoveToTrash) + { + return; + } + + // Return if disabled + $config = $this->getConfig(); + if ($config->insert_comment_revert_on_delete === false) + { + return; + } // Abort if the comment and the document have the same author. $oDocument = getModel('document')->getDocument($obj->document_srl); @@ -284,13 +314,15 @@ class pointController extends point } // Abort if the document is older than a configured limit. - $config = $this->getConfig(); $time_limit = $config->insert_comment_limit ?: $config->no_point_date; if ($time_limit > 0 && ztime($oDocument->get('regdate')) < RX_TIME - ($time_limit * 86400)) { return; } + // Get the module_srl of the document to which this comment belongs + $module_srl = $oDocument->get('module_srl'); + // Get the points of the member $cur_point = getModel('point')->getPoint($member_srl); @@ -302,6 +334,14 @@ class pointController extends point $this->setPoint($member_srl, $cur_point); } + /** + * @brief A trigger to deduct points when a comment is moved to Trash + */ + public function triggerTrashComment($obj) + { + return $this->triggerDeleteComment($obj); + } + /** * @brief Add the file registration trigger * To prevent taking points for invalid file registration this method wlil return a null object @@ -324,6 +364,13 @@ class pointController extends point return; } + // Return if disabled + $config = $this->getConfig(); + if ($config->upload_file_revert_on_delete === false) + { + return; + } + // Get the points of the member $cur_point = getModel('point')->getPoint($member_srl); @@ -442,7 +489,7 @@ class pointController extends point } // Give no points if the document is older than a configured limit. - $regdate = ztime(getModel('document')->getDocument($obj->document_srl)->get('regdate')); + $regdate = ztime($obj->get('regdate')); $config = $this->getConfig(); if ($config->read_document_limit > 0 && $regdate < RX_TIME - ($config->read_document_limit * 86400)) { @@ -453,6 +500,19 @@ class pointController extends point $author_point = 0; } + // Give no points if the document is a notice and an exception has been configured. + if ($obj->get('is_notice') === 'Y') + { + if ($config->read_document_except_notice) + { + $reader_point = 0; + } + if ($config->read_document_author_except_notice) + { + $author_point = 0; + } + } + // Adjust points of the reader. if ($reader_point) { @@ -599,7 +659,7 @@ class pointController extends point $config = $oModuleModel->getModuleConfig('point'); // Get the default configuration information - $current_point = $oPointModel->getPoint($member_srl); + $current_point = $oPointModel->getPoint($member_srl, false, $exists); $current_level = $oPointModel->getLevel($current_point, $config->level_step); // Change points @@ -641,9 +701,25 @@ class pointController extends point $oDB->begin(); // If there are points, update, if no, insert - $oPointModel = getModel('point'); - if($oPointModel->isExistsPoint($member_srl)) executeQuery("point.updatePoint", $args); - else executeQuery("point.insertPoint", $args); + if ($exists) + { + $output = executeQuery("point.updatePoint", $args); + } + else + { + $output = executeQuery("point.insertPoint", $args); + // 많은 동접시 포인트를 넣는 과정에서 미리 들어간 포인트가 있을 수 있는 문제가 있어 이를 확실하게 처리하도록 수정요청을 한 번 더 실행. + if(!$output->toBool()) + { + $output = executeQuery("point.updatePoint", $args); + } + } + + if(!$output->toBool()) + { + $oDB->rollback(); + return $output; + } // Get a new level $level = $oPointModel->getLevel($point, $config->level_step); @@ -729,7 +805,7 @@ class pointController extends point $del_group_args = new stdClass; $del_group_args->member_srl = $member_srl; $del_group_args->group_srl = implode(',', $del_group_list); - $del_group_output = executeQuery('point.deleteMemberGroup', $del_group_args); + executeQuery('point.deleteMemberGroup', $del_group_args); } // Grant a new group foreach($new_group_list as $group_srl) diff --git a/modules/point/tpl/config.html b/modules/point/tpl/config.html index 664d88163..0ace459ce 100644 --- a/modules/point/tpl/config.html +++ b/modules/point/tpl/config.html @@ -19,14 +19,14 @@
    - {$lang->about_max_level} +

    {$lang->about_max_level}

    - {$lang->about_point_name} +

    {$lang->about_point_name}

    @@ -37,7 +37,7 @@ - {$lang->about_level_icon} + {$lang->about_level_icon}
    @@ -56,31 +56,38 @@ {$lang->disable_read_document_except_robots}
    - + +
    + +
    + + +
    +

    {$lang->give_point}

    {@ $config_array = get_object_vars($config)} {@ $config_array['insert_comment_limit'] = $config_array['insert_comment_limit'] ?: $config_array['no_point_date']} {@ $action_types = array( - 'insert_document' => 0, - 'insert_comment' => 1, - 'upload_file' => 0, - 'download_file' => 0, - 'read_document' => 1, - 'voter' => 1, - 'blamer' => 1, - 'voter_comment' => 1, - 'blamer_comment' => 1, - 'download_file_author' => 0, - 'read_document_author' => 1, - 'voted' => 1, - 'blamed' => 1, - 'voted_comment' => 1, - 'blamed_comment' => 1, + 'insert_document' => ['time_limit' => 0, 'except_notice' => 0, 'revert_on_delete' => 1], + 'insert_comment' => ['time_limit' => 1, 'except_notice' => 0, 'revert_on_delete' => 1], + 'upload_file' => ['time_limit' => 0, 'except_notice' => 0, 'revert_on_delete' => 1], + 'download_file' => ['time_limit' => 0, 'except_notice' => 0, 'revert_on_delete' => 0], + 'read_document' => ['time_limit' => 1, 'except_notice' => 1, 'revert_on_delete' => 0], + 'voter' => ['time_limit' => 1, 'except_notice' => 0, 'revert_on_delete' => 0], + 'blamer' => ['time_limit' => 1, 'except_notice' => 0, 'revert_on_delete' => 0], + 'voter_comment' => ['time_limit' => 1, 'except_notice' => 0, 'revert_on_delete' => 0], + 'blamer_comment' => ['time_limit' => 1, 'except_notice' => 0, 'revert_on_delete' => 0], + 'download_file_author' => ['time_limit' => 0, 'except_notice' => 0, 'revert_on_delete' => 0], + 'read_document_author' => ['time_limit' => 1, 'except_notice' => 1, 'revert_on_delete' => 0], + 'voted' => ['time_limit' => 1, 'except_notice' => 0, 'revert_on_delete' => 0], + 'blamed' => ['time_limit' => 1, 'except_notice' => 0, 'revert_on_delete' => 0], + 'voted_comment' => ['time_limit' => 1, 'except_notice' => 0, 'revert_on_delete' => 0], + 'blamed_comment' => ['time_limit' => 1, 'except_notice' => 0, 'revert_on_delete' => 0], )}
    - + - + - + - + - - - + + + - + diff --git a/modules/spamfilter/tpl/header.html b/modules/spamfilter/tpl/header.html index 682d4a65b..d4a7b9f11 100644 --- a/modules/spamfilter/tpl/header.html +++ b/modules/spamfilter/tpl/header.html @@ -1,6 +1,7 @@ +
    -

    {$lang->spamfilter} {$lang->help}

    +

    {$lang->spamfilter}

    {$XE_VALIDATOR_MESSAGE}

    diff --git a/modules/trash/trash.admin.controller.php b/modules/trash/trash.admin.controller.php index 81b3aa4ec..b863e4613 100644 --- a/modules/trash/trash.admin.controller.php +++ b/modules/trash/trash.admin.controller.php @@ -59,9 +59,9 @@ class trashAdminController extends trash //module relation data delete... $output = $this->_relationDataDelete($isAll, $is_type, $trashSrls); - if(!$output->toBool()) return $this->setError($output->message); + if(!$output->toBool()) throw new Rhymix\Framework\Exception($output->message); - if(!$this->_emptyTrash($trashSrls)) return $this->setError($lang->fail_empty); + if(!$this->_emptyTrash($trashSrls)) throw new Rhymix\Framework\Exception($lang->fail_empty); $this->setMessage('success_deleted', 'info'); @@ -114,14 +114,14 @@ class trashAdminController extends trash { //class file check $classPath = ModuleHandler::getModulePath($oTrashVO->getOriginModule()); - if(!is_dir(FileHandler::getRealPath($classPath))) return $this->setError('not exist restore module directory'); + if(!is_dir(FileHandler::getRealPath($classPath))) throw new Rhymix\Framework\Exception('not exist restore module directory'); $classFile = sprintf('%s%s.admin.controller.php', $classPath, $oTrashVO->getOriginModule()); $classFile = FileHandler::getRealPath($classFile); - if(!file_exists($classFile)) return $this->setError('not exist restore module class file'); + if(!file_exists($classFile)) throw new Rhymix\Framework\Exception('not exist restore module class file'); $oAdminController = getAdminController($oTrashVO->getOriginModule()); - if(!method_exists($oAdminController, 'emptyTrash')) return $this->setError('not exist restore method in module class file'); + if(!method_exists($oAdminController, 'emptyTrash')) throw new Rhymix\Framework\Exception('not exist restore method in module class file'); $output2 = $oAdminController->emptyTrash($oTrashVO->getSerializedObject()); if(!$output2->toBool()) return $output; @@ -154,14 +154,14 @@ class trashAdminController extends trash //class file check $classPath = ModuleHandler::getModulePath($output->data->getOriginModule()); - if(!is_dir(FileHandler::getRealPath($classPath))) return $this->setError('not exist restore module directory'); + if(!is_dir(FileHandler::getRealPath($classPath))) throw new Rhymix\Framework\Exception('not exist restore module directory'); $classFile = sprintf('%s%s.admin.controller.php', $classPath, $output->data->getOriginModule()); $classFile = FileHandler::getRealPath($classFile); - if(!file_exists($classFile)) return $this->setError('not exist restore module class file'); + if(!file_exists($classFile)) throw new Rhymix\Framework\Exception('not exist restore module class file'); $oAdminController = getAdminController($output->data->getOriginModule()); - if(!method_exists($oAdminController, 'restoreTrash')) return $this->setError('not exist restore method in module class file'); + if(!method_exists($oAdminController, 'restoreTrash')) throw new Rhymix\Framework\Exception('not exist restore method in module class file'); $originObject = unserialize($output->data->getSerializedObject()); $output = $oAdminController->restoreTrash($originObject); @@ -176,7 +176,7 @@ class trashAdminController extends trash // restore object delete in trash box if(!$this->_emptyTrash($trashSrlList)) { $oDB->rollback(); - return $this->setError($lang->fail_empty); + throw new Rhymix\Framework\Exception($lang->fail_empty); } $oDB->commit(); } @@ -193,7 +193,7 @@ class trashAdminController extends trash */ function procTrashAdminGetList() { - if(!Context::get('is_logged')) return $this->setError('msg_not_permitted'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\NotPermitted; $trashSrls = Context::get('trash_srls'); if($trashSrls) $trashSrlList = explode(',', $trashSrls); diff --git a/modules/trash/trash.admin.view.php b/modules/trash/trash.admin.view.php index f7e07fe0a..12a5fc2ae 100644 --- a/modules/trash/trash.admin.view.php +++ b/modules/trash/trash.admin.view.php @@ -98,7 +98,7 @@ class trashAdminView extends trash $oTrashModel = getModel('trash'); $output = $oTrashModel->getTrash($trash_srl); - if(!$output->data->getTrashSrl()) return $this->setError('msg_invalid_request'); + if(!$output->data->getTrashSrl()) throw new Rhymix\Framework\Exceptions\InvalidRequest; $originObject = unserialize($output->data->getSerializedObject()); if(is_array($originObject)) $originObject = (object)$originObject; diff --git a/modules/widget/conf/module.xml b/modules/widget/conf/module.xml index d7985a382..08a43a33f 100644 --- a/modules/widget/conf/module.xml +++ b/modules/widget/conf/module.xml @@ -2,10 +2,10 @@ - - - - + + + + diff --git a/modules/widget/tpl/add_content_widget.html b/modules/widget/tpl/add_content_widget.html index 9d1a4dc3a..ac8093ecd 100644 --- a/modules/widget/tpl/add_content_widget.html +++ b/modules/widget/tpl/add_content_widget.html @@ -15,7 +15,7 @@
    -
    {$editor}
    +
    {$editor|noescape}
    {$lang->cmd_signup}{$lang->cmd_signup}  {$lang->point_given_prefix} @@ -89,7 +96,7 @@
    {$lang->cmd_login}{$lang->cmd_login}  {$lang->point_given_prefix} @@ -97,16 +104,28 @@
    {lang('point_' . $action_type)}{lang('point_' . $action_type)}  {$lang->point_given_prefix}  {$lang->point_given_suffix} + + + + + + - + {$lang->point_time_limit_prefix}   {$lang->point_time_limit_suffix} @@ -218,20 +237,3 @@

    - - \ No newline at end of file diff --git a/modules/point/tpl/header.html b/modules/point/tpl/header.html index f2b9b1e46..de21f0e31 100644 --- a/modules/point/tpl/header.html +++ b/modules/point/tpl/header.html @@ -1,6 +1,6 @@
    -

    {$lang->point} {$lang->cmd_management} {$lang->help}

    +

    {$lang->point} {$lang->cmd_management}

    • {$lang->cmd_point_config}
    • diff --git a/modules/point/tpl/member_list.html b/modules/point/tpl/member_list.html index 646fb9348..1bf6c30fc 100644 --- a/modules/point/tpl/member_list.html +++ b/modules/point/tpl/member_list.html @@ -26,7 +26,7 @@ - + {$lang->cmd_cancel} @@ -129,7 +129,7 @@ - + {$lang->cmd_cancel} diff --git a/modules/poll/poll.admin.controller.php b/modules/poll/poll.admin.controller.php index a3fd0028f..8be1eae7e 100644 --- a/modules/poll/poll.admin.controller.php +++ b/modules/poll/poll.admin.controller.php @@ -44,7 +44,7 @@ class pollAdminController extends poll else $poll_srl_list= explode('|@|', $cart); $poll_count = count($poll_srl_list); - if(!$poll_count) return $this->stop('msg_cart_is_null'); + if(!$poll_count) throw new Rhymix\Framework\Exception('msg_cart_is_null'); // Delete the post for($i=0;$i<$poll_count;$i++) { diff --git a/modules/poll/poll.admin.view.php b/modules/poll/poll.admin.view.php index 3d8a7650b..e65742301 100644 --- a/modules/poll/poll.admin.view.php +++ b/modules/poll/poll.admin.view.php @@ -139,7 +139,7 @@ class pollAdminView extends poll $args->poll_index_srl = Context::get('poll_index_srl'); $output = executeQuery('poll.getPoll', $args); - if(!$output->data) return $this->stop('msg_poll_not_exists'); + if(!$output->data) throw new Rhymix\Framework\Exception('msg_poll_not_exists'); $poll = new stdClass(); $poll->stop_date = $output->data->stop_date; @@ -148,7 +148,7 @@ class pollAdminView extends poll $output = executeQuery('poll.getPollTitle', $args); if(!$output->data) { - return $this->stop('msg_poll_not_exists'); + throw new Rhymix\Framework\Exception('msg_poll_not_exists'); } $tmp = &$poll->poll[$args->poll_index_srl]; diff --git a/modules/poll/poll.controller.php b/modules/poll/poll.controller.php index 1b836f226..f577b9242 100644 --- a/modules/poll/poll.controller.php +++ b/modules/poll/poll.controller.php @@ -102,7 +102,7 @@ class pollController extends poll } } - if(!count($args->poll)) return $this->setError('cmd_null_item'); + if(!count($args->poll)) throw new Rhymix\Framework\Exception('cmd_null_item'); $args->stop_date = $stop_date; @@ -178,12 +178,12 @@ class pollController extends poll $poll_index_srl = (int) Context::get('index_srl'); $poll_item_title = Context::get('title'); - if($poll_item_title=='') return $this->setError("msg_item_title_cannot_empty"); + if($poll_item_title=='') throw new Rhymix\Framework\Exception('msg_item_title_cannot_empty'); $logged_info = Context::get('logged_info'); - if(!$logged_info) return $this->setError("msg_cannot_add_item"); + if(!$logged_info) throw new Rhymix\Framework\Exception('msg_cannot_add_item'); - if(!$poll_srl || !$poll_index_srl) return $this->setError("msg_invalid_request"); + if(!$poll_srl || !$poll_index_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; $args = new stdClass(); $args->poll_srl = $poll_srl; @@ -191,10 +191,10 @@ class pollController extends poll // Get the information related to the survey $columnList = array('poll_type'); $output = executeQuery('poll.getPoll', $args, $columnList); - if(!$output->data) return $this->setError("poll_no_poll_or_deleted_poll"); + if(!$output->data) throw new Rhymix\Framework\Exception('poll_no_poll_or_deleted_poll'); $type = $output->data->poll_type; - if(!$this->isAbletoAddItem($type)) return $this->setError("msg_cannot_add_item"); + if(!$this->isAbletoAddItem($type)) throw new Rhymix\Framework\Exception('msg_cannot_add_item'); if($logged_info->is_admin != 'Y') { @@ -227,9 +227,9 @@ class pollController extends poll $poll_item_srl = Context::get('item_srl'); $logged_info = Context::get('logged_info'); - if(!$logged_info) return $this->setError("msg_cannot_delete_item"); + if(!$logged_info) throw new Rhymix\Framework\Exception('msg_cannot_delete_item'); - if(!$poll_srl || !$poll_index_srl || !$poll_item_srl) return $this->setError("msg_invalid_request"); + if(!$poll_srl || !$poll_index_srl || !$poll_item_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; $args = new stdClass(); $args->poll_srl = $poll_srl; @@ -245,11 +245,11 @@ class pollController extends poll // Get the information related to the survey $columnList = array('member_srl'); $output = executeQuery('poll.getPoll', $args, $columnList); - if(!$output->data) return $this->setError("poll_no_poll_or_deleted_poll"); + if(!$output->data) throw new Rhymix\Framework\Exception('poll_no_poll_or_deleted_poll'); $poll_member_srl = $output->data->member_srl; - if($add_user_srl!=$logged_info->member_srl && $poll_member_srl!=$logged_info->member_srl) return $this->setError("msg_cannot_delete_item"); - if($poll_count>0) return $this->setError("msg_cannot_delete_item_poll_exist"); + if($add_user_srl!=$logged_info->member_srl && $poll_member_srl!=$logged_info->member_srl) throw new Rhymix\Framework\Exception('msg_cannot_delete_item'); + if($poll_count>0) throw new Rhymix\Framework\Exception('msg_cannot_delete_item_poll_exist'); $oDB = &DB::getInstance(); $oDB->begin(); @@ -280,9 +280,9 @@ class pollController extends poll // Get the information related to the survey $columnList = array('poll_count', 'stop_date','poll_type'); $output = executeQuery('poll.getPoll', $args, $columnList); - if(!$output->data) return $this->setError("poll_no_poll_or_deleted_poll"); + if(!$output->data) throw new Rhymix\Framework\Exception('poll_no_poll_or_deleted_poll'); - if($output->data->stop_date < date("Ymd")) return $this->setError("msg_cannot_vote"); + if($output->data->stop_date < date("Ymd")) throw new Rhymix\Framework\Exception('msg_cannot_vote'); $columnList = array('checkcount'); $output = executeQuery('poll.getPollTitle', $args, $columnList); @@ -290,7 +290,7 @@ class pollController extends poll $poll_srl_indexes = Context::get('poll_srl_indexes'); $tmp_item_srls = explode(',',$poll_srl_indexes); - //if(count($tmp_item_srls)-1>(int)$output->data->checkcount) return $this->setError("msg_exceed_max_select"); + //if(count($tmp_item_srls)-1>(int)$output->data->checkcount) throw new Rhymix\Framework\Exception('msg_exceed_max_select'); for($i=0;$isetError('msg_check_poll_item'); + if(!count($item_srls)) throw new Rhymix\Framework\Exception('msg_check_poll_item'); // Make sure is the poll has already been taken $oPollModel = getModel('poll'); - if($oPollModel->isPolled($poll_srl)) return $this->setError('msg_already_poll'); + if($oPollModel->isPolled($poll_srl)) throw new Rhymix\Framework\Exception('msg_already_poll'); $oDB = &DB::getInstance(); $oDB->begin(); @@ -382,7 +382,7 @@ class pollController extends poll */ function procPollGetList() { - if(!Context::get('is_logged')) return $this->setError('msg_not_permitted'); + if(!Context::get('is_logged')) throw new Rhymix\Framework\Exceptions\NotPermitted; $pollSrls = Context::get('poll_srls'); if($pollSrls) $pollSrlList = explode(',', $pollSrls); diff --git a/modules/poll/tpl/poll_list.html b/modules/poll/tpl/poll_list.html index efa020893..5e502c244 100644 --- a/modules/poll/tpl/poll_list.html +++ b/modules/poll/tpl/poll_list.html @@ -6,7 +6,7 @@ xe.lang.confirm_poll_delete = '{$lang->confirm_poll_delete}';
      -

      {$lang->poll} {$lang->help}

      +

      {$lang->poll}

      {$XE_VALIDATOR_MESSAGE}

      diff --git a/modules/rss/rss.admin.controller.php b/modules/rss/rss.admin.controller.php index 4de1985fa..5241d5d06 100644 --- a/modules/rss/rss.admin.controller.php +++ b/modules/rss/rss.admin.controller.php @@ -70,7 +70,7 @@ class rssAdminController extends rss if(isset($msg['error'])) { - return $this->setError($msg['error']); + throw new Rhymix\Framework\Exception($msg['error']); } else { @@ -98,7 +98,7 @@ class rssAdminController extends rss if(!count($target_module_srls)) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } foreach($target_module_srls as $module_srl) @@ -144,7 +144,7 @@ class rssAdminController extends rss $config = getModel('rss')->getConfig(); if(!$config->image) { - return $this->setError('msg_invalid_request'); + throw new Rhymix\Framework\Exceptions\InvalidRequest; } FileHandler::removeFile($config->image); diff --git a/modules/rss/rss.model.php b/modules/rss/rss.model.php index 89cad5455..2545a0f03 100644 --- a/modules/rss/rss.model.php +++ b/modules/rss/rss.model.php @@ -14,7 +14,7 @@ class rssModel extends rss function getConfig() { - $config = getModel('module')->getModuleConfig('rss'); + $config = getModel('module')->getModuleConfig('rss') ?: new stdClass; $config->use_total_feed = $config->use_total_feed ?: 'Y'; $config->feed_document_count = $config->feed_document_count ?: 15; $config->image_url = $config->image . '?' . date('YmdHis', filemtime($config->image)); @@ -24,7 +24,7 @@ class rssModel extends rss function getRssModuleConfig($module_srl) { - $config = getModel('module')->getModulePartConfig('rss', $module_srl); + $config = getModel('module')->getModulePartConfig('rss', $module_srl) ?: new stdClass; $config->module_srl = $module_srl; $config->open_rss = $config->open_rss ?: 'N'; $config->open_total_feed = $config->open_total_feed ?: 'N'; diff --git a/modules/rss/rss.view.php b/modules/rss/rss.view.php index dd1a1080c..18599d652 100644 --- a/modules/rss/rss.view.php +++ b/modules/rss/rss.view.php @@ -179,8 +179,8 @@ class rssView extends rss $info->description = $obj->description ?: $info->description; $info->language = Context::getLangType(); $info->site_url = Context::getRequestUri(); - $info->date_r = gmdate('r'); - $info->date_c = gmdate('c'); + $info->date_r = date('r'); + $info->date_c = date('c'); $info->image = $config->image ? Context::getRequestUri() . $config->image : ''; getController('module')->replaceDefinedLangCode($info->title); diff --git a/modules/rss/tpl/format/atom10.html b/modules/rss/tpl/format/atom10.html index ac692996b..71109c9d4 100644 --- a/modules/rss/tpl/format/atom10.html +++ b/modules/rss/tpl/format/atom10.html @@ -15,8 +15,8 @@ {$oDocument->getPermanentUrl()} - {$oDocument->getRegdateGM('c')} - {$oDocument->getUpdateGM('c')} + {date('c', ztime($oDocument->get('regdate')))} + {date('c', ztime($oDocument->get('last_update')))} {$oDocument->getNickName()} diff --git a/modules/rss/tpl/format/rss10.html b/modules/rss/tpl/format/rss10.html index a354560d4..e2958947d 100644 --- a/modules/rss/tpl/format/rss10.html +++ b/modules/rss/tpl/format/rss10.html @@ -30,6 +30,6 @@ {$oDocument->getPermanentUrl()} {$oDocument->getSummary(400)|escape} {$oDocument->getNickName()} - {$oDocument->getRegdateGM('c')} + {date('c', ztime($oDocument->get('regdate')))} diff --git a/modules/rss/tpl/format/rss20.html b/modules/rss/tpl/format/rss20.html index ae9eb820a..084d9bd71 100644 --- a/modules/rss/tpl/format/rss20.html +++ b/modules/rss/tpl/format/rss20.html @@ -30,7 +30,7 @@ {$oDocument->getNickName()} {$oDocument->getPermanentUrl()} {$oDocument->getPermanentUrl()}#comment - {$oDocument->getRegdateGM('r')} + {date('r', ztime($oDocument->get('regdate')))} diff --git a/modules/rss/tpl/format/xe.html b/modules/rss/tpl/format/xe.html index c773248eb..bdb8b485f 100644 --- a/modules/rss/tpl/format/xe.html +++ b/modules/rss/tpl/format/xe.html @@ -22,8 +22,8 @@ {$oDocument->get('tags')} {$oDocument->getCommentCount()} {$oDocument->getTrackbackCount()} - {$oDocument->getRegdateGM('r')} - {$oDocument->getUpdateGM('r')} + {date('r', ztime($oDocument->get('regdate')))} + {date('r', ztime($oDocument->get('last_update')))} diff --git a/modules/rss/tpl/rss_admin_index.html b/modules/rss/tpl/rss_admin_index.html index 78c523369..e661b8a07 100644 --- a/modules/rss/tpl/rss_admin_index.html +++ b/modules/rss/tpl/rss_admin_index.html @@ -1,5 +1,5 @@
      -

      RSS {$lang->help}

      +

      RSS

      {$XE_VALIDATOR_MESSAGE}

      diff --git a/modules/spamfilter/lang/en.php b/modules/spamfilter/lang/en.php index b46ca96cc..3525a7188 100644 --- a/modules/spamfilter/lang/en.php +++ b/modules/spamfilter/lang/en.php @@ -12,9 +12,12 @@ $lang->check_trackback = 'Check Trackbacks'; $lang->word = 'Keyword'; $lang->hit = 'Hit'; $lang->latest_hit = 'Latest Hits'; +$lang->custom_message = 'Error Message'; +$lang->about_custom_message = 'You can customize the error message that will be displayed if a spam keyword is found.
      %s can be used as a placeholder for the keyword. If not used, the keyword will be hidden.'; $lang->about_interval = 'All articles attempted for posting within the assigned time will be blocked.'; $lang->about_denied_ip = 'Please enter one IP address (e.g. 127.0.0.1) or range (e.g. 127.0.0.0/24) per line. Comments may start with //.'; -$lang->about_denied_word = 'Please enter one keyword per line. Keywords may contain 2 to 40 characters.'; +$lang->about_denied_word = 'Please enter one keyword per line. Keywords may contain 2 to 180 characters.
      Formats such as /spam(key|word)?/ will be treated as a regular expression, and must use the proper syntax.
      Spam keywords are not case sensitive.'; +$lang->msg_denied_word_is_regexp = 'REGEXP'; $lang->msg_alert_limited_by_config = 'Please do not post repeatedly within %d seconds. If you keep trying, your IP address will be blocked.'; $lang->msg_alert_limited_message_by_config = 'Please do not send messages repeatedly within %d seconds. If you keep trying, your IP address will be blocked.'; $lang->msg_alert_denied_word = 'The word "%s" is not allowed on this site.'; @@ -37,5 +40,5 @@ $lang->unit_write_count = 'times'; $lang->add = 'Add'; $lang->msg_duplicate = 'Duplicate'; $lang->msg_invalid_ip = 'Invalid IP address format.'; -$lang->msg_invalid_word = 'Spam keywords must be between 2 and 40 characters.'; +$lang->msg_invalid_word = 'Spam keywords must be between 2 and 180 characters.'; $lang->msg_faillist = '
      Error (already blocked)
      %s '; diff --git a/modules/spamfilter/lang/ja.php b/modules/spamfilter/lang/ja.php index 19a8cbe5f..6b42e6cf0 100644 --- a/modules/spamfilter/lang/ja.php +++ b/modules/spamfilter/lang/ja.php @@ -29,5 +29,5 @@ $lang->yes = 'はい'; $lang->no = 'いいえ'; $lang->msg_duplicate = '既に存在します。'; $lang->msg_invalid_ip = 'IPアドレスの形式が正しくありません。'; -$lang->msg_invalid_word = 'スパムキーワードは2〜40文字の範囲で指定します。'; +$lang->msg_invalid_word = 'スパムキーワードは2〜180文字の範囲で指定します。'; $lang->msg_faillist = '
      失敗(既に存在します。)
      %s '; diff --git a/modules/spamfilter/lang/ko.php b/modules/spamfilter/lang/ko.php index 33049f86e..7da7e63e9 100644 --- a/modules/spamfilter/lang/ko.php +++ b/modules/spamfilter/lang/ko.php @@ -12,11 +12,12 @@ $lang->check_trackback = '트랙백 검사'; $lang->word = '키워드'; $lang->hit = '히트'; $lang->latest_hit = '최근 히트'; -$lang->custom_message = '에러메세지 설정'; -$lang->about_custom_message = '키워드를 출력하지 않을시 에러메세지를 설정합니다.'; +$lang->custom_message = '차단 메시지 설정'; +$lang->about_custom_message = '스팸 키워드 발견시 표시할 에러 메시지를 지정할 수 있습니다.
      %s를 넣으면 그 자리에 해당 키워드를 표시하고, 그렇지 않으면 키워드를 숨깁니다.'; $lang->about_interval = '지정된 시간 내에 글을 등록하지 못하게 합니다.'; $lang->about_denied_ip = '한 줄에 하나씩 IP 주소 또는 대역을 입력하세요. "//" 또는 "#" 뒷부분은 설명으로 저장됩니다. 예: 127.0.0.1 //설명, 127.0.0.1 #설명
      IP 대역 표기법은 매뉴얼을 참고하십시오.'; -$lang->about_denied_word = '한 줄에 하나씩 스팸 키워드를 입력하세요. (2~40자)'; +$lang->about_denied_word = '한 줄에 하나씩 스팸 키워드를 입력하세요. (2~180자)
      /스팸(키+|워드)?/ 와 같은 형태로 입력하면 정규식으로 간주하며, 올바른 정규식 문법을 사용해야 합니다.
      대소문자는 구분하지 않습니다.'; +$lang->msg_denied_word_is_regexp = '정규식'; $lang->msg_alert_limited_by_config = '%d초 이내에 연속 글 작성은 금지됩니다. 계속 시도하면 IP가 차단될 수 있습니다.'; $lang->msg_alert_limited_message_by_config = '%d초 이내에 연속 쪽지 발송은 금지됩니다. 계속 시도하면 IP가 차단될 수 있습니다.'; $lang->msg_alert_denied_word = '"%s"은(는) 사용이 금지된 단어입니다.'; @@ -39,5 +40,5 @@ $lang->unit_write_count = '회'; $lang->add = '추가'; $lang->msg_duplicate = '이미 존재합니다.'; $lang->msg_invalid_ip = 'IP 주소 형식이 올바르지 않습니다.'; -$lang->msg_invalid_word = '스팸 키워드는 2~40자 사이여야 합니다.'; +$lang->msg_invalid_word = '스팸 키워드는 2~180자 사이여야 합니다.'; $lang->msg_faillist = '
      실패 (이미 차단되어 있습니다)
      %s '; diff --git a/modules/spamfilter/queries/deleteLog.xml b/modules/spamfilter/queries/deleteLog.xml new file mode 100644 index 000000000..ee66f92af --- /dev/null +++ b/modules/spamfilter/queries/deleteLog.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/modules/spamfilter/queries/updateDeniedIPHit.xml b/modules/spamfilter/queries/updateDeniedIPHit.xml new file mode 100644 index 000000000..cd1771900 --- /dev/null +++ b/modules/spamfilter/queries/updateDeniedIPHit.xml @@ -0,0 +1,14 @@ + + +
      + + + + + + + + + + + \ No newline at end of file diff --git a/modules/spamfilter/schemas/spamfilter_denied_ip.xml b/modules/spamfilter/schemas/spamfilter_denied_ip.xml index 4911300fb..758053734 100644 --- a/modules/spamfilter/schemas/spamfilter_denied_ip.xml +++ b/modules/spamfilter/schemas/spamfilter_denied_ip.xml @@ -1,5 +1,7 @@
      + +
      diff --git a/modules/spamfilter/schemas/spamfilter_denied_word.xml b/modules/spamfilter/schemas/spamfilter_denied_word.xml index ee6dab2d7..749f30d45 100644 --- a/modules/spamfilter/schemas/spamfilter_denied_word.xml +++ b/modules/spamfilter/schemas/spamfilter_denied_word.xml @@ -1,5 +1,5 @@ - + diff --git a/modules/spamfilter/spamfilter.admin.controller.php b/modules/spamfilter/spamfilter.admin.controller.php index 463a0d4a1..1847e0fd6 100644 --- a/modules/spamfilter/spamfilter.admin.controller.php +++ b/modules/spamfilter/spamfilter.admin.controller.php @@ -66,7 +66,6 @@ class spamfilterAdminController extends spamfilter $this->setMessage(lang('success_registed').$message_fail); } - $returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : getNotEncodedUrl('', 'module', 'admin', 'act', 'dispSpamfilterAdminDeniedIPList'); $this->setRedirectUrl($returnUrl); } @@ -126,7 +125,10 @@ class spamfilterAdminController extends spamfilter $args = new stdClass; $args->ipaddress = $ipaddress; - return executeQuery('spamfilter.deleteDeniedIP', $args); + $output = executeQuery('spamfilter.deleteDeniedIP', $args); + + Rhymix\Framework\Cache::delete('spamfilter:denied_ip_list'); + return $output; } /** @@ -149,9 +151,9 @@ class spamfilterAdminController extends spamfilter continue; } - if (mb_strlen($word, 'UTF-8') < 2 || mb_strlen($word, 'UTF-8') > 40) + if (mb_strlen($word, 'UTF-8') < 2 || mb_strlen($word, 'UTF-8') > 180) { - return $this->setError('msg_invalid_word'); + throw new Rhymix\Framework\Exception('msg_invalid_word'); } $args = new stdClass; @@ -167,6 +169,8 @@ class spamfilterAdminController extends spamfilter { $output->add('fail_list', $fail_list); } + + Rhymix\Framework\Cache::delete('spamfilter:denied_word_list'); return $output; } @@ -179,7 +183,10 @@ class spamfilterAdminController extends spamfilter if(!$word) return; $args = new stdClass; $args->word = $word; - return executeQuery('spamfilter.deleteDeniedWord', $args); + $output = executeQuery('spamfilter.deleteDeniedWord', $args); + + Rhymix\Framework\Cache::delete('spamfilter:denied_word_list'); + return $output; } } /* End of file spamfilter.admin.controller.php */ diff --git a/modules/spamfilter/spamfilter.admin.view.php b/modules/spamfilter/spamfilter.admin.view.php index 992a27d28..b2dc62e3f 100644 --- a/modules/spamfilter/spamfilter.admin.view.php +++ b/modules/spamfilter/spamfilter.admin.view.php @@ -21,9 +21,16 @@ class spamfilterAdminView extends spamfilter */ function dispSpamfilterAdminDeniedIPList() { + // Get sort index + $sort_index = Context::get('sort_index'); + if (!in_array($sort_index, array('regdate', 'latest_hit', 'hit'))) + { + $sort_index = 'regdate'; + } + // Get the list of denied IP addresses and words $oSpamFilterModel = getModel('spamfilter'); - $ip_list = $oSpamFilterModel->getDeniedIPList(); + $ip_list = $oSpamFilterModel->getDeniedIPList($sort_index); Context::set('ip_list', $ip_list); $security = new Security(); @@ -39,9 +46,16 @@ class spamfilterAdminView extends spamfilter */ function dispSpamfilterAdminDeniedWordList() { + // Get sort index + $sort_index = Context::get('sort_index'); + if (!in_array($sort_index, array('regdate', 'latest_hit', 'hit'))) + { + $sort_index = 'hit'; + } + // Get the list of denied IP addresses and words $oSpamFilterModel = getModel('spamfilter'); - $word_list = $oSpamFilterModel->getDeniedWordList(); + $word_list = $oSpamFilterModel->getDeniedWordList($sort_index); Context::set('word_list', $word_list); $security = new Security(); diff --git a/modules/spamfilter/spamfilter.class.php b/modules/spamfilter/spamfilter.class.php index d55425133..9d996720f 100644 --- a/modules/spamfilter/spamfilter.class.php +++ b/modules/spamfilter/spamfilter.class.php @@ -47,7 +47,8 @@ class spamfilter extends ModuleObject */ if(!$oDB->isColumnExists('spamfilter_denied_word', 'hit')) return true; if(!$oDB->isColumnExists('spamfilter_denied_word', 'latest_hit')) return true; - + if(!$oDB->isColumnExists('spamfilter_denied_ip', 'hit')) return true; + if(!$oDB->isColumnExists('spamfilter_denied_ip', 'latest_hit')) return true; if(!$oDB->isColumnExists('spamfilter_denied_ip', 'description')) return true; if(!$oModuleModel->getTrigger('document.manage', 'spamfilter', 'controller', 'triggerManageDocument', 'before')) @@ -102,7 +103,16 @@ class spamfilter extends ModuleObject $oDB->addColumn('spamfilter_denied_word','latest_hit','date'); $oDB->addIndex('spamfilter_denied_word','idx_latest_hit', 'latest_hit'); } - + if(!$oDB->isColumnExists('spamfilter_denied_ip', 'hit')) + { + $oDB->addColumn('spamfilter_denied_ip','hit','number',12,0,true); + $oDB->addIndex('spamfilter_denied_ip','idx_hit', 'hit'); + } + if(!$oDB->isColumnExists('spamfilter_denied_ip', 'latest_hit')) + { + $oDB->addColumn('spamfilter_denied_ip','latest_hit','date'); + $oDB->addIndex('spamfilter_denied_ip','idx_latest_hit', 'latest_hit'); + } if(!$oDB->isColumnExists('spamfilter_denied_ip', 'description')) { $oDB->addColumn('spamfilter_denied_ip','description','varchar', 250); diff --git a/modules/spamfilter/spamfilter.controller.php b/modules/spamfilter/spamfilter.controller.php index ae8a8615a..6b857f800 100644 --- a/modules/spamfilter/spamfilter.controller.php +++ b/modules/spamfilter/spamfilter.controller.php @@ -195,6 +195,7 @@ class spamfilterController extends spamfilter $output->add('fail_list', $fail_list); } + Rhymix\Framework\Cache::delete('spamfilter:denied_ip_list'); return $output; } diff --git a/modules/spamfilter/spamfilter.model.php b/modules/spamfilter/spamfilter.model.php index c747fb00d..1528ff660 100644 --- a/modules/spamfilter/spamfilter.model.php +++ b/modules/spamfilter/spamfilter.model.php @@ -27,13 +27,13 @@ class spamfilterModel extends spamfilter /** * @brief Return the list of registered IP addresses which were banned */ - function getDeniedIPList() + function getDeniedIPList($sort_index = 'regdate') { $args = new stdClass(); - $args->sort_index = "regdate"; + $args->sort_index = $sort_index; $args->page = Context::get('page')?Context::get('page'):1; $output = executeQueryArray('spamfilter.getDeniedIPList', $args); - if(!$output->data) return; + if(!$output->data) return array(); return $output->data; } @@ -42,18 +42,25 @@ class spamfilterModel extends spamfilter */ function isDeniedIP() { - $ip_list = $this->getDeniedIPList(); + $ip_list = Rhymix\Framework\Cache::get('spamfilter:denied_ip_list'); + if ($ip_list === null) + { + $ip_list = $this->getDeniedIPList(); + Rhymix\Framework\Cache::set('spamfilter:denied_ip_list', $ip_list); + } if(!count($ip_list)) return new BaseObject(); $ip_ranges = array(); foreach ($ip_list as $ip_range) { - $ip_ranges[] = $ip_range->ipaddress; - } - - if (Rhymix\Framework\Filters\IpFilter::inRanges(\RX_CLIENT_IP, $ip_ranges)) - { - return new BaseObject(-1, 'msg_alert_registered_denied_ip'); + if (Rhymix\Framework\Filters\IpFilter::inRange(\RX_CLIENT_IP, $ip_range->ipaddress)) + { + $args = new stdClass(); + $args->ipaddress = $ip_range->ipaddress; + executeQuery('spamfilter.updateDeniedIPHit', $args); + + return new BaseObject(-1, 'msg_alert_registered_denied_ip'); + } } return new BaseObject(); @@ -62,14 +69,12 @@ class spamfilterModel extends spamfilter /** * @brief Return the list of registered Words which were banned */ - function getDeniedWordList() + function getDeniedWordList($sort_index = 'hit') { $args = new stdClass(); - $args->sort_index = "hit"; - $output = executeQuery('spamfilter.getDeniedWordList', $args); - if(!$output->data) return; - if(!is_array($output->data)) return array($output->data); - return $output->data; + $args->sort_index = $sort_index; + $output = executeQueryArray('spamfilter.getDeniedWordList', $args); + return $output->data ?: array(); } /** @@ -77,14 +82,28 @@ class spamfilterModel extends spamfilter */ function isDeniedWord($text) { - $word_list = $this->getDeniedWordList(); + $word_list = Rhymix\Framework\Cache::get('spamfilter:denied_word_list'); + if ($word_list === null) + { + $word_list = $this->getDeniedWordList(); + Rhymix\Framework\Cache::set('spamfilter:denied_word_list', $ip_list); + } if(!count($word_list)) return new BaseObject(); - $text = utf8_trim(utf8_normalize_spaces(htmlspecialchars_decode(strip_tags($text, '')))); + $text = strtolower(utf8_trim(utf8_normalize_spaces(htmlspecialchars_decode(strip_tags($text, ''))))); foreach ($word_list as $word_item) { $word = $word_item->word; - if (strpos($text, $word) !== false) + $hit = false; + if (preg_match('#^/.+/$#', $word)) + { + $hit = preg_match($word . 'iu', $text, $matches) ? $matches[0] : false; + } + if ($hit === false) + { + $hit = (strpos($text, strtolower($word)) !== false) ? $word : false; + } + if ($hit !== false) { $args = new stdClass(); $args->word = $word; @@ -106,9 +125,14 @@ class spamfilterModel extends spamfilter } else { - $custom_message = sprintf(lang('msg_alert_denied_word'), $word); + $custom_message = lang('msg_alert_denied_word'); } + if (strpos($custom_message, '%s') !== false) + { + $custom_message = sprintf($custom_message, escape($hit, false)); + } + return new BaseObject(-1, $custom_message); } } diff --git a/modules/spamfilter/tpl/css/spamfilter_admin.css b/modules/spamfilter/tpl/css/spamfilter_admin.css new file mode 100644 index 000000000..74c6fef0b --- /dev/null +++ b/modules/spamfilter/tpl/css/spamfilter_admin.css @@ -0,0 +1,5 @@ +span.is_regexp { + display: inline-block; + margin-left: 4px; + color: red; +} \ No newline at end of file diff --git a/modules/spamfilter/tpl/denied_ip_list.html b/modules/spamfilter/tpl/denied_ip_list.html index 26d1c664e..b2150dacf 100644 --- a/modules/spamfilter/tpl/denied_ip_list.html +++ b/modules/spamfilter/tpl/denied_ip_list.html @@ -18,7 +18,9 @@ - + + + @@ -26,11 +28,13 @@ + + - +
      IP {$lang->description}{$lang->regdate}{$lang->latest_hit} {$lang->hit} {$lang->regdate}
      {$ip_info->ipaddress} {$ip_info->description}{zdate($ip_info->latest_hit,'Y-m-d H:i')}-{$ip_info->hit} {zdate($ip_info->regdate,'Y-m-d')}
      {$lang->no_data}{$lang->no_data}
      diff --git a/modules/spamfilter/tpl/denied_word_list.html b/modules/spamfilter/tpl/denied_word_list.html index 1a521141a..160c01a1b 100644 --- a/modules/spamfilter/tpl/denied_word_list.html +++ b/modules/spamfilter/tpl/denied_word_list.html @@ -17,15 +17,15 @@
    {$lang->word}{$lang->latest_hit}{$lang->hit}{$lang->regdate}{$lang->latest_hit} {$lang->hit} {$lang->regdate}
    {$word_info->word}{$word_info->word} [{$lang->msg_denied_word_is_regexp}] {zdate($word_info->latest_hit,'Y-m-d H:i')}- {$word_info->hit} {zdate($word_info->regdate,'Y-m-d')}
    - - - + + + @@ -27,13 +27,13 @@

    - - + diff --git a/modules/widget/tpl/header.html b/modules/widget/tpl/header.html index 737ae33d7..f37ea6a06 100644 --- a/modules/widget/tpl/header.html +++ b/modules/widget/tpl/header.html @@ -1,6 +1,6 @@

    - {$lang->installed_widgets} {$lang->help} + {$lang->installed_widgets} > {$widget_info->title} {$lang->help} diff --git a/modules/widget/tpl/js/widget.js b/modules/widget/tpl/js/widget.js index 2656ebc4b..6e89920c9 100644 --- a/modules/widget/tpl/js/widget.js +++ b/modules/widget/tpl/js/widget.js @@ -747,7 +747,11 @@ function doApplyWidgetSize(fo_obj) { var $selectedSizeWidget = jQuery(selectedSizeWidget); var css_class = $form.find('#css_class').val(); - if(css_class) $selectedSizeWidget.attr('css_class', css_class); + if(css_class) { + $selectedSizeWidget.attr('css_class', css_class); + } else { + $selectedSizeWidget.attr('css_class', ''); + } var width = _getSize(fo_obj.width.value); if(width) selectedSizeWidget.style.width = width; diff --git a/modules/widget/widget.admin.view.php b/modules/widget/widget.admin.view.php index fb2a5be16..702b44091 100644 --- a/modules/widget/widget.admin.view.php +++ b/modules/widget/widget.admin.view.php @@ -59,7 +59,7 @@ class widgetAdminView extends widget function dispWidgetAdminAddContent() { $module_srl = Context::get('module_srl'); - if(!$module_srl) return $this->stop("msg_invalid_request"); + if(!$module_srl) throw new Rhymix\Framework\Exceptions\InvalidRequest; $document_srl = Context::get('document_srl'); $oDocumentModel = getModel('document'); @@ -79,7 +79,7 @@ class widgetAdminView extends widget $security->encodeHTML('member_config..'); $this->setLayoutPath('./common/tpl'); - $this->setLayoutFile("default_layout"); + $this->setLayoutFile("popup_layout"); $this->setTemplateFile('add_content_widget'); } } diff --git a/modules/widget/widget.controller.php b/modules/widget/widget.controller.php index 4bb253a4f..98674cf0c 100644 --- a/modules/widget/widget.controller.php +++ b/modules/widget/widget.controller.php @@ -47,8 +47,8 @@ class widgetController extends widget function procWidgetGenerateCode() { $widget = Context::get('selected_widget'); - if(!$widget) return $this->setError('msg_invalid_request'); - if(!Context::get('skin')) return $this->setError('msg_widget_skin_is_null'); + if(!$widget) throw new Rhymix\Framework\Exceptions\InvalidRequest; + if(!Context::get('skin')) throw new Rhymix\Framework\Exception('msg_widget_skin_is_null'); $attribute = $this->arrangeWidgetVars($widget, Context::getRequestVars(), $vars); @@ -63,9 +63,9 @@ class widgetController extends widget function procWidgetGenerateCodeInPage() { $widget = Context::get('selected_widget'); - if(!$widget) return $this->setError('msg_invalid_request'); + if(!$widget) throw new Rhymix\Framework\Exceptions\InvalidRequest; - if(!in_array($widget,array('widgetBox','widgetContent')) && !Context::get('skin')) return $this->setError('msg_widget_skin_is_null'); + if(!in_array($widget,array('widgetBox','widgetContent')) && !Context::get('skin')) throw new Rhymix\Framework\Exception('msg_widget_skin_is_null'); $attribute = $this->arrangeWidgetVars($widget, Context::getRequestVars(), $vars); // Wanted results @@ -112,18 +112,18 @@ class widgetController extends widget $page_info = $oModuleModel->getModuleInfoByModuleSrl($module_srl, $columnList); if(!$page_info->module_srl || $page_info->module != 'page') $err++; - if($err > 1) return $this->setError('msg_invalid_request'); + if($err > 1) throw new Rhymix\Framework\Exceptions\InvalidRequest; // Check permissions $logged_info = Context::get('logged_info'); if (!$logged_info->member_srl) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $module_grant = $oModuleModel->getGrant($page_info, $logged_info); if (!$module_grant->manager) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } // Enter post @@ -167,25 +167,25 @@ class widgetController extends widget $oDocumentAdminController = getAdminController('document'); $oDocument = $oDocumentModel->getDocument($document_srl); - if(!$oDocument->isExists()) return $this->setError('msg_invalid_request'); + if(!$oDocument->isExists()) throw new Rhymix\Framework\Exceptions\InvalidRequest; $module_srl = $oDocument->get('module_srl'); // Destination Information Wanted page module $oModuleModel = getModel('module'); $columnList = array('module_srl', 'module'); $page_info = $oModuleModel->getModuleInfoByModuleSrl($module_srl, $columnList); - if(!$page_info->module_srl || $page_info->module != 'page') return $this->setError('msg_invalid_request'); + if(!$page_info->module_srl || $page_info->module != 'page') throw new Rhymix\Framework\Exceptions\InvalidRequest; // Check permissions $logged_info = Context::get('logged_info'); if (!$logged_info->member_srl) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $module_grant = $oModuleModel->getGrant($page_info, $logged_info); if (!$module_grant->manager) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $output = $oDocumentAdminController->copyDocumentModule(array($oDocument->get('document_srl')), $oDocument->get('module_srl'),0); @@ -214,18 +214,18 @@ class widgetController extends widget // Destination Information Wanted page module $oModuleModel = getModel('module'); $page_info = $oModuleModel->getModuleInfoByModuleSrl($module_srl); - if(!$page_info->module_srl || $page_info->module != 'page') return $this->setError('msg_invalid_request'); + if(!$page_info->module_srl || $page_info->module != 'page') throw new Rhymix\Framework\Exceptions\InvalidRequest; // Check permissions $logged_info = Context::get('logged_info'); if (!$logged_info->member_srl) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $module_grant = $oModuleModel->getGrant($page_info, $logged_info); if (!$module_grant->manager) { - return $this->setError('msg_not_permitted'); + throw new Rhymix\Framework\Exceptions\NotPermitted; } $output = $oDocumentController->deleteDocument($oDocument->get('document_srl')); diff --git a/modules/widget/widget.view.php b/modules/widget/widget.view.php index 226c8a939..5d4272ced 100644 --- a/modules/widget/widget.view.php +++ b/modules/widget/widget.view.php @@ -121,7 +121,7 @@ class widgetView extends widget if(!Context::get('selected_widget')) Context::set('selected_widget',$widget_list[0]->widget); $this->dispWidgetGenerateCode(); - $this->setLayoutFile('default_layout'); + $this->setLayoutFile('popup_layout'); $this->setTemplateFile('widget_generate_code_in_page'); } @@ -143,7 +143,7 @@ class widgetView extends widget } $this->dispWidgetGenerateCode(); - $this->setLayoutFile('default_layout'); + $this->setLayoutFile('popup_layout'); $this->setTemplateFile('widget_style_generate_code_in_page'); } } diff --git a/tests/_data/security/example.svg b/tests/_data/security/example.svg new file mode 100644 index 000000000..438734c17 --- /dev/null +++ b/tests/_data/security/example.svg @@ -0,0 +1,69 @@ + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/tests/_data/security/ssrf.svg b/tests/_data/security/ssrf.svg new file mode 100644 index 000000000..bca6fc67f --- /dev/null +++ b/tests/_data/security/ssrf.svg @@ -0,0 +1,5 @@ + + + +test + \ No newline at end of file diff --git a/tests/_data/security/xss.svg b/tests/_data/security/xss.svg new file mode 100644 index 000000000..63270b5bd --- /dev/null +++ b/tests/_data/security/xss.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/tests/unit/classes/FrontEndFileHandlerTest.php b/tests/unit/classes/FrontEndFileHandlerTest.php index dfe99509c..a0dc55837 100644 --- a/tests/unit/classes/FrontEndFileHandlerTest.php +++ b/tests/unit/classes/FrontEndFileHandlerTest.php @@ -258,6 +258,7 @@ class FrontEndFileHandlerTest extends \Codeception\TestCase\Test $handler->loadFile(array('./common/js/jquery-1.x.min.js')); $handler->loadFile(array('./common/js/jquery-2.0.0.js')); $handler->loadFile(array('./common/js/jQuery.min.js')); + $handler->loadFile(array('http://code.jquery.com/jquery-latest.js')); $result = $handler->getCssFileList(); $this->assertEquals(0, count($result)); $result = $handler->getJsFileList(); diff --git a/tests/unit/classes/TemplateHandlerTest.php b/tests/unit/classes/TemplateHandlerTest.php index 450ecf5f1..7199614f8 100644 --- a/tests/unit/classes/TemplateHandlerTest.php +++ b/tests/unit/classes/TemplateHandlerTest.php @@ -170,7 +170,7 @@ class TemplateHandlerTest extends \Codeception\TestCase\Test // error case - inline javascript array( '
    ', - '?>
    ' + '?>
    ' ), // issue 103 array( @@ -304,35 +304,35 @@ class TemplateHandlerTest extends \Codeception\TestCase\Test // Rhymix autoescape array( '{$foo}', - PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) : $__Context->foo) ?>' + PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_QUOTES, \'UTF-8\', false) : ($__Context->foo)) ?>' ), array( '{$foo}', - PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) : $__Context->foo) ?>' + PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_QUOTES, \'UTF-8\', false) : ($__Context->foo)) ?>' ), array( '{$foo|auto}', - PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) : $__Context->foo) ?>' + PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_QUOTES, \'UTF-8\', false) : ($__Context->foo)) ?>' ), array( '{$foo|auto}', - PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) : $__Context->foo) ?>' + PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_QUOTES, \'UTF-8\', false) : ($__Context->foo)) ?>' ), array( '{$foo|autoescape}', - PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) ?>' + PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo htmlspecialchars($__Context->foo, ENT_QUOTES, \'UTF-8\', false) ?>' ), array( '{$foo|autoescape}', - PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) ?>' + PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo htmlspecialchars($__Context->foo, ENT_QUOTES, \'UTF-8\', false) ?>' ), array( '{$foo|escape}', - PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', true) ?>' + PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo htmlspecialchars($__Context->foo, ENT_QUOTES, \'UTF-8\', true) ?>' ), array( '{$foo|escape}', - PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', true) ?>' + PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo htmlspecialchars($__Context->foo, ENT_QUOTES, \'UTF-8\', true) ?>' ), array( '{$foo|noescape}', @@ -345,7 +345,7 @@ class TemplateHandlerTest extends \Codeception\TestCase\Test // Rhymix filters array( '

    {$foo|escape}

    ', - '?>

    foo, ENT_COMPAT, \'UTF-8\', true) ?>

    ' + '?>

    foo, ENT_QUOTES, \'UTF-8\', true) ?>

    ' ), array( '

    {$foo|json}

    ', @@ -399,6 +399,14 @@ class TemplateHandlerTest extends \Codeception\TestCase\Test '

    {$foo|format:2}

    ', '?>

    foo, \'2\') ?>

    ' ), + array( + '

    {$foo|shorten}

    ', + '?>

    foo) ?>

    ' + ), + array( + '

    {$foo|shorten:2}

    ', + '?>

    foo, \'2\') ?>

    ' + ), array( '

    {$foo|date:His}

    ', '?>

    foo), \'His\') ?>

    ' @@ -417,7 +425,7 @@ class TemplateHandlerTest extends \Codeception\TestCase\Test ), array( '

    {$foo|link:$url}

    ', - PHP_EOL . '$this->config->autoescape = \'on\'; ?>

    config->autoescape === \'on\' ? htmlspecialchars($__Context->url, ENT_COMPAT, \'UTF-8\', false) : $__Context->url) . \'">\' . ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) : $__Context->foo) . \'\' ?>

    ' + PHP_EOL . '$this->config->autoescape = \'on\'; ?>

    config->autoescape === \'on\' ? htmlspecialchars($__Context->url, ENT_QUOTES, \'UTF-8\', false) : ($__Context->url)) . \'">\' . ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_QUOTES, \'UTF-8\', false) : ($__Context->foo)) . \'\' ?>

    ' ), // Rhymix filters (reject malformed filters) array( diff --git a/tests/unit/framework/KoreaTest.php b/tests/unit/framework/KoreaTest.php index 958af741b..e7fdaeba2 100644 --- a/tests/unit/framework/KoreaTest.php +++ b/tests/unit/framework/KoreaTest.php @@ -13,6 +13,8 @@ class KoreaTest extends \Codeception\TestCase\Test $this->assertEquals('010-6666-7777', Rhymix\Framework\Korea::formatPhoneNumber('82+1066667777')); $this->assertEquals('0303-456-7890', Rhymix\Framework\Korea::formatPhoneNumber('03034567890')); $this->assertEquals('0505-987-6543', Rhymix\Framework\Korea::formatPhoneNumber('050-5987-6543')); + $this->assertEquals('0303-4567-8900', Rhymix\Framework\Korea::formatPhoneNumber('030345678900')); + $this->assertEquals('0505-9876-5432', Rhymix\Framework\Korea::formatPhoneNumber('050-5987-65432')); $this->assertEquals('070-7432-1000', Rhymix\Framework\Korea::formatPhoneNumber('0707-432-1000')); } @@ -26,12 +28,16 @@ class KoreaTest extends \Codeception\TestCase\Test $this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('053-4444-5555')); $this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('011-444-5555')); $this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('010-4444-5555')); + $this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('0303-4444-5555')); + $this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('0505-4444-5555')); $this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('010-4444-55555')); $this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('010-1234-5678')); $this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('02-123-4567')); $this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('02-123456')); $this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('03-456-7890')); $this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('090-9876-5432')); + $this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('0303-1111-5432')); + $this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('0505-9876-543210')); } public function testIsValidMobilePhoneNumber() diff --git a/tests/unit/framework/MailTest.php b/tests/unit/framework/MailTest.php index 90ac557fa..801b384af 100644 --- a/tests/unit/framework/MailTest.php +++ b/tests/unit/framework/MailTest.php @@ -173,4 +173,12 @@ class MailTest extends \Codeception\TestCase\Test $this->assertEquals('embed', $attachments[1]->type); $this->assertEquals('cid:thisismyrandomcid@rhymix.org', $attachments[1]->cid); } + + public function testEmailAddressValidator() + { + $this->assertEquals('devops@rhymix.org', Mail::isVaildMailAddress('devops@rhymix.org')); + $this->assertEquals('some+thing@gmail.com', Mail::isVaildMailAddress('some+thing@gmail.com')); + $this->assertEquals('weird@localhost', Mail::isVaildMailAddress('weird@localhost')); + $this->assertEquals('', Mail::isVaildMailAddress('invalid@')); + } } diff --git a/tests/unit/framework/SecurityTest.php b/tests/unit/framework/SecurityTest.php index e86859fbe..59c676ba3 100644 --- a/tests/unit/framework/SecurityTest.php +++ b/tests/unit/framework/SecurityTest.php @@ -145,27 +145,27 @@ class SecurityTest extends \Codeception\TestCase\Test error_reporting($error_reporting); } - public function testCheckXEE() + public function testCheckXXE() { $xml = ''; - $this->assertTrue(Rhymix\Framework\Security::checkXEE($xml)); + $this->assertTrue(Rhymix\Framework\Security::checkXXE($xml)); $xml = ''; - $this->assertTrue(Rhymix\Framework\Security::checkXEE($xml)); + $this->assertTrue(Rhymix\Framework\Security::checkXXE($xml)); $xml = ''; - $this->assertTrue(Rhymix\Framework\Security::checkXEE($xml)); + $this->assertTrue(Rhymix\Framework\Security::checkXXE($xml)); $xml = ''; - $this->assertFalse(Rhymix\Framework\Security::checkXEE($xml)); + $this->assertFalse(Rhymix\Framework\Security::checkXXE($xml)); $xml = ''; - $this->assertFalse(Rhymix\Framework\Security::checkXEE($xml)); + $this->assertFalse(Rhymix\Framework\Security::checkXXE($xml)); $xml = ''; - $this->assertFalse(Rhymix\Framework\Security::checkXEE($xml)); + $this->assertFalse(Rhymix\Framework\Security::checkXXE($xml)); $xml = ']>'; - $this->assertFalse(Rhymix\Framework\Security::checkXEE($xml)); + $this->assertFalse(Rhymix\Framework\Security::checkXXE($xml)); } } diff --git a/tests/unit/framework/filters/FileContentFilterTest.php b/tests/unit/framework/filters/FileContentFilterTest.php new file mode 100644 index 000000000..5cacfe45c --- /dev/null +++ b/tests/unit/framework/filters/FileContentFilterTest.php @@ -0,0 +1,14 @@ +assertTrue(FileContentFilter::check(\RX_BASEDIR . 'tests/_data/security/example.svg')); + $this->assertFalse(FileContentFilter::check(\RX_BASEDIR . 'tests/_data/security/ssrf.svg')); + $this->assertFalse(FileContentFilter::check(\RX_BASEDIR . 'tests/_data/security/ssrf.svg', 'cover.jpg')); + $this->assertFalse(FileContentFilter::check(\RX_BASEDIR . 'tests/_data/security/xss.svg')); + } +} diff --git a/tests/unit/functions/FunctionsTest.php b/tests/unit/functions/FunctionsTest.php index d2ee628c0..f9ccc4792 100644 --- a/tests/unit/functions/FunctionsTest.php +++ b/tests/unit/functions/FunctionsTest.php @@ -103,6 +103,37 @@ class FunctionsTest extends \Codeception\TestCase\Test $this->assertEquals('Rhymix ^~', base64_decode_urlsafe('Umh5bWl4IF5-')); } + public function testNumberShorten() + { + $this->assertEquals('1', number_shorten(1)); + $this->assertEquals('12', number_shorten(12)); + $this->assertEquals('123', number_shorten(123)); + $this->assertEquals('1.2K', number_shorten(1234)); + $this->assertEquals('12K', number_shorten(12345)); + $this->assertEquals('123K', number_shorten(123456)); + $this->assertEquals('1.2M', number_shorten(1234567)); + $this->assertEquals('12M', number_shorten(12345678)); + $this->assertEquals('123M', number_shorten(123456789)); + $this->assertEquals('1.2G', number_shorten(1234567890)); + $this->assertEquals('12G', number_shorten(12345678900)); + $this->assertEquals('123G', number_shorten(123456789000)); + $this->assertEquals('1.2T', number_shorten(1234567890000)); + $this->assertEquals('12T', number_shorten(12345678900000)); + $this->assertEquals('123T', number_shorten(123456789000000)); + $this->assertEquals('1234T', number_shorten(1234567890000000)); + $this->assertEquals('123', number_shorten(123, 1)); + $this->assertEquals('1K', number_shorten(1234, 1)); + $this->assertEquals('12K', number_shorten(12345, 1)); + $this->assertEquals('5.68K', number_shorten(5678, 3)); + $this->assertEquals('56.8K', number_shorten(56789, 3)); + $this->assertEquals('9.877M', number_shorten(9876543, 4)); + $this->assertEquals('98.77M', number_shorten(98765432, 4)); + $this->assertEquals('3.3333G', number_shorten(3333333333, 5)); + $this->assertEquals('33.333G', number_shorten(33333333333, 5)); + $this->assertEquals('1.00000T', number_shorten(1000000000000, 6)); + $this->assertEquals('10.0000T', number_shorten(10000000000000, 6)); + } + public function testHex2Rgb2Hex() { $this->assertEquals(array(128, 128, 128), hex2rgb('808080')); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index e052fd060..69c4dd664 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -10,6 +10,70 @@ return array( 'AWSEmptyResponseException' => $vendorDir . '/jmhobbs/swiftmailer-transport-aws-ses/classes/Swift/AWSTransport.php', 'AWSResponse' => $vendorDir . '/jmhobbs/swiftmailer-transport-aws-ses/classes/Swift/AWSTransport.php', 'ChunkedTransferSocket' => $vendorDir . '/jmhobbs/swiftmailer-transport-aws-ses/classes/Swift/AWSTransport.php', + 'Doctrine\\Common\\Lexer\\AbstractLexer' => $vendorDir . '/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php', + 'Egulias\\EmailValidator\\EmailLexer' => $vendorDir . '/egulias/email-validator/EmailValidator/EmailLexer.php', + 'Egulias\\EmailValidator\\EmailParser' => $vendorDir . '/egulias/email-validator/EmailValidator/EmailParser.php', + 'Egulias\\EmailValidator\\EmailValidator' => $vendorDir . '/egulias/email-validator/EmailValidator/EmailValidator.php', + 'Egulias\\EmailValidator\\Exception\\AtextAfterCFWS' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/AtextAfterCFWS.php', + 'Egulias\\EmailValidator\\Exception\\CRLFAtTheEnd' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/CRLFAtTheEnd.php', + 'Egulias\\EmailValidator\\Exception\\CRLFX2' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/CRLFX2.php', + 'Egulias\\EmailValidator\\Exception\\CRNoLF' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/CRNoLF.php', + 'Egulias\\EmailValidator\\Exception\\CharNotAllowed' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/CharNotAllowed.php', + 'Egulias\\EmailValidator\\Exception\\CommaInDomain' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/CommaInDomain.php', + 'Egulias\\EmailValidator\\Exception\\ConsecutiveAt' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/ConsecutiveAt.php', + 'Egulias\\EmailValidator\\Exception\\ConsecutiveDot' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/ConsecutiveDot.php', + 'Egulias\\EmailValidator\\Exception\\DomainHyphened' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/DomainHyphened.php', + 'Egulias\\EmailValidator\\Exception\\DotAtEnd' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/DotAtEnd.php', + 'Egulias\\EmailValidator\\Exception\\DotAtStart' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/DotAtStart.php', + 'Egulias\\EmailValidator\\Exception\\ExpectedQPair' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/ExpectingQPair.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingAT' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/ExpectingAT.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingATEXT' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/ExpectingATEXT.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingCTEXT' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/ExpectingCTEXT.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingDTEXT' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/ExpectingDTEXT.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingDomainLiteralClose' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/ExpectingDomainLiteralClose.php', + 'Egulias\\EmailValidator\\Exception\\InvalidEmail' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/InvalidEmail.php', + 'Egulias\\EmailValidator\\Exception\\NoDNSRecord' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/NoDNSRecord.php', + 'Egulias\\EmailValidator\\Exception\\NoDomainPart' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/NoDomainPart.php', + 'Egulias\\EmailValidator\\Exception\\NoLocalPart' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/NoLocalPart.php', + 'Egulias\\EmailValidator\\Exception\\UnclosedComment' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/UnclosedComment.php', + 'Egulias\\EmailValidator\\Exception\\UnclosedQuotedString' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/UnclosedQuotedString.php', + 'Egulias\\EmailValidator\\Exception\\UnopenedComment' => $vendorDir . '/egulias/email-validator/EmailValidator/Exception/UnopenedComment.php', + 'Egulias\\EmailValidator\\Parser\\DomainPart' => $vendorDir . '/egulias/email-validator/EmailValidator/Parser/DomainPart.php', + 'Egulias\\EmailValidator\\Parser\\LocalPart' => $vendorDir . '/egulias/email-validator/EmailValidator/Parser/LocalPart.php', + 'Egulias\\EmailValidator\\Parser\\Parser' => $vendorDir . '/egulias/email-validator/EmailValidator/Parser/Parser.php', + 'Egulias\\EmailValidator\\Validation\\DNSCheckValidation' => $vendorDir . '/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php', + 'Egulias\\EmailValidator\\Validation\\EmailValidation' => $vendorDir . '/egulias/email-validator/EmailValidator/Validation/EmailValidation.php', + 'Egulias\\EmailValidator\\Validation\\Error\\RFCWarnings' => $vendorDir . '/egulias/email-validator/EmailValidator/Validation/Error/RFCWarnings.php', + 'Egulias\\EmailValidator\\Validation\\Error\\SpoofEmail' => $vendorDir . '/egulias/email-validator/EmailValidator/Validation/Error/SpoofEmail.php', + 'Egulias\\EmailValidator\\Validation\\Exception\\EmptyValidationList' => $vendorDir . '/egulias/email-validator/EmailValidator/Validation/Exception/EmptyValidationList.php', + 'Egulias\\EmailValidator\\Validation\\MultipleErrors' => $vendorDir . '/egulias/email-validator/EmailValidator/Validation/MultipleErrors.php', + 'Egulias\\EmailValidator\\Validation\\MultipleValidationWithAnd' => $vendorDir . '/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php', + 'Egulias\\EmailValidator\\Validation\\NoRFCWarningsValidation' => $vendorDir . '/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php', + 'Egulias\\EmailValidator\\Validation\\RFCValidation' => $vendorDir . '/egulias/email-validator/EmailValidator/Validation/RFCValidation.php', + 'Egulias\\EmailValidator\\Validation\\SpoofCheckValidation' => $vendorDir . '/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php', + 'Egulias\\EmailValidator\\Warning\\AddressLiteral' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/AddressLiteral.php', + 'Egulias\\EmailValidator\\Warning\\CFWSNearAt' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/CFWSNearAt.php', + 'Egulias\\EmailValidator\\Warning\\CFWSWithFWS' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/CFWSWithFWS.php', + 'Egulias\\EmailValidator\\Warning\\Comment' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/Comment.php', + 'Egulias\\EmailValidator\\Warning\\DeprecatedComment' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/DeprecatedComment.php', + 'Egulias\\EmailValidator\\Warning\\DomainLiteral' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/DomainLiteral.php', + 'Egulias\\EmailValidator\\Warning\\DomainTooLong' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/DomainTooLong.php', + 'Egulias\\EmailValidator\\Warning\\EmailTooLong' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/EmailTooLong.php', + 'Egulias\\EmailValidator\\Warning\\IPV6BadChar' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/IPV6BadChar.php', + 'Egulias\\EmailValidator\\Warning\\IPV6ColonEnd' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/IPV6ColonEnd.php', + 'Egulias\\EmailValidator\\Warning\\IPV6ColonStart' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/IPV6ColonStart.php', + 'Egulias\\EmailValidator\\Warning\\IPV6Deprecated' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/IPV6Deprecated.php', + 'Egulias\\EmailValidator\\Warning\\IPV6DoubleColon' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/IPV6DoubleColon.php', + 'Egulias\\EmailValidator\\Warning\\IPV6GroupCount' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/IPV6GroupCount.php', + 'Egulias\\EmailValidator\\Warning\\IPV6MaxGroups' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/IPV6MaxGroups.php', + 'Egulias\\EmailValidator\\Warning\\LabelTooLong' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/LabelTooLong.php', + 'Egulias\\EmailValidator\\Warning\\LocalTooLong' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/LocalTooLong.php', + 'Egulias\\EmailValidator\\Warning\\NoDNSMXRecord' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/NoDNSMXRecord.php', + 'Egulias\\EmailValidator\\Warning\\ObsoleteDTEXT' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/ObsoleteDTEXT.php', + 'Egulias\\EmailValidator\\Warning\\QuotedPart' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/QuotedPart.php', + 'Egulias\\EmailValidator\\Warning\\QuotedString' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/QuotedString.php', + 'Egulias\\EmailValidator\\Warning\\TLD' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/TLD.php', + 'Egulias\\EmailValidator\\Warning\\Warning' => $vendorDir . '/egulias/email-validator/EmailValidator/Warning/Warning.php', 'HTMLPurifier' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.php', 'HTMLPurifier_Arborize' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Arborize.php', 'HTMLPurifier_AttrCollections' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrCollections.php', @@ -286,7 +350,8 @@ return array( 'Leafo\\ScssPhp\\Node' => $vendorDir . '/leafo/scssphp/src/Node.php', 'Leafo\\ScssPhp\\Node\\Number' => $vendorDir . '/leafo/scssphp/src/Node/Number.php', 'Leafo\\ScssPhp\\Parser' => $vendorDir . '/leafo/scssphp/src/Parser.php', - 'Leafo\\ScssPhp\\Server' => $vendorDir . '/leafo/scssphp/src/Server.php', + 'Leafo\\ScssPhp\\SourceMap\\Base64VLQEncoder' => $vendorDir . '/leafo/scssphp/src/SourceMap/Base64VLQEncoder.php', + 'Leafo\\ScssPhp\\SourceMap\\SourceMapGenerator' => $vendorDir . '/leafo/scssphp/src/SourceMap/SourceMapGenerator.php', 'Leafo\\ScssPhp\\Type' => $vendorDir . '/leafo/scssphp/src/Type.php', 'Leafo\\ScssPhp\\Util' => $vendorDir . '/leafo/scssphp/src/Util.php', 'Leafo\\ScssPhp\\Version' => $vendorDir . '/leafo/scssphp/src/Version.php', @@ -313,6 +378,7 @@ return array( 'League\\HTMLToMarkdown\\ElementInterface' => $vendorDir . '/league/html-to-markdown/src/ElementInterface.php', 'League\\HTMLToMarkdown\\Environment' => $vendorDir . '/league/html-to-markdown/src/Environment.php', 'League\\HTMLToMarkdown\\HtmlConverter' => $vendorDir . '/league/html-to-markdown/src/HtmlConverter.php', + 'League\\HTMLToMarkdown\\HtmlConverterInterface' => $vendorDir . '/league/html-to-markdown/src/HtmlConverterInterface.php', 'MatthiasMullie\\Minify\\CSS' => $vendorDir . '/matthiasmullie/minify/src/CSS.php', 'MatthiasMullie\\Minify\\Exception' => $vendorDir . '/matthiasmullie/minify/src/Exception.php', 'MatthiasMullie\\Minify\\Exceptions\\BasicException' => $vendorDir . '/matthiasmullie/minify/src/Exceptions/BasicException.php', diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index b45d385c0..d1cd39f3f 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -8,9 +8,10 @@ $baseDir = dirname($vendorDir); return array( 'Sunra\\PhpSimple\\HtmlDomParser' => array($vendorDir . '/sunra/php-simple-html-dom-parser/Src'), 'Requests' => array($vendorDir . '/rmccue/requests/library'), - 'Michelf' => array($vendorDir . '/michelf/php-markdown', $vendorDir . '/michelf/php-smartypants'), + 'Michelf' => array($vendorDir . '/michelf/php-smartypants'), 'JBBCode' => array($vendorDir . '/jbbcode/jbbcode'), 'Hautelook' => array($vendorDir . '/hautelook/phpass/src'), 'HTMLPurifier' => array($vendorDir . '/ezyang/htmlpurifier/library'), + 'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib'), '' => array($vendorDir . '/jmhobbs/swiftmailer-transport-aws-ses/classes'), ); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 90a092144..8d95ea76a 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -9,8 +9,10 @@ return array( 'TrueBV\\' => array($vendorDir . '/true/punycode/src'), 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), 'Nurigo\\' => array($vendorDir . '/coolsms/php-sdk/app/Nurigo'), + 'Michelf\\' => array($vendorDir . '/michelf/php-markdown/Michelf'), 'MatthiasMullie\\PathConverter\\' => array($vendorDir . '/matthiasmullie/path-converter/src'), 'MatthiasMullie\\Minify\\' => array($vendorDir . '/matthiasmullie/minify/src'), 'League\\HTMLToMarkdown\\' => array($vendorDir . '/league/html-to-markdown/src'), 'Leafo\\ScssPhp\\' => array($vendorDir . '/leafo/scssphp/src'), + 'Egulias\\EmailValidator\\' => array($vendorDir . '/egulias/email-validator/EmailValidator'), ); diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index d9bcbeb1f..a63f0361b 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -238,59 +238,6 @@ "sms" ] }, - { - "name": "michelf/php-markdown", - "version": "1.7.0", - "version_normalized": "1.7.0.0", - "source": { - "type": "git", - "url": "https://github.com/michelf/php-markdown.git", - "reference": "1f51cc520948f66cd2af8cbc45a5ee175e774220" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/michelf/php-markdown/zipball/1f51cc520948f66cd2af8cbc45a5ee175e774220", - "reference": "1f51cc520948f66cd2af8cbc45a5ee175e774220", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2016-10-29 18:58:20", - "type": "library", - "extra": { - "branch-alias": { - "dev-lib": "1.4.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Michelf": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Michel Fortin", - "email": "michel.fortin@michelf.ca", - "homepage": "https://michelf.ca/", - "role": "Developer" - }, - { - "name": "John Gruber", - "homepage": "https://daringfireball.net/" - } - ], - "description": "PHP Markdown", - "homepage": "https://michelf.ca/projects/php-markdown/", - "keywords": [ - "markdown" - ] - }, { "name": "rmccue/requests", "version": "v1.7.0", @@ -342,335 +289,6 @@ "sockets" ] }, - { - "name": "ezyang/htmlpurifier", - "version": "v4.9.3", - "version_normalized": "4.9.3.0", - "source": { - "type": "git", - "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "95e1bae3182efc0f3422896a3236e991049dac69" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/95e1bae3182efc0f3422896a3236e991049dac69", - "reference": "95e1bae3182efc0f3422896a3236e991049dac69", - "shasum": "" - }, - "require": { - "php": ">=5.2" - }, - "require-dev": { - "simpletest/simpletest": "^1.1" - }, - "time": "2017-06-03 02:28:16", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "HTMLPurifier": "library/" - }, - "files": [ - "library/HTMLPurifier.composer.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL" - ], - "authors": [ - { - "name": "Edward Z. Yang", - "email": "admin@htmlpurifier.org", - "homepage": "http://ezyang.com" - } - ], - "description": "Standards compliant HTML filter written in PHP", - "homepage": "http://htmlpurifier.org/", - "keywords": [ - "html" - ] - }, - { - "name": "hautelook/phpass", - "version": "0.3.5", - "version_normalized": "0.3.5.0", - "source": { - "type": "git", - "url": "https://github.com/hautelook/phpass.git", - "reference": "b4cbd9b67ed3ef5672ec79d8e0c46d24bd844abd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hautelook/phpass/zipball/b4cbd9b67ed3ef5672ec79d8e0c46d24bd844abd", - "reference": "b4cbd9b67ed3ef5672ec79d8e0c46d24bd844abd", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "time": "2012-08-31 00:00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "Hautelook": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Public Domain" - ], - "authors": [ - { - "name": "Solar Designer", - "email": "solar@openwall.com", - "homepage": "http://openwall.com/phpass/" - } - ], - "description": "Portable PHP password hashing framework", - "homepage": "http://github.com/hautelook/phpass/", - "keywords": [ - "blowfish", - "crypt", - "password", - "security" - ] - }, - { - "name": "leafo/scssphp", - "version": "v0.6.7", - "version_normalized": "0.6.7.0", - "source": { - "type": "git", - "url": "https://github.com/leafo/scssphp.git", - "reference": "562213cd803e42ea53b0735554794c4022d8db89" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/leafo/scssphp/zipball/562213cd803e42ea53b0735554794c4022d8db89", - "reference": "562213cd803e42ea53b0735554794c4022d8db89", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "kherge/box": "~2.5", - "phpunit/phpunit": "~3.7", - "squizlabs/php_codesniffer": "~2.5" - }, - "time": "2017-02-23 05:07:33", - "bin": [ - "bin/pscss" - ], - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Leafo\\ScssPhp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Leaf Corcoran", - "email": "leafot@gmail.com", - "homepage": "http://leafo.net" - } - ], - "description": "scssphp is a compiler for SCSS written in PHP.", - "homepage": "http://leafo.github.io/scssphp/", - "keywords": [ - "css", - "less", - "sass", - "scss", - "stylesheet" - ] - }, - { - "name": "league/html-to-markdown", - "version": "4.4.1", - "version_normalized": "4.4.1.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/html-to-markdown.git", - "reference": "82ea375b5b2b1da1da222644c0565c695bf88186" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/82ea375b5b2b1da1da222644c0565c695bf88186", - "reference": "82ea375b5b2b1da1da222644c0565c695bf88186", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-xml": "*", - "php": ">=5.3.3" - }, - "require-dev": { - "mikehaertl/php-shellcommand": "~1.1.0", - "phpunit/phpunit": "4.*", - "scrutinizer/ocular": "~1.1" - }, - "time": "2017-03-16 00:45:59", - "bin": [ - "bin/html-to-markdown" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.5-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "League\\HTMLToMarkdown\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Colin O'Dell", - "email": "colinodell@gmail.com", - "homepage": "http://www.colinodell.com", - "role": "Lead Developer" - }, - { - "name": "Nick Cernis", - "email": "nick@cern.is", - "homepage": "http://modernnerd.net", - "role": "Original Author" - } - ], - "description": "An HTML-to-markdown conversion helper for PHP", - "homepage": "https://github.com/thephpleague/html-to-markdown", - "keywords": [ - "html", - "markdown" - ] - }, - { - "name": "matthiasmullie/path-converter", - "version": "1.1.0", - "version_normalized": "1.1.0.0", - "source": { - "type": "git", - "url": "https://github.com/matthiasmullie/path-converter.git", - "reference": "08551ec1b156e923c242a10ab484bd4d6ead6631" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/matthiasmullie/path-converter/zipball/08551ec1b156e923c242a10ab484bd4d6ead6631", - "reference": "08551ec1b156e923c242a10ab484bd4d6ead6631", - "shasum": "" - }, - "require": { - "ext-pcre": "*", - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.8" - }, - "time": "2017-01-26 08:54:49", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "MatthiasMullie\\PathConverter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthias Mullie", - "email": "pathconverter@mullie.eu", - "homepage": "http://www.mullie.eu", - "role": "Developer" - } - ], - "description": "Relative path converter", - "homepage": "http://github.com/matthiasmullie/path-converter", - "keywords": [ - "converter", - "path", - "paths", - "relative" - ] - }, - { - "name": "matthiasmullie/minify", - "version": "1.3.45", - "version_normalized": "1.3.45.0", - "source": { - "type": "git", - "url": "https://github.com/matthiasmullie/minify.git", - "reference": "09b83e9dbdc50cf6734c6a9652a54891c0651998" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/09b83e9dbdc50cf6734c6a9652a54891c0651998", - "reference": "09b83e9dbdc50cf6734c6a9652a54891c0651998", - "shasum": "" - }, - "require": { - "ext-pcre": "*", - "matthiasmullie/path-converter": "~1.1", - "php": ">=5.3.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "~1.0", - "matthiasmullie/scrapbook": "~1.0", - "phpunit/phpunit": "~4.8" - }, - "suggest": { - "psr/cache-implementation": "Cache implementation to use with Minify::cache" - }, - "time": "2017-06-13 15:54:31", - "bin": [ - "bin/minifycss", - "bin/minifyjs" - ], - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "MatthiasMullie\\Minify\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthias Mullie", - "email": "minify@mullie.eu", - "homepage": "http://www.mullie.eu", - "role": "Developer" - } - ], - "description": "CSS & JS minifier", - "homepage": "http://www.minifier.org", - "keywords": [ - "JS", - "css", - "javascript", - "minifier", - "minify" - ] - }, { "name": "michelf/php-smartypants", "version": "1.8.1", @@ -773,123 +391,6 @@ "parser" ] }, - { - "name": "swiftmailer/swiftmailer", - "version": "v5.4.8", - "version_normalized": "5.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "9a06dc570a0367850280eefd3f1dc2da45aef517" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/9a06dc570a0367850280eefd3f1dc2da45aef517", - "reference": "9a06dc570a0367850280eefd3f1dc2da45aef517", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "mockery/mockery": "~0.9.1", - "symfony/phpunit-bridge": "~3.2" - }, - "time": "2017-05-01 15:54:03", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "lib/swift_required.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Chris Corbyn" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Swiftmailer, free feature-rich PHP mailer", - "homepage": "http://swiftmailer.org", - "keywords": [ - "email", - "mail", - "mailer" - ] - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.4.0", - "version_normalized": "1.4.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "f29dca382a6485c3cbe6379f0c61230167681937" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f29dca382a6485c3cbe6379f0c61230167681937", - "reference": "f29dca382a6485c3cbe6379f0c61230167681937", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "time": "2017-06-09 14:24:12", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ] - }, { "name": "true/punycode", "version": "v2.1.1", @@ -937,5 +438,618 @@ "idna", "punycode" ] + }, + { + "name": "ezyang/htmlpurifier", + "version": "v4.10.0", + "version_normalized": "4.10.0.0", + "source": { + "type": "git", + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "d85d39da4576a6934b72480be6978fb10c860021" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d85d39da4576a6934b72480be6978fb10c860021", + "reference": "d85d39da4576a6934b72480be6978fb10c860021", + "shasum": "" + }, + "require": { + "php": ">=5.2" + }, + "require-dev": { + "simpletest/simpletest": "^1.1" + }, + "time": "2018-02-23 01:58:20", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "HTMLPurifier": "library/" + }, + "files": [ + "library/HTMLPurifier.composer.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ] + }, + { + "name": "hautelook/phpass", + "version": "1.1.0", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/hautelook/phpass.git", + "reference": "b2daca28508000d1dd126e93ec472d771626a774" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hautelook/phpass/zipball/b2daca28508000d1dd126e93ec472d771626a774", + "reference": "b2daca28508000d1dd126e93ec472d771626a774", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "time": "2012-08-31 00:00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "Hautelook": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Public Domain" + ], + "authors": [ + { + "name": "Solar Designer", + "email": "solar@openwall.com", + "homepage": "http://openwall.com/phpass/" + } + ], + "description": "Portable PHP password hashing framework", + "homepage": "http://github.com/hautelook/phpass/", + "keywords": [ + "blowfish", + "crypt", + "password", + "security" + ] + }, + { + "name": "league/html-to-markdown", + "version": "4.8.0", + "version_normalized": "4.8.0.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/html-to-markdown.git", + "reference": "f9a879a068c68ff47b722de63f58bec79e448f9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/f9a879a068c68ff47b722de63f58bec79e448f9d", + "reference": "f9a879a068c68ff47b722de63f58bec79e448f9d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xml": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "mikehaertl/php-shellcommand": "~1.1.0", + "phpunit/phpunit": "4.*", + "scrutinizer/ocular": "~1.1" + }, + "time": "2018-09-18 12:18:08", + "bin": [ + "bin/html-to-markdown" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "League\\HTMLToMarkdown\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nick Cernis", + "email": "nick@cern.is", + "homepage": "http://modernnerd.net", + "role": "Original Author" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "An HTML-to-markdown conversion helper for PHP", + "homepage": "https://github.com/thephpleague/html-to-markdown", + "keywords": [ + "html", + "markdown" + ] + }, + { + "name": "michelf/php-markdown", + "version": "1.8.0", + "version_normalized": "1.8.0.0", + "source": { + "type": "git", + "url": "https://github.com/michelf/php-markdown.git", + "reference": "01ab082b355bf188d907b9929cd99b2923053495" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/michelf/php-markdown/zipball/01ab082b355bf188d907b9929cd99b2923053495", + "reference": "01ab082b355bf188d907b9929cd99b2923053495", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2018-01-15 00:49:33", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Michelf\\": "Michelf/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Michel Fortin", + "email": "michel.fortin@michelf.ca", + "homepage": "https://michelf.ca/", + "role": "Developer" + }, + { + "name": "John Gruber", + "homepage": "https://daringfireball.net/" + } + ], + "description": "PHP Markdown", + "homepage": "https://michelf.ca/projects/php-markdown/", + "keywords": [ + "markdown" + ] + }, + { + "name": "leafo/scssphp", + "version": "v0.7.7", + "version_normalized": "0.7.7.0", + "source": { + "type": "git", + "url": "https://github.com/leafo/scssphp.git", + "reference": "1d656f8c02a3a69404bba6b28ec4e06edddf0f49" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/leafo/scssphp/zipball/1d656f8c02a3a69404bba6b28ec4e06edddf0f49", + "reference": "1d656f8c02a3a69404bba6b28ec4e06edddf0f49", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.6", + "squizlabs/php_codesniffer": "~2.5" + }, + "time": "2018-07-22 01:22:08", + "bin": [ + "bin/pscss" + ], + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Leafo\\ScssPhp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Leaf Corcoran", + "email": "leafot@gmail.com", + "homepage": "http://leafo.net" + } + ], + "description": "scssphp is a compiler for SCSS written in PHP.", + "homepage": "http://leafo.github.io/scssphp/", + "keywords": [ + "css", + "less", + "sass", + "scss", + "stylesheet" + ] + }, + { + "name": "matthiasmullie/path-converter", + "version": "1.1.1", + "version_normalized": "1.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/matthiasmullie/path-converter.git", + "reference": "3082a6838be02b930239a97d38b5c9da4d693aca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/matthiasmullie/path-converter/zipball/3082a6838be02b930239a97d38b5c9da4d693aca", + "reference": "3082a6838be02b930239a97d38b5c9da4d693aca", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "time": "2018-02-02 11:30:10", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "MatthiasMullie\\PathConverter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthias Mullie", + "email": "pathconverter@mullie.eu", + "homepage": "http://www.mullie.eu", + "role": "Developer" + } + ], + "description": "Relative path converter", + "homepage": "http://github.com/matthiasmullie/path-converter", + "keywords": [ + "converter", + "path", + "paths", + "relative" + ] + }, + { + "name": "matthiasmullie/minify", + "version": "1.3.60", + "version_normalized": "1.3.60.0", + "source": { + "type": "git", + "url": "https://github.com/matthiasmullie/minify.git", + "reference": "ab7fea80ce5ce6549baaf272bc8bd926a7e08f90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/ab7fea80ce5ce6549baaf272bc8bd926a7e08f90", + "reference": "ab7fea80ce5ce6549baaf272bc8bd926a7e08f90", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "matthiasmullie/path-converter": "~1.1", + "php": ">=5.3.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.0", + "matthiasmullie/scrapbook": "~1.0", + "phpunit/phpunit": "~4.8" + }, + "suggest": { + "psr/cache-implementation": "Cache implementation to use with Minify::cache" + }, + "time": "2018-04-18 08:50:35", + "bin": [ + "bin/minifycss", + "bin/minifyjs" + ], + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "MatthiasMullie\\Minify\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthias Mullie", + "email": "minify@mullie.eu", + "homepage": "http://www.mullie.eu", + "role": "Developer" + } + ], + "description": "CSS & JavaScript minifier, in PHP. Removes whitespace, strips comments, combines files (incl. @import statements and small assets in CSS files), and optimizes/shortens a few common programming patterns.", + "homepage": "http://www.minifier.org", + "keywords": [ + "JS", + "css", + "javascript", + "minifier", + "minify" + ] + }, + { + "name": "doctrine/lexer", + "version": "v1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "time": "2014-09-09 13:34:57", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Doctrine\\Common\\Lexer\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "lexer", + "parser" + ] + }, + { + "name": "egulias/email-validator", + "version": "2.1.6", + "version_normalized": "2.1.6.0", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "0578b32b30b22de3e8664f797cf846fc9246f786" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/0578b32b30b22de3e8664f797cf846fc9246f786", + "reference": "0578b32b30b22de3e8664f797cf846fc9246f786", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^1.0.1", + "php": ">= 5.5" + }, + "require-dev": { + "dominicsayers/isemail": "dev-master", + "phpunit/phpunit": "^4.8.35||^5.7||^6.0", + "satooshi/php-coveralls": "^1.0.1" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "time": "2018-09-25 20:47:26", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "EmailValidator" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ] + }, + { + "name": "swiftmailer/swiftmailer", + "version": "v6.1.3", + "version_normalized": "6.1.3.0", + "source": { + "type": "git", + "url": "https://github.com/swiftmailer/swiftmailer.git", + "reference": "8ddcb66ac10c392d3beb54829eef8ac1438595f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/8ddcb66ac10c392d3beb54829eef8ac1438595f4", + "reference": "8ddcb66ac10c392d3beb54829eef8ac1438595f4", + "shasum": "" + }, + "require": { + "egulias/email-validator": "~2.0", + "php": ">=7.0.0" + }, + "require-dev": { + "mockery/mockery": "~0.9.1", + "symfony/phpunit-bridge": "~3.3@dev" + }, + "suggest": { + "ext-intl": "Needed to support internationalized email addresses", + "true/punycode": "Needed to support internationalized email addresses, if ext-intl is not installed" + }, + "time": "2018-09-11 07:12:52", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "lib/swift_required.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Corbyn" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Swiftmailer, free feature-rich PHP mailer", + "homepage": "https://swiftmailer.symfony.com", + "keywords": [ + "email", + "mail", + "mailer" + ] + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.9.0", + "version_normalized": "1.9.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8", + "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "time": "2018-08-06 14:22:27", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ] } ] diff --git a/vendor/doctrine/lexer/LICENSE b/vendor/doctrine/lexer/LICENSE new file mode 100644 index 000000000..5e781fce4 --- /dev/null +++ b/vendor/doctrine/lexer/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2013 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/doctrine/lexer/README.md b/vendor/doctrine/lexer/README.md new file mode 100644 index 000000000..66f443089 --- /dev/null +++ b/vendor/doctrine/lexer/README.md @@ -0,0 +1,5 @@ +# Doctrine Lexer + +Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers. + +This lexer is used in Doctrine Annotations and in Doctrine ORM (DQL). diff --git a/vendor/doctrine/lexer/composer.json b/vendor/doctrine/lexer/composer.json new file mode 100644 index 000000000..8cd694c65 --- /dev/null +++ b/vendor/doctrine/lexer/composer.json @@ -0,0 +1,24 @@ +{ + "name": "doctrine/lexer", + "type": "library", + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "keywords": ["lexer", "parser"], + "homepage": "http://www.doctrine-project.org", + "license": "MIT", + "authors": [ + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, + {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} + ], + "require": { + "php": ">=5.3.2" + }, + "autoload": { + "psr-0": { "Doctrine\\Common\\Lexer\\": "lib/" } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php b/vendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php new file mode 100644 index 000000000..399a55230 --- /dev/null +++ b/vendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php @@ -0,0 +1,327 @@ +. + */ + +namespace Doctrine\Common\Lexer; + +/** + * Base class for writing simple lexers, i.e. for creating small DSLs. + * + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +abstract class AbstractLexer +{ + /** + * Lexer original input string. + * + * @var string + */ + private $input; + + /** + * Array of scanned tokens. + * + * Each token is an associative array containing three items: + * - 'value' : the string value of the token in the input string + * - 'type' : the type of the token (identifier, numeric, string, input + * parameter, none) + * - 'position' : the position of the token in the input string + * + * @var array + */ + private $tokens = array(); + + /** + * Current lexer position in input string. + * + * @var integer + */ + private $position = 0; + + /** + * Current peek of current lexer position. + * + * @var integer + */ + private $peek = 0; + + /** + * The next token in the input. + * + * @var array + */ + public $lookahead; + + /** + * The last matched/seen token. + * + * @var array + */ + public $token; + + /** + * Sets the input data to be tokenized. + * + * The Lexer is immediately reset and the new input tokenized. + * Any unprocessed tokens from any previous input are lost. + * + * @param string $input The input to be tokenized. + * + * @return void + */ + public function setInput($input) + { + $this->input = $input; + $this->tokens = array(); + + $this->reset(); + $this->scan($input); + } + + /** + * Resets the lexer. + * + * @return void + */ + public function reset() + { + $this->lookahead = null; + $this->token = null; + $this->peek = 0; + $this->position = 0; + } + + /** + * Resets the peek pointer to 0. + * + * @return void + */ + public function resetPeek() + { + $this->peek = 0; + } + + /** + * Resets the lexer position on the input to the given position. + * + * @param integer $position Position to place the lexical scanner. + * + * @return void + */ + public function resetPosition($position = 0) + { + $this->position = $position; + } + + /** + * Retrieve the original lexer's input until a given position. + * + * @param integer $position + * + * @return string + */ + public function getInputUntilPosition($position) + { + return substr($this->input, 0, $position); + } + + /** + * Checks whether a given token matches the current lookahead. + * + * @param integer|string $token + * + * @return boolean + */ + public function isNextToken($token) + { + return null !== $this->lookahead && $this->lookahead['type'] === $token; + } + + /** + * Checks whether any of the given tokens matches the current lookahead. + * + * @param array $tokens + * + * @return boolean + */ + public function isNextTokenAny(array $tokens) + { + return null !== $this->lookahead && in_array($this->lookahead['type'], $tokens, true); + } + + /** + * Moves to the next token in the input string. + * + * @return boolean + */ + public function moveNext() + { + $this->peek = 0; + $this->token = $this->lookahead; + $this->lookahead = (isset($this->tokens[$this->position])) + ? $this->tokens[$this->position++] : null; + + return $this->lookahead !== null; + } + + /** + * Tells the lexer to skip input tokens until it sees a token with the given value. + * + * @param string $type The token type to skip until. + * + * @return void + */ + public function skipUntil($type) + { + while ($this->lookahead !== null && $this->lookahead['type'] !== $type) { + $this->moveNext(); + } + } + + /** + * Checks if given value is identical to the given token. + * + * @param mixed $value + * @param integer $token + * + * @return boolean + */ + public function isA($value, $token) + { + return $this->getType($value) === $token; + } + + /** + * Moves the lookahead token forward. + * + * @return array|null The next token or NULL if there are no more tokens ahead. + */ + public function peek() + { + if (isset($this->tokens[$this->position + $this->peek])) { + return $this->tokens[$this->position + $this->peek++]; + } else { + return null; + } + } + + /** + * Peeks at the next token, returns it and immediately resets the peek. + * + * @return array|null The next token or NULL if there are no more tokens ahead. + */ + public function glimpse() + { + $peek = $this->peek(); + $this->peek = 0; + return $peek; + } + + /** + * Scans the input string for tokens. + * + * @param string $input A query string. + * + * @return void + */ + protected function scan($input) + { + static $regex; + + if ( ! isset($regex)) { + $regex = sprintf( + '/(%s)|%s/%s', + implode(')|(', $this->getCatchablePatterns()), + implode('|', $this->getNonCatchablePatterns()), + $this->getModifiers() + ); + } + + $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; + $matches = preg_split($regex, $input, -1, $flags); + + foreach ($matches as $match) { + // Must remain before 'value' assignment since it can change content + $type = $this->getType($match[0]); + + $this->tokens[] = array( + 'value' => $match[0], + 'type' => $type, + 'position' => $match[1], + ); + } + } + + /** + * Gets the literal for a given token. + * + * @param integer $token + * + * @return string + */ + public function getLiteral($token) + { + $className = get_class($this); + $reflClass = new \ReflectionClass($className); + $constants = $reflClass->getConstants(); + + foreach ($constants as $name => $value) { + if ($value === $token) { + return $className . '::' . $name; + } + } + + return $token; + } + + /** + * Regex modifiers + * + * @return string + */ + protected function getModifiers() + { + return 'i'; + } + + /** + * Lexical catchable patterns. + * + * @return array + */ + abstract protected function getCatchablePatterns(); + + /** + * Lexical non-catchable patterns. + * + * @return array + */ + abstract protected function getNonCatchablePatterns(); + + /** + * Retrieve token type. Also processes the token value if necessary. + * + * @param string $value + * + * @return integer + */ + abstract protected function getType(&$value); +} diff --git a/vendor/egulias/email-validator/EmailValidator/EmailLexer.php b/vendor/egulias/email-validator/EmailValidator/EmailLexer.php new file mode 100644 index 000000000..882c96815 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/EmailLexer.php @@ -0,0 +1,221 @@ + self::S_OPENPARENTHESIS, + ')' => self::S_CLOSEPARENTHESIS, + '<' => self::S_LOWERTHAN, + '>' => self::S_GREATERTHAN, + '[' => self::S_OPENBRACKET, + ']' => self::S_CLOSEBRACKET, + ':' => self::S_COLON, + ';' => self::S_SEMICOLON, + '@' => self::S_AT, + '\\' => self::S_BACKSLASH, + '/' => self::S_SLASH, + ',' => self::S_COMMA, + '.' => self::S_DOT, + '"' => self::S_DQUOTE, + '-' => self::S_HYPHEN, + '::' => self::S_DOUBLECOLON, + ' ' => self::S_SP, + "\t" => self::S_HTAB, + "\r" => self::S_CR, + "\n" => self::S_LF, + "\r\n" => self::CRLF, + 'IPv6' => self::S_IPV6TAG, + '{' => self::S_OPENQBRACKET, + '}' => self::S_CLOSEQBRACKET, + '' => self::S_EMPTY, + '\0' => self::C_NUL, + ); + + protected $hasInvalidTokens = false; + + protected $previous; + + public function reset() + { + $this->hasInvalidTokens = false; + parent::reset(); + } + + public function hasInvalidTokens() + { + return $this->hasInvalidTokens; + } + + /** + * @param $type + * @throws \UnexpectedValueException + * @return boolean + */ + public function find($type) + { + $search = clone $this; + $search->skipUntil($type); + + if (!$search->lookahead) { + throw new \UnexpectedValueException($type . ' not found'); + } + return true; + } + + /** + * getPrevious + * + * @return array token + */ + public function getPrevious() + { + return $this->previous; + } + + /** + * moveNext + * + * @return boolean + */ + public function moveNext() + { + $this->previous = $this->token; + + return parent::moveNext(); + } + + /** + * Lexical catchable patterns. + * + * @return string[] + */ + protected function getCatchablePatterns() + { + return array( + '[a-zA-Z_]+[46]?', //ASCII and domain literal + '[^\x00-\x7F]', //UTF-8 + '[0-9]+', + '\r\n', + '::', + '\s+?', + '.', + ); + } + + /** + * Lexical non-catchable patterns. + * + * @return string[] + */ + protected function getNonCatchablePatterns() + { + return array('[\xA0-\xff]+'); + } + + /** + * Retrieve token type. Also processes the token value if necessary. + * + * @param string $value + * @throws \InvalidArgumentException + * @return integer + */ + protected function getType(&$value) + { + if ($this->isNullType($value)) { + return self::C_NUL; + } + + if ($this->isValid($value)) { + return $this->charValue[$value]; + } + + if ($this->isUTF8Invalid($value)) { + $this->hasInvalidTokens = true; + return self::INVALID; + } + + return self::GENERIC; + } + + protected function isValid($value) + { + if (isset($this->charValue[$value])) { + return true; + } + + return false; + } + + /** + * @param $value + * @return bool + */ + protected function isNullType($value) + { + if ($value === "\0") { + return true; + } + + return false; + } + + /** + * @param $value + * @return bool + */ + protected function isUTF8Invalid($value) + { + if (preg_match('/\p{Cc}+/u', $value)) { + return true; + } + + return false; + } + + protected function getModifiers() + { + return 'iu'; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/EmailParser.php b/vendor/egulias/email-validator/EmailValidator/EmailParser.php new file mode 100644 index 000000000..d0627d824 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/EmailParser.php @@ -0,0 +1,104 @@ + + */ +class EmailParser +{ + const EMAIL_MAX_LENGTH = 254; + + protected $warnings; + protected $domainPart = ''; + protected $localPart = ''; + protected $lexer; + protected $localPartParser; + protected $domainPartParser; + + public function __construct(EmailLexer $lexer) + { + $this->lexer = $lexer; + $this->localPartParser = new LocalPart($this->lexer); + $this->domainPartParser = new DomainPart($this->lexer); + $this->warnings = new \SplObjectStorage(); + } + + /** + * @param $str + * @return array + */ + public function parse($str) + { + $this->lexer->setInput($str); + + if (!$this->hasAtToken()) { + throw new NoLocalPart(); + } + + + $this->localPartParser->parse($str); + $this->domainPartParser->parse($str); + + $this->setParts($str); + + if ($this->lexer->hasInvalidTokens()) { + throw new ExpectingATEXT(); + } + + return array('local' => $this->localPart, 'domain' => $this->domainPart); + } + + public function getWarnings() + { + $localPartWarnings = $this->localPartParser->getWarnings(); + $domainPartWarnings = $this->domainPartParser->getWarnings(); + $this->warnings = array_merge($localPartWarnings, $domainPartWarnings); + + $this->addLongEmailWarning($this->localPart, $this->domainPart); + + return $this->warnings; + } + + public function getParsedDomainPart() + { + return $this->domainPart; + } + + protected function setParts($email) + { + $parts = explode('@', $email); + $this->domainPart = $this->domainPartParser->getDomainPart(); + $this->localPart = $parts[0]; + } + + protected function hasAtToken() + { + $this->lexer->moveNext(); + $this->lexer->moveNext(); + if ($this->lexer->token['type'] === EmailLexer::S_AT) { + return false; + } + + return true; + } + + /** + * @param string $localPart + * @param string $parsedDomainPart + */ + protected function addLongEmailWarning($localPart, $parsedDomainPart) + { + if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAIL_MAX_LENGTH) { + $this->warnings[EmailTooLong::CODE] = new EmailTooLong(); + } + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/EmailValidator.php b/vendor/egulias/email-validator/EmailValidator/EmailValidator.php new file mode 100644 index 000000000..44b4b93c6 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/EmailValidator.php @@ -0,0 +1,67 @@ +lexer = new EmailLexer(); + } + + /** + * @param $email + * @param EmailValidation $emailValidation + * @return bool + */ + public function isValid($email, EmailValidation $emailValidation) + { + $isValid = $emailValidation->isValid($email, $this->lexer); + $this->warnings = $emailValidation->getWarnings(); + $this->error = $emailValidation->getError(); + + return $isValid; + } + + /** + * @return boolean + */ + public function hasWarnings() + { + return !empty($this->warnings); + } + + /** + * @return array + */ + public function getWarnings() + { + return $this->warnings; + } + + /** + * @return InvalidEmail + */ + public function getError() + { + return $this->error; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Exception/AtextAfterCFWS.php b/vendor/egulias/email-validator/EmailValidator/Exception/AtextAfterCFWS.php new file mode 100644 index 000000000..97f41a2ca --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Exception/AtextAfterCFWS.php @@ -0,0 +1,9 @@ +lexer->moveNext(); + + if ($this->lexer->token['type'] === EmailLexer::S_DOT) { + throw new DotAtStart(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_EMPTY) { + throw new NoDomainPart(); + } + if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) { + throw new DomainHyphened(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { + $this->warnings[DeprecatedComment::CODE] = new DeprecatedComment(); + $this->parseDomainComments(); + } + + $domain = $this->doParseDomainPart(); + + $prev = $this->lexer->getPrevious(); + $length = strlen($domain); + + if ($prev['type'] === EmailLexer::S_DOT) { + throw new DotAtEnd(); + } + if ($prev['type'] === EmailLexer::S_HYPHEN) { + throw new DomainHyphened(); + } + if ($length > self::DOMAIN_MAX_LENGTH) { + $this->warnings[DomainTooLong::CODE] = new DomainTooLong(); + } + if ($prev['type'] === EmailLexer::S_CR) { + throw new CRLFAtTheEnd(); + } + $this->domainPart = $domain; + } + + public function getDomainPart() + { + return $this->domainPart; + } + + public function checkIPV6Tag($addressLiteral, $maxGroups = 8) + { + $prev = $this->lexer->getPrevious(); + if ($prev['type'] === EmailLexer::S_COLON) { + $this->warnings[IPV6ColonEnd::CODE] = new IPV6ColonEnd(); + } + + $IPv6 = substr($addressLiteral, 5); + //Daniel Marschall's new IPv6 testing strategy + $matchesIP = explode(':', $IPv6); + $groupCount = count($matchesIP); + $colons = strpos($IPv6, '::'); + + if (count(preg_grep('/^[0-9A-Fa-f]{0,4}$/', $matchesIP, PREG_GREP_INVERT)) !== 0) { + $this->warnings[IPV6BadChar::CODE] = new IPV6BadChar(); + } + + if ($colons === false) { + // We need exactly the right number of groups + if ($groupCount !== $maxGroups) { + $this->warnings[IPV6GroupCount::CODE] = new IPV6GroupCount(); + } + return; + } + + if ($colons !== strrpos($IPv6, '::')) { + $this->warnings[IPV6DoubleColon::CODE] = new IPV6DoubleColon(); + return; + } + + if ($colons === 0 || $colons === (strlen($IPv6) - 2)) { + // RFC 4291 allows :: at the start or end of an address + //with 7 other groups in addition + ++$maxGroups; + } + + if ($groupCount > $maxGroups) { + $this->warnings[IPV6MaxGroups::CODE] = new IPV6MaxGroups(); + } elseif ($groupCount === $maxGroups) { + $this->warnings[IPV6Deprecated::CODE] = new IPV6Deprecated(); + } + } + + protected function doParseDomainPart() + { + $domain = ''; + $openedParenthesis = 0; + do { + $prev = $this->lexer->getPrevious(); + + $this->checkNotAllowedChars($this->lexer->token); + + if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { + $this->parseComments(); + $openedParenthesis += $this->getOpenedParenthesis(); + $this->lexer->moveNext(); + $tmpPrev = $this->lexer->getPrevious(); + if ($tmpPrev['type'] === EmailLexer::S_CLOSEPARENTHESIS) { + $openedParenthesis--; + } + } + if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) { + if ($openedParenthesis === 0) { + throw new UnopenedComment(); + } else { + $openedParenthesis--; + } + } + + $this->checkConsecutiveDots(); + $this->checkDomainPartExceptions($prev); + + if ($this->hasBrackets()) { + $this->parseDomainLiteral(); + } + + $this->checkLabelLength($prev); + + if ($this->isFWS()) { + $this->parseFWS(); + } + + $domain .= $this->lexer->token['value']; + $this->lexer->moveNext(); + } while ($this->lexer->token); + + return $domain; + } + + private function checkNotAllowedChars($token) + { + $notAllowed = [EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true]; + if (isset($notAllowed[$token['type']])) { + throw new CharNotAllowed(); + } + } + + protected function parseDomainLiteral() + { + if ($this->lexer->isNextToken(EmailLexer::S_COLON)) { + $this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart(); + } + if ($this->lexer->isNextToken(EmailLexer::S_IPV6TAG)) { + $lexer = clone $this->lexer; + $lexer->moveNext(); + if ($lexer->isNextToken(EmailLexer::S_DOUBLECOLON)) { + $this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart(); + } + } + + return $this->doParseDomainLiteral(); + } + + protected function doParseDomainLiteral() + { + $IPv6TAG = false; + $addressLiteral = ''; + do { + if ($this->lexer->token['type'] === EmailLexer::C_NUL) { + throw new ExpectingDTEXT(); + } + + if ($this->lexer->token['type'] === EmailLexer::INVALID || + $this->lexer->token['type'] === EmailLexer::C_DEL || + $this->lexer->token['type'] === EmailLexer::S_LF + ) { + $this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT(); + } + + if ($this->lexer->isNextTokenAny(array(EmailLexer::S_OPENQBRACKET, EmailLexer::S_OPENBRACKET))) { + throw new ExpectingDTEXT(); + } + + if ($this->lexer->isNextTokenAny( + array(EmailLexer::S_HTAB, EmailLexer::S_SP, $this->lexer->token['type'] === EmailLexer::CRLF) + )) { + $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); + $this->parseFWS(); + } + + if ($this->lexer->isNextToken(EmailLexer::S_CR)) { + throw new CRNoLF(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH) { + $this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT(); + $addressLiteral .= $this->lexer->token['value']; + $this->lexer->moveNext(); + $this->validateQuotedPair(); + } + if ($this->lexer->token['type'] === EmailLexer::S_IPV6TAG) { + $IPv6TAG = true; + } + if ($this->lexer->token['type'] === EmailLexer::S_CLOSEQBRACKET) { + break; + } + + $addressLiteral .= $this->lexer->token['value']; + + } while ($this->lexer->moveNext()); + + $addressLiteral = str_replace('[', '', $addressLiteral); + $addressLiteral = $this->checkIPV4Tag($addressLiteral); + + if (false === $addressLiteral) { + return $addressLiteral; + } + + if (!$IPv6TAG) { + $this->warnings[DomainLiteral::CODE] = new DomainLiteral(); + return $addressLiteral; + } + + $this->warnings[AddressLiteral::CODE] = new AddressLiteral(); + + $this->checkIPV6Tag($addressLiteral); + + return $addressLiteral; + } + + protected function checkIPV4Tag($addressLiteral) + { + $matchesIP = array(); + + // Extract IPv4 part from the end of the address-literal (if there is one) + if (preg_match( + '/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', + $addressLiteral, + $matchesIP + ) > 0 + ) { + $index = strrpos($addressLiteral, $matchesIP[0]); + if ($index === 0) { + $this->warnings[AddressLiteral::CODE] = new AddressLiteral(); + return false; + } + // Convert IPv4 part to IPv6 format for further testing + $addressLiteral = substr($addressLiteral, 0, $index) . '0:0'; + } + + return $addressLiteral; + } + + protected function checkDomainPartExceptions($prev) + { + $invalidDomainTokens = array( + EmailLexer::S_DQUOTE => true, + EmailLexer::S_SEMICOLON => true, + EmailLexer::S_GREATERTHAN => true, + EmailLexer::S_LOWERTHAN => true, + ); + + if (isset($invalidDomainTokens[$this->lexer->token['type']])) { + throw new ExpectingATEXT(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_COMMA) { + throw new CommaInDomain(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_AT) { + throw new ConsecutiveAt(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_OPENQBRACKET && $prev['type'] !== EmailLexer::S_AT) { + throw new ExpectingATEXT(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN && $this->lexer->isNextToken(EmailLexer::S_DOT)) { + throw new DomainHyphened(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH + && $this->lexer->isNextToken(EmailLexer::GENERIC)) { + throw new ExpectingATEXT(); + } + } + + protected function hasBrackets() + { + if ($this->lexer->token['type'] !== EmailLexer::S_OPENBRACKET) { + return false; + } + + try { + $this->lexer->find(EmailLexer::S_CLOSEBRACKET); + } catch (\RuntimeException $e) { + throw new ExpectingDomainLiteralClose(); + } + + return true; + } + + protected function checkLabelLength($prev) + { + if ($this->lexer->token['type'] === EmailLexer::S_DOT && + $prev['type'] === EmailLexer::GENERIC && + strlen($prev['value']) > 63 + ) { + $this->warnings[LabelTooLong::CODE] = new LabelTooLong(); + } + } + + protected function parseDomainComments() + { + $this->isUnclosedComment(); + while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) { + $this->warnEscaping(); + $this->lexer->moveNext(); + } + + $this->lexer->moveNext(); + if ($this->lexer->isNextToken(EmailLexer::S_DOT)) { + throw new ExpectingATEXT(); + } + } + + protected function addTLDWarnings() + { + if ($this->warnings[DomainLiteral::CODE]) { + $this->warnings[TLD::CODE] = new TLD(); + } + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Parser/LocalPart.php b/vendor/egulias/email-validator/EmailValidator/Parser/LocalPart.php new file mode 100644 index 000000000..8ab16ab4a --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Parser/LocalPart.php @@ -0,0 +1,138 @@ +lexer->token['type'] !== EmailLexer::S_AT && $this->lexer->token) { + if ($this->lexer->token['type'] === EmailLexer::S_DOT && !$this->lexer->getPrevious()) { + throw new DotAtStart(); + } + + $closingQuote = $this->checkDQUOTE($closingQuote); + if ($closingQuote && $parseDQuote) { + $parseDQuote = $this->parseDoubleQuote(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { + $this->parseComments(); + $openedParenthesis += $this->getOpenedParenthesis(); + } + if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) { + if ($openedParenthesis === 0) { + throw new UnopenedComment(); + } else { + $openedParenthesis--; + } + } + + $this->checkConsecutiveDots(); + + if ($this->lexer->token['type'] === EmailLexer::S_DOT && + $this->lexer->isNextToken(EmailLexer::S_AT) + ) { + throw new DotAtEnd(); + } + + $this->warnEscaping(); + $this->isInvalidToken($this->lexer->token, $closingQuote); + + if ($this->isFWS()) { + $this->parseFWS(); + } + + $this->lexer->moveNext(); + } + + $prev = $this->lexer->getPrevious(); + if (strlen($prev['value']) > LocalTooLong::LOCAL_PART_LENGTH) { + $this->warnings[LocalTooLong::CODE] = new LocalTooLong(); + } + } + + protected function parseDoubleQuote() + { + $parseAgain = true; + $special = array( + EmailLexer::S_CR => true, + EmailLexer::S_HTAB => true, + EmailLexer::S_LF => true + ); + + $invalid = array( + EmailLexer::C_NUL => true, + EmailLexer::S_HTAB => true, + EmailLexer::S_CR => true, + EmailLexer::S_LF => true + ); + $setSpecialsWarning = true; + + $this->lexer->moveNext(); + + while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && $this->lexer->token) { + $parseAgain = false; + if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) { + $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); + $setSpecialsWarning = false; + } + if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH && $this->lexer->isNextToken(EmailLexer::S_DQUOTE)) { + $this->lexer->moveNext(); + } + + $this->lexer->moveNext(); + + if (!$this->escaped() && isset($invalid[$this->lexer->token['type']])) { + throw new ExpectingATEXT(); + } + } + + $prev = $this->lexer->getPrevious(); + + if ($prev['type'] === EmailLexer::S_BACKSLASH) { + if (!$this->checkDQUOTE(false)) { + throw new UnclosedQuotedString(); + } + } + + if (!$this->lexer->isNextToken(EmailLexer::S_AT) && $prev['type'] !== EmailLexer::S_BACKSLASH) { + throw new ExpectingAT(); + } + + return $parseAgain; + } + + protected function isInvalidToken($token, $closingQuote) + { + $forbidden = array( + EmailLexer::S_COMMA, + EmailLexer::S_CLOSEBRACKET, + EmailLexer::S_OPENBRACKET, + EmailLexer::S_GREATERTHAN, + EmailLexer::S_LOWERTHAN, + EmailLexer::S_COLON, + EmailLexer::S_SEMICOLON, + EmailLexer::INVALID + ); + + if (in_array($token['type'], $forbidden) && !$closingQuote) { + throw new ExpectingATEXT(); + } + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Parser/Parser.php b/vendor/egulias/email-validator/EmailValidator/Parser/Parser.php new file mode 100644 index 000000000..e5042e1a8 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Parser/Parser.php @@ -0,0 +1,215 @@ +lexer = $lexer; + } + + public function getWarnings() + { + return $this->warnings; + } + + abstract public function parse($str); + + /** @return int */ + public function getOpenedParenthesis() + { + return $this->openedParenthesis; + } + + /** + * validateQuotedPair + */ + protected function validateQuotedPair() + { + if (!($this->lexer->token['type'] === EmailLexer::INVALID + || $this->lexer->token['type'] === EmailLexer::C_DEL)) { + throw new ExpectedQPair(); + } + + $this->warnings[QuotedPart::CODE] = + new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']); + } + + protected function parseComments() + { + $this->openedParenthesis = 1; + $this->isUnclosedComment(); + $this->warnings[Comment::CODE] = new Comment(); + while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) { + if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) { + $this->openedParenthesis++; + } + $this->warnEscaping(); + $this->lexer->moveNext(); + } + + $this->lexer->moveNext(); + if ($this->lexer->isNextTokenAny(array(EmailLexer::GENERIC, EmailLexer::S_EMPTY))) { + throw new ExpectingATEXT(); + } + + if ($this->lexer->isNextToken(EmailLexer::S_AT)) { + $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt(); + } + } + + protected function isUnclosedComment() + { + try { + $this->lexer->find(EmailLexer::S_CLOSEPARENTHESIS); + return true; + } catch (\RuntimeException $e) { + throw new UnclosedComment(); + } + } + + protected function parseFWS() + { + $previous = $this->lexer->getPrevious(); + + $this->checkCRLFInFWS(); + + if ($this->lexer->token['type'] === EmailLexer::S_CR) { + throw new CRNoLF(); + } + + if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] !== EmailLexer::S_AT) { + throw new AtextAfterCFWS(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_LF || $this->lexer->token['type'] === EmailLexer::C_NUL) { + throw new ExpectingCTEXT(); + } + + if ($this->lexer->isNextToken(EmailLexer::S_AT) || $previous['type'] === EmailLexer::S_AT) { + $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt(); + } else { + $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); + } + } + + protected function checkConsecutiveDots() + { + if ($this->lexer->token['type'] === EmailLexer::S_DOT && $this->lexer->isNextToken(EmailLexer::S_DOT)) { + throw new ConsecutiveDot(); + } + } + + protected function isFWS() + { + if ($this->escaped()) { + return false; + } + + if ($this->lexer->token['type'] === EmailLexer::S_SP || + $this->lexer->token['type'] === EmailLexer::S_HTAB || + $this->lexer->token['type'] === EmailLexer::S_CR || + $this->lexer->token['type'] === EmailLexer::S_LF || + $this->lexer->token['type'] === EmailLexer::CRLF + ) { + return true; + } + + return false; + } + + protected function escaped() + { + $previous = $this->lexer->getPrevious(); + + if ($previous['type'] === EmailLexer::S_BACKSLASH + && + $this->lexer->token['type'] !== EmailLexer::GENERIC + ) { + return true; + } + + return false; + } + + protected function warnEscaping() + { + if ($this->lexer->token['type'] !== EmailLexer::S_BACKSLASH) { + return false; + } + + if ($this->lexer->isNextToken(EmailLexer::GENERIC)) { + throw new ExpectingATEXT(); + } + + if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) { + return false; + } + + $this->warnings[QuotedPart::CODE] = + new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']); + return true; + + } + + protected function checkDQUOTE($hasClosingQuote) + { + if ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE) { + return $hasClosingQuote; + } + if ($hasClosingQuote) { + return $hasClosingQuote; + } + $previous = $this->lexer->getPrevious(); + if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] === EmailLexer::GENERIC) { + throw new ExpectingATEXT(); + } + + try { + $this->lexer->find(EmailLexer::S_DQUOTE); + $hasClosingQuote = true; + } catch (\Exception $e) { + throw new UnclosedQuotedString(); + } + $this->warnings[QuotedString::CODE] = new QuotedString($previous['value'], $this->lexer->token['value']); + + return $hasClosingQuote; + } + + protected function checkCRLFInFWS() + { + if ($this->lexer->token['type'] !== EmailLexer::CRLF) { + return; + } + + if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) { + throw new CRLFX2(); + } + + if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) { + throw new CRLFAtTheEnd(); + } + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php b/vendor/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php new file mode 100644 index 000000000..e5c3e5df9 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php @@ -0,0 +1,72 @@ +checkDNS($host); + } + + public function getError() + { + return $this->error; + } + + public function getWarnings() + { + return $this->warnings; + } + + protected function checkDNS($host) + { + $variant = INTL_IDNA_VARIANT_2003; + if ( defined('INTL_IDNA_VARIANT_UTS46') ) { + $variant = INTL_IDNA_VARIANT_UTS46; + } + $host = rtrim(idn_to_ascii($host, IDNA_DEFAULT, $variant), '.') . '.'; + + $Aresult = true; + $MXresult = checkdnsrr($host, 'MX'); + + if (!$MXresult) { + $this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord(); + $Aresult = checkdnsrr($host, 'A') || checkdnsrr($host, 'AAAA'); + if (!$Aresult) { + $this->error = new NoDNSRecord(); + } + } + return $MXresult || $Aresult; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Validation/EmailValidation.php b/vendor/egulias/email-validator/EmailValidator/Validation/EmailValidation.php new file mode 100644 index 000000000..d5a015be5 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Validation/EmailValidation.php @@ -0,0 +1,34 @@ +errors = $errors; + parent::__construct(); + } + + public function getErrors() + { + return $this->errors; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php b/vendor/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php new file mode 100644 index 000000000..43fa42a64 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php @@ -0,0 +1,110 @@ +validations = $validations; + $this->mode = $mode; + } + + /** + * {@inheritdoc} + */ + public function isValid($email, EmailLexer $emailLexer) + { + $result = true; + $errors = []; + foreach ($this->validations as $validation) { + $emailLexer->reset(); + $result = $result && $validation->isValid($email, $emailLexer); + $this->warnings = array_merge($this->warnings, $validation->getWarnings()); + $errors = $this->addNewError($validation->getError(), $errors); + + if ($this->shouldStop($result)) { + break; + } + } + + if (!empty($errors)) { + $this->error = new MultipleErrors($errors); + } + + return $result; + } + + private function addNewError($possibleError, array $errors) + { + if (null !== $possibleError) { + $errors[] = $possibleError; + } + + return $errors; + } + + private function shouldStop($result) + { + return !$result && $this->mode === self::STOP_ON_ERROR; + } + + /** + * {@inheritdoc} + */ + public function getError() + { + return $this->error; + } + + /** + * {@inheritdoc} + */ + public function getWarnings() + { + return $this->warnings; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php b/vendor/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php new file mode 100644 index 000000000..e4bf0cc4d --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php @@ -0,0 +1,41 @@ +getWarnings())) { + return true; + } + + $this->error = new RFCWarnings(); + + return false; + } + + /** + * {@inheritdoc} + */ + public function getError() + { + return $this->error ?: parent::getError(); + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Validation/RFCValidation.php b/vendor/egulias/email-validator/EmailValidator/Validation/RFCValidation.php new file mode 100644 index 000000000..c4ffe3503 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Validation/RFCValidation.php @@ -0,0 +1,49 @@ +parser = new EmailParser($emailLexer); + try { + $this->parser->parse((string)$email); + } catch (InvalidEmail $invalid) { + $this->error = $invalid; + return false; + } + + $this->warnings = $this->parser->getWarnings(); + return true; + } + + public function getError() + { + return $this->error; + } + + public function getWarnings() + { + return $this->warnings; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php b/vendor/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php new file mode 100644 index 000000000..4721f0d8c --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php @@ -0,0 +1,45 @@ +setChecks(Spoofchecker::SINGLE_SCRIPT); + + if ($checker->isSuspicious($email)) { + $this->error = new SpoofEmail(); + } + + return $this->error === null; + } + + public function getError() + { + return $this->error; + } + + public function getWarnings() + { + return []; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/AddressLiteral.php b/vendor/egulias/email-validator/EmailValidator/Warning/AddressLiteral.php new file mode 100644 index 000000000..77e70f7f5 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/AddressLiteral.php @@ -0,0 +1,14 @@ +message = 'Address literal in domain part'; + $this->rfcNumber = 5321; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/CFWSNearAt.php b/vendor/egulias/email-validator/EmailValidator/Warning/CFWSNearAt.php new file mode 100644 index 000000000..be43bbe6f --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/CFWSNearAt.php @@ -0,0 +1,13 @@ +message = "Deprecated folding white space near @"; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/CFWSWithFWS.php b/vendor/egulias/email-validator/EmailValidator/Warning/CFWSWithFWS.php new file mode 100644 index 000000000..dea3450ec --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/CFWSWithFWS.php @@ -0,0 +1,13 @@ +message = 'Folding whites space followed by folding white space'; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/Comment.php b/vendor/egulias/email-validator/EmailValidator/Warning/Comment.php new file mode 100644 index 000000000..704c2908b --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/Comment.php @@ -0,0 +1,13 @@ +message = "Comments found in this email"; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/DeprecatedComment.php b/vendor/egulias/email-validator/EmailValidator/Warning/DeprecatedComment.php new file mode 100644 index 000000000..ad43bd7c9 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/DeprecatedComment.php @@ -0,0 +1,13 @@ +message = 'Deprecated comments'; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/DomainLiteral.php b/vendor/egulias/email-validator/EmailValidator/Warning/DomainLiteral.php new file mode 100644 index 000000000..6f36b5e29 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/DomainLiteral.php @@ -0,0 +1,14 @@ +message = 'Domain Literal'; + $this->rfcNumber = 5322; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/DomainTooLong.php b/vendor/egulias/email-validator/EmailValidator/Warning/DomainTooLong.php new file mode 100644 index 000000000..61ff17a76 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/DomainTooLong.php @@ -0,0 +1,14 @@ +message = 'Domain is too long, exceeds 255 chars'; + $this->rfcNumber = 5322; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/EmailTooLong.php b/vendor/egulias/email-validator/EmailValidator/Warning/EmailTooLong.php new file mode 100644 index 000000000..497309dbb --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/EmailTooLong.php @@ -0,0 +1,15 @@ +message = 'Email is too long, exceeds ' . EmailParser::EMAIL_MAX_LENGTH; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/IPV6BadChar.php b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6BadChar.php new file mode 100644 index 000000000..ba2fcc01b --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6BadChar.php @@ -0,0 +1,14 @@ +message = 'Bad char in IPV6 domain literal'; + $this->rfcNumber = 5322; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/IPV6ColonEnd.php b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6ColonEnd.php new file mode 100644 index 000000000..41afa78c6 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6ColonEnd.php @@ -0,0 +1,14 @@ +message = ':: found at the end of the domain literal'; + $this->rfcNumber = 5322; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/IPV6ColonStart.php b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6ColonStart.php new file mode 100644 index 000000000..1bf754e30 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6ColonStart.php @@ -0,0 +1,14 @@ +message = ':: found at the start of the domain literal'; + $this->rfcNumber = 5322; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/IPV6Deprecated.php b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6Deprecated.php new file mode 100644 index 000000000..d752caaa1 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6Deprecated.php @@ -0,0 +1,14 @@ +message = 'Deprecated form of IPV6'; + $this->rfcNumber = 5321; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/IPV6DoubleColon.php b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6DoubleColon.php new file mode 100644 index 000000000..4f8239499 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6DoubleColon.php @@ -0,0 +1,14 @@ +message = 'Double colon found after IPV6 tag'; + $this->rfcNumber = 5322; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/IPV6GroupCount.php b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6GroupCount.php new file mode 100644 index 000000000..a59d317f2 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6GroupCount.php @@ -0,0 +1,14 @@ +message = 'Group count is not IPV6 valid'; + $this->rfcNumber = 5322; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/IPV6MaxGroups.php b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6MaxGroups.php new file mode 100644 index 000000000..936274c13 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/IPV6MaxGroups.php @@ -0,0 +1,14 @@ +message = 'Reached the maximum number of IPV6 groups allowed'; + $this->rfcNumber = 5321; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/LabelTooLong.php b/vendor/egulias/email-validator/EmailValidator/Warning/LabelTooLong.php new file mode 100644 index 000000000..daf07f408 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/LabelTooLong.php @@ -0,0 +1,14 @@ +message = 'Label too long'; + $this->rfcNumber = 5322; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/LocalTooLong.php b/vendor/egulias/email-validator/EmailValidator/Warning/LocalTooLong.php new file mode 100644 index 000000000..0d08d8b35 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/LocalTooLong.php @@ -0,0 +1,15 @@ +message = 'Local part is too long, exceeds 64 chars (octets)'; + $this->rfcNumber = 5322; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/NoDNSMXRecord.php b/vendor/egulias/email-validator/EmailValidator/Warning/NoDNSMXRecord.php new file mode 100644 index 000000000..b3c21a1f3 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/NoDNSMXRecord.php @@ -0,0 +1,14 @@ +message = 'No MX DSN record was found for this email'; + $this->rfcNumber = 5321; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/ObsoleteDTEXT.php b/vendor/egulias/email-validator/EmailValidator/Warning/ObsoleteDTEXT.php new file mode 100644 index 000000000..10f19e334 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/ObsoleteDTEXT.php @@ -0,0 +1,14 @@ +rfcNumber = 5322; + $this->message = 'Obsolete DTEXT in domain literal'; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/QuotedPart.php b/vendor/egulias/email-validator/EmailValidator/Warning/QuotedPart.php new file mode 100644 index 000000000..7be9e6a3f --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/QuotedPart.php @@ -0,0 +1,13 @@ +message = "Deprecated Quoted String found between $prevToken and $postToken"; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/QuotedString.php b/vendor/egulias/email-validator/EmailValidator/Warning/QuotedString.php new file mode 100644 index 000000000..e9d56e1e0 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/QuotedString.php @@ -0,0 +1,13 @@ +message = "Quoted String found between $prevToken and $postToken"; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/TLD.php b/vendor/egulias/email-validator/EmailValidator/Warning/TLD.php new file mode 100644 index 000000000..2338b9f44 --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/TLD.php @@ -0,0 +1,13 @@ +message = "RFC5321, TLD"; + } +} diff --git a/vendor/egulias/email-validator/EmailValidator/Warning/Warning.php b/vendor/egulias/email-validator/EmailValidator/Warning/Warning.php new file mode 100644 index 000000000..ec6a365ff --- /dev/null +++ b/vendor/egulias/email-validator/EmailValidator/Warning/Warning.php @@ -0,0 +1,30 @@ +message; + } + + public function code() + { + return self::CODE; + } + + public function RFCNumber() + { + return $this->rfcNumber; + } + + public function __toString() + { + return $this->message() . " rfc: " . $this->rfcNumber . "interal code: " . static::CODE; + } +} diff --git a/vendor/egulias/email-validator/LICENSE b/vendor/egulias/email-validator/LICENSE new file mode 100644 index 000000000..c34d2c197 --- /dev/null +++ b/vendor/egulias/email-validator/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2013-2016 Eduardo Gulias Davis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/egulias/email-validator/README.md b/vendor/egulias/email-validator/README.md new file mode 100644 index 000000000..8fcd2a6fe --- /dev/null +++ b/vendor/egulias/email-validator/README.md @@ -0,0 +1,79 @@ +# EmailValidator +[![Build Status](https://travis-ci.org/egulias/EmailValidator.png?branch=master)](https://travis-ci.org/egulias/EmailValidator) [![Coverage Status](https://coveralls.io/repos/egulias/EmailValidator/badge.png?branch=master)](https://coveralls.io/r/egulias/EmailValidator?branch=master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/egulias/EmailValidator/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/egulias/EmailValidator/?branch=master) [![SensioLabsInsight](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6/small.png)](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6) +============================= +With the help of [PHPStorm](https://www.jetbrains.com/phpstorm/) + +## Requirements ## + + * [Composer](https://getcomposer.org) is required for installation + * [Spoofchecking](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/SpoofCheckValidation.php) and [DNSCheckValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/DNSCheckValidation.php) validation requires that your PHP system have the [PHP Internationalization Libraries](https://php.net/manual/en/book.intl.php) (also known as PHP Intl) + +## Installation ## + +Run the command below to install via Composer + +```shell +composer require egulias/email-validator "~2.1" +``` + +## Getting Started ## +`EmailValidator`requires you to decide which (or combination of them) validation/s strategy/ies you'd like to follow for each [validation](#available-validations). + +A basic example with the RFC validation +```php +isValid("example@example.com", new RFCValidation()); //true +``` + + +### Available validations ### + +1. [RFCValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/RFCValidation.php) +2. [NoRFCWarningsValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/NoRFCWarningsValidation.php) +3. [DNSCheckValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/DNSCheckValidation.php) +4. [SpoofCheckValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/SpoofCheckValidation.php) +5. [MultipleValidationWithAnd](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/MultipleValidationWithAnd.php) +6. [Your own validation](#how-to-extend) + +`MultipleValidationWithAnd` + +It is a validation that operates over other validations performing a logical and (&&) over the result of each validation. + +```php +isValid("example@example.com", $multipleValidations); //true +``` + +### How to extend ### + +It's easy! You just need to implement [EmailValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/EmailValidation.php) and you can use your own validation. + + +## Other Contributors ## +(You can find current contributors [here](https://github.com/egulias/EmailValidator/graphs/contributors)) + +As this is a port from another library and work, here are other people related to the previous one: + +* Ricard Clau [@ricardclau](https://github.com/ricardclau): Performance against PHP built-in filter_var +* Josepf Bielawski [@stloyd](https://github.com/stloyd): For its first re-work of Dominic's lib +* Dominic Sayers [@dominicsayers](https://github.com/dominicsayers): The original isemail function + +## License ## +Released under the MIT License attached with this code. + diff --git a/vendor/egulias/email-validator/composer.json b/vendor/egulias/email-validator/composer.json new file mode 100644 index 000000000..5423e9f02 --- /dev/null +++ b/vendor/egulias/email-validator/composer.json @@ -0,0 +1,44 @@ +{ + "name": "egulias/email-validator", + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "type": "Library", + "keywords": ["email", "validation", "validator", "emailvalidation", "emailvalidator"], + "license": "MIT", + "authors": [ + {"name": "Eduardo Gulias Davis"} + ], + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "repositories": [ + { + "type": "git", + "url": "https://github.com/dominicsayers/isemail" + } + ], + "require": { + "php": ">= 5.5", + "doctrine/lexer": "^1.0.1" + }, + "require-dev" : { + "satooshi/php-coveralls": "^1.0.1", + "phpunit/phpunit": "^4.8.35||^5.7||^6.0", + "dominicsayers/isemail": "dev-master" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "EmailValidator" + } + }, + "autoload-dev": { + "psr-4": { + "Egulias\\Tests\\": "test" + } + } +} diff --git a/vendor/egulias/email-validator/phpunit.xml.dist b/vendor/egulias/email-validator/phpunit.xml.dist new file mode 100644 index 000000000..b0812f97b --- /dev/null +++ b/vendor/egulias/email-validator/phpunit.xml.dist @@ -0,0 +1,26 @@ + + + + + + ./Tests/EmailValidator + ./vendor/ + + + + + + ./vendor + + + diff --git a/vendor/ezyang/htmlpurifier/NEWS b/vendor/ezyang/htmlpurifier/NEWS index fd5d56cf0..9b6e10232 100644 --- a/vendor/ezyang/htmlpurifier/NEWS +++ b/vendor/ezyang/htmlpurifier/NEWS @@ -9,6 +9,20 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier . Internal change ========================== +4.10.0, released 2018-02-22 +# PHP 5.3 is no longer officially supported by HTML Purifier + (we did not specifically break support, but we are no longer + testing on PHP 5.3) +! Relative CSS length units are now supported +- A few PHP 7.2 compatibility fixes, thanks John Flatness + +- Improve portability with old versions of libxml which don't + support accessing the data of a node +- IDNA2008 is now used for converting domains to ASCII, fixing + some rather strange bugs with international domains +- Fix race condition resulting in E_WARNING when creating + directories with Serializer + 4.9.3, released 2017-06-02 - Workaround PHP 7.1 infinite loop when opcode cache is enabled. Thanks @Xiphin (#134, #135) diff --git a/vendor/ezyang/htmlpurifier/README.md b/vendor/ezyang/htmlpurifier/README.md index b321f2b69..37715c607 100644 --- a/vendor/ezyang/htmlpurifier/README.md +++ b/vendor/ezyang/htmlpurifier/README.md @@ -2,7 +2,7 @@ HTML Purifier [![Build Status](https://secure.travis-ci.org/ezyang/htmlpurifier. ============= HTML Purifier is an HTML filtering solution that uses a unique combination -of robust whitelists and agressive parsing to ensure that not only are +of robust whitelists and aggressive parsing to ensure that not only are XSS attacks thwarted, but the resulting HTML is standards compliant. HTML Purifier is oriented towards richly formatted documents from @@ -26,4 +26,4 @@ Package available on [Composer](https://packagist.org/packages/ezyang/htmlpurifi If you're using Composer to manage dependencies, you can use - $ composer require "ezyang/htmlpurifier": "dev-master" + $ composer require "ezyang/htmlpurifier":"dev-master" diff --git a/vendor/ezyang/htmlpurifier/VERSION b/vendor/ezyang/htmlpurifier/VERSION index e94f14fa9..1910ba9d2 100644 --- a/vendor/ezyang/htmlpurifier/VERSION +++ b/vendor/ezyang/htmlpurifier/VERSION @@ -1 +1 @@ -4.9.3 \ No newline at end of file +4.10.0 \ No newline at end of file diff --git a/vendor/ezyang/htmlpurifier/extras/HTMLPurifierExtras.autoload-legacy.php b/vendor/ezyang/htmlpurifier/extras/HTMLPurifierExtras.autoload-legacy.php new file mode 100644 index 000000000..d1485bf2e --- /dev/null +++ b/vendor/ezyang/htmlpurifier/extras/HTMLPurifierExtras.autoload-legacy.php @@ -0,0 +1,15 @@ +generateDirectoryPath($config); $chmod = $config->get('Cache.SerializerPermissions'); if ($chmod === null) { - // TODO: This races - if (is_dir($directory)) return true; - return mkdir($directory); + if (!@mkdir($directory) && !is_dir($directory)) { + trigger_error( + 'Could not create directory ' . $directory . '', + E_USER_WARNING + ); + return false; + } + return true; } if (!is_dir($directory)) { $base = $this->generateBaseDirectoryPath($config); @@ -233,7 +238,7 @@ class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCac } elseif (!$this->_testPermissions($base, $chmod)) { return false; } - if (!mkdir($directory, $chmod)) { + if (!@mkdir($directory, $chmod) && !is_dir($directory)) { trigger_error( 'Could not create directory ' . $directory . '', E_USER_WARNING diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector.php index 5060eef9e..116b470c3 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector.php @@ -157,11 +157,13 @@ abstract class HTMLPurifier_Injector return false; } // check for exclusion - for ($i = count($this->currentNesting) - 2; $i >= 0; $i--) { - $node = $this->currentNesting[$i]; - $def = $this->htmlDefinition->info[$node->name]; - if (isset($def->excludes[$name])) { - return false; + if (!empty($this->currentNesting)) { + for ($i = count($this->currentNesting) - 2; $i >= 0; $i--) { + $node = $this->currentNesting[$i]; + $def = $this->htmlDefinition->info[$node->name]; + if (isset($def->excludes[$name])) { + return false; + } } } return true; diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Length.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Length.php index bbfbe6624..e70da55a9 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Length.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Length.php @@ -26,12 +26,14 @@ class HTMLPurifier_Length protected $isValid; /** - * Array Lookup array of units recognized by CSS 2.1 + * Array Lookup array of units recognized by CSS 3 * @type array */ protected static $allowedUnits = array( 'em' => true, 'ex' => true, 'px' => true, 'in' => true, - 'cm' => true, 'mm' => true, 'pt' => true, 'pc' => true + 'cm' => true, 'mm' => true, 'pt' => true, 'pc' => true, + 'ch' => true, 'rem' => true, 'vw' => true, 'vh' => true, + 'vmin' => true, 'vmax' => true ); /** diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php index 22ab5820c..6238a99e3 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php @@ -126,6 +126,41 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer } while ($level > 0); } + /** + * Portably retrieve the tag name of a node; deals with older versions + * of libxml like 2.7.6 + * @param DOMNode $node + */ + protected function getTagName($node) + { + if (property_exists($node, 'tagName')) { + return $node->tagName; + } else if (property_exists($node, 'nodeName')) { + return $node->nodeName; + } else if (property_exists($node, 'localName')) { + return $node->localName; + } + return null; + } + + /** + * Portably retrieve the data of a node; deals with older versions + * of libxml like 2.7.6 + * @param DOMNode $node + */ + protected function getData($node) + { + if (property_exists($node, 'data')) { + return $node->data; + } else if (property_exists($node, 'nodeValue')) { + return $node->nodeValue; + } else if (property_exists($node, 'textContent')) { + return $node->textContent; + } + return null; + } + + /** * @param DOMNode $node DOMNode to be tokenized. * @param HTMLPurifier_Token[] $tokens Array-list of already tokenized tokens. @@ -141,7 +176,10 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer // but we're not getting the character reference nodes because // those should have been preprocessed if ($node->nodeType === XML_TEXT_NODE) { - $tokens[] = $this->factory->createText($node->data); + $data = $this->getData($node); // Handle variable data property + if ($data !== null) { + $tokens[] = $this->factory->createText($data); + } return false; } elseif ($node->nodeType === XML_CDATA_SECTION_NODE) { // undo libxml's special treatment of

    - All({$tCount}) + {lang('all')} ({$tCount})
    @@ -10,9 +10,9 @@
    {$lang->widget_name}{$lang->version}{$lang->author}{$lang->path}{$lang->version}{$lang->author}{$lang->path} {$lang->cmd_generate_code} {$lang->cmd_delete}
    {$widget->version} + {$author->name} {$author->name} {$widget->path}{$widget->path} {$lang->cmd_generate_code} {$lang->cmd_delete}