From cb1e31bf5ee5052a8c709c1682b4ea8cdf576011 Mon Sep 17 00:00:00 2001 From: zero Date: Fri, 7 Dec 2007 09:36:12 +0000 Subject: [PATCH] =?UTF-8?q?=EC=8A=A4=ED=8C=B8=ED=95=84=ED=84=B0=20?= =?UTF-8?q?=EC=95=A0=EB=93=9C=EC=98=A8=EC=9D=84=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=ED=95=98=EA=B3=A0=20=EC=8A=A4=ED=8C=B8=ED=95=84=ED=84=B0=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=EC=97=90=EC=84=9C=20=EC=A7=81=EC=A0=91=20tri?= =?UTF-8?q?gger=EB=A1=9C=20=EA=B8=80/=EB=8C=93=EA=B8=80/=EC=8A=A4=ED=8C=B8?= =?UTF-8?q?=EA=B8=80=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=8A=A4=ED=8C=B8?= =?UTF-8?q?=ED=95=84=ED=84=B0=EB=A7=81=20=EC=A0=9C=EC=96=B4.=20=EC=97=AE?= =?UTF-8?q?=EC=9D=B8=EA=B8=80=20=EC=8A=A4=ED=8C=B8=ED=95=84=ED=84=B0?= =?UTF-8?q?=EB=A7=81=20=EA=B8=B0=EB=8A=A5=20=EA=B0=95=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://xe-core.googlecode.com/svn/sandbox@3216 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- addons/spamfilter/spamfilter.addon.php | 131 +----------------- modules/spamfilter/queries/isDeniedIP.xml | 2 +- modules/spamfilter/spamfilter.class.php | 25 +++- modules/spamfilter/spamfilter.controller.php | 106 ++++++++++++++ modules/spamfilter/spamfilter.model.php | 86 +++++++++++- .../queries/getRegistedTrackback.xml | 12 ++ .../queries/getRegistedTrackbacks.xml | 12 ++ modules/trackback/trackback.controller.php | 28 +++- modules/trackback/trackback.model.php | 10 ++ 9 files changed, 272 insertions(+), 140 deletions(-) create mode 100644 modules/trackback/queries/getRegistedTrackback.xml create mode 100644 modules/trackback/queries/getRegistedTrackbacks.xml diff --git a/addons/spamfilter/spamfilter.addon.php b/addons/spamfilter/spamfilter.addon.php index 9c52ebfe3..73ab00fb3 100644 --- a/addons/spamfilter/spamfilter.addon.php +++ b/addons/spamfilter/spamfilter.addon.php @@ -1,133 +1,6 @@ act, $effecived_target_act)) return; - - // 각 모듈별 act에 대해서도 피해갈 부분이 있으면 피해감 - switch($this->act) { - - // 게시물 작성시 신규 등록이 아니면 패스~ - case 'procBoardInsertDocument' : - // document module의 model 객체 생성 - $oDocumentModel = &getModel('document'); - - // 이미 존재하는 글인지 체크 - $document_srl = Context::get('document_srl'); - $oDocument = $oDocumentModel->getDocument($document_srl); - - // 이미 존재하는 글이라면 return - if($oDocument->isExists()) return; - break; - - // 댓글 작성시 신규 등록이 아니면 패스~ - case 'procBoardInsertComment' : - case 'procBlogInsertComment' : - $comment_srl = Context::get('comment_srl'); - $oCommentModel = &getModel('comment'); - - // 이미 존재하는 댓글인지 체크 - $comment = $oCommentModel->getComment($comment_srl); - if($comment->comment_srl == $comment_srl) return; - break; - } - - // 현재 모듈의 관리자이거나 그에 준하는 manager권한이면 그냥 패스 - if($this->grant->is_admin || $this->grant->manager) return; - - // 현 접속자의 ip address를 구함 - $ipaddress = $_SERVER['REMOTE_ADDR']; - - // spamfilter 모듈 객체 생성 - $oSpamFilterController = &getController('spamfilter'); - $oSpamFilterModel = &getModel('spamfilter'); - - // 스팸필터 기본 설정 출력 - $config = $oSpamFilterModel->getConfig(); - - // 스팸 간격을 체크하는 변수 - $interval = $config->interval?$config->interval:60; - - // 스팸 간격내에 limit_count이상 작성을 시도하면 해당 ip를 금지 시킴 - $limit_count = $config->limit_count?$config->limit_count:5; - - // 트랙백의 경우 한 글에 하나의 ip에서만 트랙백을 허용함 - $check_trackback = $config->check_trackback=='Y'?true:false; - - // 스팸 IP에 등록되어 있는지 체크하여 등록되어 있으면 return - $is_denied = $oSpamFilterModel->isDeniedIP($ipaddress); - if($is_denied) { - $output = new Object(-1, 'msg_alert_registered_denied_ip'); - $this->stop_proc = true; - return; - } - - // act==procReceiveTrackback (트랙백)일때 check_trackback==true이면 검사 - if($this->act=='trackback' && $check_trackback){ - $oTrackbackModel = &getModel('trackback'); - $document_srl = Context::get('document_srl'); - $count = $oTrackbackModel->getTrackbackCountByIPAddress($document_srl, $ipaddress); - if($count>0) { - $output = Object(-1, 'msg_alert_trackback_denied'); - $this->stop_proc = true; - return; - } - } - - // 정해진 시간내에 글 작성 시도를 하였는지 체크 - $count = $oSpamFilterModel->getLogCount($interval, $ipaddress); - - // 정해진 시간내에 정해진 글의 수를 초과시 스팸 IP로 등록시킴 - if($count>=$limit_count) { - $oSpamFilterController->insertIP($ipaddress); - $output = new Object(-1, 'msg_alert_registered_denied_ip'); - $this->stop_proc = true; - return; - - // 제한 글수까지는 아니지만 정해진 시간내에 글 작성을 계속 할때 - } elseif($count) { - $message = sprintf(Context::getLang('msg_alert_limited_by_config'), $interval); - $output = new Object(-1, $message); - $this->stop_proc = true; - } - - // 금지 단어 체크를 위해서 몇가지 지정된 변수들을 한데 묶음 - $check_vars = implode("\n",get_object_vars(Context::getRequestVars())); - - // 금지 단어를 이용하여 본문 내용을 체크 - $denied_word_list = $oSpamFilterModel->getDeniedWordList(); - $denied_word_count = count($denied_word_list); - if($denied_word_count>0) { - for($i=0;$i<$denied_word_count;$i++) { - $word = preg_quote($denied_word_list[$i]->word,'/'); - if(preg_match('/'.$word.'/i', $check_vars)) { - $message = sprintf(Context::getLang('msg_alert_denied_word'), $word); - $output = new Object(-1, $message); - $this->stop_proc = true; - return; - } - } - } - - // 로그를 남김 - $oSpamFilterController->insertLog(); + return; ?> diff --git a/modules/spamfilter/queries/isDeniedIP.xml b/modules/spamfilter/queries/isDeniedIP.xml index 6bfd31adf..53b497cc8 100644 --- a/modules/spamfilter/queries/isDeniedIP.xml +++ b/modules/spamfilter/queries/isDeniedIP.xml @@ -6,6 +6,6 @@ - + diff --git a/modules/spamfilter/spamfilter.class.php b/modules/spamfilter/spamfilter.class.php index b1375b138..831fd989e 100644 --- a/modules/spamfilter/spamfilter.class.php +++ b/modules/spamfilter/spamfilter.class.php @@ -17,6 +17,11 @@ $oModuleController->insertActionForward('spamfilter', 'view', 'dispSpamfilterAdminDeniedIPList'); $oModuleController->insertActionForward('spamfilter', 'view', 'dispSpamfilterAdminDeniedWordList'); + // 2007. 12. 7 글/ 댓글/ 엮인글이 등록될때 스팸필터링을 시도하는 트리거 + $oModuleController->insertTrigger('document.insertDocument', 'spamfilter', 'controller', 'triggerInsertDocument', 'before'); + $oModuleController->insertTrigger('comment.insertComment', 'spamfilter', 'controller', 'triggerInsertComment', 'before'); + $oModuleController->insertTrigger('trackback.insertTrackback', 'spamfilter', 'controller', 'triggerInsertTrackback', 'before'); + return new Object(); } @@ -24,6 +29,13 @@ * @brief 설치가 이상이 없는지 체크하는 method **/ function checkUpdate() { + $oModuleModel = &getModel('module'); + + // 2007. 12. 7 글/ 댓글/ 엮인글이 등록될때 스팸필터링을 시도하는 트리거 + if(!$oModuleModel->getTrigger('document.insertDocument', 'spamfilter', 'controller', 'triggerInsertDocument', 'before')) return true; + if(!$oModuleModel->getTrigger('comment.insertComment', 'spamfilter', 'controller', 'triggerInsertComment', 'before')) return true; + if(!$oModuleModel->getTrigger('trackback.insertTrackback', 'spamfilter', 'controller', 'triggerInsertTrackback', 'before')) return true; + return false; } @@ -31,7 +43,18 @@ * @brief 업데이트 실행 **/ function moduleUpdate() { - return new Object(); + $oModuleModel = &getModel('module'); + $oModuleController = &getController('module'); + + // 2007. 12. 7 글/ 댓글/ 엮인글이 등록될때 스팸필터링을 시도하는 트리거 + if(!$oModuleModel->getTrigger('document.insertDocument', 'spamfilter', 'controller', 'triggerInsertDocument', 'before')) + $oModuleController->insertTrigger('document.insertDocument', 'spamfilter', 'controller', 'triggerInsertDocument', 'before'); + if(!$oModuleModel->getTrigger('comment.insertComment', 'spamfilter', 'controller', 'triggerInsertComment', 'before')) + $oModuleController->insertTrigger('comment.insertComment', 'spamfilter', 'controller', 'triggerInsertComment', 'before'); + if(!$oModuleModel->getTrigger('trackback.insertTrackback', 'spamfilter', 'controller', 'triggerInsertTrackback', 'before')) + $oModuleController->insertTrigger('trackback.insertTrackback', 'spamfilter', 'controller', 'triggerInsertTrackback', 'before'); + + return new Object(0,'success_updated'); } /** diff --git a/modules/spamfilter/spamfilter.controller.php b/modules/spamfilter/spamfilter.controller.php index 0028d25e0..3f733d6c4 100644 --- a/modules/spamfilter/spamfilter.controller.php +++ b/modules/spamfilter/spamfilter.controller.php @@ -13,6 +13,112 @@ function init() { } + /** + * @brief 글 작성시 글 작성 시간 체크 및 금지 ip/단어 처리 루틴 + **/ + function triggerinsertDocument(&$obj) { + // 로그인 여부, 로그인 정보, 권한 유무 체크 + $is_logged = Context::get('is_logged'); + $logged_info = Context::get('logged_info'); + $grant = Context::get('grant'); + + // 로그인 되어 있을 경우 관리자 여부를 체크 + if($is_logged) { + if($logged_info->is_admin == 'Y') return new Object(); + if($grant->manager) return new Object(); + } + + $oFilterModel = &getModel('spamfilter'); + + // ip가 금지되어 있는 경우를 체크 + $output = $oFilterModel->isDeniedIP(); + if(!$output->toBool()) return $output; + + // 금지 단어에 있을 경우 체크 + $text = $obj->title.$obj->content; + $output = $oFilterModel->isDeniedWord($text); + if(!$output->toBool()) return $output; + + // 지정된 시간 체크 + $output = $oFilterModel->checkLimited(); + if(!$output->toBool()) return $output; + + // 로그 남김 + $this->insertLog(); + + return new Object(); + } + + /** + * @brief 댓글 작성 시간 및 금지 ip/ 단어 처리 루틴 + **/ + function triggerInsertComment(&$obj) { + // 로그인 여부, 로그인 정보, 권한 유무 체크 + $is_logged = Context::get('is_logged'); + $logged_info = Context::get('logged_info'); + $grant = Context::get('grant'); + + // 로그인 되어 있을 경우 관리자 여부를 체크 + if($is_logged) { + if($logged_info->is_admin == 'Y') return new Object(); + if($grant->manager) return new Object(); + } + + $oFilterModel = &getModel('spamfilter'); + + // ip가 금지되어 있는 경우를 체크 + $output = $oFilterModel->isDeniedIP(); + if(!$output->toBool()) return $output; + + // 금지 단어에 있을 경우 체크 + $text = $obj->content; + $output = $oFilterModel->isDeniedWord($text); + if(!$output->toBool()) return $output; + + // 지정된 시간 체크 + $output = $oFilterModel->checkLimited(); + if(!$output->toBool()) return $output; + + // 로그 남김 + $this->insertLog(); + + return new Object(); + } + + /** + * @brief 엮인글 작성시 시간 및 ip 검사 + **/ + function triggerInsertTrackback(&$obj) { + $oFilterModel = &getModel('spamfilter'); + + // 해당 글에 엮인글을 한번 이상 추가하였는지를 확인 + $output = $oFilterModel->isInsertedTrackback($obj->document_srl); + if(!$output->toBool()) return $output; + + // ip가 금지되어 있는 경우를 체크 + $output = $oFilterModel->isDeniedIP(); + if(!$output->toBool()) return $output; + + // 금지 단어에 있을 경우 체크 + $text = $obj->blog_name.$obj->title.$obj->excerpt.$obj->url; + $output = $oFilterModel->isDeniedWord($text); + if(!$output->toBool()) return $output; + + // 12시간 이내에 3개 이상 한 C클래스의 ip에서 엮인글 등록 시도시 금지 아이피로 지정하고 해당 ip의 글을 모두 삭제 + $oTrackbackModel = &getModel('trackback'); + list($ipA,$ipB,$ipC,$ipD) = explode('.',$_SERVER['REMOTE_ADDR']); + $ipaddress = $ipA.'.'.$ipB.'.'.$ipC; + $count = $oTrackbackModel->getRegistedTrackback(24*60*60, $ipaddress); + if($count > 2) { + $oTrackbackController = &getController('trackback'); + $oTrackbackController->deleteTrackbackSender(24*60*60, $ipaddress); + $this->insertIP($_SERVER['REMOTE_ADDR']); + return new Object(-1,'msg_alert_trackback_denied'); + } + + return new Object(); + } + /** * @brief IP 등록 * 등록된 IP는 스패머로 간주 diff --git a/modules/spamfilter/spamfilter.model.php b/modules/spamfilter/spamfilter.model.php index 97dd2a65f..54b64136b 100644 --- a/modules/spamfilter/spamfilter.model.php +++ b/modules/spamfilter/spamfilter.model.php @@ -37,11 +37,24 @@ /** * @brief 인자로 넘겨진 ipaddress가 금지 ip인지 체크하여 return **/ - function isDeniedIP($ipaddress) { - $args->ipaddress = $ipaddress; - $output = executeQuery('spamfilter.isDeniedIP', $args); - if($output->data->count>0) return true; - return false; + function isDeniedIP() { + $ipaddress = $_SERVER['REMOTE_ADDR']; + + $ip_list = $this->getDeniedIPList(); + if(!count($ip_list)) return false; + + $count = count($ip_list); + $patterns = array(); + for($i=0;$i<$count;$i++) { + $ip = str_replace('*','',$ip_list[$i]->ipaddress); + $patterns[] = $ip; + } + + $pattern = '/^('.implode($patterns,'|').')/'; + + if(preg_match($pattern, $ipaddress, $matches)) return new Object(-1,'msg_alert_registered_denied_ip'); + + return new Object(); } /** @@ -55,6 +68,69 @@ return $output->data; } + /** + * @brief 넘어온 text에 금지 단어가 있는지 확인 + **/ + function isDeniedWord($text) { + $word_list = $this->getDeniedWordList(); + if(!count($word_list)) return false; + + $count = count($word_list); + for($i=0;$i<$count;$i++) { + $word = $word_list[$i]->word; + if(strpos($text, $word)!==false) return new Object(-1,sprintf(Context::getLang('msg_alert_denied_word'), $word)); + } + + return new Object(); + } + + /** + * @brief 지정된 시간을 체크 + **/ + function checkLimited() { + $config = $this->getConfig(); + $limit_count = $config->limit_count?$config->limit_count:5; + $interval = $config->interval?$config->interval:60; + + $count = $this->getLogCount($interval); + + $ipaddress = $_SERVER['REMOTE_ADDR']; + + // 정해진 시간보다 클 경우 금지 ip로 등록 + if($count>=$limit_count) { + $oSpamFilterController = &getController('spamfilter'); + $oSpamFilterController->insertIP($ipaddress); + return new Object(-1, 'msg_alert_registered_denied_ip'); + } + + // 제한 글수까지는 아니지만 정해진 시간내에 글 작성을 계속 할때 + if($count) { + $message = sprintf(Context::getLang('msg_alert_limited_by_config'), $interval); + + $oSpamFilterController = &getController('spamfilter'); + $oSpamFilterController->insertLog(); + + return new Object(-1, $message); + } + + return new Object(); + } + + /** + * @brief 특정 글에 이미 엮인글이 등록되어 있는지 확인 + **/ + function isInsertedTrackback($document_srl) { + $config = $this->getConfig(); + $check_trackback = $config->check_trackback=='Y'?true:false; + if(!$check_trackback) return new Object(); + + $oTrackbackModel = &getModel('trackback'); + $count = $oTrackbackModel->getTrackbackCountByIPAddress($document_srl, $_SERVER['REMOTE_ADDR']); + if($count>0) return Object(-1, 'msg_alert_trackback_denied'); + + return new Object(); + } + /** * @brief 지정된 IPaddress의 특정 시간대 내의 로그 수를 return **/ diff --git a/modules/trackback/queries/getRegistedTrackback.xml b/modules/trackback/queries/getRegistedTrackback.xml new file mode 100644 index 000000000..f3bff75e3 --- /dev/null +++ b/modules/trackback/queries/getRegistedTrackback.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/modules/trackback/queries/getRegistedTrackbacks.xml b/modules/trackback/queries/getRegistedTrackbacks.xml new file mode 100644 index 000000000..603a6cdb3 --- /dev/null +++ b/modules/trackback/queries/getRegistedTrackbacks.xml @@ -0,0 +1,12 @@ + + +
+ + + + + + + + + diff --git a/modules/trackback/trackback.controller.php b/modules/trackback/trackback.controller.php index af959f07a..64f5c31d2 100644 --- a/modules/trackback/trackback.controller.php +++ b/modules/trackback/trackback.controller.php @@ -114,6 +114,15 @@ } function insertTrackback($obj, $manual_inserted = false) { + // 엮인글 정리 + $obj = Context::convertEncoding($obj); + if(!$obj->blog_name) $obj->blog_name = $obj->title; + $obj->excerpt = strip_tags($obj->excerpt); + + // trigger 호출 (before) + $output = ModuleHandler::triggerCall('trackback.insertTrackback', 'before', $obj); + if(!$output->toBool()) return $output; + // GET으로 넘어온 document_srl을 참조, 없으면 오류~ $document_srl = $obj->document_srl; @@ -129,10 +138,6 @@ $obj->module_srl = $oDocument->get('module_srl'); } - // 엮인글 정리 - $obj = Context::convertEncoding($obj); - if(!$obj->blog_name) $obj->blog_name = $obj->title; - $obj->excerpt = strip_tags($obj->excerpt); // 엮인글를 입력 $obj->trackback_srl = getNextSequence(); @@ -283,5 +288,20 @@ return new Object(0, 'msg_trackback_send_success'); } + + /** + * @brief 특정 ipaddress의 특정 시간대 내의 엮인글을 모두 삭제 + **/ + function deleteTrackbackSender($time, $ipaddress) { + $obj->regdate = date("YmdHis",time()-$time); + $obj->ipaddress = $ipaddress; + $output = executeQueryArray('trackback.getRegistedTrackbacks', $obj); + if(!$output->data || !count($output->data)) return; + + foreach($output->data as $trackback) { + $trackback_srl = $trackback->trackback_srl; + $this->deleteTrackback($trackback_srl, true); + } + } } ?> diff --git a/modules/trackback/trackback.model.php b/modules/trackback/trackback.model.php index 6021f67aa..5fbba54eb 100644 --- a/modules/trackback/trackback.model.php +++ b/modules/trackback/trackback.model.php @@ -97,5 +97,15 @@ } return $module_trackback_config; } + + /** + * @brief 정해진 시간내에 전체 엮인글 등록수를 구함 + **/ + function getRegistedTrackback($time, $ipaddress) { + $obj->regdate = date("YmdHis",time()-$time); + $obj->ipaddress = $ipaddress; + $output = executeQuery('trackback.getRegistedTrackback', $obj); + return $output->data->count; + } } ?>