1 /* Copyright 2013,2014 Akira Ohta (akohta001@gmail.com)
2 This file is part of ntch.
4 The ntch is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 The ntch is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with ntch. If not, see <http://www.gnu.org/licenses/>.
28 #define MODEL_2CH_PRIVATE_DATA
31 #include "utils/nt_std_t.h"
32 #include "utils/nt_conv_char.h"
33 #include "utils/file.h"
34 #include "utils/base64.h"
35 #include "utils/nt_pthread.h"
36 #include "cloud/nt_cloud.h"
37 #include "net/nt_http.h"
38 #include "net/nt_cookie.h"
39 #include "_2ch/model_2ch.h"
40 #include "_2ch/_2ch.h"
42 char *URL_2CH_BOARDMENU = "http://menu.2ch.net/bbsmenu.html";
43 nt_2ch_model_handle app_2ch_model;
46 #define S_SIZE (1024*2)
48 static BOOL set_post_data(char *data, size_t data_len,
49 const wchar_t *bbs, const wchar_t *id,
50 const char *name, const char *mail,
52 static BOOL set_post_data_machibbs(char *data, size_t data_len,
53 const wchar_t *bbs, const wchar_t *id,
54 const char *name, const char *mail,
56 static BOOL set_offlaw_address(char *buf, size_t buf_len,
58 wchar_t * board_name, wchar_t *dat_name);
59 static BOOL nt_write_msg_machibbs(nt_2ch_selected_item_tp selectp,
60 nt_write_data_tp writep, nt_cookie_tp cookiep);
62 static nt_pthread_result_t nt_read_board_async(void* data);
63 static nt_pthread_result_t nt_read_board_async_result(
64 nt_pthread_result_t result);
67 BOOL nt_2ch_model_init(){
68 app_2ch_model = nt_2ch_model_alloc();
69 return (NULL != app_2ch_model);
72 BOOL nt_init_board_menu()
75 char *url = URL_2CH_BOARDMENU;
78 char s_src[S_SIZE], s_dst[S_SIZE*sizeof(wchar_t)];
82 memset(s_src, '\0', S_SIZE);
83 memset(s_dst, '\0', S_SIZE*sizeof(wchar_t));
85 if(!nt_make_sha1_path(LOG_PATH, url, &outp)){
90 if(!nt_http_get(url, outp, NULL, NULL, NULL, FALSE, FALSE)){
95 fp_src = fopen(outp, "r");
100 icd = iconv_open("wchar_t", "cp932");
101 if(((iconv_t)-1) == icd){
109 if(!fgets(s_src, S_SIZE, fp_src))
114 n_src = strlen(s_src);
117 size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
119 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
124 *((wchar_t*)p_dst) = L'\0';
125 parse_board_menu(app_2ch_model, (const wchar_t*)s_dst);
137 static BOOL is_machibbs_address(const wchar_t *host_name)
140 cptr = wcsstr(host_name, L".machi.to");
141 return (cptr != NULL) ? TRUE : FALSE;
144 BOOL nt_read_thread(nt_2ch_selected_item_handle h_select)
146 nt_2ch_selected_item_tp selectp;
148 wchar_t referer[1024];
151 wchar_t *file_name, *cptr;
152 wchar_t *server_name, *board_name;
154 nt_thread_tp threadp;
158 char s_src[S_SIZE*sizeof(wchar_t)];
159 char s_dst[S_SIZE*sizeof(wchar_t)];
163 nt_cloud_handle h_cloud;
166 assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
168 selectp = (nt_2ch_selected_item_tp)h_select;
170 memset(s_src, '\0', sizeof(s_src));
171 memset(s_dst, '\0', sizeof(s_dst));
174 if(!selectp->selected_categoryp)
176 if(!selectp->selected_boardp)
178 if(!selectp->selected_threadp)
181 boardp = selectp->selected_boardp;
182 threadp = selectp->selected_threadp;
183 file_name = threadp->file_name;
186 if(!nt_parse_server_name_and_board_name(boardp->address,
187 buf, sizeof(buf), &server_name, &board_name)){
190 if(is_machibbs_address(server_name)){
191 is_matchi_bbs = TRUE;
192 wcscpy(url, L"http://");
193 wcscat(url, server_name);
194 wcscat(url, L"/bbs/offlaw.cgi/");
195 wcscat(url, board_name);
197 cptr = nt_rid_sufix(file_name);
204 wcscpy(referer, boardp->address);
205 wcscat(referer, L"/");
207 is_matchi_bbs = FALSE;
208 wcscpy(url, boardp->address);
212 if(url[len-1] != L'/'){
217 wcscat(url, L"dat/");
218 wcscat(url, file_name);
219 wcscpy(referer, L"http://");
220 wcscat(referer, server_name);
221 wcscat(referer, L"/test/read.cgi/");
222 wcscat(referer, board_name);
223 wcscat(referer, L"/");
224 cptr = nt_rid_sufix(file_name);
227 wcscat(referer, cptr);
229 wcscat(referer, L"/");
231 len = wcstombs(s_src, url, sizeof(s_src)-1);
234 len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
237 if(!nt_make_sha1_path(LOG_PATH, s_src, &outp)){
241 if(!nt_http_get(s_src, outp, s_dst, NULL, NULL, TRUE, FALSE)){
242 if(!set_offlaw_address(s_src, sizeof(s_src),
243 server_name, board_name, file_name)){
247 if(!nt_http_get(s_src, outp, s_dst, NULL, NULL, FALSE, FALSE)){
252 fp_src = fopen(outp, "r");
257 icd = iconv_open("wchar_t", "cp932");
258 if(((iconv_t)-1) == icd){
263 nt_thread_clear_children(&threadp->handle);
264 threadp->num_res = 0;
271 if(!fgets(s_src, S_SIZE, fp_src))
276 n_src = strlen(s_src);
277 n_dst = sizeof(s_dst)-1;
279 size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
281 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
285 *((wchar_t*)p_dst) = L'\0';
287 parse_thread(&threadp->handle, (const wchar_t*)s_dst, res_no);
289 parse_thread_machi_bbs(&threadp->handle, (const wchar_t*)s_dst);
295 h_cloud = nt_cloud_get_handle();
296 if(h_cloud && threadp->num_res > 0){
297 nt_cloud_update_read_count_async(h_cloud,
298 boardp->name, file_name, threadp->num_res);
301 nt_cloud_release_ref(h_cloud);
302 return (threadp->num_res > 0);
305 wchar_t* nt_read_thread_title(nt_board_handle h_board,
306 const wchar_t *dat_name)
315 char s_src[S_SIZE*sizeof(wchar_t)];
316 char s_dst[S_SIZE*sizeof(wchar_t)];
321 assert(h_board->chk_sum == NT_2CH_BOARD_CHK_SUM);
322 boardp = (nt_board_tp)h_board;
324 memset(s_src, '\0', sizeof(s_src));
325 memset(s_dst, '\0', sizeof(s_dst));
328 wcscpy(url, boardp->address);
332 if(url[len-1] != L'/'){
337 wcscat(url, L"dat/");
338 wcscat(url, dat_name);
341 len = wcstombs(s_src, url, sizeof(s_src)-1);
344 if(!nt_make_sha1_path(LOG_PATH, s_src, &outp)){
348 fp_src = fopen(outp, "r");
353 icd = iconv_open("wchar_t", "cp932");
354 if(((iconv_t)-1) == icd){
361 if(!fgets(s_src, S_SIZE, fp_src)){
370 n_src = strlen(s_src);
371 n_dst = sizeof(s_dst)-1;
373 size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
375 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
379 *((wchar_t*)p_dst) = L'\0';
380 title = parse_thread_title((const wchar_t*)s_dst);
388 BOOL nt_read_board(nt_2ch_selected_item_handle h_select)
390 nt_2ch_selected_item_tp selectp;
397 char s_src[S_SIZE], s_dst[S_SIZE*sizeof(wchar_t)];
401 nt_mutex_handle h_mutex;
404 assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
406 selectp = (nt_2ch_selected_item_tp)h_select;
408 memset(data, 0, sizeof(data));
409 memset(s_src, '\0', S_SIZE);
410 memset(s_dst, '\0', S_SIZE*sizeof(wchar_t));
411 //fputs("enter nt_read_board\n",stderr);
412 if(!selectp->selected_categoryp)
414 if(!selectp->selected_boardp)
417 boardp = selectp->selected_boardp;
418 //fwprintf(stderr, L"%ls\n", boardp->name);
419 h_mutex = nt_board_get_mutex(&boardp->handle);
422 if(!nt_mutex_lock(h_mutex))
424 //fputs(" -- lock nt_read_board\n",stderr);
426 nt_board_clear_children(&boardp->handle);
427 address = boardp->address;
430 len = wcstombs(data, address, sizeof(data)-1);
432 nt_mutex_unlock(h_mutex);
436 if(data[len-1] != '/')
438 strcat(data, "subject.txt");
441 if(!nt_make_sha1_path(LOG_PATH, data, &outp)){
442 nt_mutex_unlock(h_mutex);
446 if(!nt_http_get(data, outp, URL_2CH_BOARDMENU, NULL, NULL, FALSE, FALSE)){
448 nt_mutex_unlock(h_mutex);
452 fp_src = fopen(outp, "r");
455 nt_mutex_unlock(h_mutex);
458 icd = iconv_open("wchar_t", "cp932");
459 if(((iconv_t)-1) == icd){
462 nt_mutex_unlock(h_mutex);
469 if(!fgets(s_src, S_SIZE, fp_src))
474 n_src = strlen(s_src);
475 n_dst = (S_SIZE-1)*sizeof(wchar_t);
477 size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
479 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
483 *((wchar_t*)p_dst) = L'\0';
484 if(!parse_board(&boardp->handle, (const wchar_t*)s_dst)){
490 //fputs(" -- unlock nt_read_board\n",stderr);
491 nt_mutex_unlock(h_mutex);
492 //fputs("exit nt_read_board\n",stderr);
494 if(!boardp->threadlistp)
499 BOOL nt_write_msg(nt_2ch_selected_item_handle h_select, nt_write_data_handle h_write_data,
500 nt_cookie_tp cookiep, nt_maru_2ch_tp marup)
502 nt_2ch_selected_item_tp selectp;
503 nt_write_data_tp writep;
505 wchar_t referer[1024];
506 char post_data[1024*4];
508 char out_buf[1024*4];
511 wchar_t *server_name, *board_name;
513 nt_thread_tp threadp;
515 char s_src[S_SIZE*sizeof(wchar_t)];
516 char s_dst[S_SIZE*sizeof(wchar_t)];
521 assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
522 assert(h_write_data);
523 assert(h_write_data->chk_sum == NT_2CH_WRITE_DATA_CHK_SUM);
525 selectp = (nt_2ch_selected_item_tp)h_select;
526 writep = (nt_write_data_tp)h_write_data;
528 memset(s_src, '\0', sizeof(s_src));
529 memset(s_dst, '\0', sizeof(s_dst));
530 memset(post_data, '\0', sizeof(post_data));
532 if(!selectp->selected_categoryp)
534 if(!selectp->selected_boardp)
536 if(!selectp->selected_threadp)
539 boardp = selectp->selected_boardp;
540 threadp = selectp->selected_threadp;
541 file_name = threadp->file_name;
543 if(!nt_parse_server_name_and_board_name(boardp->address,
544 buf, sizeof(buf), &server_name, &board_name)){
548 if(is_machibbs_address(server_name)){
549 return nt_write_msg_machibbs(selectp, writep, cookiep);
552 wcscpy(url, L"http://");
553 wcscat(url, server_name);
554 wcscat(url, L"/test/bbs.cgi");
556 wcscpy(referer, L"http://");
557 wcscat(referer, server_name);
558 wcscat(referer, L"/test/read.cgi/");
559 wcscat(referer, board_name);
560 wcscat(referer, L"/");
561 dat_name = nt_rid_sufix(file_name);
564 wcscat(referer, dat_name);
565 wcscat(referer, L"/");
567 len = wcstombs(s_src, url, sizeof(s_src)-1);
570 len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
573 if(!set_post_data(post_data, sizeof(post_data),
574 board_name, dat_name, writep->name,
575 writep->mail, writep->msg)){
578 strcat(post_data, "&yuki=akari");
580 if(marup && marup->sid){
581 strcat(post_data, "&sid=");
582 strcat(post_data, marup->sid);
584 if(!nt_http_post(s_src, post_data, out_buf, sizeof(out_buf),
585 s_dst, NULL, NULL, cookiep)){
588 icd = iconv_open("wchar_t", "cp932");
589 if(((iconv_t)-1) == icd){
593 if(writep->result_html)
594 free(writep->result_html);
595 writep->result_html = malloc(1024*sizeof(wchar_t)*4);
596 if(!writep->result_html)
599 if(!nt_conv_sjis2wc(icd, out_buf, writep->result_html,
600 1024*sizeof(wchar_t)*4)){
612 static BOOL nt_write_msg_machibbs(nt_2ch_selected_item_tp selectp,
613 nt_write_data_tp writep, nt_cookie_tp cookiep)
616 wchar_t referer[1024];
617 char post_data[1024*4];
619 char out_buf[1024*4];
622 wchar_t *server_name, *board_name;
624 nt_thread_tp threadp;
626 char s_src[S_SIZE*sizeof(wchar_t)];
627 char s_dst[S_SIZE*sizeof(wchar_t)];
631 memset(s_src, '\0', sizeof(s_src));
632 memset(s_dst, '\0', sizeof(s_dst));
633 memset(post_data, '\0', sizeof(post_data));
635 if(!selectp->selected_categoryp)
637 if(!selectp->selected_boardp)
639 if(!selectp->selected_threadp)
642 boardp = selectp->selected_boardp;
643 threadp = selectp->selected_threadp;
644 file_name = threadp->file_name;
646 if(!nt_parse_server_name_and_board_name(boardp->address,
647 buf, sizeof(buf), &server_name, &board_name)){
652 wcscpy(url, L"http://");
653 wcscat(url, server_name);
654 wcscat(url, L"/bbs/write.cgi");
655 dat_name = nt_rid_sufix(file_name);
659 wcscpy(referer, boardp->address);
661 len = wcstombs(s_src, url, sizeof(s_src)-1);
664 len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
667 if(!set_post_data_machibbs(post_data, sizeof(post_data),
668 board_name, dat_name, writep->name,
669 writep->mail, writep->msg)){
672 len = wcstombs(s_src, url, sizeof(s_src)-1);
675 strcat(post_data, "&CC=%82%A0");
677 if(!nt_http_post(s_src, post_data, out_buf, sizeof(out_buf),
678 s_dst, NULL, NULL, cookiep)){
681 icd = iconv_open("wchar_t", "cp932");
682 if(((iconv_t)-1) == icd){
686 if(writep->result_html)
687 free(writep->result_html);
688 writep->result_html = malloc(1024*sizeof(wchar_t)*4);
689 if(!writep->result_html)
692 if(!nt_conv_sjis2wc(icd, out_buf, writep->result_html,
693 1024*sizeof(wchar_t)*4)){
706 static BOOL set_post_data(char *data, size_t data_len,
707 const wchar_t *bbs, const wchar_t *id,
708 const char *name, const char *mail,
716 assert(bbs && id && name && mail && msg);
718 memset(buf, 0, sizeof(buf));
719 memset(buf2, 0, sizeof(buf2));
721 icd = iconv_open("cp932", "wchar_t");
722 if(((iconv_t)-1) == icd){
729 strcpy(cptr, "bbs=");
730 cptr += strlen(data);
731 if(!nt_conv_wc2sjis(icd, bbs, buf, sizeof(buf)))
735 strcpy(cptr, "&key=");
736 cptr += strlen(cptr);
737 if(!nt_conv_wc2sjis(icd, id, buf, sizeof(buf)))
741 strcpy(cptr, "&time=");
742 cptr += strlen(cptr);
743 sprintf(buf, "%ld&FROM=", t);
749 icd = iconv_open("cp932", "UTF-8");
750 if(icd == (iconv_t)-1){
755 if(name && 0 < strlen(name)){
756 if(!nt_conv_local2sjis(icd, name, buf, sizeof(buf)))
758 if(!url_encode(buf, buf2, sizeof(buf2)))
761 cptr += strlen(buf2);
763 strcpy(cptr, "&mail=");
764 cptr += strlen(cptr);
765 if(mail && 0 < strlen(mail)){
766 if(!nt_conv_local2sjis(icd, mail, buf, sizeof(buf)))
768 if(!url_encode(buf, buf2, sizeof(buf2)))
771 cptr += strlen(buf2);
773 strcpy(cptr, "&MESSAGE=");
774 cptr += strlen(cptr);
775 if(msg && 0 < strlen(msg)){
776 if(!nt_conv_local2sjis(icd, msg, buf, sizeof(buf)))
778 if(!url_encode(buf, buf2, sizeof(buf2)))
781 cptr += strlen(buf2);
783 strcpy(cptr, "&submit=%8F%91%82%AB%8D%9E%82%DE");
790 static BOOL set_post_data_machibbs(char *data, size_t data_len,
791 const wchar_t *bbs, const wchar_t *id,
792 const char *name, const char *mail,
800 assert(bbs && id && name && mail && msg);
802 memset(buf, 0, sizeof(buf));
803 memset(buf2, 0, sizeof(buf2));
805 icd = iconv_open("cp932", "wchar_t");
806 if(((iconv_t)-1) == icd){
813 strcpy(cptr, "BBS=");
814 cptr += strlen(data);
815 if(!nt_conv_wc2sjis(icd, bbs, buf, sizeof(buf)))
819 strcpy(cptr, "&KEY=");
820 cptr += strlen(cptr);
821 if(!nt_conv_wc2sjis(icd, id, buf, sizeof(buf)))
825 strcpy(cptr, "&TIME=");
826 cptr += strlen(cptr);
827 sprintf(buf, "%ld&NAME=", t);
833 icd = iconv_open("cp932", "UTF-8");
834 if(icd == (iconv_t)-1){
839 if(name && 0 < strlen(name)){
840 if(!nt_conv_local2sjis(icd, name, buf, sizeof(buf)))
842 if(!url_encode(buf, buf2, sizeof(buf2)))
845 cptr += strlen(buf2);
847 strcpy(cptr, "&MAIL=");
848 cptr += strlen(cptr);
849 if(mail && 0 < strlen(mail)){
850 if(!nt_conv_local2sjis(icd, mail, buf, sizeof(buf)))
852 if(!url_encode(buf, buf2, sizeof(buf2)))
855 cptr += strlen(buf2);
857 strcpy(cptr, "&MESSAGE=");
858 cptr += strlen(cptr);
859 if(msg && 0 < strlen(msg)){
860 if(!nt_conv_local2sjis(icd, msg, buf, sizeof(buf)))
862 if(!url_encode(buf, buf2, sizeof(buf2)))
865 cptr += strlen(buf2);
867 strcpy(cptr, "&submit=%8F%91%82%AB%8D%9E%82%DE");
874 static BOOL set_offlaw_address(char *buf, size_t buf_len,
875 wchar_t *server_name,
876 wchar_t * board_name, wchar_t *dat_name)
882 cptr = wcsstr(server_name, L".2ch.net");
885 cptr = wcsstr(dat_name, L".dat");
888 cptr = nt_rid_sufix(dat_name);
891 wcscpy(url, L"http://");
892 wcscat(url, server_name);
893 wcscat(url, L"/test/offlaw2.so?shiro=kuma&sid=ERROR&bbs=");
894 wcscat(url, board_name);
895 wcscat(url, L"&key=");
898 len = wcstombs(buf, url, buf_len-1);
904 int nt_read_board_list(nt_link_tp selitem_list)
906 nt_2ch_selected_item_handle h_select;
909 nt_pthread_handle h_pthread;
911 assert(selitem_list);
913 linkp = selitem_list;
915 h_select = (nt_2ch_selected_item_handle)linkp->data;
916 #ifdef NT_DISABLE_PTHREAD
917 if(nt_read_board(h_select))
920 nt_2ch_selected_item_add_ref(h_select);
921 h_pthread = nt_pthread_alloc(
924 nt_read_board_async_result);
926 nt_2ch_selected_item_release_ref(h_select);
927 }else if(!nt_pthread_put_que(h_pthread)){
928 nt_pthread_release_ref(h_pthread);
929 nt_2ch_selected_item_release_ref(h_select);
931 nt_pthread_release_ref(h_pthread);
936 }while(linkp != selitem_list);
940 static nt_pthread_result_t nt_read_board_async(void* data)
942 nt_2ch_selected_item_handle h_select;
943 nt_pthread_result_t result;
945 result.code = NT_PTHREAD_RESULT_NONE;
948 h_select = (nt_2ch_selected_item_handle)data;
949 nt_2ch_selected_item_add_ref(h_select);
950 nt_2ch_selected_item_release_ref(h_select);
952 if(nt_read_board(h_select)){
953 result.code = NT_PTHREAD_RESULT_UPDATE_BOARD;
955 nt_2ch_selected_item_release_ref(h_select);
959 static nt_pthread_result_t nt_read_board_async_result(
960 nt_pthread_result_t result)
965 BOOL nt_set_sel_item(nt_2ch_model_handle h_model,
966 nt_2ch_selected_item_handle *h_sel_itemp,
967 nt_searched_thread_handle h_searched_thread, const wchar_t** errorpp)
969 const wchar_t *board_name, *dat_name, *title;
971 nt_category_handle h_category;
972 nt_board_handle h_board;
973 nt_thread_handle h_thread;
974 nt_2ch_selected_item_handle h_sel_item;
975 nt_enum_handle h_enum;
981 h_sel_item = nt_2ch_selected_item_alloc();
985 board_name = nt_searched_thread_get_board_name(h_searched_thread);
988 dat_name = nt_searched_thread_get_dat_name(h_searched_thread);
989 title = nt_searched_thread_get_title(h_searched_thread);
991 h_board = nt_get_board_by_name(
992 h_model, board_name, &h_category);
993 if(!h_board || !h_category){
994 *errorpp = L"板情報が見つかりませんでした";
995 nt_2ch_selected_item_release_ref(h_sel_item);
998 nt_set_selected_board(h_sel_item, h_category, h_board);
1001 h_enum = nt_board_get_thread_enum(h_board);
1003 if(!nt_read_board(h_sel_item)){
1004 *errorpp = L"板が開けませんでした";
1007 h_enum = nt_board_get_thread_enum(h_board);
1009 *errorpp = L"板が開けませんでした";
1014 nt_enum_unset(h_enum);
1017 nt_board_release_ref(h_board);
1018 nt_category_release_ref(h_category);
1019 *h_sel_itemp = h_sel_item;
1022 h_thread = nt_get_thread_by_dat_name(h_board, dat_name);
1025 h_thread = nt_thread_dummy_alloc(L"Dummy", dat_name, 0);
1027 h_thread = nt_thread_dummy_alloc(title, dat_name, 0);
1029 *errorpp = L"スレッド情報が見つかりませんでした";
1034 nt_set_selected_thread(h_sel_item, h_thread);
1036 if(!nt_read_thread(h_sel_item)){
1037 *errorpp = L"スレッドが開けませんでした";
1041 cptr = nt_read_thread_title(h_board, dat_name);
1043 nt_thread_set_title(h_thread, cptr);
1048 nt_thread_release_ref(h_thread);
1049 nt_board_release_ref(h_board);
1050 nt_category_release_ref(h_category);
1051 *h_sel_itemp = h_sel_item;
1055 nt_thread_release_ref(h_thread);
1056 nt_board_release_ref(h_board);
1057 nt_category_release_ref(h_category);
1058 nt_2ch_selected_item_release_ref(h_sel_item);