diff --git a/adm/board_delete.inc.php b/adm/board_delete.inc.php index 7887859a1..d1803212b 100644 --- a/adm/board_delete.inc.php +++ b/adm/board_delete.inc.php @@ -30,4 +30,7 @@ delete_cache_latest($tmp_bo_table); // 게시판 폴더 전체 삭제 rm_rf(G4_DATA_PATH.'/file/'.$tmp_bo_table); + +// syndication ping +include G4_BBS_PATH.'/syndi/include/include.adm.board_delete.inc.php'; ?> \ No newline at end of file diff --git a/adm/board_form_update.php b/adm/board_form_update.php index 7df9c8d2c..58a610b6b 100644 --- a/adm/board_form_update.php +++ b/adm/board_form_update.php @@ -280,5 +280,8 @@ if ($fields) { delete_cache_latest($bo_table); +// syndication ping +include G4_BBS_PATH.'/syndi/include/include.adm.board_form_update.php'; + goto_url("./board_form.php?w=u&bo_table={$bo_table}&{$qstr}"); ?> diff --git a/adm/board_list_update.php b/adm/board_list_update.php index 734dd6f04..75013bdd7 100644 --- a/adm/board_list_update.php +++ b/adm/board_list_update.php @@ -53,7 +53,7 @@ if ($_POST['act_button'] == "선택수정") { check_token(); // _BOARD_DELETE_ 상수를 선언해야 board_delete.inc.php 가 정상 작동함 - define("_BOARD_DELETE_", TRUE); + define('_BOARD_DELETE_', true); for ($i=0; $i diff --git a/bbs/delete.php b/bbs/delete.php index 5844dee2e..5256025c0 100644 --- a/bbs/delete.php +++ b/bbs/delete.php @@ -93,6 +93,9 @@ while ($row = sql_fetch_array($result)) // 파일테이블 행 삭제 sql_query(" delete from {$g4['board_file_table']} where bo_table = '$bo_table' and wr_id = '{$row['wr_id']}' "); + // syndication ping + include G4_BBS_PATH.'/syndi/include/include.bbs.delete.php'; + $count_write++; } else diff --git a/bbs/delete_all.php b/bbs/delete_all.php index 2885d73d5..6e4467a70 100644 --- a/bbs/delete_all.php +++ b/bbs/delete_all.php @@ -106,6 +106,9 @@ for ($i=count($tmp_array)-1; $i>=0; $i--) // 파일테이블 행 삭제 sql_query(" delete from {$g4['board_file_table']} where bo_table = '$bo_table' and wr_id = '{$row['wr_id']}' "); + // syndication ping + include G4_BBS_PATH.'/syndi/include/include.bbs.delete_all.php'; + $count_write++; } else diff --git a/bbs/move_update.php b/bbs/move_update.php index 50cc7d142..59c13fe4c 100644 --- a/bbs/move_update.php +++ b/bbs/move_update.php @@ -175,6 +175,9 @@ if ($sw == "move") sql_query(" update {$g4['board_table']} set bo_count_write = bo_count_write - '$save_count_write', bo_count_comment = bo_count_comment - '$save_count_comment' where bo_table = '$bo_table' "); } +// syndication ping +include G4_BBS_PATH.'/syndi/include/include.bbs.move_update.php'; + $msg = '해당 게시물을 선택한 게시판으로 '.$act.' 하였습니다.'; $opener_href = './board.php?bo_table='.$bo_table.'&page='.$page.'&'.$qstr; diff --git a/bbs/syndi/_common.php b/bbs/syndi/_common.php new file mode 100644 index 000000000..14553420b --- /dev/null +++ b/bbs/syndi/_common.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/bbs/syndi/config/site.config.php b/bbs/syndi/config/site.config.php new file mode 100644 index 000000000..f0af1ab7c --- /dev/null +++ b/bbs/syndi/config/site.config.php @@ -0,0 +1,19 @@ + diff --git a/bbs/syndi/func/site.func.php b/bbs/syndi/func/site.func.php new file mode 100644 index 000000000..b6a9cc632 --- /dev/null +++ b/bbs/syndi/func/site.func.php @@ -0,0 +1,440 @@ +setId($tag); + $oSite->setTitle($title); + $oSite->setUpdated(date('YmdHis')); + + // 홈페이지 주소 + $link_alternative = sprintf('http://%s', $GLOBALS['syndi_tag_domain']); + $oSite->setLinkAlternative($link_alternative); + + $link_self = sprintf('%s?id=%s&type=%s',$GLOBALS['syndi_echo_url'],$tag,$args->type); + $oSite->setLinkSelf($link_self); + + return $oSite; +} + +/** + * @brief Channel(게시판) 목록 + **/ +function Syndi_getChannelList($args) +{ + global $g4; + + $where = ''; + if($args->target_channel_id) $where .= " and b.bo_table='". mysql_real_escape_string($args->target_channel_id) . "'"; + + $sql = "select b.bo_table,b.bo_subject from " . $g4['board_table'] . " b, ". $g4['group_table'] . " g where b.bo_read_level=1 and b.bo_list_level=1 and g.gr_use_access=0 and g.gr_id = b.gr_id ". $where; + $sql .= " order by b.gr_id,b.bo_table"; + + if($args->type=='channel') + { + $sql .= sprintf(" limit %s,%s", ($args->page-1)*$args->max_entry, $args->max_entry); + } + + $result = sql_query($sql); + + $channel_list = array(); + while($row = sql_fetch_array($result)) + { + $row['bo_subject'] = $row['bo_subject']?$row['bo_subject']:$row['bo_table']; + + $tag = SyndicationHandler::getTag('channel',$row['bo_table']); + $oChannel = new SyndicationChannel; + $oChannel->setId($tag); + $oChannel->setTitle($row['bo_subject']); + $oChannel->setType('web'); + $oChannel->setUpdated(date('YmdHis')); + + $link_self = sprintf('%s?id=%s&type=%s',$GLOBALS['syndi_echo_url'],$tag,$args->type); + $oChannel->setLinkSelf($link_self); + + // 게시판 웹주소 + $link_alternative = sprintf('http://%s/bbs/board.php?bo_table=%s', $GLOBALS['syndi_tag_domain'], $row['bo_table']); + $oChannel->setLinkAlternative($link_alternative); + + $channel_list[] = $oChannel; + } + + sql_free_result($result); + + return $channel_list; +} + + +/** + * @brief 모든 게시판의 게시물을 가져올때, 다음 게시판을 가져옴 + **/ +function _Syndi_getNextChannelId($channel_id=null) +{ + global $g4; + + if(!$channel_id) + { + $sql = "select b.bo_table from " . $g4['board_table'] . " b, ". $g4['group_table'] . " g where b.bo_read_level=1 and b.bo_list_level=1 and g.gr_use_access=0 and g.gr_id = b.gr_id"; + $sql .= " order by b.gr_id,b.bo_table limit 1"; + + $row = sql_fetch($sql); + sql_free_result($result); + + return $row['bo_table']; + } + + $channel_id = mysql_real_escape_string($channel_id); + + $sql = "select b.bo_table from " . $g4['board_table'] . " b, ". $g4['group_table'] . " g where b.bo_table>'$channel_id' and b.bo_read_level=1 and b.bo_list_level=1 and g.gr_use_access=0 and g.gr_id = b.gr_id"; + $sql .= " order by b.gr_id,b.bo_table limit 1"; + + $result = sql_query($sql); + if(mysql_num_rows($result)==0) return false; + + $row = sql_fetch_array($result); + sql_free_result($result); + + return $row['bo_table']; +} + + +/** + * @brief 게시물 목록 + **/ +function Syndi_getArticleList($args) +{ + global $g4; + + /* + $args->target_content_id //게시물 번호 + $args->target_channel_id //게시판 번호 + $args->start_time //기간 + $args->end_time + $args->max_entry //출력 목록당 개수 + $args->page //페이지 번호 + $args->channel_id //모든 글 출력시 해당 게시판 + */ + + // all channel articles mysql 3.X, 4.0.X 에서는 sub query가 되지 않는다. + if(!$args->target_channel_id) + { + // $args->channel_id 가 없을 경우 첫번째 게시판을 가져온다. + if(!$args->channel_id) $args->channel_id = _Syndi_getNextChannelId(); + $args->target_channel_id = $args->channel_id; + $article_list = Syndi_getArticleList($args); + unset($args->target_channel_id); + + if(count($article_list)>0) return $article_list; + + return array(); + } + + return _Syndi_getArticleList($args); +} + + +/** + * @brief 게시물 목록 + **/ +function _Syndi_getArticleList($args) +{ + global $g4; + + /* + $args->target_content_id //게시물 번호 + $args->target_channel_id //게시판 번호 + $args->start_time //기간 + $args->end_time + $args->max_entry //출력 목록당 개수 + $args->page //페이지 번호 + */ + + $sql = "select count(*) as cnt from " . $g4['board_table'] . " b, ". $g4['group_table'] . " g where b.bo_table='" . mysql_real_escape_string($args->target_channel_id). "' and b.bo_read_level=1 and b.bo_list_level=1 and g.gr_use_access=0 and g.gr_id = b.gr_id"; + $row = sql_fetch_array(sql_query($sql)); + if($row['cnt']<1) return array(); + + $content_table = $t_board.'_'. $args->target_channel_id; + $category_table = $t_category.'_'. $args->target_channel_id; + + // get article list + $where = " and wr_is_comment=0 "; + if($args->target_content_id) $where .= ' and wr_id='. mysql_real_escape_string($args->target_content_id); + if($args->start_time) $where .= ' and wr_datetime >= '. _getTime($args->start_time); + if($args->end_time) $where .= ' and wr_datetime <= '. _getTime($args->end_time); + + $sql = "select wr_id, ca_name, wr_subject, wr_content, mb_id, wr_name, wr_homepage, wr_email, wr_datetime, wr_last + from " . $g4['write_prefix'] . $args->target_channel_id . " where 1=1" . $where; + $sql .= " order by wr_id desc "; + $sql .= sprintf(" limit %s,%s", ($args->page-1)*$args->max_entry, $args->max_entry); + + $result = sql_query($sql); + $article_list = array(); + while($row = sql_fetch_array($result)) + { + $oArticle = new SyndicationArticle; + $tag = SyndicationHandler::getTag('article', $args->target_channel_id, $row['wr_id']); + $oArticle->setId($tag); + $oArticle->setTitle($row['wr_subject']); + $oArticle->setContent($row['wr_content']); + $oArticle->setType('web'); + $oArticle->setCategory($row['ca_name']); + $oArticle->setName($row['wr_name']); + $oArticle->setEmail($row['wr_email']); + $oArticle->setUrl($row['wr_homepage']); + $oArticle->setPublished(date('YmdHis',_getTime($row['wr_datetime']))); + if($row['wr_last']) $oArticle->setUpdated(date('YmdHis',_getTime($row['wr_last']))); + + // 게시판 웹주소 + $link_channel_alternative = sprintf('http://%s/bbs/board.php?bo_table=%s',$GLOBALS['syndi_tag_domain'],$args->target_channel_id); + + // 게시물 웹주소 + $link_alternative = $link_channel_alternative . '&wr_id=' . $row['wr_id']; + + $oArticle->setLinkChannel($tag); + $oArticle->setLinkAlternative($link_alternative); + $oArticle->setLinkChannelAlternative($link_channel_alternative); + + // add list + $article_list[] = $oArticle; + } + + sql_free_result($result); + + return $article_list; +} + + + +/** + * @brief 삭제 게시물 목록 + * 삭제된 게시물에 대해 logging이 필요 + **/ +function Syndi_getDeletedList($args) +{ + global $g4; + $table = $g4['syndi_log_table']; + + // get delete article list + $where = ''; + if($args->target_content_id) $where .= " and content_id='" . mysql_real_escape_string($args->target_content_id) . "'"; + if($args->target_channel_id) $where .= " and bbs_id='" . mysql_real_escape_string($args->target_channel_id) . "'"; + if($args->start_time) $where .= ' and delete_date >= '. $args->start_time; + if($args->end_time) $where .= ' and delete_date <= '. $args->end_time; + + $sql = "select content_id, bbs_id, title, link_alternative, delete_date from $table where 1=1" . $where; + $sql .= " order by delete_date desc "; + $sql .= sprintf(" limit %s,%s", ($args->page-1)*$args->max_entry, $args->max_entry); + $result = sql_query($sql); + + $deleted_list = array(); + while($row = sql_fetch_array($result)) + { + $oDeleted = new SyndicationDeleted; + $tag = SyndicationHandler::getTag('article', $row['bbs_id'], $row['content_id']); + $oDeleted->setId($tag); + $oDeleted->setTitle($row['title']); + $oDeleted->setUpdated($row['delete_date']); + $oDeleted->setDeleted($row['delete_date']); + + if(substr($row['link_alternative'],0,2)=='./') + { + $row['link_alternative'] = 'http://' . $GLOBALS['syndi_tag_domain'] . substr($row['link_alternative'],1); + } + $oDeleted->setLinkAlternative($row['link_alternative']); + + $deleted_list[] = $oDeleted; + } + + sql_free_result($result); + + return $deleted_list; + +} + + +/** + * @brief Channel 목록 출력시 다음 페이지 번호 + * return array('page'=>다음 페이지); + **/ +function Syndi_getChannelNextPage($args) +{ + global $g4; + + $where = ''; + if($args->target_channel_id) $where .= " and bo_table='". mysql_real_escape_string($args->target_channel_id) . "'"; + + $count_sql = "select count(*) as cnt from " . $g4['board_table'] . " where bo_read_level=1 and bo_list_level=1 " .$where; + $result = sql_query($count_sql); + $row = sql_fetch_array($result); + sql_free_result($result); + + $total_count = $row['cnt']; + $total_page = ceil($total_count / $args->max_entry); + + if($args->page >= $total_page) + { + return false; + } + else + { + return array('page'=>$args->page+1); + } +} + + + +/** + * @brief 게시물 목록 출력시 다음 페이지 + * return array('page'=>다음 페이지, 'channel_id'=>다음 게시판) + **/ +function Syndi_getArticleNextPage($args) +{ + global $g4; + + // 사이트 모든 글 + if(!$args->target_channel_id) + { + // channel_id 라는 변수로 게시판id를 받는다 (mysql 3.x,4.0.x을 위해) + if(!$args->channel_id) + { + $args->channel_id = _Syndi_getNextChannelId(); + $args->all_channel = true; + } + + $args->target_channel_id = $args->channel_id; + $obj = _Syndi_getArticleNextPage($args); + + unset($args->target_channel_id, $args->all_channel); + + return $obj; + } + else + { + return _Syndi_getArticleNextPage($args); + } +} + +function _Syndi_getArticleNextPage($args) +{ + global $g4; + + $sql = "select count(*) as cnt from " . $g4['board_table'] . " b, ". $g4['group_table'] . " g where b.bo_table='" . mysql_real_escape_string($args->target_channel_id). "' and b.bo_read_level=1 and b.bo_list_level=1 and g.gr_use_access=0 and g.gr_id = b.gr_id"; + + if($row['cnt']==0) return false; + + // get article list + $where = " and wr_is_comment=0 "; + if($args->target_content_id) $where .= ' and wr_id='. mysql_real_escape_string($args->target_content_id); + if($args->start_time) $where .= ' and wr_datetime >= '. _getTime($args->start_time); + if($args->end_time) $where .= ' and wr_datetime <= '. _getTime($args->end_time); + + $count_sql = "select count(*) as cnt from " . $g4['write_prefix'] . $args->target_channel_id . " where 1=1 " .$where; + $result = sql_query($count_sql); + + $row = sql_fetch_array($result); + sql_free_result($result); + + $total_count = $row['cnt']; + $total_page = ceil($total_count / $args->max_entry); + + if($args->page >= $total_page) + { + if($args->all_channel) + { + $next_channel_id = _Syndi_getNextChannelId($args->target_channel_id); + if(!$next_channel_id) return false; + return array('page'=>1, 'channel_id'=>$next_channel_id); + } + else + { + return false; + } + } + else + { + return array('page'=>$args->page+1); + } +} + + +/** + * @brief 게시물 삭제 목록 출력시 다음 페이지 번호 + **/ +function Syndi_getDeletedNextPage($args) +{ + global $g4; + $table = $g4['syndi_log_table']; + + // get delete article list + $where = ''; + if($args->target_content_id) $where .= " and no='" . mysql_real_escape_string($args->target_content_id) . "'"; + if($args->target_channel_id) $where .= " and bbs_id='" . mysql_real_escape_string($args->target_channel_id) . "'"; + if($args->start_time) $where .= ' and delete_date >= '. $args->start_time; + if($args->end_time) $where .= ' and delete_date <= '. $args->end_time; + + $count_sql = "select count(*) as cnt from $table where 1=1" .$where; + $result = sql_query($count_sql); + $row = sql_fetch_array($result); + sql_free_result($result); + + $total_count = $row['cnt']; + $total_page = ceil($total_count / $args->max_entry); + + if($args->page >= $total_page) + { + return array('page'=>0); + } + else + { + return array('page'=>$args->page+1); + } +} + + +function _getTime($date) +{ + return strtotime($date); +} + +$oSyndicationHandler = &SyndicationHandler::getInstance(); +$oSyndicationHandler->registerFunction('site_info','Syndi_getSiteInfo'); +$oSyndicationHandler->registerFunction('channel_list','Syndi_getChannelList'); +$oSyndicationHandler->registerFunction('channel_next_page','Syndi_getChannelNextPage'); +$oSyndicationHandler->registerFunction('article_list','Syndi_getArticleList'); +$oSyndicationHandler->registerFunction('article_next_page','Syndi_getArticleNextPage'); +$oSyndicationHandler->registerFunction('deleted_list','Syndi_getDeletedList'); +$oSyndicationHandler->registerFunction('deleted_next_page','Syndi_getDeletedNextPage'); + +?> diff --git a/bbs/syndi/include/include.adm.board_delete.inc.php b/bbs/syndi/include/include.adm.board_delete.inc.php new file mode 100644 index 000000000..a419f712d --- /dev/null +++ b/bbs/syndi/include/include.adm.board_delete.inc.php @@ -0,0 +1,29 @@ +setId(SyndicationHandler::getTag('site')); +$oPing->setType('channel'); + +// delete log +$_sql = "delete from {$g4['syndi_log_table']} where bbs_id='%s'"; +sql_query(sprintf($_sql, $tmp_bo_table)); + +$oPing->request(); +?> \ No newline at end of file diff --git a/bbs/syndi/include/include.adm.board_form_update.php b/bbs/syndi/include/include.adm.board_form_update.php new file mode 100644 index 000000000..f643168be --- /dev/null +++ b/bbs/syndi/include/include.adm.board_form_update.php @@ -0,0 +1,23 @@ +setId(SyndicationHandler::getTag('site')); +$oPing->setType('channel'); + +$oPing->request(); +?> \ No newline at end of file diff --git a/bbs/syndi/include/include.adm.boardgroup_form_update.php b/bbs/syndi/include/include.adm.boardgroup_form_update.php new file mode 100644 index 000000000..fb82e76e3 --- /dev/null +++ b/bbs/syndi/include/include.adm.boardgroup_form_update.php @@ -0,0 +1,27 @@ +setId(SyndicationHandler::getTag('site')); +$oPing->setType('channel'); + +$oPing->request(); +?> \ No newline at end of file diff --git a/bbs/syndi/include/include.bbs.delete.php b/bbs/syndi/include/include.bbs.delete.php new file mode 100644 index 000000000..0ddfcc1c8 --- /dev/null +++ b/bbs/syndi/include/include.bbs.delete.php @@ -0,0 +1,37 @@ +setId(SyndicationHandler::getTag('channel', $bo_table)); +$oPing->setType('deleted'); +$oPing->request(); +?> \ No newline at end of file diff --git a/bbs/syndi/include/include.bbs.delete_all.php b/bbs/syndi/include/include.bbs.delete_all.php new file mode 100644 index 000000000..cb9bc40e2 --- /dev/null +++ b/bbs/syndi/include/include.bbs.delete_all.php @@ -0,0 +1,36 @@ +setId(SyndicationHandler::getTag('channel', $bo_table)); +$oPing->setType('deleted'); +$oPing->request(); +?> \ No newline at end of file diff --git a/bbs/syndi/include/include.bbs.move_update.php b/bbs/syndi/include/include.bbs.move_update.php new file mode 100644 index 000000000..d29a19b34 --- /dev/null +++ b/bbs/syndi/include/include.bbs.move_update.php @@ -0,0 +1,39 @@ +setId(SyndicationHandler::getTag('channel', $bo_table)); + $oPing->setType('article'); + $oPing->request(); + + unset($oPing); +} + +for($i=0, $c=count($_POST['chk_bo_table']); $i<$c; $i++) +{ + $oPing = new SyndicationPing; + $oPing->setId(SyndicationHandler::getTag('channel', $_POST['chk_bo_table'][$i])); + $oPing->setType('article'); + $oPing->request(); + + unset($oPing); +} +?> \ No newline at end of file diff --git a/bbs/syndi/include/include.bbs.write_update.php b/bbs/syndi/include/include.bbs.write_update.php new file mode 100644 index 000000000..81655e807 --- /dev/null +++ b/bbs/syndi/include/include.bbs.write_update.php @@ -0,0 +1,42 @@ +1 || $board['bo_view_level']>1) return; + +if($w == 'u' && $wr && !$wr['wr_id']) return; + + +// 수정 대상 또는 신규 입력한 id가 있다면 ping을 보냄 +if($wr['wr_id'] || $wr_id) +{ + $syndi_dir = realpath(dirname(__FILE__) .'/../'); + + // include config & Syndication Ping class + include $syndi_dir . '/config/site.config.php'; + include $syndi_dir . '/libs/SyndicationHandler.class.php'; + include $syndi_dir . '/libs/SyndicationPing.class.php'; + + $oPing = new SyndicationPing; + $oPing->setId(SyndicationHandler::getTag('channel', $board['bo_table'])); + $oPing->setType('article'); + + // if deleted + $_sql = "delete from {$g4['syndi_log_table']} where content_id='%s' and bbs_id='%s'"; + sql_query(sprintf($_sql, $wr_id ? $wr_id : $wr[wr_id], $board['bo_table'])); + + $oPing->request(); +} +?> \ No newline at end of file diff --git a/bbs/syndi/install.php b/bbs/syndi/install.php new file mode 100644 index 000000000..269c172b2 --- /dev/null +++ b/bbs/syndi/install.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/bbs/syndi/libs/SyndicationArticle.class.php b/bbs/syndi/libs/SyndicationArticle.class.php new file mode 100644 index 000000000..23f55fbf0 --- /dev/null +++ b/bbs/syndi/libs/SyndicationArticle.class.php @@ -0,0 +1,137 @@ +id = $id; + } + + /** + * @brief Author name + **/ + function setName($name) + { + $this->name = $name; + } + + /** + * @brief Author email + **/ + function setEmail($email) + { + $this->email = $email; + } + + /** + * @brief Author homepage or blog + **/ + function setUrl($url) + { + $this->url = $url; + } + + /** + * @brief category or tag of content + **/ + function setCategory($category) + { + $this->category = $category; + } + + /** + * @brief Title of content + **/ + function setTitle($title) + { + $this->title = $title; + } + + /** + * @brief content + **/ + function setContent($content) + { + $this->content = $content; + } + + /** + * @brief Syndication Content Type으로 blog 경우'blog', 일반사이트 경우 'web' + **/ + function setType($type='web') + { + $this->type = $type; + } + + /** + * @brief Syndication Ping Url + **/ + function setLinkSelf($link_self) + { + $this->link_self = $link_self; + } + + /** + * @brief Channel Syndication Ping Url + **/ + function setLinkChannel($link_channel) + { + $this->link_channel = $link_channel; + } + + /** + * @brief Article(게시물) 접근 Url + **/ + function setLinkAlternative($link_alternative) + { + $this->link_alternative = $link_alternative; + } + + /** + * @brief Channel(게시판) 접근 Url + **/ + function setLinkChannelAlternative($link_channel_alternative) + { + $this->link_channel_alternative = $link_channel_alternative; + } + + /** + * @brief published time + * 'YYYYMMDDHHIISS' type + **/ + function setPublished($published) + { + $this->published = $published; + } + + /** + * @brief update time + * 'YYYYMMDDHHIISS' type + **/ + function setUpdated($updated) + { + $this->updated = $updated; + } + + function __toString() + { + $str = ''; + foreach($this->node as $node){ + $str .= $this->get($node); + } + + return $str; + } +} + +?> diff --git a/bbs/syndi/libs/SyndicationChannel.class.php b/bbs/syndi/libs/SyndicationChannel.class.php new file mode 100644 index 000000000..0a94b5c9f --- /dev/null +++ b/bbs/syndi/libs/SyndicationChannel.class.php @@ -0,0 +1,98 @@ +id = $id; + } + + /** + * @brief Title of Channel + **/ + function setTitle($title) + { + $this->title = $title; + } + + /** + * @brief Type of Channel, web or blog + * blog 일경우 setLinkRss()를 등록해야 함 + **/ + function setType($type='web') + { + $this->type = $type; + } + + /** + * @brief Summary of Channel + **/ + function setSummary($summary) + { + $this->summary = $summary; + } + + /** + * @brief Syndication Ping Url + **/ + function setLinkSelf($link_self) + { + $this->link_self = $link_self; + } + + /** + * @brief Channel(게시판) 접근 Url + **/ + function setLinkAlternative($link_alternative) + { + $this->link_alternative = $link_alternative; + } + + /** + * @brief Channel RSS Url (type이 blog면 필수) + **/ + function setLinkRss($link_rss) + { + $this->link_rss = $link_rss; + } + + /** + * @brief 다음 페이지 Url + **/ + function setNextPage($obj) + { + if(!$obj) return; + + if($obj['page']>0) $this->link_next_in_thread = $this->link_self . '&page='. $obj['page']; + } + + /** + * @brief update time + * 'YYYYMMDDHHIISS' type + **/ + function setUpdated($updated) + { + $this->updated = $updated; + } + + function __toString() + { + $str = ''; + foreach($this->node as $node){ + $str .= $this->get($node); + } + + return $str; + } +} +?> \ No newline at end of file diff --git a/bbs/syndi/libs/SyndicationDeleted.class.php b/bbs/syndi/libs/SyndicationDeleted.class.php new file mode 100644 index 000000000..396840c07 --- /dev/null +++ b/bbs/syndi/libs/SyndicationDeleted.class.php @@ -0,0 +1,65 @@ +id = $id; + } + + /** + * @brief Title of content + **/ + function setTitle($title) + { + $this->title = $title; + } + + /** + * @brief update time + * 'YYYYMMDDHHIISS' type + **/ + function setUpdated($updated) + { + $this->updated = $updated; + } + + /** + * @brief deleted time + * 'YYYYMMDDHHIISS' type + **/ + function setDeleted($deleted) + { + $this->deleted = $deleted; + } + + /** + * @brief Article(게시물) 접근 Url + **/ + function setLinkAlternative($link_alternative) + { + $this->link_alternative = $link_alternative; + } + + function __toString() + { + $str = ''; + + foreach($this->node as $node){ + $str .= $this->get($node); + } + + return $str; + } +} +?> diff --git a/bbs/syndi/libs/SyndicationHandler.class.php b/bbs/syndi/libs/SyndicationHandler.class.php new file mode 100644 index 000000000..7a4774e9a --- /dev/null +++ b/bbs/syndi/libs/SyndicationHandler.class.php @@ -0,0 +1,346 @@ +register_function) != count($ids)) return false; + + foreach($this->register_function as $id => $func) + { + if(!in_array($id, $ids) || !is_callable($func)) + { + return false; + } + } + + return true; + } + + function registerFunction($id, $func) + { + $this->register_function[$id] = $func; + } + + function callFunction($id) + { + if(!isset($this->register_function[$id]) || !is_callable($this->register_function[$id])) return false; + + return call_user_func($this->register_function[$id], $this->param); + } + + + /** + * @brief set GET Value. + **/ + function setArgument($args=null) + { + if(!$args) $args = $_GET; + + $obj = new stdClass; + $obj->id = $args['id']; + + if($args['start-time']) $obj->start_time = SyndicationHandler::getDate($args['start-time']); + if($args['end-time']) $obj->end_time = SyndicationHandler::getDate($args['end-time']); + + $obj->max_entry = $args['max_entry']; + if(!$obj->max_entry) $obj->max_entry = 100; + + $obj->page = $args['page']; + if(!$obj->page) $obj->page = 1; + + $obj->type = $args['type']; + + // for getting all article on mysql 3.X, 4.0.X + if($args['channel_id']) $obj->channel_id = $args['channel_id']; + + $this->param = $obj; + $this->parseTag(); + } + + /** + * @brief parsing id value(Tag URI) + **/ + function parseTag() + { + // tag:domain,{YYYY}:site: + // tag:domain,{YYYY}:channel:{channel_id} + // tag:domain,{YYYY}:article:{channel_id}-{$article_id} + if(!preg_match('/^tag:([^,]+),([0-9]+):(site|channel|article)(.*)$/i',$this->param->id,$matches)) return; + + $this->target = $matches[3]; + $id = $matches[4]; + if($id && $id{0}==':') $id = substr($id, 1); + + switch($this->target) + { + case 'site': + break; + case 'channel': + if(!$id) + { + $this->target = $this->target_channel_id = $this->target_content_id = null; + return; + } + + $this->target_channel_id = $id; + break; + case 'article': + if($id && strpos($id,'-')!==false) + { + list($this->target_channel_id, $this->target_content_id) = explode('-',$id); + if(!$this->target_content_id) + { + $this->target = $this->target_channel_id = $this->target_content_id = null; + return; + } + } + else + { + $this->target = $this->target_channel_id = $this->target_content_id = null; + return; + } + break; + } + + if($this->target_channel_id) $this->param->target_channel_id = $this->target_channel_id; + if($this->target_content_id) $this->param->target_content_id = $this->target_content_id; + } + + /** + * @brief xml for Syndication Server + **/ + function getXML() + { + if(!$this->checkRegisteredFunctions()) return ''; + + switch($this->target) + { + // in site + case 'site': + // get Site info + $oSite = $this->callFunction('site_info'); + if(!$oSite) return ''; + + $list_xml = ''; + + if(in_array($this->param->type,array('article','deleted','channel'))) + { + $list = $this->callFunction($this->param->type . '_list'); + if(!$list) $list = array(); + + $obj = $this->callFunction($this->param->type . '_next_page'); + if($obj) $oSite->setNextPage($obj); + + foreach($list as $oObject) + { + $list_xml .= $oObject->wrapEntry($oObject->__toString()); + } + + $xml = $oSite->__toString(); + $xml = $oSite->wrapFeed($xml . $list_xml); + } + else + { + $xml = $oSite->__toString(); + $xml = $oSite->wrapEntry($xml . $list_xml, true); + } + + break; + + // in channel + case 'channel': + // get Channel info + $oChannelList = $this->callFunction('channel_list'); + if(!is_array($oChannelList) || count($oChannelList)==0) return ''; + $oChannel = $oChannelList[0]; + + $list_xml = ''; + + if($this->target_channel_id && in_array($this->param->type,array('article','deleted'))) + { + $list = $this->callFunction($this->param->type . '_list'); + + if(is_array($list) && count($list)) + { + $obj = $this->callFunction($this->param->type . '_next_page'); + if($obj) $oChannel->setNextPage($obj); + + foreach($list as $oObject) + { + $list_xml .= $oObject->wrapEntry($oObject->__toString()); + } + } + + $xml = $oChannel->__toString(); + $xml = $oChannel->wrapFeed($xml . $list_xml); + } + else + { + $xml = $oChannel->__toString(); + $xml = $oChannel->wrapEntry($xml . $list_xml, true); + } + + break; + + // article info + case 'article': + + if(in_array($this->param->type,array('article','deleted'))) + { + $list = $this->callFunction($this->param->type . '_list'); + } + + if(!is_array($list) || count($list)==0) return ''; + + $oObject = $list[0]; + $xml = $oObject->__toString(); + + $xml = $oObject->wrapEntry($xml, true); + + break; + } + + if(!$GLOBALS['syndi_from_encoding']) $GLOBALS['syndi_from_encoding'] = 'utf-8'; + if($xml && strtolower($GLOBALS['syndi_from_encoding']) != 'utf-8' && function_exists('iconv')) + { + $xml = iconv($GLOBALS['syndi_from_encoding'], 'utf-8//IGNORE', $xml); + } + + return $xml; + } + + /** + * @brief Tag URI + **/ + function getTag($type, $channel_id=null, $article_id=null) + { + $tag = sprintf('tag:%s,%s:%s' + ,$GLOBALS['syndi_tag_domain'] + ,$GLOBALS['syndi_tag_year'] + ,$type); + + if($type=='channel' && $channel_id) + { + $tag .= ':' . $channel_id; + } + else if($type=='article' && $channel_id && $article_id) + { + $tag .= ':' .$channel_id .'-' . $article_id; + } + + return $tag; + } + + /** + * @brief Timestamp 로 YYYYMMDDHHIISS 변환 + **/ + function getDate($timestamp) + { + $time = strtotime($timestamp); + if($time == -1) $time = SyndicationHandler::ztime(str_replace(array('-','T',':'),'',$timestamp)); + + return date('YmdHis', $time); + } + + /** + * @brief YYYYMMDDHHIISS에서 Timestamp로 변환 + **/ + function getTimestamp($date) + { + $time = mktime(substr($date,8,2),substr($date,10,2),substr($date,12,2),substr($date,4,2),substr($date,6,2),substr($date,0,4)); + $timestamp = date("Y-m-d\\TH:i:s", $time). $GLOBALS['syndi_time_zone']; + return $timestamp; + } + + function ztime($str) + { + if(!$str) return; + $hour = (int)substr($str,8,2); + $min = (int)substr($str,10,2); + $sec = (int)substr($str,12,2); + $year = (int)substr($str,0,4); + $month = (int)substr($str,4,2); + $day = (int)substr($str,6,2); + if(strlen($str) <= 8) + { + $gap = 0; + } + else + { + $gap = SyndicationHandler::zgap(); + } + + return mktime($hour, $min, $sec, $month?$month:1, $day?$day:1, $year)+$gap; + } + + function zgap() + { + $time_zone = $GLOBALS['syndi_time_zone']; + if($time_zone < 0) $to = -1; else $to = 1; + $t_hour = substr($time_zone, 1, 2) * $to; + $t_min = substr($time_zone, 3, 2) * $to; + + $server_time_zone = date("O"); + if($server_time_zone < 0) $so = -1; else $so = 1; + $c_hour = substr($server_time_zone, 1, 2) * $so; + $c_min = substr($server_time_zone, 3, 2) * $so; + + $g_min = $t_min - $c_min; + $g_hour = $t_hour - $c_hour; + + $gap = $g_min*60 + $g_hour*60*60; + + return $gap; + } + + function error($msg) + { + echo $msg; + exit; + } +} + +?> diff --git a/bbs/syndi/libs/SyndicationObject.class.php b/bbs/syndi/libs/SyndicationObject.class.php new file mode 100644 index 000000000..5c43aad98 --- /dev/null +++ b/bbs/syndi/libs/SyndicationObject.class.php @@ -0,0 +1,104 @@ +\n"; + $str .= $this->get('name'); + $str .= $this->get('email'); + $str .= $this->get('url'); + $str .= "\n"; + + return $str; + } + + $value = $this->{$node_name}; + if(!$value) return ''; + + if(strpos($node_name,'link_')!==false) + { + $type = str_replace('_','-',substr($node_name, strlen('link_'))); + return "\n"; + } + + if(in_array($node_name,array('published','deleted','updated'))) + { + $value = $this->_getTime($value); + } + + return sprintf("<%s>%s\n", $node_name, htmlspecialchars($value) ,$node_name); + } + + function _getTime($time) + { + return SyndicationHandler::getTimestamp($time); + } + + function wrapFeed($str) + { + $return = ''; + $return .= "\n"; + $return .= ''; + $return .= "\n"; + $return .= $str; + $return .= ""; + + return $return; + } + + function wrapEntry($str, $xml_info=false) + { + if($xml_info) + { + $return = ''; + $return .= "\n"; + $return .= ''; + $return .= "\n"; + } + else + { + $return .= "\n"; + } + + $return .= $str; + $return .= "\n"; + + return $return; + } +} + +?> diff --git a/bbs/syndi/libs/SyndicationPing.class.php b/bbs/syndi/libs/SyndicationPing.class.php new file mode 100644 index 000000000..484ccdcf9 --- /dev/null +++ b/bbs/syndi/libs/SyndicationPing.class.php @@ -0,0 +1,105 @@ +id = $id; + } + + function setType($type) + { + $this->type = $type; + } + + function setStartTime($start_time) + { + if($start_time) + { + $this->start_time = $this->_convertTime($start_time); + } + } + + function setEndTime($end_time) + { + if($end_time) + { + $this->end_time = $this->_convertTime($end_time); + } + } + + function _convertTime($time) + { + return str_replace('+','%2b',$time); + } + + function setMaxEntry($max_entry) + { + if($max_entry > 0 && $max_entry <= 10000) + { + $this->max_entry = $max_entry; + } + } + + function setPage($page) + { + if($page > 0 && $page <= 10000) + { + $this->page = $page; + } + } + + function getBody() + { + $str = $GLOBALS['syndi_echo_url']; + $str .= '?id=' . $this->id; + $str .= '&type=' . $this->type; + if($this->start_time && $this->end_time) + { + $str .= '&start_time=' . $this->start_time; + $str .= '&end_time=' . $this->end_time; + } + if($this->max_entry) $str .= '&max_entry=' . $this->max_entry; + if($this->page) $str .= '&page=' . $this->page; + + return 'link='.urlencode($str); + } + + function request() + { + $body = $this->getBody(); + if(!$body) return false; + + $header = "POST /ping/ HTTP/1.0\r\n". + "User-Agent: request\r\n". + "Host: " . $this->ping_host . "\r\n". + "Content-Type: application/x-www-form-urlencoded\r\n". + "Content-Length: ". strlen($body) ."\r\n". + "\r\n". + $body; + + $fp = @fsockopen($this->ping_host, '80', $errno, $errstr, 5); + if(!$fp) return false; + + fputs($fp, $header); + fclose($fp); + + return true; + } +} +?> diff --git a/bbs/syndi/libs/SyndicationSite.class.php b/bbs/syndi/libs/SyndicationSite.class.php new file mode 100644 index 000000000..26ee64dbe --- /dev/null +++ b/bbs/syndi/libs/SyndicationSite.class.php @@ -0,0 +1,74 @@ +id = $id; + } + + /** + * @brief Title of Site + **/ + function setTitle($title) + { + $this->title = $title; + } + + /** + * @brief Syndication Ping Url + **/ + function setLinkSelf($link_self) + { + $this->link_self = $link_self; + } + + /** + * @brief 접근 Url + **/ + function setLinkAlternative($link_alternative) + { + $this->link_alternative = $link_alternative; + } + + /** + * @brief 다음 페이지 Url + **/ + function setNextPage($obj) + { + if(!$obj) return; + + if($obj['page']>0) $this->link_next_in_thread = $this->link_self . '&page='. $obj['page']; + if($obj['channel_id']) $this->link_next_in_thread .= '&channel_id='. $obj['channel_id']; + } + + /** + * @brief update time + * 'YYYYMMDDHHIISS' type + **/ + function setUpdated($updated) + { + $this->updated = $updated; + } + + function __toString() + { + $str = ''; + foreach($this->node as $node){ + $str .= $this->get($node); + } + + return $str; + } +} +?> \ No newline at end of file diff --git a/bbs/syndi/libs/SyndicationStatus.class.php b/bbs/syndi/libs/SyndicationStatus.class.php new file mode 100644 index 000000000..977e194a0 --- /dev/null +++ b/bbs/syndi/libs/SyndicationStatus.class.php @@ -0,0 +1,77 @@ +site = $site; + } + + function request() + { + if(!$this->site) return false; + + $header = "GET /status/?site=".$this->site." HTTP/1.0\r\n". + "Host: " . $this->status_host . "\r\n\r\n"; + + $fp = @fsockopen($this->status_host, '80', $errno, $errstr); + if(!$fp) return false; + + $output = ''; + + fputs($fp, $header); + while(!feof($fp)){ + $output .= fgets($fp, 1024); + } + fclose($fp); + + $output = substr($output, strpos($output, "\r\n\r\n")+4); + return $this->_parse($output); + } + + function _parse($data) + { + preg_match_all('@\<([a-z_0-9=\" ]+)\>([^\<]+)\array()); + + for($i=0,$c=count($matches[0]);$i<$c;$i++){ + if(strpos($matches[1][$i], 'date="')!==false){ + $date = substr($matches[1][$i],14,8); + $output['article'][$date] = $matches[2][$i]; + }else{ + $output[$matches[1][$i]] = $matches[2][$i]; + } + } + + return $output; + } +} + +/* +$oStatus = new SyndicationStatus; +$oStatus->setSite('domain.com'); +$output = $oStatus->request(); + +$output data fields +error : 0이 아닌 경우 에러 +message : 에러 메세지 +site_url : site url +site_name : site name +first_update : Syndication 서버에 처음 등록된 시간 +last_update : Syndication 서버에 최근 갱신 시간 +status : site 상태 +visit_ok_count : ping 연속 성공 횟수 +visit_fail_count : ping 실패 횟수 +*/ +?> diff --git a/bbs/syndi/syndi_echo.php b/bbs/syndi/syndi_echo.php new file mode 100644 index 000000000..5c103f128 --- /dev/null +++ b/bbs/syndi/syndi_echo.php @@ -0,0 +1,37 @@ += 0) +{ + date_default_timezone_set(@date_default_timezone_get()); +} + +error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT); + + +$syndi_path = dirname(__FILE__); + +// include class +include $syndi_path . '/libs/SyndicationHandler.class.php'; +include $syndi_path . '/libs/SyndicationObject.class.php'; +include $syndi_path . '/libs/SyndicationSite.class.php'; +include $syndi_path . '/libs/SyndicationChannel.class.php'; +include $syndi_path . '/libs/SyndicationArticle.class.php'; +include $syndi_path . '/libs/SyndicationDeleted.class.php'; + +// config & custom func for site +include $syndi_path . '/config/site.config.php'; +include $syndi_path . '/func/site.func.php'; + +$oSyndicationHandler = &SyndicationHandler::getInstance(); +$oSyndicationHandler->setArgument(); + +echo $oSyndicationHandler->getXML(); +?> diff --git a/bbs/write_update.php b/bbs/write_update.php index 330bde8d1..8e7d12270 100644 --- a/bbs/write_update.php +++ b/bbs/write_update.php @@ -459,6 +459,8 @@ if ($w == '' || $w == 'r') { } } +// syndication ping +include G4_BBS_PATH.'/syndi/include/include.bbs.write_update.php'; //------------------------------------------------------------------------------ // 가변 파일 업로드 @@ -610,5 +612,5 @@ delete_cache_latest($bo_table); if ($file_upload_msg) alert($file_upload_msg, G4_HTTPS_BBS_URL.'/board.php?bo_table='.$bo_table.'&wr_id='.$wr_id.'&page='.$page.$qstr); else - goto_url(G4_HTTPS_BBS_URL.'/board.php?bo_table='.$bo_table.'&wr_id='.$wr_id.'&page='.$page.$qstr); + goto_url(G4_HTTPS_BBS_URL.'/board.php?bo_table='.$bo_table.'&wr_id='.$wr_id.$qstr); ?> diff --git a/install/gnuboard4s.sql b/install/gnuboard4s.sql index e517dd1ee..74dac5354 100644 --- a/install/gnuboard4s.sql +++ b/install/gnuboard4s.sql @@ -734,4 +734,20 @@ CREATE TABLE IF NOT EXISTS `g4s_uniqid` ( PRIMARY KEY (`uq_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; +-- -------------------------------------------------------- + +-- +-- Table structure for table `g4s_syndi_log` +-- + +DROP TABLE IF EXISTS `g4s_syndi_log`; +CREATE TABLE IF NOT EXISTS `g4s_syndi_log` ( + `content_id` int(11) NOT NULL, + `bbs_id` varchar(50) NOT NULL, + `title` text NOT NULL, + `link_alternative` varchar(250) NOT NULL, + `delete_date` varchar(14) NOT NULL, + PRIMARY KEY (`content_id`,`bbs_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + -- -------------------------------------------------------- \ No newline at end of file diff --git a/install/install_db.php b/install/install_db.php index f9a6ad89d..269822395 100644 --- a/install/install_db.php +++ b/install/install_db.php @@ -197,6 +197,7 @@ fwrite($f, "\$g4['scrap_table'] = G4_TABLE_PREFIX.'scrap'; // 게시글 스크 fwrite($f, "\$g4['visit_table'] = G4_TABLE_PREFIX.'visit'; // 방문자 테이블\n"); fwrite($f, "\$g4['visit_sum_table'] = G4_TABLE_PREFIX.'visit_sum'; // 방문자 합계 테이블\n"); fwrite($f, "\$g4['uniqid_table'] = G4_TABLE_PREFIX.'uniqid'; // 유니크한 값을 만드는 테이블\n"); +fwrite($f, "\$g4['syndi_log_table'] = G4_TABLE_PREFIX.'syndi_log'; // 네이버 신디케이션 컨텐츠 삭제 로그 테이블\n"); fwrite($f, "?>"); fclose($f); diff --git a/lib/common.lib.php b/lib/common.lib.php index 3d92ea8c4..d7e16f719 100644 --- a/lib/common.lib.php +++ b/lib/common.lib.php @@ -1613,8 +1613,9 @@ function convert_charset($from_charset, $to_charset, $str) // mysql_real_escape_string 의 alias 기능을 한다. function escape_trim($field) { - if ($field) - return mysql_real_escape_string(trim($field)); + if ($field) { + return mysql_real_escape_string(@trim($field)); + } }