You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1083 lines
44 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. <?php
  2. defined('BASEPATH') OR exit('No direct script access allowed');
  3. class Board extends WB_Controller {
  4. function __construct()
  5. {
  6. parent::__construct();
  7. $this->load->library('boardlib');
  8. }
  9. /**
  10. * INDEX 페이지는 접근금지
  11. */
  12. function index()
  13. {
  14. alert(langs( 'board/msg/invalid_access' ));
  15. }
  16. /**
  17. * 게시판 보기 페이지
  18. * @param $brd_key
  19. * @param $post_idx
  20. */
  21. public function view($brd_key, $post_idx)
  22. {
  23. $this->board_common($brd_key, 'read');
  24. $this->data['view'] = $this->boardlib->get_post($brd_key, $post_idx, FALSE);
  25. if(! in_array( $this->data['view']['post_status'], array("Y","B")))
  26. {
  27. alert(langs('게시판/msg/invalid_post'));
  28. exit;
  29. }
  30. // 비밀글일 경우 처리
  31. if( $this->data['view']['post_secret'] == 'Y' )
  32. {
  33. $is_auth = FALSE;
  34. if( !empty($this->data['view']['reg_user']) && $this->data['view']['reg_user'] == $this->member->info('idx') )
  35. {
  36. $is_auth = TRUE;
  37. }
  38. if( $this->data['board']['auth']['admin'] ) {
  39. $is_auth = TRUE;
  40. }
  41. // 해당 글이 답글일 경우
  42. if( strlen($this->data['view']['post_reply']) > 0 && $this->member->is_login())
  43. {
  44. // 원글중에 작성자가 있는경우 글을 볼 권한이 있다!
  45. $tmp = $this->db->where('post_num', $this->data['view']['post_num'])->where('brd_key', $brd_key)->get('board_post')->result_array();
  46. foreach($tmp as $t)
  47. {
  48. if( $t['reg_user'] && $t['reg_user'] == $this->member->info('idx') )
  49. {
  50. $is_auth = TRUE;
  51. break;
  52. }
  53. }
  54. }
  55. if(! $is_auth)
  56. {
  57. if( ! $this->session->userdata('post_password_'.$post_idx) )
  58. {
  59. redirect(base_url("board/{$brd_key}/password/{$post_idx}?w=s&reurl=".current_full_url()));
  60. }
  61. }
  62. }
  63. // 게시판 조회수 상승
  64. if( ! $this->session->userdata('post_hit_'.$post_idx) OR (int)$this->session->userdata('post_hit_'.$post_idx) + 60*60*24 < time() )
  65. {
  66. $this->db->where('post_idx', $post_idx)->set('post_hit', 'post_hit+1', FALSE)->update('board_post');
  67. $this->data['view']['post_hit'] += 1;
  68. $this->session->set_userdata('post_hit_'.$post_idx, time());
  69. }
  70. // 포인트 관련 프로세스
  71. $this->point_process('brd_point_read', 'POST_READ', '게시글 읽기', $post_idx, ($this->data['view']['reg_user'] == $this->member->info('idx')) );
  72. // 링크 추가
  73. $this->data['board']['link']['reply'] = base_url("board/{$brd_key}/write/?post_parent={$post_idx}");
  74. $this->data['board']['link']['modify'] = base_url("board/{$brd_key}/write/{$post_idx}");
  75. $this->data['board']['link']['delete'] = base_url("board/{$brd_key}/delete/{$post_idx}");
  76. // 메타태그 설정
  77. $this->site->meta_title = $this->data['view']['post_title'] . ' - ' . $this->data['board']['brd_title']; // 이 페이지의 타이틀
  78. $this->site->meta_description = cut_str(get_summary($this->data['view']['post_content'],FALSE),80); // 이 페이지의 요약 설명
  79. $this->site->meta_keywords = $this->data['view']['post_keywords']; // 이 페이지에서 추가할 키워드 메타 태그
  80. $this->site->meta_image = $this->data['view']['post_thumbnail']; // 이 페이지에서 표시할 대표이미지
  81. // 댓글 입력폼
  82. $write_skin_path = DIR_SKIN . "/board/comment/" . $this->data['board']['brd_skin_c'] . "/c_write";
  83. $comment_hidden = array("reurl"=>current_full_url(),"cmt_idx"=>"","cmt_parent"=>"");
  84. $comment_action_url = base_url( "board/{$brd_key}/comment/{$post_idx}", SSL_VERFIY ? 'https':'http' );
  85. $tmp['comment_view'] = array();
  86. $tmp['comment_form_open'] = form_open($comment_action_url,array("id"=>"form-board-comment","data-form"=>"board-comment"), $comment_hidden);
  87. $tmp['comment_form_close'] = form_close();
  88. $this->data['comment_write'] = $this->data['board']['brd_use_comment'] == 'Y' && $this->data['board']['auth']['comment'] ? $this->load->view($write_skin_path, $tmp, TRUE) : NULL;
  89. // 댓글 목록
  90. $list_skin_path = DIR_SKIN . "/board/comment/" . $this->data['board']['brd_skin_c'] . "/c_list";
  91. if( $this->data['board']['brd_use_comment'] == 'Y' )
  92. {
  93. $mem_userid = ($this->member->is_login()) ? $this->member->is_login() : '';
  94. $tmp2['comment_list'] = $this->boardlib->comment_list($brd_key, $post_idx, $this->data['board']['auth']['admin'], $mem_userid);
  95. // 각 댓글마다 대댓글 폼을 만든다.
  96. foreach($tmp2['comment_list']['list'] as &$row)
  97. {
  98. unset($tmp);
  99. $row['comment_form'] = "";
  100. if(strlen($row['cmt_reply']) < 5)
  101. {
  102. $comment_hidden = array("reurl"=>current_full_url(),"cmt_idx"=>"","cmt_parent"=>$row['cmt_idx']);
  103. $comment_action_url = base_url( "board/{$brd_key}/comment/{$post_idx}", SSL_VERFIY ? 'https':'http' );
  104. $tmp['comment_view'] = array();
  105. $tmp['comment_form_open'] = form_open($comment_action_url,array("data-form"=>"board-comment"), $comment_hidden);
  106. $tmp['comment_form_close'] = form_close();
  107. $row['comment_form'] = $this->data['board']['brd_use_comment'] == 'Y' && $this->data['board']['auth']['comment'] ? $this->load->view($write_skin_path, $tmp, TRUE) : NULL;
  108. }
  109. }
  110. }
  111. $tmp2['board'] = $this->data['board'];
  112. $this->data['comment_list'] = $this->data['board']['brd_use_comment'] == 'Y' ? $this->load->view($list_skin_path, $tmp2, TRUE) : NULL;
  113. $this->view = "view";
  114. $this->skin_type = "board/view";
  115. $this->skin = $this->data['board']['brd_skin_v'];
  116. }
  117. /**
  118. * 게시판 목록
  119. * @param $brd_key
  120. */
  121. public function lists($brd_key)
  122. {
  123. $this->board_common($brd_key, 'list');
  124. // 메타태그 설정
  125. $this->site->meta_title = $this->data['board']['brd_title'] . ' - ' . $this->data['page'] . '페이지'; // 이 페이지의 타이틀
  126. $this->site->meta_description = $this->data['board']['brd_description']; // 이 페이지의 요약 설명
  127. $this->site->meta_keywords = $this->data['board']['brd_keywords']; // 이 페이지에서 추가할 키워드 메타 태그
  128. $this->site->meta_image = ""; // 이 페이지에서 표시할 대표이미지
  129. // 레이아웃 & 뷰파일 설정
  130. $this->view = "list";
  131. $this->skin_type = "board/list";
  132. $this->skin = $this->data['board']['brd_skin_l'];
  133. }
  134. /**
  135. * 코멘트 등록/수정 처리
  136. * @param $brd_key
  137. * @param $post_idx
  138. * @param string $cmt_idx
  139. */
  140. public function comment($brd_key, $post_idx)
  141. {
  142. $this->load->library('form_validation');
  143. $this->form_validation->set_rules('cmt_content', langs('게시판/comment/form_content'), 'trim|required');
  144. if( empty($brd_key) OR empty($post_idx) )
  145. {
  146. alert(langs('게시판/msg/invalid_access'));
  147. exit;
  148. }
  149. $this->board_common($brd_key,'comment');
  150. $data['brd_key'] = $brd_key;
  151. $data['post_idx'] = $post_idx;
  152. $data['cmt_idx'] = $this->input->post('cmt_idx', TRUE);
  153. $data['cmt_parent'] = $this->input->post('cmt_parent', TRUE, 0);
  154. $data['cmt_content'] = $this->input->post('cmt_content', FALSE);
  155. $data['mem_userid'] = ( $this->member->is_login() ) ? $this->member->info('userid') : '';
  156. $data['mem_password'] = ( $this->member->is_login() ) ? $this->member->info('password') : get_password_hash( $this->input->post('mem_password', FALSE) );
  157. $data['mem_nickname'] = ( $this->member->is_login() ) ? $this->member->info('nickname') : $this->input->post('mem_nickname');
  158. $data['cmt_modtime'] = date('Y-m-d H:i:s');
  159. $data['cmt_ip'] = ip2long( $this->input->ip_address() );
  160. $data['cmt_status'] = 'Y';
  161. $data['cmt_mobile'] = $this->site->viewmode == DEVICE_MOBILE ? 'Y' : 'N';
  162. $reurl = $this->input->post('reurl', TRUE, base_url("board/{$brd_key}/{$post_idx}") );
  163. // 값 유효성 체크
  164. if( empty($data['cmt_content']) )
  165. {
  166. alert(langs('게시판/comment/content_required'));
  167. exit;
  168. }
  169. if( empty($data['mem_nickname']) )
  170. {
  171. alert(langs('게시판/comment/nickname_required'));
  172. exit;
  173. }
  174. if( empty($data['mem_password']) )
  175. {
  176. alert(langs('게시판/comment/password_required'));
  177. exit;
  178. }
  179. // 신규 등록일경우
  180. if( empty($data['cmt_idx']) )
  181. {
  182. $data['cmt_regtime'] = date('Y-m-d H:i:s');
  183. if(! empty($data['cmt_parent']))
  184. {
  185. $parent = $this->db->where('cmt_idx', $data['cmt_parent'])->where_in('cmt_status', array('Y','B'))->where('post_idx', $data['post_idx'])->get('board_comment')->row_array();
  186. if(! $parent OR !isset($parent['cmt_idx']) OR ! $parent['cmt_idx']) {
  187. alert('답변할 댓글이 없습니다.\\n답변하는 동안 댓글이 삭제되었을 수 있습니다.');
  188. exit;
  189. }
  190. if($parent['post_idx'] != $data['post_idx']) {
  191. alert('댓글을 등록할 수 없습니다.\\n잘못된 방법으로 등록을 요청하였습니다.');
  192. exit;
  193. }
  194. if(strlen($parent['cmt_reply']) >= 5) {
  195. alert('더이상 답변을 달수 없습니다.\\n\\n답변은 5단계 까지만 가능합니다.');
  196. exit;
  197. }
  198. $reply_len = strlen($parent['cmt_reply']) + 1;
  199. $begin_reply_char = 'A';
  200. $end_reply_char = 'Z';
  201. $reply_number = +1;
  202. $this->db->select("MAX(SUBSTRING(cmt_reply, {$reply_len}, 1)) AS reply")->from('board_comment')->where('cmt_num', $parent['cmt_num'])->where('post_idx', $data['post_idx'])->where("SUBSTRING(cmt_reply, {$reply_len}, 1) <>", '');
  203. if($parent['cmt_reply']) $this->db->like('cmt_reply', $parent['cmt_reply'],'after');
  204. $row = $this->db->get()->row_array();
  205. $reply_char ="";
  206. if(!$row['reply']) $reply_char = $begin_reply_char;
  207. else if ($row['reply'] == $end_reply_char) {
  208. alert('더이상 답변을 달수 없습니다.\\n\\n답변은 26개까지만 가능합니다.');
  209. exit;
  210. }
  211. else $reply_char = chr(ord($row['reply']) + $reply_number);
  212. $data['cmt_reply'] = $parent['cmt_reply'] . $reply_char;
  213. $data['cmt_num'] = $parent['cmt_num'];
  214. }
  215. else
  216. {
  217. $tmp = (int)$this->db->select_max('cmt_num','max')->from('board_comment')->where('post_idx',$data['post_idx'])->get()->row(0)->max;
  218. $data['cmt_reply'] = "";
  219. $data['cmt_num'] = $tmp+1;
  220. }
  221. if( $this->db->insert('board_comment', $data) )
  222. {
  223. // 대댓글을 위한 정보입력
  224. $cmt_idx = $this->db->insert_id();
  225. // 포인트 입력처리
  226. $this->point_process('brd_point_comment', "CMT_WRITE", "댓글 등록", $cmt_idx, FALSE);
  227. $this->board_model->update_post_comment_count($brd_key, $post_idx);
  228. alert('댓글 작성이 완료되었습니다.', $reurl);
  229. }
  230. }
  231. // 수정권한이라면
  232. else
  233. {
  234. // 기존 댓글 정보를 가져온다
  235. $comment = $this->db->where("cmt_idx", $data['cmt_idx'])->where('brd_key', $brd_key)->where('post_idx', $post_idx)->get('board_comment')->row_array();
  236. if( ! $comment || ! isset($comment['cmt_idx']) || $comment['cmt_idx'] != $data['cmt_idx'] )
  237. {
  238. alert(langs('게시판/msg/invalid_comment'));
  239. exit;
  240. }
  241. if(! $this->data['board']['auth']['admin'] )
  242. {
  243. // 기존 댓글과 수정권한이 있는지 확인한다.
  244. if( $comment['mem_userid'] )
  245. {
  246. if( $this->member->is_login() )
  247. {
  248. if( $this->member->info('userid') != $comment['mem_userid'] )
  249. {
  250. alert(langs('게시판/msg/comment_modify_unauthorize'));
  251. exit;
  252. }
  253. }
  254. else
  255. {
  256. alert_login();
  257. exit;
  258. }
  259. }
  260. else
  261. {
  262. if( $data['mem_password'] != $comment['mem_password'] )
  263. {
  264. alert(langs('게시판/msg/invalid_password'));
  265. exit;
  266. }
  267. }
  268. }
  269. // 수정일 경우는 바뀌어선 안되는 정보들은 unset
  270. unset($data['brd_key'], $data['post_idx']);
  271. $this->db->where('brd_key', $brd_key);
  272. $this->db->where('post_idx', $post_idx);
  273. $this->db->where('cmt_idx', $data['cmt_idx']);
  274. if( $this->db->update('board_comment', $data) )
  275. {
  276. $this->board_model->update_post_comment_count($brd_key, $post_idx);
  277. alert_close(langs('게시판/msg/comment_modify_success'), TRUE);
  278. exit;
  279. }
  280. }
  281. alert(langs('게시판/msg/comment_failed'));
  282. exit;
  283. }
  284. /**
  285. * 코멘트 수정/삭제 권한 확인
  286. * @param $comment
  287. * @return bool
  288. */
  289. public function _check_comment_modify($comment)
  290. {
  291. if( $this->data['board']['auth']['admin'] ) return TRUE;
  292. // 댓글 수정/삭제 권한 확인
  293. if( $comment['mem_userid'] && ! $this->member->is_login() )
  294. {
  295. return langs('게시판/msg/comment_modify_unauthorize');
  296. }
  297. else if ( $comment['mem_userid'] && $this->member->is_login() && $this->member->info('userid') != $comment['mem_userid'])
  298. {
  299. return langs('게시판/msg/comment_modify_unauthorize');
  300. }
  301. return TRUE;
  302. }
  303. /**
  304. * 코멘트 수정
  305. * @param string $cmt_idx
  306. */
  307. public function comment_modify($cmt_idx="")
  308. {
  309. if( ! $comment = $this->db->where('cmt_idx', $cmt_idx)->where('cmt_status', 'Y')->get('board_comment')->row_array() )
  310. {
  311. alert_close(langs('게시판/msg/invalid_comment'));
  312. exit;
  313. }
  314. $this->board_common($comment['brd_key']);
  315. if( ($result = $this->_check_comment_modify($comment)) !== TRUE )
  316. {
  317. alert_close($result);
  318. exit;
  319. }
  320. $this->site->meta_title = "댓글 수정";
  321. $hidden=array("mem_nickname"=>$comment['mem_nickname'],"cmt_idx"=>$comment['cmt_idx'],"cmt_parent"=>$comment['cmt_parent']);
  322. $action_url = base_url('board/'.$comment['brd_key'].'/comment/'.$comment['post_idx'].'/'.$cmt_idx, SSL_VERFIY ? 'https':'http');
  323. $this->data['comment_form_open'] = form_open($action_url, array("id"=>"form-board-comment","data-form"=>"board-comment"), $hidden);
  324. $this->data['comment_form_close'] = form_close();
  325. $this->data['comment_view'] = $comment;
  326. $this->data['is_reply'] = FALSE;
  327. $this->theme_file = "popup";
  328. $this->skin_type = "board/comment";
  329. $this->skin = $this->data['board']['brd_skin_c'];
  330. $this->view = "c_write";
  331. }
  332. /**
  333. * 댓글 삭제
  334. * @param $brd_key
  335. * @param $post_idx
  336. * @param $cmt_idx
  337. */
  338. public function comment_delete($brd_key, $post_idx, $cmt_idx)
  339. {
  340. $this->board_common($brd_key);
  341. if( ! $comment = $this->db->where('cmt_idx', $cmt_idx)->where('cmt_status', 'Y')->get('board_comment')->row_array() )
  342. {
  343. alert(langs('게시판/msg/invalid_comment'));
  344. exit;
  345. }
  346. if( ! $this->data['board']['auth']['admin'] )
  347. {
  348. if( ($result = $this->_check_comment_modify($comment)) !== TRUE )
  349. {
  350. alert($result);
  351. exit;
  352. }
  353. if( empty($comment['mem_userid']) )
  354. {
  355. alert(langs('게시판/msg/cannot_delete_guest_comment'));
  356. exit;
  357. }
  358. }
  359. // 원본 가져오기
  360. $original = $this->db->where('cmt_idx', $cmt_idx)->get('board_comment')->row_array();
  361. if(!$original OR !isset($original['cmt_idx']))
  362. alert('삭제할 원본 댓글이 없습니다.\\ 이미 삭제되엇거나 존재하지 않는 댓글입니다.');
  363. // 이 댓글의 하위 댓글이 있는지 확인
  364. $len = strlen($original['cmt_reply']);
  365. if ($len < 0) $len = 0;
  366. $comment_reply = substr($original['cmt_reply'], 0, $len);
  367. $cnt =
  368. $this->db
  369. ->select('COUNT(*) AS cnt')
  370. ->from('board_comment')
  371. ->like('cmt_reply', $comment_reply,'after')
  372. ->where('cmt_idx <>', $cmt_idx)
  373. ->where('cmt_num', $original['cmt_num'])
  374. ->where('post_idx', $original['post_idx'])
  375. ->where('cmt_status', 'Y')
  376. ->where('cmt_parent', $cmt_idx)
  377. ->get()->row(0)->cnt;
  378. if($cnt > 0)
  379. alert('삭제하려는 댓글에 답변이 달려있어 삭제할 수 없습니다.');
  380. if( $this->db->where('brd_key', $brd_key)->where('post_idx', $post_idx)->where('cmt_idx', $cmt_idx)->set('cmt_status', 'N')->update('board_comment') )
  381. {
  382. $this->board_model->update_post_comment_count($brd_key, $post_idx);
  383. // 댓글등록으로 증가한 포인트가 있다면 다시 감소
  384. $this->point_cancel("CMT_WRITE",$cmt_idx, "댓글삭제");
  385. alert(langs('게시판/msg/comment_delete_success'));
  386. exit;
  387. }
  388. }
  389. /**********************************************************
  390. *
  391. * 게시판 암호 확인 페이지
  392. * @param string $brd_key
  393. * @param string $post_idx
  394. *
  395. *********************************************************/
  396. function password($brd_key="",$post_idx="")
  397. {
  398. $this->board_common($brd_key);
  399. // 폼검증 라이브러리 로드
  400. $this->load->library("form_validation");
  401. // 폼검증 규칙 설정
  402. $this->form_validation->set_rules("password", langs('게시판/form/password'), "trim|required|min_length[4]|max_length[16]");
  403. if( $this->form_validation->run() == FALSE )
  404. {
  405. $hidden = array("reurl"=>$this->input->get('reurl', TRUE));
  406. $action_url = base_url("board/{$brd_key}/password/{$post_idx}", SSL_VERFIY ? 'https':'http');
  407. $this->data['form_open'] = form_open($action_url,array("id"=>"form-post-password","data-form"=>"post-password-form"), $hidden);
  408. $this->data['form_close']= form_close();
  409. $this->view = "password";
  410. $this->skin_type = "board/view";
  411. $this->skin = $this->data['board']['brd_skin_v'];
  412. }
  413. else
  414. {
  415. $reurl = $this->input->post("reurl", TRUE, base_url("board/{$brd_key}/{$post_idx}") );
  416. $password = $this->input->post("password", TRUE);
  417. $post = $this->board_model->get_post($brd_key, $post_idx);
  418. if( get_password_hash($password) == $post['mem_password'] )
  419. {
  420. $this->session->set_userdata('post_password_'.$post_idx, TRUE);
  421. redirect($reurl);
  422. exit;
  423. }
  424. else
  425. {
  426. alert( langs('게시판/msg/invalid_password') );
  427. exit;
  428. }
  429. }
  430. }
  431. /**
  432. * 수정이나 삭제 권한이 있나 확인한다.
  433. * @param $brd_key
  434. * @param $post_idx
  435. */
  436. public function _modify_auth($brd_key, $post_idx="")
  437. {
  438. if(empty($post_idx)) return;
  439. $post = $this->board_model->get_post($brd_key, $post_idx, FALSE);
  440. // 관리자가 아니라면
  441. if( ! $this->data['board']['auth']['admin'] )
  442. {
  443. // 회원이 작성한 글이라면
  444. if( ! empty($post['mem_userid']) )
  445. {
  446. if( ! $this->member->is_login() )
  447. {
  448. alert_login( langs('게시판/msg/modify_require_login') );
  449. exit;
  450. }
  451. else if ( $post['mem_userid'] != $this->member->info('userid') )
  452. {
  453. alert(langs('게시판/msg/modify_unauthorize'));
  454. exit;
  455. }
  456. }
  457. else
  458. {
  459. if( ! $this->session->userdata('post_password_'.$post_idx) )
  460. {
  461. redirect(base_url("board/{$brd_key}/password/{$post_idx}?reurl=".current_full_url()));
  462. }
  463. }
  464. }
  465. }
  466. /**
  467. * 글쓰기 페이지
  468. * @param $brd_key
  469. * @param string $post_idx
  470. */
  471. public function write($brd_key, $post_idx="")
  472. {
  473. $this->load->library('form_validation');
  474. $this->board_common($brd_key, 'write');
  475. // 수정이라면 권한을 확인한다.
  476. $this->_modify_auth($brd_key, $post_idx);
  477. $this->form_validation->set_rules('post_title', langs('게시판/form/post_title') ,'required|trim');
  478. $this->form_validation->set_rules('post_content', langs('게시판/form/post_content'),'required|trim');
  479. if( ! $this->member->is_login() )
  480. {
  481. $this->form_validation->set_rules('mem_nickname', langs('게시판/form/mem_nickname') ,'required|trim');
  482. $this->form_validation->set_rules('mem_password', langs('게시판/form/password') ,'required|trim|min_length[4]|max_length[16]');
  483. }
  484. if( $this->form_validation->run() != FALSE)
  485. {
  486. $this->load->library('upload');
  487. if( ! $this->member->is_login() )
  488. {
  489. // 비회원이고 리캡쳐 설정이 되있을 경우 경우 구글 리캡챠확인
  490. if( $this->site->config('google_recaptcha_site_key') && $this->site->config('google_recaptcha_secret_key') )
  491. {
  492. $this->load->library('google_recaptcha');
  493. $response = $this->input->post('g-recaptcha-response', TRUE);
  494. if( empty($response) OR ! $this->google_recaptcha->check_response( $response ) )
  495. {
  496. alert('자동등록 방지 인증에 실패하였습니다.');
  497. exit;
  498. }
  499. }
  500. // 비회원일이고 수정일 경우 입력한 패스워드와 기존 패스워드 확인
  501. if( $post_idx )
  502. {
  503. $post = $this->board_model->get_post($brd_key, $post_idx, FALSE);
  504. if( get_password_hash( $this->input->post('mem_password', TRUE) ) != $post['mem_password'] )
  505. {
  506. alert('잘못된 비밀번호 입니다.');
  507. exit;
  508. }
  509. }
  510. }
  511. // 받아온 값을 정리한다.
  512. $data['post_title'] = $this->input->post('post_title', TRUE);
  513. $data['bca_idx'] = (int) $this->input->post('bca_idx', TRUE);
  514. $data['post_parent'] = $this->input->post('post_parent', TRUE, 0);
  515. $data['post_secret'] = $this->input->post('post_secret', TRUE, 'N') == 'Y' ? "Y":'N';
  516. $data['post_content'] = $this->input->post('post_content', FALSE);
  517. $data['brd_key'] = $brd_key;
  518. $data['upd_datetime'] = date('Y-m-d H:i:s');
  519. $data['post_html'] = $this->data['use_wysiwyg'] ? 'Y' : 'N';
  520. $data['post_notice'] = $this->input->post('post_notice', TRUE) == 'Y' ? 'Y' : 'N';
  521. $data['post_ip'] = ip2long( $this->input->ip_address() );
  522. $data['post_mobile'] = $this->site->viewmode == DEVICE_MOBILE ? 'Y' : 'N';
  523. $data['post_keywords'] = $this->input->post('post_keywords', TRUE);
  524. for($i=1; $i<=9; $i++)
  525. {
  526. $data['post_ext'.$i] = $this->input->post('post_ext'.$i, TRUE,'');
  527. }
  528. $parent = array();
  529. if(! empty( $data['post_parent'] ) )
  530. {
  531. $parent = $this->board_model->get_post($brd_key, $data['post_parent'], FALSE);
  532. }
  533. // 관리자가 아니라면 사용할수 없는 옵션 끄기
  534. if(! $this->data['board']['auth']['admin'] )
  535. {
  536. $data['post_notice'] = 'N';
  537. }
  538. if($this->input->post('post_annonymous', TRUE) == 'Y' OR $this->data['board']['brd_use_anonymous'] == 'A')
  539. {
  540. $data['mem_nickname'] = "익명";
  541. }
  542. // 로그인 상태에 따라 값을 수정
  543. if( $this->member->is_login() )
  544. {
  545. $data['upd_user'] = $this->member->info('idx');
  546. $data['post_nickname'] = $this->member->info('nickname');
  547. $data['post_password'] = $this->member->info('password');
  548. }
  549. else
  550. {
  551. $data['upd_user'] = 0;
  552. $data['post_nickname'] = $this->input->post('mem_nickname', TRUE);
  553. $data['post_password'] = get_password_hash( $this->input->post('mem_password', TRUE) );
  554. }
  555. // 게시판 설정을 이용해서 값 정리
  556. if( $this->data['board']['brd_use_secret'] == 'N' ) $data['post_secret'] = 'N';
  557. else if ( $this->data['board']['brd_use_secret'] == 'A' ) $data['post_secret'] = 'Y';
  558. // 답글인경우 원글이 비밀글이면 답글도 비밀글
  559. else if ( ! empty($data['post_parent']) && $parent['post_secret'] == 'Y' ) $data['post_secret'] = 'Y';
  560. // 파일 업로드가 있다면
  561. if( $this->data['use_attach'] )
  562. {
  563. if( isset($_FILES) && isset($_FILES['userfile']) && count($_FILES['userfile']) > 0 )
  564. {
  565. $dir_path = DIR_UPLOAD . "/board/{$brd_key}/".date('Y')."/".date('m');
  566. make_dir($dir_path,FALSE);
  567. $upload_config['upload_path'] = "./".$dir_path;
  568. $upload_config['file_ext_tolower'] = TRUE;
  569. $upload_config['allowed_types'] = FILE_UPLOAD_ALLOW;
  570. $upload_config['encrypt_name'] = TRUE;
  571. $this->load->library("upload", $upload_config);
  572. $this->data['upload_array'] = array();
  573. // FOR문으로 업로드하기 위해 돌리기
  574. $files = NULL;
  575. foreach ($_FILES['userfile'] as $key => $value) {
  576. foreach ($value as $noKey => $noValue) {
  577. $files[$noKey][$key] = $noValue;
  578. }
  579. }
  580. unset($_FILES);
  581. // FOR 문 돌면서 정리
  582. foreach ($files as $file) {
  583. $_FILES['userfile'] = $file;
  584. $this->upload->initialize($upload_config);
  585. if( ! isset($_FILES['userfile']['tmp_name']) OR ! $_FILES['userfile']['tmp_name']) continue;
  586. if (! $this->upload->do_upload('userfile') )
  587. {
  588. alert('파일 업로드에 실패하였습니다.\\n'.$this->upload->display_errors(' ',' '));
  589. exit;
  590. }
  591. else
  592. {
  593. $filedata = $this->upload->data();
  594. $this->data['upload_array'][] = array(
  595. "att_target_type" => 'BOARD',
  596. "att_origin" => $filedata['orig_name'],
  597. "att_filepath" => $dir_path . "/" . $filedata['file_name'],
  598. "att_downloads" => 0,
  599. "att_filesize" => $filedata['file_size'] * 1024,
  600. "att_width" => $filedata['image_width'] ? $filedata['image_width'] : 0,
  601. "att_height" => $filedata['image_height'] ? $filedata['image_height'] : 0,
  602. "att_ext" => $filedata['file_ext'],
  603. "att_is_image" => ($filedata['is_image'] == 1) ? 'Y' : 'N',
  604. "reg_user" => $this->member->is_login(),
  605. "reg_datetime" => date('Y-m-d H:i:s')
  606. );
  607. }
  608. }
  609. }
  610. }
  611. // 첨부파일 삭제가 있다면 삭제한다.
  612. $del_file = $this->input->post("del_file", TRUE);
  613. if( $del_file && count($del_file) > 0 )
  614. {
  615. foreach($del_file as $att_idx) {
  616. $this->board_model->attach_remove($att_idx);
  617. }
  618. }
  619. // 외부이미지를복사 꺼놓음..
  620. //$data['post_content'] = $this->board_model->copy_external_image($data['post_content'], $this->agent->agent_string());
  621. // 게시판설정에 관리자승인이 되어있다면 글입력시 자동 미승인상태로
  622. if( $this->data['board']['brd_use_assign'] == 'Y' && ! PAGE_ADMIN )
  623. {
  624. $data['post_assign'] = 'N';
  625. }
  626. // 수정이냐 신규냐에 따라 값 설정
  627. if( empty($post_idx) )
  628. {
  629. $data['post_status'] = 'Y';
  630. $data['post_count_comment'] = 0;
  631. $data['post_hit'] = 0;
  632. $data['reg_user'] = $data['upd_user'];
  633. $data['reg_datetime'] = $data['upd_datetime'];
  634. // 답글인경우
  635. if(! empty($data['post_parent']))
  636. {
  637. if( strlen($parent['post_reply']) >= 10 )
  638. {
  639. alert('더 이상 답변하실 수 없습니다.\\n답변은 10단계 까지만 가능합니다.');
  640. exit;
  641. }
  642. $reply_len = strlen($parent['post_reply']) + 1;
  643. $begin_reply_char = 'A';
  644. $end_reply_char = 'Z';
  645. $reply_number = +1;
  646. $reply_char = "";
  647. $this->db->select("MAX(SUBSTRING(post_reply, {$reply_len}, 1)) AS reply")->from('board_post')->where('post_num', $parent['post_num'])->where('brd_key', $brd_key)->where("SUBSTRING(post_reply, {$reply_len}, 1) <>", '');
  648. if($parent['post_reply']) $this->db->like('post_reply', $parent['post_reply'],'after');
  649. $row = $this->db->get()->row_array();
  650. if(! $row['reply']) {
  651. $reply_char = $begin_reply_char;
  652. }
  653. else if ($row['reply'] == $end_reply_char) {
  654. alert("더 이상 답변하실 수 없습니다.\\n답변은 26개 까지만 가능합니다.");
  655. exit;
  656. }
  657. else {
  658. $reply_char = chr(ord($row['reply']) + $reply_number);
  659. }
  660. $data['post_reply'] = $parent['post_reply'] . $reply_char;
  661. // 답변의 원글이 비밀글이라면, 비밀번호는 원글과 동일하게 넣는다.
  662. if( $parent['post_secret'] == 'Y' ) {
  663. $data['mem_password'] = $parent['mem_password'];
  664. }
  665. $data['post_num'] = $parent['post_num'];
  666. }
  667. else {
  668. $tmp = (int)$this->db->select_max('post_num','max')->from('board_post')->where('brd_key',$brd_key)->get()->row(0)->max;
  669. $data['post_reply'] = "";
  670. $data['post_num'] = $tmp+1;
  671. }
  672. if(! $this->db->insert('board_post', $data) )
  673. {
  674. alert(langs('게시판/msg/write_failed'));
  675. exit;
  676. }
  677. $post_idx = $this->db->insert_id();
  678. }
  679. else {
  680. $this->db->where('brd_key', $brd_key);
  681. $this->db->where('post_idx', $post_idx);
  682. if(! $this->db->update('board_post', $data))
  683. {
  684. alert(langs('게시판/msg/write_failed'));
  685. exit;
  686. }
  687. }
  688. // 업로드된 데이타가 있을경우에 DB에 기록
  689. if(isset($this->data['upload_array']) && count($this->data['upload_array']) >0 )
  690. {
  691. foreach($this->data['upload_array'] as &$arr) {
  692. $arr['att_target'] = $post_idx;
  693. }
  694. $this->db->insert_batch("attach", $this->data['upload_array']);
  695. }
  696. // 자신의 글은 바로 볼수 있도록
  697. if( ! $this->member->is_login() )
  698. {
  699. $this->session->set_userdata('post_password_'.$post_idx, TRUE);
  700. }
  701. if($this->member->is_login())
  702. {
  703. $this->point_process('brd_point_write', "POST_WRITE", "게시글 등록", $post_idx, FALSE);
  704. }
  705. $insert_data['post_idx'] = $post_idx;
  706. $insert_data['post_status'] = 'Y';
  707. alert(langs('게시판/msg/write_success'), base_url("board/{$brd_key}/{$post_idx}"));
  708. exit;
  709. }
  710. else {
  711. // 수정일경우를 대비해서 글 고유 pk 넘김
  712. $this->data['post_idx'] = (int)$post_idx;
  713. $this->data['post_parent'] = $this->input->get('post_parent', TRUE);
  714. $this->data['view'] = empty($post_idx) ? array() : $this->board_model->get_post($brd_key, $post_idx, FALSE);
  715. $this->data['parent'] = empty($this->data['post_parent']) ? array() : $this->board_model->get_post($brd_key, $this->data['post_parent'], FALSE);
  716. if( $this->data['post_idx'] && (! $this->data['view'] OR ! isset($this->data['view']['post_idx']) OR !$this->data['view']['post_idx'] ) )
  717. {
  718. alert(langs('게시판/msg/invalid_access'));
  719. exit;
  720. }
  721. $hidden = array();
  722. // 답글작성일경우 부모 번호 넘겨주기
  723. if($this->data['post_parent']) {
  724. $hidden['post_parent'] = $this->data['post_parent'];
  725. $this->data['view']['post_title'] = "RE : ". $this->data['parent']['post_title'];
  726. }
  727. $write_url = base_url("board/{$brd_key}/write" . ($post_idx ? '/'.$post_idx : ''), SSL_VERFIY ? "https":'http');
  728. $this->data['form_open'] = form_open_multipart($write_url, array("data-form"=>"post", "id"=>"form-post","autocomplete"=>"off"), $hidden);
  729. $this->data['form_close'] = form_close();
  730. // 메타태그 설정
  731. $this->site->meta_title = $this->data['board']['brd_title'] . ' - '. ((empty($post_idx)) ? '새 글 작성' : '글 수정'); // 이 페이지의 타이틀
  732. $this->site->meta_description = $this->data['board']['brd_description']; // 이 페이지의 요약 설명
  733. $this->site->meta_keywords = $this->data['board']['brd_keywords']; // 이 페이지에서 추가할 키워드 메타 태그
  734. $this->site->meta_image = ""; // 이 페이지에서 표시할 대표이미지
  735. // 레이아웃 & 뷰파일 설정
  736. $this->view = "write";
  737. $this->skin_type = "board/write";
  738. $this->skin = $this->data['board']['brd_skin_w'];
  739. }
  740. }
  741. /**
  742. * 첨부파일 다운로드 하기
  743. * @param $brd_key
  744. * @param $post_idx
  745. * @param $bmt_idx
  746. */
  747. public function download($brd_key, $post_idx, $att_idx)
  748. {
  749. if(empty($brd_key) OR empty($post_idx) OR empty($att_idx))
  750. {
  751. alert(langs( 'board/msg/invalid_access' ));
  752. }
  753. $this->board_common($brd_key, 'download');
  754. if(! $att = $this->db->where('att_idx', $att_idx)->where('att_target_type', 'BOARD')->where('att_target', $post_idx)->get('attach')->row_array())
  755. {
  756. alert(langs( 'board/msg/invalid_attach_file' ));
  757. exit;
  758. }
  759. $post = $this->boardlib->get_post($brd_key, $post_idx, TRUE);
  760. $this->point_process('brd_point_download', "POST_ATTACH_DOWNLOAD", "첨부파일 다운로드", $post_idx, ($post['reg_user'] == $this->member->info('idx')) );
  761. $this->db->where('att_idx', $att['att_idx'])->set('att_downloads', 'att_downloads + 1', FALSE)->update('attach');
  762. $this->load->helper('download');
  763. $data = file_get_contents(FCPATH.$att['att_filepath']);
  764. $name = urlencode($att['att_origin']);
  765. force_download($name, $data);
  766. }
  767. /**
  768. * 게시판에 관련된 포인트를 처리합니다.
  769. * @param $type
  770. * @param $mpo_type
  771. * @param $msg
  772. * @param $target_idx
  773. */
  774. public function point_process($type, $mpo_type, $msg, $target_idx, $check_writer=FALSE)
  775. {
  776. // 첨부파일 다운시 필요한 포인트가 있다면 확인
  777. if( $this->data['board'][$type] != 0 )
  778. {
  779. // 회원일 경우만 실행한다.
  780. if( $this->member->is_login() )
  781. {
  782. // 본인의 것은 실행하지 않는다.
  783. if( ! $check_writer )
  784. {
  785. // 이미 처리된 포인트 내역이 있는지 확인한다. (포인트는 한번만 차감/등록한다.)
  786. $res = (int) $this->db->select('COUNT(*) as cnt')->where('target_type', $mpo_type)->where('target_idx', $target_idx)->where('mem_idx', $this->member->is_login())->get('member_point')->row(0)->cnt;
  787. if( $res <= 0)
  788. {
  789. // 포인트 차감일 경우, 해당 포인트가 있는지 확인한다
  790. if( (int)$this->data['board'][$type] < 0)
  791. {
  792. if( (int)$this->member->info('point') < abs((int)$this->data['board'][$type]) )
  793. {
  794. alert(langs('회원/point/not_enough') . "({$this->data['board'][$type]})");
  795. exit;
  796. }
  797. }
  798. // 포인트 실제 처리
  799. $this->member->add_point($this->member->is_login(),$this->data['board'][$type."_flag"], $this->data['board'][$type], FALSE, $mpo_type, $msg, $target_idx);
  800. }
  801. }
  802. }
  803. // 비회원일 경우 아예 실행이 불가능하다.
  804. else
  805. {
  806. alert(langs('공통/msg/login_required'));
  807. exit;
  808. }
  809. }
  810. }
  811. /**
  812. * 게시판에 관련된 포인트를 삭제등의 행동시 취소합니다.
  813. * @param $target_type
  814. * @param $target_idx
  815. * @param $msg
  816. */
  817. public function point_cancel($target_type, $target_idx, $msg)
  818. {
  819. // 댓글등록으로 증가한 포인트가 있다면 다시 감소
  820. // 포인트 입력처리
  821. if( $this->member->is_login() )
  822. {
  823. $ret = $this->db->where('target_type', $target_type)->where('mem_idx', $this->member->is_login() )->where('target_idx', $target_idx)->where('mpo_value !=','0')->get('member_point')->row_array();
  824. if( $ret && isset($ret['mpo_value']) && $ret['mpo_value'] != 0 )
  825. {
  826. $this->member->add_point($this->member->is_login(),$ret['mpo_flag']*-1, $ret['mpo_value'], FALSE, $target_type, $msg, $target_idx);
  827. }
  828. }
  829. }
  830. /**
  831. * 게시글 삭제
  832. * @param $brd_key
  833. * @param $post_idx
  834. */
  835. public function delete($brd_key, $post_idx)
  836. {
  837. $this->board_common($brd_key);
  838. $this->_modify_auth($brd_key, $post_idx);
  839. $post = $this->board_model->get_post($brd_key, $post_idx, FALSE);
  840. $len = strlen($post['post_reply']);
  841. if( $len < 0 ) $len = 0;
  842. $reply = substr($post['post_reply'], 0, $len);
  843. // 게시글에 답글이 달려있는경우 삭제할 수 없다
  844. $count = (int) $this->db->select('COUNT(*) AS cnt')
  845. ->where('post_idx <>', $post['post_idx'])
  846. ->where('post_num', $post['post_num'])
  847. ->where('brd_key', $post['brd_key'])
  848. ->like('post_reply', $reply, 'after')
  849. ->where_in('post_status',array('Y','B'))
  850. ->get('board_post')
  851. ->row(0)
  852. ->cnt;
  853. if( $count > 1 )
  854. {
  855. alert(langs('게시판/msg/cant_delete_because_child'));
  856. exit;
  857. }
  858. if( $this->db->where('post_idx', $post_idx)->set('post_status', 'N')->update('board_post') )
  859. {
  860. $this->point_cancel("POST_WRITE", $post_idx, "게시글 삭제");
  861. alert( langs('게시판/msg/delete_success'), base_url("board/{$brd_key}") );
  862. exit;
  863. }
  864. else
  865. {
  866. alert( langs('게시판/msg/delete_failed') );
  867. exit;
  868. }
  869. }
  870. /**
  871. * 권한 확인
  872. * @return array
  873. */
  874. private function check_auth()
  875. {
  876. $return = array();
  877. return $return;
  878. }
  879. /**
  880. * 게시판마다 공통으로 불러오기
  881. * @param $brd_key
  882. * @param string $check_type
  883. */
  884. private function board_common($brd_key, $check_type="")
  885. {
  886. $this->boardlib->common_data($brd_key);
  887. if( $check_type && ! $this->data['board']['auth'][$check_type] )
  888. {
  889. $msg = langs('게시판/msg/list_unauthorize');;
  890. if( $check_type == 'write' ) $msg = langs('게시판/msg/write_unauthorize');
  891. else if ($check_type == 'view' || $check_type == 'read') $msg = langs('게시판/msg/read_unauthorize');
  892. else if ($check_type == 'download') $msg = langs('게시판/msg/download_unauthorize');
  893. else if ($check_type == 'reply') $msg = langs('게시판/msg/reply_unauthorize');
  894. else if ($check_type == 'comment') $msg = langs('게시판/msg/comment_unauthorize');
  895. alert($msg);
  896. exit;
  897. }
  898. $use_list = $check_type == 'list';
  899. $this->data['list'] = array(
  900. "list"=>array(),
  901. "total_count" => 0
  902. );
  903. $this->data['pagination'] = "";
  904. if( $use_list )
  905. {
  906. // 게시글 목록 가져오기
  907. $this->data['list'] = $this->boardlib->post_list($this->data['board'], $this->param);
  908. // 페이지네이션 세팅
  909. $paging['page'] = $this->param['page'];
  910. $paging['page_rows'] = $this->data['board']['brd_page_rows'];
  911. $paging['total_rows'] = $this->data['list']['total_count'];
  912. $paging['fixed_page_num'] = $this->data['board']['brd_fixed_num'];
  913. $this->load->library('paging', $paging);
  914. $this->data['pagination'] = $this->paging->create();
  915. }
  916. // 레이아웃 정의
  917. $this->theme = $this->site->get_layout();
  918. $this->skin_type = "board";
  919. $this->active = "/board/".$this->data['board']['brd_key'];
  920. }
  921. }