From 6b1ac80b7f9d5e7f3c76054feb1a24c5e9e4f999 Mon Sep 17 00:00:00 2001 From: Arcturus Date: Fri, 27 Sep 2024 17:11:41 +0900 Subject: [PATCH] patch new codes --- AvocadoEdition_Light/bbs/list.php | 14 + AvocadoEdition_Light/common.php | 51 +- AvocadoEdition_Light/config.php | 6 + .../lib/Cache/FileCache.class.php | 198 +++++++ AvocadoEdition_Light/lib/Cache/obj.class.php | 104 ++++ AvocadoEdition_Light/lib/cache.lib.php | 125 +++++ AvocadoEdition_Light/lib/get_data.lib.php | 514 +++++++++++++++++- AvocadoEdition_Light/lib/thumbnail.lib.php | 311 ++++++++--- AvocadoEdition_Light/lib/url.lib.php | 497 +++++++++++++++++ 9 files changed, 1729 insertions(+), 91 deletions(-) create mode 100644 AvocadoEdition_Light/lib/Cache/FileCache.class.php create mode 100644 AvocadoEdition_Light/lib/Cache/obj.class.php create mode 100644 AvocadoEdition_Light/lib/cache.lib.php create mode 100644 AvocadoEdition_Light/lib/url.lib.php diff --git a/AvocadoEdition_Light/bbs/list.php b/AvocadoEdition_Light/bbs/list.php index 7d0a629..a942001 100644 --- a/AvocadoEdition_Light/bbs/list.php +++ b/AvocadoEdition_Light/bbs/list.php @@ -112,6 +112,13 @@ if (!$sca && !$stx) { $list[$i] = get_list($row, $board, $board_skin_url, G5_IS_MOBILE ? $board['bo_mobile_subject_len'] : $board['bo_subject_len']); $list[$i]['is_notice'] = true; + $list[$i]['list_content'] = $list[$i]['wr_content']; + + // 비밀글인 경우 리스트에서 내용이 출력되지 않게 글 내용을 지웁니다. + if (strstr($list[$i]['wr_option'], "secret")) { + $list[$i]['wr_content'] = ''; + } + $i++; $notice_count++; @@ -198,6 +205,13 @@ if ($page_rows > 0) { $list[$i]['subject'] = search_font($stx, $list[$i]['subject']); } $list[$i]['is_notice'] = false; + $list[$i]['list_content'] = $list[$i]['wr_content']; + + // 비밀글인 경우 리스트에서 내용이 출력되지 않게 글 내용을 지웁니다. + if (strstr($list[$i]['wr_option'], "secret")) { + $list[$i]['wr_content'] = ''; + } + $list_num = $total_count - ($page - 1) * $list_page_rows - $notice_count; $list[$i]['num'] = $list_num - $k; diff --git a/AvocadoEdition_Light/common.php b/AvocadoEdition_Light/common.php index ec26747..60fa0dd 100644 --- a/AvocadoEdition_Light/common.php +++ b/AvocadoEdition_Light/common.php @@ -227,11 +227,54 @@ $_REQUEST = array_map_deep(G5_ESCAPE_FUNCTION, $_REQUEST); // 완두콩님이 알려주신 보안관련 오류 수정 // $member 에 값을 직접 넘길 수 있음 $config = []; -$member = []; -$board = []; -$group = []; +$member = [ + 'mb_id' => '', + 'mb_level' => 1, + 'mb_name' => '', + 'mb_point' => 0, + 'mb_certify' => '', + 'mb_email' => '', + 'mb_open' => '', + 'mb_homepage' => '', + 'mb_tel' => '', + 'mb_hp' => '', + 'mb_zip1' => '', + 'mb_zip2' => '', + 'mb_addr1' => '', + 'mb_addr2' => '', + 'mb_addr3' => '', + 'mb_addr_jibeon' => '', + 'mb_signature' => '', + 'mb_profile' => '' +]; +$board = [ + 'bo_table' => '', + 'bo_skin' => '', + 'bo_mobile_skin' => '', + 'bo_upload_count' => 0, + 'bo_use_dhtml_editor' => '', + 'bo_subject' => '', + 'bo_image_width' => 0 +]; +$group = [ + 'gr_device' => '', + 'gr_subject' => '' +]; $article = []; $g5 = []; +if (version_compare(phpversion(), '8.0.0', '>=')) { + $g5 = ['title' => '']; +} +$qaconfig = []; +$g5_debug = [ + 'php' => [], + 'sql' => [] +]; + +include_once G5_LIB_PATH . '/hook.lib.php'; +include_once G5_LIB_PATH . '/get_data.lib.php'; +include_once G5_LIB_PATH . '/cache.lib.php'; +include_once G5_LIB_PATH . '/url.lib.php'; //============================================================================== // 공통 @@ -240,8 +283,6 @@ $dbconfig_file = G5_DATA_PATH . '/' . G5_DBCONFIG_FILE; if (file_exists($dbconfig_file)) { include_once $dbconfig_file; include_once G5_LIB_PATH . '/common.lib.php'; // 공통 라이브러리 - include_once G5_LIB_PATH . '/get_data.lib.php'; - $g5["font_table"] = G5_TABLE_PREFIX . "editor_fonts"; $connect_db = sql_connect(G5_MYSQL_HOST, G5_MYSQL_USER, G5_MYSQL_PASSWORD) or die('MySQL Connect Error!!!'); diff --git a/AvocadoEdition_Light/config.php b/AvocadoEdition_Light/config.php index 7c3413b..67472e6 100644 --- a/AvocadoEdition_Light/config.php +++ b/AvocadoEdition_Light/config.php @@ -26,6 +26,10 @@ www.sir.kr 과 sir.kr 도메인은 서로 다른 도메인으로 인식합니다 define('G5_COOKIE_DOMAIN', ''); define('G5_DBCONFIG_FILE', 'dbconfig.php'); +// 빈값으로 두면 DB 버전이나 호스팅사 정책의 기본값에 따라 설정됩니다. +define('G5_DB_ENGINE', ''); +// utf8mb4 인코딩은 MySQL 또는 MariaDB 5.5 버전 이상을 요구합니다. +define('G5_DB_CHARSET', 'utf8'); define('G5_ADMIN_DIR', 'adm'); define('G5_BBS_DIR', 'bbs'); @@ -50,6 +54,8 @@ define('G5_SYNDI_DIR', 'syndi'); define('G5_PHPMAILER_DIR', 'PHPMailer'); define('G5_SESSION_DIR', 'session'); define('G5_THEME_DIR', 'theme'); +define('G5_GROUP_DIR', 'group'); +define('G5_CONTENT_DIR', 'content'); // URL 은 브라우저상에서의 경로 (도메인으로 부터의) if (G5_DOMAIN) { diff --git a/AvocadoEdition_Light/lib/Cache/FileCache.class.php b/AvocadoEdition_Light/lib/Cache/FileCache.class.php new file mode 100644 index 0000000..a8f924e --- /dev/null +++ b/AvocadoEdition_Light/lib/Cache/FileCache.class.php @@ -0,0 +1,198 @@ +$name = $options[$name]; + } + } + } + + /** + * Fetches an entry from the cache. + * + * @param string $id + */ + public function get($id, $expired_time = 0) + { + $data = $this->_get($id, $expired_time); + return is_array($data) ? $data['data'] : FALSE; + } + + protected function get_cache_file_path($id) + { + + $id = str_replace(DIRECTORY_SEPARATOR, '/', $id); + $add_separator = ''; + $add_file_extension = ''; + + if (strpos('/', $id) !== 0) { + $add_separator = '/'; + } + + $ext = pathinfo($id, PATHINFO_EXTENSION); + + if (!(isset($ext['extension']) && $ext['extension'])) { + $add_file_extension = $this->file_extension; + } + + return $this->_cache_path . $add_separator . $id . $add_file_extension; + + } + + protected function _get($id, $expired_time = 0) + { + $cache_file_path = $this->get_cache_file_path($id); + + if (!is_file($cache_file_path)) { + return FALSE; + } + + $server_time = defined('G5_SERVER_TIME') ? G5_SERVER_TIME : time(); + + try { + $file_contents = file_get_contents($cache_file_path); + $file_ex = explode("\n\n", $file_contents); + $data = unserialize(base64_decode($file_ex[1])); + } catch (Exception $e) { + $data = array('ttl' => 1, 'time' => $server_time - 1000); + } + + if ($data['ttl'] > 0 && $server_time > $data['time'] + $data['ttl']) { + unlink($cache_file_path); + return FALSE; + } + + if ($data['time'] && $expired_time && $data['time'] < ($server_time - $expired_time)) { + unlink($cache_file_path); + return FALSE; + } + + return $data; + } + + public function write_file($path, $data, $mode = 'wb') + { + if (!$fp = @fopen($path, $mode)) { + return FALSE; + } + + flock($fp, LOCK_EX); + + for ($result = $written = 0, $length = strlen($data); $written < $length; $written += $result) { + if (($result = fwrite($fp, substr($data, $written))) === FALSE) { + break; + } + } + + flock($fp, LOCK_UN); + fclose($fp); + + return is_int($result); + } + + /** + * Deletes a cache entry. + * + * @param string $id + * + * @return bool + */ + public function delete($id) + { + $cache_file_path = $this->get_cache_file_path($id); + + return file_exists($cache_file_path) ? unlink($cache_file_path) : FALSE; + } + + /** + * Puts data into the cache. + * + * @param string $id + * @param mixed $data + * @param int $lifetime + * + * @return bool + */ + public function save($id, $data, $ttl = 60, $raw = FALSE) + { + $cache_file_path = $this->get_cache_file_path($id); + + $contents = array( + 'time' => time(), + 'ttl' => $ttl, + 'data' => $data + ); + + $cache_content = "\n\n"; + $cache_content .= base64_encode(serialize($contents)); + + if ($this->write_file($cache_file_path, $cache_content)) { + chmod($cache_file_path, G5_FILE_PERMISSION); + return TRUE; + } + + return FALSE; + } + + /** + * Fetches a base directory to store the cache data + * + * @return string + */ + protected function getCacheDirectory() + { + return $this->_cache_path; + } + + /** + * Encodes some data to a string so it can be written to disk + * + * @param mixed $data + * @param int $ttl + * @return string + */ + public function encode($data, $ttl) + { + $expire = null; + if ($ttl !== null) { + $expire = time() + $ttl; + } + return base64_encode(serialize(array($data, $expire))); + } + + /** + * Decodes a string encoded by {@see encode()} + * + * Must returns a tuple (data, expire). Expire + * can be null to signal no expiration. + * + * @param string $data + * @return array (data, expire) + */ + public function decode($data) + { + return unserialize(base64_decode($data)); + } +} diff --git a/AvocadoEdition_Light/lib/Cache/obj.class.php b/AvocadoEdition_Light/lib/Cache/obj.class.php new file mode 100644 index 0000000..3f920ff --- /dev/null +++ b/AvocadoEdition_Light/lib/Cache/obj.class.php @@ -0,0 +1,104 @@ +writes; + break; + case 'content': + $datas = $this->contents; + break; + default: + $datas = $this->etcs; + break; + } + + if ($this->exists($type, $key, $group)) { + if (is_object($datas[$group][$key])) + return clone $datas[$group][$key]; + else + return $datas[$group][$key]; + } + + return false; + } + + function exists($type, $key, $group = 'default') + { + + $return_data = ''; + + switch ($type) { + case 'bbs': + $datas = $this->writes; + break; + case 'content': + $datas = $this->contents; + break; + default: + $datas = $this->etcs; + break; + } + + return isset($datas[$group]) && (isset($datas[$group][$key]) || array_key_exists($key, $datas[$group])); + } + + function set($type, $key, $data = array(), $group = 'default') + { + if (is_object($data)) + $data = clone $data; + + switch ($type) { + case 'bbs': + $this->writes[$group][$key] = $data; + break; + case 'content': + $this->contents[$group][$key] = $data; + break; + default: + $this->etcs[$group][$key] = $data; + break; + } + + } + /** + * cache 데이터 제거 + * @param string $type + * @param string $key + * @param string $group + * @return bool + */ + function delete($type, $key, $group = 'default') + { + if (!$this->exists($type, $key, $group)) { + return false; + } + + switch ($type) { + case 'bbs': + $datas = &$this->writes; + break; + case 'content': + $datas = &$this->contents; + break; + default: + $datas = &$this->etcs; + break; + } + + unset($datas[$group][$key]); + + return true; + } + +} //end Class; diff --git a/AvocadoEdition_Light/lib/cache.lib.php b/AvocadoEdition_Light/lib/cache.lib.php new file mode 100644 index 0000000..e2d336d --- /dev/null +++ b/AvocadoEdition_Light/lib/cache.lib.php @@ -0,0 +1,125 @@ + G5_DATA_PATH . '/cache', + 'file_extension' => '.php', + ); + $instance = new FileCache($options); + } + + return $instance; +} + +function g5_cache_secret_key() +{ + static $str = ''; + + if ($str) + return $str; + + $str = substr(md5($_SERVER['SERVER_SOFTWARE'] . $_SERVER['DOCUMENT_ROOT']), 0, 6); + + return $str; +} + +function g5_latest_cache_data($bo_table, $cache_list = array(), $find_wr_id = 0) +{ + static $cache = array(); + + if ($bo_table && $cache_list && !isset($cache[$bo_table])) { + foreach ((array) $cache_list as $wr) { + if (empty($wr) || !isset($wr['wr_id'])) + continue; + $cache[$bo_table][$wr['wr_id']] = $wr; + } + } + + if ($find_wr_id && isset($cache[$bo_table][$find_wr_id])) { + return $cache[$bo_table][$find_wr_id]; + } +} + +function g5_set_cache($key, $save_data, $ttl = null) +{ + + if ($cache = get_cachemanage_instance()) { + run_event('g5_set_cache_event', $cache, $key, $save_data, $ttl); + + if ((is_object($cache) && get_class($cache) === 'FileCache')) { + $cache->save($key, $save_data, $ttl); + } + } +} + +function g5_get_cache($key, $expired_time = 0) +{ + + if ($cache = get_cachemanage_instance()) { + if ((is_object($cache) && get_class($cache) === 'FileCache')) { + return $cache->get($key, $expired_time); + } + + return run_replace('g5_get_cache_replace', false, $cache, $key, $expired_time); + } + + return false; +} + +function g5_delete_cache($key) +{ + if ($cache = get_cachemanage_instance()) { + return $cache->delete($key); + } + + return false; +} + +function g5_delete_all_cache() +{ + + $board_tables = get_board_names(); + + foreach ($board_tables as $board_table) { + delete_cache_latest($board_table); + } + + run_event('adm_cache_delete', $board_tables); + +} + +function g5_delete_cache_by_prefix($key) +{ + + $cache = get_cachemanage_instance(); + $files = null; + + if ((is_object($cache) && get_class($cache) === 'FileCache')) { + $files = glob(G5_DATA_PATH . '/cache/' . $key . '*'); + + foreach ((array) $files as $filename) { + if (empty($filename)) + continue; + + unlink($filename); + } + } + + $files = run_replace('g5_delete_cache_by_prefix', $files, $key, $cache); + + return ($files) ? true : false; +} diff --git a/AvocadoEdition_Light/lib/get_data.lib.php b/AvocadoEdition_Light/lib/get_data.lib.php index 7d3aa59..d62b790 100644 --- a/AvocadoEdition_Light/lib/get_data.lib.php +++ b/AvocadoEdition_Light/lib/get_data.lib.php @@ -14,8 +14,520 @@ function get_config($is_cache = false) return $cache; } - $sql = "SELECT * FROM {$g5['config_table']} "; + $sql = " select * from {$g5['config_table']} "; $cache = run_replace('get_config', sql_fetch($sql)); return $cache; } + +function get_content_db($co_id, $is_cache = false) +{ + global $g5, $g5_object; + + static $cache = []; + + $type = 'content'; + + $co_id = preg_replace('/[^a-z0-9_]/i', '', $co_id); + $co = $g5_object->get($type, $co_id, $type); + + if (!$co) { + + $cache_file_name = "{$type}-{$co_id}-" . g5_cache_secret_key(); + $co = g5_get_cache($cache_file_name, 10800); + + if ($co === false) { + $sql = " select * from {$g5['content_table']} where co_id = '$co_id' "; + $co = sql_fetch($sql); + + g5_set_cache($cache_file_name, $co, 10800); + } + + $g5_object->set($type, $co_id, $co, $type); + } + + return $co; +} + +function get_board_names() +{ + global $g5; + + static $boards = []; + + $boards = run_replace('get_board_names_cache', $boards); + + if (!$boards) { + $sql = " select bo_table from {$g5['board_table']} "; + $result = sql_query($sql); + + while ($row = sql_fetch_array($result)) { + $boards[] = $row['bo_table']; + } + } + + return $boards; +} + +function get_board_db($bo_table, $is_cache = false) +{ + global $g5; + + static $cache = []; + + $bo_table = preg_replace('/[^a-z0-9_]/i', '', $bo_table); + $cache = run_replace('get_board_db_cache', $cache, $bo_table, $is_cache); + $key = md5($bo_table); + + if ($is_cache && isset($cache[$key])) { + return $cache[$key]; + } + + if (!($cache[$key] = run_replace('get_board_db', [], $bo_table))) { + + $sql = " select * from {$g5['board_table']} where bo_table = '$bo_table' "; + + $board = sql_fetch($sql); + + $board_defaults = [ + 'bo_table' => '', + 'bo_skin' => '', + 'bo_mobile_skin' => '', + 'bo_upload_count' => 0, + 'bo_use_dhtml_editor' => '', + 'bo_subject' => '', + 'bo_image_width' => 0 + ]; + + $cache[$key] = array_merge($board_defaults, (array) $board); + } + + return $cache[$key]; +} + +function get_menu_db($use_mobile = 0, $is_cache = false) +{ + global $g5; + + static $cache = []; + + $cache = run_replace('get_menu_db_cache', $cache, $use_mobile, $is_cache); + + $key = md5($use_mobile); + + if ($is_cache && isset($cache[$key])) { + return $cache[$key]; + } + + $where = $use_mobile ? "me_mobile_use = '1'" : "me_use = '1'"; + + if (!($cache[$key] = run_replace('get_menu_db', [], $use_mobile))) { + $sql = " select * + from {$g5['menu_table']} + where $where + and length(me_code) = '2' + order by me_order, me_id "; + $result = sql_query($sql, false); + + for ($i = 0; $row = sql_fetch_array($result); $i++) { + + $row['ori_me_link'] = $row['me_link']; + $row['me_link'] = short_url_clean($row['me_link']); + $row['sub'] = isset($row['sub']) ? $row['sub'] : []; + $cache[$key][$i] = $row; + + $sql2 = " select * + from {$g5['menu_table']} + where $where + and length(me_code) = '4' + and substring(me_code, 1, 2) = '{$row['me_code']}' + order by me_order, me_id "; + $result2 = sql_query($sql2); + for ($k = 0; $row2 = sql_fetch_array($result2); $k++) { + $row2['ori_me_link'] = $row2['me_link']; + $row2['me_link'] = short_url_clean($row2['me_link']); + $cache[$key][$i]['sub'][$k] = $row2; + } + } + } + + return $cache[$key]; +} + +// 게시판 테이블에서 하나의 행을 읽음 +function get_content_by_field($write_table, $type = 'bbs', $where_field = '', $where_value = '', $is_cache = false) +{ + global $g5, $g5_object; + + static $cache = []; + + $order_key = 'wr_id'; + + if ($type === 'content') { + $check_array = ['co_id', 'co_html', 'co_subject', 'co_content', 'co_seo_title', 'co_mobile_content', 'co_skin', 'co_mobile_skin', 'co_tag_filter_use', 'co_hit', 'co_include_head', 'co_include_tail']; + + $order_key = 'co_id'; + } else { + $check_array = ['wr_id', 'wr_num', 'wr_reply', 'wr_parent', 'wr_is_comment', 'ca_name', 'wr_option', 'wr_subject', 'wr_content', 'wr_seo_title', 'wr_link1', 'wr_link2', 'wr_hit', 'wr_good', 'wr_nogood', 'mb_id', 'wr_name', 'wr_email', 'wr_homepage', 'wr_datetime', 'wr_ip', 'wr_1', 'wr_2', 'wr_3', 'wr_4', 'wr_5', 'wr_6', 'wr_7', 'wr_8', 'wr_9', 'wr_10']; + } + + if (!in_array($where_field, $check_array)) { + return ''; + } + + $where_value = strip_tags($where_value); + $key = md5($write_table . '|' . $where_field . '|' . $where_value); + + if ($is_cache && isset($cache[$key])) { + return $cache[$key]; + } + + $sql = " select * from {$write_table} where $where_field = '" . sql_real_escape_string($where_value) . "' order by $order_key desc limit 1 "; + + $cache[$key] = sql_fetch($sql); + + if ($type === 'content') { + + $g5_object->set($type, $cache[$key]['co_id'], $cache[$key], 'content'); + + } else { + + $wr_bo_table = preg_replace('/^' . preg_quote($g5['write_prefix']) . '/i', '', $write_table); + $g5_object->set($type, $cache[$key]['wr_id'], $cache[$key], $wr_bo_table); + + } + + return $cache[$key]; +} + +// 게시판 첨부파일 테이블에서 하나의 행을 읽음 +function get_board_file_db($bo_table, $wr_id, $fields = '*', $add_where = '', $is_cache = false) +{ + global $g5; + + static $cache = []; + + $wr_id = (int) $wr_id; + $key = md5($bo_table . '|' . $wr_id . $fields . $add_where); + + if ($is_cache && isset($cache[$key])) { + return $cache[$key]; + } + + $sql = " select $fields from {$g5['board_file_table']} + where bo_table = '$bo_table' and wr_id = '$wr_id' $add_where order by bf_no limit 0, 1 "; + + $cache[$key] = sql_fetch($sql); + + return $cache[$key]; +} + +function get_poll_db($po_id, $is_cache = false) +{ + global $g5; + + static $cache = []; + + $po_id = (int) $po_id; + $key = md5($po_id); + + if ($is_cache && isset($cache[$key])) { + return $cache[$key]; + } + + $sql = " select * from {$g5['poll_table']} where po_id = '{$po_id}' "; + + $cache[$key] = sql_fetch($sql); + + return $cache[$key]; +} + +function get_point_db($po_id, $is_cache = false) +{ + global $g5; + + static $cache = []; + + $po_id = (int) $po_id; + $key = md5($po_id); + + if ($is_cache && isset($cache[$key])) { + return $cache[$key]; + } + + $sql = " select * from {$g5['point_table']} where po_id = '{$po_id}' "; + + $cache[$key] = sql_fetch($sql); + + return $cache[$key]; +} + +function get_mail_content_db($ma_id, $is_cache = false) +{ + global $g5; + + static $cache = []; + + $ma_id = (int) $ma_id; + $key = md5($ma_id); + + if ($is_cache && isset($cache[$key])) { + return $cache[$key]; + } + + $sql = " select * from {$g5['mail_table']} where ma_id = '{$ma_id}' "; + + $cache[$key] = sql_fetch($sql); + + return $cache[$key]; +} + +function get_qacontent_db($qa_id, $is_cache = false) +{ + global $g5; + + static $cache = []; + + $qa_id = (int) $qa_id; + $key = md5($qa_id); + + if ($is_cache && isset($cache[$key])) { + return $cache[$key]; + } + + $sql = " select * from {$g5['qa_content_table']} where qa_id = '{$qa_id}' "; + + $cache[$key] = sql_fetch($sql); + + return $cache[$key]; +} + +function get_thumbnail_find_cache($bo_table, $wr_id, $wr_key) +{ + global $g5; + + if ($cache_content = g5_latest_cache_data($bo_table, [], $wr_id)) { + if ($wr_key === 'content') { + return $cache_content; + } else if ($wr_key === 'file' && isset($cache_content['first_file_thumb'])) { + return $cache_content['first_file_thumb']; + } + } + + if ($wr_key === 'content') { + $write_table = $g5['write_prefix'] . $bo_table; + return get_write($write_table, $wr_id); + } + + return get_board_file_db($bo_table, $wr_id, 'bf_file, bf_content', "and bf_type in (1, 2, 3, 18) ", true); +} + +function get_write_table_name($bo_table) +{ + global $g5; + + return $g5['write_prefix'] . preg_replace('/[^a-z0-9_]/i', '', $bo_table); +} + +function get_db_charset($charset) +{ + + $add_charset = $charset; + + if ('utf8mb4' === $charset) { + $add_charset .= ' COLLATE utf8mb4_unicode_ci'; + } + + return run_replace('get_db_charset', $add_charset, $charset); +} + +function get_db_create_replace($sql_str) +{ + + if (in_array(strtolower(G5_DB_ENGINE), ['innodb', 'myisam'])) { + $sql_str = preg_replace('/ENGINE=MyISAM/', 'ENGINE=' . G5_DB_ENGINE, $sql_str); + } else { + $sql_str = preg_replace('/ENGINE=MyISAM/', '', $sql_str); + } + + if (G5_DB_CHARSET !== 'utf8') { + $sql_str = preg_replace('/CHARSET=utf8/', 'CHARACTER SET ' . get_db_charset(G5_DB_CHARSET), $sql_str); + } + + return $sql_str; +} + +function get_class_encrypt() +{ + static $cache; + + if ($cache && is_object($cache)) { + return $cache; + } + + $cache = run_replace('get_class_encrypt', new str_encrypt()); + + return $cache; +} + +function get_string_encrypt($str) +{ + + $new = get_class_encrypt(); + + $encrypt_str = $new->encrypt($str); + + return $encrypt_str; +} + +function get_string_decrypt($str) +{ + + $new = get_class_encrypt(); + + $decrypt_str = $new->decrypt($str); + + return $decrypt_str; +} + +function get_permission_debug_show() +{ + global $member; + + $bool = false; + if (defined('G5_DEBUG') && G5_DEBUG) { + $bool = true; + } + + return run_replace('get_permission_debug_show', $bool, $member); +} + +function get_check_mod_rewrite() +{ + + if (function_exists('apache_get_modules') && in_array('mod_rewrite', apache_get_modules())) + $mod_rewrite = 1; + elseif (isset($_SERVER['IIS_UrlRewriteModule'])) + $mod_rewrite = 1; + else + $mod_rewrite = 0; + + return $mod_rewrite; +} + +function get_mb_icon_name($mb_id) +{ + + if ($icon_name = run_replace('get_mb_icon_name', '', $mb_id)) { + return $icon_name; + } + + return $mb_id; +} + +// 생성되면 안되는 게시판명 +function get_bo_table_banned_word() +{ + + $folders = [G5_CONTENT_DIR, 'rss']; + + foreach (glob(G5_PATH . '/*', GLOB_ONLYDIR) as $dir) { + $folders[] = basename($dir); + } + + return run_replace('get_bo_table_banned_word', $folders); +} + +function get_board_sort_fields($board = [], $make_key_return = '') +{ + $bo_sort_fields = run_replace('get_board_sort_fields', [ + ['wr_num, wr_reply', '기본'], + ['wr_datetime asc', '날짜 이전것 부터'], + ['wr_datetime desc', '날짜 최근것 부터'], + ['wr_hit asc, wr_num, wr_reply', '조회수 낮은것 부터'], + ['wr_hit desc, wr_num, wr_reply', '조회수 높은것 부터'], + ['wr_last asc', '최근글 이전것 부터'], + ['wr_last desc', '최근글 최근것 부터'], + ['wr_comment asc, wr_num, wr_reply', '댓글수 낮은것 부터'], + ['wr_comment desc, wr_num, wr_reply', '댓글수 높은것 부터'], + ['wr_good asc, wr_num, wr_reply', '추천수 낮은것 부터'], + ['wr_good desc, wr_num, wr_reply', '추천수 높은것 부터'], + ['wr_nogood asc, wr_num, wr_reply', '비추천수 낮은것 부터'], + ['wr_nogood desc, wr_num, wr_reply', '비추천수 높은것 부터'], + ['wr_subject asc, wr_num, wr_reply', '제목 오름차순'], + ['wr_subject desc, wr_num, wr_reply', '제목 내림차순'], + ['wr_name asc, wr_num, wr_reply', '글쓴이 오름차순'], + ['wr_name desc, wr_num, wr_reply', '글쓴이 내림차순'], + ['ca_name asc, wr_num, wr_reply', '분류명 오름차순'], + ['ca_name desc, wr_num, wr_reply', '분류명 내림차순'], + ], $board, $make_key_return); + + if ($make_key_return) { + + $returns = []; + foreach ($bo_sort_fields as $v) { + $key = preg_replace("/[\<\>\'\"\\\'\\\"\%\=\(\)\/\^\*\s]/", "", $v[0]); + $returns[$key] = $v[0]; + } + + return $returns; + } + return $bo_sort_fields; +} + +function get_board_sfl_select_options($sfl) +{ + + global $is_admin; + + $str = ''; + $str .= ''; + $str .= ''; + $str .= ''; + if ($is_admin) { + $str .= ''; + $str .= ''; + } + $str .= ''; + $str .= ''; + + return run_replace('get_board_sfl_select_options', $str, $sfl); +} + +function get_qa_sfl_select_options($sfl) +{ + + global $is_admin; + + $str = ''; + $str .= ''; + $str .= ''; + $str .= ''; + if ($is_admin) + $str .= ''; + + return run_replace('get_qa_sfl_select_options', $str, $sfl); +} + +// 읽지 않은 메모 갯수 반환 +function get_memo_not_read($mb_id, $add_where = '') +{ + global $g5; + + $sql = " SELECT count(*) as cnt FROM {$g5['memo_table']} WHERE me_recv_mb_id = '$mb_id' and me_type= 'recv' and me_read_datetime like '0%' $add_where "; + $row = sql_fetch($sql, false); + + return isset($row['cnt']) ? $row['cnt'] : 0; +} + +function get_scrap_totals($mb_id = '') +{ + global $g5; + + $add_where = $mb_id ? " and mb_id = '$mb_id' " : ''; + + $sql = " select count(*) as cnt from {$g5['scrap_table']} where 1=1 $add_where"; + $row = sql_fetch($sql, false); + + return isset($row['cnt']) ? $row['cnt'] : 0; +} diff --git a/AvocadoEdition_Light/lib/thumbnail.lib.php b/AvocadoEdition_Light/lib/thumbnail.lib.php index abb4001..2455dad 100644 --- a/AvocadoEdition_Light/lib/thumbnail.lib.php +++ b/AvocadoEdition_Light/lib/thumbnail.lib.php @@ -8,52 +8,63 @@ if (!defined('_GNUBOARD_')) function get_list_thumbnail($bo_table, $wr_id, $thumb_width, $thumb_height, $is_create = false, $is_crop = false, $crop_mode = 'center', $is_sharpen = false, $um_value = '80/0.5/3') { global $g5, $config; - $filename = $alt = ""; + $filename = $alt = $data_path = ''; $edt = false; - $sql = " select bf_file, bf_content from {$g5['board_file_table']} - where bo_table = '$bo_table' and wr_id = '$wr_id' and bf_type between '1' and '3' order by bf_no limit 0, 1 "; - $row = sql_fetch($sql); + $empty_array = array('src' => '', 'ori' => '', 'alt' => ''); - if ($row['bf_file']) { + $write = get_thumbnail_find_cache($bo_table, $wr_id, 'content'); + + // 비밀글이면 썸네일을 노출하지 않습니다. + if (isset($write['wr_option']) && strstr($write['wr_option'], "secret")) { + return run_replace('is_secret_list_thumbnail', $empty_array, $bo_table, $write); + } + + $row = get_thumbnail_find_cache($bo_table, $wr_id, 'file'); + + if (isset($row['bf_file']) && $row['bf_file']) { $filename = $row['bf_file']; $filepath = G5_DATA_PATH . '/file/' . $bo_table; $alt = get_text($row['bf_content']); } else { - $write_table = $g5['write_prefix'] . $bo_table; - $sql = " select wr_content from $write_table where wr_id = '$wr_id' "; - $write = sql_fetch($sql); - $matches = get_editor_image($write['wr_content'], false); $edt = true; - for ($i = 0; $i < count($matches[1]); $i++) { - // 이미지 path 구함 - $p = parse_url($matches[1][$i]); - if (strpos($p['path'], '/' . G5_DATA_DIR . '/') != 0) - $data_path = preg_replace('/^\/.*\/' . G5_DATA_DIR . '/', '/' . G5_DATA_DIR, $p['path']); - else - $data_path = $p['path']; + if ($matches = get_editor_image($write['wr_content'], false)) { + for ($i = 0; $i < count($matches[1]); $i++) { + // 이미지 path 구함 + $p = parse_url($matches[1][$i]); + if (strpos($p['path'], '/' . G5_DATA_DIR . '/') != 0) + $data_path = preg_replace('/^\/.*\/' . G5_DATA_DIR . '/', '/' . G5_DATA_DIR, $p['path']); + else + $data_path = $p['path']; - $srcfile = G5_PATH . $data_path; + $srcfile = G5_PATH . $data_path; - if (preg_match("/\.({$config['cf_image_extension']})$/i", $srcfile) && is_file($srcfile)) { - $size = @getimagesize($srcfile); - if (empty($size)) - continue; + if (preg_match("/\.({$config['cf_image_extension']})$/i", $srcfile) && is_file($srcfile)) { + $size = @getimagesize($srcfile); + if (empty($size)) + continue; - $filename = basename($srcfile); - $filepath = dirname($srcfile); + $filename = basename($srcfile); + $filepath = dirname($srcfile); - preg_match("/alt=[\"\']?([^\"\']*)[\"\']?/", $matches[0][$i], $malt); - $alt = get_text($malt[1]); + preg_match("/alt=[\"\']?([^\"\']*)[\"\']?/", $matches[0][$i], $malt); + $alt = isset($malt[1]) ? get_text($malt[1]) : ''; - break; - } - } + break; + } + + $filename = run_replace('get_editor_filename', $filename, $p); + } //end for + } //end if } if (!$filename) - return false; + return $empty_array; + + if ($thumbnail_info = run_replace('get_list_thumbnail_info', array(), array('bo_table' => $bo_table, 'wr_id' => $wr_id, 'data_path' => $data_path, 'edt' => $edt, 'filename' => $filename, 'filepath' => $filepath, 'thumb_width' => $thumb_width, 'thumb_height' => $thumb_height, 'is_create' => $is_create, 'is_crop' => $is_crop, 'crop_mode' => $crop_mode, 'is_sharpen' => $is_sharpen, 'um_value' => $um_value))) { + return $thumbnail_info; + } $tname = thumbnail($filename, $filepath, $filepath, $thumb_width, $thumb_height, $is_create, $is_crop, $crop_mode, $is_sharpen, $um_value); @@ -68,7 +79,7 @@ function get_list_thumbnail($bo_table, $wr_id, $thumb_width, $thumb_height, $is_ $src = G5_DATA_URL . '/file/' . $bo_table . '/' . $tname; } } else { - return false; + return $empty_array; } $thumb = array("src" => $src, "ori" => $ori, "alt" => $alt); @@ -76,6 +87,22 @@ function get_list_thumbnail($bo_table, $wr_id, $thumb_width, $thumb_height, $is_ return $thumb; } +// 게시글보기 파일 썸네일 리턴 +function get_file_thumbnail($file) +{ + + if (!is_array($file)) + return ''; + + if (preg_match('/(\.jpg|\.jpeg|\.gif|\.png|\.bmp|\.webp)$/i', $file['file']) && $contents = run_replace('get_file_thumbnail_tags', '', $file)) { + return $contents; + } else if ($file['view']) { + return get_view_thumbnail($file['view']); + } + + return $file['view']; +} + // 게시글보기 썸네일 생성 function get_view_thumbnail($contents, $thumb_width = 0) { @@ -90,19 +117,23 @@ function get_view_thumbnail($contents, $thumb_width = 0) if (empty($matches)) return $contents; + $extensions = array(1 => 'gif', 2 => 'jpg', 3 => 'png', 18 => 'webp'); + for ($i = 0; $i < count($matches[1]); $i++) { $img = $matches[1][$i]; + $img_tag = isset($matches[0][$i]) ? $matches[0][$i] : ''; + preg_match("/src=[\'\"]?([^>\'\"]+[^>\'\"]+)/i", $img, $m); - $src = $m[1]; + $src = isset($m[1]) ? $m[1] : ''; preg_match("/style=[\"\']?([^\"\'>]+)/i", $img, $m); - $style = $m[1]; + $style = isset($m[1]) ? $m[1] : ''; preg_match("/width:\s*(\d+)px/", $style, $m); - $width = $m[1]; + $width = isset($m[1]) ? $m[1] : ''; preg_match("/height:\s*(\d+)px/", $style, $m); - $height = $m[1]; + $height = isset($m[1]) ? $m[1] : ''; preg_match("/alt=[\"\']?([^\"\']*)[\"\']?/", $img, $m); - $alt = get_text($m[1]); + $alt = isset($m[1]) ? get_text($m[1]) : ''; // 이미지 path 구함 $p = parse_url($src); @@ -118,8 +149,12 @@ function get_view_thumbnail($contents, $thumb_width = 0) if (empty($size)) continue; + $file_ext = $extensions[$size[2]]; + if (!$file_ext) + continue; + // jpg 이면 exif 체크 - if ($size[2] == 2 && function_exists('exif_read_data')) { + if ($file_ext === 'jpg' && function_exists('exif_read_data')) { $degree = 0; $exif = @exif_read_data($srcfile); if (!empty($exif['Orientation'])) { @@ -144,16 +179,22 @@ function get_view_thumbnail($contents, $thumb_width = 0) } } + // Animated GIF 체크 + $is_animated = false; + if ($file_ext === 'gif') { + $is_animated = is_animated_gif($srcfile); + + if ($replace_content = run_replace('thumbnail_is_animated_gif_content', '', $contents, $srcfile, $is_animated, $img_tag, $data_path, $size)) { + + $contents = $replace_content; + continue; + } + } + // 원본 width가 thumb_width보다 작다면 if ($size[0] <= $thumb_width) continue; - // Animated GIF 체크 - $is_animated = false; - if ($size[2] == 1) { - $is_animated = is_animated_gif($srcfile); - } - // 썸네일 높이 $thumb_height = round(($thumb_width * $size[1]) / $size[0]); $filename = basename($srcfile); @@ -175,17 +216,17 @@ function get_view_thumbnail($contents, $thumb_width = 0) } // $img_tag에 editor 경로가 있으면 원본보기 링크 추가 - $img_tag = $matches[0][$i]; if (strpos($img_tag, G5_DATA_DIR . '/' . G5_EDITOR_DIR) && preg_match("/\.({$config['cf_image_extension']})$/i", $filename)) { $imgurl = str_replace(G5_URL, "", $src); - $thumb_tag = '' . $thumb_tag . ''; + $attr_href = run_replace('thumb_view_image_href', G5_BBS_URL . '/view_image.php?fn=' . urlencode($imgurl), $filename, '', $width, $height, $alt); + $thumb_tag = '' . $thumb_tag . ''; } $contents = str_replace($img_tag, $thumb_tag, $contents); } } - return $contents; + return run_replace('get_view_thumbnail', $contents); } function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_height, $is_create, $is_crop = false, $crop_mode = 'center', $is_sharpen = false, $um_value = '80/0.5/3') @@ -200,10 +241,22 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h if (!is_file($source_file)) // 원본 파일이 없다면 return; + $size = @getimagesize($source_file); - if ($size[2] < 1 || $size[2] > 3) // gif, jpg, png 에 대해서만 적용 + + $extensions = array(1 => 'gif', 2 => 'jpg', 3 => 'png', 18 => 'webp'); + $file_ext = $extensions[$size[2]]; // 파일 확장자 + if (!$file_ext) return; + // gif, jpg, png, webp 에 대해서만 적용 + // if ( !(isset($size[2]) && ($size[2] == 1 || $size[2] == 2 || $size[2] == 3 || $size[2] == 18)) ) + // return; + + // $extensions 배열에 없는 확장자 라면 썸네일 만들지 않음 + // if (!in_array($file_ext, $extensions)) + // return; + if (!is_dir($target_path)) { @mkdir($target_path, G5_DIR_PERMISSION); @chmod($target_path, G5_DIR_PERMISSION); @@ -214,15 +267,18 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h return ''; // Animated GIF는 썸네일 생성하지 않음 - if ($size[2] == 1) { + if ($file_ext === 'gif') { if (is_animated_gif($source_file)) return basename($source_file); + } else if ($file_ext === 'webp') { + if (is_animated_webp($source_file)) + return basename($source_file); } - $ext = array(1 => 'gif', 2 => 'jpg', 3 => 'png'); $thumb_filename = preg_replace("/\.[^\.]+$/i", "", $filename); // 확장자제거 - $thumb_file = "$target_path/thumb-{$thumb_filename}_{$thumb_width}x{$thumb_height}." . $ext[$size[2]]; + // $thumb_file = "$target_path/thumb-{$thumb_filename}_{$thumb_width}x{$thumb_height}.".$ext[$size[2]]; + $thumb_file = "$target_path/thumb-{$thumb_filename}_{$thumb_width}x{$thumb_height}." . $file_ext; $thumb_time = @filemtime($thumb_file); $source_time = @filemtime($source_file); @@ -237,10 +293,10 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h $src = null; $degree = 0; - if ($size[2] == 1) { + if ($file_ext === 'gif') { $src = @imagecreatefromgif($source_file); $src_transparency = @imagecolortransparent($src); - } else if ($size[2] == 2) { + } else if ($file_ext === 'jpg') { $src = @imagecreatefromjpeg($source_file); if (function_exists('exif_read_data')) { @@ -272,9 +328,12 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h } } } - } else if ($size[2] == 3) { + } else if ($file_ext === 'png') { $src = @imagecreatefrompng($source_file); @imagealphablending($src, true); + } else if ($file_ext === 'webp') { + $src = @imagecreatefromwebp($source_file); + @imagealphablending($src, true); } else { return; } @@ -284,12 +343,16 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h $is_large = true; // width, height 설정 + if ($thumb_width) { if (!$thumb_height) { $thumb_height = round(($thumb_width * $size[1]) / $size[0]); } else { - if ($size[0] < $thumb_width || $size[1] < $thumb_height) + if ($crop_mode === 'center' && ($size[0] > $thumb_width || $size[1] > $thumb_height)) { + $is_large = true; + } else if ($size[0] < $thumb_width || $size[1] < $thumb_height) { $is_large = false; + } } } else { if ($thumb_height) { @@ -332,10 +395,10 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h $dst = imagecreatetruecolor($dst_w, $dst_h); - if ($size[2] == 3) { + if ($file_ext === 'png') { imagealphablending($dst, false); imagesavealpha($dst, true); - } else if ($size[2] == 1) { + } else if ($file_ext === 'gif') { $palletsize = imagecolorstotal($src); if ($src_transparency >= 0 && $src_transparency < $palletsize) { $transparent_color = imagecolorsforindex($src, $src_transparency); @@ -348,22 +411,24 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h $dst = imagecreatetruecolor($dst_w, $dst_h); $bgcolor = imagecolorallocate($dst, 255, 255, 255); // 배경색 - if ($src_w > $src_h) { - $tmp_h = round(($dst_w * $src_h) / $src_w); - $dst_y = round(($dst_h - $tmp_h) / 2); - $dst_h = $tmp_h; - } else { - $tmp_w = round(($dst_h * $src_w) / $src_h); - $dst_x = round(($dst_w - $tmp_w) / 2); - $dst_w = $tmp_w; + if (!((defined('G5_USE_THUMB_RATIO') && false === G5_USE_THUMB_RATIO) || (defined('G5_THEME_USE_THUMB_RATIO') && false === G5_THEME_USE_THUMB_RATIO))) { + if ($src_w > $src_h) { + $tmp_h = round(($dst_w * $src_h) / $src_w); + $dst_y = round(($dst_h - $tmp_h) / 2); + $dst_h = $tmp_h; + } else { + $tmp_w = round(($dst_h * $src_w) / $src_h); + $dst_x = round(($dst_w - $tmp_w) / 2); + $dst_w = $tmp_w; + } } - if ($size[2] == 3) { + if ($file_ext === 'png') { $bgcolor = imagecolorallocatealpha($dst, 0, 0, 0, 127); imagefill($dst, 0, 0, $bgcolor); imagealphablending($dst, false); imagesavealpha($dst, true); - } else if ($size[2] == 1) { + } else if ($file_ext === 'gif') { $palletsize = imagecolorstotal($src); if ($src_transparency >= 0 && $src_transparency < $palletsize) { $transparent_color = imagecolorsforindex($src, $src_transparency); @@ -381,30 +446,72 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h $dst = imagecreatetruecolor($dst_w, $dst_h); $bgcolor = imagecolorallocate($dst, 255, 255, 255); // 배경색 - if ($src_w < $dst_w) { - if ($src_h >= $dst_h) { - $dst_x = round(($dst_w - $src_w) / 2); - $src_h = $dst_h; + if (((defined('G5_USE_THUMB_RATIO') && false === G5_USE_THUMB_RATIO) || (defined('G5_THEME_USE_THUMB_RATIO') && false === G5_THEME_USE_THUMB_RATIO))) { + //이미지 썸네일을 비율 유지하지 않습니다. (5.2.6 버전 이하에서 처리된 부분과 같음) + + if ($src_w < $dst_w) { + if ($src_h >= $dst_h) { + $dst_x = round(($dst_w - $src_w) / 2); + $src_h = $dst_h; + if ($dst_w > $src_w) { + $dst_w = $src_w; + } + } else { + $dst_x = round(($dst_w - $src_w) / 2); + $dst_y = round(($dst_h - $src_h) / 2); + $dst_w = $src_w; + $dst_h = $src_h; + } } else { - $dst_x = round(($dst_w - $src_w) / 2); - $dst_y = round(($dst_h - $src_h) / 2); - $dst_w = $src_w; - $dst_h = $src_h; + if ($src_h < $dst_h) { + $dst_y = round(($dst_h - $src_h) / 2); + $dst_h = $src_h; + $src_w = $dst_w; + } } + } else { - if ($src_h < $dst_h) { - $dst_y = round(($dst_h - $src_h) / 2); - $dst_h = $src_h; - $src_w = $dst_w; + //이미지 썸네일을 비율 유지하며 썸네일 생성합니다. + if ($src_w < $dst_w) { + if ($src_h >= $dst_h) { + if ($src_h > $src_w) { + $tmp_w = round(($dst_h * $src_w) / $src_h); + $dst_x = round(($dst_w - $tmp_w) / 2); + $dst_w = $tmp_w; + } else { + $dst_x = round(($dst_w - $src_w) / 2); + $src_h = $dst_h; + if ($dst_w > $src_w) { + $dst_w = $src_w; + } + } + } else { + $dst_x = round(($dst_w - $src_w) / 2); + $dst_y = round(($dst_h - $src_h) / 2); + $dst_w = $src_w; + $dst_h = $src_h; + } + } else { + if ($src_h < $dst_h) { + if ($src_w > $dst_w) { + $tmp_h = round(($dst_w * $src_h) / $src_w); + $dst_y = round(($dst_h - $tmp_h) / 2); + $dst_h = $tmp_h; + } else { + $dst_y = round(($dst_h - $src_h) / 2); + $dst_h = $src_h; + $src_w = $dst_w; + } + } } } - if ($size[2] == 3) { + if ($file_ext === 'png') { $bgcolor = imagecolorallocatealpha($dst, 0, 0, 0, 127); imagefill($dst, 0, 0, $bgcolor); imagealphablending($dst, false); imagesavealpha($dst, true); - } else if ($size[2] == 1) { + } else if ($file_ext === 'gif') { $palletsize = imagecolorstotal($src); if ($src_transparency >= 0 && $src_transparency < $palletsize) { $transparent_color = imagecolorsforindex($src, $src_transparency); @@ -427,22 +534,24 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h UnsharpMask($dst, $val[0], $val[1], $val[2]); } - if ($size[2] == 1) { + if ($file_ext === 'gif') { imagegif($dst, $thumb_file); - } else if ($size[2] == 3) { + } else if ($file_ext === 'png') { if (!defined('G5_THUMB_PNG_COMPRESS')) $png_compress = 5; else $png_compress = G5_THUMB_PNG_COMPRESS; imagepng($dst, $thumb_file, $png_compress); - } else { + } else if ($file_ext === 'jpg') { if (!defined('G5_THUMB_JPG_QUALITY')) $jpg_quality = 90; else $jpg_quality = G5_THUMB_JPG_QUALITY; imagejpeg($dst, $thumb_file, $jpg_quality); + } else if ($file_ext === 'webp') { + imagewebp($dst, $thumb_file); } chmod($thumb_file, G5_FILE_PERMISSION); // 추후 삭제를 위하여 파일모드 변경 @@ -510,7 +619,7 @@ function UnsharpMask($img, $amount, $radius, $threshold) $radius = abs(round($radius)); // Only integers make sense. if ($radius == 0) { return $img; - imagedestroy($img); + // imagedestroy($img); } $w = imagesx($img); $h = imagesy($img); @@ -634,10 +743,37 @@ function UnsharpMask($img, $amount, $radius, $threshold) } +// 움직이는 webp 파일인지 검사한다. +// 출처) https://stackoverflow.com/questions/45190469/how-to-identify-whether-webp-image-is-static-or-animated?answertab=votes#tab-top +function is_animated_webp($filename) +{ + $contents = file_get_contents($filename); + $where = strpos($contents, "ANMF"); + if ($where !== false) { + // animated + $is_animated = true; + } else { + // non animated + $is_animated = false; + } + return $is_animated; +} + function is_animated_gif($filename) { - if (!($fh = @fopen($filename, 'rb'))) + + static $cache = array(); + $key = md5($filename); + + if (isset($cache[$key])) { + return $cache[$key]; + } + + if (!($fh = @fopen($filename, 'rb'))) { + $cache[$key] = false; return false; + } + $count = 0; // 출처 : http://www.php.net/manual/en/function.imagecreatefromgif.php#104473 // an animated gif contains multiple "frames", with each frame having a @@ -654,5 +790,10 @@ function is_animated_gif($filename) } fclose($fh); - return $count > 1; + + $cache[$key] = ($count > 1) ? true : false; + + run_event('is_animated_gif_after', $filename, $cache[$key]); + + return $cache[$key]; } diff --git a/AvocadoEdition_Light/lib/url.lib.php b/AvocadoEdition_Light/lib/url.lib.php new file mode 100644 index 0000000..268e66b --- /dev/null +++ b/AvocadoEdition_Light/lib/url.lib.php @@ -0,0 +1,497 @@ + 1) { + + $get_content = get_content_db($no, true); + $segments[2] = (isset($get_content['co_seo_title']) && $get_content['co_seo_title']) ? urlencode($get_content['co_seo_title']) . '/' : urlencode($no); + + } else { + $segments[2] = urlencode($no); + } + + } else if (in_array($folder, $boards)) { // 게시판 + + $segments[1] = $folder; + + if ($no) { + + if ($config['cf_bbs_rewrite'] > 1) { + + $get_write = get_write($g5['write_prefix'] . $folder, $no, true); + + $segments[2] = (isset($get_write['wr_seo_title']) && $get_write['wr_seo_title']) ? urlencode($get_write['wr_seo_title']) . '/' : urlencode($no); + + } else { + $segments[2] = urlencode($no); + } + + } else if ($action) { + $segments[2] = urlencode($action); + } + + } else { + $segments[1] = $folder; + if ($no) { + $no_array = explode("=", $no); + $no_value = end($no_array); + $segments[2] = urlencode($no_value); + } + } + + if ($query_string) { + // If the first character of the query string is '&', replace it with '?'. + if (substr($query_string, 0, 1) == '&') { + $add_query = preg_replace("/\&/", "?", $query_string, 1); + } else { + $add_query = '?' . $query_string; + } + } + + } else { // don't use shortten url + if (in_array($folder, $boards)) { + $url = G5_BBS_URL . '/board.php?bo_table=' . $folder; + if ($no) { + $url .= '&wr_id=' . $no; + } + if ($query_string) { + if (substr($query_string, 0, 1) !== '&') { + $url .= '&'; + } + + $url .= $query_string; + } + } else { + $url = G5_BBS_URL . '/' . $folder . '.php'; + if ($no) { + $url .= ($folder === 'content') ? '?co_id=' . $no : '?' . $no; + } + if ($query_string) { + $url .= (!$no ? '?' : '&') . $query_string; + } + } + + $segments[0] = $url; + } + + return implode('/', $segments) . $add_query; +} + +function short_url_clean($string_url, $add_qry = '') +{ + + global $config, $g5; + + if (isset($config['cf_bbs_rewrite']) && $config['cf_bbs_rewrite']) { + + $string_url = str_replace('&', '&', $string_url); + $url = parse_url($string_url); + $page_name = isset($url['path']) ? basename($url['path'], ".php") : ''; + + $array_page_names = run_replace('url_clean_page_names', array('board', 'write', 'content')); + + if (stripos(preg_replace('/^https?:/i', '', $string_url), preg_replace('/^https?:/i', '', G5_BBS_URL)) === false || !in_array($page_name, $array_page_names)) { //게시판이 아니면 리턴 + return run_replace('false_short_url_clean', $string_url, $url, $page_name, $array_page_names); + } + + $return_url = ''; + parse_str($url['query'], $vars); + + /* + // 예) Array ( [scheme] => http [host] => sir.kr [path] => /bbs/board.php [query] => wr_id=1110870&bo_table=cm_free&cpage=1 [fragment] => c_1110946 ) + foreach($vars as $k => $v) { $page_name .= "/".$v; } + */ + + if ($page_name === 'write') { + $vars['action'] = 'write'; + $allow_param_keys = array('bo_table' => '', 'action' => ''); + } else if ($page_name === 'content') { + $vars['action'] = 'content'; + $allow_param_keys = array('action' => '', 'co_id' => ''); + } else { + $allow_param_keys = array('bo_table' => '', 'wr_id' => ''); + } + + $s = array(); + + foreach ($allow_param_keys as $key => $v) { + if (!isset($vars[$key]) || empty($vars[$key])) + continue; + + $s[$key] = $vars[$key]; + } + + if ($config['cf_bbs_rewrite'] > 1 && $page_name === 'board' && (isset($s['wr_id']) && $s['wr_id']) && (isset($s['bo_table']) && $s['bo_table'])) { + $get_write = get_write(get_write_table_name($s['bo_table']), $s['wr_id'], true); + + if ($get_write['wr_seo_title']) { + unset($s['wr_id']); + $s['wr_seo_title'] = urlencode($get_write['wr_seo_title']) . '/'; + } + } + + $fragment = isset($url['fragment']) ? '#' . $url['fragment'] : ''; + + $host = G5_URL; + + if (isset($url['host'])) { + + $array_file_paths = run_replace('url_clean_page_paths', array('/' . G5_BBS_DIR . '/board.php', '/' . G5_BBS_DIR . '/write.php', '/' . G5_BBS_DIR . '/content.php')); + + $str_path = isset($url['path']) ? $url['path'] : ''; + $http = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://'; + $port = (isset($url['port']) && ($url['port'] !== 80 || $url['port'] !== 443)) ? ':' . $url['port'] : ''; + $host = $http . $url['host'] . $port . str_replace($array_file_paths, '', $str_path); + } + + $add_param = ''; + + if ($result = array_diff_key($vars, $allow_param_keys)) { + $add_param = '?' . http_build_query($result, '', '&'); + } + + if ($add_qry) { + $add_param .= $add_param ? '&' . $add_qry : '?' . $add_qry; + } + + foreach ($s as $k => $v) { + $return_url .= '/' . $v; + } + + return $host . $return_url . $add_param . $fragment; + } + + return $string_url; +} + +function correct_goto_url($url) +{ + + if (substr($url, -1) !== '/') { + return $url . '/'; + } + + return $url; +} + +function generate_seo_title($string, $wordLimit = G5_SEO_TITLE_WORD_CUT) +{ + $separator = '-'; + + if ($wordLimit != 0) { + $wordArr = explode(' ', $string); + $string = implode(' ', array_slice($wordArr, 0, $wordLimit)); + } + + $quoteSeparator = preg_quote($separator, '#'); + + $trans = array( + '&.+?;' => '', + '[^\w\d _-]' => '', + '\s+' => $separator, + '(' . $quoteSeparator . ')+' => $separator + ); + + $string = strip_tags($string); + + if (function_exists('mb_convert_encoding')) { + $string = mb_convert_encoding($string, 'UTF-8', 'UTF-8'); + } + + foreach ($trans as $key => $val) { + $string = preg_replace('#' . $key . '#iu', $val, $string); + } + + $string = strtolower($string); + + return trim(trim($string, $separator)); +} + +function exist_seo_url($type, $seo_title, $write_table, $sql_id = 0) +{ + global $g5; + + $exists_title = ''; + $sql_id = preg_replace('/[^a-z0-9_\-]/i', '', $sql_id); + // 영카트 상품코드의 경우 - 하이픈이 들어가야 함 + + if ($type === 'bbs') { + $sql = "select wr_seo_title FROM {$write_table} WHERE wr_seo_title = '" . sql_real_escape_string($seo_title) . "' AND wr_id <> '$sql_id' limit 1"; + $row = sql_fetch($sql); + + $exists_title = isset($row['wr_seo_title']) ? $row['wr_seo_title'] : ''; + + } else if ($type === 'content') { + + $sql = "select co_seo_title FROM {$write_table} WHERE co_seo_title = '" . sql_real_escape_string($seo_title) . "' AND co_id <> '$sql_id' limit 1"; + $row = sql_fetch($sql); + + $exists_title = isset($row['co_seo_title']) ? $row['co_seo_title'] : ''; + + } else { + return run_replace('exist_check_seo_title', $seo_title, $type, $write_table, $sql_id); + } + + if ($exists_title) + return 'is_exists'; + else + return ''; +} + +function check_case_exist_title($data, $case = G5_BBS_DIR, $is_redirect = false) +{ + global $config, $g5, $board; + + if ((int) $config['cf_bbs_rewrite'] !== 2) { + return; + } + + $seo_title = ''; + $redirect_url = ''; + + if ($case == G5_BBS_DIR && isset($data['wr_seo_title'])) { + $db_table = $g5['write_prefix'] . $board['bo_table']; + + if (exist_seo_url($case, $data['wr_seo_title'], $db_table, $data['wr_id'])) { + $seo_title = $data['wr_seo_title'] . '-' . $data['wr_id']; + $sql = " update `{$db_table}` set wr_seo_title = '" . sql_real_escape_string($seo_title) . "' where wr_id = '{$data['wr_id']}' "; + sql_query($sql, false); + + get_write($db_table, $data['wr_id'], false); + $redirect_url = get_pretty_url($board['bo_table'], $data['wr_id']); + } + } else if ($case == G5_CONTENT_DIR && isset($data['co_seo_title'])) { + $db_table = $g5['content_table']; + + if (exist_seo_url($case, $data['co_seo_title'], $db_table, $data['co_id'])) { + $seo_title = $data['co_seo_title'] . '-' . substr(get_random_token_string(4), 4); + $sql = " update `{$db_table}` set co_seo_title = '" . sql_real_escape_string($seo_title) . "' where co_id = '{$data['co_id']}' "; + sql_query($sql, false); + + get_content_db($data['co_id'], false); + g5_delete_cache_by_prefix('content-' . $data['co_id'] . '-'); + $redirect_url = get_pretty_url($case, $data['co_id']); + } + } else if (defined('G5_SHOP_DIR') && $case == G5_SHOP_DIR && isset($data['it_seo_title'])) { + $db_table = $g5['g5_shop_item_table']; + + if (shop_exist_check_seo_title($data['it_seo_title'], $case, $db_table, $data['it_id'])) { + $seo_title = $data['it_seo_title'] . '-' . substr(get_random_token_string(4), 4); + $sql = " update `{$db_table}` set it_seo_title = '" . sql_real_escape_string($seo_title) . "' where it_id = '{$data['it_id']}' "; + sql_query($sql, false); + + get_shop_item($data['it_id'], false); + $redirect_url = get_pretty_url($case, $data['it_id']); + } + } + + if ($is_redirect && $seo_title && $redirect_url) { + goto_url($redirect_url); + } +} + +function exist_seo_title_recursive($type, $seo_title, $write_table, $sql_id = 0) +{ + static $count = 0; + + $seo_title_add = ($count > 0) ? utf8_strcut($seo_title, 100000 - ($count + 1), '') . "-$count" : $seo_title; + + if (!exist_seo_url($type, $seo_title_add, $write_table, $sql_id)) { + return $seo_title_add; + } + + $count++; + + if ($count > 99998) { + return $seo_title_add; + } + + return exist_seo_title_recursive($type, $seo_title, $write_table, $sql_id); +} + +function seo_title_update($db_table, $pk_id, $type = 'bbs') +{ + + global $g5; + + $pk_id = (int) $pk_id; + + if ($type === 'bbs') { + + $write = get_write($db_table, $pk_id, true); + if (!(isset($write['wr_seo_title']) && $write['wr_seo_title']) && (isset($write['wr_subject']) && $write['wr_subject'])) { + $wr_seo_title = exist_seo_title_recursive('bbs', generate_seo_title($write['wr_subject']), $db_table, $pk_id); + + $sql = " update `{$db_table}` set wr_seo_title = '{$wr_seo_title}' where wr_id = '{$pk_id}' "; + sql_query($sql); + } + } else if ($type === 'content') { + + $co = get_content_db($pk_id, true); + if (!(isset($co['co_seo_title']) && $co['co_seo_title']) && (isset($co['co_subject']) && $co['co_subject'])) { + $co_seo_title = exist_seo_title_recursive('content', generate_seo_title($co['co_subject']), $db_table, $pk_id); + + $sql = " update `{$db_table}` set co_seo_title = '{$co_seo_title}' where co_id = '{$pk_id}' "; + sql_query($sql); + } + } +} + +function get_nginx_conf_rules($return_string = false) +{ + $get_path_url = parse_url(G5_URL); + $base_path = isset($get_path_url['path']) ? $get_path_url['path'] . '/' : '/'; + + $rules = array(); + $rules[] = '#### ' . G5_VERSION . ' nginx rules BEGIN #####'; + + if ($add_rules = run_replace('add_nginx_conf_pre_rules', '', $get_path_url, $base_path, $return_string)) { + $rules[] = $add_rules; + } + + $rules[] = 'if (!-e $request_filename) {'; + + if ($add_rules = run_replace('add_nginx_conf_rules', '', $get_path_url, $base_path, $return_string)) { + $rules[] = $add_rules; + } + + $rules[] = "rewrite ^{$base_path}content/([0-9a-zA-Z_]+)$ {$base_path}" . G5_BBS_DIR . "/content.php?co_id=$1&rewrite=1 break;"; + $rules[] = "rewrite ^{$base_path}content/([^/]+)/$ {$base_path}" . G5_BBS_DIR . "/content.php?co_seo_title=$1&rewrite=1 break;"; + $rules[] = "rewrite ^{$base_path}rss/([0-9a-zA-Z_]+)$ {$base_path}" . G5_BBS_DIR . "/rss.php?bo_table=$1 break;"; + $rules[] = "rewrite ^{$base_path}([0-9a-zA-Z_]+)$ {$base_path}" . G5_BBS_DIR . "/board.php?bo_table=$1&rewrite=1 break;"; + $rules[] = "rewrite ^{$base_path}([0-9a-zA-Z_]+)/write$ {$base_path}" . G5_BBS_DIR . "/write.php?bo_table=$1&rewrite=1 break;"; + $rules[] = "rewrite ^{$base_path}([0-9a-zA-Z_]+)/([^/]+)/$ {$base_path}" . G5_BBS_DIR . "/board.php?bo_table=$1&wr_seo_title=$2&rewrite=1 break;"; + $rules[] = "rewrite ^{$base_path}([0-9a-zA-Z_]+)/([0-9]+)$ {$base_path}" . G5_BBS_DIR . "/board.php?bo_table=$1&wr_id=$2&rewrite=1 break;"; + $rules[] = '}'; + $rules[] = '#### ' . G5_VERSION . ' nginx rules END #####'; + + return $return_string ? implode("\n", $rules) : $rules; +} + +function get_mod_rewrite_rules($return_string = false) +{ + $get_path_url = parse_url(G5_URL); + $base_path = isset($get_path_url['path']) ? $get_path_url['path'] . '/' : '/'; + + $rules = array(); + $rules[] = '#### ' . G5_VERSION . ' rewrite BEGIN #####'; + $rules[] = ''; + $rules[] = 'RewriteEngine On'; + $rules[] = 'RewriteBase ' . $base_path; + + if ($add_rules = run_replace('add_mod_rewrite_pre_rules', '', $get_path_url, $base_path, $return_string)) { + $rules[] = $add_rules; + } + + $rules[] = 'RewriteCond %{REQUEST_FILENAME} -f [OR]'; + $rules[] = 'RewriteCond %{REQUEST_FILENAME} -d'; + $rules[] = 'RewriteRule ^ - [L]'; + + if ($add_rules = run_replace('add_mod_rewrite_rules', '', $get_path_url, $base_path, $return_string)) { + $rules[] = $add_rules; + } + + $rules[] = 'RewriteRule ^content/([0-9a-zA-Z_]+)$ ' . G5_BBS_DIR . '/content.php?co_id=$1&rewrite=1 [QSA,L]'; + $rules[] = 'RewriteRule ^content/([^/]+)/$ ' . G5_BBS_DIR . '/content.php?co_seo_title=$1&rewrite=1 [QSA,L]'; + $rules[] = 'RewriteRule ^rss/([0-9a-zA-Z_]+)$ ' . G5_BBS_DIR . '/rss.php?bo_table=$1 [QSA,L]'; + $rules[] = 'RewriteRule ^([0-9a-zA-Z_]+)$ ' . G5_BBS_DIR . '/board.php?bo_table=$1&rewrite=1 [QSA,L]'; + $rules[] = 'RewriteRule ^([0-9a-zA-Z_]+)/([^/]+)/$ ' . G5_BBS_DIR . '/board.php?bo_table=$1&wr_seo_title=$2&rewrite=1 [QSA,L]'; + $rules[] = 'RewriteRule ^([0-9a-zA-Z_]+)/write$ ' . G5_BBS_DIR . '/write.php?bo_table=$1&rewrite=1 [QSA,L]'; + $rules[] = 'RewriteRule ^([0-9a-zA-Z_]+)/([0-9]+)$ ' . G5_BBS_DIR . '/board.php?bo_table=$1&wr_id=$2&rewrite=1 [QSA,L]'; + $rules[] = ''; + $rules[] = '#### ' . G5_VERSION . ' rewrite END #####'; + + return $return_string ? implode("\n", $rules) : $rules; +} + +function check_need_rewrite_rules() +{ + $is_apache = (stripos($_SERVER['SERVER_SOFTWARE'], 'apache') !== false); + + if ($is_apache) { + $save_path = G5_PATH . '/.htaccess'; + + if (!file_exists($save_path)) { + return true; + } + + $rules = get_mod_rewrite_rules(); + + $bof_str = $rules[0]; + $eof_str = end($rules); + + $code = file_get_contents($save_path); + + if (strpos($code, $bof_str) === false || strpos($code, $eof_str) === false) { + return true; + } + } + + return false; +} + +function update_rewrite_rules() +{ + + $is_apache = (stripos($_SERVER['SERVER_SOFTWARE'], 'apache') !== false); + + if ($is_apache) { + $save_path = G5_PATH . '/.htaccess'; + + if ((!file_exists($save_path) && is_writable(G5_PATH)) || is_writable($save_path)) { + + $rules = get_mod_rewrite_rules(); + + $bof_str = $rules[0]; + $eof_str = end($rules); + + if (file_exists($save_path)) { + $code = file_get_contents($save_path); + + if ($code && strpos($code, $bof_str) !== false && strpos($code, $eof_str) !== false) { + return true; + } + } + + $fp = fopen($save_path, "ab"); + flock($fp, LOCK_EX); + + $rewrite_str = implode("\n", $rules); + + fwrite($fp, "\n"); + fwrite($fp, $rewrite_str); + fwrite($fp, "\n"); + + flock($fp, LOCK_UN); + fclose($fp); + + return true; + } + } + + return false; + +}