/** 입력변수 체크 * @class write * @param $data: 게시물 데이타 $table: 테이블 명 * @return */ function checkField(&$data, $table, $param = '') { global $mini; $param = param($param); // DB 컬럼 로드 iss($col); $col = getColumns($table); // 체크박스로 받아오는 것들 초기화 iss($data['notice']); iss($data['secret']); iss($data['alert']); iss($data['robot']); iss($data['memo']); iss($data['autobr']); iss($data['popup']); iss($data['issue']); // 입력변수 체크 foreach ($data as $key => $val) { switch ($key) { // 비밀번호 case 'pass_encode': case 'pass': if (isset($data['pass_encode']) && $data['pass_encode']) { switch ($mini['site']['secure_pass']) { case 'md5': case 'sha1': case 'mixed': check($data['pass_encode'], "type:id, name:암호화된 비밀번호, min:16, max:40"); break; case 'mysql': $data['pass_encode'] = mysql_escape_string($data['pass_encode']); $tmp = array(); $tmp = sql("SELECT password('{$data['pass_encode']}') as pass"); $data['pass'] = $tmp['pass']; break; case 'mysql_old': $data['pass_encode'] = mysql_escape_string($data['pass_encode']); $tmp = array(); $tmp = sql("SELECT old_password('{$data['pass_encode']}') as pass"); $data['pass'] = $tmp['pass']; break; } $data['pass'] = $data['pass_encode']; unset($data['pass_encode']); } else { if ($key != 'pass') { unset($data[$key]); } } break; // 추가필드 // 추가필드 case 'field': if (is_array($val)) { str($data[$key], 'encode'); $data[$key] = serialize($data[$key]); } else { if (!empty($val)) { __error('추가필드 형식이 올바르지 않습니다. field[필드명] 형태로 지정하셔야 합니다'); } } break; // 링크 // 링크 case 'link': if (is_array($val)) { if (empty($param['is_conv'])) { foreach ($val as $key2 => $val2) { $data[$key][$key2] = trim($data[$key][$key2]); check($data[$key][$key2], 'type:homepage, name:링크, is_not:1'); } } str($data[$key], 'encode'); $data[$key] = serialize($data[$key]); } else { if (!empty($val)) { __error('링크 형식이 올바르지 않습니다. link[숫자] 형태로 지정하셔야 합니다'); } } break; // 공지사항 // 공지사항 case 'notice': if (!empty($val) && !getPermit("name:notice")) { __error('공지사항을 쓸 권한이 없습니다'); } break; // 이름 // 이름 case 'name': if (empty($param['trackback']) && empty($param['is_conv'])) { check($val, "min:1, max:16, name:이름"); } break; // 메일 // 메일 case 'mail': if (empty($param['is_conv'])) { check($val, "type:mail, name:메일, is_not:1"); } break; // 제목 필터 // 제목 필터 case 'title': if (empty($val) || strCut($val) < 3 && empty($mini['member']['level_admin'])) { __error('제목을 3bytes 이상 입력해주세요'); } filter($data[$key], 'encode', 0); break; // 내용 필터 // 내용 필터 case 'ment': if (empty($val) || strCut($val) < 4 && empty($mini['member']['level_admin'])) { __error('내용을 4bytes 이상 입력해주세요'); } filter($data[$key], 'encode'); break; // 공지사항 날짜 // 공지사항 날짜 case 'date_notice': case 'date_popup': case 'date_issue': if (!empty($val)) { $tmp_name = str_replace('date_', '', $key); if ($mini['time'] >= strtotime($val)) { __error('유효시간이 과거입니다'); } if (empty($data[$tmp_name])) { $data[$key] = ''; } } break; // 관련글 // 관련글 case 'relate': if (!empty($val)) { $data[$key] = preg_replace("/[^0-9\\,]+/is", "", $val); } break; default: // 존재하지 않는 필드일 때 빼기 if (!inStr($key, $col)) { unset($data[$key]); } else { // 값 처리하기 if (is_array($val)) { foreach ($val as $key2 => $val2) { str($val2, 'encode'); } } else { str($data[$key], 'encode'); } } } } // 스킵한 것 지우기 if (isset($data['pass_encode'])) { unset($data['pass_encode']); } }
/** 내용 필터 * @class io * @param $str: 내용 자료 $mode: [encode!|decode] $autolink: 자동링크 사용여부 [0|1!] * @return String */ function filter(&$str, $mode = 'encode', $autolink = 1) { global $mini; //// 태그필터 if (!getPermit("name:html") && $mode == 'encode') { $str = str_replace("<", "<", $str); } else { if ($mode == 'encode') { $str = str_replace("<", "<", $str); // 태그, 주석형식만 디코딩 (php코드나 기타등등은 디코딩되면 안됨) $str = preg_replace(array("/\\<\\;(\\/)?([a-zA-Z0-9]+)([^\\>]*)\\>/", "/\\<\\;\\!\\-\\-(.+)\\-\\-\\>/sm"), array("<\\1\\2\\3>", "<!--\\1-->"), $str); } else { if ($mode == 'decode') { $str = str_replace("<", "<", $str); } } } //// 문자표현 //+ magic_quote 에 따라 잘못될 수도 있음. 차후에 테스트 해봐야 함 if ($mode == 'encode') { $str = str_replace('\\', '\\\\', $str); } //// 치명태그, 자바스크립트 막기 if (empty($mini['member']['level_admin']) && $mode == 'encode') { $str = preg_replace("/j\\s*a\\s*v\\s*a\\s*s\\s*c\\s*r\\s*i\\s*p\\s*t\\s*\\:/is", "javascript:", $str); $str = preg_replace("/on([a-z]+)\\=/is", "on\\1=", $str); $str = preg_replace("/\\<(\\/)?(style|plaintext|pre|xmp|base|meta|iframe|script|textarea|input|form)/is", "&lt;\\1\\2", $str); } elseif ($mode == 'decode') { $str = str_replace(array("=", "javascript:"), array("=", "javascript:"), $str); } //// 허용태그 풀기 if (!empty($mini['board']['filter_tag']) && empty($mini['member']['level_admin']) && $mode == 'encode') { $str = preg_replace("/\\&(amp\\;)?lt\\;(\\/)?(" . str_replace(array(',', ' '), array('|', ''), $mini['board']['filter_tag']) . ")/is", "<\\2\\3", $str); } //// 자동링크 if ($autolink == 1) { if (!function_exists("strtohex")) { function strtohex($str) { $retval = ""; for ($i = 0; $i < strlen($str[1]); $i++) { $retval .= "&#x" . bin2hex(substr($str[1], $i, 1)) . ";"; } return $retval; } } if ($mode == 'encode') { if (!empty($mini['board']['use_mail_encode'])) { $str = preg_replace_callback("/([[a-z0-9\\.\\-_\\+]+\\@[a-z0-9\\.\\-_\\+]+)/is", "strtohex", $str); } // 메일은 HEX로 $str = preg_replace("/([^'\"a-z0-9\\=\\:\\]\\,])([a-z0-9]+)\\:\\/\\/([^'\"\\s]+)/is", "\\1<a href='\\2://\\3' target='_blank' title='autolink'>\\2://\\3</a>", $str); $str = preg_replace("/^([a-z0-9]+)\\:\\/\\/([^'\"\\s]+)/is", "<a href='\\1://\\2' target='_blank' title='autolink'>\\1://\\2</a>", $str); } else { $str = preg_replace("/\\<a href\\='([^']+)' target\\='\\_blank' title\\='autolink'\\>([^\\<]+)\\<\\/a\\>/isU", "\\1", $str); } } //// 매크로 처리 if (!function_exists("macro_tool")) { // 목록 function macro_list($v) { global $mini; if (empty($mini['macro_list'])) { $mini['macro_list'] = 1; } else { $mini['macro_list']++; } $v[1] = trim($v[1]); $v[2] = trim($v[2]); $output = "<span id='macroListTitle{$mini['macro_list']}' style='display:none;'>{$v[1]}<!--macro--></span><div id='macroListMent{$mini['macro_list']}' class='macroListMent' style='display:none;'>{$v[2]}</div><!--macro-->"; return $output; } // 폴딩 function macro_fold($v) { def($v[1], "클릭하시면 내용이 펼쳐집니다"); $v[1] = trim($v[1]); $v[2] = trim($v[2]); $output = "<div class='fold'>{$v[1]}</div><div class='fold_ment' style='display:none;'>{$v[2]}</div><!--f-->"; return $output; } // 그밖의 function macro_tool($v) { global $mini, $tmp_check; if (!isset($tmp_check)) { $tmp_check = 0; } def($width, ''); def($height, ''); def($align, 'center'); def($title, '1'); $mode = trim($v[1]); $v[2] = trim($v[2]); $src = $output = ''; $src_arr = array(); foreach (explode(",", $v[2]) as $key => $val) { // 주소 if ($key == 0) { $val = preg_replace("/^:/i", "", $val); if (preg_match("/\\|/", $val)) { $tmp = explode("|", $val); } else { $tmp[] = $val; } foreach ($tmp as $key2 => $val2) { $val2 = trim($val2); if ($val2) { switch ($mode) { case 'img': if (!preg_match("/[^0-9]/", $val2)) { $val2 = "{$mini['dir']}download.php?mode=view&no={$val2}"; } else { $val2 = amp($val2, 'encode'); } $src .= ",{$val2}"; $src_arr[] = $val2; break; case 'slide': case 'flv': case 'music': case 'movie': //if (!preg_match("/[^0-9]/", $val2)) $val2 = "{$mini['dir']}download.php?mode=view&no={$val2}"; $src .= "," . urlencode($val2); $src_arr[] = $val2; break; case 'file': if (!preg_match("/[^0-9]/", $val2)) { $val2 = "{$mini['dir']}download.php?mode=view&no={$val2}"; } else { $val2 = amp($val2, 'encode'); } $src .= "," . urlencode($val2); $src_arr[] = $val2; break; default: $src = $val2; } } } $src = preg_replace("/^\\,/", "", $src); continue; } // 설정 입력 $tmp = array(); $tmp = explode(":", $val); if (!empty($tmp[0]) && !empty($tmp[1])) { $tmp[0] = trim($tmp[0]); // 허용 속성 if (!preg_match("/^(width|height|title|align|startLine|style|size)\$/i", $tmp[0])) { $output = $v[0]; } ${$tmp[0]} = trim($tmp[1]); } } $output2 = ''; // 앞에 해당되는 것이 없을 경우 if (empty($output)) { switch ($mode) { // 이미지 case 'img': // 크기 $size = ''; if ($width) { $size .= " width='{$width}'"; } if ($height) { $size .= " height='{$height}'"; } // 설명 if ($title) { $title = "<div class='macroImageTitle' style='display:none;'></div>"; } else { $title = ''; } $output2 = "<img alt='macroImage' src='{$src}'{$size} class='macroImage" . ($size ? " hand' onclick='viewImage(this);'" : "'") . " />{$title}"; break; // 슬라이드 // 슬라이드 case 'slide': $time = $tmp_check; $output2 = "<div id='iiSlideTarget_{$time}'></div>" . "<script type='text/javascript' src='{$mini['dir']}js/iiSlideImage.js.php?no={$src}&id=iiSlideTarget_{$time}&title={$title}&width={$width}&height={$height}'></script>"; break; // 동영상 // 동영상 case 'flv': case 'music': $time = $tmp_check; if (!empty($src_arr)) { if (empty($width)) { $width = '400'; } if (empty($height)) { $height = '220'; } // 주소처리 // $src = amp($src, 'encode'); if (empty($mini['is_swfobject'])) { $mini['is_swfobject'] = 1; $output2 .= "\n<script type='text/javascript' src='{$mini['dir']}addon/mediaplayer/swfobject.js'></script>"; } $output2 .= "<div id='iiMediaTarget_{$time}'></div>" . "<script type='text/javascript'>" . "var so{$time} = new SWFObject('{$mini['dir']}addon/mediaplayer/mediaplayer.swf','mp{$time}','{$width}','{$height}','8');" . "so{$time}.addParam('allowscriptaccess','always');" . "so{$time}.addParam('allowfullscreen','true');" . "so{$time}.addVariable('width','{$width}');" . "so{$time}.addVariable('height','{$height}');" . "so{$time}.addVariable('file','{$mini['dir']}playlist.php%3Fsel%3D" . (preg_match("/[^0-9]/", $src) ? urlencode(base64_encode($src)) : $src) . ($mode == 'music' ? "%26type%3Dmusic" : "") . "');" . ($mode == 'music' ? "so{$time}.addVariable('displaywidth','150');" : "") . "so{$time}.addVariable('javascriptid','mp{$time}');" . "so{$time}.addVariable('enablejs','true');" . "so{$time}.write('iiMediaTarget_{$time}');"; $output2 .= "</script>"; } break; case 'code': def($startLine, 1); switch ($src) { case 'cpp': case 'csharp': case 'css': case 'delphi': case 'java': case 'javascript': case 'php': case 'python': case 'ruby': case 'sql': case 'vb': str($v[3], 'encode'); $v[3] = str_replace("&#91;", "[", $v[3]); $v[3] = str_replace("&#93;", "]", $v[3]); $v[3] = str_replace(array("&lt;"), array("<"), $v[3]); $v[3] = str_replace(array("\\n", "\r\n", "\n"), array("\n", "\n", "<br /><!--n-->"), $v[3]); $output2 = "<pre title='code' class='{$src}:firstline[{$startLine}]'>{$v[3]}</pre>"; break; //+ bbcode 지워야 함 //+ bbcode 지워야 함 default: str($v[3], 'encode'); $v[3] = str_replace("&#91;", "[", $v[3]); $v[3] = str_replace("&#93;", "]", $v[3]); $v[3] = str_replace(array("\\n", "\r\n", "\n"), array("\n", "\n", "<br /><!--n-->"), $v[3]); $output2 = "<div class='bbcode'><pre>{$v[3]}</pre></div>"; } break; // 글상자 // 글상자 case 'box': $v[3] = str_replace("\t", " ", $v[3]); $v[3] = str_replace(array("<"), array("<"), $v[3]); $output2 = "<div class='iiBox_{$src}'>{$v[3]}</div>"; break; // 글꼴 // 글꼴 case 'font': $tmp = "font-family:\"{$src}\";"; if (!empty($size)) { $tmp .= "font-size:{$size};"; } $output2 = "<span style='{$tmp}'>{$v[3]}</span>"; break; // 파일추가 // 파일추가 case 'file': $src = urldecode($src); $output2 = "<a href='{$src}' target='_blank'>{$v[3]}</a>"; break; } // 정렬 switch ($align) { case 'inleft': case 'inright': $align = str_replace("in", "", $align); $align2 = $align == 'right' ? 'left' : 'right'; $output = "<table class='macroImage' align='{$align}' style='margin-{$align2}:10px;'><tr><td>{$output2}</td></tr></table>"; break; default: if ($mode == 'img' || $mode == 'slide' || $mode == 'flv' || $mode == 'music') { $output = "<div style='text-align:{$align};'><table class='macroImage' align='{$align}'><tr><td>{$output2}</td></tr></table></div>"; } else { $output = $output2; } } $v[0] = str_replace(array("<!--", "-->"), array("<!--", "-->"), $v[0]); $output = "<!--macroToolStart-->{$output}<!--macroToolEnd:{$v[0]}:macroToolEnd-->"; } $tmp_check++; return $output; } // 내부 URL금지 및 target 설정 function macro_url_security($v) { global $mini; if (!preg_match("/\\shref\\=(['\"]?)[a-z0-9]+\\:\\/\\/[^'\"]+(['\"]?)/is", $v[1])) { $v[1] = preg_replace("/(\\s)href\\=('|\")?([^'\"]+)('|\")?/is", "\\1href=\\2{$mini['pdir']}error.php?msg=" . urlencode("내부 주소로 링크되어 차단되었습니다") . "\\4", $v[1]); } if (!preg_match("/\\starget\\=(['\"]?)([^'\"]+)(['\"]?)/i", $v[1])) { return "<a{$v[1]} target='_blank'>"; } else { return "<a{$v[1]}>"; } } } // 링크 보안처리 if (empty($mini['member']['level_admin']) && $mode == 'encode') { $str = preg_replace_callback("/\\<a([^\\>]+)\\>/isU", "macro_url_security", $str); } // encode if ($mode == 'encode') { $str_left = $str_right = $preg_left = $preg_right = array(); $str_left[] = "\\\\]"; $str_right[] = "]"; $str_left[] = "\\\\["; $str_right[] = "["; $str = str_replace($str_left, $str_right, $str); $preg_left[] = "/\\[a\\:([^\\]]+)\\]([^\\[]+)\\[\\/a\\]/isU"; $preg_right[] = "<a href='\\1' target='_blank'>\\2</a><!--macro-->"; $preg_left[] = "/\\[printList\\]/i"; $preg_right[] = "<div id='macroListPrint'></div>"; foreach (array('i', 'b', 'u', 'strike', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'sup', 'sub') as $val2) { $preg_left[] = "/\\[{$val2}\\](.+)\\[\\/{$val2}\\]/isU"; $preg_right[] = "<{$val2}>\\1</{$val2}><!--macro-->"; } $preg_left[] = "/\\[h](.+)\\[\\/h\\]/sU"; $preg_right[] = "<span class='highlight'>\\1</span><!--macro-->"; // 제일 마지막 $str = preg_replace($preg_left, $preg_right, $str); $str = preg_replace_callback("/\\[(code|font|box|file)\\:([^\\]]+)\\](.+)\\[\\/(code|font|box|file)\\]/isU", "macro_tool", $str); $str = preg_replace_callback("/\\[list\\:([^\\]]+)\\](.+)\\[\\/list\\]/isU", "macro_list", $str); $str = preg_replace_callback("/\\[fold\\:?([^\\]\\:]*)](.+)\\[\\/fold\\]/isU", "macro_fold", $str); $str = preg_replace_callback("/\\[(img|slide|flv|music)\\:(.+)\\]/isU", "macro_tool", $str); } else { $str_left = $str_right = $preg_left = $preg_right = array(); $str_left[] = "]"; $str_right[] = "\\]"; $str_left[] = "["; $str_right[] = "\\["; $str = str_replace($str_left, $str_right, $str); $preg_left[] = "/\\<span id\\='macroListTitle[0-9]+' style\\='display\\:none\\;'\\>(.+)\\<\\!\\-\\-macro\\-\\-\\>\\<\\/span\\>\\<div id\\='macroListMent[0-9]+' class\\='macroListMent' style\\='display\\:none\\;'\\>(.+)\\<\\/div\\>(<|\\<)\\!\\-\\-macro\\-\\-(\\>|>)/isU"; $preg_right[] = "[list:\\1]\\2[/list]"; $preg_left[] = "/\\<div id\\='macroListPrint'\\>\\<\\/div\\>/i"; $preg_right[] = "[printList]"; $preg_left[] = "/\\<span class\\='highlight'\\>(.+)\\<\\/span\\>(<|\\<)\\!\\-\\-macro\\-\\-(\\>|>)/isU"; $preg_right[] = "[h]\\1[/h]"; $preg_left[] = "/\\<\\!\\-\\-macroToolStart\\-\\-\\>.+\\<\\!\\-\\-macroToolEnd\\:(.+)\\:macroToolEnd\\-\\-\\>/isU"; $preg_right[] = "\\1"; $preg_left[] = "/\\<div class\\='fold'\\>(.+)\\<\\/div\\>\\<div class\\='fold_ment' style\\='display\\:none\\;'\\>(.+)\\<\\/div\\>(<|\\<)\\!\\-\\-f\\-\\-(\\>|>)/isU"; $preg_right[] = "[fold:\\1]\\2[/fold]"; $preg_left[] = "/\\<a href\\='([^']+)' target\\='\\_blank'\\>([^\\<]+)\\<\\/a\\>(<|\\<)\\!\\-\\-macro\\-\\-(\\>|>)/isU"; $preg_right[] = "[a:\\1]\\2[/a]"; foreach (array('i', 'b', 'u', 'strike', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'sup', 'sub') as $val2) { $preg_left[] = "/\\<{$val2}\\>(.+)\\<\\/{$val2}\\>(<|\\<)\\!\\-\\-macro\\-\\-(\\>|>)/isU"; $preg_right[] = "[{$val2}]\\1[/{$val2}]"; } $str = preg_replace($preg_left, $preg_right, $str); } //// 내용필터 if (empty($mini['member']['level_admin']) && !empty($mini['board']['use_filter']) && !empty($mini['board']['filter_ment']) && $mode == 'encode') { // 단어 나눔 $tmp = explode(",", $mini['board']['filter_ment']); $tmp_ment = $str; // 복수공백 제거, 공백기호 적용 $tmp_ment = preg_replace("/"|'|||[\\x2A-\\x2F\\x5B\\x5D\\x7B\\x7D\\x7E]/s", "", $tmp_ment); // 태그, 특수기호 제거 $tmp_ment = preg_replace(array("/\\<[^\\>]+\\>/s", "/<|>|&/s", "/[\\x21-\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7E]/s"), "", $tmp_ment); // 함수 정의 if (!function_exists("asc_hex")) { function asc_hex($char) { $t_char = ''; $j = 0; $word_length = strlen($char); for ($i = 0; $i < $word_length; $i++) { if ($j == 0) { if (ord(substr($char, $i, 1)) > 0xa1 && ord(substr($char, $i, 1)) <= 0xfe) { $j = 1; $t_char = $t_char . bin2hex(substr($char, $i, 1)); } else { $t_char = $t_char . "00" . bin2hex(substr($char, $i, 1)) . " "; } } else { $t_char = $t_char . bin2hex(substr($char, $i, 1)) . " "; $j = 0; } } return $t_char; } } // 루프 if (!empty($tmp_ment) && !empty($tmp)) { foreach ($tmp as $val) { $val = trim($val); $pos = strpos($tmp_ment, $val); if ($pos !== false) { // 진짜 같은지 확인 if (asc_hex(substr($tmp_ment, $pos, strlen($val))) == asc_hex($val)) { if ($mini['board']['filter_mode'] == 'denied') { __error("[{$val}] 금지단어가 포함되어 있습니다"); } else { $str = preg_replace("/" . $val . "/is", "<span class='filter' title='{$val}'>금지단어</span><span style='display:none;'>{$val}</span>", $str); } } } } } } else { if ($mode == 'decode') { $str = preg_replace("/\\<span class\\='filter' title\\='([^']+)'\\>금지단어\\<\\/span\\>\\<span style\\=\\'display\\:none\\;\\'\\>[^\\<]+<\\/span\\>/isU", "\\1", $str); } } //// 맨 뒤 escape 방지 if (substr($str, -1) == "\\" && $mode == 'encode') { $str = substr_replace($str, "\", -1); } }