1 /* Copyright 2013 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;
269 if(!fgets(s_src, S_SIZE, fp_src))
274 n_src = strlen(s_src);
275 n_dst = sizeof(s_dst)-1;
277 size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
279 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
283 *((wchar_t*)p_dst) = L'\0';
285 parse_thread(&threadp->handle, (const wchar_t*)s_dst);
287 parse_thread_machi_bbs(&threadp->handle, (const wchar_t*)s_dst);
293 h_cloud = nt_cloud_get_handle();
294 if(h_cloud && threadp->num_res > 0){
295 nt_cloud_update_read_count_async(h_cloud,
296 boardp->name, file_name, threadp->num_res);
299 nt_cloud_release_ref(h_cloud);
300 return (threadp->num_res > 0);
303 wchar_t* nt_read_thread_title(nt_board_handle h_board,
304 const wchar_t *dat_name)
313 char s_src[S_SIZE*sizeof(wchar_t)];
314 char s_dst[S_SIZE*sizeof(wchar_t)];
319 assert(h_board->chk_sum == NT_2CH_BOARD_CHK_SUM);
320 boardp = (nt_board_tp)h_board;
322 memset(s_src, '\0', sizeof(s_src));
323 memset(s_dst, '\0', sizeof(s_dst));
326 wcscpy(url, boardp->address);
330 if(url[len-1] != L'/'){
335 wcscat(url, L"dat/");
336 wcscat(url, dat_name);
339 len = wcstombs(s_src, url, sizeof(s_src)-1);
342 if(!nt_make_sha1_path(LOG_PATH, s_src, &outp)){
346 fp_src = fopen(outp, "r");
351 icd = iconv_open("wchar_t", "cp932");
352 if(((iconv_t)-1) == icd){
359 if(!fgets(s_src, S_SIZE, fp_src)){
368 n_src = strlen(s_src);
369 n_dst = sizeof(s_dst)-1;
371 size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
373 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
377 *((wchar_t*)p_dst) = L'\0';
378 title = parse_thread_title((const wchar_t*)s_dst);
386 BOOL nt_read_board(nt_2ch_selected_item_handle h_select)
388 nt_2ch_selected_item_tp selectp;
395 char s_src[S_SIZE], s_dst[S_SIZE*sizeof(wchar_t)];
399 nt_mutex_handle h_mutex;
402 assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
404 selectp = (nt_2ch_selected_item_tp)h_select;
406 memset(data, 0, sizeof(data));
407 memset(s_src, '\0', S_SIZE);
408 memset(s_dst, '\0', S_SIZE*sizeof(wchar_t));
409 //fputs("enter nt_read_board\n",stderr);
410 if(!selectp->selected_categoryp)
412 if(!selectp->selected_boardp)
415 boardp = selectp->selected_boardp;
416 //fwprintf(stderr, L"%ls\n", boardp->name);
417 h_mutex = nt_board_get_mutex(&boardp->handle);
420 if(!nt_mutex_lock(h_mutex))
422 //fputs(" -- lock nt_read_board\n",stderr);
424 nt_board_clear_children(&boardp->handle);
425 address = boardp->address;
428 len = wcstombs(data, address, sizeof(data)-1);
430 nt_mutex_unlock(h_mutex);
434 if(data[len-1] != '/')
436 strcat(data, "subject.txt");
439 if(!nt_make_sha1_path(LOG_PATH, data, &outp)){
440 nt_mutex_unlock(h_mutex);
444 if(!nt_http_get(data, outp, URL_2CH_BOARDMENU, NULL, NULL, FALSE, FALSE)){
446 nt_mutex_unlock(h_mutex);
450 fp_src = fopen(outp, "r");
453 nt_mutex_unlock(h_mutex);
456 icd = iconv_open("wchar_t", "cp932");
457 if(((iconv_t)-1) == icd){
460 nt_mutex_unlock(h_mutex);
467 if(!fgets(s_src, S_SIZE, fp_src))
472 n_src = strlen(s_src);
473 n_dst = (S_SIZE-1)*sizeof(wchar_t);
475 size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
477 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
481 *((wchar_t*)p_dst) = L'\0';
482 if(!parse_board(&boardp->handle, (const wchar_t*)s_dst)){
488 //fputs(" -- unlock nt_read_board\n",stderr);
489 nt_mutex_unlock(h_mutex);
490 //fputs("exit nt_read_board\n",stderr);
492 if(!boardp->threadlistp)
497 BOOL nt_write_msg(nt_2ch_selected_item_handle h_select, nt_write_data_handle h_write_data,
498 nt_cookie_tp cookiep, nt_maru_2ch_tp marup)
500 nt_2ch_selected_item_tp selectp;
501 nt_write_data_tp writep;
503 wchar_t referer[1024];
504 char post_data[1024*4];
506 char out_buf[1024*4];
509 wchar_t *server_name, *board_name;
511 nt_thread_tp threadp;
513 char s_src[S_SIZE*sizeof(wchar_t)];
514 char s_dst[S_SIZE*sizeof(wchar_t)];
519 assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
520 assert(h_write_data);
521 assert(h_write_data->chk_sum == NT_2CH_WRITE_DATA_CHK_SUM);
523 selectp = (nt_2ch_selected_item_tp)h_select;
524 writep = (nt_write_data_tp)h_write_data;
526 memset(s_src, '\0', sizeof(s_src));
527 memset(s_dst, '\0', sizeof(s_dst));
528 memset(post_data, '\0', sizeof(post_data));
530 if(!selectp->selected_categoryp)
532 if(!selectp->selected_boardp)
534 if(!selectp->selected_threadp)
537 boardp = selectp->selected_boardp;
538 threadp = selectp->selected_threadp;
539 file_name = threadp->file_name;
541 if(!nt_parse_server_name_and_board_name(boardp->address,
542 buf, sizeof(buf), &server_name, &board_name)){
546 if(is_machibbs_address(server_name)){
547 return nt_write_msg_machibbs(selectp, writep, cookiep);
550 wcscpy(url, L"http://");
551 wcscat(url, server_name);
552 wcscat(url, L"/test/bbs.cgi");
554 wcscpy(referer, L"http://");
555 wcscat(referer, server_name);
556 wcscat(referer, L"/test/read.cgi/");
557 wcscat(referer, board_name);
558 wcscat(referer, L"/");
559 dat_name = nt_rid_sufix(file_name);
562 wcscat(referer, dat_name);
563 wcscat(referer, L"/");
565 len = wcstombs(s_src, url, sizeof(s_src)-1);
568 len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
571 if(!set_post_data(post_data, sizeof(post_data),
572 board_name, dat_name, writep->name,
573 writep->mail, writep->msg)){
576 strcat(post_data, "&yuki=akari");
578 if(marup && marup->sid){
579 strcat(post_data, "&sid=");
580 strcat(post_data, marup->sid);
582 if(!nt_http_post(s_src, post_data, out_buf, sizeof(out_buf),
583 s_dst, NULL, NULL, cookiep)){
586 icd = iconv_open("wchar_t", "cp932");
587 if(((iconv_t)-1) == icd){
591 if(writep->result_html)
592 free(writep->result_html);
593 writep->result_html = malloc(1024*sizeof(wchar_t)*4);
594 if(!writep->result_html)
597 if(!nt_conv_sjis2wc(icd, out_buf, writep->result_html,
598 1024*sizeof(wchar_t)*4)){
610 static BOOL nt_write_msg_machibbs(nt_2ch_selected_item_tp selectp,
611 nt_write_data_tp writep, nt_cookie_tp cookiep)
614 wchar_t referer[1024];
615 char post_data[1024*4];
617 char out_buf[1024*4];
620 wchar_t *server_name, *board_name;
622 nt_thread_tp threadp;
624 char s_src[S_SIZE*sizeof(wchar_t)];
625 char s_dst[S_SIZE*sizeof(wchar_t)];
629 memset(s_src, '\0', sizeof(s_src));
630 memset(s_dst, '\0', sizeof(s_dst));
631 memset(post_data, '\0', sizeof(post_data));
633 if(!selectp->selected_categoryp)
635 if(!selectp->selected_boardp)
637 if(!selectp->selected_threadp)
640 boardp = selectp->selected_boardp;
641 threadp = selectp->selected_threadp;
642 file_name = threadp->file_name;
644 if(!nt_parse_server_name_and_board_name(boardp->address,
645 buf, sizeof(buf), &server_name, &board_name)){
650 wcscpy(url, L"http://");
651 wcscat(url, server_name);
652 wcscat(url, L"/bbs/write.cgi");
653 dat_name = nt_rid_sufix(file_name);
657 wcscpy(referer, boardp->address);
659 len = wcstombs(s_src, url, sizeof(s_src)-1);
662 len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
665 if(!set_post_data_machibbs(post_data, sizeof(post_data),
666 board_name, dat_name, writep->name,
667 writep->mail, writep->msg)){
670 len = wcstombs(s_src, url, sizeof(s_src)-1);
673 strcat(post_data, "&CC=%82%A0");
675 if(!nt_http_post(s_src, post_data, out_buf, sizeof(out_buf),
676 s_dst, NULL, NULL, cookiep)){
679 icd = iconv_open("wchar_t", "cp932");
680 if(((iconv_t)-1) == icd){
684 if(writep->result_html)
685 free(writep->result_html);
686 writep->result_html = malloc(1024*sizeof(wchar_t)*4);
687 if(!writep->result_html)
690 if(!nt_conv_sjis2wc(icd, out_buf, writep->result_html,
691 1024*sizeof(wchar_t)*4)){
704 static BOOL set_post_data(char *data, size_t data_len,
705 const wchar_t *bbs, const wchar_t *id,
706 const char *name, const char *mail,
714 assert(bbs && id && name && mail && msg);
716 memset(buf, 0, sizeof(buf));
717 memset(buf2, 0, sizeof(buf2));
719 icd = iconv_open("cp932", "wchar_t");
720 if(((iconv_t)-1) == icd){
727 strcpy(cptr, "bbs=");
728 cptr += strlen(data);
729 if(!nt_conv_wc2sjis(icd, bbs, buf, sizeof(buf)))
733 strcpy(cptr, "&key=");
734 cptr += strlen(cptr);
735 if(!nt_conv_wc2sjis(icd, id, buf, sizeof(buf)))
739 strcpy(cptr, "&time=");
740 cptr += strlen(cptr);
741 sprintf(buf, "%ld&FROM=", t);
747 icd = iconv_open("cp932", "UTF-8");
748 if(icd == (iconv_t)-1){
753 if(name && 0 < strlen(name)){
754 if(!nt_conv_local2sjis(icd, name, buf, sizeof(buf)))
756 if(!url_encode(buf, buf2, sizeof(buf2)))
759 cptr += strlen(buf2);
761 strcpy(cptr, "&mail=");
762 cptr += strlen(cptr);
763 if(mail && 0 < strlen(mail)){
764 if(!nt_conv_local2sjis(icd, mail, buf, sizeof(buf)))
766 if(!url_encode(buf, buf2, sizeof(buf2)))
769 cptr += strlen(buf2);
771 strcpy(cptr, "&MESSAGE=");
772 cptr += strlen(cptr);
773 if(msg && 0 < strlen(msg)){
774 if(!nt_conv_local2sjis(icd, msg, buf, sizeof(buf)))
776 if(!url_encode(buf, buf2, sizeof(buf2)))
779 cptr += strlen(buf2);
781 strcpy(cptr, "&submit=%8F%91%82%AB%8D%9E%82%DE");
788 static BOOL set_post_data_machibbs(char *data, size_t data_len,
789 const wchar_t *bbs, const wchar_t *id,
790 const char *name, const char *mail,
798 assert(bbs && id && name && mail && msg);
800 memset(buf, 0, sizeof(buf));
801 memset(buf2, 0, sizeof(buf2));
803 icd = iconv_open("cp932", "wchar_t");
804 if(((iconv_t)-1) == icd){
811 strcpy(cptr, "BBS=");
812 cptr += strlen(data);
813 if(!nt_conv_wc2sjis(icd, bbs, buf, sizeof(buf)))
817 strcpy(cptr, "&KEY=");
818 cptr += strlen(cptr);
819 if(!nt_conv_wc2sjis(icd, id, buf, sizeof(buf)))
823 strcpy(cptr, "&TIME=");
824 cptr += strlen(cptr);
825 sprintf(buf, "%ld&NAME=", t);
831 icd = iconv_open("cp932", "UTF-8");
832 if(icd == (iconv_t)-1){
837 if(name && 0 < strlen(name)){
838 if(!nt_conv_local2sjis(icd, name, buf, sizeof(buf)))
840 if(!url_encode(buf, buf2, sizeof(buf2)))
843 cptr += strlen(buf2);
845 strcpy(cptr, "&MAIL=");
846 cptr += strlen(cptr);
847 if(mail && 0 < strlen(mail)){
848 if(!nt_conv_local2sjis(icd, mail, buf, sizeof(buf)))
850 if(!url_encode(buf, buf2, sizeof(buf2)))
853 cptr += strlen(buf2);
855 strcpy(cptr, "&MESSAGE=");
856 cptr += strlen(cptr);
857 if(msg && 0 < strlen(msg)){
858 if(!nt_conv_local2sjis(icd, msg, buf, sizeof(buf)))
860 if(!url_encode(buf, buf2, sizeof(buf2)))
863 cptr += strlen(buf2);
865 strcpy(cptr, "&submit=%8F%91%82%AB%8D%9E%82%DE");
872 static BOOL set_offlaw_address(char *buf, size_t buf_len,
873 wchar_t *server_name,
874 wchar_t * board_name, wchar_t *dat_name)
880 cptr = wcsstr(server_name, L".2ch.net");
883 cptr = wcsstr(dat_name, L".dat");
886 cptr = nt_rid_sufix(dat_name);
889 wcscpy(url, L"http://");
890 wcscat(url, server_name);
891 wcscat(url, L"/test/offlaw2.so?shiro=kuma&sid=ERROR&bbs=");
892 wcscat(url, board_name);
893 wcscat(url, L"&key=");
896 len = wcstombs(buf, url, buf_len-1);
902 int nt_read_board_list(nt_link_tp selitem_list)
904 nt_2ch_selected_item_handle h_select;
907 nt_pthread_handle h_pthread;
909 assert(selitem_list);
911 linkp = selitem_list;
913 h_select = (nt_2ch_selected_item_handle)linkp->data;
914 #ifdef NT_DISABLE_PTHREAD
915 if(nt_read_board(h_select))
918 nt_2ch_selected_item_add_ref(h_select);
919 h_pthread = nt_pthread_alloc(
922 nt_read_board_async_result);
924 nt_2ch_selected_item_release_ref(h_select);
925 }else if(!nt_pthread_put_que(h_pthread)){
926 nt_pthread_release_ref(h_pthread);
927 nt_2ch_selected_item_release_ref(h_select);
929 nt_pthread_release_ref(h_pthread);
934 }while(linkp != selitem_list);
938 static nt_pthread_result_t nt_read_board_async(void* data)
940 nt_2ch_selected_item_handle h_select;
941 nt_pthread_result_t result;
943 result.code = NT_PTHREAD_RESULT_NONE;
946 h_select = (nt_2ch_selected_item_handle)data;
947 nt_2ch_selected_item_add_ref(h_select);
948 nt_2ch_selected_item_release_ref(h_select);
950 if(nt_read_board(h_select)){
951 result.code = NT_PTHREAD_RESULT_UPDATE_BOARD;
953 nt_2ch_selected_item_release_ref(h_select);
957 static nt_pthread_result_t nt_read_board_async_result(
958 nt_pthread_result_t result)
963 BOOL nt_set_sel_item(nt_2ch_model_handle h_model,
964 nt_2ch_selected_item_handle *h_sel_itemp,
965 nt_searched_thread_handle h_searched_thread, const wchar_t** errorpp)
967 const wchar_t *board_name, *dat_name, *title;
968 nt_category_handle h_category;
969 nt_board_handle h_board;
970 nt_thread_handle h_thread;
971 nt_2ch_selected_item_handle h_sel_item;
972 nt_enum_handle h_enum;
976 h_sel_item = nt_2ch_selected_item_alloc();
980 board_name = nt_searched_thread_get_board_name(h_searched_thread);
983 dat_name = nt_searched_thread_get_dat_name(h_searched_thread);
984 title = nt_searched_thread_get_title(h_searched_thread);
986 h_board = nt_get_board_by_name(
987 h_model, board_name, &h_category);
988 if(!h_board || !h_category){
989 *errorpp = L"板情報が見つかりませんでした";
990 nt_2ch_selected_item_release_ref(h_sel_item);
993 nt_set_selected_board(h_sel_item, h_category, h_board);
996 h_enum = nt_board_get_thread_enum(h_board);
998 if(!nt_read_board(h_sel_item)){
999 *errorpp = L"板が開けませんでした";
1002 h_enum = nt_board_get_thread_enum(h_board);
1004 *errorpp = L"板が開けませんでした";
1009 nt_enum_unset(h_enum);
1012 nt_board_release_ref(h_board);
1013 nt_category_release_ref(h_category);
1014 *h_sel_itemp = h_sel_item;
1017 h_thread = nt_get_thread_by_dat_name(h_board, dat_name);
1021 h_thread = nt_thread_dummy_alloc(title, dat_name, 0);
1023 *errorpp = L"スレッド情報が見つかりませんでした";
1028 nt_set_selected_thread(h_sel_item, h_thread);
1029 nt_thread_release_ref(h_thread);
1031 if(!nt_read_thread(h_sel_item)){
1032 *errorpp = L"スレッドが開けませんでした";
1036 nt_board_release_ref(h_board);
1037 nt_category_release_ref(h_category);
1038 *h_sel_itemp = h_sel_item;
1041 nt_board_release_ref(h_board);
1042 nt_category_release_ref(h_category);
1043 nt_2ch_selected_item_release_ref(h_sel_item);