diff --git a/modules/poll/conf/info.xml b/modules/poll/conf/info.xml new file mode 100644 index 000000000..e143c0927 --- /dev/null +++ b/modules/poll/conf/info.xml @@ -0,0 +1,8 @@ + + + 엮인글 + + 제로 + 엮인글 관리 모듈 + + diff --git a/modules/poll/conf/module.xml b/modules/poll/conf/module.xml new file mode 100644 index 000000000..50ed7c141 --- /dev/null +++ b/modules/poll/conf/module.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/modules/poll/lang/ko.lang.php b/modules/poll/lang/ko.lang.php new file mode 100644 index 000000000..a09478230 --- /dev/null +++ b/modules/poll/lang/ko.lang.php @@ -0,0 +1,22 @@ + + * @brief 엮인글(trackback) 모듈의 기본 언어팩 + **/ + + $lang->cmd_delete_checked_trackback = '선택항목 삭제'; + + $lang->msg_cart_is_null = '삭제할 글을 선택해주세요'; + $lang->msg_checked_trackback_is_deleted = '%d개의 엮인글이 삭제되었습니다'; + + $lang->search_target_list = array( + 'url' => '대상 URL', + 'blog_name' => '대상 사이트 이름', + 'title' => '제목', + 'excerpt' => '내용', + 'regdate' => '등록일', + 'ipaddress' => 'IP 주소', + ); + +?> diff --git a/modules/poll/queries/deleteModuleTrackbacks.xml b/modules/poll/queries/deleteModuleTrackbacks.xml new file mode 100644 index 000000000..dc80d00fe --- /dev/null +++ b/modules/poll/queries/deleteModuleTrackbacks.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/modules/poll/queries/deleteTrackback.xml b/modules/poll/queries/deleteTrackback.xml new file mode 100644 index 000000000..e5a5e60f8 --- /dev/null +++ b/modules/poll/queries/deleteTrackback.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/poll/queries/deleteTrackbacks.xml b/modules/poll/queries/deleteTrackbacks.xml new file mode 100644 index 000000000..7b81949a0 --- /dev/null +++ b/modules/poll/queries/deleteTrackbacks.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/poll/queries/getTotalTrackbackList.xml b/modules/poll/queries/getTotalTrackbackList.xml new file mode 100644 index 000000000..9171d08df --- /dev/null +++ b/modules/poll/queries/getTotalTrackbackList.xml @@ -0,0 +1,22 @@ + + +
+ + + + + + + + + + + + + + + + + + + diff --git a/modules/poll/queries/getTrackback.xml b/modules/poll/queries/getTrackback.xml new file mode 100644 index 000000000..82eb419f1 --- /dev/null +++ b/modules/poll/queries/getTrackback.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/poll/queries/getTrackbackCount.xml b/modules/poll/queries/getTrackbackCount.xml new file mode 100644 index 000000000..9204bf91e --- /dev/null +++ b/modules/poll/queries/getTrackbackCount.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/poll/queries/getTrackbackCountByIPAddress.xml b/modules/poll/queries/getTrackbackCountByIPAddress.xml new file mode 100644 index 000000000..23871ee91 --- /dev/null +++ b/modules/poll/queries/getTrackbackCountByIPAddress.xml @@ -0,0 +1,12 @@ + + +
+ + + + + + + + + diff --git a/modules/poll/queries/getTrackbackList.xml b/modules/poll/queries/getTrackbackList.xml new file mode 100644 index 000000000..204972316 --- /dev/null +++ b/modules/poll/queries/getTrackbackList.xml @@ -0,0 +1,14 @@ + + +
+ + + + + + + + + + + diff --git a/modules/poll/queries/insertTrackback.xml b/modules/poll/queries/insertTrackback.xml new file mode 100644 index 000000000..d31308330 --- /dev/null +++ b/modules/poll/queries/insertTrackback.xml @@ -0,0 +1,17 @@ + + +
+ + + + + + + + + + + + + + diff --git a/modules/poll/schemas/trackbacks.xml b/modules/poll/schemas/trackbacks.xml new file mode 100644 index 000000000..acf2ffcf6 --- /dev/null +++ b/modules/poll/schemas/trackbacks.xml @@ -0,0 +1,12 @@ +
+ + + + + + + + + + +
diff --git a/modules/poll/tpl/filter/delete_checked.xml b/modules/poll/tpl/filter/delete_checked.xml new file mode 100644 index 000000000..a410c54e6 --- /dev/null +++ b/modules/poll/tpl/filter/delete_checked.xml @@ -0,0 +1,12 @@ + +
+ + + + + + + + + +
diff --git a/modules/poll/tpl/trackback_list.html b/modules/poll/tpl/trackback_list.html new file mode 100644 index 000000000..ebf329a47 --- /dev/null +++ b/modules/poll/tpl/trackback_list.html @@ -0,0 +1,83 @@ + + + +
+ {$lang->total_count} : {number_format($total_count)}, + {$lang->page_count} : {number_format($page)} / {number_format($total_page)} +
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->no}{$lang->module}{$lang->blog_name}{$lang->title}{$lang->date}{$lang->ipaddress}{$lang->cmd_move}
{$no}{$module_list[$val->module_srl]->browser_title}{$val->blog_name}{$val->title}{zdate($val->regdate,"Y-m-d")}{$val->ipaddress}{$lang->cmd_move}
{$val->excerpt}
+
+ + +
+ +
+ +
+ + +
+
+ + + +
+ + + + +
+
+
+ + + +
+ [{$lang->first_page}] + + + + {$page_no} + + [{$page_no}] + + + + [{$lang->last_page}] +
diff --git a/modules/poll/trackback.class.php b/modules/poll/trackback.class.php new file mode 100644 index 000000000..11c0353ba --- /dev/null +++ b/modules/poll/trackback.class.php @@ -0,0 +1,38 @@ +insertActionForward('trackback', 'controller', 'procTrackbackReceive'); + $oModuleController->insertActionForward('trackback', 'view', 'dispTrackbackAdminList'); + $oModuleController->insertActionForward('trackback', 'controller', 'procTrackbackAdminDeleteChecked'); + + return new Object(); + } + + /** + * @brief 설치가 이상이 없는지 체크하는 method + **/ + function moduleIsInstalled() { + return new Object(); + } + + /** + * @brief 업데이트 실행 + **/ + function moduleUpdate() { + return new Object(); + } + + } +?> diff --git a/modules/poll/trackback.controller.php b/modules/poll/trackback.controller.php new file mode 100644 index 000000000..97bd08954 --- /dev/null +++ b/modules/poll/trackback.controller.php @@ -0,0 +1,217 @@ +stop('msg_cart_is_null'); + $trackback_srl_list= explode('|@|', $cart); + $trackback_count = count($trackback_srl_list); + if(!$trackback_count) return $this->stop('msg_cart_is_null'); + + // 글삭제 + for($i=0;$i<$trackback_count;$i++) { + $trackback_srl = trim($trackback_srl_list[$i]); + if(!$trackback_srl) continue; + + $this->deleteTrackback($trackback_srl, true); + } + + $this->setMessage( sprintf(Context::getLang('msg_checked_trackback_is_deleted'), $trackback_count) ); + } + + /** + * @brief 엮인글 입력 + **/ + function procTrackbackReceive() { + Context::setRequestMethod("XMLRPC"); + + $obj = Context::gets('document_srl','url','title','excerpt'); + + // GET으로 넘어온 document_srl을 참조, 없으면 오류~ + $document_srl = $obj->document_srl; + if(!$document_srl) return $this->stop('fail'); + + // document model 객체 생성후 원본글을 가져옴 + $oDocumentModel = &getModel('document'); + $document = $oDocumentModel->getDocument($document_srl); + + // 원본글이 없거나 트랙백 허용을 하지 않으면 오류 표시 + if(!$document_srl) return $this->stop('fail'); + if($document->allow_trackback=='N') return $this->stop('fail'); + + // 엮인글 정리 + $obj = Context::convertEncoding($obj); + if(!$obj->blog_name) $obj->blog_name = $obj->title; + $obj->excerpt = strip_tags($obj->excerpt); + + // 엮인글를 입력 + $obj->list_order = $obj->trackback_srl = getNextSequence(); + $obj->module_srl = $document->module_srl; + $output = executeQuery('trackback.insertTrackback', $obj); + + // 입력에 이상이 없으면 해당 글의 엮인글 수를 올림 + if(!$output->toBool()) return $this->stop( 'fail'); + + // trackback model 객체 생성 + $oTrackbackModel = &getModel('trackback'); + + // 해당 글의 전체 엮인글 수를 구해옴 + $trackback_count = $oTrackbackModel->getTrackbackCount($document_srl); + + // document controller 객체 생성 + $oDocumentController = &getController('document'); + + // 해당글의 엮인글 수를 업데이트 + $output = $oDocumentController->updateTrackbackCount($document_srl, $trackback_count); + + // 결과 return + if(!$output->toBool()) return $this->stop('fail'); + + $this->setMessage('success'); + } + + /** + * @brief 단일 엮인글 삭제 + **/ + function deleteTrackback($trackback_srl, $is_admin = false) { + // trackback model 객체 생성 + $oTrackbackModel = &getModel('trackback'); + + // 삭제하려는 엮인글이 있는지 확인 + $trackback = $oTrackbackModel->getTrackback($trackback_srl); + if($trackback->data->trackback_srl != $trackback_srl) return new Object(-1, 'msg_invalid_request'); + $document_srl = $trackback->data->document_srl; + + // document model 객체 생성 + $oDocumentModel = &getModel('document'); + + // 권한이 있는지 확인 + if(!$is_admin && !$oDocumentModel->isGranted($document_srl)) return new Object(-1, 'msg_not_permitted'); + + $args->trackback_srl = $trackback_srl; + $output = executeQuery('trackback.deleteTrackback', $args); + if(!$output->toBool()) return new Object(-1, 'msg_error_occured'); + + // 엮인글 수를 구해서 업데이트 + $trackback_count = $oTrackbackModel->getTrackbackCount($document_srl); + + // document controller 객체 생성 + $oDocumentController = &getController('document','controller'); + + // 해당글의 엮인글 수를 업데이트 + $output = $oDocumentController->updateTrackbackCount($document_srl, $trackback_count); + $output->add('document_srl', $document_srl); + + return $output; + } + + /** + * @brief 글에 속한 모든 트랙백 삭제 + **/ + function deleteTrackbacks($document_srl) { + // 삭제 + $args->document_srl = $document_srl; + $output = executeQuery('trackback.deleteTrackbacks', $args); + + return $output; + } + + /** + * @brief 모듈에 속한 모든 트랙백 삭제 + **/ + function deleteModuleTrackbacks($module_srl) { + // 삭제 + $args->module_srl = $module_srl; + $output = executeQuery('trackback.deleteModuleTrackbacks', $args); + + return $output; + } + + /** + * @brief 엮인글을 발송 + * + * 발송 후 결과처리는 하지 않는 구조임 + **/ + function sendTrackback($document, $trackback_url, $charset) { + // 발송할 정보를 정리 + $http = parse_url($trackback_url); + $obj->blog_name = Context::getBrowserTitle(); + $obj->title = $document->title; + $obj->excerpt = cut_str($document->content, 240); + $obj->url = sprintf("%s?document_srl=%d", Context::getRequestUri(), $document->document_srl); + + // blog_name, title, excerpt, url의 문자열을 요청된 charset으로 변경 + if($charset && function_exists('iconv')) { + foreach($obj as $key=>$val) { + $obj->{$key} = iconv('UTF-8',$charset,$val); + } + } + + // socket으로 발송할 내용 작성 + if($http['query']) $http['query'].="&"; + if(!$http['port']) $http['port'] = 80; + + $content = + sprintf( + "title=%s&". + "url=%s&". + "blog_name=%s&". + "excerpt=%s", + urlencode($obj->title), + urlencode($obj->url), + urlencode($obj->blog_name), + urlencode($obj->excerpt) + ); + if($http['query']) $content .= '&'.$http['query']; + $content_length = strlen($content); + + // header 정리 + $header = + sprintf( + "POST %s HTTP/1.1\r\n". + "Host: %s\r\n". + "Content-Type: %s\r\n". + "Content-Length: %s\r\n\r\n". + "%s\r\n", + $http['path'], + $http['host'], + "application/x-www-form-urlencoded", + $content_length, + $content + ); + if(!$http['host']||!$http['port']) return; + + // 발송하려는 대상 서버의 socket을 연다 + $fp = @fsockopen($http['host'], $http['port'], $errno, $errstr, 5); + if(!$fp) return; + + // 작성한 헤더 정보를 발송 + fputs($fp, $header); + + // 결과를 기다림 (특정 서버의 경우 EOF가 떨어지지 않을 수가 있음 + while(!feof($fp)) { + $line = trim(fgets($fp, 4096)); + if(eregi("^",$line)) break; + } + + // socket 닫음 + fclose($fp); + } + } +?> diff --git a/modules/poll/trackback.model.php b/modules/poll/trackback.model.php new file mode 100644 index 000000000..b05d65005 --- /dev/null +++ b/modules/poll/trackback.model.php @@ -0,0 +1,116 @@ +trackback_srl = $trackback_srl; + return executeQuery('trackback.getTrackback', $args); + } + + /** + * @brief document_srl 에 해당하는 엮인글의 전체 갯수를 가져옴 + **/ + function getTrackbackCount($document_srl) { + $args->document_srl = $document_srl; + $output = executeQuery('trackback.getTrackbackCount', $args); + $total_count = $output->data->count; + + return (int)$total_count; + } + + /** + * @brief 특정 document에 특정 ip로 기록된 트랙백의 갯수 + * spamfilter 에서 사용할 method임 + **/ + function getTrackbackCountByIPAddress($document_srl, $ipaddress) { + $args->document_srl = $document_srl; + $args->ipaddress = $ipaddress; + $output = executeQuery('trackback.getTrackbackCountByIPAddress', $args); + $total_count = $output->data->count; + + return (int)$total_count; + } + + /** + * @brief 특정 문서에 속한 엮인글의 목록을 가져옴 + **/ + function getTrackbackList($document_srl) { + $args->document_srl = $document_srl; + $args->list_order = 'list_order'; + $output = executeQuery('trackback.getTrackbackList', $args); + + if(!$output->toBool()) return $output; + + $trackback_list = $output->data; + + if(!is_array($trackback_list)) $trackback_list = array($trackback_list); + + return $trackback_list; + } + + /** + * @brief 모든 엮인글를 시간 역순으로 가져옴 (관리자용) + **/ + function getTotalTrackbackList($obj) { + // 검색 옵션 정리 + $search_target = trim(Context::get('search_target')); + $search_keyword = trim(Context::get('search_keyword')); + + if($search_target && $search_keyword) { + switch($search_target) { + case 'url' : + if($search_keyword) $search_keyword = str_replace(' ','%',$search_keyword); + $args->s_url = $search_keyword; + break; + case 'title' : + if($search_keyword) $search_keyword = str_replace(' ','%',$search_keyword); + $args->s_title= $search_keyword; + break; + case 'blog_name' : + if($search_keyword) $search_keyword = str_replace(' ','%',$search_keyword); + $args->s_blog_name= $search_keyword; + break; + case 'excerpt' : + if($search_keyword) $search_keyword = str_replace(' ','%',$search_keyword); + $args->s_excerpt = $search_keyword; + break; + case 'regdate' : + $args->s_regdate = $search_keyword; + break; + case 'ipaddress' : + $args->s_ipaddress= $search_keyword; + break; + } + } + + + // 변수 설정 + $args->sort_index = $obj->sort_index; + $args->page = $obj->page?$obj->page:1; + $args->list_count = $obj->list_count?$obj->list_count:20; + $args->page_count = $obj->page_count?$obj->page_count:10; + + // trackback.getTotalTrackbackList 쿼리 실행 + $output = executeQuery('trackback.getTotalTrackbackList', $args); + + // 결과가 없거나 오류 발생시 그냥 return + if(!$output->toBool()||!count($output->data)) return $output; + + return $output; + } + } +?> diff --git a/modules/poll/trackback.view.php b/modules/poll/trackback.view.php new file mode 100644 index 000000000..9d77fa147 --- /dev/null +++ b/modules/poll/trackback.view.php @@ -0,0 +1,63 @@ +page = Context::get('page'); ///< 페이지 + $args->list_count = 50; ///< 한페이지에 보여줄 글 수 + $args->page_count = 10; ///< 페이지 네비게이션에 나타날 페이지의 수 + + $args->sort_index = 'list_order'; ///< 소팅 값 + + // 목록 구함 + $oTrackbackModel = &getModel('trackback'); + $output = $oTrackbackModel->getTotalTrackbackList($args); + + // 목록의 loop를 돌면서 mid를 구하기 위한 module_srl값을 구함 + $trackback_count = count($output->data); + if($trackback_count) { + foreach($output->data as $key => $val) { + $module_srl = $val->module_srl; + if(!in_array($module_srl, $module_srl_list)) $module_srl_list[] = $module_srl; + } + if(count($module_srl_list)) { + $args->module_srls = implode(',',$module_srl_list); + $mid_output = executeQuery('module.getModuleInfoByModuleSrl', $args); + if($mid_output->data && !is_array($mid_output->data)) $mid_output->data = array($mid_output->data); + for($i=0;$idata);$i++) { + $mid_info = $mid_output->data[$i]; + $module_list[$mid_info->module_srl] = $mid_info; + } + } + } + + // 템플릿에 쓰기 위해서 변수 설정 + Context::set('total_count', $output->total_count); + Context::set('total_page', $output->total_page); + Context::set('page', $output->page); + Context::set('trackback_list', $output->data); + Context::set('page_navigation', $output->page_navigation); + Context::set('module_list', $module_list); + + // 템플릿 지정 + $this->setTemplatePath($this->module_path.'tpl'); + $this->setTemplateFile('trackback_list'); + } + + } +?>