Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65a419e9cd | ||
|
|
3f32ecd3e6 | ||
|
|
b5d218d446 | ||
|
|
f2e7dbc5ed | ||
|
|
c38de4c94b | ||
|
|
7d8a660642 | ||
|
|
5875e8b86b | ||
|
|
68a5b9c25a | ||
|
|
2dff49914b | ||
|
|
51518e45e4 | ||
|
|
7883ff65dc | ||
|
|
a2608754bd | ||
|
|
758bb67b7b | ||
|
|
0037f72cce | ||
|
|
df940f8168 | ||
|
|
614b040960 | ||
|
|
dccb50d8a3 | ||
|
|
5331aa8be5 | ||
|
|
79f915988b | ||
|
|
3cfe8b6b84 | ||
|
|
31ef78e916 | ||
|
|
a612e69d3e | ||
|
|
29e55de1fa | ||
|
|
c4db6e7751 | ||
|
|
47a3790c57 | ||
|
|
2894c269ea | ||
|
|
c00c73465a | ||
|
|
3e0e8be6da | ||
|
|
92a052fa7a | ||
|
|
4ebdd8ba30 | ||
|
|
4d5c597665 | ||
|
|
7e65a297bf | ||
|
|
ddcc82d89b | ||
|
|
ad99ea7673 | ||
|
|
b3fa6dc127 | ||
|
|
e6780f3b4b | ||
|
|
bededeaf01 | ||
|
|
73b868a444 | ||
|
|
eb249a2aee | ||
|
|
813fdef0c7 | ||
|
|
f8561e9398 | ||
|
|
52590509d5 | ||
|
|
604cef808e | ||
|
|
82574fd4a8 | ||
|
|
c3db9b454e | ||
|
|
bf19cd8bf5 | ||
|
|
b2c0e1af29 | ||
|
|
60d37b853b | ||
|
|
919b75a138 | ||
|
|
01fab8136e | ||
|
|
5054e24631 | ||
|
|
deff7d2079 | ||
|
|
5e6b4fa668 | ||
|
|
ef1be317e1 | ||
|
|
137d78ff73 | ||
|
|
0ddcda4b0c | ||
|
|
bf27af3925 | ||
|
|
607e15424d | ||
|
|
7c490448ec | ||
|
|
d775d2255f | ||
|
|
b94771de92 | ||
|
|
b29e16a198 | ||
|
|
0e06b4f9ce | ||
|
|
f2ab751e5f | ||
|
|
3432497efe | ||
|
|
60bb03049e | ||
|
|
a7541256cb |
+11
@@ -13,6 +13,17 @@ cheditor5.*/
|
||||
log/
|
||||
g5_tree/
|
||||
.vscode/
|
||||
.claude/
|
||||
.cursor/
|
||||
.windsurf/
|
||||
.idea/
|
||||
.playwright-mcp
|
||||
.mcp.json
|
||||
.agents
|
||||
.DS_Store
|
||||
*.swp
|
||||
*.swo
|
||||
CLAUDE.local.md
|
||||
naver*.html
|
||||
initests01/
|
||||
SIRsoft000/
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ function print_menu2($key, $no = '')
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($is_admin != 'super' && (!array_key_exists($menu[$key][$i][0], $auth) || !strstr($auth[$menu[$key][$i][0]], 'r'))) {
|
||||
if ($is_admin != 'super' && (!array_key_exists($menu[$key][$i][0], $auth) || strpos($auth[$menu[$key][$i][0]], 'r') === false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -281,7 +281,7 @@ function auth_check($auth, $attr, $return = false)
|
||||
|
||||
$attr = strtolower($attr);
|
||||
|
||||
if (!strstr($auth, $attr)) {
|
||||
if (strpos($auth, $attr) === false) {
|
||||
if ($attr == 'r') {
|
||||
$msg = '읽을 권한이 없습니다.';
|
||||
if ($return) {
|
||||
@@ -389,7 +389,7 @@ function order_select($fld, $sel = '')
|
||||
// 불법접근을 막도록 토큰을 생성하면서 토큰값을 리턴
|
||||
function get_admin_token()
|
||||
{
|
||||
$token = md5(uniqid(rand(), true));
|
||||
$token = get_random_token_string(16);
|
||||
set_session('ss_admin_token', $token);
|
||||
|
||||
return $token;
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ $print_version = ($is_admin == 'super') ? 'Version ' . G5_GNUBOARD_VER : '';
|
||||
</div>
|
||||
<footer id="ft">
|
||||
<p>
|
||||
Copyright © <?php echo $_SERVER['HTTP_HOST']; ?>. All rights reserved. <?php echo $print_version; ?><br>
|
||||
Copyright © <?php echo htmlspecialchars($_SERVER['HTTP_HOST']); ?>. All rights reserved. <?php echo $print_version; ?><br>
|
||||
<button type="button" class="scroll_top"><span class="top_img"></span><span class="top_txt">TOP</span></button>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
+4
-1
@@ -23,6 +23,9 @@ if (!$sst) {
|
||||
$sst = "a.mb_id, au_menu";
|
||||
$sod = "";
|
||||
}
|
||||
$allowed_sst = array('a.mb_id', 'mb_nick', 'au_menu', 'au_auth', 'a.mb_id, au_menu');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = 'a.mb_id, au_menu';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
$sql_order = " order by $sst $sod ";
|
||||
|
||||
$sql = " select count(*) as cnt
|
||||
@@ -151,7 +154,7 @@ $colspan = 5;
|
||||
//if (isset($stx))
|
||||
// echo '<script>document.fsearch.sfl.value = "'.$sfl.'";</script>'."\n";
|
||||
|
||||
if (strstr($sfl, 'mb_id')) {
|
||||
if (strpos($sfl, 'mb_id') !== false) {
|
||||
$mb_id = $stx;
|
||||
} else {
|
||||
$mb_id = '';
|
||||
|
||||
+16
-13
@@ -39,14 +39,17 @@ $bo_include_tail = isset($_POST['bo_include_tail']) ? preg_replace(array("#[\\\]
|
||||
$check_captcha = false;
|
||||
|
||||
// 관리자가 자동등록방지 CAPTCHA를 사용해야 할 경우
|
||||
if ($w === 'u') {
|
||||
if (isset($board['bo_include_head'], $board['bo_include_tail']) &&
|
||||
($board['bo_include_head'] !== $bo_include_head || $board['bo_include_tail'] !== $bo_include_tail)) {
|
||||
$check_captcha = true;
|
||||
}
|
||||
} elseif ($w === '') {
|
||||
if ($bo_include_head !== '_head.php' || $bo_include_tail !== '_tail.php') {
|
||||
$check_captcha = true;
|
||||
// 최고 관리자인 경우에만 수정가능
|
||||
if ($is_admin === 'super') {
|
||||
if ($w === 'u') {
|
||||
if (isset($board['bo_include_head'], $board['bo_include_tail']) &&
|
||||
($board['bo_include_head'] !== $bo_include_head || $board['bo_include_tail'] !== $bo_include_tail)) {
|
||||
$check_captcha = true;
|
||||
}
|
||||
} elseif ($w === '') {
|
||||
if ($bo_include_head !== '_head.php' || $bo_include_tail !== '_tail.php') {
|
||||
$check_captcha = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +139,7 @@ $bo_hot = isset($_POST['bo_hot']) ? (int) $_POST['bo_hot'] : 0;
|
||||
$bo_image_width = isset($_POST['bo_image_width']) ? (int) $_POST['bo_image_width'] : 0;
|
||||
$bo_use_search = isset($_POST['bo_use_search']) ? (int) $_POST['bo_use_search'] : 0;
|
||||
$bo_use_cert = isset($_POST['bo_use_cert']) ? preg_replace('/[^0-9a-z_]/i', '', $_POST['bo_use_cert']) : '';
|
||||
$bo_device = isset($_POST['bo_device']) ? clean_xss_tags($_POST['bo_device'], 1, 1) : '';
|
||||
$bo_device = isset($_POST['bo_device']) ? addslashes(clean_xss_tags(stripslashes($_POST['bo_device']), 1, 1)) : '';
|
||||
$bo_list_level = isset($_POST['bo_list_level']) ? (int) $_POST['bo_list_level'] : 0;
|
||||
$bo_read_level = isset($_POST['bo_read_level']) ? (int) $_POST['bo_read_level'] : 0;
|
||||
$bo_write_level = isset($_POST['bo_write_level']) ? (int) $_POST['bo_write_level'] : 0;
|
||||
@@ -152,9 +155,9 @@ $bo_read_point = isset($_POST['bo_read_point']) ? (int) $_POST['bo_read_point']
|
||||
$bo_write_point = isset($_POST['bo_write_point']) ? (int) $_POST['bo_write_point'] : 0;
|
||||
$bo_comment_point = isset($_POST['bo_comment_point']) ? (int) $_POST['bo_comment_point'] : 0;
|
||||
$bo_download_point = isset($_POST['bo_download_point']) ? (int) $_POST['bo_download_point'] : 0;
|
||||
$bo_select_editor = isset($_POST['bo_select_editor']) ? clean_xss_tags($_POST['bo_select_editor'], 1, 1) : '';
|
||||
$bo_skin = isset($_POST['bo_skin']) ? clean_xss_tags($_POST['bo_skin'], 1, 1) : '';
|
||||
$bo_mobile_skin = isset($_POST['bo_mobile_skin']) ? clean_xss_tags($_POST['bo_mobile_skin'], 1, 1) : '';
|
||||
$bo_select_editor = isset($_POST['bo_select_editor']) ? addslashes(clean_xss_tags(stripslashes($_POST['bo_select_editor']), 1, 1)) : '';
|
||||
$bo_skin = isset($_POST['bo_skin']) ? addslashes(clean_xss_tags(stripslashes($_POST['bo_skin']), 1, 1)) : '';
|
||||
$bo_mobile_skin = isset($_POST['bo_mobile_skin']) ? addslashes(clean_xss_tags(stripslashes($_POST['bo_mobile_skin']), 1, 1)) : '';
|
||||
$bo_content_head = isset($_POST['bo_content_head']) ? $_POST['bo_content_head'] : '';
|
||||
$bo_content_tail = isset($_POST['bo_content_tail']) ? $_POST['bo_content_tail'] : '';
|
||||
$bo_mobile_content_head = isset($_POST['bo_mobile_content_head']) ? $_POST['bo_mobile_content_head'] : '';
|
||||
@@ -173,7 +176,7 @@ $bo_write_min = isset($_POST['bo_write_min']) ? (int) $_POST['bo_write_min'] : 0
|
||||
$bo_write_max = isset($_POST['bo_write_max']) ? (int) $_POST['bo_write_max'] : 0;
|
||||
$bo_comment_min = isset($_POST['bo_comment_min']) ? (int) $_POST['bo_comment_min'] : 0;
|
||||
$bo_comment_max = isset($_POST['bo_comment_max']) ? (int) $_POST['bo_comment_max'] : 0;
|
||||
$bo_sort_field = isset($_POST['bo_sort_field']) ? clean_xss_tags($_POST['bo_sort_field'], 1, 1) : '';
|
||||
$bo_sort_field = isset($_POST['bo_sort_field']) ? addslashes(clean_xss_tags(stripslashes($_POST['bo_sort_field']), 1, 1)) : '';
|
||||
|
||||
if (strpbrk($bo_skin.$bo_mobile_skin, "?%*:|\"<>") !== false) {
|
||||
alert('스킨 디렉토리명 오류!');
|
||||
|
||||
@@ -32,6 +32,9 @@ if (!$sst) {
|
||||
$sst = "a.gr_id, a.bo_table";
|
||||
$sod = "asc";
|
||||
}
|
||||
$allowed_sst = array('a.gr_id', 'bo_table', 'bo_skin', 'bo_mobile_skin', 'bo_subject', 'bo_use_sns', 'bo_use_search', 'bo_order', 'a.gr_id, a.bo_table');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = 'a.gr_id, a.bo_table';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
$sql_order = " order by $sst $sod ";
|
||||
|
||||
$sql = " select count(*) as cnt {$sql_common} {$sql_search} {$sql_order} ";
|
||||
|
||||
@@ -34,6 +34,9 @@ if ($stx) {
|
||||
$sql_search .= " ) ";
|
||||
}
|
||||
|
||||
$allowed_sst = array('gr_id', 'gr_subject', 'gr_admin', 'gr_order');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = '';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
if ($sst) {
|
||||
$sql_order = " order by {$sst} {$sod} ";
|
||||
} else {
|
||||
|
||||
@@ -28,6 +28,9 @@ if (!$sst) {
|
||||
$sst = "gm_datetime";
|
||||
$sod = "desc";
|
||||
}
|
||||
$allowed_sst = array('gm_datetime', 'b.mb_id', 'b.mb_name', 'b.mb_nick', 'b.mb_today_login', 'a.gm_datetime');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = 'gm_datetime';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
$sql_order = " order by {$sst} {$sod} ";
|
||||
|
||||
$sql = " select count(*) as cnt
|
||||
|
||||
@@ -35,8 +35,8 @@ $co_timg_del = (isset($_POST['co_timg_del']) && $_POST['co_timg_del']) ? 1 : 0;
|
||||
$co_html = isset($_POST['co_html']) ? (int) $_POST['co_html'] : 0;
|
||||
$co_content = isset($_POST['co_content']) ? $_POST['co_content'] : '';
|
||||
$co_mobile_content = isset($_POST['co_mobile_content']) ? $_POST['co_mobile_content'] : '';
|
||||
$co_skin = isset($_POST['co_skin']) ? clean_xss_tags($_POST['co_skin'], 1, 1) : '';
|
||||
$co_mobile_skin = isset($_POST['co_mobile_skin']) ? clean_xss_tags($_POST['co_mobile_skin'], 1, 1) : '';
|
||||
$co_skin = isset($_POST['co_skin']) ? addslashes(clean_xss_tags(stripslashes($_POST['co_skin']), 1, 1)) : '';
|
||||
$co_mobile_skin = isset($_POST['co_mobile_skin']) ? addslashes(clean_xss_tags(stripslashes($_POST['co_mobile_skin']), 1, 1)) : '';
|
||||
|
||||
// 관리자가 자동등록방지를 사용해야 할 경우
|
||||
if (((isset($co_row['co_include_head']) && $co_row['co_include_head'] !== $co_include_head) || (isset($co_row['co_include_tail']) && $co_row['co_include_tail'] !== $co_include_tail)) && function_exists('get_admin_captcha_by') && get_admin_captcha_by()) {
|
||||
|
||||
+1
-1
@@ -586,7 +586,7 @@ td.td_grpset {width:160px;border-left:1px solid #e9ecee;text-align:center}
|
||||
.td_time{text-align:center;width:130px}
|
||||
.td_center{text-align:center;}
|
||||
.td_type{width:120px}
|
||||
.td_consent{width:200px}
|
||||
.td_consent{min-width:70px;max-width:200px}
|
||||
|
||||
.td_mng_s{width:60px}
|
||||
.td_mng_m{width:100px}
|
||||
|
||||
@@ -317,6 +317,63 @@ if (!isset($member['mb_marketing_agree'])) {
|
||||
$is_check = true;
|
||||
}
|
||||
|
||||
// 쿠폰 로그 테이블에 UNIQUE 인덱스 추가 (쿠폰 이중사용 방지)
|
||||
if (defined('G5_USE_SHOP') && G5_USE_SHOP) {
|
||||
$result = sql_query("SHOW INDEX FROM `{$g5['g5_shop_coupon_log_table']}` WHERE Key_name = 'idx_coupon_use'", false);
|
||||
if (!$result || !sql_num_rows($result)) {
|
||||
// 기존에 동일 쿠폰이 중복 사용된 데이터가 있으면 UNIQUE 인덱스 생성 실패하므로 중복 데이터 정리
|
||||
$dup_sql = " SELECT cp_id, mb_id, MIN(cl_id) as keep_id
|
||||
FROM `{$g5['g5_shop_coupon_log_table']}`
|
||||
GROUP BY cp_id, mb_id
|
||||
HAVING COUNT(*) > 1 ";
|
||||
|
||||
$dup_result = sql_query($dup_sql, false);
|
||||
if ($dup_result && sql_num_rows($dup_result)) {
|
||||
while ($dup_row = sql_fetch_array($dup_result)) {
|
||||
|
||||
echo $dup_row['cp_id']." 의 동일 쿠폰이 중복 사용된 데이터가 있으므로 인덱스 생성이 불가합니다. <br>";
|
||||
|
||||
$sql = " DELETE FROM `{$g5['g5_shop_coupon_log_table']}`
|
||||
WHERE cp_id = '{$dup_row['cp_id']}'
|
||||
AND mb_id = '{$dup_row['mb_id']}'
|
||||
AND cl_id != '{$dup_row['keep_id']}' ";
|
||||
if ($is_admin === 'super') {
|
||||
echo "데이터베이스에서 검토후에 이 쿼리문을 실행해 주세요.<br>$sql<br>";
|
||||
}
|
||||
// sql_query($sql);
|
||||
}
|
||||
}
|
||||
|
||||
// MyISAM + utf8mb4 환경에서 키 길이 초과 방지: cp_id varchar(100), mb_id varchar(100)으로 조정
|
||||
sql_query("ALTER TABLE `{$g5['g5_shop_coupon_log_table']}` MODIFY `cp_id` varchar(100) NOT NULL DEFAULT '', MODIFY `mb_id` varchar(100) NOT NULL DEFAULT ''", false);
|
||||
sql_query("ALTER TABLE `{$g5['g5_shop_coupon_log_table']}` ADD UNIQUE KEY `idx_coupon_use` (`cp_id`, `mb_id`)", false);
|
||||
$is_check = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 자동 로그인 토큰 테이블 생성 (KVE-2026-0610: 추측 가능한 자동 로그인 쿠키 위조 방지)
|
||||
// 다중 디바이스 지원을 위해 회원당 여러 토큰을 별도 테이블로 관리
|
||||
if (!isset($g5['member_auto_login_table'])) {
|
||||
$g5['member_auto_login_table'] = G5_TABLE_PREFIX.'member_auto_login';
|
||||
}
|
||||
if (!sql_query(" DESC `{$g5['member_auto_login_table']}` ", false)) {
|
||||
sql_query(" CREATE TABLE IF NOT EXISTS `{$g5['member_auto_login_table']}` (
|
||||
`al_id` int(11) NOT NULL auto_increment,
|
||||
`mb_id` varchar(20) NOT NULL default '',
|
||||
`al_token` varchar(64) NOT NULL default '',
|
||||
`al_user_agent` varchar(255) NOT NULL default '',
|
||||
`al_ip` varchar(45) NOT NULL default '',
|
||||
`al_created` datetime DEFAULT NULL,
|
||||
`al_last_used` datetime DEFAULT NULL,
|
||||
`al_expire` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`al_id`),
|
||||
UNIQUE KEY `al_token` (`al_token`),
|
||||
KEY `mb_id` (`mb_id`),
|
||||
KEY `al_expire` (`al_expire`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ", true);
|
||||
$is_check = true;
|
||||
}
|
||||
|
||||
$is_check = run_replace('admin_dbupgrade', $is_check);
|
||||
|
||||
$db_upgrade_msg = $is_check ? 'DB 업그레이드가 완료되었습니다.' : '더 이상 업그레이드 할 내용이 없습니다.<br>현재 DB 업그레이드가 완료된 상태입니다.';
|
||||
|
||||
+9
-4
@@ -284,14 +284,19 @@ if (!auth_check_menu($auth, '200200', 'r', true)) {
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$row2['mb_id'] = '';
|
||||
$row2 = array('mb_id'=>'');
|
||||
for ($i = 0; $row = sql_fetch_array($result); $i++) {
|
||||
if ($row2['mb_id'] != $row['mb_id']) {
|
||||
if (empty($row2) || $row2['mb_id'] != $row['mb_id']) {
|
||||
$sql2 = " SELECT mb_id, mb_name, mb_nick, mb_email, mb_homepage, mb_point from {$g5['member_table']} where mb_id = '{$row['mb_id']}' ";
|
||||
$row2 = sql_fetch($sql2);
|
||||
}
|
||||
|
||||
$mb_nick = get_sideview($row['mb_id'], $row2['mb_nick'], $row2['mb_email'], $row2['mb_homepage']);
|
||||
$mb_nick = get_sideview(
|
||||
$row['mb_id'],
|
||||
isset($row2['mb_nick']) ? $row2['mb_nick'] : '',
|
||||
isset($row2['mb_email']) ? $row2['mb_email'] : '',
|
||||
isset($row2['mb_homepage']) ? $row2['mb_homepage'] : ''
|
||||
);
|
||||
|
||||
$link1 = $link2 = "";
|
||||
if (!preg_match("/^\@/", $row['po_rel_table']) && $row['po_rel_table']) {
|
||||
@@ -302,7 +307,7 @@ if (!auth_check_menu($auth, '200200', 'r', true)) {
|
||||
|
||||
<tr>
|
||||
<td class="td_mbid"><a href="./point_list.php?sfl=mb_id&stx=<?php echo $row['mb_id'] ?>"><?php echo $row['mb_id'] ?></a></td>
|
||||
<td class="td_mbname"><?php echo get_text($row2['mb_name']); ?></td>
|
||||
<td class="td_mbname"><?php echo isset($row2['mb_name']) ? get_text($row2['mb_name']) : ''; ?></td>
|
||||
<td class="td_name sv_use">
|
||||
<div><?php echo $mb_nick ?></div>
|
||||
</td>
|
||||
|
||||
@@ -80,7 +80,7 @@ require_once './admin.head.php';
|
||||
<tr>
|
||||
<th scope="row"><label for="mb_email">E-mail</label></th>
|
||||
<td>
|
||||
<?php echo help("메일 주소에 단어 포함 (예 : @" . preg_replace('#^(www[^\.]*\.){1}#', '', $_SERVER['HTTP_HOST']) . ")") ?>
|
||||
<?php echo help("메일 주소에 단어 포함 (예 : @" . htmlspecialchars(preg_replace('#^(www[^\.]*\.){1}#', '', $_SERVER['HTTP_HOST'])) . ")") ?>
|
||||
<input type="text" name="mb_email" value="<?php echo get_sanitize_input($mb_email); ?>" id="mb_email" class="frm_input" size="50">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -12,10 +12,10 @@ $sql_common = " from {$g5['member_table']} ";
|
||||
$sql_where = " where (1) ";
|
||||
|
||||
$mb_id1 = isset($_POST['mb_id1']) ? (int) $_POST['mb_id1'] : 1;
|
||||
$mb_id1_from = isset($_POST['mb_id1_from']) ? clean_xss_tags($_POST['mb_id1_from'], 1, 1, 30) : '';
|
||||
$mb_id1_to = isset($_POST['mb_id1_to']) ? clean_xss_tags($_POST['mb_id1_to'], 1, 1, 30) : '';
|
||||
$mb_email = isset($_POST['mb_email']) ? clean_xss_tags($_POST['mb_email'], 1, 1, 100) : '';
|
||||
$mb_mailling = isset($_POST['mb_mailling']) ? clean_xss_tags($_POST['mb_mailling'], 1, 1, 100) : '';
|
||||
$mb_id1_from = isset($_POST['mb_id1_from']) ? addslashes(clean_xss_tags(stripslashes($_POST['mb_id1_from']), 1, 1, 30)) : '';
|
||||
$mb_id1_to = isset($_POST['mb_id1_to']) ? addslashes(clean_xss_tags(stripslashes($_POST['mb_id1_to']), 1, 1, 30)) : '';
|
||||
$mb_email = isset($_POST['mb_email']) ? addslashes(clean_xss_tags(stripslashes($_POST['mb_email']), 1, 1, 100)) : '';
|
||||
$mb_mailling = isset($_POST['mb_mailling']) ? addslashes(clean_xss_tags(stripslashes($_POST['mb_mailling']), 1, 1, 100)) : '';
|
||||
$mb_level_from = isset($_POST['mb_level_from'])? (int) $_POST['mb_level_from'] : 1;
|
||||
$mb_level_to = isset($_POST['mb_level_to']) ? (int) $_POST['mb_level_to'] : 10;
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ $mb_certify = isset($_POST['mb_certify']) ? preg_replace('/[^0-9a-z_]/i', ''
|
||||
$mb_zip = isset($_POST['mb_zip']) ? preg_replace('/[^0-9a-z_]/i', '', $_POST['mb_zip']) : '';
|
||||
|
||||
// 광고성 정보 수신
|
||||
$mb_marketing_agree = isset($_POST['mb_marketing_agree']) ? clean_xss_tags($_POST['mb_marketing_agree'], 1, 1) : '0';
|
||||
$mb_thirdparty_agree = isset($_POST['mb_thirdparty_agree']) ? clean_xss_tags($_POST['mb_thirdparty_agree'], 1, 1) : '0';
|
||||
$mb_marketing_agree = isset($_POST['mb_marketing_agree']) ? addslashes(clean_xss_tags(stripslashes($_POST['mb_marketing_agree']), 1, 1)) : '0';
|
||||
$mb_thirdparty_agree = isset($_POST['mb_thirdparty_agree']) ? addslashes(clean_xss_tags(stripslashes($_POST['mb_thirdparty_agree']), 1, 1)) : '0';
|
||||
|
||||
// 관리자가 자동등록방지를 사용해야 할 경우 ( 회원의 비밀번호 변경시 캡챠를 체크한다 )
|
||||
if ($mb_password) {
|
||||
@@ -84,9 +84,9 @@ for ($i = 1; $i <= 10; $i++) {
|
||||
|
||||
foreach ($check_keys as $key) {
|
||||
if( in_array($key, array('mb_signature', 'mb_profile')) ){
|
||||
$posts[$key] = isset($_POST[$key]) ? clean_xss_tags($_POST[$key], 1, 1, 0, 0) : '';
|
||||
$posts[$key] = isset($_POST[$key]) ? addslashes(clean_xss_tags(stripslashes($_POST[$key]), 1, 1, 0, 0)) : '';
|
||||
} else {
|
||||
$posts[$key] = isset($_POST[$key]) ? clean_xss_tags($_POST[$key], 1, 1) : '';
|
||||
$posts[$key] = isset($_POST[$key]) ? addslashes(clean_xss_tags(stripslashes($_POST[$key]), 1, 1)) : '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-9
@@ -6,6 +6,12 @@ auth_check_menu($auth, $sub_menu, 'r');
|
||||
|
||||
$sql_common = " from {$g5['member_table']} ";
|
||||
|
||||
// $sfl 화이트리스트 검증 (KVE-2026-0340)
|
||||
$allowed_sfl = array('mb_id', 'mb_nick', 'mb_name', 'mb_level', 'mb_email', 'mb_tel', 'mb_hp', 'mb_point', 'mb_datetime', 'mb_ip', 'mb_recommend');
|
||||
if (!in_array($sfl, $allowed_sfl)) {
|
||||
$sfl = 'mb_id';
|
||||
}
|
||||
|
||||
$sql_search = " where (1) ";
|
||||
if ($stx) {
|
||||
$sql_search .= " and ( ";
|
||||
@@ -127,7 +133,7 @@ $colspan = 16;
|
||||
<th scope="col" rowspan="2" id="mb_list_cert"><?php echo subject_sort_link('mb_certify', '', 'desc') ?>본인확인</a></th>
|
||||
<th scope="col" id="mb_list_mailc"><?php echo subject_sort_link('mb_email_certify', '', 'desc') ?>메일인증</a></th>
|
||||
<th scope="col" id="mb_list_open"><?php echo subject_sort_link('mb_open', '', 'desc') ?>정보공개</a></th>
|
||||
<th scope="col" id="mb_list_mailr"><?php echo subject_sort_link('mb_mailling', '', 'desc') ?>광고성이메일수신</a></th>
|
||||
<th scope="col" id="mb_list_mailr"><?php echo subject_sort_link('mb_mailling', '', 'desc') ?>광고성이메일</a></th>
|
||||
<th scope="col" id="mb_list_auth">상태</th>
|
||||
<th scope="col" id="mb_list_mobile">휴대폰</th>
|
||||
<th scope="col" id="mb_list_lastcall"><?php echo subject_sort_link('mb_today_login', '', 'desc') ?>최종접속</a></th>
|
||||
@@ -137,9 +143,9 @@ $colspan = 16;
|
||||
<tr>
|
||||
<th scope="col" id="mb_list_name"><?php echo subject_sort_link('mb_name') ?>이름</a></th>
|
||||
<th scope="col" id="mb_list_nick"><?php echo subject_sort_link('mb_nick') ?>닉네임</a></th>
|
||||
<th scope="col" id="mb_list_sms"><?php echo subject_sort_link('mb_sms', '', 'desc') ?>광고성SMS/카카오톡수신</a></th>
|
||||
<th scope="col" id="mb_list_adultc"><?php echo subject_sort_link('mb_adult', '', 'desc') ?>성인인증</a></th>
|
||||
<th scope="col" id="mb_list_auth"><?php echo subject_sort_link('mb_intercept_date', '', 'desc') ?>접근차단</a></th>
|
||||
<th scope="col" id="mb_list_sms"><?php echo subject_sort_link('mb_sms', '', 'desc') ?>광고성SMS</a></th>
|
||||
<th scope="col" id="mb_list_deny"><?php echo subject_sort_link('mb_level', '', 'desc') ?>권한</a></th>
|
||||
<th scope="col" id="mb_list_tel">전화번호</th>
|
||||
<th scope="col" id="mb_list_join"><?php echo subject_sort_link('mb_datetime', '', 'desc') ?>가입일</a></th>
|
||||
@@ -258,7 +264,7 @@ $colspan = 16;
|
||||
<input type="checkbox" name="mb_open[<?php echo $i; ?>]" <?php echo $row['mb_open'] ? 'checked' : ''; ?> value="1" id="mb_open_<?php echo $i; ?>">
|
||||
</td>
|
||||
<td headers="mb_list_mailr" class="td_consent">
|
||||
<label for="mb_mailling_<?php echo $i; ?>" class="sound_only">메일수신</label>
|
||||
<label for="mb_mailling_<?php echo $i; ?>" class="sound_only">광고성이메일수신</label>
|
||||
<input type="checkbox" name="mb_mailling[<?php echo $i; ?>]" <?php echo $row['mb_mailling'] ? 'checked' : ''; ?> value="1" id="mb_mailling_<?php echo $i; ?>">
|
||||
<input type="hidden" name="mb_mailling_default[<?php echo $i; ?>]" value="<?php echo isset($row['mb_mailling']) ? $row['mb_mailling'] : '0'; ?> " id="mb_mailling_default_<?php echo $i; ?>">
|
||||
</td>
|
||||
@@ -281,12 +287,6 @@ $colspan = 16;
|
||||
<td headers="mb_list_nick" class="td_name sv_use">
|
||||
<div><?php echo $mb_nick ?></div>
|
||||
</td>
|
||||
|
||||
<td headers="mb_list_sms">
|
||||
<label for="mb_sms_<?php echo $i; ?>" class="sound_only">SMS수신</label>
|
||||
<input type="checkbox" name="mb_sms[<?php echo $i; ?>]" <?php echo $row['mb_sms'] ? 'checked' : ''; ?> value="1" id="mb_sms_<?php echo $i; ?>">
|
||||
<input type="hidden" name="mb_sms_default[<?php echo $i; ?>]" value="<?php echo isset($row['mb_sms']) ? $row['mb_sms'] : '0'; ?> " id="mb_sms_default_<?php echo $i; ?>">
|
||||
</td>
|
||||
<td headers="mb_list_adultc">
|
||||
<label for="mb_adult_<?php echo $i; ?>" class="sound_only">성인인증</label>
|
||||
<input type="checkbox" name="mb_adult[<?php echo $i; ?>]" <?php echo $row['mb_adult'] ? 'checked' : ''; ?> value="1" id="mb_adult_<?php echo $i; ?>">
|
||||
@@ -297,6 +297,11 @@ $colspan = 16;
|
||||
<label for="mb_intercept_date_<?php echo $i; ?>" class="sound_only">접근차단</label>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<td headers="mb_list_sms">
|
||||
<label for="mb_sms_<?php echo $i; ?>" class="sound_only">광고성SMS/카카오톡수신</label>
|
||||
<input type="checkbox" name="mb_sms[<?php echo $i; ?>]" <?php echo $row['mb_sms'] ? 'checked' : ''; ?> value="1" id="mb_sms_<?php echo $i; ?>">
|
||||
<input type="hidden" name="mb_sms_default[<?php echo $i; ?>]" value="<?php echo isset($row['mb_sms']) ? $row['mb_sms'] : '0'; ?> " id="mb_sms_default_<?php echo $i; ?>">
|
||||
</td>
|
||||
<td headers="mb_list_auth" class="td_mbstat">
|
||||
<?php echo get_member_level_select("mb_level[$i]", 1, $member['mb_level'], $row['mb_level']) ?>
|
||||
</td>
|
||||
|
||||
+4
-1
@@ -25,6 +25,9 @@ if (!$sst) {
|
||||
$sst = "po_id";
|
||||
$sod = "desc";
|
||||
}
|
||||
$allowed_sst = array('po_id', 'mb_id', 'po_content', 'po_point', 'po_datetime');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = 'po_id';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
$sql_order = " order by {$sst} {$sod} ";
|
||||
|
||||
$sql = " select count(*) as cnt
|
||||
@@ -66,7 +69,7 @@ if ($config['cf_point_term'] > 0) {
|
||||
$po_expire_term = $config['cf_point_term'];
|
||||
}
|
||||
|
||||
if (strstr($sfl, "mb_id")) {
|
||||
if (strpos($sfl, "mb_id") !== false) {
|
||||
$mb_id = $stx;
|
||||
} else {
|
||||
$mb_id = "";
|
||||
|
||||
@@ -21,6 +21,9 @@ if (!$sst) {
|
||||
$sst = "po_id";
|
||||
$sod = "desc";
|
||||
}
|
||||
$allowed_sst = array('po_id', 'po_subject', 'po_level', 'po_use', 'po_etc');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = 'po_id';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
$sql_order = " order by {$sst} {$sod} ";
|
||||
|
||||
$sql = " select count(*) as cnt
|
||||
|
||||
@@ -36,6 +36,9 @@ if (!$sst) {
|
||||
$sst = "pp_id";
|
||||
$sod = "desc";
|
||||
}
|
||||
$allowed_sst = array('pp_id', 'pp_word', 'pp_date', 'pp_ip');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = 'pp_id';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
$sql_order = " order by {$sst} {$sod} ";
|
||||
|
||||
$sql = " select count(*) as cnt
|
||||
|
||||
@@ -31,7 +31,7 @@ include_once("./admin.head.php");
|
||||
echo $list_tag_st;
|
||||
while($file=readdir($dir)) {
|
||||
|
||||
if (!strstr($file,'sess_')) continue;
|
||||
if (strpos($file,'sess_') === false) continue;
|
||||
if (strpos($file,'sess_')!=0) continue;
|
||||
|
||||
$session_file = G5_DATA_PATH.'/session/'.$file;
|
||||
|
||||
@@ -42,6 +42,9 @@ if (!$sst)
|
||||
$sst = "ca_id";
|
||||
$sod = "asc";
|
||||
}
|
||||
$allowed_sst = array('ca_id', 'ca_name', 'ca_mb_id', 'ca_use');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = 'ca_id';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
$sql_order = "order by $sst $sod";
|
||||
|
||||
// 출력할 레코드를 얻음
|
||||
|
||||
@@ -640,7 +640,7 @@ if(!$default['de_kakaopay_cancelpwd']){
|
||||
<tr id="kcp_vbank_url" class="pg_vbank_url">
|
||||
<th scope="row">NHN KCP 가상계좌<br>입금통보 URL</th>
|
||||
<td>
|
||||
<?php echo help("NHN KCP 가상계좌 사용시 다음 주소를 <strong><a href=\"http://admin.kcp.co.kr\" target=\"_blank\">NHN KCP 관리자</a> > 상점정보관리 > 정보변경 > 공통URL 정보 > 공통URL 변경후</strong>에 넣으셔야 상점에 자동으로 입금 통보됩니다."); ?>
|
||||
<?php echo help("NHN KCP 가상계좌 사용시 다음 주소를 <strong><a href=\"https://partner.kcp.co.kr\" target=\"_blank\">NHN KCP 관리자</a> > 상점정보관리 > 정보변경 > 공통URL 정보 > 공통URL 변경후</strong>에 넣으셔야 상점에 자동으로 입금 통보됩니다."); ?>
|
||||
<?php echo G5_SHOP_URL; ?>/settle_kcp_common.php</td>
|
||||
</tr>
|
||||
<tr id="inicis_vbank_url" class="pg_vbank_url">
|
||||
@@ -694,7 +694,7 @@ if(!$default['de_kakaopay_cancelpwd']){
|
||||
<tr>
|
||||
<th scope="row"><label for="de_easy_pay_use">PG사 간편결제 버튼 사용</label></th>
|
||||
<td>
|
||||
<?php echo help("주문서 작성 페이지에 PG사 간편결제(PAYCO, PAYNOW, KPAY) 버튼의 별도 사용 여부를 설정합니다.", 50); ?>
|
||||
<?php echo help("주문서 작성 페이지에 PG사 간편결제(PAYCO, 토스, KPAY...) 버튼의 별도 사용 여부를 설정합니다.", 50); ?>
|
||||
<select id="de_easy_pay_use" name="de_easy_pay_use">
|
||||
<option value="0" <?php echo get_selected($default['de_easy_pay_use'], 0); ?>>노출안함</option>
|
||||
<option value="1" <?php echo get_selected($default['de_easy_pay_use'], 1); ?>>노출함</option>
|
||||
@@ -715,13 +715,13 @@ if(!$default['de_kakaopay_cancelpwd']){
|
||||
<?php
|
||||
$account_checked = $vbank_checked = $transfer_checked = '';
|
||||
|
||||
if (strstr($default['de_taxsave_types'], 'account')) {
|
||||
if (strpos($default['de_taxsave_types'], 'account') !== false) {
|
||||
$account_checked = 'checked="checked"';
|
||||
}
|
||||
if (strstr($default['de_taxsave_types'], 'vbank')) {
|
||||
if (strpos($default['de_taxsave_types'], 'vbank') !== false) {
|
||||
$vbank_checked = 'checked="checked"';
|
||||
}
|
||||
if (strstr($default['de_taxsave_types'], 'transfer')) {
|
||||
if (strpos($default['de_taxsave_types'], 'transfer') !== false) {
|
||||
$transfer_checked = 'checked="checked"';
|
||||
}
|
||||
?>
|
||||
@@ -1097,8 +1097,7 @@ if(!$default['de_kakaopay_cancelpwd']){
|
||||
<a href="http://testadmin8.kcp.co.kr/" target="_blank" class="btn_frmline">테스트 관리자</a>
|
||||
</div>
|
||||
<div class="scf_cardtest lg_cardtest">
|
||||
<a href="https://app.tosspayments.com/" target="_blank" class="btn_frmline">실결제 관리자</a>
|
||||
<a href="https://pgweb.tosspayments.com/tmert" target="_blank" class="btn_frmline">테스트 관리자</a>
|
||||
<a href="https://app.tosspayments.com/" target="_blank" class="btn_frmline">상점 관리자</a>
|
||||
</div>
|
||||
<div class="scf_cardtest toss_cardtest">
|
||||
<a href="https://app.tosspayments.com/" target="_blank" class="btn_frmline">상점 관리자</a>
|
||||
@@ -1122,14 +1121,14 @@ if(!$default['de_kakaopay_cancelpwd']){
|
||||
<dt>휴대폰</dt><dd>테스트 지원되지 않음.</dd>
|
||||
</dl>
|
||||
<ul id="kcp_cardtest_tip" class="scf_cardtest_tip_adm scf_cardtest_tip_adm_hide">
|
||||
<li>테스트결제의 <a href="http://testadmin8.kcp.co.kr/assist/login.LoginAction.do" target="_blank">상점관리자</a> 로그인 정보는 NHN KCP로 문의하시기 바랍니다. (기술지원 1544-8661)</li>
|
||||
<li>테스트결제의 <a href="https://testpartner.kcp.co.kr/" target="_blank">상점관리자</a> 로그인 정보는 NHN KCP로 문의하시기 바랍니다. (기술지원 1544-8661)</li>
|
||||
<li><b>일반결제</b>의 테스트 사이트코드는 <b>T0000</b> 이며, <b>에스크로 결제</b>의 테스트 사이트코드는 <b>T0007</b> 입니다.</li>
|
||||
</ul>
|
||||
<ul id="lg_cardtest_tip" class="scf_cardtest_tip_adm scf_cardtest_tip_adm_hide">
|
||||
<li>테스트결제의 <a href="https://pgweb.tosspayments.com/tmert" target="_blank">상점관리자</a> 로그인 정보는 토스페이먼츠 상점아이디 첫 글자에 t를 추가해서 로그인하시기 바랍니다. 예) tsi_lguplus</li>
|
||||
<li>테스트 결제건에 대한 <a href="https://app.tosspayments.com/" target="_blank">상점관리자</a> 접근은, 상점관리자 상단 '테스트 모드'를 활성화 하여서 접근할 수 있습니다.</li>
|
||||
</ul>
|
||||
<ul id="toss_cardtest_tip" class="scf_cardtest_tip_adm scf_cardtest_tip_adm_hide">
|
||||
<li>테스트 결제 시 <a href="https://app.tosspayments.com/" target="_blank">상점관리자</a> 로그인 정보는 실결제용 키와는 다르니 반드시 <b>[테스트] API 연동 키</b>로 로그인해야 합니다. 예) test_ck_toss</li>
|
||||
<li>테스트 결제건에 대한 <a href="https://app.tosspayments.com/" target="_blank">상점관리자</a> 접근은, 상점관리자 상단 '테스트 모드'를 활성화 하여서 접근할 수 있습니다.</li>
|
||||
</ul>
|
||||
<ul id="inicis_cardtest_tip" class="scf_cardtest_tip_adm scf_cardtest_tip_adm_hide">
|
||||
<li><b>일반결제</b>의 테스트 사이트 mid는 <b>INIpayTest</b> 이며, <b>에스크로 결제</b>의 테스트 사이트 mid는 <b>iniescrow0</b> 입니다.</li>
|
||||
@@ -2142,4 +2141,5 @@ if($default['de_iche_use'] || $default['de_vbank_use'] || $default['de_hp_use']
|
||||
}
|
||||
}
|
||||
|
||||
include_once (G5_ADMIN_PATH.'/admin.tail.php');
|
||||
|
||||
include_once (G5_ADMIN_PATH.'/admin.tail.php');
|
||||
|
||||
@@ -64,6 +64,8 @@ foreach($check_skin_keys as $key){
|
||||
if( isset($_POST[$key]) && preg_match('#\.+(\/|\\\)#', $_POST[$key]) ){
|
||||
alert('스킨설정에 유효하지 문자가 포함되어 있습니다.');
|
||||
}
|
||||
|
||||
$$key = $_POST[$key] = sql_real_escape_string($_POST[$key]);
|
||||
}
|
||||
|
||||
// 현금영수증 발급수단
|
||||
|
||||
@@ -6,6 +6,8 @@ auth_check_menu($auth, $sub_menu, "r");
|
||||
|
||||
$sql_common = " from {$g5['g5_shop_coupon_table']} ";
|
||||
|
||||
if ($sfl && !in_array($sfl, array('mb_id', 'cp_subject', 'cp_id'))) $sfl = '';
|
||||
|
||||
$sql_search = " where (1) ";
|
||||
if ($stx) {
|
||||
$sql_search .= " and ( ";
|
||||
@@ -24,6 +26,9 @@ if (!$sst) {
|
||||
$sst = "cp_no";
|
||||
$sod = "desc";
|
||||
}
|
||||
$allowed_sst = array('cp_no', 'cp_id', 'cp_subject', 'mb_id', 'cp_end', 'cp_start', 'cp_method');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = 'cp_no';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
$sql_order = " order by {$sst} {$sod} ";
|
||||
|
||||
$sql = " select count(*) as cnt
|
||||
|
||||
@@ -212,28 +212,28 @@ if($data['od_settle_case'] == 'KAKAOPAY')
|
||||
$od_pg = 'KAKAOPAY';
|
||||
|
||||
$od_email = get_email_address($data['od_email']);
|
||||
$od_name = clean_xss_tags($data['od_name']);
|
||||
$od_tel = clean_xss_tags($data['od_tel']);
|
||||
$od_hp = clean_xss_tags($data['od_hp']);
|
||||
$od_name = addslashes(clean_xss_tags($data['od_name']));
|
||||
$od_tel = addslashes(clean_xss_tags($data['od_tel']));
|
||||
$od_hp = addslashes(clean_xss_tags($data['od_hp']));
|
||||
$od_zip = preg_replace('/[^0-9]/', '', $data['od_zip']);
|
||||
$od_zip1 = substr($od_zip, 0, 3);
|
||||
$od_zip2 = substr($od_zip, 3);
|
||||
$od_addr1 = clean_xss_tags($data['od_addr1']);
|
||||
$od_addr2 = clean_xss_tags($data['od_addr2']);
|
||||
$od_addr3 = clean_xss_tags($data['od_addr3']);
|
||||
$od_addr1 = addslashes(clean_xss_tags($data['od_addr1']));
|
||||
$od_addr2 = addslashes(clean_xss_tags($data['od_addr2']));
|
||||
$od_addr3 = addslashes(clean_xss_tags($data['od_addr3']));
|
||||
$od_addr_jibeon = preg_match("/^(N|R)$/", $data['od_addr_jibeon']) ? $data['od_addr_jibeon'] : '';
|
||||
$od_b_name = clean_xss_tags($data['od_b_name']);
|
||||
$od_b_tel = clean_xss_tags($data['od_b_tel']);
|
||||
$od_b_hp = clean_xss_tags($data['od_b_hp']);
|
||||
$od_b_name = addslashes(clean_xss_tags($data['od_b_name']));
|
||||
$od_b_tel = addslashes(clean_xss_tags($data['od_b_tel']));
|
||||
$od_b_hp = addslashes(clean_xss_tags($data['od_b_hp']));
|
||||
$od_b_zip = preg_replace('/[^0-9]/', '', $data['od_b_zip']);
|
||||
$od_b_zip1 = substr($od_b_zip, 0, 3);
|
||||
$od_b_zip2 = substr($od_b_zip, 3);
|
||||
$od_b_addr1 = clean_xss_tags($data['od_b_addr1']);
|
||||
$od_b_addr2 = clean_xss_tags($data['od_b_addr2']);
|
||||
$od_b_addr3 = clean_xss_tags($data['od_b_addr3']);
|
||||
$od_b_addr1 = addslashes(clean_xss_tags($data['od_b_addr1']));
|
||||
$od_b_addr2 = addslashes(clean_xss_tags($data['od_b_addr2']));
|
||||
$od_b_addr3 = addslashes(clean_xss_tags($data['od_b_addr3']));
|
||||
$od_b_addr_jibeon = preg_match("/^(N|R)$/", $data['od_b_addr_jibeon']) ? $data['od_b_addr_jibeon'] : '';
|
||||
$od_memo = clean_xss_tags($data['od_memo'], 0, 1, 0, 0);
|
||||
$od_deposit_name = clean_xss_tags($data['od_deposit_name']);
|
||||
$od_memo = addslashes(clean_xss_tags($data['od_memo'], 0, 1, 0, 0));
|
||||
$od_deposit_name = addslashes(clean_xss_tags($data['od_deposit_name']));
|
||||
$od_tax_flag = $default['de_tax_flag_use'];
|
||||
$od_receipt_price = $tot_ct_price + $od_send_cost + $od_send_cost2 - ($od_temp_point + $tot_cp_price + $tot_sc_cp_price);
|
||||
$od_receipt_point = $od_temp_point;
|
||||
|
||||
@@ -67,7 +67,9 @@ for ($i=0; $row=sql_fetch_array($result); $i++)
|
||||
for ($i=0; $i<$len; $i++)
|
||||
$nbsp .= " ";
|
||||
|
||||
$category_select .= "<option value=\"{$row['ca_id']}\">$nbsp{$row['ca_name']}</option>\n";
|
||||
// 전체 카테고리 경로 표시
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row['ca_id']) : $row['ca_name'];
|
||||
$category_select .= "<option value=\"{$row['ca_id']}\">$nbsp{$category_path}</option>\n";
|
||||
}
|
||||
|
||||
// 모바일 1줄당 이미지수 필드 추가
|
||||
|
||||
@@ -107,7 +107,9 @@ if($ev_id) {
|
||||
$len = strlen($row1['ca_id']) / 2 - 1;
|
||||
$nbsp = "";
|
||||
for ($i=0; $i<$len; $i++) $nbsp .= " ";
|
||||
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
|
||||
// 전체 카테고리 경로 표시
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
|
||||
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$category_path.'</option>'.PHP_EOL;
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
@@ -146,9 +146,11 @@ for ($i=0; $row=sql_fetch_array($result); $i++)
|
||||
$nbsp = "";
|
||||
for ($i=0; $i<$len; $i++)
|
||||
$nbsp .= " ";
|
||||
|
||||
$category_select .= "<option value=\"{$row['ca_id']}\">$nbsp{$row['ca_name']}</option>\n";
|
||||
|
||||
|
||||
// 전체 카테고리 경로 표시 (예: 남성의류 > 상의 > 셔츠)
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row['ca_id']) : $row['ca_name'];
|
||||
$category_select .= "<option value=\"{$row['ca_id']}\">$nbsp{$category_path}</option>\n";
|
||||
|
||||
$script .= "ca_use['{$row['ca_id']}'] = {$row['ca_use']};\n";
|
||||
$script .= "ca_stock_qty['{$row['ca_id']}'] = {$row['ca_stock_qty']};\n";
|
||||
//$script .= "ca_explan_html['$row[ca_id]'] = $row[ca_explan_html];\n";
|
||||
@@ -1394,7 +1396,9 @@ $(function(){
|
||||
for ($i=0; $i<$len; $i++)
|
||||
$nbsp .= " ";
|
||||
|
||||
echo "<option value=\"{$row['ca_id']}\">$nbsp{$row['ca_name']}</option>\n";
|
||||
// 전체 카테고리 경로 표시
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row['ca_id']) : $row['ca_name'];
|
||||
echo "<option value=\"{$row['ca_id']}\">$nbsp{$category_path}</option>\n";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
@@ -25,7 +25,8 @@ for ($i=0; $row=sql_fetch_array($result); $i++)
|
||||
for ($i=0; $i<$len; $i++) {
|
||||
$nbsp .= ' ';
|
||||
}
|
||||
$ca_list .= '<option value="'.$row['ca_id'].'">'.$nbsp.$row['ca_name'].'</option>'.PHP_EOL;
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row['ca_id']) : $row['ca_name'];
|
||||
$ca_list .= '<option value="'.$row['ca_id'].'">'.$nbsp.$category_path.'</option>'.PHP_EOL;
|
||||
}
|
||||
|
||||
$where = " and ";
|
||||
@@ -67,6 +68,9 @@ if (!$sst) {
|
||||
$sst = "it_id";
|
||||
$sod = "desc";
|
||||
}
|
||||
$allowed_sst = array('it_id', 'it_name', 'it_order', 'it_use', 'it_soldout', 'it_hit', 'it_price', 'it_cust_price', 'it_point', 'it_stock_qty');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = 'it_id';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
$sql_order = "order by $sst $sod";
|
||||
|
||||
|
||||
@@ -100,7 +104,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
|
||||
$len = strlen($row1['ca_id']) / 2 - 1;
|
||||
$nbsp = '';
|
||||
for ($i=0; $i<$len; $i++) $nbsp .= ' ';
|
||||
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sca, $row1['ca_id']).'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
|
||||
// 전체 카테고리 경로 표시
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
|
||||
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sca, $row1['ca_id']).'>'.$nbsp.$category_path.'</option>'.PHP_EOL;
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
@@ -31,6 +31,9 @@ if (!$sst) {
|
||||
$sst = "iq_id";
|
||||
$sod = "desc";
|
||||
}
|
||||
$allowed_sst = array('iq_id', 'a.it_id', 'it_name', 'iq_time');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = 'iq_id';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
|
||||
$sql_common = " from {$g5['g5_shop_item_qa_table']} a
|
||||
left join {$g5['g5_shop_item_table']} b on (a.it_id = b.it_id)
|
||||
@@ -79,7 +82,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
|
||||
$nbsp = "";
|
||||
for ($i=0; $i<$len; $i++) $nbsp .= " ";
|
||||
$selected = ($row1['ca_id'] == $sca) ? ' selected="selected"' : '';
|
||||
echo '<option value="'.$row1['ca_id'].'"'.$selected.'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
|
||||
// 전체 카테고리 경로 표시
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
|
||||
echo '<option value="'.$row1['ca_id'].'"'.$selected.'>'.$nbsp.$category_path.'</option>'.PHP_EOL;
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
@@ -83,7 +83,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
|
||||
$len = strlen($row1['ca_id']) / 2 - 1;
|
||||
$nbsp = "";
|
||||
for ($i=0; $i<$len; $i++) $nbsp .= " ";
|
||||
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
|
||||
// 전체 카테고리 경로 표시
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
|
||||
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$category_path.'</option>'.PHP_EOL;
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
@@ -82,7 +82,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
|
||||
$len = strlen($row1['ca_id']) / 2 - 1;
|
||||
$nbsp = "";
|
||||
for ($i=0; $i<$len; $i++) $nbsp .= " ";
|
||||
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
|
||||
// 전체 카테고리 경로 표시
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
|
||||
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$category_path.'</option>'.PHP_EOL;
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
@@ -46,6 +46,9 @@ if (!$sst) {
|
||||
$sst = "it_id";
|
||||
$sod = "desc";
|
||||
}
|
||||
$allowed_sst = array('it_id', 'it_name', 'it_type1', 'it_type2', 'it_type3', 'it_type4', 'it_type5', 'ca_id');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = 'it_id';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
$sql_order = "order by $sst $sod";
|
||||
|
||||
$sql_common = " from {$g5['g5_shop_item_table']} ";
|
||||
@@ -98,7 +101,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
|
||||
$len = strlen($row1['ca_id']) / 2 - 1;
|
||||
$nbsp = "";
|
||||
for ($i=0; $i<$len; $i++) $nbsp .= " ";
|
||||
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sca, $row1['ca_id']).'>'.$nbsp.$row1['ca_name'].PHP_EOL;
|
||||
// 전체 카테고리 경로 표시
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
|
||||
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sca, $row1['ca_id']).'>'.$nbsp.$category_path.PHP_EOL;
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
@@ -33,6 +33,9 @@ if (!$sst) {
|
||||
$sst = "is_id";
|
||||
$sod = "desc";
|
||||
}
|
||||
$allowed_sst = array('is_id', 'a.it_id', 'it_name', 'is_name', 'is_score', 'is_time');
|
||||
if ($sst && !in_array($sst, $allowed_sst)) $sst = 'is_id';
|
||||
if ($sod && !in_array(strtolower($sod), array('asc', 'desc'))) $sod = '';
|
||||
|
||||
$sql_common = " from {$g5['g5_shop_item_use_table']} a
|
||||
left join {$g5['g5_shop_item_table']} b on (a.it_id = b.it_id)
|
||||
@@ -81,7 +84,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
|
||||
$nbsp = "";
|
||||
for ($i=0; $i<$len; $i++) $nbsp .= " ";
|
||||
$selected = ($row1['ca_id'] == $sca) ? ' selected="selected"' : '';
|
||||
echo '<option value="'.$row1['ca_id'].'"'.$selected.'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
|
||||
// 전체 카테고리 경로 표시
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
|
||||
echo '<option value="'.$row1['ca_id'].'"'.$selected.'>'.$nbsp.$category_path.PHP_EOL;
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
@@ -84,7 +84,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
|
||||
$len = strlen($row1['ca_id']) / 2 - 1;
|
||||
$nbsp = "";
|
||||
for ($i=0; $i<$len; $i++) $nbsp .= " ";
|
||||
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
|
||||
// 전체 카테고리 경로 표시
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
|
||||
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$category_path.'</option>'.PHP_EOL;
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
@@ -509,39 +509,33 @@ add_javascript(G5_POSTCODE_JS, 0); //다음 주소 js
|
||||
<?php
|
||||
if ($od['od_settle_case'] != '무통장') {
|
||||
switch($od['od_pg']) {
|
||||
case 'lg':
|
||||
$pg_url = 'https://app.tosspayments.com';
|
||||
$pg_test = '토스페이먼츠(구버전)';
|
||||
if ($default['de_card_test']) {
|
||||
$pg_url = 'https://pgweb.tosspayments.com/tmert';
|
||||
$pg_test .= ' 테스트 ';
|
||||
}
|
||||
break;
|
||||
case 'inicis':
|
||||
$pg_url = 'https://iniweb.inicis.com/';
|
||||
$pg_test = 'KG이니시스';
|
||||
$pg_test = 'KG이니시스 ';
|
||||
break;
|
||||
case 'KAKAOPAY':
|
||||
$pg_url = 'https://mms.cnspay.co.kr';
|
||||
$pg_test = 'KAKAOPAY';
|
||||
$pg_test = 'KAKAOPAY ';
|
||||
break;
|
||||
case 'nicepay':
|
||||
$pg_url = 'https://npg.nicepay.co.kr/';
|
||||
$pg_test = 'NICEPAY';
|
||||
$pg_test = 'NICEPAY ';
|
||||
break;
|
||||
case 'lg':
|
||||
case 'toss':
|
||||
$pg_url = 'https://app.tosspayments.com';
|
||||
$pg_test = '토스페이먼츠 ';
|
||||
// 상점관리자 로그인 후 상단 '테스트 모드' 활성화 시 테스트 화면 노출
|
||||
break;
|
||||
default:
|
||||
$pg_url = 'http://admin8.kcp.co.kr';
|
||||
$pg_test = 'KCP';
|
||||
$pg_url = 'https://partner.kcp.co.kr';
|
||||
$pg_test = 'KCP ';
|
||||
if ($default['de_card_test']) {
|
||||
// 로그인 아이디 / 비번
|
||||
// 일반 : test1234 / test12345
|
||||
// 에스크로 : escrow / escrow913
|
||||
$pg_url = 'http://testadmin8.kcp.co.kr';
|
||||
$pg_test .= ' 테스트 ';
|
||||
$pg_url = 'https://testpartner.kcp.co.kr';
|
||||
$pg_test .= '테스트 ';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1170,4 +1164,4 @@ function chk_receipt_price()
|
||||
</script>
|
||||
|
||||
<?php
|
||||
include_once(G5_ADMIN_PATH.'/admin.tail.php');
|
||||
include_once(G5_ADMIN_PATH.'/admin.tail.php');
|
||||
|
||||
@@ -26,8 +26,8 @@ $od_cancel_price = isset($_GET['od_cancel_price']) ? preg_replace('/[^0-9a-z]/i'
|
||||
$od_refund_price = isset($_GET['od_refund_price']) ? preg_replace('/[^0-9a-z]/i', '', $_GET['od_refund_price']) : '';
|
||||
$od_receipt_point = isset($_GET['od_receipt_point']) ? preg_replace('/[^0-9a-z]/i', '', $_GET['od_receipt_point']) : '';
|
||||
$od_coupon = isset($_GET['od_coupon']) ? preg_replace('/[^0-9a-z]/i', '', $_GET['od_coupon']) : '';
|
||||
$od_settle_case = isset($_GET['od_settle_case']) ? clean_xss_tags($_GET['od_settle_case'], 1, 1) : '';
|
||||
$od_escrow = isset($_GET['od_escrow']) ? clean_xss_tags($_GET['od_escrow'], 1, 1) : '';
|
||||
$od_settle_case = isset($_GET['od_settle_case']) ? addslashes(clean_xss_tags(stripslashes($_GET['od_settle_case']), 1, 1)) : '';
|
||||
$od_escrow = isset($_GET['od_escrow']) ? addslashes(clean_xss_tags(stripslashes($_GET['od_escrow']), 1, 1)) : '';
|
||||
|
||||
$tot_itemcount = $tot_orderprice = $tot_receiptprice = $tot_ordercancel = $tot_misu = $tot_couponprice = 0;
|
||||
$sql_search = "";
|
||||
@@ -350,7 +350,7 @@ if( function_exists('pg_setting_check') ){
|
||||
if($default['de_escrow_use'] && $row['od_escrow'])
|
||||
$od_paytype .= '<span class="list_escrow">에스크로</span>';
|
||||
|
||||
$uid = md5($row['od_id'].$row['od_time'].$row['od_ip']);
|
||||
$uid = function_exists('get_shop_uid') ? get_shop_uid('order', $row['od_id'], $row['od_time'], $row['od_ip']) : md5($row['od_id'].$row['od_time'].$row['od_ip']);
|
||||
|
||||
$invoice_time = is_null_time($row['od_invoice_time']) ? G5_TIME_YMDHIS : $row['od_invoice_time'];
|
||||
$delivery_company = $row['od_delivery_company'] ? $row['od_delivery_company'] : $default['de_delivery_company'];
|
||||
|
||||
@@ -71,7 +71,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
|
||||
$len = strlen($row1['ca_id']) / 2 - 1;
|
||||
$nbsp = "";
|
||||
for ($i=0; $i<$len; $i++) $nbsp .= " ";
|
||||
echo "<option value='{$row1['ca_id']}'".get_selected($row1['ca_id'], $sel_ca_id).">$nbsp{$row1['ca_name']}\n";
|
||||
// 전체 카테고리 경로 표시
|
||||
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
|
||||
echo "<option value='{$row1['ca_id']}'".get_selected($row1['ca_id'], $sel_ca_id).">$nbsp{$category_path}\n";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
@@ -4,7 +4,7 @@ include_once ('../../common.php');
|
||||
include_once(G5_ADMIN_PATH.'/admin.lib.php');
|
||||
include_once(G5_SMS5_PATH.'/sms5.lib.php');
|
||||
|
||||
if (!strstr($_SERVER['SCRIPT_NAME'], 'install.php')) {
|
||||
if (strpos($_SERVER['SCRIPT_NAME'], 'install.php') === false) {
|
||||
// SMS5 테이블 G5_TABLE_PREFIX 적용
|
||||
if($g5['sms5_prefix'] != 'sms5_' && sql_num_rows(sql_query("show tables like 'sms5_config'")))
|
||||
{
|
||||
|
||||
@@ -10,14 +10,14 @@ check_admin_token();
|
||||
|
||||
$g5['title'] = "SMS 기본설정";
|
||||
|
||||
$cf_phone = isset($_REQUEST['cf_phone']) ? clean_xss_tags($_REQUEST['cf_phone'], 1, 1) : '';
|
||||
$cf_sms_use = isset($_REQUEST['cf_sms_use']) ? clean_xss_tags($_REQUEST['cf_sms_use'], 1, 1) : '';
|
||||
$cf_sms_type = isset($_REQUEST['cf_sms_type']) ? clean_xss_tags($_REQUEST['cf_sms_type'], 1, 1) : '';
|
||||
$cf_icode_id = isset($_REQUEST['cf_icode_id']) ? clean_xss_tags($_REQUEST['cf_icode_id'], 1, 1) : '';
|
||||
$cf_icode_pw = isset($_REQUEST['cf_icode_pw']) ? clean_xss_tags($_REQUEST['cf_icode_pw'], 1, 1) : '';
|
||||
$cf_icode_server_ip = isset($_REQUEST['cf_icode_server_ip']) ? clean_xss_tags($_REQUEST['cf_icode_server_ip'], 1, 1) : '';
|
||||
$cf_phone = isset($_REQUEST['cf_phone']) ? addslashes(clean_xss_tags(stripslashes($_REQUEST['cf_phone']), 1, 1)) : '';
|
||||
$cf_sms_use = isset($_REQUEST['cf_sms_use']) ? addslashes(clean_xss_tags(stripslashes($_REQUEST['cf_sms_use']), 1, 1)) : '';
|
||||
$cf_sms_type = isset($_REQUEST['cf_sms_type']) ? addslashes(clean_xss_tags(stripslashes($_REQUEST['cf_sms_type']), 1, 1)) : '';
|
||||
$cf_icode_id = isset($_REQUEST['cf_icode_id']) ? addslashes(clean_xss_tags(stripslashes($_REQUEST['cf_icode_id']), 1, 1)) : '';
|
||||
$cf_icode_pw = isset($_REQUEST['cf_icode_pw']) ? addslashes(clean_xss_tags(stripslashes($_REQUEST['cf_icode_pw']), 1, 1)) : '';
|
||||
$cf_icode_server_ip = isset($_REQUEST['cf_icode_server_ip']) ? addslashes(clean_xss_tags(stripslashes($_REQUEST['cf_icode_server_ip']), 1, 1)) : '';
|
||||
$cf_icode_server_port = isset($_REQUEST['cf_icode_server_port']) ? clean_xss_tags($_REQUEST['cf_icode_server_port'], 1, 1) : '';
|
||||
$cf_icode_token_key = isset($_REQUEST['cf_icode_token_key']) ? clean_xss_tags($_REQUEST['cf_icode_token_key'], 1, 1) : '';
|
||||
$cf_icode_token_key = isset($_REQUEST['cf_icode_token_key']) ? addslashes(clean_xss_tags(stripslashes($_REQUEST['cf_icode_token_key']), 1, 1)) : '';
|
||||
|
||||
// 회신번호 체크
|
||||
if(!check_vaild_callback($cf_phone))
|
||||
|
||||
@@ -114,7 +114,7 @@ function multi_update(sel)
|
||||
<div class="local_sch01 local_sch sms_preset_sch">
|
||||
<form>
|
||||
<label for="fg_no" class="sound_only">그룹명</label>
|
||||
<select name="fg_no" id="fg_no" onchange="location.href='<?php echo $_SERVER['SCRIPT_NAME']?>?fg_no='+this.value;">
|
||||
<select name="fg_no" id="fg_no" onchange="location.href='<?php echo htmlspecialchars($_SERVER['SCRIPT_NAME'])?>?fg_no='+this.value;">
|
||||
<option value="" <?php echo $fg_no?'':'selected'?>> 전체 </option>
|
||||
<option value="0" <?php echo $fg_no=='0'?'selected':''?>> 미분류 (<?php echo number_format($no_count)?>) </option>
|
||||
<?php for($i=0; $i<count($group); $i++) {?>
|
||||
|
||||
@@ -130,7 +130,7 @@ function no_hp_click(val)
|
||||
|
||||
<form name="search_form" class="local_sch01 local_sch">
|
||||
<label for="bg_no" class="sound_only">그룹명</label>
|
||||
<select name="bg_no" id="bg_no" onchange="location.href='<?php echo $_SERVER['SCRIPT_NAME']?>?bg_no='+this.value;">
|
||||
<select name="bg_no" id="bg_no" onchange="location.href='<?php echo htmlspecialchars($_SERVER['SCRIPT_NAME'])?>?bg_no='+this.value;">
|
||||
<option value=""<?php echo get_selected('', $bg_no); ?>> 전체 </option>
|
||||
<option value="<?php echo $no_group['bg_no']?>"<?php echo get_selected($no_group['bg_no'], $bg_no); ?>> <?php echo $no_group['bg_name']?> (<?php echo number_format($no_group['bg_count'])?> 명) </option>
|
||||
<?php for($i=0; $i<count($group); $i++) {?>
|
||||
|
||||
@@ -125,7 +125,7 @@ while ($row = array_shift($send_list))
|
||||
continue 2;
|
||||
}
|
||||
|
||||
array_push($list, array('bk_hp' => $hp, 'bk_name' => $name));
|
||||
array_push($list, array('bk_hp' => $hp, 'bk_name' => $name, 'mb_id' => '', 'bg_no' => '', 'bk_no' => ''));
|
||||
array_push($hps, $hp);
|
||||
break;
|
||||
|
||||
|
||||
+2
-1
@@ -7,7 +7,8 @@ $content = isset($_POST['content']) ? strip_tags($_POST['content']) : '';
|
||||
//$filter = explode(",", strtolower(trim($config['cf_filter'])));
|
||||
// strtolower 에 의한 한글 변형으로 아래 코드로 대체 (곱슬최씨님이 알려 주셨습니다.)
|
||||
$filter = explode(",", trim($config['cf_filter']));
|
||||
for ($i=0; $i<count($filter); $i++) {
|
||||
$filter_cnt = count($filter);
|
||||
for ($i=0; $i<$filter_cnt; $i++) {
|
||||
$str = $filter[$i];
|
||||
|
||||
// 제목 필터링 (찾으면 중지)
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
include_once('./_common.php');
|
||||
include_once(G5_LIB_PATH.'/register.lib.php');
|
||||
|
||||
// 회원 ID 열거 공격 방지를 위한 Rate Limit (분당 30회)
|
||||
if (function_exists('check_rate_limit') && !check_rate_limit('ajax_mb_id_check', 30, 60)) {
|
||||
die('너무 많은 요청이 발생했습니다. 잠시 후 다시 시도해 주세요.');
|
||||
}
|
||||
|
||||
$mb_id = isset($_POST['reg_mb_id']) ? trim($_POST['reg_mb_id']) : '';
|
||||
|
||||
set_session('ss_check_mb_id', '');
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
include_once('./_common.php');
|
||||
include_once(G5_LIB_PATH.'/register.lib.php');
|
||||
|
||||
// 회원 닉네임 열거 공격 방지를 위한 Rate Limit (분당 30회)
|
||||
if (function_exists('check_rate_limit') && !check_rate_limit('ajax_mb_nick_check', 30, 60)) {
|
||||
die('너무 많은 요청이 발생했습니다. 잠시 후 다시 시도해 주세요.');
|
||||
}
|
||||
|
||||
$mb_nick = isset($_POST['reg_mb_nick']) ? trim($_POST['reg_mb_nick']) : '';
|
||||
$mb_id = isset($_POST['reg_mb_id']) ? trim($_POST['reg_mb_id']) : '';
|
||||
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
include_once("./_common.php");
|
||||
include_once(G5_LIB_PATH."/register.lib.php");
|
||||
|
||||
// 추천인 ID 열거 공격 방지를 위한 Rate Limit (분당 30회)
|
||||
if (function_exists('check_rate_limit') && !check_rate_limit('ajax_mb_recommend_check', 30, 60)) {
|
||||
die('너무 많은 요청이 발생했습니다. 잠시 후 다시 시도해 주세요.');
|
||||
}
|
||||
|
||||
$mb_recommend = isset($_POST["reg_mb_recommend"]) ? trim($_POST["reg_mb_recommend"]) : '';
|
||||
|
||||
if ($msg = valid_mb_id($mb_recommend)) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
include_once('./_common.php');
|
||||
|
||||
if (function_exists('check_request_origin')) check_request_origin(G5_BBS_URL);
|
||||
|
||||
$count = (isset($_POST['chk_wr_id']) && is_array($_POST['chk_wr_id'])) ? count($_POST['chk_wr_id']) : 0;
|
||||
$post_btn_submit = isset($_POST['btn_submit']) ? clean_xss_tags($_POST['btn_submit'], 1, 1) : '';
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
include_once('./_common.php');
|
||||
|
||||
$mb_id = isset($_REQUEST['mb_id']) ? clean_xss_tags($_REQUEST['mb_id'], 1, 1) : '';
|
||||
$mb_id = isset($_REQUEST['mb_id']) ? addslashes(clean_xss_tags(stripslashes($_REQUEST['mb_id']), 1, 1)) : '';
|
||||
|
||||
$sql = " select mb_id, mb_email, mb_datetime from {$g5['member_table']} where mb_id = '{$mb_id}' ";
|
||||
$row = sql_fetch($sql);
|
||||
|
||||
+24
-1
@@ -9,6 +9,13 @@ if (!$config['cf_email_use'])
|
||||
if (!$is_member && $config['cf_formmail_is_member'])
|
||||
alert_close('회원만 이용하실 수 있습니다.');
|
||||
|
||||
// 발송 횟수 제한 (직접 POST 우회 방지)
|
||||
$sendmail_count = (int)get_session('ss_sendmail_count') + 1;
|
||||
set_session('ss_sendmail_count', $sendmail_count);
|
||||
if ($sendmail_count > 3) {
|
||||
alert_close('폼메일 발송 횟수를 초과하였습니다.');
|
||||
}
|
||||
|
||||
$email_enc = new str_encrypt();
|
||||
$to = $email_enc->decrypt($to);
|
||||
|
||||
@@ -40,7 +47,23 @@ if ($type) {
|
||||
else
|
||||
$mail_content = $content;
|
||||
|
||||
mailer($fnick, $fmail, $to, $subject, $mail_content, $type, $file);
|
||||
// 발신자 정보 서버측 강제 설정
|
||||
$reply_to_email = '';
|
||||
if ($is_member) {
|
||||
$fnick = (isset($member['mb_nick']) && $member['mb_nick']) ? $member['mb_nick'] : $member['mb_name'];
|
||||
$fmail = $member['mb_email'];
|
||||
} else {
|
||||
// 비회원: From을 관리자 이메일로 고정 (발신자 위장 방지)
|
||||
// 비회원이 입력한 이메일은 Reply-To로 설정하여 회신 기능 유지
|
||||
$user_email = get_email_address(trim($fmail));
|
||||
$fnick = strip_tags(trim($fnick));
|
||||
$fmail = $config['cf_admin_email'];
|
||||
if ($user_email) {
|
||||
$reply_to_email = $user_email;
|
||||
}
|
||||
}
|
||||
|
||||
mailer($fnick, $fmail, $to, $subject, $mail_content, $type, $file, '', '', $reply_to_email);
|
||||
|
||||
// 임시 첨부파일 삭제
|
||||
if(!empty($file)) {
|
||||
|
||||
+19
-8
@@ -76,16 +76,22 @@ if(isset($_POST['js']) && $_POST['js'] === "on") {
|
||||
}
|
||||
else
|
||||
{
|
||||
// 추천(찬성), 비추천(반대) 카운트 증가
|
||||
// 레이스 컨디션 방지: g5_board_good 테이블의 UNIQUE KEY(bo_table, wr_id, mb_id)를
|
||||
// 이용해 INSERT IGNORE를 먼저 수행하고, 성공한 경우에만 카운터를 증가시킨다.
|
||||
sql_query(" insert ignore into {$g5['board_good_table']} set bo_table = '{$bo_table}', wr_id = '{$wr_id}', mb_id = '{$member['mb_id']}', bg_flag = '{$good}', bg_datetime = '".G5_TIME_YMDHIS."' ");
|
||||
if (get_sql_affected_rows() <= 0) {
|
||||
$error = '이미 추천 또는 비추천 하신 글 입니다.';
|
||||
print_result($error, $count);
|
||||
}
|
||||
|
||||
// INSERT 성공 시에만 카운터 증가
|
||||
sql_query(" update {$g5['write_prefix']}{$bo_table} set wr_{$good} = wr_{$good} + 1 where wr_id = '{$wr_id}' ");
|
||||
// 내역 생성
|
||||
sql_query(" insert {$g5['board_good_table']} set bo_table = '{$bo_table}', wr_id = '{$wr_id}', mb_id = '{$member['mb_id']}', bg_flag = '{$good}', bg_datetime = '".G5_TIME_YMDHIS."' ");
|
||||
|
||||
$sql = " select wr_{$good} as count from {$g5['write_prefix']}{$bo_table} where wr_id = '$wr_id' ";
|
||||
$row = sql_fetch($sql);
|
||||
|
||||
$count = $row['count'];
|
||||
|
||||
|
||||
run_event('bbs_increase_good_json', $bo_table, $wr_id, $good);
|
||||
|
||||
print_result($error, $count);
|
||||
@@ -140,10 +146,15 @@ if(isset($_POST['js']) && $_POST['js'] === "on") {
|
||||
}
|
||||
else
|
||||
{
|
||||
// 추천(찬성), 비추천(반대) 카운트 증가
|
||||
// 레이스 컨디션 방지: g5_board_good 테이블의 UNIQUE KEY(bo_table, wr_id, mb_id)를
|
||||
// 이용해 INSERT IGNORE를 먼저 수행하고, 성공한 경우에만 카운터를 증가시킨다.
|
||||
sql_query(" insert ignore into {$g5['board_good_table']} set bo_table = '{$bo_table}', wr_id = '{$wr_id}', mb_id = '{$member['mb_id']}', bg_flag = '{$good}', bg_datetime = '".G5_TIME_YMDHIS."' ");
|
||||
if (get_sql_affected_rows() <= 0) {
|
||||
alert('이미 추천 또는 비추천 하신 글 입니다.');
|
||||
}
|
||||
|
||||
// INSERT 성공 시에만 카운터 증가
|
||||
sql_query(" update {$g5['write_prefix']}{$bo_table} set wr_{$good} = wr_{$good} + 1 where wr_id = '{$wr_id}' ");
|
||||
// 내역 생성
|
||||
sql_query(" insert {$g5['board_good_table']} set bo_table = '{$bo_table}', wr_id = '{$wr_id}', mb_id = '{$member['mb_id']}', bg_flag = '{$good}', bg_datetime = '".G5_TIME_YMDHIS."' ");
|
||||
|
||||
if ($good == 'good')
|
||||
$status = '추천';
|
||||
@@ -151,7 +162,7 @@ if(isset($_POST['js']) && $_POST['js'] === "on") {
|
||||
$status = '비추천';
|
||||
|
||||
$href = get_pretty_url($bo_table, $wr_id);
|
||||
|
||||
|
||||
run_event('bbs_increase_good_html', $bo_table, $wr_id, $good, $href);
|
||||
|
||||
alert("이 글을 $status 하셨습니다.", '', false);
|
||||
|
||||
+87
-43
@@ -14,7 +14,8 @@ if ($board['bo_use_category']) {
|
||||
$category_option .= '>전체</a></li>';
|
||||
|
||||
$categories = explode('|', $board['bo_category_list']); // 구분자가 , 로 되어 있음
|
||||
for ($i=0; $i<count($categories); $i++) {
|
||||
$categories_cnt = count($categories);
|
||||
for ($i=0; $i<$categories_cnt; $i++) {
|
||||
$category = trim($categories[$i]);
|
||||
if ($category=='') continue;
|
||||
$category_option .= '<li><a href="'.(get_pretty_url($bo_table,'','sca='.urlencode($category))).'"';
|
||||
@@ -89,15 +90,31 @@ if (!$is_search_bbs) {
|
||||
$from_notice_idx = ($page - 1) * $page_rows;
|
||||
if($from_notice_idx < 0)
|
||||
$from_notice_idx = 0;
|
||||
$board_notice_count = count($arr_notice);
|
||||
|
||||
for ($k=0; $k<$board_notice_count; $k++) {
|
||||
if (trim($arr_notice[$k]) == '') continue;
|
||||
// 유효한 공지 wr_id만 수집 (정수화로 SQL injection 방지)
|
||||
$notice_ids_int = array();
|
||||
foreach ($arr_notice as $k_idx => $nid_raw) {
|
||||
$nid_int = (int) trim($nid_raw);
|
||||
if ($nid_int > 0) {
|
||||
$notice_ids_int[$k_idx] = $nid_int;
|
||||
}
|
||||
}
|
||||
|
||||
$row = sql_fetch(" select * from {$write_table} where wr_id = '{$arr_notice[$k]}' ");
|
||||
// N+1 쿼리 제거: 공지 전체를 단일 IN 쿼리로 일괄 조회
|
||||
$notice_rows_by_id = array();
|
||||
if (!empty($notice_ids_int)) {
|
||||
$sql = " select * from {$write_table} where wr_id in (" . implode(',', $notice_ids_int) . ") ";
|
||||
$result = sql_query($sql);
|
||||
while ($nrow = sql_fetch_array($result)) {
|
||||
$notice_rows_by_id[$nrow['wr_id']] = $nrow;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($row['wr_id']) || !$row['wr_id']) continue;
|
||||
// 원래 bo_notice 순서대로 처리 (페이징 로직의 $k 인덱스 의미 보존)
|
||||
foreach ($notice_ids_int as $k => $nid) {
|
||||
if (!isset($notice_rows_by_id[$nid])) continue;
|
||||
|
||||
$row = $notice_rows_by_id[$nid];
|
||||
$notice_array[] = $row['wr_id'];
|
||||
|
||||
if($k < $from_notice_idx) continue;
|
||||
@@ -106,7 +123,7 @@ if (!$is_search_bbs) {
|
||||
$list[$i]['is_notice'] = true;
|
||||
$list[$i]['list_content'] = $list[$i]['wr_content'];
|
||||
|
||||
// 비밀글인 경우 리스트에서 내용이 출력되지 않게 글 내용을 지웁니다.
|
||||
// 비밀글인 경우 리스트에서 내용이 출력되지 않게 글 내용을 지웁니다.
|
||||
if (strstr($list[$i]['wr_option'], "secret")) {
|
||||
$list[$i]['wr_content'] = '';
|
||||
}
|
||||
@@ -178,45 +195,72 @@ if ($sst) {
|
||||
$sql_order = " order by {$sst} {$sod} ";
|
||||
}
|
||||
|
||||
if ($is_search_bbs) {
|
||||
$sql = " select distinct wr_parent from {$write_table} where {$sql_search} {$sql_order} limit {$from_record}, $page_rows ";
|
||||
} else {
|
||||
$sql = " select * from {$write_table} where wr_is_comment = 0 ";
|
||||
if(!empty($notice_array))
|
||||
$sql .= " and wr_id not in (".implode(', ', $notice_array).") ";
|
||||
$sql .= " {$sql_order} limit {$from_record}, $page_rows ";
|
||||
// 페이지의 공지개수가 목록수 보다 작을 때만 실행
|
||||
$rows_to_process = array();
|
||||
if ($page_rows > 0) {
|
||||
if ($is_search_bbs) {
|
||||
// 1차: 검색 결과의 wr_parent ID 목록 조회
|
||||
$sql = " select distinct wr_parent from {$write_table} where {$sql_search} {$sql_order} limit {$from_record}, $page_rows ";
|
||||
$result = sql_query($sql);
|
||||
|
||||
$parent_ids_in_order = array();
|
||||
while ($id_row = sql_fetch_array($result)) {
|
||||
$pid = (int) $id_row['wr_parent'];
|
||||
if ($pid > 0) {
|
||||
$parent_ids_in_order[] = $pid;
|
||||
}
|
||||
}
|
||||
|
||||
// 2차: N+1 쿼리 제거 - 단일 IN 쿼리로 전체 행 일괄 조회
|
||||
if (!empty($parent_ids_in_order)) {
|
||||
$batch_sql = " select * from {$write_table} where wr_id in (" . implode(',', $parent_ids_in_order) . ") ";
|
||||
$batch_result = sql_query($batch_sql);
|
||||
|
||||
$rows_by_id = array();
|
||||
while ($br = sql_fetch_array($batch_result)) {
|
||||
$rows_by_id[$br['wr_id']] = $br;
|
||||
}
|
||||
|
||||
// DISTINCT 쿼리의 원래 정렬 순서대로 재구성
|
||||
foreach ($parent_ids_in_order as $pid) {
|
||||
if (isset($rows_by_id[$pid])) {
|
||||
$rows_to_process[] = $rows_by_id[$pid];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$sql = " select * from {$write_table} where wr_is_comment = 0 ";
|
||||
if(!empty($notice_array))
|
||||
$sql .= " and wr_id not in (".implode(', ', $notice_array).") ";
|
||||
$sql .= " {$sql_order} limit {$from_record}, $page_rows ";
|
||||
|
||||
$result = sql_query($sql);
|
||||
while ($row = sql_fetch_array($result)) {
|
||||
$rows_to_process[] = $row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 페이지의 공지개수가 목록수 보다 작을 때만 실행
|
||||
if($page_rows > 0) {
|
||||
$result = sql_query($sql);
|
||||
|
||||
$k = 0;
|
||||
|
||||
while ($row = sql_fetch_array($result))
|
||||
{
|
||||
// 검색일 경우 wr_id만 얻었으므로 다시 한행을 얻는다
|
||||
if ($is_search_bbs)
|
||||
$row = sql_fetch(" select * from {$write_table} where wr_id = '{$row['wr_parent']}' ");
|
||||
|
||||
$list[$i] = get_list($row, $board, $board_skin_url, G5_IS_MOBILE ? $board['bo_mobile_subject_len'] : $board['bo_subject_len']);
|
||||
if (strstr($sfl, 'subject')) {
|
||||
$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;
|
||||
|
||||
$i++;
|
||||
$k++;
|
||||
$k = 0;
|
||||
foreach ($rows_to_process as $row)
|
||||
{
|
||||
$list[$i] = get_list($row, $board, $board_skin_url, G5_IS_MOBILE ? $board['bo_mobile_subject_len'] : $board['bo_subject_len']);
|
||||
if (strstr($sfl, 'subject')) {
|
||||
$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;
|
||||
|
||||
$i++;
|
||||
$k++;
|
||||
}
|
||||
|
||||
g5_latest_cache_data($board['bo_table'], $list);
|
||||
|
||||
+27
-4
@@ -54,7 +54,7 @@ if ($mb['mb_leave_date'] && $mb['mb_leave_date'] <= date("Ymd", G5_SERVER_TIME))
|
||||
|
||||
// 메일인증 설정이 되어 있다면
|
||||
if ( is_use_email_certify() && !preg_match("/[1-9]/", $mb['mb_email_certify'])) {
|
||||
$ckey = md5($mb['mb_ip'].$mb['mb_datetime']);
|
||||
$ckey = function_exists('get_email_cert_key') ? get_email_cert_key($mb_id, $mb['mb_datetime']) : md5($mb['mb_ip'].$mb['mb_datetime']);
|
||||
confirm("{$mb['mb_email']} 메일로 메일인증을 받으셔야 로그인 가능합니다. 다른 메일주소로 변경하여 인증하시려면 취소를 클릭하시기 바랍니다.", G5_URL, G5_BBS_URL.'/register_email.php?mb_id='.$mb_id.'&ckey='.$ckey);
|
||||
}
|
||||
|
||||
@@ -90,10 +90,33 @@ if($config['cf_use_point']) {
|
||||
if (isset($auto_login) && $auto_login) {
|
||||
// 3.27
|
||||
// 자동로그인 ---------------------------
|
||||
// 쿠키 한달간 저장
|
||||
$key = md5($_SERVER['SERVER_ADDR'] . $_SERVER['SERVER_SOFTWARE'] . $_SERVER['HTTP_USER_AGENT'] . $mb['mb_password']);
|
||||
// 예측 불가능한 랜덤 토큰을 생성하여 g5_member_auto_login 테이블에 저장.
|
||||
// 다중 디바이스 지원: 디바이스마다 별도의 토큰 행이 생성되며 서로 독립적으로 동작.
|
||||
|
||||
$auto_token = get_random_token_string(32); // 64자 hex - 쿠키에는 원본
|
||||
$auto_token_hash = hash('sha256', $auto_token); // 64자 hex - DB에는 해시
|
||||
$auto_ua = isset($_SERVER['HTTP_USER_AGENT']) ? substr($_SERVER['HTTP_USER_AGENT'], 0, 255) : '';
|
||||
$auto_ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
|
||||
$auto_now = G5_TIME_YMDHIS;
|
||||
$auto_expire = date('Y-m-d H:i:s', G5_SERVER_TIME + 86400 * 31);
|
||||
|
||||
// 만료된 토큰 정리 (해당 회원 한정)
|
||||
sql_query(" delete from {$g5['member_auto_login_table']}
|
||||
where mb_id = '{$mb['mb_id']}'
|
||||
and al_expire < '{$auto_now}' ");
|
||||
|
||||
// 새 토큰 INSERT (해시값만 저장)
|
||||
sql_query(" insert into {$g5['member_auto_login_table']}
|
||||
set mb_id = '{$mb['mb_id']}',
|
||||
al_token = '{$auto_token_hash}',
|
||||
al_user_agent = '".addslashes($auto_ua)."',
|
||||
al_ip = '".addslashes($auto_ip)."',
|
||||
al_created = '{$auto_now}',
|
||||
al_last_used = '{$auto_now}',
|
||||
al_expire = '{$auto_expire}' ");
|
||||
|
||||
set_cookie('ck_mb_id', $mb['mb_id'], 86400 * 31);
|
||||
set_cookie('ck_auto', $key, 86400 * 31);
|
||||
set_cookie('ck_auto', $auto_token, 86400 * 31); // 쿠키에는 원본 토큰
|
||||
// 자동로그인 end ---------------------------
|
||||
} else {
|
||||
set_cookie('ck_mb_id', '', 0);
|
||||
|
||||
@@ -11,6 +11,18 @@ session_unset(); // 모든 세션변수를 언레지스터 시켜줌
|
||||
session_destroy(); // 세션해제함
|
||||
|
||||
// 자동로그인 해제 --------------------------------
|
||||
// DB에 저장된 해당 디바이스의 자동 로그인 토큰만 무효화
|
||||
// (다른 디바이스의 자동 로그인은 유지)
|
||||
// DB에는 토큰의 SHA256 해시가 저장되어 있으므로 비교 시에도 해시값 사용
|
||||
$logout_token = get_cookie('ck_auto');
|
||||
$logout_mb_id = get_cookie('ck_mb_id');
|
||||
if (isset($g5['member_auto_login_table']) && $logout_token && $logout_mb_id && preg_match('/^[a-f0-9]{64}$/', $logout_token)) {
|
||||
$logout_mb_id = substr(preg_replace("/[^a-zA-Z0-9_]*/", "", $logout_mb_id), 0, 20);
|
||||
$logout_token_hash = hash('sha256', $logout_token);
|
||||
sql_query(" delete from {$g5['member_auto_login_table']}
|
||||
where mb_id = '{$logout_mb_id}'
|
||||
and al_token = '{$logout_token_hash}' ");
|
||||
}
|
||||
set_cookie('ck_mb_id', '', 0);
|
||||
set_cookie('ck_auto', '', 0);
|
||||
// 자동로그인 해제 end --------------------------------
|
||||
|
||||
@@ -3,13 +3,19 @@ define('G5_CERT_IN_PROG', true);
|
||||
include_once('./_common.php');
|
||||
global $g5;
|
||||
|
||||
// 로그인 검증 (본인인증 갱신은 로그인 필수)
|
||||
if (!$is_member) {
|
||||
alert('로그인 후 이용해 주십시오.', G5_BBS_URL.'/login.php');
|
||||
}
|
||||
|
||||
if (!($w == '' || $w == 'u')) {
|
||||
alert('w 값이 제대로 넘어오지 않았습니다.');
|
||||
}
|
||||
$url = urldecode($url);
|
||||
|
||||
if($w == '') {
|
||||
$mb_id = isset($_POST['mb_id']) ? trim($_POST['mb_id']) : '';
|
||||
// 본인 계정만 수정 가능 (POST mb_id 무시, 세션 회원 ID 사용)
|
||||
$mb_id = $member['mb_id'];
|
||||
$mb_name = isset($_POST['mb_name']) ? trim($_POST['mb_name']) : '';
|
||||
$mb_hp = isset($_POST['mb_hp']) ? trim($_POST['mb_hp']) : '';
|
||||
} else
|
||||
|
||||
+2
-2
@@ -13,8 +13,8 @@ if (!$member['mb_open'] && $is_admin != 'super' && $member['mb_id'] != $mb_id) {
|
||||
}
|
||||
|
||||
$content = "";
|
||||
$me_recv_mb_id = isset($_REQUEST['me_recv_mb_id']) ? clean_xss_tags($_REQUEST['me_recv_mb_id'], 1, 1) : '';
|
||||
$me_id = isset($_REQUEST['me_id']) ? clean_xss_tags($_REQUEST['me_id'], 1, 1) : '';
|
||||
$me_recv_mb_id = isset($_REQUEST['me_recv_mb_id']) ? addslashes(clean_xss_tags(stripslashes($_REQUEST['me_recv_mb_id']), 1, 1)) : '';
|
||||
$me_id = isset($_REQUEST['me_id']) ? addslashes(clean_xss_tags(stripslashes($_REQUEST['me_id']), 1, 1)) : '';
|
||||
|
||||
// 탈퇴한 회원에게 쪽지 보낼 수 없음
|
||||
if ($me_recv_mb_id)
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
include_once('./_common.php');
|
||||
include_once(G5_CAPTCHA_PATH.'/captcha.lib.php');
|
||||
|
||||
if (function_exists('check_request_origin')) check_request_origin(G5_BBS_URL);
|
||||
|
||||
if ($is_guest)
|
||||
alert('회원만 이용하실 수 있습니다.');
|
||||
|
||||
@@ -18,7 +20,8 @@ $me_memo = isset($_POST['me_memo']) ? preg_replace("#[\\\]+$#", "", substr(trim(
|
||||
|
||||
run_event('memo_form_update_before', $recv_list);
|
||||
|
||||
for ($i=0; $i<count($recv_list); $i++) {
|
||||
$recv_list_cnt = count($recv_list);
|
||||
for ($i=0; $i<$recv_list_cnt; $i++) {
|
||||
|
||||
$recv_list_id = substr(preg_replace("/[^a-zA-Z0-9_]*/", "", $recv_list[$i]), 0, 20);
|
||||
|
||||
@@ -63,7 +66,8 @@ if (!$is_admin) {
|
||||
}
|
||||
}
|
||||
|
||||
for ($i=0; $i<count($member_list['id']); $i++) {
|
||||
$member_list_cnt = count($member_list['id']);
|
||||
for ($i=0; $i<$member_list_cnt; $i++) {
|
||||
$tmp_row = sql_fetch(" select max(me_id) as max_me_id from {$g5['memo_table']} ");
|
||||
$me_id = $tmp_row['max_me_id'] + 1;
|
||||
|
||||
|
||||
+9
-5
@@ -61,7 +61,7 @@ while ($row = sql_fetch_array($result))
|
||||
|
||||
$nick = cut_str($member['mb_nick'], $config['cf_cut_name']);
|
||||
if (!$row2['wr_is_comment'] && $config['cf_use_copy_log']) {
|
||||
if(strstr($row2['wr_option'], 'html')) {
|
||||
if(strpos($row2['wr_option'], 'html') !== false) {
|
||||
$log_tag1 = '<div class="content_'.$sw.'">';
|
||||
$log_tag2 = '</div>';
|
||||
} else {
|
||||
@@ -233,10 +233,12 @@ delete_cache_latest($bo_table);
|
||||
|
||||
if ($sw == 'move')
|
||||
{
|
||||
for ($i=0; $i<count($save); $i++)
|
||||
$save_cnt = count($save);
|
||||
for ($i=0; $i<$save_cnt; $i++)
|
||||
{
|
||||
if( isset($save[$i]['bf_file']) && $save[$i]['bf_file'] ){
|
||||
for ($k=0; $k<count($save[$i]['bf_file']); $k++) {
|
||||
$bf_file_cnt = count($save[$i]['bf_file']);
|
||||
for ($k=0; $k<$bf_file_cnt; $k++) {
|
||||
$del_file = run_replace('delete_file_path', clean_relative_paths($save[$i]['bf_file'][$k]), $save[$i]);
|
||||
|
||||
if ( is_file($del_file) && file_exists($del_file) ){
|
||||
@@ -248,7 +250,8 @@ if ($sw == 'move')
|
||||
}
|
||||
}
|
||||
|
||||
for ($k=0; $k<count($save[$i]['wr_contents']); $k++){
|
||||
$wr_contents_cnt = count($save[$i]['wr_contents']);
|
||||
for ($k=0; $k<$wr_contents_cnt; $k++){
|
||||
delete_editor_thumbnail($save[$i]['wr_contents'][$k]);
|
||||
}
|
||||
|
||||
@@ -262,7 +265,8 @@ if ($sw == 'move')
|
||||
$sql = " select bo_notice from {$g5['board_table']} where bo_table = '{$bo_table}' ";
|
||||
$row = sql_fetch($sql);
|
||||
$arr_notice = explode(',', $row['bo_notice']);
|
||||
for ($i=0; $i<count($arr_notice); $i++) {
|
||||
$arr_notice_cnt = count($arr_notice);
|
||||
for ($i=0; $i<$arr_notice_cnt; $i++) {
|
||||
$move_id = (int)$arr_notice[$i];
|
||||
// 게시판에 wr_id 가 있다면 이동한게 아니므로 bo_notice 에 다시 넣음
|
||||
$row2 = sql_fetch(" select count(*) as cnt from $write_table where wr_id = '{$move_id}' ");
|
||||
|
||||
+2
-1
@@ -97,7 +97,8 @@ for($i=0;$i<$count_chk_bn_id;$i++)
|
||||
$notice_array = explode(",", trim($board['bo_notice']));
|
||||
$bo_notice = "";
|
||||
$lf = '';
|
||||
for ($k=0; $k<count($notice_array); $k++) {
|
||||
$notice_array_cnt = count($notice_array);
|
||||
for ($k=0; $k<$notice_array_cnt; $k++) {
|
||||
if ((int)$write['wr_id'] != (int)$notice_array[$k])
|
||||
$bo_notice .= $lf.$notice_array[$k];
|
||||
|
||||
|
||||
+18
-11
@@ -16,25 +16,32 @@ $email = get_email_address(trim($_POST['mb_email']));
|
||||
if (!$email)
|
||||
alert_close('메일주소 오류입니다.');
|
||||
|
||||
// OWASP 권장: 이메일 존재 여부와 무관하게 동일한 응답 메시지 사용
|
||||
// (이메일 열거 공격 방지)
|
||||
$generic_message = $email.' 메일로 회원아이디와 비밀번호를 인증할 수 있는 메일이 발송 되었습니다.\\n\\n메일을 확인하여 주십시오.';
|
||||
|
||||
$sql = " select count(*) as cnt from {$g5['member_table']} where mb_email = '$email' ";
|
||||
$row = sql_fetch($sql);
|
||||
if ($row['cnt'] > 1)
|
||||
alert('동일한 메일주소가 2개 이상 존재합니다.\\n\\n관리자에게 문의하여 주십시오.');
|
||||
if ($row['cnt'] > 1) {
|
||||
// 시스템 데이터 무결성 이슈 - 운영자 로그에만 기록하고 사용자에겐 일반 메시지
|
||||
@error_log("[g5 password_lost2] Duplicate email detected: $email (count={$row['cnt']})");
|
||||
alert_close($generic_message);
|
||||
}
|
||||
|
||||
$sql = " select mb_no, mb_id, mb_name, mb_nick, mb_email, mb_datetime, mb_leave_date from {$g5['member_table']} where mb_email = '$email' ";
|
||||
$mb = sql_fetch($sql);
|
||||
if (empty($mb['mb_id']) || $mb['mb_leave_date']) {
|
||||
alert('존재하지 않는 회원입니다.');
|
||||
} elseif (is_admin($mb['mb_id'])) {
|
||||
alert('관리자 아이디는 접근 불가합니다.');
|
||||
|
||||
// 회원이 없거나 탈퇴했거나 관리자이면 메일 발송 없이 동일한 메시지로 응답
|
||||
if (empty($mb['mb_id']) || $mb['mb_leave_date'] || is_admin($mb['mb_id'])) {
|
||||
alert_close($generic_message);
|
||||
}
|
||||
|
||||
// 임시비밀번호 발급
|
||||
$change_password = rand(100000, 999999);
|
||||
// 임시비밀번호 발급 (CSPRNG 사용)
|
||||
$change_password = get_random_token_string(5); // 10자리 hex (0-9, a-f)
|
||||
$mb_lost_certify = get_encrypt_string($change_password);
|
||||
|
||||
// 어떠한 회원정보도 포함되지 않은 일회용 난수를 생성하여 인증에 사용
|
||||
$mb_nonce = md5(pack('V*', rand(), rand(), rand(), rand()));
|
||||
// 어떠한 회원정보도 포함되지 않은 일회용 난수를 생성하여 인증에 사용 (CSPRNG 사용)
|
||||
$mb_nonce = get_random_token_string(16);
|
||||
|
||||
// 임시비밀번호와 난수를 mb_lost_certify 필드에 저장
|
||||
$sql = " update {$g5['member_table']} set mb_lost_certify = '$mb_nonce $mb_lost_certify' where mb_id = '{$mb['mb_id']}' ";
|
||||
@@ -74,4 +81,4 @@ mailer($config['cf_admin_email_name'], $config['cf_admin_email'], $mb['mb_email'
|
||||
|
||||
run_event('password_lost2_after', $mb, $mb_nonce, $mb_lost_certify);
|
||||
|
||||
alert_close($email.' 메일로 회원아이디와 비밀번호를 인증할 수 있는 메일이 발송 되었습니다.\\n\\n메일을 확인하여 주십시오.');
|
||||
alert_close($generic_message);
|
||||
+14
-2
@@ -2,16 +2,28 @@
|
||||
include_once('./_common.php');
|
||||
include_once(G5_LIB_PATH.'/mailer.lib.php');
|
||||
|
||||
if (function_exists('check_request_origin')) check_request_origin(G5_BBS_URL);
|
||||
|
||||
if ($w == '')
|
||||
{
|
||||
$po_id = isset($_POST['po_id']) ? (int) $_POST['po_id'] : '';
|
||||
$pc_name = isset($_POST['pc_name']) ? clean_xss_tags($_POST['pc_name'], 1, 1) : '';
|
||||
$pc_idea = isset($_POST['pc_idea']) ? clean_xss_tags($_POST['pc_idea'], 1, 1) : '';
|
||||
|
||||
$po = sql_fetch(" select * from {$g5['poll_table']} where po_id = '{$po_id}' ");
|
||||
if (!$po['po_id'])
|
||||
alert('po_id 값이 제대로 넘어오지 않았습니다.');
|
||||
|
||||
// 기타의견 사용 여부 검사
|
||||
if (!$po['po_etc'])
|
||||
alert('기타의견이 비활성화되어 있습니다.');
|
||||
|
||||
// 접근 권한 검사
|
||||
if ($member['mb_level'] < $po['po_level'])
|
||||
alert('권한이 없습니다.');
|
||||
|
||||
$pc_name = isset($_POST['pc_name']) ? addslashes(clean_xss_tags(stripslashes($_POST['pc_name']), 1, 1)) : '';
|
||||
$pc_name = preg_replace("#[\\\]+$#", "", $pc_name);
|
||||
$pc_idea = isset($_POST['pc_idea']) ? addslashes(clean_xss_tags(stripslashes($_POST['pc_idea']), 1, 1)) : '';
|
||||
|
||||
$tmp_row = sql_fetch(" select max(pc_id) as max_pc_id from {$g5['poll_etc_table']} ");
|
||||
$pc_id = $tmp_row['max_pc_id'] + 1;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ include_once('./_common.php');
|
||||
include_once(G5_CAPTCHA_PATH.'/captcha.lib.php');
|
||||
|
||||
$po_id = isset($_REQUEST['po_id']) ? (int) $_REQUEST['po_id'] : '';
|
||||
$skin_dir = isset($skin_dir) ? clean_relative_paths(strip_tags($skin_dir)) : '';
|
||||
|
||||
$po = sql_fetch(" select * from {$g5['poll_table']} where po_id = '{$po_id}' ");
|
||||
if (!$po['po_id'])
|
||||
|
||||
+21
-37
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
include_once('./_common.php');
|
||||
|
||||
if (function_exists('check_request_origin')) check_request_origin(G5_BBS_URL);
|
||||
|
||||
$po_id = isset($_POST['po_id']) ? preg_replace('/[^0-9]/', '', $_POST['po_id']) : 0;
|
||||
|
||||
$po = sql_fetch(" select * from {$g5['poll_table']} where po_id = '$po_id' ");
|
||||
@@ -14,50 +16,32 @@ $gb_poll = isset($_POST['gb_poll']) ? preg_replace('/[^0-9]/', '', $_POST['gb_po
|
||||
if(!$gb_poll)
|
||||
alert_close('항목을 선택하세요.');
|
||||
|
||||
$search_mb_id = false;
|
||||
$search_ip = false;
|
||||
|
||||
if($is_member) {
|
||||
// 투표했던 회원아이디들 중에서 찾아본다
|
||||
$ids = explode(',', trim($po['mb_ids']));
|
||||
for ($i=0; $i<count($ids); $i++) {
|
||||
if ($member['mb_id'] == trim($ids[$i])) {
|
||||
$search_mb_id = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 투표했던 ip들 중에서 찾아본다
|
||||
$ips = explode(',', trim($po['po_ips']));
|
||||
for ($i=0; $i<count($ips); $i++) {
|
||||
if ($_SERVER['REMOTE_ADDR'] == trim($ips[$i])) {
|
||||
$search_ip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$post_skin_dir = isset($_POST['skin_dir']) ? clean_xss_tags($_POST['skin_dir'], 1, 1) : '';
|
||||
$result_url = G5_BBS_URL."/poll_result.php?po_id=$po_id&skin_dir={$post_skin_dir}";
|
||||
|
||||
// 없다면 선택한 투표항목을 1증가 시키고 ip, id를 저장
|
||||
if (!($search_ip || $search_mb_id)) {
|
||||
$po_ips = $po['po_ips'] . $_SERVER['REMOTE_ADDR'].",";
|
||||
$mb_ids = $po['mb_ids'];
|
||||
if ($is_member) { // 회원일 때는 id만 추가
|
||||
$mb_ids .= $member['mb_id'].',';
|
||||
$sql = " update {$g5['poll_table']} set po_cnt{$gb_poll} = po_cnt{$gb_poll} + 1, mb_ids = '$mb_ids' where po_id = '$po_id' ";
|
||||
} else {
|
||||
$sql = " update {$g5['poll_table']} set po_cnt{$gb_poll} = po_cnt{$gb_poll} + 1, po_ips = '$po_ips' where po_id = '$po_id' ";
|
||||
}
|
||||
|
||||
sql_query($sql);
|
||||
// 레이스 컨디션 방지: MyISAM은 트랜잭션을 지원하지 않으므로,
|
||||
// WHERE 조건에 중복 검증(FIND_IN_SET)을 포함한 원자적 UPDATE로 처리한다.
|
||||
// 기존 투표자 목록에 없을 때만 갱신되며, 동시 요청이 와도 DB 서버 레벨에서 직렬화된다.
|
||||
if ($is_member) {
|
||||
$sql = " update {$g5['poll_table']}
|
||||
set po_cnt{$gb_poll} = po_cnt{$gb_poll} + 1,
|
||||
mb_ids = concat(ifnull(mb_ids, ''), '".$member['mb_id'].",')
|
||||
where po_id = '$po_id'
|
||||
and find_in_set('".$member['mb_id']."', ifnull(mb_ids, '')) = 0 ";
|
||||
} else {
|
||||
$sql = " update {$g5['poll_table']}
|
||||
set po_cnt{$gb_poll} = po_cnt{$gb_poll} + 1,
|
||||
po_ips = concat(ifnull(po_ips, ''), '".$_SERVER['REMOTE_ADDR'].",')
|
||||
where po_id = '$po_id'
|
||||
and find_in_set('".$_SERVER['REMOTE_ADDR']."', ifnull(po_ips, '')) = 0 ";
|
||||
}
|
||||
sql_query($sql);
|
||||
|
||||
if (get_sql_affected_rows() <= 0) {
|
||||
alert(addcslashes($po['po_subject'], '"\\/').'에 이미 참여하셨습니다.', $result_url);
|
||||
}
|
||||
|
||||
if (!$search_mb_id)
|
||||
insert_point($member['mb_id'], $po['po_point'], $po['po_id'] . '. ' . cut_str($po['po_subject'],20) . ' 투표 참여 ', '@poll', $po['po_id'], '투표');
|
||||
insert_point($member['mb_id'], $po['po_point'], $po['po_id'] . '. ' . cut_str($po['po_subject'],20) . ' 투표 참여 ', '@poll', $po['po_id'], '투표');
|
||||
|
||||
//goto_url($g5['bbs_url'].'/poll_result.php?po_id='.$po_id.'&skin_dir='.$skin_dir);
|
||||
goto_url($result_url);
|
||||
+2
-1
@@ -29,7 +29,8 @@ if ($qaconfig['qa_category']) {
|
||||
$category_option .= '>전체</a></li>';
|
||||
|
||||
$categories = explode('|', $qaconfig['qa_category']); // 구분자가 | 로 되어 있음
|
||||
for ($i=0; $i<count($categories); $i++) {
|
||||
$categories_cnt = count($categories);
|
||||
for ($i=0; $i<$categories_cnt; $i++) {
|
||||
$category = trim($categories[$i]);
|
||||
if ($category=='') continue;
|
||||
$category_msg = '';
|
||||
|
||||
+2
-1
@@ -54,7 +54,8 @@ if(is_file($skin_file)) {
|
||||
$category_option = '';
|
||||
if(trim($qaconfig['qa_category'])) {
|
||||
$category = explode('|', $qaconfig['qa_category']);
|
||||
for($i=0; $i<count($category); $i++) {
|
||||
$category_cnt = count($category);
|
||||
for($i=0; $i<$category_cnt; $i++) {
|
||||
$category_option .= option_selected($category[$i], $write['qa_category']);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -219,7 +219,7 @@ for ($i=1; $i<=$upload_count; $i++) {
|
||||
$upload[$i]['filesize'] = $filesize;
|
||||
|
||||
// 아래의 문자열이 들어간 파일은 -x 를 붙여서 웹경로를 알더라도 실행을 하지 못하도록 함
|
||||
$filename = preg_replace("/\.(php|pht|phtm|htm|cgi|pl|exe|jsp|asp|inc|phar)/i", "$0-x", $filename);
|
||||
$filename = preg_replace("/\.(php|pht|phtm|htm|shtml|shtm|cgi|pl|exe|jsp|asp|inc|phar|svg|svgz)/i", "$0-x", $filename);
|
||||
|
||||
shuffle($chars_array);
|
||||
$shuffle = implode('', $chars_array);
|
||||
|
||||
@@ -5,7 +5,7 @@ include_once(G5_CAPTCHA_PATH.'/captcha.lib.php');
|
||||
$g5['title'] = '메일인증 메일주소 변경';
|
||||
include_once('./_head.php');
|
||||
|
||||
$mb_id = isset($_GET['mb_id']) ? substr(clean_xss_tags($_GET['mb_id']), 0, 20) : '';
|
||||
$mb_id = isset($_GET['mb_id']) ? substr(addslashes(clean_xss_tags(stripslashes($_GET['mb_id']), 1, 1)), 0, 20) : '';
|
||||
$sql = " select mb_email, mb_datetime, mb_ip, mb_email_certify, mb_id from {$g5['member_table']} where mb_id = '{$mb_id}' ";
|
||||
$mb = sql_fetch($sql);
|
||||
|
||||
@@ -18,9 +18,9 @@ if (substr($mb['mb_email_certify'],0,1)!=0) {
|
||||
}
|
||||
|
||||
$ckey = isset($_GET['ckey']) ? trim($_GET['ckey']) : '';
|
||||
$key = md5($mb['mb_ip'].$mb['mb_datetime']);
|
||||
$key = get_email_cert_key($mb_id, $mb['mb_datetime']);
|
||||
|
||||
if(!$ckey || $ckey != $key)
|
||||
if(!$ckey || $ckey !== $key)
|
||||
alert('올바른 방법으로 이용해 주십시오.', G5_URL);
|
||||
?>
|
||||
|
||||
@@ -28,6 +28,7 @@ if(!$ckey || $ckey != $key)
|
||||
|
||||
<form method="post" name="fregister_email" action="<?php echo G5_HTTPS_BBS_URL.'/register_email_update.php'; ?>" onsubmit="return fregister_email_submit(this);">
|
||||
<input type="hidden" name="mb_id" value="<?php echo $mb_id; ?>">
|
||||
<input type="hidden" name="ckey" value="<?php echo $key; ?>">
|
||||
|
||||
<div class="tbl_frm01 tbl_frm rg_em">
|
||||
<table>
|
||||
|
||||
@@ -3,13 +3,28 @@ include_once('./_common.php');
|
||||
include_once(G5_CAPTCHA_PATH.'/captcha.lib.php');
|
||||
include_once(G5_LIB_PATH.'/mailer.lib.php');
|
||||
|
||||
$mb_id = isset($_POST['mb_id']) ? substr(clean_xss_tags($_POST['mb_id']), 0, 20) : '';
|
||||
// 로그인 검증
|
||||
if (!$is_member) {
|
||||
alert('로그인 후 이용해 주십시오.', G5_BBS_URL.'/login.php');
|
||||
}
|
||||
|
||||
// 본인 계정만 수정 가능 (POST mb_id 무시, 세션 회원 ID 사용)
|
||||
$mb_id = $member['mb_id'];
|
||||
$mb_email = isset($_POST['mb_email']) ? get_email_address(trim($_POST['mb_email'])) : '';
|
||||
|
||||
if(!$mb_id || !$mb_email)
|
||||
alert('올바른 방법으로 이용해 주십시오.', G5_URL);
|
||||
|
||||
$sql = " select mb_name from {$g5['member_table']} where mb_id = '{$mb_id}' and substring(mb_email_certify, 1, 1) = '0' ";
|
||||
// ckey 검증 (register_email.php 폼에서 전달받은 인증키)
|
||||
$ckey = isset($_POST['ckey']) ? trim($_POST['ckey']) : '';
|
||||
$key = get_email_cert_key($mb_id, $member['mb_datetime']);
|
||||
if (!$ckey || $ckey !== $key) {
|
||||
alert('올바른 방법으로 이용해 주십시오.', G5_URL);
|
||||
}
|
||||
|
||||
$esc_mb_id = sql_real_escape_string($mb_id);
|
||||
|
||||
$sql = " select mb_name from {$g5['member_table']} where mb_id = '{$esc_mb_id}' and substring(mb_email_certify, 1, 1) = '0' ";
|
||||
$mb = sql_fetch($sql);
|
||||
if (!$mb) {
|
||||
alert("이미 메일인증 하신 회원입니다.", G5_URL);
|
||||
@@ -19,7 +34,7 @@ if (!chk_captcha()) {
|
||||
alert('자동등록방지 숫자가 틀렸습니다.');
|
||||
}
|
||||
|
||||
$sql = " select count(*) as cnt from {$g5['member_table']} where mb_id <> '{$mb_id}' and mb_email = '$mb_email' ";
|
||||
$sql = " select count(*) as cnt from {$g5['member_table']} where mb_id <> '{$esc_mb_id}' and mb_email = '$mb_email' ";
|
||||
$row = sql_fetch($sql);
|
||||
if ($row['cnt']) {
|
||||
alert("{$mb_email} 메일은 이미 존재하는 메일주소 입니다.\\n\\n다른 메일주소를 입력해 주십시오.");
|
||||
@@ -30,10 +45,10 @@ $subject = '['.$config['cf_title'].'] 인증확인 메일입니다.';
|
||||
|
||||
$mb_name = $mb['mb_name'];
|
||||
|
||||
// 어떠한 회원정보도 포함되지 않은 일회용 난수를 생성하여 인증에 사용
|
||||
$mb_md5 = md5(pack('V*', rand(), rand(), rand(), rand()));
|
||||
// 어떠한 회원정보도 포함되지 않은 일회용 난수를 생성하여 인증에 사용 (CSPRNG 사용)
|
||||
$mb_md5 = get_random_token_string(16);
|
||||
|
||||
sql_query(" update {$g5['member_table']} set mb_email_certify2 = '$mb_md5' where mb_id = '$mb_id' ");
|
||||
sql_query(" update {$g5['member_table']} set mb_email_certify2 = '$mb_md5' where mb_id = '{$esc_mb_id}' ");
|
||||
|
||||
$certify_href = G5_BBS_URL.'/email_certify.php?mb_id='.$mb_id.'&mb_md5='.$mb_md5;
|
||||
|
||||
@@ -44,7 +59,7 @@ ob_end_clean();
|
||||
|
||||
mailer($config['cf_admin_email_name'], $config['cf_admin_email'], $mb_email, $subject, $content, 1);
|
||||
|
||||
$sql = " update {$g5['member_table']} set mb_email = '$mb_email' where mb_id = '$mb_id' ";
|
||||
$sql = " update {$g5['member_table']} set mb_email = '$mb_email' where mb_id = '{$esc_mb_id}' ";
|
||||
sql_query($sql);
|
||||
|
||||
alert("인증메일을 {$mb_email} 메일로 다시 보내 드렸습니다.\\n\\n잠시후 {$mb_email} 메일을 확인하여 주십시오.", G5_URL);
|
||||
@@ -6,7 +6,7 @@ include_once(G5_LIB_PATH.'/register.lib.php');
|
||||
run_event('register_form_before');
|
||||
|
||||
// 불법접근을 막도록 토큰생성
|
||||
$token = md5(uniqid(rand(), true));
|
||||
$token = get_random_token_string(16);
|
||||
set_session("ss_token", $token);
|
||||
set_session("ss_cert_no", "");
|
||||
set_session("ss_cert_hash", "");
|
||||
|
||||
@@ -63,20 +63,34 @@ $mb_7 = isset($_POST['mb_7']) ? trim($_POST['mb_7'])
|
||||
$mb_8 = isset($_POST['mb_8']) ? trim($_POST['mb_8']) : "";
|
||||
$mb_9 = isset($_POST['mb_9']) ? trim($_POST['mb_9']) : "";
|
||||
$mb_10 = isset($_POST['mb_10']) ? trim($_POST['mb_10']) : "";
|
||||
$mb_name = clean_xss_tags($mb_name, 1, 1);
|
||||
$mb_name = addslashes(clean_xss_tags(stripslashes($mb_name), 1, 1));
|
||||
$mb_email = get_email_address($mb_email);
|
||||
$mb_homepage = clean_xss_tags($mb_homepage, 1, 1);
|
||||
$mb_tel = clean_xss_tags($mb_tel, 1, 1);
|
||||
$mb_homepage = addslashes(clean_xss_tags(stripslashes($mb_homepage), 1, 1));
|
||||
$mb_tel = addslashes(clean_xss_tags(stripslashes($mb_tel), 1, 1));
|
||||
$mb_zip1 = preg_replace('/[^0-9]/', '', $mb_zip1);
|
||||
$mb_zip2 = preg_replace('/[^0-9]/', '', $mb_zip2);
|
||||
$mb_addr1 = clean_xss_tags($mb_addr1, 1, 1);
|
||||
$mb_addr2 = clean_xss_tags($mb_addr2, 1, 1);
|
||||
$mb_addr3 = clean_xss_tags($mb_addr3, 1, 1);
|
||||
$mb_addr1 = addslashes(clean_xss_tags(stripslashes($mb_addr1), 1, 1));
|
||||
$mb_addr2 = addslashes(clean_xss_tags(stripslashes($mb_addr2), 1, 1));
|
||||
$mb_addr3 = addslashes(clean_xss_tags(stripslashes($mb_addr3), 1, 1));
|
||||
$mb_addr_jibeon = preg_match("/^(N|R)$/", $mb_addr_jibeon) ? $mb_addr_jibeon : '';
|
||||
|
||||
$mb_marketing_agree = isset($_POST['mb_marketing_agree']) ? trim($_POST['mb_marketing_agree']) : "0";
|
||||
$mb_thirdparty_agree = isset($_POST['mb_thirdparty_agree']) ? trim($_POST['mb_thirdparty_agree']) : "0";
|
||||
|
||||
// _default 변수 명시적 초기화 (폼에 해당 섹션이 없으면 null)
|
||||
$mb_marketing_agree_default = isset($_POST['mb_marketing_agree_default']) ? trim($_POST['mb_marketing_agree_default']) : null;
|
||||
$mb_mailling_default = isset($_POST['mb_mailling_default']) ? trim($_POST['mb_mailling_default']) : null;
|
||||
$mb_sms_default = isset($_POST['mb_sms_default']) ? trim($_POST['mb_sms_default']) : null;
|
||||
$mb_thirdparty_agree_default = isset($_POST['mb_thirdparty_agree_default']) ? trim($_POST['mb_thirdparty_agree_default']) : null;
|
||||
|
||||
// 폼에 수신설정 섹션이 없는 경우 기존 DB 값 유지 (회원정보 수정 시)
|
||||
if ($w == 'u') {
|
||||
if ($mb_marketing_agree_default === null) $mb_marketing_agree = $member['mb_marketing_agree'];
|
||||
if ($mb_mailling_default === null) $mb_mailling = $member['mb_mailling'];
|
||||
if ($mb_sms_default === null) $mb_sms = $member['mb_sms'];
|
||||
if ($mb_thirdparty_agree_default === null) $mb_thirdparty_agree = $member['mb_thirdparty_agree'];
|
||||
}
|
||||
|
||||
run_event('register_form_update_before', $mb_id, $w);
|
||||
|
||||
if ($w == '' || $w == 'u') {
|
||||
@@ -305,9 +319,9 @@ if ($w == '') {
|
||||
if ($config['cf_email_mb_member']) {
|
||||
$subject = '['.$config['cf_title'].'] 회원가입을 축하드립니다.';
|
||||
|
||||
// 어떠한 회원정보도 포함되지 않은 일회용 난수를 생성하여 인증에 사용
|
||||
// 어떠한 회원정보도 포함되지 않은 일회용 난수를 생성하여 인증에 사용 (CSPRNG 사용)
|
||||
if ($config['cf_use_email_certify']) {
|
||||
$mb_md5 = md5(pack('V*', rand(), rand(), rand(), rand()));
|
||||
$mb_md5 = get_random_token_string(16);
|
||||
sql_query(" update {$g5['member_table']} set mb_email_certify2 = '$mb_md5' where mb_id = '$mb_id' ");
|
||||
$certify_href = G5_BBS_URL.'/email_certify.php?mb_id='.$mb_id.'&mb_md5='.$mb_md5;
|
||||
}
|
||||
@@ -386,28 +400,28 @@ if ($w == '') {
|
||||
|
||||
// 마케팅 목적의 개인정보 수집 및 이용
|
||||
$sql_marketing_date = "";
|
||||
if ($mb_marketing_agree_default !== $mb_marketing_agree) {
|
||||
if ($mb_marketing_agree_default !== null && $mb_marketing_agree_default !== $mb_marketing_agree) {
|
||||
$sql_marketing_date .= " , mb_marketing_date = '".G5_TIME_YMDHIS."' ";
|
||||
$agree_items[] = "마케팅 목적의 개인정보 수집 및 이용(" . ($mb_marketing_agree == 1 ? "동의" : "철회") . ")";
|
||||
}
|
||||
|
||||
// 광고성 이메일 수신
|
||||
$sql_mailling_date = "";
|
||||
if ($mb_mailling_default !== $mb_mailling) {
|
||||
if ($mb_mailling_default !== null && $mb_mailling_default !== $mb_mailling) {
|
||||
$sql_mailling_date .= " , mb_mailling_date = '".G5_TIME_YMDHIS."' ";
|
||||
$agree_items[] = "광고성 이메일 수신(" . ($mb_mailling == 1 ? "동의" : "철회") . ")";
|
||||
}
|
||||
|
||||
// 광고성 SMS/카카오톡 수신
|
||||
$sql_sms_date = "";
|
||||
if ($mb_sms_default !== $mb_sms) {
|
||||
if ($mb_sms_default !== null && $mb_sms_default !== $mb_sms) {
|
||||
$sql_sms_date .= " , mb_sms_date = '".G5_TIME_YMDHIS."' ";
|
||||
$agree_items[] = "광고성 SMS/카카오톡 수신(" . ($mb_sms == 1 ? "동의" : "철회") . ")";
|
||||
}
|
||||
|
||||
// 개인정보 제3자 제공
|
||||
$sql_thirdparty_date = "";
|
||||
if ($mb_thirdparty_agree_default !== $mb_thirdparty_agree) {
|
||||
if ($mb_thirdparty_agree_default !== null && $mb_thirdparty_agree_default !== $mb_thirdparty_agree) {
|
||||
$sql_thirdparty_date .= " , mb_thirdparty_date = '".G5_TIME_YMDHIS."' ";
|
||||
$agree_items[] = "개인정보 제3자 제공(" . ($mb_thirdparty_agree == 1 ? "동의" : "철회") . ")";
|
||||
}
|
||||
@@ -590,8 +604,8 @@ if( $config['cf_member_img_size'] && $config['cf_member_img_width'] && $config['
|
||||
if ($config['cf_use_email_certify'] && $old_email != $mb_email) {
|
||||
$subject = '['.$config['cf_title'].'] 인증확인 메일입니다.';
|
||||
|
||||
// 어떠한 회원정보도 포함되지 않은 일회용 난수를 생성하여 인증에 사용
|
||||
$mb_md5 = md5(pack('V*', rand(), rand(), rand(), rand()));
|
||||
// 어떠한 회원정보도 포함되지 않은 일회용 난수를 생성하여 인증에 사용 (CSPRNG 사용)
|
||||
$mb_md5 = get_random_token_string(16);
|
||||
|
||||
sql_query(" update {$g5['member_table']} set mb_email_certify2 = '$mb_md5' where mb_id = '$mb_id' ");
|
||||
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ $result = sql_query($sql);
|
||||
for ($i=0; $row=sql_fetch_array($result); $i++) {
|
||||
$file = '';
|
||||
|
||||
if (strstr($row['wr_option'], 'html'))
|
||||
if (strpos($row['wr_option'], 'html') !== false)
|
||||
$html = 1;
|
||||
else
|
||||
$html = 0;
|
||||
|
||||
+11
-7
@@ -72,7 +72,9 @@ if ($stx) {
|
||||
$field = explode('||', trim($sfl));
|
||||
|
||||
$str = '(';
|
||||
for ($i=0; $i<count($s); $i++) {
|
||||
$s_cnt = count($s);
|
||||
$field_cnt = count($field);
|
||||
for ($i=0; $i<$s_cnt; $i++) {
|
||||
if (trim($s[$i]) == '') continue;
|
||||
|
||||
$search_str = $s[$i];
|
||||
@@ -85,7 +87,7 @@ if ($stx) {
|
||||
|
||||
$op2 = '';
|
||||
// 필드의 수만큼 다중 필드 검색 가능 (필드1+필드2...)
|
||||
for ($k=0; $k<count($field); $k++) {
|
||||
for ($k=0; $k<$field_cnt; $k++) {
|
||||
$str .= $op2;
|
||||
switch ($field[$k]) {
|
||||
case 'mb_id' :
|
||||
@@ -119,7 +121,8 @@ if ($stx) {
|
||||
$time1 = get_microtime();
|
||||
|
||||
$total_count = 0;
|
||||
for ($i=0; $i<count($g5_search['tables']); $i++) {
|
||||
$tables_cnt = count($g5_search['tables']);
|
||||
for ($i=0; $i<$tables_cnt; $i++) {
|
||||
$tmp_write_table = $g5['write_prefix'] . $g5_search['tables'][$i];
|
||||
|
||||
$sql = " select wr_id from {$tmp_write_table} where {$sql_search} ";
|
||||
@@ -148,7 +151,8 @@ if ($stx) {
|
||||
if ($page < 1) { $page = 1; } // 페이지가 없으면 첫 페이지 (1 페이지)
|
||||
$from_record = ($page - 1) * $rows; // 시작 열을 구함
|
||||
|
||||
for ($i=0; $i<count($search_table); $i++) {
|
||||
$search_table_cnt = count($search_table);
|
||||
for ($i=0; $i<$search_table_cnt; $i++) {
|
||||
if ($from_record < $search_table_count[$i]) {
|
||||
$table_index = $i;
|
||||
$from_record = $from_record - ($i > 0 ? $search_table_count[$i-1] : 0);
|
||||
@@ -183,11 +187,11 @@ if ($stx) {
|
||||
}
|
||||
|
||||
// 비밀글은 검색 불가
|
||||
if (strstr($row['wr_option'].(isset($row2['wr_option']) ? $row2['wr_option'] : ''), 'secret'))
|
||||
if (strpos($row['wr_option'].(isset($row2['wr_option']) ? $row2['wr_option'] : ''), 'secret') !== false)
|
||||
$row['wr_content'] = '[비밀글 입니다.]';
|
||||
|
||||
$subject = get_text($row['wr_subject']);
|
||||
if (strstr($sfl, 'wr_subject'))
|
||||
if (strpos($sfl, 'wr_subject') !== false)
|
||||
$subject = search_font($stx, $subject);
|
||||
|
||||
if ($read_level[$idx] <= $member['mb_level'])
|
||||
@@ -199,7 +203,7 @@ if ($stx) {
|
||||
$content = str_replace(' ', '', $content);
|
||||
$content = cut_str($content, 300, "…");
|
||||
|
||||
if (strstr($sfl, 'wr_content'))
|
||||
if (strpos($sfl, 'wr_content') !== false)
|
||||
$content = search_font($stx, $content);
|
||||
}
|
||||
else
|
||||
|
||||
+4
-4
@@ -111,17 +111,17 @@ if ($is_member) {
|
||||
|
||||
$view = get_view($write, $board, $board_skin_path);
|
||||
|
||||
if (strstr($sfl, 'subject'))
|
||||
if (strpos($sfl, 'subject') !== false)
|
||||
$view['subject'] = search_font($stx, $view['subject']);
|
||||
|
||||
$html = 0;
|
||||
if (strstr($view['wr_option'], 'html1'))
|
||||
if (strpos($view['wr_option'], 'html1') !== false)
|
||||
$html = 1;
|
||||
else if (strstr($view['wr_option'], 'html2'))
|
||||
else if (strpos($view['wr_option'], 'html2') !== false)
|
||||
$html = 2;
|
||||
|
||||
$view['content'] = conv_content($view['wr_content'], $html);
|
||||
if (strstr($sfl, 'content'))
|
||||
if (strpos($sfl, 'content') !== false)
|
||||
$view['content'] = search_font($stx, $view['content']);
|
||||
|
||||
//$view['rich_content'] = preg_replace("/{이미지\:([0-9]+)[:]?([^}]*)}/ie", "view_image(\$view, '\\1', '\\2')", $view['content']);
|
||||
|
||||
@@ -40,7 +40,7 @@ for ($i=0; $row=sql_fetch_array($result); $i++)
|
||||
//$list[$i]['content'] = eregi_replace("[^ \n<>]{130}", "\\0\n", $row['wr_content']);
|
||||
|
||||
$list[$i]['content'] = $list[$i]['content1']= '비밀글 입니다.';
|
||||
if (!strstr($row['wr_option'], 'secret') ||
|
||||
if (strpos($row['wr_option'], 'secret') === false ||
|
||||
$is_admin ||
|
||||
($write['mb_id']===$member['mb_id'] && $member['mb_id']) ||
|
||||
($row['mb_id']===$member['mb_id'] && $member['mb_id'])) {
|
||||
|
||||
+3
-1
@@ -346,8 +346,10 @@ if ($w == '') {
|
||||
}
|
||||
|
||||
for($i=0;$i<$file_count;$i++){
|
||||
if(! isset($file[$i])) {
|
||||
if (!isset($file[$i])) {
|
||||
$file[$i] = array('file'=>null, 'source'=>null, 'size'=>null, 'bf_content' => null);
|
||||
} else {
|
||||
$file[$i]['bf_content'] = isset($file[$i]['bf_content']) ? htmlspecialchars($file[$i]['bf_content'], ENT_QUOTES, 'UTF-8', false) : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,9 @@ if (substr_count($wr_content, "&#") > 50) {
|
||||
}
|
||||
|
||||
$w = isset($_POST['w']) ? clean_xss_tags($_POST['w']) : '';
|
||||
$wr_name = isset($_POST['wr_name']) ? clean_xss_tags(trim($_POST['wr_name'])) : '';
|
||||
$wr_secret = isset($_POST['wr_secret']) ? clean_xss_tags($_POST['wr_secret']) : '';
|
||||
$wr_name = isset($_POST['wr_name']) ? addslashes(clean_xss_tags(stripslashes(trim($_POST['wr_name'])))) : '';
|
||||
$wr_name = preg_replace("#[\\\]+$#", "", $wr_name);
|
||||
$wr_secret = isset($_POST['wr_secret']) ? addslashes(clean_xss_tags(stripslashes($_POST['wr_secret']))) : '';
|
||||
$wr_email = $wr_subject = '';
|
||||
$reply_array = array();
|
||||
|
||||
@@ -31,9 +32,9 @@ $wr_7 = isset($_POST['wr_7']) ? $_POST['wr_7'] : '';
|
||||
$wr_8 = isset($_POST['wr_8']) ? $_POST['wr_8'] : '';
|
||||
$wr_9 = isset($_POST['wr_9']) ? $_POST['wr_9'] : '';
|
||||
$wr_10 = isset($_POST['wr_10']) ? $_POST['wr_10'] : '';
|
||||
$wr_facebook_user = isset($_POST['wr_facebook_user']) ? clean_xss_tags($_POST['wr_facebook_user'], 1, 1) : '';
|
||||
$wr_twitter_user = isset($_POST['wr_twitter_user']) ? clean_xss_tags($_POST['wr_twitter_user'], 1, 1) : '';
|
||||
$wr_homepage = isset($_POST['wr_homepage']) ? clean_xss_tags($_POST['wr_homepage'], 1, 1) : '';
|
||||
$wr_facebook_user = isset($_POST['wr_facebook_user']) ? addslashes(clean_xss_tags(stripslashes($_POST['wr_facebook_user']), 1, 1)) : '';
|
||||
$wr_twitter_user = isset($_POST['wr_twitter_user']) ? addslashes(clean_xss_tags(stripslashes($_POST['wr_twitter_user']), 1, 1)) : '';
|
||||
$wr_homepage = isset($_POST['wr_homepage']) ? addslashes(clean_xss_tags(stripslashes($_POST['wr_homepage']), 1, 1)) : '';
|
||||
|
||||
if (!empty($_POST['wr_email']))
|
||||
$wr_email = get_email_address(trim($_POST['wr_email']));
|
||||
@@ -255,7 +256,8 @@ if ($w == 'c') // 댓글 입력
|
||||
// 중복된 메일 주소는 제거
|
||||
$unique_email = array_unique($array_email);
|
||||
$unique_email = array_values($unique_email);
|
||||
for ($i=0; $i<count($unique_email); $i++) {
|
||||
$unique_email_cnt = count($unique_email);
|
||||
for ($i=0; $i<$unique_email_cnt; $i++) {
|
||||
mailer($wr_name, $wr_email, $unique_email[$i], $subject, $content, 1);
|
||||
}
|
||||
}
|
||||
|
||||
+21
-14
@@ -241,12 +241,13 @@ if ($w == '' || $w == 'r') {
|
||||
} else {
|
||||
$mb_id = '';
|
||||
// 비회원의 경우 이름이 누락되는 경우가 있음
|
||||
$wr_name = clean_xss_tags(trim($_POST['wr_name']));
|
||||
$wr_name = addslashes(clean_xss_tags(stripslashes(trim($_POST['wr_name']))));
|
||||
$wr_name = preg_replace("#[\\\]+$#", "", $wr_name);
|
||||
if (!$wr_name)
|
||||
alert('이름은 필히 입력하셔야 합니다.');
|
||||
$wr_password = get_encrypt_string($wr_password);
|
||||
$wr_email = get_email_address(trim($_POST['wr_email']));
|
||||
$wr_homepage = clean_xss_tags($wr_homepage);
|
||||
$wr_homepage = addslashes(clean_xss_tags(stripslashes($wr_homepage)));
|
||||
}
|
||||
|
||||
if ($w == 'r') {
|
||||
@@ -362,16 +363,17 @@ if ($w == '' || $w == 'r') {
|
||||
$wr_homepage = addslashes(clean_xss_tags($member['mb_homepage']));
|
||||
} else {
|
||||
$mb_id = $wr['mb_id'];
|
||||
if(isset($_POST['wr_name']) && $_POST['wr_name'])
|
||||
$wr_name = clean_xss_tags(trim($_POST['wr_name']));
|
||||
else
|
||||
if(isset($_POST['wr_name']) && $_POST['wr_name']) {
|
||||
$wr_name = addslashes(clean_xss_tags(stripslashes(trim($_POST['wr_name']))));
|
||||
$wr_name = preg_replace("#[\\\]+$#", "", $wr_name);
|
||||
} else
|
||||
$wr_name = addslashes(clean_xss_tags($wr['wr_name']));
|
||||
if(isset($_POST['wr_email']) && $_POST['wr_email'])
|
||||
$wr_email = get_email_address(trim($_POST['wr_email']));
|
||||
else
|
||||
$wr_email = addslashes($wr['wr_email']);
|
||||
if(isset($_POST['wr_homepage']) && $_POST['wr_homepage'])
|
||||
$wr_homepage = addslashes(clean_xss_tags($_POST['wr_homepage']));
|
||||
$wr_homepage = addslashes(clean_xss_tags(stripslashes($_POST['wr_homepage'])));
|
||||
else
|
||||
$wr_homepage = addslashes(clean_xss_tags($wr['wr_homepage']));
|
||||
}
|
||||
@@ -379,7 +381,8 @@ if ($w == '' || $w == 'r') {
|
||||
$mb_id = "";
|
||||
// 비회원의 경우 이름이 누락되는 경우가 있음
|
||||
if (!trim($wr_name)) alert("이름은 필히 입력하셔야 합니다.");
|
||||
$wr_name = clean_xss_tags(trim($_POST['wr_name']));
|
||||
$wr_name = addslashes(clean_xss_tags(stripslashes(trim($_POST['wr_name']))));
|
||||
$wr_name = preg_replace("#[\\\]+$#", "", $wr_name);
|
||||
$wr_email = get_email_address(trim($_POST['wr_email']));
|
||||
}
|
||||
|
||||
@@ -430,7 +433,8 @@ if ($w == '' || $w == 'r') {
|
||||
}
|
||||
} else {
|
||||
$bo_notice = '';
|
||||
for ($i=0; $i<count($notice_array); $i++)
|
||||
$notice_array_cnt = count($notice_array);
|
||||
for ($i=0; $i<$notice_array_cnt; $i++)
|
||||
if ((int)$wr_id != (int)$notice_array[$i])
|
||||
$bo_notice .= $notice_array[$i] . ',';
|
||||
$bo_notice = trim($bo_notice);
|
||||
@@ -480,7 +484,8 @@ $file_upload_msg = '';
|
||||
$upload = array();
|
||||
|
||||
if(isset($_FILES['bf_file']['name']) && is_array($_FILES['bf_file']['name'])) {
|
||||
for ($i=0; $i<count($_FILES['bf_file']['name']); $i++) {
|
||||
$bf_file_cnt = count($_FILES['bf_file']['name']);
|
||||
for ($i=0; $i<$bf_file_cnt; $i++) {
|
||||
$upload[$i]['file'] = '';
|
||||
$upload[$i]['source'] = '';
|
||||
$upload[$i]['filesize'] = 0;
|
||||
@@ -572,7 +577,7 @@ if(isset($_FILES['bf_file']['name']) && is_array($_FILES['bf_file']['name'])) {
|
||||
$upload[$i]['filesize'] = $filesize;
|
||||
|
||||
// 아래의 문자열이 들어간 파일은 -x 를 붙여서 웹경로를 알더라도 실행을 하지 못하도록 함
|
||||
$filename = preg_replace("/\.(php|pht|phtm|htm|cgi|pl|exe|jsp|asp|inc|phar)/i", "$0-x", $filename);
|
||||
$filename = preg_replace("/\.(php|pht|phtm|htm|shtml|shtm|cgi|pl|exe|jsp|asp|inc|phar|svg|svgz)/i", "$0-x", $filename);
|
||||
|
||||
shuffle($chars_array);
|
||||
$shuffle = implode('', $chars_array);
|
||||
@@ -595,7 +600,8 @@ if(isset($_FILES['bf_file']['name']) && is_array($_FILES['bf_file']['name'])) {
|
||||
} // end if
|
||||
|
||||
// 나중에 테이블에 저장하는 이유는 $wr_id 값을 저장해야 하기 때문입니다.
|
||||
for ($i=0; $i<count($upload); $i++)
|
||||
$upload_cnt = count($upload);
|
||||
for ($i=0; $i<$upload_cnt; $i++)
|
||||
{
|
||||
$upload[$i]['source'] = sql_real_escape_string($upload[$i]['source']);
|
||||
$bf_content[$i] = isset($bf_content[$i]) ? sql_real_escape_string($bf_content[$i]) : '';
|
||||
@@ -704,9 +710,9 @@ if (!($w == 'u' || $w == 'cu') && $config['cf_email_use'] && $board['bo_use_emai
|
||||
$wr_subject = get_text(stripslashes($wr_subject));
|
||||
|
||||
$tmp_html = 0;
|
||||
if (strstr($html, 'html1'))
|
||||
if (strpos($html, 'html1') !== false)
|
||||
$tmp_html = 1;
|
||||
else if (strstr($html, 'html2'))
|
||||
else if (strpos($html, 'html2') !== false)
|
||||
$tmp_html = 2;
|
||||
|
||||
$wr_content = conv_content(conv_unescape_nl(stripslashes($wr_content)), $tmp_html);
|
||||
@@ -751,7 +757,8 @@ if (!($w == 'u' || $w == 'cu') && $config['cf_email_use'] && $board['bo_use_emai
|
||||
$unique_email = array_unique($array_email);
|
||||
$unique_email = run_replace('write_update_mail_list', array_values($unique_email), $board, $wr_id);
|
||||
|
||||
for ($i=0; $i<count($unique_email); $i++) {
|
||||
$unique_email_cnt = count($unique_email);
|
||||
for ($i=0; $i<$unique_email_cnt; $i++) {
|
||||
mailer($wr_name, $wr_email, $unique_email[$i], $subject, $content, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class G5CloudflareRequestHandler {
|
||||
'197.234.240.0/22',
|
||||
'198.41.128.0/17',
|
||||
'162.158.0.0/15',
|
||||
'104.16.0.0/12',
|
||||
'104.16.0.0/13',
|
||||
'104.24.0.0/14',
|
||||
'172.64.0.0/13',
|
||||
'131.0.72.0/22',
|
||||
|
||||
+31
-11
@@ -165,6 +165,11 @@ if (file_exists($dbconfig_file)) {
|
||||
sql_set_charset(G5_DB_CHARSET, $connect_db);
|
||||
if(defined('G5_MYSQL_SET_MODE') && G5_MYSQL_SET_MODE) sql_query("SET SESSION sql_mode = ''");
|
||||
if (defined('G5_TIMEZONE')) sql_query(" set time_zone = '".G5_TIMEZONE."'");
|
||||
|
||||
// 자동 로그인 토큰 테이블 - 기존 dbconfig.php에 정의되지 않은 경우 fallback
|
||||
if (!isset($g5['member_auto_login_table'])) {
|
||||
$g5['member_auto_login_table'] = G5_TABLE_PREFIX.'member_auto_login';
|
||||
}
|
||||
} else {
|
||||
?>
|
||||
|
||||
@@ -556,17 +561,30 @@ if (isset($_SESSION['ss_mb_id']) && $_SESSION['ss_mb_id']) { // 로그인중이
|
||||
$tmp_mb_id = substr(preg_replace("/[^a-zA-Z0-9_]*/", "", $tmp_mb_id), 0, 20);
|
||||
// 최고관리자는 자동로그인 금지
|
||||
if (strtolower($tmp_mb_id) !== strtolower($config['cf_admin'])) {
|
||||
$sql = " select mb_password, mb_intercept_date, mb_leave_date, mb_email_certify, mb_datetime from {$g5['member_table']} where mb_id = '{$tmp_mb_id}' ";
|
||||
$row = sql_fetch($sql);
|
||||
if($row['mb_password']){
|
||||
$key = md5($_SERVER['SERVER_ADDR'] . $_SERVER['SERVER_SOFTWARE'] . $_SERVER['HTTP_USER_AGENT'] . $row['mb_password']);
|
||||
// 쿠키에 저장된 키와 같다면
|
||||
$tmp_key = get_cookie('ck_auto');
|
||||
if ($tmp_key === $key && $tmp_key) {
|
||||
// 쿠키 값을 g5_member_auto_login 테이블의 토큰과 비교
|
||||
// 다중 디바이스 지원을 위해 회원당 여러 토큰을 별도 테이블에 저장
|
||||
$tmp_key = get_cookie('ck_auto');
|
||||
// 토큰 형식 검증 (64자 hex) - 빈 값/잘못된 형식 차단
|
||||
if ($tmp_key && preg_match('/^[a-f0-9]{64}$/', $tmp_key)) {
|
||||
$tmp_key_hash = hash('sha256', $tmp_key); // 쿠키 값을 해시해서 DB와 비교
|
||||
$sql = " select al.al_id, al.al_expire,
|
||||
m.mb_intercept_date, m.mb_leave_date, m.mb_email_certify, m.mb_datetime
|
||||
from {$g5['member_auto_login_table']} al
|
||||
inner join {$g5['member_table']} m on m.mb_id = al.mb_id
|
||||
where al.mb_id = '{$tmp_mb_id}'
|
||||
and al.al_token = '{$tmp_key_hash}'
|
||||
and al.al_expire > '".G5_TIME_YMDHIS."' ";
|
||||
$row = sql_fetch($sql);
|
||||
if (isset($row['al_id']) && $row['al_id']) {
|
||||
// 차단, 탈퇴가 아니고 메일인증이 사용이면서 인증을 받았다면
|
||||
if ($row['mb_intercept_date'] == '' &&
|
||||
$row['mb_leave_date'] == '' &&
|
||||
(!$config['cf_use_email_certify'] || preg_match('/[1-9]/', $row['mb_email_certify'])) ) {
|
||||
// 마지막 사용 시간 갱신
|
||||
sql_query(" update {$g5['member_auto_login_table']}
|
||||
set al_last_used = '".G5_TIME_YMDHIS."'
|
||||
where al_id = '{$row['al_id']}' ");
|
||||
|
||||
// 세션에 회원아이디를 저장하여 로그인으로 간주
|
||||
set_session('ss_mb_id', $tmp_mb_id);
|
||||
if(function_exists('update_auth_session_token')) update_auth_session_token($row['mb_datetime']);
|
||||
@@ -576,9 +594,9 @@ if (isset($_SESSION['ss_mb_id']) && $_SESSION['ss_mb_id']) { // 로그인중이
|
||||
exit;
|
||||
}
|
||||
}
|
||||
// $row 배열변수 해제
|
||||
unset($row);
|
||||
}
|
||||
// $row 배열변수 해제
|
||||
unset($row);
|
||||
}
|
||||
}
|
||||
// 자동로그인 end ---------------------------------------
|
||||
@@ -591,7 +609,8 @@ if (!(isset($member['mb_id']) && $config['cf_admin'] === $member['mb_id'])) {
|
||||
if ($cf_possible_ip) {
|
||||
$is_possible_ip = false;
|
||||
$pattern = explode("\n", $cf_possible_ip);
|
||||
for ($i=0; $i<count($pattern); $i++) {
|
||||
$pattern_cnt = count($pattern);
|
||||
for ($i=0; $i<$pattern_cnt; $i++) {
|
||||
$pattern[$i] = trim($pattern[$i]);
|
||||
if (empty($pattern[$i]))
|
||||
continue;
|
||||
@@ -610,7 +629,8 @@ if (!(isset($member['mb_id']) && $config['cf_admin'] === $member['mb_id'])) {
|
||||
// 접근차단 IP
|
||||
$is_intercept_ip = false;
|
||||
$pattern = explode("\n", trim($config['cf_intercept_ip']));
|
||||
for ($i=0; $i<count($pattern); $i++) {
|
||||
$pattern_cnt = count($pattern);
|
||||
for ($i=0; $i<$pattern_cnt; $i++) {
|
||||
$pattern[$i] = trim($pattern[$i]);
|
||||
if (empty($pattern[$i]))
|
||||
continue;
|
||||
|
||||
+2
-2
@@ -173,7 +173,7 @@ define('G5_DIR_PERMISSION', 0755); // 디렉토리 생성시 퍼미션
|
||||
define('G5_FILE_PERMISSION', 0644); // 파일 생성시 퍼미션
|
||||
|
||||
// 모바일 인지 결정 $_SERVER['HTTP_USER_AGENT']
|
||||
define('G5_MOBILE_AGENT', 'phone|samsung|lgtel|mobile|[^A]skt|nokia|blackberry|BB10|android|sony');
|
||||
define('G5_MOBILE_AGENT', 'phone|samsung.*mobile|lgtel|mobile|[^A]skt|nokia|blackberry|BB10|android|sony');
|
||||
|
||||
// SMTP
|
||||
// lib/mailer.lib.php 에서 사용
|
||||
@@ -235,4 +235,4 @@ define('G5_VISIT_BROWSCAP_USE', false);
|
||||
define('G5_IP_DISPLAY', '\\1.♡.\\3.\\4');
|
||||
|
||||
// KAKAO 우편번호 서비스 CDN
|
||||
define('G5_POSTCODE_JS', '<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js" async></script>');
|
||||
define('G5_POSTCODE_JS', '<script src="//t1.kakaocdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js" async></script>');
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<FilesMatch "\.(htaccess|htpasswd|[Pp][Hh][Pp]|[Pp][Hh][Tt]|[Ss]?[Pp]?[Hh][Tt][Mm][Ll]?|[Ii][Nn][Cc]|[Cc][Gg][Ii]|[Pp][Ll]|[Pp][Hh][Aa][Rr]|[Ss][Vv][Gg][Zz]?)">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</FilesMatch>
|
||||
RedirectMatch 403 /session/.*
|
||||
+1
-1
@@ -28,7 +28,7 @@ $g5['lo_location'] = addslashes($g5['title']);
|
||||
if (!$g5['lo_location'])
|
||||
$g5['lo_location'] = addslashes(clean_xss_tags($_SERVER['REQUEST_URI']));
|
||||
$g5['lo_url'] = addslashes(clean_xss_tags($_SERVER['REQUEST_URI']));
|
||||
if (strstr($g5['lo_url'], '/'.G5_ADMIN_DIR.'/') || $is_admin == 'super') $g5['lo_url'] = '';
|
||||
if (strpos($g5['lo_url'], '/'.G5_ADMIN_DIR.'/') !== false || $is_admin == 'super') $g5['lo_url'] = '';
|
||||
|
||||
/*
|
||||
// 만료된 페이지로 사용하시는 경우
|
||||
|
||||
@@ -554,6 +554,28 @@ CREATE TABLE IF NOT EXISTS `g5_member` (
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `g5_member_auto_login`
|
||||
-- KVE-2026-0610: 자동 로그인 토큰 저장 (다중 디바이스 지원)
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `g5_member_auto_login`;
|
||||
CREATE TABLE IF NOT EXISTS `g5_member_auto_login` (
|
||||
`al_id` int(11) NOT NULL auto_increment,
|
||||
`mb_id` varchar(20) NOT NULL default '',
|
||||
`al_token` varchar(64) NOT NULL default '',
|
||||
`al_user_agent` varchar(255) NOT NULL default '',
|
||||
`al_ip` varchar(45) NOT NULL default '',
|
||||
`al_created` datetime DEFAULT NULL,
|
||||
`al_last_used` datetime DEFAULT NULL,
|
||||
`al_expire` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`al_id`),
|
||||
UNIQUE KEY `al_token` (`al_token`),
|
||||
KEY `mb_id` (`mb_id`),
|
||||
KEY `al_expire` (`al_expire`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `g5_memo`
|
||||
--
|
||||
|
||||
@@ -169,6 +169,7 @@ CREATE TABLE IF NOT EXISTS `g5_shop_coupon_log` (
|
||||
`cp_price` int(11) NOT NULL DEFAULT '0',
|
||||
`cl_datetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
PRIMARY KEY (`cl_id`),
|
||||
UNIQUE KEY `idx_coupon_use` (`cp_id`, `mb_id`),
|
||||
KEY `mb_id` (`mb_id`),
|
||||
KEY `od_id` (`od_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
@@ -158,7 +158,7 @@ if ($g5_install || $is_install === false) {
|
||||
cf_theme = 'basic',
|
||||
cf_admin = '$admin_id',
|
||||
cf_admin_email = '$admin_email',
|
||||
cf_admin_email_name = '".G5_VERSION."',
|
||||
cf_admin_email_name = '".G5_VERSION.'_'.substr(base_convert(mt_rand(), 10, 36), 0, 6)."',
|
||||
cf_use_point = '1',
|
||||
cf_use_copy_log = '1',
|
||||
cf_login_point = '100',
|
||||
@@ -596,6 +596,7 @@ fwrite($f, "\$g5['board_new_table'] = G5_TABLE_PREFIX.'board_new'; // 게시판
|
||||
fwrite($f, "\$g5['login_table'] = G5_TABLE_PREFIX.'login'; // 로그인 테이블 (접속자수)\n");
|
||||
fwrite($f, "\$g5['mail_table'] = G5_TABLE_PREFIX.'mail'; // 회원메일 테이블\n");
|
||||
fwrite($f, "\$g5['member_table'] = G5_TABLE_PREFIX.'member'; // 회원 테이블\n");
|
||||
fwrite($f, "\$g5['member_auto_login_table'] = G5_TABLE_PREFIX.'member_auto_login'; // 자동 로그인 토큰 테이블\n");
|
||||
fwrite($f, "\$g5['memo_table'] = G5_TABLE_PREFIX.'memo'; // 메모 테이블\n");
|
||||
fwrite($f, "\$g5['poll_table'] = G5_TABLE_PREFIX.'poll'; // 투표 테이블\n");
|
||||
fwrite($f, "\$g5['poll_etc_table'] = G5_TABLE_PREFIX.'poll_etc'; // 투표 기타의견 테이블\n");
|
||||
@@ -659,7 +660,7 @@ fclose($f);
|
||||
// data 디렉토리 및 하위 디렉토리에서는 .htaccess .htpasswd .php .phtml .html .htm .inc .cgi .pl .phar 파일을 실행할수 없게함.
|
||||
$f = fopen($data_path.'/.htaccess', 'w');
|
||||
$str = <<<EOD
|
||||
<FilesMatch "\.(htaccess|htpasswd|[Pp][Hh][Pp]|[Pp][Hh][Tt]|[Pp]?[Hh][Tt][Mm][Ll]?|[Ii][Nn][Cc]|[Cc][Gg][Ii]|[Pp][Ll]|[Pp][Hh][Aa][Rr])">
|
||||
<FilesMatch "\.(htaccess|htpasswd|[Pp][Hh][Pp]|[Pp][Hh][Tt]|[Ss]?[Pp]?[Hh][Tt][Mm][Ll]?|[Ii][Nn][Cc]|[Cc][Gg][Ii]|[Pp][Ll]|[Pp][Hh][Aa][Rr]|[Ss][Vv][Gg][Zz]?)">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</FilesMatch>
|
||||
|
||||
+5
-5
@@ -423,7 +423,7 @@ var win_zip = function(frm_name, frm_zip, frm_addr1, frm_addr2, frm_addr3, frm_j
|
||||
element_wrap = document.createElement("div");
|
||||
element_wrap.setAttribute("id", daum_pape_id);
|
||||
element_wrap.style.cssText = 'display:none;border:1px solid;left:0;width:100%;height:300px;margin:5px 0;position:relative;-webkit-overflow-scrolling:touch;';
|
||||
element_wrap.innerHTML = '<img src="//t1.daumcdn.net/postcode/resource/images/close.png" id="btnFoldWrap" style="cursor:pointer;position:absolute;right:0px;top:-21px;z-index:1" class="close_daum_juso" alt="접기 버튼">';
|
||||
element_wrap.innerHTML = '<img src="//t1.kakaocdn.net/postcode/resource/images/close.png" id="btnFoldWrap" style="cursor:pointer;position:absolute;right:0px;top:-21px;z-index:1" class="close_daum_juso" alt="접기 버튼">';
|
||||
jQuery('form[name="'+frm_name+'"]').find('input[name="'+frm_addr1+'"]').before(element_wrap);
|
||||
jQuery("#"+daum_pape_id).off("click", ".close_daum_juso").on("click", ".close_daum_juso", function(e){
|
||||
e.preventDefault();
|
||||
@@ -432,7 +432,7 @@ var win_zip = function(frm_name, frm_zip, frm_addr1, frm_addr2, frm_addr3, frm_j
|
||||
});
|
||||
}
|
||||
|
||||
new daum.Postcode({
|
||||
new kakao.Postcode({
|
||||
oncomplete: function(data) {
|
||||
complete_fn(data);
|
||||
// iframe을 넣은 element를 안보이게 한다.
|
||||
@@ -454,7 +454,7 @@ var win_zip = function(frm_name, frm_zip, frm_addr1, frm_addr2, frm_addr3, frm_j
|
||||
element_wrap.style.display = 'block';
|
||||
break;
|
||||
case 2 : //새창으로 띄우기
|
||||
new daum.Postcode({
|
||||
new kakao.Postcode({
|
||||
oncomplete: function(data) {
|
||||
complete_fn(data);
|
||||
}
|
||||
@@ -467,7 +467,7 @@ var win_zip = function(frm_name, frm_zip, frm_addr1, frm_addr2, frm_addr3, frm_j
|
||||
element_layer = document.createElement("div");
|
||||
element_layer.setAttribute("id", rayer_id);
|
||||
element_layer.style.cssText = 'display:none;border:5px solid;position:fixed;width:300px;height:460px;left:50%;margin-left:-155px;top:50%;margin-top:-235px;overflow:hidden;-webkit-overflow-scrolling:touch;z-index:10000';
|
||||
element_layer.innerHTML = '<img src="//i1.daumcdn.net/localimg/localimages/07/postcode/320/close.png" id="btnCloseLayer" style="cursor:pointer;position:absolute;right:-3px;top:-3px;z-index:1" class="close_daum_juso" alt="닫기 버튼">';
|
||||
element_layer.innerHTML = '<img src="//t1.kakaocdn.net/localimg/localimages/07/postcode/320/close.png" id="btnCloseLayer" style="cursor:pointer;position:absolute;right:-3px;top:-3px;z-index:1" class="close_daum_juso" alt="닫기 버튼">';
|
||||
document.body.appendChild(element_layer);
|
||||
jQuery("#"+rayer_id).off("click", ".close_daum_juso").on("click", ".close_daum_juso", function(e){
|
||||
e.preventDefault();
|
||||
@@ -476,7 +476,7 @@ var win_zip = function(frm_name, frm_zip, frm_addr1, frm_addr2, frm_addr3, frm_j
|
||||
});
|
||||
}
|
||||
|
||||
new daum.Postcode({
|
||||
new kakao.Postcode({
|
||||
oncomplete: function(data) {
|
||||
complete_fn(data);
|
||||
// iframe을 넣은 element를 안보이게 한다.
|
||||
|
||||
@@ -25,7 +25,7 @@ class G5_URI {
|
||||
$ext = end($script_names);
|
||||
|
||||
/* if extension is found in URL, eliminate it */
|
||||
if(strstr($uri,".")) {
|
||||
if(strpos($uri,".") !== false) {
|
||||
$arr_uri = explode('.', $uri);
|
||||
/* get last part */
|
||||
$last = end($arr_uri);
|
||||
|
||||
+560
-127
@@ -257,22 +257,42 @@ function url_auto_link($str)
|
||||
{
|
||||
global $g5;
|
||||
global $config;
|
||||
|
||||
|
||||
if ($replace_str = run_replace('url_auto_link_before', '', $str)) {
|
||||
return $replace_str;
|
||||
}
|
||||
|
||||
|
||||
$ori_str = $str;
|
||||
|
||||
|
||||
// 140326 유창화님 제안코드로 수정
|
||||
// http://sir.kr/pg_lecture/461
|
||||
// http://sir.kr/pg_lecture/463
|
||||
|
||||
// 각 패턴의 존재 여부를 빠르게 체크하여 preg_replace 호출을 최소화한다.
|
||||
// 일반 텍스트 게시글(URL/이메일이 없는 대부분의 경우)에서는 fast path로 즉시 반환.
|
||||
// strpos(x5) ~= 1~2ms vs preg_replace(x3) ~= 20~50ms 이므로 핫패스에서 큰 이득.
|
||||
$has_url_scheme = strpos($str, '://') !== false;
|
||||
$has_www = stripos($str, 'www.') !== false;
|
||||
$has_at = strpos($str, '@') !== false;
|
||||
$has_amp = strpos($str, '&') !== false;
|
||||
$has_quote = strpos($str, "'") !== false;
|
||||
|
||||
if (!$has_url_scheme && !$has_www && !$has_at && !$has_amp && !$has_quote) {
|
||||
return run_replace('url_auto_link', $str, $ori_str);
|
||||
}
|
||||
|
||||
$attr_nofollow = (function_exists('check_html_link_nofollow') && check_html_link_nofollow('url_auto_link')) ? ' rel="nofollow"' : '';
|
||||
$str = str_replace(array("<", ">", "&", """, " ", "'"), array("\t_lt_\t", "\t_gt_\t", "&", "\"", "\t_nbsp_\t", "'"), $str);
|
||||
//$str = preg_replace("`(?:(?:(?:href|src)\s*=\s*(?:\"|'|)){0})((http|https|ftp|telnet|news|mms)://[^\"'\s()]+)`", "<A HREF=\"\\1\" TARGET='{$config['cf_link_target']}'>\\1</A>", $str);
|
||||
$str = preg_replace("/([^(href=\"?'?)|(src=\"?'?)]|\(|^)((http|https|ftp|telnet|news|mms):\/\/[a-zA-Z0-9\.-]+\.[가-힣\xA1-\xFEa-zA-Z0-9\.:&#!=_\?\/~\+%@;\-\|\,\(\)]+)/i", "\\1<A HREF=\"\\2\" TARGET=\"{$config['cf_link_target']}\" $attr_nofollow>\\2</A>", $str);
|
||||
$str = preg_replace("/(^|[\"'\s(])(www\.[^\"'\s()]+)/i", "\\1<A HREF=\"http://\\2\" TARGET=\"{$config['cf_link_target']}\" $attr_nofollow>\\2</A>", $str);
|
||||
$str = preg_replace("/[0-9a-z_-]+@[a-z0-9._-]{4,}/i", "<a href=\"mailto:\\0\" $attr_nofollow>\\0</a>", $str);
|
||||
if ($has_url_scheme) {
|
||||
$str = preg_replace("/([^(href=\"?'?)|(src=\"?'?)]|\(|^)((http|https|ftp|telnet|news|mms):\/\/[a-zA-Z0-9\.-]+\.[가-힣\xA1-\xFEa-zA-Z0-9\.:&#!=_\?\/~\+%@;\-\|\,\(\)]+)/i", "\\1<A HREF=\"\\2\" TARGET=\"{$config['cf_link_target']}\" $attr_nofollow>\\2</A>", $str);
|
||||
}
|
||||
if ($has_www) {
|
||||
$str = preg_replace("/(^|[\"'\s(])(www\.[^\"'\s()]+)/i", "\\1<A HREF=\"http://\\2\" TARGET=\"{$config['cf_link_target']}\" $attr_nofollow>\\2</A>", $str);
|
||||
}
|
||||
if ($has_at) {
|
||||
$str = preg_replace("/[0-9a-z_-]+@[a-z0-9._-]{4,}/i", "<a href=\"mailto:\\0\" $attr_nofollow>\\0</a>", $str);
|
||||
}
|
||||
$str = str_replace(array("\t_nbsp_\t", "\t_lt_\t", "\t_gt_\t", "'"), array(" ", "<", ">", "'"), $str);
|
||||
|
||||
/*
|
||||
@@ -442,9 +462,9 @@ function get_list($write_row, $board, $skin_url, $subject_len=40)
|
||||
if ($board['bo_use_list_content'])
|
||||
{
|
||||
$html = 0;
|
||||
if (strstr($list['wr_option'], 'html1'))
|
||||
if (strpos($list['wr_option'], 'html1') !== false)
|
||||
$html = 1;
|
||||
else if (strstr($list['wr_option'], 'html2'))
|
||||
else if (strpos($list['wr_option'], 'html2') !== false)
|
||||
$html = 2;
|
||||
|
||||
$list['content'] = conv_content($list['wr_content'], $html);
|
||||
@@ -505,7 +525,7 @@ function get_list($write_row, $board, $skin_url, $subject_len=40)
|
||||
$list['icon_hot'] = '<i class="fa fa-heart" aria-hidden="true"></i> ';
|
||||
|
||||
$list['icon_secret'] = '';
|
||||
if (strstr($list['wr_option'], 'secret'))
|
||||
if (strpos($list['wr_option'], 'secret') !== false)
|
||||
$list['icon_secret'] = '<i class="fa fa-lock" aria-hidden="true"></i> ';
|
||||
|
||||
// 링크
|
||||
@@ -552,7 +572,8 @@ function search_font($stx, $str)
|
||||
// "/(검색1|검색2)/i" 와 같은 패턴을 만듬
|
||||
$pattern = '';
|
||||
$bar = '';
|
||||
for ($m=0; $m<count($s); $m++) {
|
||||
$s_cnt = count($s);
|
||||
for ($m=0; $m<$s_cnt; $m++) {
|
||||
if (trim($s[$m]) == '') continue;
|
||||
// 태그는 포함하지 않아야 하는데 잘 안되는군. ㅡㅡa
|
||||
//$pattern .= $bar . '([^<])(' . quotemeta($s[$m]) . ')';
|
||||
@@ -645,20 +666,51 @@ function html_purifier($html)
|
||||
{
|
||||
global $is_admin, $write;
|
||||
|
||||
$f = file(G5_PLUGIN_PATH . '/htmlpurifier/safeiframe.txt');
|
||||
$domains = array();
|
||||
foreach ($f as $domain) {
|
||||
// 첫행이 # 이면 주석 처리
|
||||
if (!preg_match("/^#/", $domain)) {
|
||||
$domain = trim($domain);
|
||||
if ($domain) {
|
||||
array_push($domains, $domain);
|
||||
// 요청 단위로 HTMLPurifier 인스턴스를 캐싱한다.
|
||||
// HTMLPurifier 인스턴스 하나는 약 10~15MB의 메모리를 사용하므로,
|
||||
// 같은 요청 내에서 여러 번 호출되는 경우(예: 게시글 목록의 첨부파일 설명)
|
||||
// 매번 새 인스턴스를 만드는 것은 메모리 사용량을 수십~수백 MB까지 증가시킨다.
|
||||
//
|
||||
// config에 영향을 주는 변수는 "글쓴이가 관리자인지" 하나뿐이므로
|
||||
// 캐시 키를 admin/normal 두 가지로 분리하여 최대 2개의 인스턴스만 유지한다.
|
||||
//
|
||||
// 캐싱이 동작 변경을 일으키는 경우(html_purifier_config / html_purifier_safeiframes
|
||||
// hook이 $html 내용에 따라 동적으로 config를 바꾸는 플러그인을 사용하는 경우)
|
||||
// G5_HTMLPURIFIER_NO_CACHE 상수를 정의하여 비활성화할 수 있다.
|
||||
static $purifier_cache = array();
|
||||
static $domains_cache = null;
|
||||
|
||||
$cache_enabled = !(defined('G5_HTMLPURIFIER_NO_CACHE') && G5_HTMLPURIFIER_NO_CACHE);
|
||||
$is_admin_post = (isset($write['mb_id']) && $write['mb_id'] && is_admin($write['mb_id']));
|
||||
$cache_key = $is_admin_post ? 'admin' : 'normal';
|
||||
|
||||
// 캐시 적중 시 인스턴스 재사용
|
||||
if ($cache_enabled && isset($purifier_cache[$cache_key])) {
|
||||
$purifier = $purifier_cache[$cache_key];
|
||||
return run_replace('html_purifier_result', $purifier->purify($html), $purifier, $html);
|
||||
}
|
||||
|
||||
// safeiframe.txt 파싱 결과를 요청 단위로 캐싱 (파일 I/O + 정규식 비용 절감)
|
||||
if ($domains_cache === null) {
|
||||
$domains_cache = array();
|
||||
$f = @file(G5_PLUGIN_PATH . '/htmlpurifier/safeiframe.txt');
|
||||
if ($f !== false) {
|
||||
foreach ($f as $domain) {
|
||||
// 첫행이 # 이면 주석 처리
|
||||
if (preg_match("/^#/", $domain)) continue;
|
||||
$domain = trim($domain);
|
||||
if ($domain !== '') {
|
||||
$domains_cache[] = $domain;
|
||||
}
|
||||
}
|
||||
unset($f);
|
||||
}
|
||||
}
|
||||
|
||||
$domains = $domains_cache;
|
||||
// 글쓴이가 관리자인 경우에만 현재 사이트 도메인을 허용
|
||||
if (isset($write['mb_id']) && $write['mb_id'] && is_admin($write['mb_id'])) {
|
||||
array_push($domains, $_SERVER['HTTP_HOST'] . '/');
|
||||
if ($is_admin_post) {
|
||||
$domains[] = $_SERVER['HTTP_HOST'] . '/';
|
||||
}
|
||||
$safeiframe = implode('|', run_replace('html_purifier_safeiframes', $domains, $html));
|
||||
|
||||
@@ -682,7 +734,10 @@ function html_purifier($html)
|
||||
|
||||
/*
|
||||
* HTMLPurifier 설정을 변경할 수 있는 Event hook
|
||||
* 리스너에서는 첫번째 인자($config)로 `HTMLPurifier_Config` 객체를 받을 수 있다
|
||||
* 리스너에서는 첫번째 인자($config)로 `HTMLPurifier_Config` 객체를 받을 수 있다.
|
||||
* NB: 인스턴스 캐싱이 활성화된 경우(기본값) 이 hook은 캐시 미스 시점에만 실행됨
|
||||
* (요청당 최대 2회). $html 내용에 따라 동적으로 config를 변경해야 한다면
|
||||
* G5_HTMLPURIFIER_NO_CACHE 상수를 정의해 캐시를 비활성화하라.
|
||||
*/
|
||||
run_event('html_purifier_config', $config, array(
|
||||
'html' => $html,
|
||||
@@ -697,6 +752,11 @@ function html_purifier($html)
|
||||
|
||||
$purifier = new HTMLPurifier($config);
|
||||
|
||||
// 인스턴스 캐싱
|
||||
if ($cache_enabled) {
|
||||
$purifier_cache[$cache_key] = $purifier;
|
||||
}
|
||||
|
||||
return run_replace('html_purifier_result', $purifier->purify($html), $purifier, $html);
|
||||
}
|
||||
|
||||
@@ -740,7 +800,9 @@ function get_sql_search($search_ca_name, $search_field, $search_text, $search_op
|
||||
$not_comment = $tmp[1];
|
||||
|
||||
$str .= "(";
|
||||
for ($i=0; $i<count($s); $i++) {
|
||||
$s_cnt = count($s);
|
||||
$field_cnt = count($field);
|
||||
for ($i=0; $i<$s_cnt; $i++) {
|
||||
// 검색어
|
||||
$search_str = trim($s[$i]);
|
||||
if ($search_str == "") continue;
|
||||
@@ -752,7 +814,7 @@ function get_sql_search($search_ca_name, $search_field, $search_text, $search_op
|
||||
$str .= "(";
|
||||
|
||||
$op2 = "";
|
||||
for ($k=0; $k<count($field); $k++) { // 필드의 수만큼 다중 필드 검색 가능 (필드1+필드2...)
|
||||
for ($k=0; $k<$field_cnt; $k++) { // 필드의 수만큼 다중 필드 검색 가능 (필드1+필드2...)
|
||||
|
||||
// SQL Injection 방지
|
||||
// 필드값에 a-z A-Z 0-9 _ , | 이외의 값이 있다면 검색필드를 wr_subject 로 설정한다.
|
||||
@@ -997,7 +1059,8 @@ function get_category_option($bo_table='', $ca_name='')
|
||||
|
||||
$categories = explode("|", $board['bo_category_list'].($is_admin?"|공지":"")); // 구분자가 | 로 되어 있음
|
||||
$str = "";
|
||||
for ($i=0; $i<count($categories); $i++) {
|
||||
$categories_cnt = count($categories);
|
||||
for ($i=0; $i<$categories_cnt; $i++) {
|
||||
$category = trim($categories[$i]);
|
||||
if (!$category) continue;
|
||||
|
||||
@@ -1083,16 +1146,24 @@ function insert_point($mb_id, $point, $content='', $rel_table='', $rel_id='', $r
|
||||
$mb_point = get_point_sum($mb_id);
|
||||
|
||||
// 이미 등록된 내역이라면 건너뜀
|
||||
// 레이스 컨디션 방지: MyISAM은 트랜잭션을 지원하지 않으므로 MySQL named lock(GET_LOCK)으로
|
||||
// 검증/INSERT 구간을 직렬화한다. rel 키가 없는 일반 포인트 지급은 락 대상이 아니다.
|
||||
$point_lock_name = '';
|
||||
if ($rel_table || $rel_id || $rel_action)
|
||||
{
|
||||
$point_lock_name = 'g5pt_' . md5($mb_id.'|'.$rel_table.'|'.$rel_id.'|'.$rel_action);
|
||||
sql_fetch(" select get_lock('$point_lock_name', 5) as got_lock ");
|
||||
|
||||
$sql = " select count(*) as cnt from {$g5['point_table']}
|
||||
where mb_id = '$mb_id'
|
||||
and po_rel_table = '$rel_table'
|
||||
and po_rel_id = '$rel_id'
|
||||
and po_rel_action = '$rel_action' ";
|
||||
$row = sql_fetch($sql);
|
||||
if ($row['cnt'])
|
||||
if ($row['cnt']) {
|
||||
sql_query(" select release_lock('$point_lock_name') ");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// 포인트 건별 생성
|
||||
@@ -1134,6 +1205,11 @@ function insert_point($mb_id, $point, $content='', $rel_table='', $rel_id='', $r
|
||||
$sql = " update {$g5['member_table']} set mb_point = '$po_mb_point' where mb_id = '$mb_id' ";
|
||||
sql_query($sql);
|
||||
|
||||
// named lock 해제
|
||||
if ($point_lock_name) {
|
||||
sql_query(" select release_lock('$point_lock_name') ");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1141,43 +1217,71 @@ function insert_point($mb_id, $point, $content='', $rel_table='', $rel_id='', $r
|
||||
function insert_use_point($mb_id, $point, $po_id='')
|
||||
{
|
||||
global $g5, $config;
|
||||
|
||||
|
||||
if ($replace_insert = run_replace('insert_use_point_before', '', $mb_id, $point, $po_id)) {
|
||||
return $replace_insert;
|
||||
}
|
||||
|
||||
|
||||
// 레이스 컨디션 방지: 매 단계마다 가장 오래된 행 1개를 SELECT한 후
|
||||
// WHERE 절에 사전 검증 조건을 포함한 원자적 UPDATE로 차감한다.
|
||||
// affected_rows로 성공/실패를 판별하고 실패 시 재시도하므로 락 없이 무결성 보장.
|
||||
// (MyISAM/InnoDB 모두 호환, FOR UPDATE 불필요)
|
||||
if($config['cf_point_term'])
|
||||
$sql_order = " order by po_expire_date asc, po_id asc ";
|
||||
else
|
||||
$sql_order = " order by po_id asc ";
|
||||
|
||||
$point1 = abs($point);
|
||||
$sql = " select po_id, po_point, po_use_point
|
||||
from {$g5['point_table']}
|
||||
where mb_id = '$mb_id'
|
||||
and po_id <> '$po_id'
|
||||
and po_expired = '0'
|
||||
and po_point > po_use_point
|
||||
$sql_order ";
|
||||
$result = sql_query($sql);
|
||||
for($i=0; $row=sql_fetch_array($result); $i++) {
|
||||
$point2 = $row['po_point'];
|
||||
$point3 = $row['po_use_point'];
|
||||
$remaining = abs($point);
|
||||
$max_iter = 1000; // 무한루프 안전장치 (정상 케이스는 차감 행 수만큼만 반복)
|
||||
|
||||
if(($point2 - $point3) > $point1) {
|
||||
while ($remaining > 0 && $max_iter-- > 0) {
|
||||
// 사용 가능한 가장 오래된 행 1개 조회
|
||||
$sql = " select po_id, po_point, po_use_point
|
||||
from {$g5['point_table']}
|
||||
where mb_id = '$mb_id'
|
||||
and po_id <> '$po_id'
|
||||
and po_expired = '0'
|
||||
and po_point > po_use_point
|
||||
$sql_order
|
||||
limit 1 ";
|
||||
$row = sql_fetch($sql);
|
||||
if (!$row || empty($row['po_id'])) {
|
||||
break; // 더 이상 사용 가능한 포인트 없음
|
||||
}
|
||||
|
||||
$available = $row['po_point'] - $row['po_use_point'];
|
||||
|
||||
if ($available > $remaining) {
|
||||
// 이 행만으로 충분 (부분 차감)
|
||||
// WHERE 절에서 "현재도 충분한 잔여가 있는가"를 원자적으로 재검증
|
||||
$sql = " update {$g5['point_table']}
|
||||
set po_use_point = po_use_point + '$point1'
|
||||
where po_id = '{$row['po_id']}' ";
|
||||
set po_use_point = po_use_point + '$remaining'
|
||||
where po_id = '{$row['po_id']}'
|
||||
and po_expired = '0'
|
||||
and (po_point - po_use_point) > '$remaining' ";
|
||||
sql_query($sql);
|
||||
break;
|
||||
|
||||
if (get_sql_affected_rows() > 0) {
|
||||
$remaining = 0;
|
||||
break;
|
||||
}
|
||||
// 0건 = 다른 프로세스가 이 행을 먼저 차감 → 다시 SELECT로 재시도
|
||||
} else {
|
||||
$point4 = $point2 - $point3;
|
||||
// 이 행을 완전 소진 + expired 마킹
|
||||
// WHERE 절에서 SELECT 시점의 po_use_point 값과 일치할 때만 UPDATE
|
||||
$consume = $available;
|
||||
$sql = " update {$g5['point_table']}
|
||||
set po_use_point = po_use_point + '$point4',
|
||||
set po_use_point = po_use_point + '$consume',
|
||||
po_expired = '100'
|
||||
where po_id = '{$row['po_id']}' ";
|
||||
where po_id = '{$row['po_id']}'
|
||||
and po_use_point = '{$row['po_use_point']}'
|
||||
and po_expired = '0' ";
|
||||
sql_query($sql);
|
||||
$point1 -= $point4;
|
||||
|
||||
if (get_sql_affected_rows() > 0) {
|
||||
$remaining -= $consume;
|
||||
}
|
||||
// 0건 = 다른 프로세스가 이 행을 먼저 변경 → 다시 SELECT로 재시도
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1187,41 +1291,68 @@ function delete_use_point($mb_id, $point)
|
||||
{
|
||||
global $g5, $config;
|
||||
|
||||
// 레이스 컨디션 방지: 매 단계마다 사용된 가장 최근 행 1개를 조회한 후
|
||||
// WHERE 절에 SELECT 시점의 상태를 검증하는 원자적 UPDATE로 환원한다.
|
||||
if($config['cf_point_term'])
|
||||
$sql_order = " order by po_expire_date desc, po_id desc ";
|
||||
else
|
||||
$sql_order = " order by po_id desc ";
|
||||
|
||||
$point1 = abs($point);
|
||||
$sql = " select po_id, po_use_point, po_expired, po_expire_date
|
||||
from {$g5['point_table']}
|
||||
where mb_id = '$mb_id'
|
||||
and po_expired <> '1'
|
||||
and po_use_point > 0
|
||||
$sql_order ";
|
||||
$result = sql_query($sql);
|
||||
for($i=0; $row=sql_fetch_array($result); $i++) {
|
||||
$point2 = $row['po_use_point'];
|
||||
$remaining = abs($point);
|
||||
$max_iter = 1000;
|
||||
|
||||
$po_expired = $row['po_expired'];
|
||||
if($row['po_expired'] == 100 && ($row['po_expire_date'] == '9999-12-31' || $row['po_expire_date'] >= G5_TIME_YMD))
|
||||
$po_expired = 0;
|
||||
|
||||
if($point2 > $point1) {
|
||||
$sql = " update {$g5['point_table']}
|
||||
set po_use_point = po_use_point - '$point1',
|
||||
po_expired = '$po_expired'
|
||||
where po_id = '{$row['po_id']}' ";
|
||||
sql_query($sql);
|
||||
while ($remaining > 0 && $max_iter-- > 0) {
|
||||
// 사용분이 있는 가장 최근 행 1개 조회
|
||||
$sql = " select po_id, po_use_point, po_expired, po_expire_date
|
||||
from {$g5['point_table']}
|
||||
where mb_id = '$mb_id'
|
||||
and po_expired <> '1'
|
||||
and po_use_point > 0
|
||||
$sql_order
|
||||
limit 1 ";
|
||||
$row = sql_fetch($sql);
|
||||
if (!$row || empty($row['po_id'])) {
|
||||
break;
|
||||
}
|
||||
|
||||
$row_used = $row['po_use_point'];
|
||||
|
||||
// 만료 마커(100) 복구 여부 결정
|
||||
$po_expired_new = $row['po_expired'];
|
||||
if ($row['po_expired'] == 100 && ($row['po_expire_date'] == '9999-12-31' || $row['po_expire_date'] >= G5_TIME_YMD))
|
||||
$po_expired_new = 0;
|
||||
|
||||
if ($row_used > $remaining) {
|
||||
// 부분 환원
|
||||
// WHERE에 현재 po_use_point가 차감 가능한 수준인지와 expired 상태를 함께 검증
|
||||
$sql = " update {$g5['point_table']}
|
||||
set po_use_point = po_use_point - '$remaining',
|
||||
po_expired = '$po_expired_new'
|
||||
where po_id = '{$row['po_id']}'
|
||||
and po_use_point >= '$remaining'
|
||||
and po_expired = '{$row['po_expired']}' ";
|
||||
sql_query($sql);
|
||||
|
||||
if (get_sql_affected_rows() > 0) {
|
||||
$remaining = 0;
|
||||
break;
|
||||
}
|
||||
// 0건 = 다른 프로세스가 이 행을 먼저 변경 → 재시도
|
||||
} else {
|
||||
// 사용분 전체 환원
|
||||
$consume = $row_used;
|
||||
$sql = " update {$g5['point_table']}
|
||||
set po_use_point = '0',
|
||||
po_expired = '$po_expired'
|
||||
where po_id = '{$row['po_id']}' ";
|
||||
po_expired = '$po_expired_new'
|
||||
where po_id = '{$row['po_id']}'
|
||||
and po_use_point = '{$row['po_use_point']}'
|
||||
and po_expired = '{$row['po_expired']}' ";
|
||||
sql_query($sql);
|
||||
|
||||
$point1 -= $point2;
|
||||
if (get_sql_affected_rows() > 0) {
|
||||
$remaining -= $consume;
|
||||
}
|
||||
// 0건 = 다른 프로세스가 이 행을 먼저 변경 → 재시도
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1231,39 +1362,63 @@ function delete_expire_point($mb_id, $point)
|
||||
{
|
||||
global $g5, $config;
|
||||
|
||||
$point1 = abs($point);
|
||||
$sql = " select po_id, po_use_point, po_expired, po_expire_date
|
||||
from {$g5['point_table']}
|
||||
where mb_id = '$mb_id'
|
||||
and po_expired = '1'
|
||||
and po_point >= 0
|
||||
and po_use_point > 0
|
||||
order by po_expire_date desc, po_id desc ";
|
||||
$result = sql_query($sql);
|
||||
for($i=0; $row=sql_fetch_array($result); $i++) {
|
||||
$point2 = $row['po_use_point'];
|
||||
$po_expired = '0';
|
||||
// 레이스 컨디션 방지: 매 단계마다 소멸된 가장 최근 행 1개를 조회한 후
|
||||
// WHERE 절에 SELECT 시점의 상태를 검증하는 원자적 UPDATE로 환원한다.
|
||||
$remaining = abs($point);
|
||||
$max_iter = 1000;
|
||||
|
||||
while ($remaining > 0 && $max_iter-- > 0) {
|
||||
// 소멸 처리된 가장 최근 행 1개 조회
|
||||
$sql = " select po_id, po_use_point, po_expired, po_expire_date
|
||||
from {$g5['point_table']}
|
||||
where mb_id = '$mb_id'
|
||||
and po_expired = '1'
|
||||
and po_point >= 0
|
||||
and po_use_point > 0
|
||||
order by po_expire_date desc, po_id desc
|
||||
limit 1 ";
|
||||
$row = sql_fetch($sql);
|
||||
if (!$row || empty($row['po_id'])) {
|
||||
break;
|
||||
}
|
||||
|
||||
$row_used = $row['po_use_point'];
|
||||
$po_expire_date = '9999-12-31';
|
||||
if($config['cf_point_term'] > 0)
|
||||
if ($config['cf_point_term'] > 0)
|
||||
$po_expire_date = date('Y-m-d', strtotime('+'.($config['cf_point_term'] - 1).' days', G5_SERVER_TIME));
|
||||
|
||||
if($point2 > $point1) {
|
||||
if ($row_used > $remaining) {
|
||||
// 부분 환원
|
||||
$sql = " update {$g5['point_table']}
|
||||
set po_use_point = po_use_point - '$point1',
|
||||
po_expired = '$po_expired',
|
||||
set po_use_point = po_use_point - '$remaining',
|
||||
po_expired = '0',
|
||||
po_expire_date = '$po_expire_date'
|
||||
where po_id = '{$row['po_id']}' ";
|
||||
sql_query($sql);
|
||||
break;
|
||||
} else {
|
||||
$sql = " update {$g5['point_table']}
|
||||
set po_use_point = '0',
|
||||
po_expired = '$po_expired',
|
||||
po_expire_date = '$po_expire_date'
|
||||
where po_id = '{$row['po_id']}' ";
|
||||
where po_id = '{$row['po_id']}'
|
||||
and po_expired = '1'
|
||||
and po_use_point >= '$remaining' ";
|
||||
sql_query($sql);
|
||||
|
||||
$point1 -= $point2;
|
||||
if (get_sql_affected_rows() > 0) {
|
||||
$remaining = 0;
|
||||
break;
|
||||
}
|
||||
// 0건 = 다른 프로세스가 이 행을 먼저 변경 → 재시도
|
||||
} else {
|
||||
// 사용분 전체 환원
|
||||
$consume = $row_used;
|
||||
$sql = " update {$g5['point_table']}
|
||||
set po_use_point = '0',
|
||||
po_expired = '0',
|
||||
po_expire_date = '$po_expire_date'
|
||||
where po_id = '{$row['po_id']}'
|
||||
and po_expired = '1'
|
||||
and po_use_point = '{$row['po_use_point']}' ";
|
||||
sql_query($sql);
|
||||
|
||||
if (get_sql_affected_rows() > 0) {
|
||||
$remaining -= $consume;
|
||||
}
|
||||
// 0건 = 다른 프로세스가 이 행을 먼저 변경 → 재시도
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1612,18 +1767,27 @@ function view_link($view, $number, $attribute)
|
||||
|
||||
function cut_str($str, $len, $suffix="…")
|
||||
{
|
||||
$arr_str = preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY);
|
||||
$str_len = count($arr_str);
|
||||
|
||||
if ($str_len >= $len) {
|
||||
$slice_str = array_slice($arr_str, 0, $len);
|
||||
$str = join("", $slice_str);
|
||||
|
||||
return $str . ($str_len > $len ? $suffix : '');
|
||||
} else {
|
||||
$str = join("", $arr_str);
|
||||
// 빠른 경로: 바이트 길이가 이미 제한 이내라면 문자 수 계산 불필요
|
||||
// UTF-8의 모든 문자는 최소 1바이트이므로 bytes <= len이면 chars <= len이 보장됨
|
||||
if (strlen($str) <= $len) {
|
||||
return $str;
|
||||
}
|
||||
|
||||
// mbstring 확장 사용 (PHP 4.0.6+ 기본 내장): 문자 배열 생성 없이 길이/슬라이스 처리
|
||||
if (function_exists('mb_strlen')) {
|
||||
if (mb_strlen($str, 'UTF-8') > $len) {
|
||||
return mb_substr($str, 0, $len, 'UTF-8') . $suffix;
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
// mbstring 미설치 환경 폴백 (기존 동작 유지)
|
||||
$arr_str = preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY);
|
||||
$str_len = count($arr_str);
|
||||
if ($str_len > $len) {
|
||||
return join("", array_slice($arr_str, 0, $len)) . $suffix;
|
||||
}
|
||||
return join("", $arr_str);
|
||||
}
|
||||
|
||||
|
||||
@@ -1754,7 +1918,8 @@ function sql_query($sql, $error=G5_DISPLAY_SQL_ERROR, $link=null)
|
||||
$sql = trim($sql);
|
||||
// union의 사용을 허락하지 않습니다.
|
||||
//$sql = preg_replace("#^select.*from.*union.*#i", "select 1", $sql);
|
||||
$sql = preg_replace("#^select.*from.*[\s\(]+union[\s\)]+.*#i ", "select 1", $sql);
|
||||
//$sql = preg_replace("#^select.*from.*[\s\(]+union[\s\)]+.*#i ", "select 1", $sql);
|
||||
$sql = preg_replace("#^select.*from.*([\s\(]+union[\s\)]+|/\*.*union.*\*/).*#i", "select 1", $sql);
|
||||
// `information_schema` DB로의 접근을 허락하지 않습니다.
|
||||
$sql = preg_replace("#^select.*from.*where.*`?information_schema`?.*#i", "select 1", $sql);
|
||||
|
||||
@@ -1764,7 +1929,24 @@ function sql_query($sql, $error=G5_DISPLAY_SQL_ERROR, $link=null)
|
||||
|
||||
if(function_exists('mysqli_query') && G5_MYSQLI_USE) {
|
||||
if ($error) {
|
||||
$result = @mysqli_query($link, $sql) or die("<p>$sql<p>" . mysqli_errno($link) . " : " . mysqli_error($link) . "<p>error file : {$_SERVER['SCRIPT_NAME']}");
|
||||
$result = @mysqli_query($link, $sql);
|
||||
if (!$result) {
|
||||
$err_no = mysqli_errno($link);
|
||||
$err_msg = mysqli_error($link);
|
||||
$err_file = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '';
|
||||
|
||||
// 서버 로그에는 항상 상세 기록 (운영자가 추적 가능하도록)
|
||||
@error_log("[g5 sql_query] {$err_no}: {$err_msg} | SQL: {$sql} | file: {$err_file}");
|
||||
|
||||
if ($is_debug) {
|
||||
// 디버그 모드: 상세 표시 (XSS 방지를 위해 escape)
|
||||
die("<p>" . htmlspecialchars($sql, ENT_QUOTES, 'UTF-8')
|
||||
. "<p>" . (int)$err_no . " : " . htmlspecialchars($err_msg, ENT_QUOTES, 'UTF-8')
|
||||
. "<p>error file : " . htmlspecialchars($err_file, ENT_QUOTES, 'UTF-8'));
|
||||
}
|
||||
// 운영 환경: 일반 메시지로만 처리하여 DB 구조/경로 정보 노출 방지
|
||||
die('데이터베이스 처리 중 오류가 발생했습니다.');
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
$result = @mysqli_query($link, $sql);
|
||||
@@ -1774,7 +1956,21 @@ function sql_query($sql, $error=G5_DISPLAY_SQL_ERROR, $link=null)
|
||||
}
|
||||
} else {
|
||||
if ($error) {
|
||||
$result = @mysql_query($sql, $link) or die("<p>$sql<p>" . mysql_errno() . " : " . mysql_error() . "<p>error file : {$_SERVER['SCRIPT_NAME']}");
|
||||
$result = @mysql_query($sql, $link);
|
||||
if (!$result) {
|
||||
$err_no = mysql_errno();
|
||||
$err_msg = mysql_error();
|
||||
$err_file = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '';
|
||||
|
||||
@error_log("[g5 sql_query] {$err_no}: {$err_msg} | SQL: {$sql} | file: {$err_file}");
|
||||
|
||||
if ($is_debug) {
|
||||
die("<p>" . htmlspecialchars($sql, ENT_QUOTES, 'UTF-8')
|
||||
. "<p>" . (int)$err_no . " : " . htmlspecialchars($err_msg, ENT_QUOTES, 'UTF-8')
|
||||
. "<p>error file : " . htmlspecialchars($err_file, ENT_QUOTES, 'UTF-8'));
|
||||
}
|
||||
die('데이터베이스 처리 중 오류가 발생했습니다.');
|
||||
}
|
||||
} else {
|
||||
$result = @mysql_query($sql, $link);
|
||||
}
|
||||
@@ -2314,24 +2510,192 @@ function _callback_normalizeString($matches){
|
||||
// 토큰 생성
|
||||
function _token()
|
||||
{
|
||||
return md5(uniqid(rand(), true));
|
||||
return get_random_token_string(16);
|
||||
}
|
||||
|
||||
|
||||
// 불법접근을 막도록 토큰을 생성하면서 토큰값을 리턴
|
||||
// HMAC 기반 — 세션 내부 비밀값 사용, 타임스탬프 포함, 다중 탭 호환
|
||||
// 토큰 형식: 타임스탬프.HMAC
|
||||
function get_token()
|
||||
{
|
||||
$token = md5(uniqid(rand(), true));
|
||||
set_session('ss_token', $token);
|
||||
$key = _get_token_key();
|
||||
$secret = _get_token_secret();
|
||||
$time = time();
|
||||
|
||||
return $token;
|
||||
$hmac = hash_hmac('sha256', $secret . '|csrf_token|' . $time, $key);
|
||||
|
||||
return $time . '.' . $hmac;
|
||||
}
|
||||
|
||||
|
||||
// POST로 넘어온 토큰과 세션에 저장된 토큰 비교
|
||||
function check_token()
|
||||
// POST로 넘어온 토큰의 HMAC 및 만료 시간 검증
|
||||
// 기본 만료: 7200초(2시간)
|
||||
function check_token($expire = 7200)
|
||||
{
|
||||
set_session('ss_token', '');
|
||||
$token = isset($_POST['token']) ? $_POST['token'] : '';
|
||||
|
||||
$dot = strpos($token, '.');
|
||||
if (!$token || $dot === false) {
|
||||
alert('올바른 방법으로 이용해 주십시오.');
|
||||
return false;
|
||||
}
|
||||
|
||||
$time = (int)substr($token, 0, $dot);
|
||||
$hmac = substr($token, $dot + 1);
|
||||
|
||||
// 만료 검증
|
||||
if (abs(time() - $time) > $expire) {
|
||||
alert('토큰이 만료되었습니다. 페이지를 새로고침 해주십시오.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// HMAC 검증
|
||||
$key = _get_token_key();
|
||||
$secret = _get_token_secret();
|
||||
$expected = hash_hmac('sha256', $secret . '|csrf_token|' . $time, $key);
|
||||
|
||||
if ($hmac !== $expected) {
|
||||
alert('올바른 방법으로 이용해 주십시오.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// 토큰 암호화 키 반환 (내부용)
|
||||
function _get_token_key()
|
||||
{
|
||||
return (defined('G5_TOKEN_ENCRYPTION_KEY') && G5_TOKEN_ENCRYPTION_KEY)
|
||||
? G5_TOKEN_ENCRYPTION_KEY
|
||||
: (defined('G5_TABLE_PREFIX') ? G5_TABLE_PREFIX : '');
|
||||
}
|
||||
|
||||
|
||||
// 세션 내부 비밀값 반환 (내부용, 서버측에만 존재)
|
||||
function _get_token_secret()
|
||||
{
|
||||
$secret = get_session('ss_token_secret');
|
||||
if (!$secret) {
|
||||
$secret = get_random_token_string(16);
|
||||
set_session('ss_token_secret', $secret);
|
||||
}
|
||||
return $secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 세션 기반 단순 Rate Limit. 자동화 도구의 무차별 호출을 늦추기 위한 용도.
|
||||
*
|
||||
* 같은 키에 대해 $window 초 동안 $max 회까지만 허용. 초과 시 false 반환.
|
||||
* 세션 쿠키를 무시하는 정교한 봇은 우회 가능하지만, 세션 생성 비용으로 attack rate가 떨어지고
|
||||
* 가장 흔한 form-only enumeration 시나리오는 효과적으로 차단된다.
|
||||
*
|
||||
* @param string $key 레이트 리밋 식별자 (예: 'ajax_mb_id_check')
|
||||
* @param int $max 윈도우당 최대 허용 횟수
|
||||
* @param int $window 윈도우 크기 (초)
|
||||
* @return bool true = 허용, false = 차단
|
||||
*/
|
||||
function check_rate_limit($key, $max = 30, $window = 60)
|
||||
{
|
||||
$session_key = 'ss_rate_' . $key;
|
||||
$now = time();
|
||||
|
||||
$data = get_session($session_key);
|
||||
if (!is_array($data) || !isset($data['reset']) || $data['reset'] < $now) {
|
||||
$data = array('count' => 0, 'reset' => $now + $window);
|
||||
}
|
||||
|
||||
$data['count']++;
|
||||
set_session($session_key, $data);
|
||||
|
||||
return $data['count'] <= $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* 이메일 미인증 회원의 메일주소 변경 페이지 접근 토큰을 생성한다.
|
||||
*
|
||||
* HMAC-SHA256 + 서버 시크릿(G5_TOKEN_ENCRYPTION_KEY)
|
||||
* @param string $mb_id
|
||||
* @param string $mb_datetime
|
||||
* @return string 64자 hex
|
||||
*/
|
||||
function get_email_cert_key($mb_id, $mb_datetime)
|
||||
{
|
||||
$key = (defined('G5_TOKEN_ENCRYPTION_KEY') && G5_TOKEN_ENCRYPTION_KEY)
|
||||
? G5_TOKEN_ENCRYPTION_KEY
|
||||
: (defined('G5_TABLE_PREFIX') ? G5_TABLE_PREFIX : '');
|
||||
|
||||
$payload = 'email_cert|' . $mb_id . '|' . $mb_datetime;
|
||||
|
||||
return hash_hmac('sha256', $payload, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* CSRF 방지용 Origin/Referer 검증 (OWASP 권장 패턴).
|
||||
*
|
||||
* 브라우저가 자동으로 보내는 Origin 헤더를 우선 확인하고, 없으면 Referer를 사용해
|
||||
* 요청이 현재 사이트에서 발생했는지 검증한다. 크로스 오리진에서 유입된 요청은
|
||||
* 두 헤더 모두 공격자가 제어할 수 없으므로 위조가 불가능하다.
|
||||
*
|
||||
* 폼 파일(스킨) 수정 없이 처리 파일에만 호출을 추가하면 되므로 적용 범위가 넓고
|
||||
* 커스텀 테마 호환성에 영향이 없다.
|
||||
*
|
||||
* 특수 환경(프록시 등)에서 헤더가 유실되는 경우 G5_DISABLE_ORIGIN_CHECK 상수로
|
||||
* 비활성화할 수 있다.
|
||||
*
|
||||
* @param string $redirect_url 검증 실패 시 리다이렉트할 URL (기본: G5_URL)
|
||||
* @return bool
|
||||
*/
|
||||
function check_request_origin($redirect_url = '')
|
||||
{
|
||||
// 환경에 따라 opt-out 가능
|
||||
if (defined('G5_DISABLE_ORIGIN_CHECK') && G5_DISABLE_ORIGIN_CHECK) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// GET 요청은 검증하지 않음 (CSRF는 상태 변경 요청에만 의미 있음)
|
||||
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '';
|
||||
if ($method === 'GET' || $method === 'HEAD') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$redirect_url) {
|
||||
$redirect_url = defined('G5_URL') ? G5_URL : '/';
|
||||
}
|
||||
|
||||
// Origin 우선, 없으면 Referer 사용
|
||||
$origin = isset($_SERVER['HTTP_ORIGIN']) ? trim($_SERVER['HTTP_ORIGIN']) : '';
|
||||
$referer = isset($_SERVER['HTTP_REFERER']) ? trim($_SERVER['HTTP_REFERER']) : '';
|
||||
$source = $origin !== '' ? $origin : $referer;
|
||||
|
||||
if ($source === '') {
|
||||
alert('올바른 경로로 접근해 주십시오.', $redirect_url);
|
||||
}
|
||||
|
||||
$source_host = @parse_url($source, PHP_URL_HOST);
|
||||
if (!$source_host) {
|
||||
alert('올바른 경로로 접근해 주십시오.', $redirect_url);
|
||||
}
|
||||
|
||||
// config.php의 G5_URL에서 호스트 추출 (HTTP_HOST보다 신뢰할 수 있음)
|
||||
$server_host = defined('G5_URL') ? @parse_url(G5_URL, PHP_URL_HOST) : '';
|
||||
if (!$server_host) {
|
||||
$server_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
|
||||
$colon = strpos($server_host, ':');
|
||||
if ($colon !== false) {
|
||||
$server_host = substr($server_host, 0, $colon);
|
||||
}
|
||||
}
|
||||
|
||||
// www. 접두사 제거하여 비교 (www.example.com == example.com)
|
||||
$source_host = preg_replace('/^www\./i', '', $source_host);
|
||||
$server_host = preg_replace('/^www\./i', '', $server_host);
|
||||
|
||||
if (!$server_host || strcasecmp($source_host, $server_host) !== 0) {
|
||||
alert('올바른 경로로 접근해 주십시오.', $redirect_url);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2654,7 +3018,8 @@ function delete_editor_thumbnail($contents)
|
||||
if(!$matchs)
|
||||
return;
|
||||
|
||||
for($i=0; $i<count($matchs[1]); $i++) {
|
||||
$matchs_cnt = count($matchs[1]);
|
||||
for($i=0; $i<$matchs_cnt; $i++) {
|
||||
// 이미지 path 구함
|
||||
$imgurl = @parse_url($matchs[1][$i]);
|
||||
// $srcfile = dirname(G5_PATH).$imgurl['path'];
|
||||
@@ -2879,7 +3244,11 @@ class html_process {
|
||||
$tmp_sql = " select count(*) as cnt from {$g5['login_table']} where lo_ip = '{$_SERVER['REMOTE_ADDR']}' ";
|
||||
$tmp_row = sql_fetch($tmp_sql);
|
||||
$http_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
|
||||
|
||||
|
||||
if (!isset($member['mb_id'])) {
|
||||
$member['mb_id'] = '';
|
||||
}
|
||||
|
||||
if ($tmp_row['cnt']) {
|
||||
$tmp_sql = " update {$g5['login_table']} set mb_id = '{$member['mb_id']}', lo_datetime = '".G5_TIME_YMDHIS."', lo_location = '{$g5['lo_location']}', lo_url = '{$g5['lo_url']}' where lo_ip = '{$_SERVER['REMOTE_ADDR']}' ";
|
||||
sql_query($tmp_sql, FALSE);
|
||||
@@ -3269,7 +3638,8 @@ function module_exec_check($exe, $type)
|
||||
break;
|
||||
}
|
||||
|
||||
for($i=0; $i<count($out); $i++) {
|
||||
$out_cnt = count($out);
|
||||
for($i=0; $i<$out_cnt; $i++) {
|
||||
if(strpos($out[$i], 'KCP ENC') !== false) {
|
||||
$search = true;
|
||||
break;
|
||||
@@ -3284,7 +3654,8 @@ function module_exec_check($exe, $type)
|
||||
break;
|
||||
}
|
||||
|
||||
for($i=0; $i<count($out); $i++) {
|
||||
$out_cnt = count($out);
|
||||
for($i=0; $i<$out_cnt; $i++) {
|
||||
if(strpos($out[$i], 'CLIENT') !== false) {
|
||||
$search = true;
|
||||
break;
|
||||
@@ -3299,7 +3670,8 @@ function module_exec_check($exe, $type)
|
||||
break;
|
||||
}
|
||||
|
||||
for($i=0; $i<count($out); $i++) {
|
||||
$out_cnt = count($out);
|
||||
for($i=0; $i<$out_cnt; $i++) {
|
||||
if(strpos(strtolower($out[$i]), 'ret code') !== false) {
|
||||
$search = true;
|
||||
break;
|
||||
@@ -3959,10 +4331,16 @@ class str_encrypt
|
||||
|
||||
function __construct($salt='')
|
||||
{
|
||||
if(!$salt)
|
||||
$this->salt = md5(preg_replace('/[^0-9A-Za-z]/', substr(G5_MYSQL_USER, -1), $_SERVER['SERVER_SOFTWARE'].$_SERVER['DOCUMENT_ROOT']));
|
||||
else
|
||||
global $config;
|
||||
|
||||
if (!$salt) {
|
||||
$config_hash = md5(serialize(array($config['cf_title'], $config['cf_theme'], $config['cf_admin_email_name'], $config['cf_login_point'], $config['cf_memo_send_point'])));
|
||||
|
||||
//$this->salt = md5(preg_replace('/[^0-9A-Za-z]/', substr($config_hash, -1), $_SERVER['SERVER_SOFTWARE'].$config_hash.$_SERVER['DOCUMENT_ROOT']));
|
||||
$this->salt = hash('sha256', preg_replace('/[^0-9A-Za-z]/', substr($config_hash, -1), $_SERVER['SERVER_SOFTWARE'].$config_hash.$_SERVER['DOCUMENT_ROOT']));
|
||||
} else {
|
||||
$this->salt = $salt;
|
||||
}
|
||||
|
||||
$this->length = strlen($this->salt);
|
||||
}
|
||||
@@ -3998,10 +4376,26 @@ class str_encrypt
|
||||
}
|
||||
}
|
||||
|
||||
// 26년도에 너무 늦게 만들어서 기존의 사용자들과 충돌을 피하기 위해 get_sql_affected_rows 이라 네이밍함
|
||||
function get_sql_affected_rows($link=null)
|
||||
{
|
||||
global $g5;
|
||||
|
||||
if (!$link) {
|
||||
$link = $g5['connect_db'];
|
||||
}
|
||||
|
||||
if (function_exists('mysqli_affected_rows') && G5_MYSQLI_USE) {
|
||||
return @mysqli_affected_rows($link);
|
||||
} else {
|
||||
return @mysql_affected_rows($link);
|
||||
}
|
||||
}
|
||||
|
||||
// 불법접근을 막도록 토큰을 생성하면서 토큰값을 리턴
|
||||
function get_write_token($bo_table)
|
||||
{
|
||||
$token = md5(uniqid(rand(), true));
|
||||
$token = get_random_token_string(16);
|
||||
set_session('ss_write_'.$bo_table.'_token', $token);
|
||||
|
||||
return $token;
|
||||
@@ -4304,10 +4698,49 @@ function get_token_encryption_key($str=''){
|
||||
|
||||
function get_random_token_string($length=6)
|
||||
{
|
||||
if(function_exists('random_bytes')){
|
||||
return bin2hex(random_bytes($length));
|
||||
// 사용 가능한 가장 안전한 CSPRNG를 우선순위대로 시도하여 $length 바이트의 무작위 값을 얻는다.
|
||||
// PHP 5.2.17 ~ 8.x 호환. 모든 단계는 function_exists/defined로 가드되어 구버전에서도 안전.
|
||||
$bytes = false;
|
||||
|
||||
// 1순위. PHP 7.0+ : random_bytes() — OS의 CSPRNG 직접 사용 (가장 안전)
|
||||
if (function_exists('random_bytes')) {
|
||||
$bytes = random_bytes($length);
|
||||
}
|
||||
// 2순위. PHP 5.3+ : openssl_random_pseudo_bytes() — OpenSSL 확장이 있으면 사용
|
||||
elseif (function_exists('openssl_random_pseudo_bytes')) {
|
||||
$strong = false;
|
||||
$tmp = openssl_random_pseudo_bytes($length, $strong);
|
||||
if ($tmp !== false && $strong === true) {
|
||||
$bytes = $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// 3순위. Linux/Unix : /dev/urandom 직접 읽기 (PHP 5.2 호환, OS 차원의 CSPRNG)
|
||||
if ($bytes === false && DIRECTORY_SEPARATOR === '/' && @is_readable('/dev/urandom')) {
|
||||
$fp = @fopen('/dev/urandom', 'rb');
|
||||
if ($fp !== false) {
|
||||
$tmp = @fread($fp, $length);
|
||||
@fclose($fp);
|
||||
if ($tmp !== false && strlen($tmp) === $length) {
|
||||
$bytes = $tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4순위. mcrypt 확장 (PHP 5.2 호환, PHP 7.2에서 제거됨) — Windows 등에서 fallback
|
||||
if ($bytes === false && function_exists('mcrypt_create_iv') && defined('MCRYPT_DEV_URANDOM')) {
|
||||
$tmp = @mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
|
||||
if ($tmp !== false && strlen($tmp) === $length) {
|
||||
$bytes = $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if ($bytes !== false) {
|
||||
return bin2hex($bytes);
|
||||
}
|
||||
|
||||
// 최후 수단: 약한 RNG (암호학적 안전성 없음, 기존 동작 호환을 위해 유지)
|
||||
// 이 경로에 도달하면 시스템에 안전한 난수 소스가 전혀 없는 비정상 환경이므로 점검 필요.
|
||||
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||
$output = substr(str_shuffle($characters), 0, $length);
|
||||
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ function latest($skin_dir='', $bo_table='', $rows=10, $subject_len=40, $cache_ti
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
$row['wr_email'] = ''; //이메일 저장 안함
|
||||
if (strstr($row['wr_option'], 'secret')){ // 비밀글일 경우 내용, 링크, 파일 저장 안함
|
||||
if (strpos($row['wr_option'], 'secret') !== false){ // 비밀글일 경우 내용, 링크, 파일 저장 안함
|
||||
$row['wr_content'] = $row['wr_link1'] = $row['wr_link2'] = '';
|
||||
$row['file'] = array('count'=>0);
|
||||
}
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@ include_once(G5_PHPMAILER_PATH.'/PHPMailerAutoload.php');
|
||||
|
||||
// 메일 보내기 (파일 여러개 첨부 가능)
|
||||
// type : text=0, html=1, text+html=2
|
||||
function mailer($fname, $fmail, $to, $subject, $content, $type=0, $file="", $cc="", $bcc="")
|
||||
function mailer($fname, $fmail, $to, $subject, $content, $type=0, $file="", $cc="", $bcc="", $reply_to="")
|
||||
{
|
||||
global $config;
|
||||
global $g5;
|
||||
@@ -43,6 +43,8 @@ function mailer($fname, $fmail, $to, $subject, $content, $type=0, $file="", $cc=
|
||||
$mail->addCC($cc);
|
||||
if ($bcc)
|
||||
$mail->addBCC($bcc);
|
||||
if ($reply_to)
|
||||
$mail->addReplyTo($reply_to);
|
||||
//print_r2($file); exit;
|
||||
if ($file != "") {
|
||||
foreach ($file as $f) {
|
||||
|
||||
@@ -89,7 +89,8 @@ class naverpay_register
|
||||
$send_cost_limit = explode(";", $default['de_send_cost_limit']);
|
||||
$send_cost_list = explode(";", $default['de_send_cost_list']);
|
||||
|
||||
for ($k=0; $k<count($send_cost_limit); $k++) {
|
||||
$send_cost_limit_cnt = count($send_cost_limit);
|
||||
for ($k=0; $k<$send_cost_limit_cnt; $k++) {
|
||||
// 총판매금액이 배송비 상한가 보다 작다면
|
||||
if ($total_price < preg_replace('/[^0-9]/', '', $send_cost_limit[$k])) {
|
||||
$diff_cost = preg_replace('/[^0-9]/', '', $send_cost_list[$k]);
|
||||
|
||||
+135
-13
@@ -3,6 +3,79 @@
|
||||
// 쇼핑몰 라이브러리 모음 시작
|
||||
//==============================================================================
|
||||
|
||||
/**
|
||||
* 쇼핑몰 주문/개인결제 조회용 식별자(uid)를 생성한다.
|
||||
*
|
||||
* 결정적(deterministic) 생성 방식은 유지되므로 여러 파일에서 독립적으로 호출해도
|
||||
* 동일한 값을 얻을 수 있어 기존 검증 구조를 그대로 사용 가능하다.
|
||||
*
|
||||
* @param string $type 'order' 또는 'personalpay' 등 네임스페이스 구분자
|
||||
* @param string $id 주문번호 / 개인결제번호 등
|
||||
* @param string $time 생성 시각 (od_time / pp_time)
|
||||
* @param string $ip 생성 시 IP (od_ip / pp_ip)
|
||||
* @return string 64자 hex
|
||||
*/
|
||||
function get_shop_uid($type, $id, $time, $ip)
|
||||
{
|
||||
$key = (defined('G5_TOKEN_ENCRYPTION_KEY') && G5_TOKEN_ENCRYPTION_KEY)
|
||||
? G5_TOKEN_ENCRYPTION_KEY
|
||||
: (defined('G5_TABLE_PREFIX') ? G5_TABLE_PREFIX : '');
|
||||
|
||||
$payload = $type . '|' . $id . '|' . $time . '|' . $ip;
|
||||
|
||||
return hash_hmac('sha256', $payload, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 현금영수증 발급 또는 조회에 대한 검증
|
||||
*
|
||||
* 다음 셋 중 하나여야 접근 허용:
|
||||
* 1. 관리자
|
||||
* 2. 본인 주문/개인결제 (로그인 회원이고 mb_id 일치)
|
||||
* 3. 비회원이지만 정당한 세션 uid 보유 (orderinquiry.php에서 비밀번호 검증 통과 후
|
||||
* 또는 주문 완료 직후 세션에 저장된 ss_orderview_uid / ss_personalpay_uid가
|
||||
* 현재 주문/개인결제의 HMAC uid와 일치)
|
||||
*
|
||||
* @param array $od 주문 또는 개인결제 행 (DB에서 fetch한 결과)
|
||||
* @param string $type 'order' (g5_shop_order) 또는 'personalpay' (g5_shop_personalpay)
|
||||
* @return bool
|
||||
*/
|
||||
function is_shop_order_owner($od, $type = 'order')
|
||||
{
|
||||
global $is_admin, $is_member, $member;
|
||||
|
||||
if (!is_array($od)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 관리자
|
||||
if ($is_admin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 본인 주문/개인결제 (로그인 회원)
|
||||
if ($is_member && isset($od['mb_id']) && $od['mb_id'] !== '' && $od['mb_id'] === $member['mb_id']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 세션 uid 검증
|
||||
if ($type === 'personalpay') {
|
||||
if (empty($od['pp_id'])) {
|
||||
return false;
|
||||
}
|
||||
$expected = get_shop_uid('personalpay', $od['pp_id'], $od['pp_time'], $_SERVER['REMOTE_ADDR']);
|
||||
$session_uid = get_session('ss_personalpay_uid');
|
||||
} else {
|
||||
if (empty($od['od_id'])) {
|
||||
return false;
|
||||
}
|
||||
$expected = get_shop_uid('order', $od['od_id'], $od['od_time'], $od['od_ip']);
|
||||
$session_uid = get_session('ss_orderview_uid');
|
||||
}
|
||||
|
||||
return ($session_uid !== '' && $expected === $session_uid);
|
||||
}
|
||||
|
||||
/*
|
||||
간편 사용법 : 상품유형을 1~5 사이로 지정합니다.
|
||||
$disp = new item_list(1);
|
||||
@@ -1796,7 +1869,8 @@ function get_sendcost($cart_id, $selected=1)
|
||||
$send_cost_limit = explode(";", $default['de_send_cost_limit']);
|
||||
$send_cost_list = explode(";", $default['de_send_cost_list']);
|
||||
$send_cost = 0;
|
||||
for ($k=0; $k<count($send_cost_limit); $k++) {
|
||||
$send_cost_limit_cnt = count($send_cost_limit);
|
||||
for ($k=0; $k<$send_cost_limit_cnt; $k++) {
|
||||
// 총판매금액이 배송비 상한가 보다 작다면
|
||||
if ($total_price < preg_replace('/[^0-9]/', '', $send_cost_limit[$k])) {
|
||||
$send_cost = preg_replace('/[^0-9]/', '', $send_cost_list[$k]);
|
||||
@@ -1871,7 +1945,8 @@ function get_item_sendcost2($it_id, $price, $qty)
|
||||
$send_cost_limit = explode(";", $default['de_send_cost_limit']);
|
||||
$send_cost_list = explode(";", $default['de_send_cost_list']);
|
||||
|
||||
for ($k=0; $k<count($send_cost_limit); $k++) {
|
||||
$send_cost_limit_cnt = count($send_cost_limit);
|
||||
for ($k=0; $k<$send_cost_limit_cnt; $k++) {
|
||||
// 총판매금액이 배송비 상한가 보다 작다면
|
||||
if ($price < preg_replace('/[^0-9]/', '', $send_cost_limit[$k])) {
|
||||
$sendcost = preg_replace('/[^0-9]/', '', $send_cost_list[$k]);
|
||||
@@ -2111,8 +2186,9 @@ function get_delivery_inquiry($company, $invoice, $class='')
|
||||
|
||||
$dlcomp = explode(")", str_replace("(", "", G5_DELIVERY_COMPANY));
|
||||
|
||||
for($i=0; $i<count($dlcomp); $i++) {
|
||||
if(strstr($dlcomp[$i], $company)) {
|
||||
$dlcomp_cnt = count($dlcomp);
|
||||
for($i=0; $i<$dlcomp_cnt; $i++) {
|
||||
if(strpos($dlcomp[$i], $company) !== false) {
|
||||
list($com, $url, $tel) = explode("^", $dlcomp[$i]);
|
||||
break;
|
||||
}
|
||||
@@ -2327,12 +2403,12 @@ function exists_inicis_shop_order($oid, $pp=array(), $od_time='', $od_ip='')
|
||||
//개인결제
|
||||
if( $pp ) {
|
||||
$hash_data = md5($pp['pp_id'].$pp['pp_price'].$pp['pp_time']);
|
||||
if( $hash_data == get_session('ss_personalpay_hash') ){
|
||||
if( $hash_data === get_session('ss_personalpay_hash') ){
|
||||
// 개인결제번호제거
|
||||
set_session('ss_personalpay_id', '');
|
||||
set_session('ss_personalpay_hash', '');
|
||||
|
||||
$uid = md5($pp['pp_id'].$pp['pp_time'].$od_ip);
|
||||
$uid = get_shop_uid('personalpay', $pp['pp_id'], $pp['pp_time'], $od_ip);
|
||||
set_session('ss_personalpay_uid', $uid);
|
||||
|
||||
goto_url(G5_SHOP_URL.'/personalpayresult.php?pp_id='.$pp['pp_id'].'&uid='.$uid.'&ini_noti=1');
|
||||
@@ -2346,7 +2422,7 @@ function exists_inicis_shop_order($oid, $pp=array(), $od_time='', $od_ip='')
|
||||
|
||||
if( $oid == get_session('ss_order_id') ){
|
||||
// orderview 에서 사용하기 위해 session에 넣고
|
||||
$uid = md5($oid.$od_time.$od_ip);
|
||||
$uid = get_shop_uid('order', $oid, $od_time, $od_ip);
|
||||
set_session('ss_orderview_uid', $uid);
|
||||
goto_url(G5_SHOP_URL.'/orderinquiryview.php?od_id='.$oid.'&uid='.$uid.'&ini_noti=1');
|
||||
} else {
|
||||
@@ -2388,7 +2464,8 @@ function get_delivery_company($company)
|
||||
$option .= '<option value="자체배송" '.get_selected($company, '자체배송').'>자체배송</option>'.PHP_EOL;
|
||||
|
||||
$dlcomp = explode(")", str_replace("(", "", G5_DELIVERY_COMPANY));
|
||||
for ($i=0; $i<count($dlcomp); $i++) {
|
||||
$dlcomp_cnt = count($dlcomp);
|
||||
for ($i=0; $i<$dlcomp_cnt; $i++) {
|
||||
if (trim($dlcomp[$i])=="") continue;
|
||||
list($value, $url, $tel) = explode("^", $dlcomp[$i]);
|
||||
$option .= '<option value="'.$value.'" '.get_selected($company, $value).'>'.$value.'</option>'.PHP_EOL;
|
||||
@@ -2406,7 +2483,8 @@ function get_itemuse_thumb($contents, $thumb_width, $thumb_height, $is_create=fa
|
||||
|
||||
$matches = get_editor_image($contents, false);
|
||||
|
||||
for($i=0; $i<count($matches[1]); $i++)
|
||||
$matches_cnt = count($matches[1]);
|
||||
for($i=0; $i<$matches_cnt; $i++)
|
||||
{
|
||||
// 이미지 path 구함
|
||||
$p = parse_url($matches[1][$i]);
|
||||
@@ -2461,7 +2539,7 @@ function get_itemuselist_thumbnail($it_id, $contents, $thumb_width, $thumb_heigh
|
||||
}
|
||||
|
||||
function shop_is_taxsave($od, $is_view_receipt=false){
|
||||
global $default, $is_memeber;
|
||||
global $default, $is_member;
|
||||
|
||||
$od_pay_type = '';
|
||||
|
||||
@@ -2474,12 +2552,12 @@ function shop_is_taxsave($od, $is_view_receipt=false){
|
||||
}
|
||||
|
||||
if( $od_pay_type ) {
|
||||
if( $default['de_taxsave_use'] && strstr( $default['de_taxsave_types'], $od_pay_type ) ){
|
||||
if( $default['de_taxsave_use'] && strpos( $default['de_taxsave_types'], $od_pay_type ) !== false ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// 아직 현금영수증 받기전 상태일때만
|
||||
if( $is_view_receipt && ! $od['od_cash'] && in_array($od['od_settle_case'], array('계좌이체', '가상계좌')) && ! strstr( $default['de_taxsave_types'], $od_pay_type ) ){
|
||||
if( $is_view_receipt && ! $od['od_cash'] && in_array($od['od_settle_case'], array('계좌이체', '가상계좌')) && strpos( $default['de_taxsave_types'], $od_pay_type ) === false ){
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
@@ -2770,6 +2848,50 @@ function get_item_images_info($it, $size=array(), $image_width=0, $image_height=
|
||||
return $images;
|
||||
}
|
||||
|
||||
// 카테고리 전체 경로를 가져오는 함수 (예: 남성의류 > 상의 > 셔츠)
|
||||
function get_shop_category_path($ca_id, $separator = ' > ')
|
||||
{
|
||||
global $g5;
|
||||
static $category_cache = array(); // 카테고리명 캐시
|
||||
static $path_cache = array(); // 경로 캐시
|
||||
|
||||
if (!$ca_id) return '';
|
||||
|
||||
// 동일한 separator로 이미 조회한 경로가 있으면 캐시에서 반환
|
||||
$cache_key = $ca_id . '|' . $separator;
|
||||
if (isset($path_cache[$cache_key])) {
|
||||
return $path_cache[$cache_key];
|
||||
}
|
||||
|
||||
$path_arr = array();
|
||||
$ca_id_len = strlen($ca_id);
|
||||
|
||||
// 카테고리 ID를 2자리씩 분할하여 각 단계의 카테고리명을 조회
|
||||
for ($i = 2; $i <= $ca_id_len; $i += 2) {
|
||||
$current_ca_id = substr($ca_id, 0, $i);
|
||||
|
||||
// 캐시에 없으면 DB 조회
|
||||
if (!isset($category_cache[$current_ca_id])) {
|
||||
$sql = " select ca_name from {$g5['g5_shop_category_table']} where ca_id = '$current_ca_id' ";
|
||||
$row = sql_fetch($sql);
|
||||
if ($row) {
|
||||
$category_cache[$current_ca_id] = $row['ca_name'];
|
||||
} else {
|
||||
$category_cache[$current_ca_id] = '';
|
||||
}
|
||||
}
|
||||
|
||||
if ($category_cache[$current_ca_id]) {
|
||||
$path_arr[] = $category_cache[$current_ca_id];
|
||||
}
|
||||
}
|
||||
|
||||
$result = implode($separator, $path_arr);
|
||||
$path_cache[$cache_key] = $result; // 결과를 캐시에 저장
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function check_payment_method($od_settle_case) {
|
||||
global $default;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ function get_list_thumbnail($bo_table, $wr_id, $thumb_width, $thumb_height, $is_
|
||||
$write = get_thumbnail_find_cache($bo_table, $wr_id, 'content');
|
||||
|
||||
// 비밀글이면 썸네일을 노출하지 않습니다.
|
||||
if (isset($write['wr_option']) && strstr($write['wr_option'], "secret")) {
|
||||
if (isset($write['wr_option']) && strpos($write['wr_option'], "secret") !== false) {
|
||||
return run_replace('is_secret_list_thumbnail', $empty_array, $bo_table, $write);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ function get_list_thumbnail($bo_table, $wr_id, $thumb_width, $thumb_height, $is_
|
||||
$edt = true;
|
||||
|
||||
if( $matches = get_editor_image($write['wr_content'], false) ){
|
||||
for($i=0; $i<count($matches[1]); $i++)
|
||||
$matches_cnt = count($matches[1]);
|
||||
for($i=0; $i<$matches_cnt; $i++)
|
||||
{
|
||||
// 이미지 path 구함
|
||||
$p = parse_url($matches[1][$i]);
|
||||
@@ -117,7 +118,8 @@ function get_view_thumbnail($contents, $thumb_width=0)
|
||||
|
||||
$extensions = array(1=>'gif', 2=>'jpg', 3=>'png', 18=>'webp');
|
||||
|
||||
for($i=0; $i<count($matches[1]); $i++) {
|
||||
$matches_cnt = count($matches[1]);
|
||||
for($i=0; $i<$matches_cnt; $i++) {
|
||||
|
||||
$img = $matches[1][$i];
|
||||
$img_tag = isset($matches[0][$i]) ? $matches[0][$i] : '';
|
||||
@@ -275,11 +277,10 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h
|
||||
$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}.".$file_ext;
|
||||
|
||||
$thumb_time = @filemtime($thumb_file);
|
||||
$source_time = @filemtime($source_file);
|
||||
|
||||
if (file_exists($thumb_file)) {
|
||||
$thumb_time = @filemtime($thumb_file);
|
||||
$source_time = @filemtime($source_file);
|
||||
if ($is_create == false && $source_time < $thumb_time) {
|
||||
return basename($thumb_file);
|
||||
}
|
||||
|
||||
@@ -132,10 +132,10 @@ if(isset($data['pp_id']) && !empty($data['pp_id'])) {
|
||||
}
|
||||
|
||||
$good_mny = isset($PAY['P_AMT']) ? $PAY['P_AMT'] : 0;
|
||||
$pp_name = clean_xss_tags($data['pp_name']);
|
||||
$pp_email = clean_xss_tags($data['pp_email']);
|
||||
$pp_hp = clean_xss_tags($data['pp_hp']);
|
||||
$pp_settle_case = clean_xss_tags($data['pp_settle_case']);
|
||||
$pp_name = addslashes(clean_xss_tags($data['pp_name']));
|
||||
$pp_email = addslashes(clean_xss_tags($data['pp_email']));
|
||||
$pp_hp = addslashes(clean_xss_tags($data['pp_hp']));
|
||||
$pp_settle_case = addslashes(clean_xss_tags($data['pp_settle_case']));
|
||||
|
||||
$_POST['P_HASH'] = $hash;
|
||||
$_POST['P_AUTH_NO'] = isset($PAY['P_AUTH_NO']) ? $PAY['P_AUTH_NO'] : '';
|
||||
|
||||
@@ -124,10 +124,10 @@ if($PGIP == "211.219.96.165" || $PGIP == "118.129.210.25" || $PGIP == "183.109.7
|
||||
}
|
||||
|
||||
$good_mny = $P_AMT;
|
||||
$pp_name = clean_xss_tags($data['pp_name']);
|
||||
$pp_email = clean_xss_tags($data['pp_email']);
|
||||
$pp_hp = clean_xss_tags($data['pp_hp']);
|
||||
$pp_settle_case = clean_xss_tags($data['pp_settle_case']);
|
||||
$pp_name = addslashes(clean_xss_tags($data['pp_name']));
|
||||
$pp_email = addslashes(clean_xss_tags($data['pp_email']));
|
||||
$pp_hp = addslashes(clean_xss_tags($data['pp_hp']));
|
||||
$pp_settle_case = addslashes(clean_xss_tags($data['pp_settle_case']));
|
||||
|
||||
set_session('P_TID', $P_TID);
|
||||
set_session('P_AMT', $P_AMT);
|
||||
|
||||
@@ -7,6 +7,11 @@ include_once(G5_MSHOP_PATH.'/_head.php');
|
||||
$sql_common = " from `{$g5['g5_shop_item_qa_table']}` a join `{$g5['g5_shop_item_table']}` b on (a.it_id=b.it_id) ";
|
||||
$sql_search = " where (1) ";
|
||||
|
||||
if( isset($sfl) && ! in_array($sfl, array('b.it_name', 'a.it_id', 'a.iq_subject', 'a.iq_question', 'a.iq_name', 'a.mb_id')) ){
|
||||
//다른값이 들어가있다면 초기화
|
||||
$sfl = '';
|
||||
}
|
||||
|
||||
if(!$sfl)
|
||||
$sfl = 'b.it_name';
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ if (!$is_member)
|
||||
alert_close('회원만 메일을 발송할 수 있습니다.');
|
||||
|
||||
// 스팸을 발송할 수 없도록 세션에 아무값이나 저장하여 hidden 으로 넘겨서 다음 페이지에서 비교함
|
||||
$token = md5(uniqid(rand(), true));
|
||||
$token = get_random_token_string(16);
|
||||
set_session("ss_token", $token);
|
||||
|
||||
$it = get_shop_item($it_id, true);
|
||||
|
||||
@@ -7,6 +7,11 @@ include_once(G5_MSHOP_PATH.'/_head.php');
|
||||
$sql_common = " from `{$g5['g5_shop_item_use_table']}` a join `{$g5['g5_shop_item_table']}` b on (a.it_id=b.it_id) ";
|
||||
$sql_search = " where a.is_confirm = '1' ";
|
||||
|
||||
if( isset($sfl) && ! in_array($sfl, array('b.it_name', 'a.it_id', 'a.is_subject', 'a.is_content', 'a.is_name', 'a.mb_id')) ){
|
||||
//다른값이 들어가있다면 초기화
|
||||
$sfl = '';
|
||||
}
|
||||
|
||||
if(!$sfl)
|
||||
$sfl = 'b.it_name';
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ $txTid = isset($_POST['TxTid']) ? clean_xss_tags($_POST['TxTid']) : ''; //
|
||||
$authToken = isset($_POST['AuthToken']) ? clean_xss_tags($_POST['AuthToken']) : ''; // authentication TOKEN
|
||||
$payMethod = isset($_POST['PayMethod']) ? clean_xss_tags($_POST['PayMethod']) : ''; // payment method
|
||||
$mid = isset($_POST['MID']) ? clean_xss_tags($_POST['MID']) : ''; // merchant id
|
||||
$moid = isset($_POST['Moid']) ? clean_xss_tags($_POST['Moid']) : ''; // order number
|
||||
$moid = isset($_POST['Moid']) ? addslashes(clean_xss_tags(stripslashes($_POST['Moid']))) : ''; // order number
|
||||
$amt = isset($_POST['Amt']) ? (int) preg_replace('/[^0-9]/', '', $_POST['Amt']) : 0; // Amount of payment
|
||||
$reqReserved = isset($_POST['ReqReserved']) ? clean_xss_tags($_POST['ReqReserved']) : ''; // mall custom field
|
||||
$netCancelURL = isset($_POST['NetCancelURL']) ? clean_xss_tags($_POST['NetCancelURL']) : ''; // netCancelURL
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user