Compare commits

...
181 Commits
Author SHA1 Message Date
thisgun 2aae238d70 Merge branch 'renewal2' of github.com:gnuboard/g5 into renewal 2018-01-25 16:59:43 +09:00
thisgun 6f1c3bee2c 틀린 구문 수정 2018-01-25 16:29:51 +09:00
thisgun 5094fafdf6 Merge branch 'renewal2' of github.com:gnuboard/g5 into renewal 2018-01-25 09:50:09 +09:00
thisgun 3eac467259 버전 5.3.0.2 으로 변경 2018-01-24 18:35:45 +09:00
thisgun 326d7b9865 Merge branch 'master' into renewal2 2018-01-19 18:24:08 +09:00
thisgun 80d47facff 문법 오류 수정 2018-01-19 18:23:57 +09:00
thisgun 9e2204fdac 메모에 페이징 적용 2018-01-19 18:18:45 +09:00
thisgun 18749864c0 메모에 페이징 적용 2018-01-19 16:05:33 +09:00
thisgun 97483e7fdb 회원가입 스킨 수정 2018-01-18 12:22:46 +09:00
thisgun 06459ceeeb 회원 이미지 아이콘 등록 버그 수정 2018-01-18 11:42:34 +09:00
thisgun ffb3cb7fd8 일부 소셜 로그인 소스 수정 2018-01-18 10:33:37 +09:00
thisgun 365b5e53a9 모바일 댓글 스킨 수정 2018-01-17 17:33:46 +09:00
thisgun 75b8241e91 모바일 스킨 수정 2018-01-17 17:24:52 +09:00
thisgun eff027939c 댓글 부분 처리 수정 2018-01-17 17:07:38 +09:00
thisgun 99a02d692f 회원아이콘 불편한 점 수정 2018-01-17 16:53:41 +09:00
thisgun d250c772af 소셜 로그인 관련 수정 2018-01-16 17:23:45 +09:00
thisgun fab5f673d9 일부 구문 수정 2018-01-16 15:43:14 +09:00
thisgun e3f91c8a81 일부 css 수정 2018-01-16 14:55:39 +09:00
thisgun 1140c55cec Merge branch 'master' into renewal2 2018-01-16 13:46:54 +09:00
thisgun a1247d5da9 이전글 다음글 오류 수정 2018-01-11 20:12:26 +09:00
thisgun c85d6cf414 게시판 타이틀 잘못된 부분 수정 2018-01-05 10:55:21 +09:00
thisgun fc976f2bed 관리자 설문조사 페이지 필터구문 추가 2018-01-05 10:19:47 +09:00
thisgun b34f577fbd iframe 허용 목록의 잘못된 정규식 수정 2017-12-27 18:10:40 +09:00
thisgun f2a6e758f3 충돌 수정 2017-12-27 12:22:20 +09:00
thisgun b64e3179cd 충돌 수정 2017-12-27 11:15:14 +09:00
thisgun c1e1f64580 5.2.9.8.1 버전 수정 2017-12-27 09:56:10 +09:00
thisgun 5ab91fa0ab Open Redirect 취약점 수정 2017-12-27 09:45:22 +09:00
thisgun 5abc41cdb9 게시판 글쓰기 iframe 허용 코드 수정 2017-12-27 09:14:48 +09:00
thisgun dd51045f6d 5.3.0.1 버전 보안패치 및 오류 수정 2017-12-22 15:31:32 +09:00
thisgun 2ca86e3649 베타 버전 5.3.0.1 수정 2017-12-22 14:45:13 +09:00
thisgun 7e33fe21cb sns 댓글 코드 수정 2017-12-22 14:44:27 +09:00
thisgun abd2d60522 버전정보 수정 2017-12-22 14:35:21 +09:00
thisgun a31e155c1e 하단 로고 코드 수정 2017-12-22 14:21:22 +09:00
thisgun b8a6be9662 관리자 메뉴 아이콘 추가 2017-12-22 14:11:57 +09:00
thisgun 022322d678 일부 코드 수정 2017-12-22 14:11:44 +09:00
thisgun 1d161bb26e 썸네일 코드 수정 2017-12-22 11:39:17 +09:00
thisgun 3e123debdf 기타 오류 수정 2017-12-22 11:06:15 +09:00
thisgun 95d187eeee 5.2 버전과 충돌 수정 2017-12-21 10:27:14 +09:00
thisgun 9567478b7d Merge branch 'renewal2' of github.com:gnuboard/g5 into renewal2 2017-12-21 10:21:50 +09:00
thisgun 4566ef6935 여러 코드 수정 2017-12-21 10:16:55 +09:00
thisgun e48f823e50 관리자 메뉴 수정 2017-12-20 18:51:12 +09:00
thisgun 68f8836cfb 5.2.9.8 버전 수정 2017-12-20 11:59:10 +09:00
thisgun 1e41f6a8ff 파일 업로드 취약점 수정 2017-12-18 12:21:23 +09:00
thisgun 75de0e3e60 충돌 수정 2017-12-12 12:02:49 +09:00
thisgun 875a326344 그누보드 CSRF 취약점(KVE-2017-0883,0884,0923) 수정 2017-12-12 11:59:10 +09:00
thisgun 7f9664af0a 그누보드 Reflected XSS 취약점 (891, 906, 908, 910) 수정 2017-12-11 17:52:20 +09:00
thisgun 8755c8ece7 Open Redirect 취약점 수정 2017-12-11 14:34:01 +09:00
thisgun 66358414f2 pht 파일 업로드 취약점 수정 adm1nkyj(김용진, http://adm1nkyj.kr) 님 제보 2017-12-08 11:27:37 +09:00
thisgun 82279c376b 5.2.9.7 버전 수정 2017-12-07 11:16:48 +09:00
thisgun 8b096e770c 스팸글댓글 유입을 줄이려고 링크에 nofollow 추가함 2017-12-07 11:02:10 +09:00
thisgun 6bf57bd4c6 최신글 캐시 파일 삭제 취약점 수정 2017-12-06 18:31:36 +09:00
thisgun ea55f3880e 그누보드4 가져오기 코드에 게시판 모바일 설정 추가 적용 2017-12-06 16:11:24 +09:00
thisgun 19e0ea60a7 php 잘못된 숏태그 수정 2017-12-05 19:10:41 +09:00
thisgun 7831d9dfb6 가비아 호스팅에서 설치시 에러 문제 수정 2017-12-05 17:10:55 +09:00
thisgun 907db24187 htmlpurifier 4.9.3 버전의 변경 2017-12-05 14:41:49 +09:00
thisgun 5a424d5977 Merge branch 'master' of github.com:gnuboard/g5 2017-12-04 16:02:42 +09:00
thisgun 0408bae838 충돌 수정 2017-12-04 16:02:23 +09:00
thisgun 6c4353fffe php 7.2 버전에서 오류 나는 코드 수정 2017-12-04 15:56:59 +09:00
thisgun 35268a413f 관리자 게시판 복사 링크 수정 2017-12-04 15:21:15 +09:00
thisgun fd1ec11ad1 그누보드4 import 코드 수정 2017-12-04 14:26:12 +09:00
sora90224 89ad616008 에디터 기본태그 적용 2017-11-29 16:07:07 +09:00
thisgun 9f89455b3c 그누보드 XSS 취약점 (17-876, 17-879) 수정 2017-11-28 17:23:50 +09:00
thisgun 2a94c17b58 일부 코드 수정 2017-11-21 10:56:19 +09:00
sora90224 c9924a711f #77 사이드뷰 수정 2017-11-21 10:38:27 +09:00
thisgun d04f5f54d5 모바일에서 글자 크기 조정 class 수정 2017-11-21 10:28:08 +09:00
thisgun dc005d6441 프로필 이미지 코드 수정 2017-11-21 09:56:27 +09:00
thisgun ecc5c2e7e9 기타 오류 수정 2017-11-21 09:20:15 +09:00
thisgun d37619aa95 프로필 이미지 잘못된 코드 전부 수정 2017-11-20 21:10:17 +09:00
thisgun 0ae22667a0 주석 처리 2017-11-20 10:54:03 +09:00
thisgun dff2c45acc 관리자 메뉴 정렬 부분 수정 2017-11-20 09:29:01 +09:00
thisgun 56da0d90e3 소셜 로그인 가입 처리 수정 2017-11-17 18:21:18 +09:00
thisgun 88dc122183 소셜 로그인 메일 인증에 관해서 수정 2017-11-17 18:04:23 +09:00
thisgun 7dba46f650 소셜 회원가입 코드 정리 2017-11-17 17:37:57 +09:00
thisgun 604531906a 소셜로그인 세션 관련 수정 2017-11-17 15:25:49 +09:00
thisgun 25bce8592d 회원 탈퇴 부분 수정 2017-11-17 10:30:42 +09:00
thisgun 520b99c0a5 kakao 수정 2017-11-16 16:00:43 +09:00
thisgun 22bd15b6ef 카카오 설정 수정 2017-11-16 15:38:35 +09:00
thisgun 45582cb859 소셜 로그인 잘못된 설정 수정 2017-11-16 12:17:57 +09:00
thisgun 723e485755 소셜 설정값 수정 2017-11-16 11:27:47 +09:00
thisgun 215d631ed9 소셜 로그인 정보 수정 2017-11-16 11:05:28 +09:00
thisgun 5ab4f9536a 소셜 로그인 수정 2017-11-16 10:38:02 +09:00
thisgun ca07c830b3 잘못된 문구 수정 2017-11-15 16:56:21 +09:00
thisgun d337fc41c0 Merge branch 'renewal2' of github.com:gnuboard/g5 into renewal2 2017-11-15 15:58:26 +09:00
thisgun f1a3f87d68 소셜 문구 수정 2017-11-15 15:58:17 +09:00
sora90224 1626733833 Merge branch 'renewal2' of github.com:gnuboard/g5 into renewal2 2017-11-15 10:27:16 +09:00
sora90224 a64ab417b1 #76 상단높이 수정 2017-11-15 10:25:08 +09:00
thisgun b8d788c1b4 리뉴얼 잘못된 코드 수정 2017-11-14 14:48:37 +09:00
thisgun 761722881a 소셜 css 수정 2017-11-14 12:07:33 +09:00
thisgun 05fb6f7a68 bxslider 파일 수정 2017-11-14 11:46:34 +09:00
thisgun c427c25ee4 회원가입 코드 수정 2017-11-13 12:22:03 +09:00
thisgun 53b5e8b5ff 리뉴얼 수정 중 2017-11-13 10:34:21 +09:00
thisgun a72b34adf6 리뉴얼 수정 2017-11-10 18:45:26 +09:00
sora90224 b6ffbcf901 Merge branch 'renewal2' of github.com:gnuboard/g5 into renewal2 2017-11-10 12:10:25 +09:00
sora90224 76b691c719 #75 소셜로그인 수정 2017-11-10 12:10:05 +09:00
thisgun a402501c6f 갤러리 스킨 수정 및 일부 코드 수정 2017-11-10 10:59:20 +09:00
thisgun 1afb5a76ca 리뉴얼 수정 2017-11-09 16:36:38 +09:00
thisgun 260de461bc 그누보드5 리뉴얼 테마 수정 2017-11-09 10:32:24 +09:00
thisgun f0035aeb98 리뉴얼 테마 수정 2017-11-09 09:39:49 +09:00
thisgun 320314262d 소셜 로그인 일부 소스 수정 2017-11-08 19:45:30 +09:00
thisgun b3b0762d30 소셜 로그인 수정 2017-11-08 11:59:41 +09:00
thisgun c865379f13 소셜 로그인 수정 2017-11-07 19:06:52 +09:00
thisgun 218d198716 리뉴얼 작업 수정중 2017-11-07 18:15:26 +09:00
thisgun 980ca5b11e 리뉴얼 수정중 2017-11-07 17:49:01 +09:00
thisgun 0f91e6bb09 소셜 플러그인 수정중 2017-11-07 16:56:46 +09:00
thisgun bf23913cff Merge branch 'master' of github.com:gnuboard/g5 into renewal5 2017-11-07 16:11:20 +09:00
thisgun b03b0a1b1a 그누보드5 리뉴얼 소셜 수정중 2017-11-06 16:13:13 +09:00
thisgun 23bf0d6a17 소셜로그인 수정 2017-10-26 10:19:49 +09:00
thisgun 1824cf0f27 리뉴얼 스킨 파일 수정 2017-10-25 15:50:52 +09:00
thisgun 4ab7d7a402 회원 스킨 수정 2017-10-25 15:23:59 +09:00
thisgun 4cf3013de6 리뉴얼 content 스킨 수정 2017-10-25 15:09:11 +09:00
thisgun 4ea62e4036 리뉴얼 faq 스킨 수정 2017-10-25 15:08:23 +09:00
thisgun 726f456595 리뉴얼 new 스킨 수정 2017-10-25 14:59:52 +09:00
thisgun 43310e615b 리뉴얼 visit 수정 2017-10-25 12:10:51 +09:00
thisgun 570f0cfb69 검색어 스킨 리뉴얼 수정 2017-10-25 12:07:49 +09:00
thisgun 68538d988e 리뉴얼 qa skin 수정 2017-10-25 11:59:32 +09:00
thisgun d6faf2cc72 리뉴얼 popular 스킨 수정 2017-10-25 11:57:55 +09:00
thisgun e0f330912c 리뉴얼 poll 스킨 수정 2017-10-25 11:57:27 +09:00
thisgun f25cf1a69b outlogin skin 리뉴얼에서 수정 2017-10-25 11:51:06 +09:00
thisgun 82a48854a7 리뉴얼 수정중 1 2017-10-25 11:49:05 +09:00
thisgun 376025ba31 master 와 merge 2017-10-25 11:09:31 +09:00
thisgun 2d51200270 테마 파일 수정 2017-10-25 10:37:21 +09:00
thisgun 1b37f8b4e7 관리자 페이지 앵커 스크립트 적용 2017-10-24 17:52:49 +09:00
thisgun 8a5b733d92 리뉴얼5 브랜치 수정중 2017-10-24 14:05:47 +09:00
thisgun d66b56484f 리뉴얼 수정중 10-18 2017-10-18 16:59:52 +09:00
thisgun cb7fda687c 리뉴얼 수정중 10-18 2017-10-18 16:59:33 +09:00
thisgun 2b73333273 테마 수정중 2017-09-01 21:01:48 +09:00
thisgun b5b4c67bcd 테마 모바일 수정중 2017-09-01 14:53:27 +09:00
thisgun bb896d81aa 틀린 구문 수정 2017-09-01 14:19:06 +09:00
thisgun ae2bab45aa 테마 수정 2017-09-01 14:09:49 +09:00
thisgun b7adf0a158 리뉴얼 테마 수정중 2017-09-01 13:55:58 +09:00
thisgun dac658451e 테마 일부 수정 2017-09-01 11:45:50 +09:00
thisgun a20dc27a5a 리뉴얼 부분 수정 2017-09-01 11:28:15 +09:00
thisgun 00a98ea6ea 그누보드5 리뉴얼 수정 2017-08-31 17:58:08 +09:00
thisgun 63907105f3 소셜 로그인 등 수정 2017-08-31 15:15:56 +09:00
thisgun 4447579b20 모바일 스킨 수정 2017-08-28 20:40:23 +09:00
thisgun fe63e1c4ad 찾기 수정 2017-08-28 20:39:48 +09:00
thisgun e285dadef5 QA 스킨 모바일 수정 2017-08-28 20:39:19 +09:00
thisgun 3b081723ba 모바일 스킨 수정 2017-08-28 20:38:09 +09:00
thisgun d400071b87 모바일 스킨 수정 2017-08-28 20:37:47 +09:00
thisgun 32c93ff469 모바일 스킨 수정 2017-08-28 20:37:06 +09:00
thisgun d52c2fb9fc 모바일 새창 스킨 수정 2017-08-28 20:36:33 +09:00
thisgun 6d8d45410a 모바일 수정 2017-08-28 20:35:47 +09:00
thisgun 624a944262 123 2017-08-28 20:33:22 +09:00
thisgun da0ade0de1 123 2017-08-28 20:32:48 +09:00
thisgun f4da43acfc 123 2017-08-28 20:31:37 +09:00
thisgun 123bea4607 1 2017-08-28 20:30:54 +09:00
thisgun 08bbdb090a 모바일 수정중 2017-08-28 20:28:42 +09:00
thisgun 05a474714b 리뉴얼 수정중 2017-08-28 20:08:21 +09:00
thisgun dd51aeb47f 리뉴얼 수정중 2017-08-28 11:26:10 +09:00
thisgun 597e4f711e 리뉴얼 수정중 2017-08-28 11:24:51 +09:00
thisgun 116bb30468 관리자 메뉴 수정 2017-08-28 10:43:49 +09:00
thisgun 12f0e53d41 sms 관리 수정 2017-08-28 10:39:53 +09:00
thisgun 5712c7540b 관리자 메뉴 처리 2017-08-28 10:26:56 +09:00
thisgun aede8990fb 6 2017-08-25 17:26:15 +09:00
thisgun 53e1ecb15f 5 2017-08-25 17:25:48 +09:00
thisgun f3e8404acf 5 2017-08-25 17:25:40 +09:00
thisgun 0468981740 5 2017-08-25 17:24:36 +09:00
thisgun d9b983678a 5 2017-08-25 17:24:11 +09:00
thisgun d5406effd7 5 2017-08-25 17:23:37 +09:00
thisgun 70282230e7 5 2017-08-25 17:23:08 +09:00
thisgun adac801b42 5 2017-08-25 17:17:17 +09:00
thisgun cd37bcde96 회원폼 수정 2017-08-25 17:13:20 +09:00
thisgun a2eb5044db 3 2017-08-25 17:10:06 +09:00
thisgun 4e3926bbf8 3 2017-08-25 17:09:06 +09:00
thisgun 1d2ab850fd 환경설정 파일 수정 2017-08-25 17:08:25 +09:00
thisgun be3687cef3 2 2017-08-25 16:52:30 +09:00
thisgun 453fce1649 2 2017-08-25 16:50:43 +09:00
thisgun cf3ec61f07 2 2017-08-25 16:49:28 +09:00
thisgun 8a63521550 2 2017-08-25 16:48:12 +09:00
thisgun a02634c386 1 2017-08-25 16:30:11 +09:00
thisgun 0352b2d59d 1 2017-08-25 16:29:01 +09:00
thisgun 4fc41d05ae 관리자 페이지 수정 2017-08-25 16:11:47 +09:00
thisgun 6dbafdaadb 관리자 페이지 수정중 2017-08-25 14:37:58 +09:00
thisgun f145b12932 관리자 페이지 수정 2017-08-25 14:27:54 +09:00
thisgun ab3f7a3c76 Merge branch 'master' of github.com:gnuboard/g5 into renewal10 2017-08-25 09:30:17 +09:00
thisgun 47a4a10f89 리뉴얼 소스 수정 2017-08-24 12:02:40 +09:00
thisgun 97cb50ab8b Merge branch 'master' into renewal10 2017-08-22 17:04:59 +09:00
thisgun 7e5c171a6d 리뉴얼소스 수정 2017-08-14 20:30:22 +09:00
thisgun 816247ab53 Merge branch 'master' of github.com:gnuboard/g5 into renewal10 2017-08-14 17:31:05 +09:00
thisgun 0432bd677b 그누보드5 리뉴얼 패치중 2017-08-14 16:40:48 +09:00
thisgun 0954b3ce74 리뉴얼과 합침 2017-08-11 15:35:18 +09:00
255 changed files with 32772 additions and 31793 deletions
+15 -1
View File
@@ -3,6 +3,20 @@ if (!defined('_GNUBOARD_')) exit;
$begin_time = get_microtime();
$files = glob(G5_ADMIN_PATH.'/css/admin_extend_*');
if (is_array($files)) {
foreach ((array) $files as $k=>$css_file) {
$fileinfo = pathinfo($css_file);
$ext = $fileinfo['extension'];
if( $ext !== 'css' ) continue;
$css_file = str_replace(G5_ADMIN_PATH, G5_ADMIN_URL, $css_file);
add_stylesheet('<link rel="stylesheet" href="'.$css_file.'">', $k);
}
}
include_once(G5_PATH.'/head.sub.php');
function print_menu1($key, $no='')
@@ -124,7 +138,7 @@ function imageview(id, w, h)
$button_title = $menu['menu'.$key][0][1];
?>
<li class="gnb_li<?php echo $current_class;?>">
<button type="button" class="btn_op menu-<?php echo $jj; ?>" title="<?php echo $button_title; ?>"><?php echo $button_title;?></button>
<button type="button" class="btn_op menu-<?php echo $key; ?> menu-order-<?php echo $jj; ?>" title="<?php echo $button_title; ?>"><?php echo $button_title;?></button>
<div class="gnb_oparea_wr">
<div class="gnb_oparea">
<h3><?php echo $menu['menu'.$key][0][1];?></h3>
+1 -1
View File
@@ -176,7 +176,7 @@ function get_theme_config_value($dir, $key='*')
$tconfig = array();
$theme_config_file = G5_PATH.'/'.G5_THEME_DIR.'/'.$dir.'/theme.config.php';
if(is_file) {
if(is_file($theme_config_file)) {
include($theme_config_file);
if($key == '*') {
+2 -2
View File
@@ -1242,9 +1242,9 @@ $pg_anchor = '<ul class="anchor">
<div class="btn_fixed_top">
<?php if( $bo_table && $w ){ ?>
<a href="./board_copy.php?bo_table='.$bo_table.'" id="board_copy" target="win_board_copy" class=" btn_02 btn">게시판복사</a>
<a href="./board_copy.php?bo_table=<?php echo $board['bo_table']; ?>" id="board_copy" target="win_board_copy" class=" btn_02 btn">게시판복사</a>
<a href="<?php echo G5_BBS_URL ?>/board.php?bo_table=<?php echo $board['bo_table']; ?>'" class=" btn_02 btn">게시판 바로가기</a>
<a href="./board_thumbnail_delete.php?bo_table=<?php echo $board['bo_table']; ?>'&amp;'.$qstr.'" onclick="return delete_confirm2('게시판 썸네일 파일을 삭제하시겠습니까?');" class="btn_02 btn">게시판 썸네일 삭제</a>
<a href="./board_thumbnail_delete.php?bo_table=<?php echo $board['bo_table'].'&amp;'.$qstr;?>" onclick="return delete_confirm2('게시판 썸네일 파일을 삭제하시겠습니까?');" class="btn_02 btn">게시판 썸네일 삭제</a>
<?php } ?>
<input type="submit" value="확인" class="btn_submi btn btn_01" accesskey="s">
</div>
+18 -20
View File
@@ -486,17 +486,15 @@ if ($config['cf_sms_use'] && $config['cf_icode_id'] && $config['cf_icode_pw']) {
</td>
</tr>
<tr>
<th scope="row" rowspan="2"><label for="cf_recaptcha_site_key">구글 reCAPTCHA Site key</label></th>
<td colspan="3" style="border-bottom:none 0">
<th scope="row"><label for="cf_recaptcha_site_key">구글 reCAPTCHA Site key</label></th>
<td colspan="3">
<?php echo help('reCAPTCHA V2와 Invisible reCAPTCHA 캡챠의 sitekey 와 secret 키는 동일하지 않고, 서로 발급받는 키가 다릅니다.') ?>
<input type="text" name="cf_recaptcha_site_key" value="<?php echo $config['cf_recaptcha_site_key']; ?>" id="cf_recaptcha_site_key" class="frm_input" size="52"> <a href="https://www.google.com/recaptcha/admin" target="_blank" class="btn_frmline">reCAPTCHA 등록하기</a>
</td>
</tr>
<tr>
<td>
<input type="text" name="cf_recaptcha_site_key" value="<?php echo $config['cf_recaptcha_site_key']; ?>" id="cf_naver_clientid" class="frm_input" size="52"> <a href="https://www.google.com/recaptcha/admin" target="_blank" class="btn_frmline">reCAPTCHA 등록하기</a>
</td>
<th scope="row"><label for="cf_recaptcha_secret_key">구글 reCAPTCHA Secret key</label></th>
<td>
<td colspan="3">
<input type="text" name="cf_recaptcha_secret_key" value="<?php echo $config['cf_recaptcha_secret_key']; ?>" id="cf_recaptcha_secret_key" class="frm_input" size="52">
</td>
</tr>
@@ -1057,54 +1055,54 @@ if ($config['cf_sms_use'] && $config['cf_icode_id'] && $config['cf_icode_pw']) {
<tr>
<th scope="row"><label for="cf_social_servicelist">소셜로그인설정</label></th>
<td colspan="3" class="social_config_explain">
<p>
<div class="explain_box">
<input type="checkbox" name="cf_social_servicelist[]" id="check_social_naver" value="naver" <?php echo option_array_checked('naver', $config['cf_social_servicelist']); ?> >
<label for="check_social_naver">네이버 로그인을 사용합니다</label>
<div>
<h3>네이버 CallbackURL</h3>
<p><?php echo get_social_callbackurl('naver'); ?></p>
</div>
</p>
<p>
</div>
<div class="explain_box">
<input type="checkbox" name="cf_social_servicelist[]" id="check_social_kakao" value="kakao" <?php echo option_array_checked('kakao', $config['cf_social_servicelist']); ?> >
<label for="check_social_kakao">카카오 로그인을 사용합니다</label>
<div>
<h3>카카오 웹 Redirect Path</h3>
<p><?php echo get_social_callbackurl('kakao', true); ?></p>
</p>
</div>
</p>
<p>
</div>
<div class="explain_box">
<input type="checkbox" name="cf_social_servicelist[]" id="check_social_facebook" value="facebook" <?php echo option_array_checked('facebook', $config['cf_social_servicelist']); ?> >
<label for="check_social_facebook">페이스북 로그인을 사용합니다</label>
<div>
<h3>페이스북 유효한 OAuth 리디렉션 URI</h3>
<p><?php echo get_social_callbackurl('facebook'); ?></p>
</div>
</p>
<p>
</div>
<div class="explain_box">
<input type="checkbox" name="cf_social_servicelist[]" id="check_social_google" value="google" <?php echo option_array_checked('google', $config['cf_social_servicelist']); ?> >
<label for="check_social_google">구글 로그인을 사용합니다</label>
<div>
<h3>구글 승인된 리디렉션 URI</h3>
<p><?php echo get_social_callbackurl('google'); ?></p>
</div>
</p>
<p>
</div>
<div class="explain_box">
<input type="checkbox" name="cf_social_servicelist[]" id="check_social_twitter" value="twitter" <?php echo option_array_checked('twitter', $config['cf_social_servicelist']); ?> >
<label for="check_social_twitter">트위터 로그인을 사용합니다</label>
<div>
<h3>트위터 CallbackURL</h3>
<p><?php echo get_social_callbackurl('twitter'); ?></p>
</div>
</p>
<p>
</div>
<div class="explain_box">
<input type="checkbox" name="cf_social_servicelist[]" id="check_social_payco" value="payco" <?php echo option_array_checked('payco', $config['cf_social_servicelist']); ?> >
<label for="check_social_payco">페이코 로그인을 사용합니다</label>
<div>
<h3>페이코 CallbackURL</h3>
<p><?php echo get_social_callbackurl('payco'); ?></p>
</div>
</p>
</div>
</td>
</tr>
<tr>
@@ -1160,7 +1158,7 @@ if ($config['cf_sms_use'] && $config['cf_icode_id'] && $config['cf_icode_pw']) {
</td>
<th scope="row"><label for="cf_kakao_client_secret">카카오 Client Secret</label></th>
<td>
<input type="text" name="cf_kakao_client_secret" value="<?php echo $config['cf_kakao_client_secret'] ?>" id="cf_kakao_js_apikey" class="frm_input" size="45">
<input type="text" name="cf_kakao_client_secret" value="<?php echo $config['cf_kakao_client_secret'] ?>" id="cf_kakao_client_secret" class="frm_input" size="45">
</td>
</tr>
<tr>
+27 -15
View File
@@ -29,7 +29,7 @@ h2{font-size: 1.083em;font-weight: bold;margin:10px 0}
/* 레이아웃 */
#hd h1 {position:absolute;font-size:0;line-height:0;overflow:hidden}
#hd_top{position:fixed;top:0;left:0;width:100%;width:100%;height:50px;background:#3f51b5;z-index:1000}
#hd_top{position:fixed;top:0;left:0;width:100%;height:50px;background:#3f51b5;z-index:1000}
#hd_top:after{display:block;visibility:hidden;clear:both;content:""}
#logo{background:#2f409f;height:100%;float:left;width:220px;padding:15px 0 15px 50px;text-align:center}
#btn_gnb{background:url(../img/menu-cl.png) 50% 50% no-repeat #223390;width:50px;height:50px;border:0;position:absolute;top:0;left:0;text-indent:-999px;overflow:hidden}
@@ -58,18 +58,20 @@ h2{font-size: 1.083em;font-weight: bold;margin:10px 0}
#gnb .gnb_ul{position:relative;height:100%;background:#ebebeb;width:50px}
#gnb .gnb_li{border-bottom:1px solid #ddd }
#gnb .gnb_li button{background-color: #ebebeb;border:0;width:50px;height:50px;text-indent:-999px;overflow:hidden;}
#gnb .gnb_li .menu-1{background:url(../img/menu-1-1.png) 50% 50% no-repeat #ebebeb }
#gnb .on .menu-1{background:url(../img/menu-1.png) 50% 50% no-repeat #fff}
#gnb .gnb_li .menu-2{background:url(../img/menu-2-1.png) 50% 50% no-repeat #ebebeb }
#gnb .on .menu-2{background:url(../img/menu-2.png) 50% 50% no-repeat #fff}
#gnb .gnb_li .menu-3{background:url(../img/menu-3-1.png) 50% 50% no-repeat #ebebeb }
#gnb .on .menu-3{background:url(../img/menu-3.png) 50% 50% no-repeat #fff}
#gnb .gnb_li .menu-4{background:url(../img/menu-7-1.png) 50% 50% no-repeat #ebebeb }
#gnb .on .menu-4{background:url(../img/menu-7.png) 50% 50% no-repeat #fff}
#gnb .gnb_li .menu-5{background:url(../img/menu-6-1.png) 50% 50% no-repeat #ebebeb }
#gnb .on .menu-5{background:url(../img/menu-6.png) 50% 50% no-repeat #fff}
#gnb .gnb_li .menu-6{background:url(../img/menu-4-1.png) 50% 50% no-repeat #ebebeb }
#gnb .on .menu-6{background:url(../img/menu-4.png) 50% 50% no-repeat #fff}
#gnb .gnb_li .btn_op{background:url(../img/menu_default.png) 50% 50% no-repeat #ebebeb}
#gnb .on .btn_op{background:url(../img/menu_default_on.png) 50% 50% no-repeat #fff}
#gnb .gnb_li .btn_op.menu-100{background:url(../img/menu-1-1.png) 50% 50% no-repeat #ebebeb }
#gnb .on .btn_op.menu-100{background:url(../img/menu-1.png) 50% 50% no-repeat #fff}
#gnb .gnb_li .btn_op.menu-200{background:url(../img/menu-2-1.png) 50% 50% no-repeat #ebebeb }
#gnb .on .btn_op.menu-200{background:url(../img/menu-2.png) 50% 50% no-repeat #fff}
#gnb .gnb_li .btn_op.menu-300{background:url(../img/menu-3-1.png) 50% 50% no-repeat #ebebeb }
#gnb .on .btn_op.menu-300{background:url(../img/menu-3.png) 50% 50% no-repeat #fff}
#gnb .gnb_li .btn_op.menu-400{background:url(../img/menu-7-1.png) 50% 50% no-repeat #ebebeb }
#gnb .on .btn_op.menu-400{background:url(../img/menu-7.png) 50% 50% no-repeat #fff}
#gnb .gnb_li .btn_op.menu-500{background:url(../img/menu-6-1.png) 50% 50% no-repeat #ebebeb }
#gnb .on .btn_op.menu-500{background:url(../img/menu-6.png) 50% 50% no-repeat #fff}
#gnb .gnb_li .btn_op.menu-900{background:url(../img/menu-4-1.png) 50% 50% no-repeat #ebebeb }
#gnb .on .btn_op.menu-900{background:url(../img/menu-4.png) 50% 50% no-repeat #fff}
#gnb .gnb_li button:hover{background-color:#f3f3f3}
#gnb .gnb_oparea{display:none;position:absolute;top:0;left:50px;background:#fff;height:100%;width:170px;padding:20px;border-right:1px solid #dbdbdb;
-webkit-box-shadow: 2px 0 2px rgba(150,150,150,100.1);
@@ -687,7 +689,7 @@ box-shadow: 2px 2px 3px 0px rgba(0,0,0,0.2);}
.theme_p{margin:0 0 10px }
#theme_list{padding:0;margin:0;list-style:none; width: 1000px;position:relative}
#theme_list:after{display:block;visibility:hidden;clear:both;content:""}
#theme_list li{margin:10px 10px 10px 0 ;margin:0;float:left;}
#theme_list li{margin:10px 10px 10px 0;float:left}
#theme_list li:after{display:block;visibility:hidden;clear:both;content:""}
#theme_list li .tmli_if{border: 1px solid #d1dee2;width:302px;}
#theme_list li .tmli_if>img{width:300px;height:225px;}
@@ -747,4 +749,14 @@ box-shadow: 2px 2px 3px 0px rgba(0,0,0,0.2);}
#processing{margin: 0 auto;padding: 70px 0;border: 1px solid #eee;background: #f9f9f9;text-align:center;}
#processing p{font-size:1.2em}
.check_processing {width:300px;height:300px;margin:0 auto;background:url(../img/check.png) no-repeat 50% 50% }
#processing button{background:#ff3061;border:none;color:#fff;padding: 15px;width:200px;margin-top:15px;border-radius:5px;font-weight:bold;font-size:1.167em}
#processing button{background:#ff3061;border:none;color:#fff;padding: 15px;width:200px;margin-top:15px;border-radius:5px;font-weight:bold;font-size:1.167em}
@media only screen and (max-device-width : 768px) and (orientation : landscape){
/* Styles */
input[type="text"]{max-width:200px}
}
@media only screen and (max-device-width : 480px) and (orientation : portrait){
/* Styles */
input[type="text"]{max-width:200px}
}
+1 -1
View File
@@ -1,6 +1,6 @@
@charset "utf-8";
#preview_item{height:50px}
#preview_item ul{margin:0;padding:0;top:0;width:100%margin:0 auto;text-align:center;background:#000;position:fixed;top:0;z-index:999999;width:100%;}
#preview_item ul{margin:0;padding:0;top:0;width:100%;margin:0 auto;text-align:center;background:#000;position:fixed;top:0;z-index:999999}
#preview_item ul li{list-style:none;display:inline-block;height:50px;line-height:50px;padding:0 2px;*display:inline; zoom:1;}
#preview_item ul li a{color:#ccc;padding:0 8px;height:32px;line-height:30px;background:none;font-weight:bold;border-radius:5px;display:inline-block;vertical-align:middle;border:1px solid #aaa;}
#preview_item ul li a:hover{background:#fff;text-decoration:none;border:1px solid #ccc;color:#333}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

+1 -1
View File
@@ -106,7 +106,7 @@ include_once('./admin.head.php');
<?php } ?>
</tbody>
</table>
<textarea name="ma_list" style="display:none"><?=$ma_list?></textarea>
<textarea name="ma_list" style="display:none"><?php echo $ma_list?></textarea>
</div>
<div class="btn_confirm01 btn_confirm">
+23 -2
View File
@@ -249,6 +249,22 @@ add_javascript(G5_POSTCODE_JS, 0); //다음 주소 js
?>
</td>
</tr>
<tr>
<th scope="row"><label for="mb_img">회원이미지</label></th>
<td colspan="3">
<?php echo help('이미지 크기는 <strong>넓이 '.$config['cf_member_img_width'].'픽셀 높이 '.$config['cf_member_img_height'].'픽셀</strong>로 해주세요.') ?>
<input type="file" name="mb_img" id="mb_img">
<?php
$mb_dir = substr($mb['mb_id'],0,2);
$icon_file = G5_DATA_PATH.'/member_image/'.$mb_dir.'/'.$mb['mb_id'].'.gif';
if (file_exists($icon_file)) {
$icon_url = G5_DATA_URL.'/member_image/'.$mb_dir.'/'.$mb['mb_id'].'.gif';
echo '<img src="'.$icon_url.'" alt="">';
echo '<input type="checkbox" id="del_mb_img" name="del_mb_img" value="1">삭제';
}
?>
</td>
</tr>
<tr>
<th scope="row">메일 수신</th>
<td>
@@ -447,8 +463,13 @@ this.form.mb_intercept_date.value=this.form.mb_intercept_date.defaultValue; }">
<script>
function fmember_submit(f)
{
if (!f.mb_icon.value.match(/\.gif$/i) && f.mb_icon.value) {
alert('아이콘은 gif 파일만 가능합니다.');
if (!f.mb_icon.value.match(/\.(gif|jpe?g|png)$/i) && f.mb_icon.value) {
alert('아이콘은 이미지 파일만 가능합니다.');
return false;
}
if (!f.mb_img.value.match(/\.(gif|jpe?g|png)$/i) && f.mb_img.value) {
alert('회원이미지는 이미지 파일만 가능합니다.');
return false;
}
+74 -11
View File
@@ -2,6 +2,7 @@
$sub_menu = "200100";
include_once("./_common.php");
include_once(G5_LIB_PATH."/register.lib.php");
include_once(G5_LIB_PATH.'/thumbnail.lib.php');
if ($w == 'u')
check_demo();
@@ -120,26 +121,88 @@ else if ($w == 'u')
if ($del_mb_icon)
@unlink(G5_DATA_PATH.'/member/'.$mb_dir.'/'.$mb_id.'.gif');
$image_regex = "/(\.(gif|jpe?g|png))$/i";
$mb_icon_img = $mb_id.'.gif';
// 아이콘 업로드
if (is_uploaded_file($_FILES['mb_icon']['tmp_name'])) {
if (!preg_match("/(\.gif)$/i", $_FILES['mb_icon']['name'])) {
alert($_FILES['mb_icon']['name'] . '은(는) gif 파일이 아닙니다.');
if (isset($_FILES['mb_icon']) && is_uploaded_file($_FILES['mb_icon']['tmp_name'])) {
if (!preg_match($image_regex, $_FILES['mb_icon']['name'])) {
alert($_FILES['mb_icon']['name'] . '은(는) 이미지 파일이 아닙니다.');
}
if (preg_match("/(\.gif)$/i", $_FILES['mb_icon']['name'])) {
@mkdir(G5_DATA_PATH.'/member/'.$mb_dir, G5_DIR_PERMISSION);
@chmod(G5_DATA_PATH.'/member/'.$mb_dir, G5_DIR_PERMISSION);
if (preg_match($image_regex, $_FILES['mb_icon']['name'])) {
$mb_icon_dir = G5_DATA_PATH.'/member/'.$mb_dir;
@mkdir($mb_icon_dir, G5_DIR_PERMISSION);
@chmod($mb_icon_dir, G5_DIR_PERMISSION);
$dest_path = G5_DATA_PATH.'/member/'.$mb_dir.'/'.$mb_id.'.gif';
$dest_path = $mb_icon_dir.'/'.$mb_icon_img;
move_uploaded_file($_FILES['mb_icon']['tmp_name'], $dest_path);
chmod($dest_path, G5_FILE_PERMISSION);
if (file_exists($dest_path)) {
$size = @getimagesize($dest_path);
if ($size[0] > $config['cf_member_icon_width'] || $size[1] > $config['cf_member_icon_height']) {
$thumb = null;
if($size[2] === 2 || $size[2] === 3) {
//jpg 또는 png 파일 적용
$thumb = thumbnail($mb_icon_img, $mb_icon_dir, $mb_icon_dir, $config['cf_member_icon_width'], $config['cf_member_icon_height'], true, true);
if($thumb) {
@unlink($dest_path);
rename($mb_icon_dir.'/'.$thumb, $dest_path);
}
}
if( !$thumb ){
// 아이콘의 폭 또는 높이가 설정값 보다 크다면 이미 업로드 된 아이콘 삭제
@unlink($dest_path);
}
}
}
}
}
$mb_img_dir = G5_DATA_PATH.'/member_image/';
if( !is_dir($mb_img_dir) ){
@mkdir($mb_img_dir, G5_DIR_PERMISSION);
@chmod($mb_img_dir, G5_DIR_PERMISSION);
}
$mb_img_dir .= substr($mb_id,0,2);
// 회원 이미지 삭제
if ($del_mb_img)
@unlink($mb_img_dir.'/'.$mb_icon_img);
// 아이콘 업로드
if (isset($_FILES['mb_img']) && is_uploaded_file($_FILES['mb_img']['tmp_name'])) {
if (!preg_match($image_regex, $_FILES['mb_img']['name'])) {
alert($_FILES['mb_img']['name'] . '은(는) 이미지 파일이 아닙니다.');
}
if (preg_match($image_regex, $_FILES['mb_img']['name'])) {
@mkdir($mb_img_dir, G5_DIR_PERMISSION);
@chmod($mb_img_dir, G5_DIR_PERMISSION);
$dest_path = $mb_img_dir.'/'.$mb_icon_img;
move_uploaded_file($_FILES['mb_img']['tmp_name'], $dest_path);
chmod($dest_path, G5_FILE_PERMISSION);
if (file_exists($dest_path)) {
$size = getimagesize($dest_path);
// 아이콘의 폭 또는 높이가 설정값 보다 크다면 이미 업로드 된 아이콘 삭제
if ($size[0] > $config['cf_member_icon_width'] || $size[1] > $config['cf_member_icon_height']) {
@unlink($dest_path);
$size = @getimagesize($dest_path);
if ($size[0] > $config['cf_member_img_width'] || $size[1] > $config['cf_member_img_height']) {
$thumb = null;
if($size[2] === 2 || $size[2] === 3) {
//jpg 또는 png 파일 적용
$thumb = thumbnail($mb_icon_img, $mb_img_dir, $mb_img_dir, $config['cf_member_img_width'], $config['cf_member_img_height'], true, true);
if($thumb) {
@unlink($dest_path);
rename($mb_img_dir.'/'.$thumb, $dest_path);
}
}
if( !$thumb ){
// 아이콘의 폭 또는 높이가 설정값 보다 크다면 이미 업로드 된 아이콘 삭제
@unlink($dest_path);
}
}
}
}
+2
View File
@@ -10,6 +10,8 @@ if (!count($_POST['chk'])) {
auth_check($auth[$sub_menu], 'w');
check_admin_token();
if ($_POST['act_button'] == "선택수정") {
for ($i=0; $i<count($_POST['chk']); $i++)
+2
View File
@@ -4,6 +4,8 @@ include_once('./_common.php');
auth_check($auth[$sub_menu], 'w');
$po_id = isset($po_id) ? (int) $po_id : 0;
$html_title = '투표';
if ($w == '')
$html_title .= ' 생성';
+34
View File
@@ -10,6 +10,40 @@ auth_check($auth[$sub_menu], 'w');
check_admin_token();
$check_keys = array(
'po_subject',
'po_poll1',
'po_poll2',
'po_poll3',
'po_poll4',
'po_poll5',
'po_poll6',
'po_poll7',
'po_poll8',
'po_poll9',
'po_cnt1',
'po_cnt2',
'po_cnt3',
'po_cnt4',
'po_cnt5',
'po_cnt6',
'po_cnt7',
'po_cnt8',
'po_cnt9',
'po_etc',
'po_level',
'po_point',
'po_id'
);
foreach( $_POST as $key=>$value ){
if( empty($value) ) continue;
if( in_array($key, $check_keys) ) {
$_POST[$key] = strip_tags($value);
}
}
if ($w == '')
{
$sql = " insert {$g5['poll_table']}
+28 -17
View File
@@ -13,26 +13,37 @@ $g5['title'] = '메일 테스트';
include_once('./admin.head.php');
if (isset($_POST['email'])) {
$_POST['email'] = strip_tags($_POST['email']);
$email = explode(',', $_POST['email']);
for ($i=0; $i<count($email); $i++)
mailer($config['cf_admin_email_name'], $config['cf_admin_email'], trim($email[$i]), '[메일검사] 제목', '<span style="font-size:9pt;">[메일검사] 내용<p>이 내용이 제대로 보인다면 보내는 메일 서버에는 이상이 없는것입니다.<p>'.G5_TIME_YMDHIS.'<p>이 메일 주소로는 회신되지 않습니다.</span>', 1);
echo '<section>';
echo '<h2>결과메세지</h2>';
echo '<div class="local_desc01 local_desc"><p>';
echo '다음 '.count($email).'개의 메일 주소로 테스트 메일 발송이 완료되었습니다.';
echo '</p></div>';
echo '<ul>';
for ($i=0;$i<count($email);$i++) {
echo '<li>'.$email[$i].'</li>';
$real_email = array();
for ($i=0; $i<count($email); $i++){
if (!preg_match("/([0-9a-zA-Z_-]+)@([0-9a-zA-Z_-]+)\.([0-9a-zA-Z_-]+)/", $email[$i])) continue;
$real_email[] = $email[$i];
mailer($config['cf_admin_email_name'], $config['cf_admin_email'], trim($email[$i]), '[메일검사] 제목', '<span style="font-size:9pt;">[메일검사] 내용<p>이 내용이 제대로 보인다면 보내는 메일 서버에는 이상이 없는것입니다.<p>'.G5_TIME_YMDHIS.'<p>이 메일 주소로는 회신되지 않습니다.</span>', 1);
}
if( $real_email ){
echo '<section>';
echo '<h2>결과메세지</h2>';
echo '<div class="local_desc01 local_desc"><p>';
echo '다음 '.count($real_email).'개의 메일 주소로 테스트 메일 발송이 완료되었습니다.';
echo '</p></div>';
echo '<ul>';
for ($i=0;$i<count($real_email);$i++) {
echo '<li>'.$real_email[$i].'</li>';
}
echo '</ul>';
echo '<div class="local_desc02 local_desc"><p>';
echo '해당 주소로 테스트 메일이 도착했는지 확인해 주십시오.<br>';
echo '만약, 테스트 메일이 오지 않는다면 더 다양한 계정의 메일 주소로 메일을 보내 보십시오.<br>';
echo '그래도 메일이 하나도 도착하지 않는다면 메일 서버(sendmail server)의 오류일 가능성이 높으니, 웹 서버관리자에게 문의하여 주십시오.<br>';
echo '</p></div>';
echo '</section>';
}
echo '</ul>';
echo '<div class="local_desc02 local_desc"><p>';
echo '해당 주소로 테스트 메일이 도착했는지 확인해 주십시오.<br>';
echo '만약, 테스트 메일이 오지 않는다면 더 다양한 계정의 메일 주소로 메일을 보내 보십시오.<br>';
echo '그래도 메일이 하나도 도착하지 않는다면 메일 서버(sendmail server)의 오류일 가능성이 높으니, 웹 서버관리자에게 문의하여 주십시오.<br>';
echo '</p></div>';
echo '</section>';
}
?>
+9 -5
View File
@@ -10,9 +10,9 @@ if ($w == 'u') // 업데이트
{
// 실제 번호를 넘김
$k = $_POST['chk'][$i];
$fg_no = $_POST['fg_no'][$k];
$fg_name = $_POST['fg_name'][$k];
$fg_member = $_POST['fg_member'][$k];
$fg_no = (int) $_POST['fg_no'][$k];
$fg_name = strip_tags($_POST['fg_name'][$k]);
$fg_member = strip_tags($_POST['fg_member'][$k]);
if (!is_numeric($fg_no))
alert('그룹 고유번호가 없습니다.');
@@ -38,7 +38,7 @@ else if ($w == 'de') // 그룹삭제
{
// 실제 번호를 넘김
$k = $_POST['chk'][$i];
$fg_no = $_POST['fg_no'][$k];
$fg_no = (int) $_POST['fg_no'][$k];
if (!is_numeric($fg_no))
alert('그룹 고유번호가 없습니다.');
@@ -57,7 +57,7 @@ else if ($w == 'em')
{
// 실제 번호를 넘김
$k = $_POST['chk'][$i];
$fg_no = $_POST['fg_no'][$k];
$fg_no = (int) $_POST['fg_no'][$k];
if ($fg_no == 'no') $fg_no = 0;
@@ -71,6 +71,8 @@ else if ($w == 'no')
{
if ($fg_no == 'no') $fg_no = 0;
$fg_no = (int) $fg_no;
if ($fg_no)
sql_query("update {$g5['sms5_form_group_table']} set fg_count = 0 where fg_no = '$fg_no'");
@@ -81,6 +83,8 @@ else // 등록
if (!strlen(trim($fg_name)))
alert('그룹명을 입력해주세요');
$fg_name = strip_tags($fg_name);
$res = sql_fetch("select fg_name from {$g5['sms5_form_group_table']} where fg_name = '$fg_name'");
if ($res)
alert('같은 그룹명이 존재합니다.');
+3
View File
@@ -4,6 +4,9 @@ include_once("./_common.php");
auth_check($auth[$sub_menu], "w");
$fo_name = isset($fo_name) ? strip_tags($fo_name) : '';
$fo_content = isset($fo_content) ? strip_tags($fo_content) : '';
$g5['title'] = "이모티콘 업데이트";
if ($w == 'u') // 업데이트
+6 -4
View File
@@ -10,8 +10,8 @@ if ($w == 'u') // 업데이트
{
// 실제 번호를 넘김
$k = $_POST['chk'][$i];
$bg_no = $_POST['bg_no'][$k];
$bg_name = $_POST['bg_name'][$k];
$bg_no = (int) $_POST['bg_no'][$k];
$bg_name = strip_tags($_POST['bg_name'][$k]);
if (!is_numeric($bg_no))
alert('그룹 고유번호가 없습니다.');
@@ -36,7 +36,7 @@ else if ($w == 'de') // 그룹삭제
{
// 실제 번호를 넘김
$k = $_POST['chk'][$i];
$bg_no = $_POST['bg_no'][$k];
$bg_no = (int) $_POST['bg_no'][$k];
if (!is_numeric($bg_no))
alert('그룹 고유번호가 없습니다.');
@@ -55,7 +55,7 @@ else if ($w == 'em') // 비우기
{
// 실제 번호를 넘김
$k = $_POST['chk'][$i];
$bg_no = $_POST['bg_no'][$k];
$bg_no = (int) $_POST['bg_no'][$k];
sql_query("update {$g5['sms5_book_group_table']} set bg_count = 0, bg_member = 0, bg_nomember = 0, bg_receipt = 0, bg_reject = 0 where bg_no='$bg_no'");
sql_query("delete from {$g5['sms5_book_table']} where bg_no='$bg_no'");
@@ -63,6 +63,8 @@ else if ($w == 'em') // 비우기
}
else // 등록
{
$bg_name = strip_tags($bg_name);
if (!strlen(trim($bg_name)))
alert('그룹명을 입력해주세요');
+1 -1
View File
@@ -49,7 +49,7 @@ $now_year = (int)substr(G5_TIME_YMD, 0, 4);
<option value="specific">선택년월의 자료삭제</option>
</select>
</div>
<div class="visit_del_bt"">
<div class="visit_del_bt">
<label for="pass">관리자 비밀번호<strong class="sound_only"> 필수</strong></label>
<input type="password" name="pass" id="pass" class="frm_input required">
<input type="submit" value="확인" class="btn_submit">
+2 -2
View File
@@ -15,7 +15,7 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'">처음</a>'; //페이지 처
<div class="local_sch local_sch01">
<form name="fvisit" method="get" onsubmit="return fvisit_submit(this);">
<?=$listall?>
<?php echo $listall?>
<label for="sch_sort" class="sound_only">검색분류</label>
<select name="sfl" id="sch_sort" class="search_sort">
<option value="vi_ip"<?php echo get_selected($sfl, 'vi_ip'); ?>>IP</option>
@@ -104,7 +104,7 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'">처음</a>'; //페이지 처
?>
<tr class="<?php echo $bg; ?>">
<td class="td_id"><a href="<?php echo $_SERVER['SCRIPT_NAME']; ?>?sfl=vi_ip&amp;stx=<?php echo $ip; ?>"><?php echo $ip; ?></a></td>
<td class="td_left"><?php echo $link.$title; ?></a></td>
<td class="td_left"><?php echo $link.$title; ?><?php echo $link ? '</a>' : ''; ?></td>
<td class="td_idsmall td_category1"><?php echo $brow; ?></td>
<td class="td_idsmall td_category3"><?php echo $os; ?></td>
<td class="td_idsmall td_category2"><?php echo $device; ?></td>
+2 -3
View File
@@ -129,7 +129,7 @@ switch ($day) {
<div id="wr_cont">
<form>
<select name="bo_table">
<option value="">전체게시판</a>
<option value="">전체게시판</option>
<?php
$sql = " select bo_table, bo_subject from {$g5['board_table']} order by bo_count_write desc ";
$result = sql_query($sql);
@@ -173,7 +173,6 @@ if (empty($line1) || empty($line2)) {
} else {
?>
<div id="chart1" style="height:500px; width:100%;"></div>
<div>
<script>
$(document).ready(function(){
var line1 = [<?php echo implode($line1, ','); ?>];
@@ -204,7 +203,7 @@ $(document).ready(function(){
<?php
}
?>
</div>
<?php
include_once ('./admin.tail.php');
?>
+2 -2
View File
@@ -136,7 +136,7 @@ if (isset($wr_id) && $wr_id) {
set_session($ss_name, TRUE);
}
$g5['title'] = ((G5_IS_MOBILE && $board['bo_mobile_subject']) ? $board['bo_mobile_subject'] : $board['bo_subject']);
$g5['title'] = strip_tags(conv_subject($write['wr_subject'], 255))." > ".((G5_IS_MOBILE && $board['bo_mobile_subject']) ? $board['bo_mobile_subject'] : $board['bo_subject']);
} else {
if ($member['mb_level'] < $board['bo_list_level']) {
if ($member['mb_id'])
@@ -171,7 +171,7 @@ if (isset($wr_id) && $wr_id) {
if (!isset($page) || (isset($page) && $page == 0)) $page = 1;
$g5['title'] = ((G5_IS_MOBILE && $board['bo_mobile_subject']) ? $board['bo_mobile_subject'] : $board['bo_subject']) ;
$g5['title'] = ((G5_IS_MOBILE && $board['bo_mobile_subject']) ? $board['bo_mobile_subject'] : $board['bo_subject']).' '.$page.' 페이지';
}
include_once(G5_PATH.'/head.sub.php');
+10 -3
View File
@@ -15,9 +15,16 @@ set_cookie('ck_auto', '', 0);
// 자동로그인 해제 end --------------------------------
if ($url) {
$p = @parse_url($url);
if ($p['scheme'] || $p['host']) {
alert('url에 도메인을 지정할 수 없습니다.');
if ( substr($url, 0, 2) == '//' )
$url = 'http:' . $url;
$p = @parse_url(urldecode($url));
/*
// OpenRediect 취약점관련, PHP 5.3 이하버전에서는 parse_url 버그가 있음 ( Safflower 님 제보 ) 아래 url 예제
// http://localhost/bbs/logout.php?url=http://sir.kr%23@/
*/
if (preg_match('/^https?:\/\//i', $url) || $p['scheme'] || $p['host']) {
alert('url에 도메인을 지정할 수 없습니다.', G5_URL);
}
$link = $url;
+11 -3
View File
@@ -4,6 +4,8 @@ include_once('./_common.php');
if ($is_guest)
alert_close('회원만 이용하실 수 있습니다.');
set_session('ss_memo_delete_token', $token = uniqid(time()));
$g5['title'] = '내 쪽지함';
include_once(G5_PATH.'/head.sub.php');
@@ -20,6 +22,10 @@ $sql = " select count(*) as cnt from {$g5['memo_table']} where me_{$kind}_mb_id
$row = sql_fetch($sql);
$total_count = number_format($row['cnt']);
$total_page = ceil($total_count / $config['cf_page_rows']); // 전체 페이지 계산
if ($page < 1) { $page = 1; } // 페이지가 없으면 첫 페이지 (1 페이지)
$from_record = ((int) $page - 1) * $config['cf_page_rows']; // 시작 열을 구함
if ($kind == 'recv')
{
$kind_title = '받은';
@@ -39,7 +45,7 @@ $sql = " select a.*, b.mb_id, b.mb_nick, b.mb_email, b.mb_homepage
from {$g5['memo_table']} a
left join {$g5['member_table']} b on (a.me_{$unkind}_mb_id = b.mb_id)
where a.me_{$kind}_mb_id = '{$member['mb_id']}'
order by a.me_id desc ";
order by a.me_id desc limit $from_record, {$config['cf_page_rows']} ";
$result = sql_query($sql);
for ($i=0; $row=sql_fetch_array($result); $i++)
{
@@ -64,10 +70,12 @@ for ($i=0; $row=sql_fetch_array($result); $i++)
$list[$i]['name'] = $name;
$list[$i]['send_datetime'] = $send_datetime;
$list[$i]['read_datetime'] = $read_datetime;
$list[$i]['view_href'] = './memo_view.php?me_id='.$row['me_id'].'&amp;kind='.$kind;
$list[$i]['del_href'] = './memo_delete.php?me_id='.$row['me_id'].'&amp;kind='.$kind;
$list[$i]['view_href'] = './memo_view.php?me_id='.$row['me_id'].'&amp;kind='.$kind.'&amp;page='.$page;
$list[$i]['del_href'] = './memo_delete.php?me_id='.$row['me_id'].'&amp;token='.$token.'&amp;kind='.$kind;
}
$write_pages = get_paging(G5_IS_MOBILE ? $config['cf_mobile_pages'] : $config['cf_write_pages'], $page, $total_page, "./memo.php?kind=$kind".$qstr."&amp;page=");
include_once($member_skin_path.'/memo.skin.php');
include_once(G5_PATH.'/tail.sub.php');
+6
View File
@@ -4,6 +4,12 @@ include_once('./_common.php');
if (!$is_member)
alert('회원만 이용하실 수 있습니다.');
$delete_token = get_session('ss_memo_delete_token');
set_session('ss_memo_delete_token', '');
if (!($token && $delete_token == $token))
alert('토큰 에러로 삭제 불가합니다.');
$me_id = (int)$_REQUEST['me_id'];
$sql = " select * from {$g5['memo_table']} where me_id = '{$me_id}' ";
+10 -2
View File
@@ -57,14 +57,22 @@ $sql = " select * from {$g5[memo_table]}
order by me_id desc
limit 1 ";
$next = sql_fetch($sql);
if ($next[me_id])
$next_link = './memo_view.php?kind='.$kind.'&amp;me_id='.$next[me_id];
if ($next['me_id'])
$next_link = './memo_view.php?kind='.$kind.'&amp;me_id='.$next['me_id'];
else
//$next_link = 'javascript:alert(\'쪽지의 마지막입니다.\');';
$next_link = '';
$mb = get_member($memo['me_'.$unkind.'_mb_id']);
$list_link = './memo.php?kind='.$kind;
if(isset($page) && $page){
$prev_link .= '&amp;page='.(int) $page;
$next_link .= '&amp;page='.(int) $page;
$list_link .= '&amp;page='.(int) $page;
}
include_once($member_skin_path.'/memo_view.skin.php');
include_once(G5_PATH.'/tail.sub.php');
+6
View File
@@ -4,6 +4,12 @@ include_once('./_common.php');
if($is_guest)
alert('회원이시라면 로그인 후 이용해 주십시오.', G5_URL);
$delete_token = get_session('ss_qa_delete_token');
set_session('ss_qa_delete_token', '');
if (!($token && $delete_token == $token))
alert('토큰 에러로 삭제 불가합니다.');
$tmp_array = array();
if ($qa_id) // 건별삭제
$tmp_array[0] = $qa_id;
+2 -1
View File
@@ -109,7 +109,8 @@ if(is_file($skin_file)) {
*/
if(($view['qa_type'] && $is_admin) || (!$view['qa_type'] && $view['qa_status'] == 0)) {
$update_href = G5_BBS_URL.'/qawrite.php?w=u&amp;qa_id='.$view['qa_id'].$qstr;
$delete_href = G5_BBS_URL.'/qadelete.php?qa_id='.$view['qa_id'].$qstr;
set_session('ss_qa_delete_token', $token = uniqid(time()));
$delete_href = G5_BBS_URL.'/qadelete.php?qa_id='.$view['qa_id'].'&amp;token='.$token.$qstr;
}
// 질문글이고 등록된 답변이 있다면
+1 -1
View File
@@ -200,7 +200,7 @@ for ($i=1; $i<=count($_FILES['bf_file']['name']); $i++) {
$upload[$i]['filesize'] = $filesize;
// 아래의 문자열이 들어간 파일은 -x 를 붙여서 웹경로를 알더라도 실행을 하지 못하도록 함
$filename = preg_replace("/\.(php|phtm|htm|cgi|pl|exe|jsp|asp|inc)/i", "$0-x", $filename);
$filename = preg_replace("/\.(php|pht|phtm|htm|cgi|pl|exe|jsp|asp|inc)/i", "$0-x", $filename);
shuffle($chars_array);
$shuffle = implode('', $chars_array);
+49 -22
View File
@@ -3,6 +3,7 @@ include_once('./_common.php');
include_once(G5_CAPTCHA_PATH.'/captcha.lib.php');
include_once(G5_LIB_PATH.'/register.lib.php');
include_once(G5_LIB_PATH.'/mailer.lib.php');
include_once(G5_LIB_PATH.'/thumbnail.lib.php');
// 리퍼러 체크
referer_check();
@@ -362,13 +363,16 @@ $msg = "";
// 아이콘 업로드
$mb_icon = '';
$image_regex = "/(\.(gif|jpe?g|png))$/i";
$mb_icon_img = $mb_id.'.gif';
if (isset($_FILES['mb_icon']) && is_uploaded_file($_FILES['mb_icon']['tmp_name'])) {
if (preg_match("/(\.gif)$/i", $_FILES['mb_icon']['name'])) {
if (preg_match($image_regex, $_FILES['mb_icon']['name'])) {
// 아이콘 용량이 설정값보다 이하만 업로드 가능
if ($_FILES['mb_icon']['size'] <= $config['cf_member_icon_size']) {
@mkdir($mb_dir, G5_DIR_PERMISSION);
@chmod($mb_dir, G5_DIR_PERMISSION);
$dest_path = $mb_dir.'/'.$mb_id.'.gif';
$dest_path = $mb_dir.'/'.$mb_icon_img;
move_uploaded_file($_FILES['mb_icon']['tmp_name'], $dest_path);
chmod($dest_path, G5_FILE_PERMISSION);
if (file_exists($dest_path)) {
@@ -377,13 +381,24 @@ if (isset($_FILES['mb_icon']) && is_uploaded_file($_FILES['mb_icon']['tmp_name']
// gif 파일에 악성코드를 심어 업로드 하는 경우를 방지
// 에러메세지는 출력하지 않는다.
//-----------------------------------------------------------------
$size = getimagesize($dest_path);
if ($size[2] != 1) // gif 파일이 아니면 올라간 이미지를 삭제한다.
@unlink($dest_path);
else
// 아이콘의 폭 또는 높이가 설정값 보다 크다면 이미 업로드 된 아이콘 삭제
if ($size[0] > $config['cf_member_icon_width'] || $size[1] > $config['cf_member_icon_height'])
$size = @getimagesize($dest_path);
if (!($size[2] === 1 || $size[2] === 2 || $size[2] === 3)) { // jpg, gif, png 파일이 아니면 올라간 이미지를 삭제한다.
@unlink($dest_path);
} else if ($size[0] > $config['cf_member_icon_width'] || $size[1] > $config['cf_member_icon_height']) {
$thumb = null;
if($size[2] === 2 || $size[2] === 3) {
//jpg 또는 png 파일 적용
$thumb = thumbnail($mb_icon_img, $mb_dir, $mb_dir, $config['cf_member_icon_width'], $config['cf_member_icon_height'], true, true);
if($thumb) {
@unlink($dest_path);
rename($mb_dir.'/'.$thumb, $dest_path);
}
}
if( !$thumb ){
// 아이콘의 폭 또는 높이가 설정값 보다 크다면 이미 업로드 된 아이콘 삭제
@unlink($dest_path);
}
}
//=================================================================\
}
} else {
@@ -391,7 +406,7 @@ if (isset($_FILES['mb_icon']) && is_uploaded_file($_FILES['mb_icon']['tmp_name']
}
} else {
$msg .= $_FILES['mb_icon']['name'].'은(는) gif 파일이 아닙니다.';
$msg .= $_FILES['mb_icon']['name'].'은(는) 이미지 파일이 아닙니다.';
}
}
@@ -406,34 +421,46 @@ if( $config['cf_member_img_size'] && $config['cf_member_img_width'] && $config['
// 아이콘 삭제
if (isset($_POST['del_mb_img'])) {
@unlink($mb_dir.'/'.$mb_id.'.gif');
@unlink($mb_dir.'/'.$mb_icon_img);
}
$msg = '';
// 회원 프로필 이미지 업로드
$mb_img = '';
if (isset($_FILES['mb_img']) && is_uploaded_file($_FILES['mb_img']['tmp_name'])) {
if (preg_match("/(\.gif)$/i", $_FILES['mb_img']['name']) || preg_match("/(\.jpg)$/i", $_FILES['mb_img']['name'])) {
$msg = $msg ? $msg."\\r\\n" : '';
if (preg_match($image_regex, $_FILES['mb_img']['name'])) {
// 아이콘 용량이 설정값보다 이하만 업로드 가능
if ($_FILES['mb_icon']['size'] <= $config['cf_member_img_size']) {
if ($_FILES['mb_img']['size'] <= $config['cf_member_img_size']) {
@mkdir($mb_dir, G5_DIR_PERMISSION);
@chmod($mb_dir, G5_DIR_PERMISSION);
$dest_path = $mb_dir.'/'.$mb_id.'.gif';
$dest_path = $mb_dir.'/'.$mb_icon_img;
move_uploaded_file($_FILES['mb_img']['tmp_name'], $dest_path);
chmod($dest_path, G5_FILE_PERMISSION);
if (file_exists($dest_path)) {
$size = getimagesize($dest_path);
if ( ! ($size[2] === 1 || $size[2] === 2) ) // gif 또는 jpg 파일이 아니면 올라간 이미지를 삭제한다.
@unlink($dest_path);
else
// 이미지의 폭 또는 높이가 설정값 보다 크다면 이미 업로드 된 아이콘 삭제
if ($size[0] > $config['cf_member_img_width'] || $size[1] > $config['cf_member_img_height'])
$size = @getimagesize($dest_path);
if (!($size[2] === 1 || $size[2] === 2 || $size[2] === 3)) { // gif jpg png 파일이 아니면 올라간 이미지를 삭제한다.
@unlink($dest_path);
} else if ($size[0] > $config['cf_member_img_width'] || $size[1] > $config['cf_member_img_height']) {
$thumb = null;
if($size[2] === 2 || $size[2] === 3) {
//jpg 또는 png 파일 적용
$thumb = thumbnail($mb_icon_img, $mb_dir, $mb_dir, $config['cf_member_img_width'], $config['cf_member_img_height'], true, true);
if($thumb) {
@unlink($dest_path);
rename($mb_dir.'/'.$thumb, $dest_path);
}
}
if( !$thumb ){
// 아이콘의 폭 또는 높이가 설정값 보다 크다면 이미 업로드 된 아이콘 삭제
@unlink($dest_path);
}
}
//=================================================================\
}
} else {
$msg .= '회원아이콘을 '.number_format($config['cf_member_img_size']).'바이트 이하로 업로드 해주십시오.';
$msg .= '회원이미지을 '.number_format($config['cf_member_img_size']).'바이트 이하로 업로드 해주십시오.';
}
} else {
+6 -4
View File
@@ -25,20 +25,20 @@ if (!$board['bo_use_list_view']) {
$sql_search = " and " . $sql_search;
// 윗글을 얻음
$sql = " select wr_id, wr_subject from {$write_table} where wr_is_comment = 0 and wr_num = '{$write['wr_num']}' and wr_reply < '{$write['wr_reply']}' {$sql_search} order by wr_num desc, wr_reply desc limit 1 ";
$sql = " select wr_id, wr_subject, wr_datetime from {$write_table} where wr_is_comment = 0 and wr_num = '{$write['wr_num']}' and wr_reply < '{$write['wr_reply']}' {$sql_search} order by wr_num desc, wr_reply desc limit 1 ";
$prev = sql_fetch($sql);
// 위의 쿼리문으로 값을 얻지 못했다면
if (!$prev['wr_id']) {
$sql = " select wr_id, wr_subject from {$write_table} where wr_is_comment = 0 and wr_num < '{$write['wr_num']}' {$sql_search} order by wr_num desc, wr_reply desc limit 1 ";
$sql = " select wr_id, wr_subject, wr_datetime from {$write_table} where wr_is_comment = 0 and wr_num < '{$write['wr_num']}' {$sql_search} order by wr_num desc, wr_reply desc limit 1 ";
$prev = sql_fetch($sql);
}
// 아래글을 얻음
$sql = " select wr_id, wr_subject from {$write_table} where wr_is_comment = 0 and wr_num = '{$write['wr_num']}' and wr_reply > '{$write['wr_reply']}' {$sql_search} order by wr_num, wr_reply limit 1 ";
$sql = " select wr_id, wr_subject, wr_datetime from {$write_table} where wr_is_comment = 0 and wr_num = '{$write['wr_num']}' and wr_reply > '{$write['wr_reply']}' {$sql_search} order by wr_num, wr_reply limit 1 ";
$next = sql_fetch($sql);
// 위의 쿼리문으로 값을 얻지 못했다면
if (!$next['wr_id']) {
$sql = " select wr_id, wr_subject from {$write_table} where wr_is_comment = 0 and wr_num > '{$write['wr_num']}' {$sql_search} order by wr_num, wr_reply limit 1 ";
$sql = " select wr_id, wr_subject, wr_datetime from {$write_table} where wr_is_comment = 0 and wr_num > '{$write['wr_num']}' {$sql_search} order by wr_num, wr_reply limit 1 ";
$next = sql_fetch($sql);
}
}
@@ -48,6 +48,7 @@ $prev_href = '';
if (isset($prev['wr_id']) && $prev['wr_id']) {
$prev_wr_subject = get_text(cut_str($prev['wr_subject'], 255));
$prev_href = './board.php?bo_table='.$bo_table.'&amp;wr_id='.$prev['wr_id'].$qstr;
$prev_wr_date = $prev['wr_datetime'];
}
// 다음글 링크
@@ -55,6 +56,7 @@ $next_href = '';
if (isset($next['wr_id']) && $next['wr_id']) {
$next_wr_subject = get_text(cut_str($next['wr_subject'], 255));
$next_href = './board.php?bo_table='.$bo_table.'&amp;wr_id='.$next['wr_id'].$qstr;
$next_wr_date = $next['wr_datetime'];
}
// 쓰기 링크
+1 -1
View File
@@ -386,7 +386,7 @@ else
$captcha_html = '';
$captcha_js = '';
$is_use_captcha = ((!empty($board['bo_use_captcha']) || $is_guest) && !$is_admin) ? 1 : 0;
$is_use_captcha = ((($board['bo_use_captcha'] && $w!=='u') || $is_guest) && !$is_admin) ? 1 : 0;
if ($is_use_captcha) {
$captcha_html = captcha_html();
+2 -2
View File
@@ -188,7 +188,7 @@ if ($w == '' || $w == 'u') {
alert('w 값이 제대로 넘어오지 않았습니다.');
}
$is_use_captcha = ((!empty($board['bo_use_captcha']) || $is_guest) && !$is_admin) ? 1 : 0;
$is_use_captcha = ((($board['bo_use_captcha'] && $w!=='u') || $is_guest) && !$is_admin) ? 1 : 0;
if ($is_use_captcha && !chk_captcha()) {
alert('자동등록방지 숫자가 틀렸습니다.');
@@ -526,7 +526,7 @@ for ($i=0; $i<count($_FILES['bf_file']['name']); $i++) {
$upload[$i]['filesize'] = $filesize;
// 아래의 문자열이 들어간 파일은 -x 를 붙여서 웹경로를 알더라도 실행을 하지 못하도록 함
$filename = preg_replace("/\.(php|phtm|htm|cgi|pl|exe|jsp|asp|inc)/i", "$0-x", $filename);
$filename = preg_replace("/\.(php|pht|phtm|htm|cgi|pl|exe|jsp|asp|inc)/i", "$0-x", $filename);
shuffle($chars_array);
$shuffle = implode('', $chars_array);
+4 -3
View File
@@ -29,7 +29,8 @@ for ($i=0; $i<$ext_cnt; $i++) {
function g5_path()
{
$result['path'] = str_replace('\\', '/', dirname(__FILE__));
$chroot = substr($_SERVER['SCRIPT_FILENAME'], 0, strpos($_SERVER['SCRIPT_FILENAME'], dirname(__FILE__)));
$result['path'] = str_replace('\\', '/', $chroot.dirname(__FILE__));
$tilde_remove = preg_replace('/^\/\~[^\/]+(.*)$/', '$1', $_SERVER['SCRIPT_NAME']);
$document_root = str_replace($tilde_remove, '', $_SERVER['SCRIPT_FILENAME']);
$pattern = '/' . preg_quote($document_root, '/') . '/i';
@@ -139,7 +140,7 @@ if (file_exists($dbconfig_file)) {
sql_set_charset('utf8', $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."'");
if (defined('G5_TIMEZONE')) sql_query(" set time_zone = '".G5_TIMEZONE."'");
} else {
?>
@@ -489,7 +490,7 @@ if(isset($config['cf_theme']) && trim($config['cf_theme'])) {
// 테마 설정 로드
if(is_file(G5_THEME_PATH.'/theme.config.php'))
if(defined('G5_THEME_PATH') && is_file(G5_THEME_PATH.'/theme.config.php'))
include_once(G5_THEME_PATH.'/theme.config.php');
//=====================================================================================
+1 -1
View File
@@ -5,7 +5,7 @@
********************/
define('G5_VERSION', '그누보드5');
define('G5_GNUBOARD_VER', '5.3');
define('G5_GNUBOARD_VER', '5.3.0.2');
// 이 상수가 정의되지 않으면 각각의 개별 페이지는 별도로 실행될 수 없음
define('_GNUBOARD_', true);
+7
View File
@@ -423,6 +423,13 @@ box-shadow: 2px 2px 3px 0px rgba(0,0,0,0.2);}
box-shadow: inset 1px 1px 2px #222542;
}
/* cheditor 이슈 */
.cheditor-popup-window *, .cheditor-popup-window :after, .cheditor-popup-window :before {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
/* Mobile화면으로 */
#device_change {display:block;margin:0.3em;padding:0.5em 0;border:1px solid #eee;border-radius:2em;background:#fff;color:#000;font-size:2em;text-decoration:none;text-align:center}
+4 -4
View File
@@ -39,8 +39,8 @@ ul,li,dl,dt,dd{list-style:none;padding:0;margin:0}
#hd:after {display:block;visibility:hidden;clear:both;content:""}
#hd_h1 {position:absolute;font-size:0;text-indent:-9999em;line-height:0;overflow:hidden}
#logo {padding:15px 10px;height:50px;text-align:center}
#logo img{vertical-align:middle}
#logo {padding:10px 10px;height:50px;text-align:center}
#logo img{vertical-align:middle;max-height:100%;width:auto}
#gnb_open {position:absolute;top:10px;left:10px;padding:0 10px;height:30px;width:30px;border:0;background-size:70%;color:#fff;background:none; font-size: 16px;}
#gnb {display:none;background:#262626;position:fixed;top:0;left:0;z-index:99999;height:100%;overflow-y:auto;width:300px;
-webkit-box-shadow:0 0 5px rgba(55,55,5,0.4));
@@ -236,8 +236,8 @@ a.btn_admin:focus, a.btn_admin:hover {}
/* 기본폼 */
.form_01{margin:10px}
.form_01 div{margin:5px 0;position:relative}
.form_01 li{margin:5px 0;position:relative}
.form_01 .write_div{margin:5px 0;position:relative}
.form_01 li{margin:5px 0;position:relative;list-style:none}
.form_01 textarea, .frm_input {border:1px solid #ccc;background:#fff;color:#000;vertical-align:middle;border-radius:3px;padding:5px;}
.form_01 textarea {width:100%;height:100px}
.frm_input {height:40px;}
+9
View File
@@ -0,0 +1,9 @@
<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
// 유저 사이드뷰에서 아이콘 지정 안했을시 기본 no 프로필 이미지
define('G5_NO_PROFILE_IMG', '<span class="profile_img"><img src="'.G5_IMG_URL.'/no_profile.gif" alt="no_profile" width="20" height="20"></span>');
// 썸네일 처리 방식, 비율유지 하지 않고 썸네일을 생성하려면 주석을 풀고 값은 false 입력합니다. ( true 또는 주석으로 된 경우에는 비율 유지합니다. )
//define('G5_USE_THUMB_RATIO', false);
?>
+2 -2
View File
@@ -1,6 +1,6 @@
<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
define('G5_JS_VER', '171106');
define('G5_CSS_VER', '171106');
define('G5_JS_VER', '171222');
define('G5_CSS_VER', '171222');
?>
+43
View File
@@ -379,9 +379,52 @@ document.onkeydown = noRefresh ;
$comma = '';
$sql_common = '';
// 모바일 스킨 디렉토리
if( ! isset($row['bo_mobile_skin']) ){
$row['bo_mobile_skin'] = 'basic';
}
// 모바일 제목 길이
if( ! isset($row['bo_mobile_subject_len']) ){
$row['bo_mobile_subject_len'] = '30';
}
// 모바일 페이지당 목록 수
if( ! isset($row['bo_mobile_page_rows']) ){
$row['bo_mobile_page_rows'] = '15';
}
// 갤러리 이미지 폭 ( 리스트 )
if( ! isset($row['bo_gallery_width']) ){
$row['bo_gallery_width'] = '174';
}
// 갤러리 이미지 높이 ( 리스트 )
if( ! isset($row['bo_gallery_height']) ){
$row['bo_gallery_height'] = '124';
}
// 모바일 갤러리 이미지 폭 ( 리스트 )
if( ! isset($row['bo_mobile_gallery_width']) ){
$row['bo_mobile_gallery_width'] = '125';
}
// 모바일 갤러리 이미지 높이 ( 리스트 )
if( ! isset($row['bo_mobile_gallery_height']) ){
$row['bo_mobile_gallery_height'] = '100';
}
foreach($row as $key=>$val) {
if(!in_array($key, $columns))
continue;
if($key === 'bo_notice'){
$val = str_replace("\n", ",", $val);
if( substr($val, -1) === ',' ){
$val = substr($val, 0, -1);
}
}
$sql_common .= $comma . " $key = '".addslashes($val)."' ";
+1 -1
View File
@@ -385,7 +385,7 @@ fclose($f);
// data 디렉토리 및 하위 디렉토리에서는 .htaccess .htpasswd .php .phtml .html .htm .inc .cgi .pl 파일을 실행할수 없게함.
$f = fopen($data_path.'/.htaccess', 'w');
$str = <<<EOD
<FilesMatch "\.(htaccess|htpasswd|[Pp][Hh][Pp]|[Pp]?[Hh][Tt][Mm][Ll]?|[Ii][Nn][Cc]|[Cc][Gg][Ii]|[Pp][Ll])">
<FilesMatch "\.(htaccess|htpasswd|[Pp][Hh][Pp]|[Pp][Hh][Tt]|[Pp]?[Hh][Tt][Mm][Ll]?|[Ii][Nn][Cc]|[Cc][Gg][Ii]|[Pp][Ll])">
Order allow,deny
Deny from all
</FilesMatch>
+26 -8
View File
@@ -216,11 +216,12 @@ function url_auto_link($str)
// 140326 유창화님 제안코드로 수정
// http://sir.kr/pg_lecture/461
// http://sir.kr/pg_lecture/463
$attr_nofollow = (function_exists('check_html_link_nofollow') && check_html_link_nofollow('url_auto_link')) ? ' rel="nofollow"' : '';
$str = str_replace(array("&lt;", "&gt;", "&amp;", "&quot;", "&nbsp;", "&#039;"), 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']}\">\\2</A>", $str);
$str = preg_replace("/(^|[\"'\s(])(www\.[^\"'\s()]+)/i", "\\1<A HREF=\"http://\\2\" TARGET=\"{$config['cf_link_target']}\">\\2</A>", $str);
$str = preg_replace("/[0-9a-z_-]+@[a-z0-9._-]{4,}/i", "<a href=\"mailto:\\0\">\\0</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);
$str = str_replace(array("\t_nbsp_\t", "\t_lt_\t", "\t_gt_\t", "'"), array("&nbsp;", "&lt;", "&gt;", "&#039;"), $str);
/*
@@ -538,6 +539,9 @@ function conv_content($content, $html, $filter=true)
return $content;
}
function check_html_link_nofollow($type=''){
return true;
}
// http://htmlpurifier.org/
// Standards-Compliant HTML Filtering
@@ -561,6 +565,7 @@ function html_purifier($html)
$safeiframe = implode('|', $domains);
include_once(G5_PLUGIN_PATH.'/htmlpurifier/HTMLPurifier.standalone.php');
include_once(G5_PLUGIN_PATH.'/htmlpurifier/extend.video.php');
$config = HTMLPurifier_Config::createDefault();
// data/cache 디렉토리에 CSS, HTML, URI 디렉토리 등을 만든다.
$config->set('Cache.SerializerPath', G5_DATA_PATH.'/cache');
@@ -568,8 +573,13 @@ function html_purifier($html)
$config->set('HTML.SafeObject', false);
$config->set('Output.FlashCompat', false);
$config->set('HTML.SafeIframe', true);
if( (function_exists('check_html_link_nofollow') && check_html_link_nofollow('html_purifier')) ){
$config->set('HTML.Nofollow', true); // rel=nofollow 으로 스팸유입을 줄임
}
$config->set('URI.SafeIframeRegexp','%^(https?:)?//('.$safeiframe.')%');
$config->set('Attr.AllowedFrameTargets', array('_blank'));
//유튜브, 비메오 전체화면 가능하게 하기
$config->set('Filter.Custom', array(new HTMLPurifier_Filter_Iframevideo()));
$purifier = new HTMLPurifier($config);
return $purifier->purify($html);
}
@@ -1213,8 +1223,8 @@ function get_sideview($mb_id, $name='', $email='', $homepage='')
$tmp_name = "";
if ($mb_id) {
//$tmp_name = "<a href=\"".G5_BBS_URL."/profile.php?mb_id=".$mb_id."\" class=\"sv_member\" title=\"$name 자기소개\" target=\"_blank\" onclick=\"return false;\">$name</a>";
$tmp_name = '<a href="'.G5_BBS_URL.'/profile.php?mb_id='.$mb_id.'" class="sv_member" title="'.$name.' 자기소개" target="_blank" onclick="return false;">';
//$tmp_name = "<a href=\"".G5_BBS_URL."/profile.php?mb_id=".$mb_id."\" class=\"sv_member\" title=\"$name 자기소개\" rel="nofollow" target=\"_blank\" onclick=\"return false;\">$name</a>";
$tmp_name = '<a href="'.G5_BBS_URL.'/profile.php?mb_id='.$mb_id.'" class="sv_member" title="'.$name.' 자기소개" target="_blank" rel="nofollow" onclick="return false;">';
if ($config['cf_use_member_icon']) {
$mb_dir = substr($mb_id,0,2);
@@ -1247,7 +1257,7 @@ function get_sideview($mb_id, $name='', $email='', $homepage='')
if(!$bo_table)
return $name;
$tmp_name = '<a href="'.G5_BBS_URL.'/board.php?bo_table='.$bo_table.'&amp;sca='.$sca.'&amp;sfl=wr_name,1&amp;stx='.$name.'" title="'.$name.' 이름으로 검색" class="sv_guest" onclick="return false;">'.$name.'</a>';
$tmp_name = '<a href="'.G5_BBS_URL.'/board.php?bo_table='.$bo_table.'&amp;sca='.$sca.'&amp;sfl=wr_name,1&amp;stx='.$name.'" title="'.$name.' 이름으로 검색" class="sv_guest" rel="nofollow" onclick="return false;">'.$name.'</a>';
$title_mb_id = '[비회원]';
}
@@ -2143,6 +2153,10 @@ function check_device($device)
// 게시판 최신글 캐시 파일 삭제
function delete_cache_latest($bo_table)
{
if (!preg_match("/^([A-Za-z0-9_]{1,20})$/", $bo_table)) {
return;
}
$files = glob(G5_DATA_PATH.'/cache/latest-'.$bo_table.'-*');
if (is_array($files)) {
foreach ($files as $filename)
@@ -2949,9 +2963,13 @@ function replace_filename($name)
@session_start();
$ss_id = session_id();
$usec = get_microtime();
$ext = array_pop(explode('.', $name));
$file_path = pathinfo($name);
$ext = $file_path['extension'];
$return_filename = sha1($ss_id.$_SERVER['REMOTE_ADDR'].$usec);
if( $ext )
$return_filename .= '.'.$ext;
return sha1($ss_id.$_SERVER['REMOTE_ADDR'].$usec).'.'.$ext;
return $return_filename;
}
// 아이코드 사용자정보
+60 -27
View File
@@ -349,14 +349,17 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h
} else { // 비율에 맞게 생성
$dst = imagecreatetruecolor($dst_w, $dst_h);
$bgcolor = imagecolorallocate($dst, 255, 255, 255); // 배경색
if($src_w > $src_h) {
$tmp_h = round(($dst_w * $src_h) / $src_w);
$dst_y = round(($dst_h - $tmp_h) / 2);
$dst_h = $tmp_h;
} else {
$tmp_w = round(($dst_h * $src_w) / $src_h);
$dst_x = round(($dst_w - $tmp_w) / 2);
$dst_w = $tmp_w;
if ( !((defined('G5_USE_THUMB_RATIO') && false === G5_USE_THUMB_RATIO) || (defined('G5_THEME_USE_THUMB_RATIO') && false === G5_THEME_USE_THUMB_RATIO)) ){
if($src_w > $src_h) {
$tmp_h = round(($dst_w * $src_h) / $src_w);
$dst_y = round(($dst_h - $tmp_h) / 2);
$dst_h = $tmp_h;
} else {
$tmp_w = round(($dst_h * $src_w) / $src_h);
$dst_x = round(($dst_w - $tmp_w) / 2);
$dst_w = $tmp_w;
}
}
if($size[2] == 3) {
@@ -382,34 +385,64 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h
$dst = imagecreatetruecolor($dst_w, $dst_h);
$bgcolor = imagecolorallocate($dst, 255, 255, 255); // 배경색
if($src_w < $dst_w) {
if($src_h >= $dst_h) {
if( $src_h > $src_w ){
$tmp_w = round(($dst_h * $src_w) / $src_h);
$dst_x = round(($dst_w - $tmp_w) / 2);
$dst_w = $tmp_w;
} else {
if ( ((defined('G5_USE_THUMB_RATIO') && false === G5_USE_THUMB_RATIO) || (defined('G5_THEME_USE_THUMB_RATIO') && false === G5_THEME_USE_THUMB_RATIO)) ){
//이미지 썸네일을 비율 유지하지 않습니다. (5.2.6 버전 이하에서 처리된 부분과 같음)
if($src_w < $dst_w) {
if($src_h >= $dst_h) {
$dst_x = round(($dst_w - $src_w) / 2);
$src_h = $dst_h;
if( $dst_w > $src_w ){
$dst_w = $src_w;
}
} else {
$dst_x = round(($dst_w - $src_w) / 2);
$dst_y = round(($dst_h - $src_h) / 2);
$dst_w = $src_w;
$dst_h = $src_h;
}
} else {
$dst_x = round(($dst_w - $src_w) / 2);
$dst_y = round(($dst_h - $src_h) / 2);
$dst_w = $src_w;
$dst_h = $src_h;
}
} else {
if($src_h < $dst_h) {
if( $src_w > $dst_w ){
$tmp_h = round(($dst_w * $src_h) / $src_w);
$dst_y = round(($dst_h - $tmp_h) / 2);
$dst_h = $tmp_h;
} else {
if($src_h < $dst_h) {
$dst_y = round(($dst_h - $src_h) / 2);
$dst_h = $src_h;
$src_w = $dst_w;
}
}
} else {
//이미지 썸네일을 비율 유지하며 썸네일 생성합니다.
if($src_w < $dst_w) {
if($src_h >= $dst_h) {
if( $src_h > $src_w ){
$tmp_w = round(($dst_h * $src_w) / $src_h);
$dst_x = round(($dst_w - $tmp_w) / 2);
$dst_w = $tmp_w;
} else {
$dst_x = round(($dst_w - $src_w) / 2);
$src_h = $dst_h;
if( $dst_w > $src_w ){
$dst_w = $src_w;
}
}
} else {
$dst_x = round(($dst_w - $src_w) / 2);
$dst_y = round(($dst_h - $src_h) / 2);
$dst_w = $src_w;
$dst_h = $src_h;
}
} else {
if($src_h < $dst_h) {
if( $src_w > $dst_w ){
$tmp_h = round(($dst_w * $src_h) / $src_w);
$dst_y = round(($dst_h - $tmp_h) / 2);
$dst_h = $tmp_h;
} else {
$dst_y = round(($dst_h - $src_h) / 2);
$dst_h = $src_h;
$src_w = $dst_w;
}
}
}
}
if($size[2] == 3) {
+1 -1
View File
@@ -28,7 +28,7 @@ include_once(G5_LIB_PATH.'/popular.lib.php');
<div id="hd_wrapper">
<div id="logo">
<a href="<?php echo G5_URL ?>"><img src="<?php echo G5_IMG_URL ?>/m_logo.png" alt="<?php echo $config['cf_title']; ?>" height="15"></a>
<a href="<?php echo G5_URL ?>"><img src="<?php echo G5_IMG_URL ?>/m_logo.png" alt="<?php echo $config['cf_title']; ?>"></a>
</div>
<button type="button" id="gnb_open" class="hd_opener"><i class="fa fa-bars" aria-hidden="true"></i><span class="sound_only"> 메뉴열기</span></button>
@@ -84,7 +84,7 @@ var char_max = parseInt(<?php echo $comment_max ?>); // 최대
?>
<aside id="bo_vc_w">
<h2>댓글쓰기</h2>
<form name="fviewcomment" action="./write_comment_update.php" onsubmit="return fviewcomment_submit(this);" method="post" autocomplete="off" class="bo_vc_w">
<form name="fviewcomment" id="fviewcomment" action="<?php echo $comment_action_url; ?>" onsubmit="return fviewcomment_submit(this);" method="post" autocomplete="off" class="bo_vc_w">
<input type="hidden" name="w" value="<?php echo $w ?>" id="w">
<input type="hidden" name="bo_table" value="<?php echo $bo_table ?>">
<input type="hidden" name="wr_id" value="<?php echo $wr_id ?>">
@@ -246,7 +246,10 @@ var char_max = parseInt(<?php echo $comment_max ?>); // 최대
function comment_box(comment_id, work)
{
var el_id;
var el_id,
form_el = 'fviewcomment',
respond = document.getElementById(form_el);
// 댓글 아이디가 넘어오면 답변, 수정
if (comment_id)
{
@@ -263,11 +266,13 @@ var char_max = parseInt(<?php echo $comment_max ?>); // 최대
if (save_before)
{
document.getElementById(save_before).style.display = 'none';
document.getElementById(save_before).innerHTML = '';
}
document.getElementById(el_id).style.display = '';
document.getElementById(el_id).innerHTML = save_html;
document.getElementById(el_id).appendChild(respond);
//입력값 초기화
document.getElementById('wr_content').value = '';
// 댓글 수정
if (work == 'cu')
{
+14 -14
View File
@@ -49,11 +49,11 @@ add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0
echo $option_hidden;
?>
<div class="form_01">
<div class="form_01 write_div">
<h2 class="sound_only"><?php echo $g5['title'] ?></h2>
<?php if ($is_category) { ?>
<div class="bo_w_select">
<div class="bo_w_select write_div">
<label for="ca_name" class="sound_only">분류<strong>필수</strong></label>
<select id="ca_name" name="ca_name" required>
<option value="">선택하세요</option>
@@ -63,46 +63,46 @@ add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0
<?php } ?>
<?php if ($is_name) { ?>
<div>
<div class="write_div">
<label for="wr_name" class="sound_only">이름<strong>필수</strong></label>
<input type="text" name="wr_name" value="<?php echo $name ?>" id="wr_name" required class="frm_input full_input required" maxlength="20" placeholder="이름">
</div>
<?php } ?>
<?php if ($is_password) { ?>
<div>
<div class="write_div">
<label for="wr_password" class="sound_only">비밀번호<strong>필수</strong></label>
<input type="password" name="wr_password" id="wr_password" <?php echo $password_required ?> class="frm_input full_input <?php echo $password_required ?>" maxlength="20" placeholder="비밀번호">
</div>
<?php } ?>
<?php if ($is_email) { ?>
<div>
<div class="write_div">
<label for="wr_email" class="sound_only">이메일</label>
<input type="email" name="wr_email" value="<?php echo $email ?>" id="wr_email" class="frm_input full_input email" maxlength="100" placeholder="이메일">
</div>
<?php } ?>
<?php if ($is_homepage) { ?>
<div>
<div class="write_div">
<label for="wr_homepage" class="sound_only">홈페이지</label>
<input type="url" name="wr_homepage" value="<?php echo $homepage ?>" id="wr_homepage" class="frm_input full_input " placeholder="홈페이지">
</div>
<?php } ?>
<?php if ($option) { ?>
<div>
<div class="write_div">
<span class="sound_only">옵션</span>
<?php echo $option ?>
</div>
<?php } ?>
<div class="bo_w_tit">
<div class="bo_w_tit write_div">
<label for="wr_subject" class="sound_only">제목<strong>필수</strong></label>
<input type="text" name="wr_subject" value="<?php echo $subject ?>" id="wr_subject" required class="frm_input full_input required" placeholder="제목">
</div>
<div>
<div class="write_div">
<label for="wr_content" class="sound_only">내용<strong>필수</strong></label>
<?php if($write_min || $write_max) { ?>
<!-- 최소/최대 글자 수 사용 시 -->
@@ -117,7 +117,7 @@ add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0
<?php for ($i=1; $is_link && $i<=G5_LINK_COUNT; $i++) { ?>
<div class="bo_w_link">
<div class="bo_w_link write_div">
<label for="wr_link<?php echo $i ?>"><i class="fa fa-link" aria-hidden="true"></i> <span class="sound_only">링크 #<?php echo $i ?></span></label>
<input type="url" name="wr_link<?php echo $i ?>" value="<?php if($w=="u"){echo$write['wr_link'.$i];} ?>" id="wr_link<?php echo $i ?>" class="frm_input wr_link">
</div>
@@ -125,8 +125,8 @@ add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0
<?php for ($i=0; $is_file && $i<$file_count; $i++) { ?>
<div class="bo_w_flie">
<div class="file_wr">
<div class="bo_w_flie write_div">
<div class="file_wr write_div">
<label for="bf_file_<?php echo $i+1 ?>" class="lb_icon"><i class="fa fa-download" aria-hidden="true"></i><span class="sound_only">파일 #<?php echo $i+1 ?></span></label>
<input type="file" name="bf_file[]" id="bf_file_<?php echo $i+1 ?>" title="파일첨부 <?php echo $i+1 ?> : 용량 <?php echo $upload_max_filesize ?> 이하만 업로드 가능" class="frm_file ">
</div>
@@ -144,7 +144,7 @@ add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0
<?php } ?>
<?php if ($is_use_captcha) { //자동등록방지 ?>
<div>
<div class="write_div">
<span class="sound_only">자동등록방지</span>
<?php echo $captcha_html ?>
@@ -153,7 +153,7 @@ add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0
</div>
<div class="btn_top top">
<div class="btn_top top write_div">
<a href="./board.php?bo_table=<?php echo $bo_table ?>" class="btn_cancel">취소</a>
<input type="submit" value="작성완료" id="btn_submit" class="btn_submit" accesskey="s">
</div>
@@ -84,7 +84,7 @@ var char_max = parseInt(<?php echo $comment_max ?>); // 최대
?>
<aside id="bo_vc_w">
<h2>댓글쓰기</h2>
<form name="fviewcomment" action="./write_comment_update.php" onsubmit="return fviewcomment_submit(this);" method="post" autocomplete="off" class="bo_vc_w">
<form name="fviewcomment" id="fviewcomment" action="<?php echo $comment_action_url; ?>" onsubmit="return fviewcomment_submit(this);" method="post" autocomplete="off" class="bo_vc_w">
<input type="hidden" name="w" value="<?php echo $w ?>" id="w">
<input type="hidden" name="bo_table" value="<?php echo $bo_table ?>">
<input type="hidden" name="wr_id" value="<?php echo $wr_id ?>">
@@ -246,7 +246,10 @@ var char_max = parseInt(<?php echo $comment_max ?>); // 최대
function comment_box(comment_id, work)
{
var el_id;
var el_id,
form_el = 'fviewcomment',
respond = document.getElementById(form_el);
// 댓글 아이디가 넘어오면 답변, 수정
if (comment_id)
{
@@ -263,11 +266,13 @@ var char_max = parseInt(<?php echo $comment_max ?>); // 최대
if (save_before)
{
document.getElementById(save_before).style.display = 'none';
document.getElementById(save_before).innerHTML = '';
}
document.getElementById(el_id).style.display = '';
document.getElementById(el_id).innerHTML = save_html;
document.getElementById(el_id).appendChild(respond);
//입력값 초기화
document.getElementById('wr_content').value = '';
// 댓글 수정
if (work == 'cu')
{
+14 -14
View File
@@ -49,11 +49,11 @@ add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0
echo $option_hidden;
?>
<div class="form_01">
<div class="form_01 write_div">
<h2 class="sound_only"><?php echo $g5['title'] ?></h2>
<?php if ($is_category) { ?>
<div class="bo_w_select">
<div class="bo_w_select write_div">
<label for="ca_name" class="sound_only">분류<strong>필수</strong></label>
<select id="ca_name" name="ca_name" required>
<option value="">선택하세요</option>
@@ -63,46 +63,46 @@ add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0
<?php } ?>
<?php if ($is_name) { ?>
<div>
<div class="write_div">
<label for="wr_name" class="sound_only">이름<strong>필수</strong></label>
<input type="text" name="wr_name" value="<?php echo $name ?>" id="wr_name" required class="frm_input full_input required" maxlength="20" placeholder="이름">
</div>
<?php } ?>
<?php if ($is_password) { ?>
<div>
<div class="write_div">
<label for="wr_password" class="sound_only">비밀번호<strong>필수</strong></label>
<input type="password" name="wr_password" id="wr_password" <?php echo $password_required ?> class="frm_input full_input <?php echo $password_required ?>" maxlength="20" placeholder="비밀번호">
</div>
<?php } ?>
<?php if ($is_email) { ?>
<div>
<div class="write_div">
<label for="wr_email" class="sound_only">이메일</label>
<input type="email" name="wr_email" value="<?php echo $email ?>" id="wr_email" class="frm_input full_input email" maxlength="100" placeholder="이메일">
</div>
<?php } ?>
<?php if ($is_homepage) { ?>
<div>
<div class="write_div">
<label for="wr_homepage" class="sound_only">홈페이지</label>
<input type="url" name="wr_homepage" value="<?php echo $homepage ?>" id="wr_homepage" class="frm_input full_input " placeholder="홈페이지">
</div>
<?php } ?>
<?php if ($option) { ?>
<div>
<div class="write_div">
<span class="sound_only">옵션</span>
<?php echo $option ?>
</div>
<?php } ?>
<div class="bo_w_tit">
<div class="bo_w_tit write_div">
<label for="wr_subject" class="sound_only">제목<strong>필수</strong></label>
<input type="text" name="wr_subject" value="<?php echo $subject ?>" id="wr_subject" required class="frm_input full_input required" placeholder="제목">
</div>
<div>
<div class="write_div">
<label for="wr_content" class="sound_only">내용<strong>필수</strong></label>
<?php if($write_min || $write_max) { ?>
<!-- 최소/최대 글자 수 사용 시 -->
@@ -117,7 +117,7 @@ add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0
<?php for ($i=1; $is_link && $i<=G5_LINK_COUNT; $i++) { ?>
<div class="bo_w_link">
<div class="bo_w_link write_div">
<label for="wr_link<?php echo $i ?>"><i class="fa fa-link" aria-hidden="true"></i> <span class="sound_only">링크 #<?php echo $i ?></span></label>
<input type="url" name="wr_link<?php echo $i ?>" value="<?php if($w=="u"){echo$write['wr_link'.$i];} ?>" id="wr_link<?php echo $i ?>" class="frm_input wr_link">
</div>
@@ -125,8 +125,8 @@ add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0
<?php for ($i=0; $is_file && $i<$file_count; $i++) { ?>
<div class="bo_w_flie">
<div class="file_wr">
<div class="bo_w_flie write_div">
<div class="file_wr write_div">
<label for="bf_file_<?php echo $i+1 ?>" class="lb_icon"><i class="fa fa-download" aria-hidden="true"></i><span class="sound_only">파일 #<?php echo $i+1 ?></span></label>
<input type="file" name="bf_file[]" id="bf_file_<?php echo $i+1 ?>" title="파일첨부 <?php echo $i+1 ?> : 용량 <?php echo $upload_max_filesize ?> 이하만 업로드 가능" class="frm_file ">
</div>
@@ -144,7 +144,7 @@ add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0
<?php } ?>
<?php if ($is_use_captcha) { //자동등록방지 ?>
<div>
<div class="write_div">
<span class="sound_only">자동등록방지</span>
<?php echo $captcha_html ?>
@@ -153,7 +153,7 @@ add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0
</div>
<div class="btn_top top">
<div class="btn_top top write_div">
<a href="./board.php?bo_table=<?php echo $bo_table ?>" class="btn_cancel">취소</a>
<input type="submit" value="작성완료" id="btn_submit" class="btn_submit" accesskey="s">
</div>
+5 -2
View File
@@ -9,8 +9,8 @@ add_stylesheet('<link rel="stylesheet" href="'.$member_skin_url.'/style.css">',
<h1 id="win_title"><?php echo $g5['title'] ?></h1>
<ul class="win_ul">
<li><a href="./memo.php?kind=recv" class="selected">받은쪽지</a></li>
<li><a href="./memo.php?kind=send">보낸쪽지</a></li>
<li><a href="./memo.php?kind=recv" class="<?php if ($kind == 'recv') { ?>selected<?php } ?>">받은쪽지</a></li>
<li><a href="./memo.php?kind=send" class="<?php if ($kind == 'send') { ?>selected<?php } ?>">보낸쪽지</a></li>
<li><a href="./memo_form.php">쪽지쓰기</a></li>
</ul>
<div class="new_win_con">
@@ -32,6 +32,9 @@ add_stylesheet('<link rel="stylesheet" href="'.$member_skin_url.'/style.css">',
<?php if ($i==0) { echo "<li class=\"empty_list\">자료가 없습니다.</li>"; } ?>
</ul>
<!-- 페이지 -->
<?php echo $write_pages; ?>
<p class="win_desc">
쪽지 보관일수는 최장 <strong><?php echo $config['cf_memo_del'] ?></strong>일 입니다.
</p>
+1 -1
View File
@@ -50,7 +50,7 @@ add_stylesheet('<link rel="stylesheet" href="'.$member_skin_url.'/style.css">',
<?php if($next_link) { ?>
<a href="<?php echo $next_link ?>" class="btn_b03 btn">다음쪽지</a>
<?php } ?>
<a href="./memo.php?kind=<?php echo $kind ?>" class="btn_b03 btn">목록보기</a>
<a href="<?php echo $list_link ?>" class="btn_b03 btn">목록보기</a>
<button type="button" onclick="window.close();" class="btn_close">창닫기</button>
</div>
</div>
@@ -171,7 +171,7 @@ add_stylesheet('<link rel="stylesheet" href="'.$member_skin_url.'/style.css">',
<input type="file" name="mb_icon" id="reg_mb_icon">
<span class="frm_info">
이미지 크기는 가로 <?php echo $config['cf_member_icon_width'] ?>픽셀, 세로 <?php echo $config['cf_member_icon_height'] ?>픽셀 이하로 해주세요.<br>
gif만 가능하며 용량 <?php echo number_format($config['cf_member_icon_size']) ?>바이트 이하만 등록됩니다.
gif, jpg, png파일만 가능하며 용량 <?php echo number_format($config['cf_member_icon_size']) ?>바이트 이하만 등록됩니다.
</span>
<?php if ($w == 'u' && file_exists($mb_icon_path)) { ?>
<img src="<?php echo $mb_icon_url ?>" alt="회원아이콘">
@@ -188,7 +188,7 @@ add_stylesheet('<link rel="stylesheet" href="'.$member_skin_url.'/style.css">',
<input type="file" name="mb_img" id="reg_mb_img" >
<span class="frm_info">
이미지 크기는 가로 <?php echo $config['cf_member_img_width'] ?>픽셀, 세로 <?php echo $config['cf_member_img_height'] ?>픽셀 이하로 해주세요.<br>
gif 또는 jpg만 가능하며 용량 <?php echo number_format($config['cf_member_img_size']) ?>바이트 이하만 등록됩니다.
gif, jpg, png파일만 가능하며 용량 <?php echo number_format($config['cf_member_img_size']) ?>바이트 이하만 등록됩니다.
</span>
<?php if ($w == 'u' && file_exists($mb_img_path)) { ?>
<img src="<?php echo $mb_img_url ?>" alt="회원아이콘">
@@ -418,14 +418,24 @@ add_stylesheet('<link rel="stylesheet" href="'.$member_skin_url.'/style.css">',
if (typeof f.mb_icon != 'undefined') {
if (f.mb_icon.value) {
if (!f.mb_icon.value.toLowerCase().match(/.(gif)$/i)) {
alert('회원아이콘이 gif 파일이 아닙니다.');
if (!f.mb_icon.value.toLowerCase().match(/.(gif|jpe?g|png)$/i)) {
alert('회원아이콘이 이미지 파일이 아닙니다.');
f.mb_icon.focus();
return false;
}
}
}
if (typeof f.mb_img != "undefined") {
if (f.mb_img.value) {
if (!f.mb_img.value.toLowerCase().match(/.(gif|jpe?g|png)$/i)) {
alert("회원이미지가 이미지 파일이 아닙니다.");
f.mb_img.focus();
return false;
}
}
}
if (typeof(f.mb_recommend) != 'undefined' && f.mb_recommend.value) {
if (f.mb_id.value == f.mb_recommend.value) {
alert('본인을 추천할 수 없습니다.');
+8 -2
View File
@@ -8,8 +8,14 @@ add_stylesheet('<link rel="stylesheet" href="'.$popular_skin_url.'/style.css">',
<aside id="popular">
<h2><i class="fa fa-star-o" aria-hidden="true"></i> 인기검색어</h2>
<div>
<?php for ($i=0; $i<count($list); $i++) { ?>
<?php
if( isset($list) && is_array($list) ){
for ($i=0; $i<count($list); $i++) {
?>
<a href="<?php echo G5_BBS_URL ?>/search.php?sfl=wr_subject&amp;sop=and&amp;stx=<?php echo urlencode($list[$i]['pp_word']) ?>"><?php echo get_text($list[$i]['pp_word']); ?></a>
<?php } ?>
<?php
} //end for
} //end if
?>
</div>
</aside>
+1 -1
View File
@@ -15,7 +15,7 @@ function editor_html($id, $content, $is_dhtml_editor=true)
$width = isset($editor_width) ? $editor_width : "100%";
$height = isset($editor_height) ? $editor_height : "250px";
if (defined(G5_PUNYCODE))
if (defined('G5_PUNYCODE'))
$editor_url = G5_PUNYCODE.'/'.G5_EDITOR_DIR.'/'.$config['cf_editor'];
else
$editor_url = G5_EDITOR_URL.'/'.$config['cf_editor'];
@@ -48,8 +48,8 @@
</div>
</div>
<script src="./js/jquery-1.8.3.min.js"></script>
<script src="./js/jquery-ui.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js"></script>
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
<script src="./js/jquery.iframe-transport.js"></script>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+79
View File
@@ -0,0 +1,79 @@
<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
//https://stackoverflow.com/questions/4739284/htmlpurifier-iframe-vimeo-and-youtube-video
/**
* Based on: http://sachachua.com/blog/2011/08/drupal-html-purifier-embedding-iframes-youtube/
* Iframe filter that does some primitive whitelisting in a somewhat recognizable and tweakable way
*/
if( !class_exists('HTMLPurifier_Filter_Iframevideo') ){
class HTMLPurifier_Filter_iframevideo extends HTMLPurifier_Filter
{
public $name = 'Iframevideo';
/**
*
* @param string $html
* @param HTMLPurifier_Config $config
* @param HTMLPurifier_Context $context
* @return string
*/
public function preFilter($html, $config, $context)
{
if (strstr($html, '<iframe')) {
$html = preg_replace_callback('/<iframe.*?src="https?:\/\/www\.youtube\.com\/embed\/([^"]*)[^>]*>(.*?)?\/iframe>/i', array($this, 'trust_url_match'), $html);
$html = preg_replace_callback('/<iframe.*?src="https?:\/\/player\.vimeo.com\/video\/([^"]*)[^>]*>(.*?)?\/iframe>/i', array($this, 'trust_url_match'), $html);
//$html = preg_replace('#<iframe#i', '<img class="Iframevideo"', $html);
//$html = preg_replace('#</iframe>#i', '</img>', $html);
}
return $html;
}
public function trust_url_match($matches)
{
$str = $matches[0];
if( $matches[1] ){
$str = preg_replace('#<iframe#i', '<img class="Iframevideo"', $str);
$str = preg_replace('#</iframe>#i', '</img>', $str);
}
return $str;
}
/**
*
* @param string $html
* @param HTMLPurifier_Config $config
* @param HTMLPurifier_Context $context
* @return string
*/
public function postFilter($html, $config, $context)
{
$post_regex = '#<img class="Iframevideo"([^>]+?)>#';
return preg_replace_callback($post_regex, array($this, 'postFilterCallback'), $html);
}
/**
*
* @param array $matches
* @return string
*/
protected function postFilterCallback($matches)
{
// Domain Whitelist
$youTubeMatch = preg_match('#src="https?://www.youtube(-nocookie)?.com/#i', $matches[1]);
$vimeoMatch = preg_match('#src="https?://player.vimeo.com/#i', $matches[1]);
if ($youTubeMatch || $vimeoMatch) {
$extra = ' frameborder="0"';
if ($youTubeMatch) {
$extra .= ' allowfullscreen';
} elseif ($vimeoMatch) {
$extra .= ' webkitAllowFullScreen mozallowfullscreen allowFullScreen';
}
return '<iframe ' . $matches[1] . $extra . '></iframe>';
} else {
return '';
}
}
}
}
?>
@@ -1,48 +1,48 @@
<?php
/**
* Converts HTMLPurifier_ConfigSchema_Interchange to our runtime
* representation used to perform checks on user configuration.
*/
class HTMLPurifier_ConfigSchema_Builder_ConfigSchema
{
/**
* @param HTMLPurifier_ConfigSchema_Interchange $interchange
* @return HTMLPurifier_ConfigSchema
*/
public function build($interchange)
{
$schema = new HTMLPurifier_ConfigSchema();
foreach ($interchange->directives as $d) {
$schema->add(
$d->id->key,
$d->default,
$d->type,
$d->typeAllowsNull
);
if ($d->allowed !== null) {
$schema->addAllowedValues(
$d->id->key,
$d->allowed
);
}
foreach ($d->aliases as $alias) {
$schema->addAlias(
$alias->key,
$d->id->key
);
}
if ($d->valueAliases !== null) {
$schema->addValueAliases(
$d->id->key,
$d->valueAliases
);
}
}
$schema->postProcess();
return $schema;
}
}
// vim: et sw=4 sts=4
<?php
/**
* Converts HTMLPurifier_ConfigSchema_Interchange to our runtime
* representation used to perform checks on user configuration.
*/
class HTMLPurifier_ConfigSchema_Builder_ConfigSchema
{
/**
* @param HTMLPurifier_ConfigSchema_Interchange $interchange
* @return HTMLPurifier_ConfigSchema
*/
public function build($interchange)
{
$schema = new HTMLPurifier_ConfigSchema();
foreach ($interchange->directives as $d) {
$schema->add(
$d->id->key,
$d->default,
$d->type,
$d->typeAllowsNull
);
if ($d->allowed !== null) {
$schema->addAllowedValues(
$d->id->key,
$d->allowed
);
}
foreach ($d->aliases as $alias) {
$schema->addAlias(
$alias->key,
$d->id->key
);
}
if ($d->valueAliases !== null) {
$schema->addValueAliases(
$d->id->key,
$d->valueAliases
);
}
}
$schema->postProcess();
return $schema;
}
}
// vim: et sw=4 sts=4
@@ -1,144 +1,144 @@
<?php
/**
* Converts HTMLPurifier_ConfigSchema_Interchange to an XML format,
* which can be further processed to generate documentation.
*/
class HTMLPurifier_ConfigSchema_Builder_Xml extends XMLWriter
{
/**
* @type HTMLPurifier_ConfigSchema_Interchange
*/
protected $interchange;
/**
* @type string
*/
private $namespace;
/**
* @param string $html
*/
protected function writeHTMLDiv($html)
{
$this->startElement('div');
$purifier = HTMLPurifier::getInstance();
$html = $purifier->purify($html);
$this->writeAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
$this->writeRaw($html);
$this->endElement(); // div
}
/**
* @param mixed $var
* @return string
*/
protected function export($var)
{
if ($var === array()) {
return 'array()';
}
return var_export($var, true);
}
/**
* @param HTMLPurifier_ConfigSchema_Interchange $interchange
*/
public function build($interchange)
{
// global access, only use as last resort
$this->interchange = $interchange;
$this->setIndent(true);
$this->startDocument('1.0', 'UTF-8');
$this->startElement('configdoc');
$this->writeElement('title', $interchange->name);
foreach ($interchange->directives as $directive) {
$this->buildDirective($directive);
}
if ($this->namespace) {
$this->endElement();
} // namespace
$this->endElement(); // configdoc
$this->flush();
}
/**
* @param HTMLPurifier_ConfigSchema_Interchange_Directive $directive
*/
public function buildDirective($directive)
{
// Kludge, although I suppose having a notion of a "root namespace"
// certainly makes things look nicer when documentation is built.
// Depends on things being sorted.
if (!$this->namespace || $this->namespace !== $directive->id->getRootNamespace()) {
if ($this->namespace) {
$this->endElement();
} // namespace
$this->namespace = $directive->id->getRootNamespace();
$this->startElement('namespace');
$this->writeAttribute('id', $this->namespace);
$this->writeElement('name', $this->namespace);
}
$this->startElement('directive');
$this->writeAttribute('id', $directive->id->toString());
$this->writeElement('name', $directive->id->getDirective());
$this->startElement('aliases');
foreach ($directive->aliases as $alias) {
$this->writeElement('alias', $alias->toString());
}
$this->endElement(); // aliases
$this->startElement('constraints');
if ($directive->version) {
$this->writeElement('version', $directive->version);
}
$this->startElement('type');
if ($directive->typeAllowsNull) {
$this->writeAttribute('allow-null', 'yes');
}
$this->text($directive->type);
$this->endElement(); // type
if ($directive->allowed) {
$this->startElement('allowed');
foreach ($directive->allowed as $value => $x) {
$this->writeElement('value', $value);
}
$this->endElement(); // allowed
}
$this->writeElement('default', $this->export($directive->default));
$this->writeAttribute('xml:space', 'preserve');
if ($directive->external) {
$this->startElement('external');
foreach ($directive->external as $project) {
$this->writeElement('project', $project);
}
$this->endElement();
}
$this->endElement(); // constraints
if ($directive->deprecatedVersion) {
$this->startElement('deprecated');
$this->writeElement('version', $directive->deprecatedVersion);
$this->writeElement('use', $directive->deprecatedUse->toString());
$this->endElement(); // deprecated
}
$this->startElement('description');
$this->writeHTMLDiv($directive->description);
$this->endElement(); // description
$this->endElement(); // directive
}
}
// vim: et sw=4 sts=4
<?php
/**
* Converts HTMLPurifier_ConfigSchema_Interchange to an XML format,
* which can be further processed to generate documentation.
*/
class HTMLPurifier_ConfigSchema_Builder_Xml extends XMLWriter
{
/**
* @type HTMLPurifier_ConfigSchema_Interchange
*/
protected $interchange;
/**
* @type string
*/
private $namespace;
/**
* @param string $html
*/
protected function writeHTMLDiv($html)
{
$this->startElement('div');
$purifier = HTMLPurifier::getInstance();
$html = $purifier->purify($html);
$this->writeAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
$this->writeRaw($html);
$this->endElement(); // div
}
/**
* @param mixed $var
* @return string
*/
protected function export($var)
{
if ($var === array()) {
return 'array()';
}
return var_export($var, true);
}
/**
* @param HTMLPurifier_ConfigSchema_Interchange $interchange
*/
public function build($interchange)
{
// global access, only use as last resort
$this->interchange = $interchange;
$this->setIndent(true);
$this->startDocument('1.0', 'UTF-8');
$this->startElement('configdoc');
$this->writeElement('title', $interchange->name);
foreach ($interchange->directives as $directive) {
$this->buildDirective($directive);
}
if ($this->namespace) {
$this->endElement();
} // namespace
$this->endElement(); // configdoc
$this->flush();
}
/**
* @param HTMLPurifier_ConfigSchema_Interchange_Directive $directive
*/
public function buildDirective($directive)
{
// Kludge, although I suppose having a notion of a "root namespace"
// certainly makes things look nicer when documentation is built.
// Depends on things being sorted.
if (!$this->namespace || $this->namespace !== $directive->id->getRootNamespace()) {
if ($this->namespace) {
$this->endElement();
} // namespace
$this->namespace = $directive->id->getRootNamespace();
$this->startElement('namespace');
$this->writeAttribute('id', $this->namespace);
$this->writeElement('name', $this->namespace);
}
$this->startElement('directive');
$this->writeAttribute('id', $directive->id->toString());
$this->writeElement('name', $directive->id->getDirective());
$this->startElement('aliases');
foreach ($directive->aliases as $alias) {
$this->writeElement('alias', $alias->toString());
}
$this->endElement(); // aliases
$this->startElement('constraints');
if ($directive->version) {
$this->writeElement('version', $directive->version);
}
$this->startElement('type');
if ($directive->typeAllowsNull) {
$this->writeAttribute('allow-null', 'yes');
}
$this->text($directive->type);
$this->endElement(); // type
if ($directive->allowed) {
$this->startElement('allowed');
foreach ($directive->allowed as $value => $x) {
$this->writeElement('value', $value);
}
$this->endElement(); // allowed
}
$this->writeElement('default', $this->export($directive->default));
$this->writeAttribute('xml:space', 'preserve');
if ($directive->external) {
$this->startElement('external');
foreach ($directive->external as $project) {
$this->writeElement('project', $project);
}
$this->endElement();
}
$this->endElement(); // constraints
if ($directive->deprecatedVersion) {
$this->startElement('deprecated');
$this->writeElement('version', $directive->deprecatedVersion);
$this->writeElement('use', $directive->deprecatedUse->toString());
$this->endElement(); // deprecated
}
$this->startElement('description');
$this->writeHTMLDiv($directive->description);
$this->endElement(); // description
$this->endElement(); // directive
}
}
// vim: et sw=4 sts=4
@@ -1,11 +1,11 @@
<?php
/**
* Exceptions related to configuration schema
*/
class HTMLPurifier_ConfigSchema_Exception extends HTMLPurifier_Exception
{
}
// vim: et sw=4 sts=4
<?php
/**
* Exceptions related to configuration schema
*/
class HTMLPurifier_ConfigSchema_Exception extends HTMLPurifier_Exception
{
}
// vim: et sw=4 sts=4
@@ -1,47 +1,47 @@
<?php
/**
* Generic schema interchange format that can be converted to a runtime
* representation (HTMLPurifier_ConfigSchema) or HTML documentation. Members
* are completely validated.
*/
class HTMLPurifier_ConfigSchema_Interchange
{
/**
* Name of the application this schema is describing.
* @type string
*/
public $name;
/**
* Array of Directive ID => array(directive info)
* @type HTMLPurifier_ConfigSchema_Interchange_Directive[]
*/
public $directives = array();
/**
* Adds a directive array to $directives
* @param HTMLPurifier_ConfigSchema_Interchange_Directive $directive
* @throws HTMLPurifier_ConfigSchema_Exception
*/
public function addDirective($directive)
{
if (isset($this->directives[$i = $directive->id->toString()])) {
throw new HTMLPurifier_ConfigSchema_Exception("Cannot redefine directive '$i'");
}
$this->directives[$i] = $directive;
}
/**
* Convenience function to perform standard validation. Throws exception
* on failed validation.
*/
public function validate()
{
$validator = new HTMLPurifier_ConfigSchema_Validator();
return $validator->validate($this);
}
}
// vim: et sw=4 sts=4
<?php
/**
* Generic schema interchange format that can be converted to a runtime
* representation (HTMLPurifier_ConfigSchema) or HTML documentation. Members
* are completely validated.
*/
class HTMLPurifier_ConfigSchema_Interchange
{
/**
* Name of the application this schema is describing.
* @type string
*/
public $name;
/**
* Array of Directive ID => array(directive info)
* @type HTMLPurifier_ConfigSchema_Interchange_Directive[]
*/
public $directives = array();
/**
* Adds a directive array to $directives
* @param HTMLPurifier_ConfigSchema_Interchange_Directive $directive
* @throws HTMLPurifier_ConfigSchema_Exception
*/
public function addDirective($directive)
{
if (isset($this->directives[$i = $directive->id->toString()])) {
throw new HTMLPurifier_ConfigSchema_Exception("Cannot redefine directive '$i'");
}
$this->directives[$i] = $directive;
}
/**
* Convenience function to perform standard validation. Throws exception
* on failed validation.
*/
public function validate()
{
$validator = new HTMLPurifier_ConfigSchema_Validator();
return $validator->validate($this);
}
}
// vim: et sw=4 sts=4
@@ -1,89 +1,89 @@
<?php
/**
* Interchange component class describing configuration directives.
*/
class HTMLPurifier_ConfigSchema_Interchange_Directive
{
/**
* ID of directive.
* @type HTMLPurifier_ConfigSchema_Interchange_Id
*/
public $id;
/**
* Type, e.g. 'integer' or 'istring'.
* @type string
*/
public $type;
/**
* Default value, e.g. 3 or 'DefaultVal'.
* @type mixed
*/
public $default;
/**
* HTML description.
* @type string
*/
public $description;
/**
* Whether or not null is allowed as a value.
* @type bool
*/
public $typeAllowsNull = false;
/**
* Lookup table of allowed scalar values.
* e.g. array('allowed' => true).
* Null if all values are allowed.
* @type array
*/
public $allowed;
/**
* List of aliases for the directive.
* e.g. array(new HTMLPurifier_ConfigSchema_Interchange_Id('Ns', 'Dir'))).
* @type HTMLPurifier_ConfigSchema_Interchange_Id[]
*/
public $aliases = array();
/**
* Hash of value aliases, e.g. array('alt' => 'real'). Null if value
* aliasing is disabled (necessary for non-scalar types).
* @type array
*/
public $valueAliases;
/**
* Version of HTML Purifier the directive was introduced, e.g. '1.3.1'.
* Null if the directive has always existed.
* @type string
*/
public $version;
/**
* ID of directive that supercedes this old directive.
* Null if not deprecated.
* @type HTMLPurifier_ConfigSchema_Interchange_Id
*/
public $deprecatedUse;
/**
* Version of HTML Purifier this directive was deprecated. Null if not
* deprecated.
* @type string
*/
public $deprecatedVersion;
/**
* List of external projects this directive depends on, e.g. array('CSSTidy').
* @type array
*/
public $external = array();
}
// vim: et sw=4 sts=4
<?php
/**
* Interchange component class describing configuration directives.
*/
class HTMLPurifier_ConfigSchema_Interchange_Directive
{
/**
* ID of directive.
* @type HTMLPurifier_ConfigSchema_Interchange_Id
*/
public $id;
/**
* Type, e.g. 'integer' or 'istring'.
* @type string
*/
public $type;
/**
* Default value, e.g. 3 or 'DefaultVal'.
* @type mixed
*/
public $default;
/**
* HTML description.
* @type string
*/
public $description;
/**
* Whether or not null is allowed as a value.
* @type bool
*/
public $typeAllowsNull = false;
/**
* Lookup table of allowed scalar values.
* e.g. array('allowed' => true).
* Null if all values are allowed.
* @type array
*/
public $allowed;
/**
* List of aliases for the directive.
* e.g. array(new HTMLPurifier_ConfigSchema_Interchange_Id('Ns', 'Dir'))).
* @type HTMLPurifier_ConfigSchema_Interchange_Id[]
*/
public $aliases = array();
/**
* Hash of value aliases, e.g. array('alt' => 'real'). Null if value
* aliasing is disabled (necessary for non-scalar types).
* @type array
*/
public $valueAliases;
/**
* Version of HTML Purifier the directive was introduced, e.g. '1.3.1'.
* Null if the directive has always existed.
* @type string
*/
public $version;
/**
* ID of directive that supercedes this old directive.
* Null if not deprecated.
* @type HTMLPurifier_ConfigSchema_Interchange_Id
*/
public $deprecatedUse;
/**
* Version of HTML Purifier this directive was deprecated. Null if not
* deprecated.
* @type string
*/
public $deprecatedVersion;
/**
* List of external projects this directive depends on, e.g. array('CSSTidy').
* @type array
*/
public $external = array();
}
// vim: et sw=4 sts=4
@@ -1,58 +1,58 @@
<?php
/**
* Represents a directive ID in the interchange format.
*/
class HTMLPurifier_ConfigSchema_Interchange_Id
{
/**
* @type string
*/
public $key;
/**
* @param string $key
*/
public function __construct($key)
{
$this->key = $key;
}
/**
* @return string
* @warning This is NOT magic, to ensure that people don't abuse SPL and
* cause problems for PHP 5.0 support.
*/
public function toString()
{
return $this->key;
}
/**
* @return string
*/
public function getRootNamespace()
{
return substr($this->key, 0, strpos($this->key, "."));
}
/**
* @return string
*/
public function getDirective()
{
return substr($this->key, strpos($this->key, ".") + 1);
}
/**
* @param string $id
* @return HTMLPurifier_ConfigSchema_Interchange_Id
*/
public static function make($id)
{
return new HTMLPurifier_ConfigSchema_Interchange_Id($id);
}
}
// vim: et sw=4 sts=4
<?php
/**
* Represents a directive ID in the interchange format.
*/
class HTMLPurifier_ConfigSchema_Interchange_Id
{
/**
* @type string
*/
public $key;
/**
* @param string $key
*/
public function __construct($key)
{
$this->key = $key;
}
/**
* @return string
* @warning This is NOT magic, to ensure that people don't abuse SPL and
* cause problems for PHP 5.0 support.
*/
public function toString()
{
return $this->key;
}
/**
* @return string
*/
public function getRootNamespace()
{
return substr($this->key, 0, strpos($this->key, "."));
}
/**
* @return string
*/
public function getDirective()
{
return substr($this->key, strpos($this->key, ".") + 1);
}
/**
* @param string $id
* @return HTMLPurifier_ConfigSchema_Interchange_Id
*/
public static function make($id)
{
return new HTMLPurifier_ConfigSchema_Interchange_Id($id);
}
}
// vim: et sw=4 sts=4
@@ -1,226 +1,226 @@
<?php
class HTMLPurifier_ConfigSchema_InterchangeBuilder
{
/**
* Used for processing DEFAULT, nothing else.
* @type HTMLPurifier_VarParser
*/
protected $varParser;
/**
* @param HTMLPurifier_VarParser $varParser
*/
public function __construct($varParser = null)
{
$this->varParser = $varParser ? $varParser : new HTMLPurifier_VarParser_Native();
}
/**
* @param string $dir
* @return HTMLPurifier_ConfigSchema_Interchange
*/
public static function buildFromDirectory($dir = null)
{
$builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder();
$interchange = new HTMLPurifier_ConfigSchema_Interchange();
return $builder->buildDir($interchange, $dir);
}
/**
* @param HTMLPurifier_ConfigSchema_Interchange $interchange
* @param string $dir
* @return HTMLPurifier_ConfigSchema_Interchange
*/
public function buildDir($interchange, $dir = null)
{
if (!$dir) {
$dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema';
}
if (file_exists($dir . '/info.ini')) {
$info = parse_ini_file($dir . '/info.ini');
$interchange->name = $info['name'];
}
$files = array();
$dh = opendir($dir);
while (false !== ($file = readdir($dh))) {
if (!$file || $file[0] == '.' || strrchr($file, '.') !== '.txt') {
continue;
}
$files[] = $file;
}
closedir($dh);
sort($files);
foreach ($files as $file) {
$this->buildFile($interchange, $dir . '/' . $file);
}
return $interchange;
}
/**
* @param HTMLPurifier_ConfigSchema_Interchange $interchange
* @param string $file
*/
public function buildFile($interchange, $file)
{
$parser = new HTMLPurifier_StringHashParser();
$this->build(
$interchange,
new HTMLPurifier_StringHash($parser->parseFile($file))
);
}
/**
* Builds an interchange object based on a hash.
* @param HTMLPurifier_ConfigSchema_Interchange $interchange HTMLPurifier_ConfigSchema_Interchange object to build
* @param HTMLPurifier_StringHash $hash source data
* @throws HTMLPurifier_ConfigSchema_Exception
*/
public function build($interchange, $hash)
{
if (!$hash instanceof HTMLPurifier_StringHash) {
$hash = new HTMLPurifier_StringHash($hash);
}
if (!isset($hash['ID'])) {
throw new HTMLPurifier_ConfigSchema_Exception('Hash does not have any ID');
}
if (strpos($hash['ID'], '.') === false) {
if (count($hash) == 2 && isset($hash['DESCRIPTION'])) {
$hash->offsetGet('DESCRIPTION'); // prevent complaining
} else {
throw new HTMLPurifier_ConfigSchema_Exception('All directives must have a namespace');
}
} else {
$this->buildDirective($interchange, $hash);
}
$this->_findUnused($hash);
}
/**
* @param HTMLPurifier_ConfigSchema_Interchange $interchange
* @param HTMLPurifier_StringHash $hash
* @throws HTMLPurifier_ConfigSchema_Exception
*/
public function buildDirective($interchange, $hash)
{
$directive = new HTMLPurifier_ConfigSchema_Interchange_Directive();
// These are required elements:
$directive->id = $this->id($hash->offsetGet('ID'));
$id = $directive->id->toString(); // convenience
if (isset($hash['TYPE'])) {
$type = explode('/', $hash->offsetGet('TYPE'));
if (isset($type[1])) {
$directive->typeAllowsNull = true;
}
$directive->type = $type[0];
} else {
throw new HTMLPurifier_ConfigSchema_Exception("TYPE in directive hash '$id' not defined");
}
if (isset($hash['DEFAULT'])) {
try {
$directive->default = $this->varParser->parse(
$hash->offsetGet('DEFAULT'),
$directive->type,
$directive->typeAllowsNull
);
} catch (HTMLPurifier_VarParserException $e) {
throw new HTMLPurifier_ConfigSchema_Exception($e->getMessage() . " in DEFAULT in directive hash '$id'");
}
}
if (isset($hash['DESCRIPTION'])) {
$directive->description = $hash->offsetGet('DESCRIPTION');
}
if (isset($hash['ALLOWED'])) {
$directive->allowed = $this->lookup($this->evalArray($hash->offsetGet('ALLOWED')));
}
if (isset($hash['VALUE-ALIASES'])) {
$directive->valueAliases = $this->evalArray($hash->offsetGet('VALUE-ALIASES'));
}
if (isset($hash['ALIASES'])) {
$raw_aliases = trim($hash->offsetGet('ALIASES'));
$aliases = preg_split('/\s*,\s*/', $raw_aliases);
foreach ($aliases as $alias) {
$directive->aliases[] = $this->id($alias);
}
}
if (isset($hash['VERSION'])) {
$directive->version = $hash->offsetGet('VERSION');
}
if (isset($hash['DEPRECATED-USE'])) {
$directive->deprecatedUse = $this->id($hash->offsetGet('DEPRECATED-USE'));
}
if (isset($hash['DEPRECATED-VERSION'])) {
$directive->deprecatedVersion = $hash->offsetGet('DEPRECATED-VERSION');
}
if (isset($hash['EXTERNAL'])) {
$directive->external = preg_split('/\s*,\s*/', trim($hash->offsetGet('EXTERNAL')));
}
$interchange->addDirective($directive);
}
/**
* Evaluates an array PHP code string without array() wrapper
* @param string $contents
*/
protected function evalArray($contents)
{
return eval('return array(' . $contents . ');');
}
/**
* Converts an array list into a lookup array.
* @param array $array
* @return array
*/
protected function lookup($array)
{
$ret = array();
foreach ($array as $val) {
$ret[$val] = true;
}
return $ret;
}
/**
* Convenience function that creates an HTMLPurifier_ConfigSchema_Interchange_Id
* object based on a string Id.
* @param string $id
* @return HTMLPurifier_ConfigSchema_Interchange_Id
*/
protected function id($id)
{
return HTMLPurifier_ConfigSchema_Interchange_Id::make($id);
}
/**
* Triggers errors for any unused keys passed in the hash; such keys
* may indicate typos, missing values, etc.
* @param HTMLPurifier_StringHash $hash Hash to check.
*/
protected function _findUnused($hash)
{
$accessed = $hash->getAccessed();
foreach ($hash as $k => $v) {
if (!isset($accessed[$k])) {
trigger_error("String hash key '$k' not used by builder", E_USER_NOTICE);
}
}
}
}
// vim: et sw=4 sts=4
<?php
class HTMLPurifier_ConfigSchema_InterchangeBuilder
{
/**
* Used for processing DEFAULT, nothing else.
* @type HTMLPurifier_VarParser
*/
protected $varParser;
/**
* @param HTMLPurifier_VarParser $varParser
*/
public function __construct($varParser = null)
{
$this->varParser = $varParser ? $varParser : new HTMLPurifier_VarParser_Native();
}
/**
* @param string $dir
* @return HTMLPurifier_ConfigSchema_Interchange
*/
public static function buildFromDirectory($dir = null)
{
$builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder();
$interchange = new HTMLPurifier_ConfigSchema_Interchange();
return $builder->buildDir($interchange, $dir);
}
/**
* @param HTMLPurifier_ConfigSchema_Interchange $interchange
* @param string $dir
* @return HTMLPurifier_ConfigSchema_Interchange
*/
public function buildDir($interchange, $dir = null)
{
if (!$dir) {
$dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema';
}
if (file_exists($dir . '/info.ini')) {
$info = parse_ini_file($dir . '/info.ini');
$interchange->name = $info['name'];
}
$files = array();
$dh = opendir($dir);
while (false !== ($file = readdir($dh))) {
if (!$file || $file[0] == '.' || strrchr($file, '.') !== '.txt') {
continue;
}
$files[] = $file;
}
closedir($dh);
sort($files);
foreach ($files as $file) {
$this->buildFile($interchange, $dir . '/' . $file);
}
return $interchange;
}
/**
* @param HTMLPurifier_ConfigSchema_Interchange $interchange
* @param string $file
*/
public function buildFile($interchange, $file)
{
$parser = new HTMLPurifier_StringHashParser();
$this->build(
$interchange,
new HTMLPurifier_StringHash($parser->parseFile($file))
);
}
/**
* Builds an interchange object based on a hash.
* @param HTMLPurifier_ConfigSchema_Interchange $interchange HTMLPurifier_ConfigSchema_Interchange object to build
* @param HTMLPurifier_StringHash $hash source data
* @throws HTMLPurifier_ConfigSchema_Exception
*/
public function build($interchange, $hash)
{
if (!$hash instanceof HTMLPurifier_StringHash) {
$hash = new HTMLPurifier_StringHash($hash);
}
if (!isset($hash['ID'])) {
throw new HTMLPurifier_ConfigSchema_Exception('Hash does not have any ID');
}
if (strpos($hash['ID'], '.') === false) {
if (count($hash) == 2 && isset($hash['DESCRIPTION'])) {
$hash->offsetGet('DESCRIPTION'); // prevent complaining
} else {
throw new HTMLPurifier_ConfigSchema_Exception('All directives must have a namespace');
}
} else {
$this->buildDirective($interchange, $hash);
}
$this->_findUnused($hash);
}
/**
* @param HTMLPurifier_ConfigSchema_Interchange $interchange
* @param HTMLPurifier_StringHash $hash
* @throws HTMLPurifier_ConfigSchema_Exception
*/
public function buildDirective($interchange, $hash)
{
$directive = new HTMLPurifier_ConfigSchema_Interchange_Directive();
// These are required elements:
$directive->id = $this->id($hash->offsetGet('ID'));
$id = $directive->id->toString(); // convenience
if (isset($hash['TYPE'])) {
$type = explode('/', $hash->offsetGet('TYPE'));
if (isset($type[1])) {
$directive->typeAllowsNull = true;
}
$directive->type = $type[0];
} else {
throw new HTMLPurifier_ConfigSchema_Exception("TYPE in directive hash '$id' not defined");
}
if (isset($hash['DEFAULT'])) {
try {
$directive->default = $this->varParser->parse(
$hash->offsetGet('DEFAULT'),
$directive->type,
$directive->typeAllowsNull
);
} catch (HTMLPurifier_VarParserException $e) {
throw new HTMLPurifier_ConfigSchema_Exception($e->getMessage() . " in DEFAULT in directive hash '$id'");
}
}
if (isset($hash['DESCRIPTION'])) {
$directive->description = $hash->offsetGet('DESCRIPTION');
}
if (isset($hash['ALLOWED'])) {
$directive->allowed = $this->lookup($this->evalArray($hash->offsetGet('ALLOWED')));
}
if (isset($hash['VALUE-ALIASES'])) {
$directive->valueAliases = $this->evalArray($hash->offsetGet('VALUE-ALIASES'));
}
if (isset($hash['ALIASES'])) {
$raw_aliases = trim($hash->offsetGet('ALIASES'));
$aliases = preg_split('/\s*,\s*/', $raw_aliases);
foreach ($aliases as $alias) {
$directive->aliases[] = $this->id($alias);
}
}
if (isset($hash['VERSION'])) {
$directive->version = $hash->offsetGet('VERSION');
}
if (isset($hash['DEPRECATED-USE'])) {
$directive->deprecatedUse = $this->id($hash->offsetGet('DEPRECATED-USE'));
}
if (isset($hash['DEPRECATED-VERSION'])) {
$directive->deprecatedVersion = $hash->offsetGet('DEPRECATED-VERSION');
}
if (isset($hash['EXTERNAL'])) {
$directive->external = preg_split('/\s*,\s*/', trim($hash->offsetGet('EXTERNAL')));
}
$interchange->addDirective($directive);
}
/**
* Evaluates an array PHP code string without array() wrapper
* @param string $contents
*/
protected function evalArray($contents)
{
return eval('return array(' . $contents . ');');
}
/**
* Converts an array list into a lookup array.
* @param array $array
* @return array
*/
protected function lookup($array)
{
$ret = array();
foreach ($array as $val) {
$ret[$val] = true;
}
return $ret;
}
/**
* Convenience function that creates an HTMLPurifier_ConfigSchema_Interchange_Id
* object based on a string Id.
* @param string $id
* @return HTMLPurifier_ConfigSchema_Interchange_Id
*/
protected function id($id)
{
return HTMLPurifier_ConfigSchema_Interchange_Id::make($id);
}
/**
* Triggers errors for any unused keys passed in the hash; such keys
* may indicate typos, missing values, etc.
* @param HTMLPurifier_StringHash $hash Hash to check.
*/
protected function _findUnused($hash)
{
$accessed = $hash->getAccessed();
foreach ($hash as $k => $v) {
if (!isset($accessed[$k])) {
trigger_error("String hash key '$k' not used by builder", E_USER_NOTICE);
}
}
}
}
// vim: et sw=4 sts=4
@@ -1,248 +1,248 @@
<?php
/**
* Performs validations on HTMLPurifier_ConfigSchema_Interchange
*
* @note If you see '// handled by InterchangeBuilder', that means a
* design decision in that class would prevent this validation from
* ever being necessary. We have them anyway, however, for
* redundancy.
*/
class HTMLPurifier_ConfigSchema_Validator
{
/**
* @type HTMLPurifier_ConfigSchema_Interchange
*/
protected $interchange;
/**
* @type array
*/
protected $aliases;
/**
* Context-stack to provide easy to read error messages.
* @type array
*/
protected $context = array();
/**
* to test default's type.
* @type HTMLPurifier_VarParser
*/
protected $parser;
public function __construct()
{
$this->parser = new HTMLPurifier_VarParser();
}
/**
* Validates a fully-formed interchange object.
* @param HTMLPurifier_ConfigSchema_Interchange $interchange
* @return bool
*/
public function validate($interchange)
{
$this->interchange = $interchange;
$this->aliases = array();
// PHP is a bit lax with integer <=> string conversions in
// arrays, so we don't use the identical !== comparison
foreach ($interchange->directives as $i => $directive) {
$id = $directive->id->toString();
if ($i != $id) {
$this->error(false, "Integrity violation: key '$i' does not match internal id '$id'");
}
$this->validateDirective($directive);
}
return true;
}
/**
* Validates a HTMLPurifier_ConfigSchema_Interchange_Id object.
* @param HTMLPurifier_ConfigSchema_Interchange_Id $id
*/
public function validateId($id)
{
$id_string = $id->toString();
$this->context[] = "id '$id_string'";
if (!$id instanceof HTMLPurifier_ConfigSchema_Interchange_Id) {
// handled by InterchangeBuilder
$this->error(false, 'is not an instance of HTMLPurifier_ConfigSchema_Interchange_Id');
}
// keys are now unconstrained (we might want to narrow down to A-Za-z0-9.)
// we probably should check that it has at least one namespace
$this->with($id, 'key')
->assertNotEmpty()
->assertIsString(); // implicit assertIsString handled by InterchangeBuilder
array_pop($this->context);
}
/**
* Validates a HTMLPurifier_ConfigSchema_Interchange_Directive object.
* @param HTMLPurifier_ConfigSchema_Interchange_Directive $d
*/
public function validateDirective($d)
{
$id = $d->id->toString();
$this->context[] = "directive '$id'";
$this->validateId($d->id);
$this->with($d, 'description')
->assertNotEmpty();
// BEGIN - handled by InterchangeBuilder
$this->with($d, 'type')
->assertNotEmpty();
$this->with($d, 'typeAllowsNull')
->assertIsBool();
try {
// This also tests validity of $d->type
$this->parser->parse($d->default, $d->type, $d->typeAllowsNull);
} catch (HTMLPurifier_VarParserException $e) {
$this->error('default', 'had error: ' . $e->getMessage());
}
// END - handled by InterchangeBuilder
if (!is_null($d->allowed) || !empty($d->valueAliases)) {
// allowed and valueAliases require that we be dealing with
// strings, so check for that early.
$d_int = HTMLPurifier_VarParser::$types[$d->type];
if (!isset(HTMLPurifier_VarParser::$stringTypes[$d_int])) {
$this->error('type', 'must be a string type when used with allowed or value aliases');
}
}
$this->validateDirectiveAllowed($d);
$this->validateDirectiveValueAliases($d);
$this->validateDirectiveAliases($d);
array_pop($this->context);
}
/**
* Extra validation if $allowed member variable of
* HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
* @param HTMLPurifier_ConfigSchema_Interchange_Directive $d
*/
public function validateDirectiveAllowed($d)
{
if (is_null($d->allowed)) {
return;
}
$this->with($d, 'allowed')
->assertNotEmpty()
->assertIsLookup(); // handled by InterchangeBuilder
if (is_string($d->default) && !isset($d->allowed[$d->default])) {
$this->error('default', 'must be an allowed value');
}
$this->context[] = 'allowed';
foreach ($d->allowed as $val => $x) {
if (!is_string($val)) {
$this->error("value $val", 'must be a string');
}
}
array_pop($this->context);
}
/**
* Extra validation if $valueAliases member variable of
* HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
* @param HTMLPurifier_ConfigSchema_Interchange_Directive $d
*/
public function validateDirectiveValueAliases($d)
{
if (is_null($d->valueAliases)) {
return;
}
$this->with($d, 'valueAliases')
->assertIsArray(); // handled by InterchangeBuilder
$this->context[] = 'valueAliases';
foreach ($d->valueAliases as $alias => $real) {
if (!is_string($alias)) {
$this->error("alias $alias", 'must be a string');
}
if (!is_string($real)) {
$this->error("alias target $real from alias '$alias'", 'must be a string');
}
if ($alias === $real) {
$this->error("alias '$alias'", "must not be an alias to itself");
}
}
if (!is_null($d->allowed)) {
foreach ($d->valueAliases as $alias => $real) {
if (isset($d->allowed[$alias])) {
$this->error("alias '$alias'", 'must not be an allowed value');
} elseif (!isset($d->allowed[$real])) {
$this->error("alias '$alias'", 'must be an alias to an allowed value');
}
}
}
array_pop($this->context);
}
/**
* Extra validation if $aliases member variable of
* HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
* @param HTMLPurifier_ConfigSchema_Interchange_Directive $d
*/
public function validateDirectiveAliases($d)
{
$this->with($d, 'aliases')
->assertIsArray(); // handled by InterchangeBuilder
$this->context[] = 'aliases';
foreach ($d->aliases as $alias) {
$this->validateId($alias);
$s = $alias->toString();
if (isset($this->interchange->directives[$s])) {
$this->error("alias '$s'", 'collides with another directive');
}
if (isset($this->aliases[$s])) {
$other_directive = $this->aliases[$s];
$this->error("alias '$s'", "collides with alias for directive '$other_directive'");
}
$this->aliases[$s] = $d->id->toString();
}
array_pop($this->context);
}
// protected helper functions
/**
* Convenience function for generating HTMLPurifier_ConfigSchema_ValidatorAtom
* for validating simple member variables of objects.
* @param $obj
* @param $member
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
protected function with($obj, $member)
{
return new HTMLPurifier_ConfigSchema_ValidatorAtom($this->getFormattedContext(), $obj, $member);
}
/**
* Emits an error, providing helpful context.
* @throws HTMLPurifier_ConfigSchema_Exception
*/
protected function error($target, $msg)
{
if ($target !== false) {
$prefix = ucfirst($target) . ' in ' . $this->getFormattedContext();
} else {
$prefix = ucfirst($this->getFormattedContext());
}
throw new HTMLPurifier_ConfigSchema_Exception(trim($prefix . ' ' . $msg));
}
/**
* Returns a formatted context string.
* @return string
*/
protected function getFormattedContext()
{
return implode(' in ', array_reverse($this->context));
}
}
// vim: et sw=4 sts=4
<?php
/**
* Performs validations on HTMLPurifier_ConfigSchema_Interchange
*
* @note If you see '// handled by InterchangeBuilder', that means a
* design decision in that class would prevent this validation from
* ever being necessary. We have them anyway, however, for
* redundancy.
*/
class HTMLPurifier_ConfigSchema_Validator
{
/**
* @type HTMLPurifier_ConfigSchema_Interchange
*/
protected $interchange;
/**
* @type array
*/
protected $aliases;
/**
* Context-stack to provide easy to read error messages.
* @type array
*/
protected $context = array();
/**
* to test default's type.
* @type HTMLPurifier_VarParser
*/
protected $parser;
public function __construct()
{
$this->parser = new HTMLPurifier_VarParser();
}
/**
* Validates a fully-formed interchange object.
* @param HTMLPurifier_ConfigSchema_Interchange $interchange
* @return bool
*/
public function validate($interchange)
{
$this->interchange = $interchange;
$this->aliases = array();
// PHP is a bit lax with integer <=> string conversions in
// arrays, so we don't use the identical !== comparison
foreach ($interchange->directives as $i => $directive) {
$id = $directive->id->toString();
if ($i != $id) {
$this->error(false, "Integrity violation: key '$i' does not match internal id '$id'");
}
$this->validateDirective($directive);
}
return true;
}
/**
* Validates a HTMLPurifier_ConfigSchema_Interchange_Id object.
* @param HTMLPurifier_ConfigSchema_Interchange_Id $id
*/
public function validateId($id)
{
$id_string = $id->toString();
$this->context[] = "id '$id_string'";
if (!$id instanceof HTMLPurifier_ConfigSchema_Interchange_Id) {
// handled by InterchangeBuilder
$this->error(false, 'is not an instance of HTMLPurifier_ConfigSchema_Interchange_Id');
}
// keys are now unconstrained (we might want to narrow down to A-Za-z0-9.)
// we probably should check that it has at least one namespace
$this->with($id, 'key')
->assertNotEmpty()
->assertIsString(); // implicit assertIsString handled by InterchangeBuilder
array_pop($this->context);
}
/**
* Validates a HTMLPurifier_ConfigSchema_Interchange_Directive object.
* @param HTMLPurifier_ConfigSchema_Interchange_Directive $d
*/
public function validateDirective($d)
{
$id = $d->id->toString();
$this->context[] = "directive '$id'";
$this->validateId($d->id);
$this->with($d, 'description')
->assertNotEmpty();
// BEGIN - handled by InterchangeBuilder
$this->with($d, 'type')
->assertNotEmpty();
$this->with($d, 'typeAllowsNull')
->assertIsBool();
try {
// This also tests validity of $d->type
$this->parser->parse($d->default, $d->type, $d->typeAllowsNull);
} catch (HTMLPurifier_VarParserException $e) {
$this->error('default', 'had error: ' . $e->getMessage());
}
// END - handled by InterchangeBuilder
if (!is_null($d->allowed) || !empty($d->valueAliases)) {
// allowed and valueAliases require that we be dealing with
// strings, so check for that early.
$d_int = HTMLPurifier_VarParser::$types[$d->type];
if (!isset(HTMLPurifier_VarParser::$stringTypes[$d_int])) {
$this->error('type', 'must be a string type when used with allowed or value aliases');
}
}
$this->validateDirectiveAllowed($d);
$this->validateDirectiveValueAliases($d);
$this->validateDirectiveAliases($d);
array_pop($this->context);
}
/**
* Extra validation if $allowed member variable of
* HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
* @param HTMLPurifier_ConfigSchema_Interchange_Directive $d
*/
public function validateDirectiveAllowed($d)
{
if (is_null($d->allowed)) {
return;
}
$this->with($d, 'allowed')
->assertNotEmpty()
->assertIsLookup(); // handled by InterchangeBuilder
if (is_string($d->default) && !isset($d->allowed[$d->default])) {
$this->error('default', 'must be an allowed value');
}
$this->context[] = 'allowed';
foreach ($d->allowed as $val => $x) {
if (!is_string($val)) {
$this->error("value $val", 'must be a string');
}
}
array_pop($this->context);
}
/**
* Extra validation if $valueAliases member variable of
* HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
* @param HTMLPurifier_ConfigSchema_Interchange_Directive $d
*/
public function validateDirectiveValueAliases($d)
{
if (is_null($d->valueAliases)) {
return;
}
$this->with($d, 'valueAliases')
->assertIsArray(); // handled by InterchangeBuilder
$this->context[] = 'valueAliases';
foreach ($d->valueAliases as $alias => $real) {
if (!is_string($alias)) {
$this->error("alias $alias", 'must be a string');
}
if (!is_string($real)) {
$this->error("alias target $real from alias '$alias'", 'must be a string');
}
if ($alias === $real) {
$this->error("alias '$alias'", "must not be an alias to itself");
}
}
if (!is_null($d->allowed)) {
foreach ($d->valueAliases as $alias => $real) {
if (isset($d->allowed[$alias])) {
$this->error("alias '$alias'", 'must not be an allowed value');
} elseif (!isset($d->allowed[$real])) {
$this->error("alias '$alias'", 'must be an alias to an allowed value');
}
}
}
array_pop($this->context);
}
/**
* Extra validation if $aliases member variable of
* HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
* @param HTMLPurifier_ConfigSchema_Interchange_Directive $d
*/
public function validateDirectiveAliases($d)
{
$this->with($d, 'aliases')
->assertIsArray(); // handled by InterchangeBuilder
$this->context[] = 'aliases';
foreach ($d->aliases as $alias) {
$this->validateId($alias);
$s = $alias->toString();
if (isset($this->interchange->directives[$s])) {
$this->error("alias '$s'", 'collides with another directive');
}
if (isset($this->aliases[$s])) {
$other_directive = $this->aliases[$s];
$this->error("alias '$s'", "collides with alias for directive '$other_directive'");
}
$this->aliases[$s] = $d->id->toString();
}
array_pop($this->context);
}
// protected helper functions
/**
* Convenience function for generating HTMLPurifier_ConfigSchema_ValidatorAtom
* for validating simple member variables of objects.
* @param $obj
* @param $member
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
protected function with($obj, $member)
{
return new HTMLPurifier_ConfigSchema_ValidatorAtom($this->getFormattedContext(), $obj, $member);
}
/**
* Emits an error, providing helpful context.
* @throws HTMLPurifier_ConfigSchema_Exception
*/
protected function error($target, $msg)
{
if ($target !== false) {
$prefix = ucfirst($target) . ' in ' . $this->getFormattedContext();
} else {
$prefix = ucfirst($this->getFormattedContext());
}
throw new HTMLPurifier_ConfigSchema_Exception(trim($prefix . ' ' . $msg));
}
/**
* Returns a formatted context string.
* @return string
*/
protected function getFormattedContext()
{
return implode(' in ', array_reverse($this->context));
}
}
// vim: et sw=4 sts=4
@@ -1,130 +1,130 @@
<?php
/**
* Fluent interface for validating the contents of member variables.
* This should be immutable. See HTMLPurifier_ConfigSchema_Validator for
* use-cases. We name this an 'atom' because it's ONLY for validations that
* are independent and usually scalar.
*/
class HTMLPurifier_ConfigSchema_ValidatorAtom
{
/**
* @type string
*/
protected $context;
/**
* @type object
*/
protected $obj;
/**
* @type string
*/
protected $member;
/**
* @type mixed
*/
protected $contents;
public function __construct($context, $obj, $member)
{
$this->context = $context;
$this->obj = $obj;
$this->member = $member;
$this->contents =& $obj->$member;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertIsString()
{
if (!is_string($this->contents)) {
$this->error('must be a string');
}
return $this;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertIsBool()
{
if (!is_bool($this->contents)) {
$this->error('must be a boolean');
}
return $this;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertIsArray()
{
if (!is_array($this->contents)) {
$this->error('must be an array');
}
return $this;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertNotNull()
{
if ($this->contents === null) {
$this->error('must not be null');
}
return $this;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertAlnum()
{
$this->assertIsString();
if (!ctype_alnum($this->contents)) {
$this->error('must be alphanumeric');
}
return $this;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertNotEmpty()
{
if (empty($this->contents)) {
$this->error('must not be empty');
}
return $this;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertIsLookup()
{
$this->assertIsArray();
foreach ($this->contents as $v) {
if ($v !== true) {
$this->error('must be a lookup array');
}
}
return $this;
}
/**
* @param string $msg
* @throws HTMLPurifier_ConfigSchema_Exception
*/
protected function error($msg)
{
throw new HTMLPurifier_ConfigSchema_Exception(ucfirst($this->member) . ' in ' . $this->context . ' ' . $msg);
}
}
// vim: et sw=4 sts=4
<?php
/**
* Fluent interface for validating the contents of member variables.
* This should be immutable. See HTMLPurifier_ConfigSchema_Validator for
* use-cases. We name this an 'atom' because it's ONLY for validations that
* are independent and usually scalar.
*/
class HTMLPurifier_ConfigSchema_ValidatorAtom
{
/**
* @type string
*/
protected $context;
/**
* @type object
*/
protected $obj;
/**
* @type string
*/
protected $member;
/**
* @type mixed
*/
protected $contents;
public function __construct($context, $obj, $member)
{
$this->context = $context;
$this->obj = $obj;
$this->member = $member;
$this->contents =& $obj->$member;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertIsString()
{
if (!is_string($this->contents)) {
$this->error('must be a string');
}
return $this;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertIsBool()
{
if (!is_bool($this->contents)) {
$this->error('must be a boolean');
}
return $this;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertIsArray()
{
if (!is_array($this->contents)) {
$this->error('must be an array');
}
return $this;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertNotNull()
{
if ($this->contents === null) {
$this->error('must not be null');
}
return $this;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertAlnum()
{
$this->assertIsString();
if (!ctype_alnum($this->contents)) {
$this->error('must be alphanumeric');
}
return $this;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertNotEmpty()
{
if (empty($this->contents)) {
$this->error('must not be empty');
}
return $this;
}
/**
* @return HTMLPurifier_ConfigSchema_ValidatorAtom
*/
public function assertIsLookup()
{
$this->assertIsArray();
foreach ($this->contents as $v) {
if ($v !== true) {
$this->error('must be a lookup array');
}
}
return $this;
}
/**
* @param string $msg
* @throws HTMLPurifier_ConfigSchema_Exception
*/
protected function error($msg)
{
throw new HTMLPurifier_ConfigSchema_Exception(ucfirst($this->member) . ' in ' . $this->context . ' ' . $msg);
}
}
// vim: et sw=4 sts=4
@@ -1,8 +1,8 @@
Attr.AllowedClasses
TYPE: lookup/null
VERSION: 4.0.0
DEFAULT: null
--DESCRIPTION--
List of allowed class values in the class attribute. By default, this is null,
which means all classes are allowed.
--# vim: et sw=4 sts=4
Attr.AllowedClasses
TYPE: lookup/null
VERSION: 4.0.0
DEFAULT: null
--DESCRIPTION--
List of allowed class values in the class attribute. By default, this is null,
which means all classes are allowed.
--# vim: et sw=4 sts=4
@@ -1,12 +1,12 @@
Attr.AllowedFrameTargets
TYPE: lookup
DEFAULT: array()
--DESCRIPTION--
Lookup table of all allowed link frame targets. Some commonly used link
targets include _blank, _self, _parent and _top. Values should be
lowercase, as validation will be done in a case-sensitive manner despite
W3C's recommendation. XHTML 1.0 Strict does not permit the target attribute
so this directive will have no effect in that doctype. XHTML 1.1 does not
enable the Target module by default, you will have to manually enable it
(see the module documentation for more details.)
--# vim: et sw=4 sts=4
Attr.AllowedFrameTargets
TYPE: lookup
DEFAULT: array()
--DESCRIPTION--
Lookup table of all allowed link frame targets. Some commonly used link
targets include _blank, _self, _parent and _top. Values should be
lowercase, as validation will be done in a case-sensitive manner despite
W3C's recommendation. XHTML 1.0 Strict does not permit the target attribute
so this directive will have no effect in that doctype. XHTML 1.1 does not
enable the Target module by default, you will have to manually enable it
(see the module documentation for more details.)
--# vim: et sw=4 sts=4
@@ -1,9 +1,9 @@
Attr.AllowedRel
TYPE: lookup
VERSION: 1.6.0
DEFAULT: array()
--DESCRIPTION--
List of allowed forward document relationships in the rel attribute. Common
values may be nofollow or print. By default, this is empty, meaning that no
document relationships are allowed.
--# vim: et sw=4 sts=4
Attr.AllowedRel
TYPE: lookup
VERSION: 1.6.0
DEFAULT: array()
--DESCRIPTION--
List of allowed forward document relationships in the rel attribute. Common
values may be nofollow or print. By default, this is empty, meaning that no
document relationships are allowed.
--# vim: et sw=4 sts=4
@@ -1,9 +1,9 @@
Attr.AllowedRev
TYPE: lookup
VERSION: 1.6.0
DEFAULT: array()
--DESCRIPTION--
List of allowed reverse document relationships in the rev attribute. This
attribute is a bit of an edge-case; if you don't know what it is for, stay
away.
--# vim: et sw=4 sts=4
Attr.AllowedRev
TYPE: lookup
VERSION: 1.6.0
DEFAULT: array()
--DESCRIPTION--
List of allowed reverse document relationships in the rev attribute. This
attribute is a bit of an edge-case; if you don't know what it is for, stay
away.
--# vim: et sw=4 sts=4
@@ -1,19 +1,19 @@
Attr.ClassUseCDATA
TYPE: bool/null
DEFAULT: null
VERSION: 4.0.0
--DESCRIPTION--
If null, class will auto-detect the doctype and, if matching XHTML 1.1 or
XHTML 2.0, will use the restrictive NMTOKENS specification of class. Otherwise,
it will use a relaxed CDATA definition. If true, the relaxed CDATA definition
is forced; if false, the NMTOKENS definition is forced. To get behavior
of HTML Purifier prior to 4.0.0, set this directive to false.
Some rational behind the auto-detection:
in previous versions of HTML Purifier, it was assumed that the form of
class was NMTOKENS, as specified by the XHTML Modularization (representing
XHTML 1.1 and XHTML 2.0). The DTDs for HTML 4.01 and XHTML 1.0, however
specify class as CDATA. HTML 5 effectively defines it as CDATA, but
with the additional constraint that each name should be unique (this is not
explicitly outlined in previous specifications).
--# vim: et sw=4 sts=4
Attr.ClassUseCDATA
TYPE: bool/null
DEFAULT: null
VERSION: 4.0.0
--DESCRIPTION--
If null, class will auto-detect the doctype and, if matching XHTML 1.1 or
XHTML 2.0, will use the restrictive NMTOKENS specification of class. Otherwise,
it will use a relaxed CDATA definition. If true, the relaxed CDATA definition
is forced; if false, the NMTOKENS definition is forced. To get behavior
of HTML Purifier prior to 4.0.0, set this directive to false.
Some rational behind the auto-detection:
in previous versions of HTML Purifier, it was assumed that the form of
class was NMTOKENS, as specified by the XHTML Modularization (representing
XHTML 1.1 and XHTML 2.0). The DTDs for HTML 4.01 and XHTML 1.0, however
specify class as CDATA. HTML 5 effectively defines it as CDATA, but
with the additional constraint that each name should be unique (this is not
explicitly outlined in previous specifications).
--# vim: et sw=4 sts=4
@@ -1,11 +1,11 @@
Attr.DefaultImageAlt
TYPE: string/null
DEFAULT: null
VERSION: 3.2.0
--DESCRIPTION--
This is the content of the alt tag of an image if the user had not
previously specified an alt attribute. This applies to all images without
a valid alt attribute, as opposed to %Attr.DefaultInvalidImageAlt, which
only applies to invalid images, and overrides in the case of an invalid image.
Default behavior with null is to use the basename of the src tag for the alt.
--# vim: et sw=4 sts=4
Attr.DefaultImageAlt
TYPE: string/null
DEFAULT: null
VERSION: 3.2.0
--DESCRIPTION--
This is the content of the alt tag of an image if the user had not
previously specified an alt attribute. This applies to all images without
a valid alt attribute, as opposed to %Attr.DefaultInvalidImageAlt, which
only applies to invalid images, and overrides in the case of an invalid image.
Default behavior with null is to use the basename of the src tag for the alt.
--# vim: et sw=4 sts=4
@@ -1,9 +1,9 @@
Attr.DefaultInvalidImage
TYPE: string
DEFAULT: ''
--DESCRIPTION--
This is the default image an img tag will be pointed to if it does not have
a valid src attribute. In future versions, we may allow the image tag to
be removed completely, but due to design issues, this is not possible right
now.
--# vim: et sw=4 sts=4
Attr.DefaultInvalidImage
TYPE: string
DEFAULT: ''
--DESCRIPTION--
This is the default image an img tag will be pointed to if it does not have
a valid src attribute. In future versions, we may allow the image tag to
be removed completely, but due to design issues, this is not possible right
now.
--# vim: et sw=4 sts=4
@@ -1,8 +1,8 @@
Attr.DefaultInvalidImageAlt
TYPE: string
DEFAULT: 'Invalid image'
--DESCRIPTION--
This is the content of the alt tag of an invalid image if the user had not
previously specified an alt attribute. It has no effect when the image is
valid but there was no alt attribute present.
--# vim: et sw=4 sts=4
Attr.DefaultInvalidImageAlt
TYPE: string
DEFAULT: 'Invalid image'
--DESCRIPTION--
This is the content of the alt tag of an invalid image if the user had not
previously specified an alt attribute. It has no effect when the image is
valid but there was no alt attribute present.
--# vim: et sw=4 sts=4
@@ -1,10 +1,10 @@
Attr.DefaultTextDir
TYPE: string
DEFAULT: 'ltr'
--DESCRIPTION--
Defines the default text direction (ltr or rtl) of the document being
parsed. This generally is the same as the value of the dir attribute in
HTML, or ltr if that is not specified.
--ALLOWED--
'ltr', 'rtl'
--# vim: et sw=4 sts=4
Attr.DefaultTextDir
TYPE: string
DEFAULT: 'ltr'
--DESCRIPTION--
Defines the default text direction (ltr or rtl) of the document being
parsed. This generally is the same as the value of the dir attribute in
HTML, or ltr if that is not specified.
--ALLOWED--
'ltr', 'rtl'
--# vim: et sw=4 sts=4
@@ -1,16 +1,16 @@
Attr.EnableID
TYPE: bool
DEFAULT: false
VERSION: 1.2.0
--DESCRIPTION--
Allows the ID attribute in HTML. This is disabled by default due to the
fact that without proper configuration user input can easily break the
validation of a webpage by specifying an ID that is already on the
surrounding HTML. If you don't mind throwing caution to the wind, enable
this directive, but I strongly recommend you also consider blacklisting IDs
you use (%Attr.IDBlacklist) or prefixing all user supplied IDs
(%Attr.IDPrefix). When set to true HTML Purifier reverts to the behavior of
pre-1.2.0 versions.
--ALIASES--
HTML.EnableAttrID
--# vim: et sw=4 sts=4
Attr.EnableID
TYPE: bool
DEFAULT: false
VERSION: 1.2.0
--DESCRIPTION--
Allows the ID attribute in HTML. This is disabled by default due to the
fact that without proper configuration user input can easily break the
validation of a webpage by specifying an ID that is already on the
surrounding HTML. If you don't mind throwing caution to the wind, enable
this directive, but I strongly recommend you also consider blacklisting IDs
you use (%Attr.IDBlacklist) or prefixing all user supplied IDs
(%Attr.IDPrefix). When set to true HTML Purifier reverts to the behavior of
pre-1.2.0 versions.
--ALIASES--
HTML.EnableAttrID
--# vim: et sw=4 sts=4
@@ -1,8 +1,8 @@
Attr.ForbiddenClasses
TYPE: lookup
VERSION: 4.0.0
DEFAULT: array()
--DESCRIPTION--
List of forbidden class values in the class attribute. By default, this is
empty, which means that no classes are forbidden. See also %Attr.AllowedClasses.
--# vim: et sw=4 sts=4
Attr.ForbiddenClasses
TYPE: lookup
VERSION: 4.0.0
DEFAULT: array()
--DESCRIPTION--
List of forbidden class values in the class attribute. By default, this is
empty, which means that no classes are forbidden. See also %Attr.AllowedClasses.
--# vim: et sw=4 sts=4
@@ -1,10 +1,10 @@
Attr.ID.HTML5
TYPE: bool/null
DEFAULT: null
VERSION: 4.8.0
--DESCRIPTION--
In HTML5, restrictions on the format of the id attribute have been significantly
relaxed, such that any string is valid so long as it contains no spaces and
is at least one character. In lieu of a general HTML5 compatibility flag,
set this configuration directive to true to use the relaxed rules.
--# vim: et sw=4 sts=4
Attr.ID.HTML5
TYPE: bool/null
DEFAULT: null
VERSION: 4.8.0
--DESCRIPTION--
In HTML5, restrictions on the format of the id attribute have been significantly
relaxed, such that any string is valid so long as it contains no spaces and
is at least one character. In lieu of a general HTML5 compatibility flag,
set this configuration directive to true to use the relaxed rules.
--# vim: et sw=4 sts=4
@@ -1,5 +1,5 @@
Attr.IDBlacklist
TYPE: list
DEFAULT: array()
DESCRIPTION: Array of IDs not allowed in the document.
--# vim: et sw=4 sts=4
Attr.IDBlacklist
TYPE: list
DEFAULT: array()
DESCRIPTION: Array of IDs not allowed in the document.
--# vim: et sw=4 sts=4
@@ -1,9 +1,9 @@
Attr.IDBlacklistRegexp
TYPE: string/null
VERSION: 1.6.0
DEFAULT: NULL
--DESCRIPTION--
PCRE regular expression to be matched against all IDs. If the expression is
matches, the ID is rejected. Use this with care: may cause significant
degradation. ID matching is done after all other validation.
--# vim: et sw=4 sts=4
Attr.IDBlacklistRegexp
TYPE: string/null
VERSION: 1.6.0
DEFAULT: NULL
--DESCRIPTION--
PCRE regular expression to be matched against all IDs. If the expression is
matches, the ID is rejected. Use this with care: may cause significant
degradation. ID matching is done after all other validation.
--# vim: et sw=4 sts=4
@@ -1,12 +1,12 @@
Attr.IDPrefix
TYPE: string
VERSION: 1.2.0
DEFAULT: ''
--DESCRIPTION--
String to prefix to IDs. If you have no idea what IDs your pages may use,
you may opt to simply add a prefix to all user-submitted ID attributes so
that they are still usable, but will not conflict with core page IDs.
Example: setting the directive to 'user_' will result in a user submitted
'foo' to become 'user_foo' Be sure to set %HTML.EnableAttrID to true
before using this.
--# vim: et sw=4 sts=4
Attr.IDPrefix
TYPE: string
VERSION: 1.2.0
DEFAULT: ''
--DESCRIPTION--
String to prefix to IDs. If you have no idea what IDs your pages may use,
you may opt to simply add a prefix to all user-submitted ID attributes so
that they are still usable, but will not conflict with core page IDs.
Example: setting the directive to 'user_' will result in a user submitted
'foo' to become 'user_foo' Be sure to set %HTML.EnableAttrID to true
before using this.
--# vim: et sw=4 sts=4
@@ -1,14 +1,14 @@
Attr.IDPrefixLocal
TYPE: string
VERSION: 1.2.0
DEFAULT: ''
--DESCRIPTION--
Temporary prefix for IDs used in conjunction with %Attr.IDPrefix. If you
need to allow multiple sets of user content on web page, you may need to
have a seperate prefix that changes with each iteration. This way,
seperately submitted user content displayed on the same page doesn't
clobber each other. Ideal values are unique identifiers for the content it
represents (i.e. the id of the row in the database). Be sure to add a
seperator (like an underscore) at the end. Warning: this directive will
not work unless %Attr.IDPrefix is set to a non-empty value!
--# vim: et sw=4 sts=4
Attr.IDPrefixLocal
TYPE: string
VERSION: 1.2.0
DEFAULT: ''
--DESCRIPTION--
Temporary prefix for IDs used in conjunction with %Attr.IDPrefix. If you
need to allow multiple sets of user content on web page, you may need to
have a seperate prefix that changes with each iteration. This way,
seperately submitted user content displayed on the same page doesn't
clobber each other. Ideal values are unique identifiers for the content it
represents (i.e. the id of the row in the database). Be sure to add a
seperator (like an underscore) at the end. Warning: this directive will
not work unless %Attr.IDPrefix is set to a non-empty value!
--# vim: et sw=4 sts=4
@@ -1,31 +1,31 @@
AutoFormat.AutoParagraph
TYPE: bool
VERSION: 2.0.1
DEFAULT: false
--DESCRIPTION--
<p>
This directive turns on auto-paragraphing, where double newlines are
converted in to paragraphs whenever possible. Auto-paragraphing:
</p>
<ul>
<li>Always applies to inline elements or text in the root node,</li>
<li>Applies to inline elements or text with double newlines in nodes
that allow paragraph tags,</li>
<li>Applies to double newlines in paragraph tags</li>
</ul>
<p>
<code>p</code> tags must be allowed for this directive to take effect.
We do not use <code>br</code> tags for paragraphing, as that is
semantically incorrect.
</p>
<p>
To prevent auto-paragraphing as a content-producer, refrain from using
double-newlines except to specify a new paragraph or in contexts where
it has special meaning (whitespace usually has no meaning except in
tags like <code>pre</code>, so this should not be difficult.) To prevent
the paragraphing of inline text adjacent to block elements, wrap them
in <code>div</code> tags (the behavior is slightly different outside of
the root node.)
</p>
--# vim: et sw=4 sts=4
AutoFormat.AutoParagraph
TYPE: bool
VERSION: 2.0.1
DEFAULT: false
--DESCRIPTION--
<p>
This directive turns on auto-paragraphing, where double newlines are
converted in to paragraphs whenever possible. Auto-paragraphing:
</p>
<ul>
<li>Always applies to inline elements or text in the root node,</li>
<li>Applies to inline elements or text with double newlines in nodes
that allow paragraph tags,</li>
<li>Applies to double newlines in paragraph tags</li>
</ul>
<p>
<code>p</code> tags must be allowed for this directive to take effect.
We do not use <code>br</code> tags for paragraphing, as that is
semantically incorrect.
</p>
<p>
To prevent auto-paragraphing as a content-producer, refrain from using
double-newlines except to specify a new paragraph or in contexts where
it has special meaning (whitespace usually has no meaning except in
tags like <code>pre</code>, so this should not be difficult.) To prevent
the paragraphing of inline text adjacent to block elements, wrap them
in <code>div</code> tags (the behavior is slightly different outside of
the root node.)
</p>
--# vim: et sw=4 sts=4
@@ -1,12 +1,12 @@
AutoFormat.Custom
TYPE: list
VERSION: 2.0.1
DEFAULT: array()
--DESCRIPTION--
<p>
This directive can be used to add custom auto-format injectors.
Specify an array of injector names (class name minus the prefix)
or concrete implementations. Injector class must exist.
</p>
--# vim: et sw=4 sts=4
AutoFormat.Custom
TYPE: list
VERSION: 2.0.1
DEFAULT: array()
--DESCRIPTION--
<p>
This directive can be used to add custom auto-format injectors.
Specify an array of injector names (class name minus the prefix)
or concrete implementations. Injector class must exist.
</p>
--# vim: et sw=4 sts=4
@@ -1,11 +1,11 @@
AutoFormat.DisplayLinkURI
TYPE: bool
VERSION: 3.2.0
DEFAULT: false
--DESCRIPTION--
<p>
This directive turns on the in-text display of URIs in &lt;a&gt; tags, and disables
those links. For example, <a href="http://example.com">example</a> becomes
example (<a>http://example.com</a>).
</p>
--# vim: et sw=4 sts=4
AutoFormat.DisplayLinkURI
TYPE: bool
VERSION: 3.2.0
DEFAULT: false
--DESCRIPTION--
<p>
This directive turns on the in-text display of URIs in &lt;a&gt; tags, and disables
those links. For example, <a href="http://example.com">example</a> becomes
example (<a>http://example.com</a>).
</p>
--# vim: et sw=4 sts=4
@@ -1,12 +1,12 @@
AutoFormat.Linkify
TYPE: bool
VERSION: 2.0.1
DEFAULT: false
--DESCRIPTION--
<p>
This directive turns on linkification, auto-linking http, ftp and
https URLs. <code>a</code> tags with the <code>href</code> attribute
must be allowed.
</p>
--# vim: et sw=4 sts=4
AutoFormat.Linkify
TYPE: bool
VERSION: 2.0.1
DEFAULT: false
--DESCRIPTION--
<p>
This directive turns on linkification, auto-linking http, ftp and
https URLs. <code>a</code> tags with the <code>href</code> attribute
must be allowed.
</p>
--# vim: et sw=4 sts=4
@@ -1,12 +1,12 @@
AutoFormat.PurifierLinkify.DocURL
TYPE: string
VERSION: 2.0.1
DEFAULT: '#%s'
ALIASES: AutoFormatParam.PurifierLinkifyDocURL
--DESCRIPTION--
<p>
Location of configuration documentation to link to, let %s substitute
into the configuration's namespace and directive names sans the percent
sign.
</p>
--# vim: et sw=4 sts=4
AutoFormat.PurifierLinkify.DocURL
TYPE: string
VERSION: 2.0.1
DEFAULT: '#%s'
ALIASES: AutoFormatParam.PurifierLinkifyDocURL
--DESCRIPTION--
<p>
Location of configuration documentation to link to, let %s substitute
into the configuration's namespace and directive names sans the percent
sign.
</p>
--# vim: et sw=4 sts=4
@@ -1,12 +1,12 @@
AutoFormat.PurifierLinkify
TYPE: bool
VERSION: 2.0.1
DEFAULT: false
--DESCRIPTION--
<p>
Internal auto-formatter that converts configuration directives in
syntax <a>%Namespace.Directive</a> to links. <code>a</code> tags
with the <code>href</code> attribute must be allowed.
</p>
--# vim: et sw=4 sts=4
AutoFormat.PurifierLinkify
TYPE: bool
VERSION: 2.0.1
DEFAULT: false
--DESCRIPTION--
<p>
Internal auto-formatter that converts configuration directives in
syntax <a>%Namespace.Directive</a> to links. <code>a</code> tags
with the <code>href</code> attribute must be allowed.
</p>
--# vim: et sw=4 sts=4
@@ -1,14 +1,14 @@
AutoFormat.RemoveEmpty.Predicate
TYPE: hash
VERSION: 4.7.0
DEFAULT: array('colgroup' => array(), 'th' => array(), 'td' => array(), 'iframe' => array('src'))
--DESCRIPTION--
<p>
Given that an element has no contents, it will be removed by default, unless
this predicate dictates otherwise. The predicate can either be an associative
map from tag name to list of attributes that must be present for the element
to be considered preserved: thus, the default always preserves <code>colgroup</code>,
<code>th</code> and <code>td</code>, and also <code>iframe</code> if it
has a <code>src</code>.
</p>
--# vim: et sw=4 sts=4
AutoFormat.RemoveEmpty.Predicate
TYPE: hash
VERSION: 4.7.0
DEFAULT: array('colgroup' => array(), 'th' => array(), 'td' => array(), 'iframe' => array('src'))
--DESCRIPTION--
<p>
Given that an element has no contents, it will be removed by default, unless
this predicate dictates otherwise. The predicate can either be an associative
map from tag name to list of attributes that must be present for the element
to be considered preserved: thus, the default always preserves <code>colgroup</code>,
<code>th</code> and <code>td</code>, and also <code>iframe</code> if it
has a <code>src</code>.
</p>
--# vim: et sw=4 sts=4
@@ -1,11 +1,11 @@
AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions
TYPE: lookup
VERSION: 4.0.0
DEFAULT: array('td' => true, 'th' => true)
--DESCRIPTION--
<p>
When %AutoFormat.RemoveEmpty and %AutoFormat.RemoveEmpty.RemoveNbsp
are enabled, this directive defines what HTML elements should not be
removede if they have only a non-breaking space in them.
</p>
--# vim: et sw=4 sts=4
AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions
TYPE: lookup
VERSION: 4.0.0
DEFAULT: array('td' => true, 'th' => true)
--DESCRIPTION--
<p>
When %AutoFormat.RemoveEmpty and %AutoFormat.RemoveEmpty.RemoveNbsp
are enabled, this directive defines what HTML elements should not be
removede if they have only a non-breaking space in them.
</p>
--# vim: et sw=4 sts=4
@@ -1,15 +1,15 @@
AutoFormat.RemoveEmpty.RemoveNbsp
TYPE: bool
VERSION: 4.0.0
DEFAULT: false
--DESCRIPTION--
<p>
When enabled, HTML Purifier will treat any elements that contain only
non-breaking spaces as well as regular whitespace as empty, and remove
them when %AutoForamt.RemoveEmpty is enabled.
</p>
<p>
See %AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions for a list of elements
that don't have this behavior applied to them.
</p>
--# vim: et sw=4 sts=4
AutoFormat.RemoveEmpty.RemoveNbsp
TYPE: bool
VERSION: 4.0.0
DEFAULT: false
--DESCRIPTION--
<p>
When enabled, HTML Purifier will treat any elements that contain only
non-breaking spaces as well as regular whitespace as empty, and remove
them when %AutoForamt.RemoveEmpty is enabled.
</p>
<p>
See %AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions for a list of elements
that don't have this behavior applied to them.
</p>
--# vim: et sw=4 sts=4
@@ -1,46 +1,46 @@
AutoFormat.RemoveEmpty
TYPE: bool
VERSION: 3.2.0
DEFAULT: false
--DESCRIPTION--
<p>
When enabled, HTML Purifier will attempt to remove empty elements that
contribute no semantic information to the document. The following types
of nodes will be removed:
</p>
<ul><li>
Tags with no attributes and no content, and that are not empty
elements (remove <code>&lt;a&gt;&lt;/a&gt;</code> but not
<code>&lt;br /&gt;</code>), and
</li>
<li>
Tags with no content, except for:<ul>
<li>The <code>colgroup</code> element, or</li>
<li>
Elements with the <code>id</code> or <code>name</code> attribute,
when those attributes are permitted on those elements.
</li>
</ul></li>
</ul>
<p>
Please be very careful when using this functionality; while it may not
seem that empty elements contain useful information, they can alter the
layout of a document given appropriate styling. This directive is most
useful when you are processing machine-generated HTML, please avoid using
it on regular user HTML.
</p>
<p>
Elements that contain only whitespace will be treated as empty. Non-breaking
spaces, however, do not count as whitespace. See
%AutoFormat.RemoveEmpty.RemoveNbsp for alternate behavior.
</p>
<p>
This algorithm is not perfect; you may still notice some empty tags,
particularly if a node had elements, but those elements were later removed
because they were not permitted in that context, or tags that, after
being auto-closed by another tag, where empty. This is for safety reasons
to prevent clever code from breaking validation. The general rule of thumb:
if a tag looked empty on the way in, it will get removed; if HTML Purifier
made it empty, it will stay.
</p>
--# vim: et sw=4 sts=4
AutoFormat.RemoveEmpty
TYPE: bool
VERSION: 3.2.0
DEFAULT: false
--DESCRIPTION--
<p>
When enabled, HTML Purifier will attempt to remove empty elements that
contribute no semantic information to the document. The following types
of nodes will be removed:
</p>
<ul><li>
Tags with no attributes and no content, and that are not empty
elements (remove <code>&lt;a&gt;&lt;/a&gt;</code> but not
<code>&lt;br /&gt;</code>), and
</li>
<li>
Tags with no content, except for:<ul>
<li>The <code>colgroup</code> element, or</li>
<li>
Elements with the <code>id</code> or <code>name</code> attribute,
when those attributes are permitted on those elements.
</li>
</ul></li>
</ul>
<p>
Please be very careful when using this functionality; while it may not
seem that empty elements contain useful information, they can alter the
layout of a document given appropriate styling. This directive is most
useful when you are processing machine-generated HTML, please avoid using
it on regular user HTML.
</p>
<p>
Elements that contain only whitespace will be treated as empty. Non-breaking
spaces, however, do not count as whitespace. See
%AutoFormat.RemoveEmpty.RemoveNbsp for alternate behavior.
</p>
<p>
This algorithm is not perfect; you may still notice some empty tags,
particularly if a node had elements, but those elements were later removed
because they were not permitted in that context, or tags that, after
being auto-closed by another tag, where empty. This is for safety reasons
to prevent clever code from breaking validation. The general rule of thumb:
if a tag looked empty on the way in, it will get removed; if HTML Purifier
made it empty, it will stay.
</p>
--# vim: et sw=4 sts=4
@@ -1,11 +1,11 @@
AutoFormat.RemoveSpansWithoutAttributes
TYPE: bool
VERSION: 4.0.1
DEFAULT: false
--DESCRIPTION--
<p>
This directive causes <code>span</code> tags without any attributes
to be removed. It will also remove spans that had all attributes
removed during processing.
</p>
--# vim: et sw=4 sts=4
AutoFormat.RemoveSpansWithoutAttributes
TYPE: bool
VERSION: 4.0.1
DEFAULT: false
--DESCRIPTION--
<p>
This directive causes <code>span</code> tags without any attributes
to be removed. It will also remove spans that had all attributes
removed during processing.
</p>
--# vim: et sw=4 sts=4
@@ -1,11 +1,11 @@
CSS.AllowDuplicates
TYPE: bool
DEFAULT: false
VERSION: 4.8.0
--DESCRIPTION--
<p>
By default, HTML Purifier removes duplicate CSS properties,
like <code>color:red; color:blue</code>. If this is set to
true, duplicate properties are allowed.
</p>
--# vim: et sw=4 sts=4
CSS.AllowDuplicates
TYPE: bool
DEFAULT: false
VERSION: 4.8.0
--DESCRIPTION--
<p>
By default, HTML Purifier removes duplicate CSS properties,
like <code>color:red; color:blue</code>. If this is set to
true, duplicate properties are allowed.
</p>
--# vim: et sw=4 sts=4
@@ -1,8 +1,8 @@
CSS.AllowImportant
TYPE: bool
DEFAULT: false
VERSION: 3.1.0
--DESCRIPTION--
This parameter determines whether or not !important cascade modifiers should
be allowed in user CSS. If false, !important will stripped.
--# vim: et sw=4 sts=4
CSS.AllowImportant
TYPE: bool
DEFAULT: false
VERSION: 3.1.0
--DESCRIPTION--
This parameter determines whether or not !important cascade modifiers should
be allowed in user CSS. If false, !important will stripped.
--# vim: et sw=4 sts=4
@@ -1,11 +1,11 @@
CSS.AllowTricky
TYPE: bool
DEFAULT: false
VERSION: 3.1.0
--DESCRIPTION--
This parameter determines whether or not to allow "tricky" CSS properties and
values. Tricky CSS properties/values can drastically modify page layout or
be used for deceptive practices but do not directly constitute a security risk.
For example, <code>display:none;</code> is considered a tricky property that
will only be allowed if this directive is set to true.
--# vim: et sw=4 sts=4
CSS.AllowTricky
TYPE: bool
DEFAULT: false
VERSION: 3.1.0
--DESCRIPTION--
This parameter determines whether or not to allow "tricky" CSS properties and
values. Tricky CSS properties/values can drastically modify page layout or
be used for deceptive practices but do not directly constitute a security risk.
For example, <code>display:none;</code> is considered a tricky property that
will only be allowed if this directive is set to true.
--# vim: et sw=4 sts=4
@@ -1,12 +1,12 @@
CSS.AllowedFonts
TYPE: lookup/null
VERSION: 4.3.0
DEFAULT: NULL
--DESCRIPTION--
<p>
Allows you to manually specify a set of allowed fonts. If
<code>NULL</code>, all fonts are allowed. This directive
affects generic names (serif, sans-serif, monospace, cursive,
fantasy) as well as specific font families.
</p>
--# vim: et sw=4 sts=4
CSS.AllowedFonts
TYPE: lookup/null
VERSION: 4.3.0
DEFAULT: NULL
--DESCRIPTION--
<p>
Allows you to manually specify a set of allowed fonts. If
<code>NULL</code>, all fonts are allowed. This directive
affects generic names (serif, sans-serif, monospace, cursive,
fantasy) as well as specific font families.
</p>
--# vim: et sw=4 sts=4
@@ -1,18 +1,18 @@
CSS.AllowedProperties
TYPE: lookup/null
VERSION: 3.1.0
DEFAULT: NULL
--DESCRIPTION--
<p>
If HTML Purifier's style attributes set is unsatisfactory for your needs,
you can overload it with your own list of tags to allow. Note that this
method is subtractive: it does its job by taking away from HTML Purifier
usual feature set, so you cannot add an attribute that HTML Purifier never
supported in the first place.
</p>
<p>
<strong>Warning:</strong> If another directive conflicts with the
elements here, <em>that</em> directive will win and override.
</p>
--# vim: et sw=4 sts=4
CSS.AllowedProperties
TYPE: lookup/null
VERSION: 3.1.0
DEFAULT: NULL
--DESCRIPTION--
<p>
If HTML Purifier's style attributes set is unsatisfactory for your needs,
you can overload it with your own list of tags to allow. Note that this
method is subtractive: it does its job by taking away from HTML Purifier
usual feature set, so you cannot add an attribute that HTML Purifier never
supported in the first place.
</p>
<p>
<strong>Warning:</strong> If another directive conflicts with the
elements here, <em>that</em> directive will win and override.
</p>
--# vim: et sw=4 sts=4

Some files were not shown because too many files have changed in this diff Show More