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 "net/nt_http.h"
37 #include "net/nt_cookie.h"
38 #include "_2ch/model_2ch.h"
39 #include "_2ch/_2ch.h"
41 char *URL_2CH_BOARDMENU = "http://menu.2ch.net/bbsmenu.html";
42 nt_2ch_model_handle app_2ch_model;
45 #define S_SIZE (1024*2)
47 static BOOL set_post_data(char *data, size_t data_len,
48 const wchar_t *bbs, const wchar_t *id,
49 const char *name, const char *mail,
51 static BOOL set_post_data_machibbs(char *data, size_t data_len,
52 const wchar_t *bbs, const wchar_t *id,
53 const char *name, const char *mail,
55 static BOOL set_offlaw_address(char *buf, size_t buf_len,
57 wchar_t * board_name, wchar_t *dat_name);
58 static BOOL nt_write_msg_machibbs(nt_2ch_selected_item_tp selectp,
59 nt_write_data_tp writep, nt_cookie_tp cookiep);
61 static nt_pthread_result_t nt_read_board_async(void* data);
62 static nt_pthread_result_t nt_read_board_async_result(
63 nt_pthread_result_t result);
66 BOOL nt_2ch_model_init(){
67 app_2ch_model = nt_2ch_model_alloc();
68 return (NULL != app_2ch_model);
71 BOOL nt_init_board_menu()
74 char *url = URL_2CH_BOARDMENU;
77 char s_src[S_SIZE], s_dst[S_SIZE*sizeof(wchar_t)];
81 memset(s_src, '\0', S_SIZE);
82 memset(s_dst, '\0', S_SIZE*sizeof(wchar_t));
84 if(!nt_make_sha1_path(LOG_PATH, url, &outp)){
89 if(!nt_http_get(url, outp, NULL, NULL, NULL, FALSE, FALSE)){
94 fp_src = fopen(outp, "r");
99 icd = iconv_open("wchar_t", "cp932");
100 if(((iconv_t)-1) == icd){
108 if(!fgets(s_src, S_SIZE, fp_src))
113 n_src = strlen(s_src);
116 size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
118 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
123 *((wchar_t*)p_dst) = L'\0';
124 parse_board_menu(app_2ch_model, (const wchar_t*)s_dst);
136 static BOOL is_machibbs_address(const wchar_t *host_name)
139 cptr = wcsstr(host_name, L".machi.to");
140 return (cptr != NULL) ? TRUE : FALSE;
143 BOOL nt_read_thread(nt_2ch_selected_item_handle h_select)
145 nt_2ch_selected_item_tp selectp;
147 wchar_t referer[1024];
150 wchar_t *file_name, *cptr;
151 wchar_t *server_name, *board_name;
153 nt_thread_tp threadp;
157 char s_src[S_SIZE*sizeof(wchar_t)];
158 char s_dst[S_SIZE*sizeof(wchar_t)];
164 assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
166 selectp = (nt_2ch_selected_item_tp)h_select;
168 memset(s_src, '\0', sizeof(s_src));
169 memset(s_dst, '\0', sizeof(s_dst));
172 if(!selectp->selected_categoryp)
174 if(!selectp->selected_boardp)
176 if(!selectp->selected_threadp)
179 boardp = selectp->selected_boardp;
180 threadp = selectp->selected_threadp;
181 file_name = threadp->file_name;
184 if(!nt_parse_server_name_and_board_name(boardp->address,
185 buf, sizeof(buf), &server_name, &board_name)){
188 if(is_machibbs_address(server_name)){
189 is_matchi_bbs = TRUE;
190 wcscpy(url, L"http://");
191 wcscat(url, server_name);
192 wcscat(url, L"/bbs/offlaw.cgi/");
193 wcscat(url, board_name);
195 cptr = nt_rid_sufix(file_name);
202 wcscpy(referer, boardp->address);
203 wcscat(referer, L"/");
205 is_matchi_bbs = FALSE;
206 wcscpy(url, boardp->address);
210 if(url[len-1] != L'/'){
215 wcscat(url, L"dat/");
216 wcscat(url, file_name);
217 wcscpy(referer, L"http://");
218 wcscat(referer, server_name);
219 wcscat(referer, L"/test/read.cgi/");
220 wcscat(referer, board_name);
221 wcscat(referer, L"/");
222 cptr = nt_rid_sufix(file_name);
225 wcscat(referer, cptr);
227 wcscat(referer, L"/");
229 len = wcstombs(s_src, url, sizeof(s_src)-1);
232 len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
235 if(!nt_make_sha1_path(LOG_PATH, s_src, &outp)){
239 if(!nt_http_get(s_src, outp, s_dst, NULL, NULL, TRUE, FALSE)){
240 if(!set_offlaw_address(s_src, sizeof(s_src),
241 server_name, board_name, file_name)){
245 if(!nt_http_get(s_src, outp, s_dst, NULL, NULL, FALSE, FALSE)){
250 fp_src = fopen(outp, "r");
255 icd = iconv_open("wchar_t", "cp932");
256 if(((iconv_t)-1) == icd){
261 nt_thread_clear_children(&threadp->handle);
262 threadp->num_res = 0;
267 if(!fgets(s_src, S_SIZE, fp_src))
272 n_src = strlen(s_src);
273 n_dst = sizeof(s_dst)-1;
275 size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
277 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
281 *((wchar_t*)p_dst) = L'\0';
283 parse_thread(&threadp->handle, (const wchar_t*)s_dst);
285 parse_thread_machi_bbs(&threadp->handle, (const wchar_t*)s_dst);
291 return (threadp->num_res > 0);
294 wchar_t* nt_read_thread_title(nt_board_handle h_board,
295 const wchar_t *dat_name)
304 char s_src[S_SIZE*sizeof(wchar_t)];
305 char s_dst[S_SIZE*sizeof(wchar_t)];
310 assert(h_board->chk_sum == NT_2CH_BOARD_CHK_SUM);
311 boardp = (nt_board_tp)h_board;
313 memset(s_src, '\0', sizeof(s_src));
314 memset(s_dst, '\0', sizeof(s_dst));
317 wcscpy(url, boardp->address);
321 if(url[len-1] != L'/'){
326 wcscat(url, L"dat/");
327 wcscat(url, dat_name);
330 len = wcstombs(s_src, url, sizeof(s_src)-1);
333 if(!nt_make_sha1_path(LOG_PATH, s_src, &outp)){
337 fp_src = fopen(outp, "r");
342 icd = iconv_open("wchar_t", "cp932");
343 if(((iconv_t)-1) == icd){
350 if(!fgets(s_src, S_SIZE, fp_src)){
359 n_src = strlen(s_src);
360 n_dst = sizeof(s_dst)-1;
362 size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
364 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
368 *((wchar_t*)p_dst) = L'\0';
369 title = parse_thread_title((const wchar_t*)s_dst);
377 BOOL nt_read_board(nt_2ch_selected_item_handle h_select)
379 nt_2ch_selected_item_tp selectp;
386 char s_src[S_SIZE], s_dst[S_SIZE*sizeof(wchar_t)];
390 nt_mutex_handle h_mutex;
393 assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
395 selectp = (nt_2ch_selected_item_tp)h_select;
397 memset(data, 0, sizeof(data));
398 memset(s_src, '\0', S_SIZE);
399 memset(s_dst, '\0', S_SIZE*sizeof(wchar_t));
400 //fputs("enter nt_read_board\n",stderr);
401 if(!selectp->selected_categoryp)
403 if(!selectp->selected_boardp)
406 boardp = selectp->selected_boardp;
407 //fwprintf(stderr, L"%ls\n", boardp->name);
408 h_mutex = nt_board_get_mutex(&boardp->handle);
411 if(!nt_mutex_lock(h_mutex))
413 //fputs(" -- lock nt_read_board\n",stderr);
415 nt_board_clear_children(&boardp->handle);
416 address = boardp->address;
419 len = wcstombs(data, address, sizeof(data)-1);
421 nt_mutex_unlock(h_mutex);
425 if(data[len-1] != '/')
427 strcat(data, "subject.txt");
430 if(!nt_make_sha1_path(LOG_PATH, data, &outp)){
431 nt_mutex_unlock(h_mutex);
435 if(!nt_http_get(data, outp, URL_2CH_BOARDMENU, NULL, NULL, FALSE, FALSE)){
437 nt_mutex_unlock(h_mutex);
441 fp_src = fopen(outp, "r");
444 nt_mutex_unlock(h_mutex);
447 icd = iconv_open("wchar_t", "cp932");
448 if(((iconv_t)-1) == icd){
451 nt_mutex_unlock(h_mutex);
458 if(!fgets(s_src, S_SIZE, fp_src))
463 n_src = strlen(s_src);
464 n_dst = (S_SIZE-1)*sizeof(wchar_t);
466 size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
468 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
472 *((wchar_t*)p_dst) = L'\0';
473 if(!parse_board(&boardp->handle, (const wchar_t*)s_dst)){
479 //fputs(" -- unlock nt_read_board\n",stderr);
480 nt_mutex_unlock(h_mutex);
481 //fputs("exit nt_read_board\n",stderr);
483 if(!boardp->threadlistp)
488 BOOL nt_write_msg(nt_2ch_selected_item_handle h_select, nt_write_data_handle h_write_data,
489 nt_cookie_tp cookiep, nt_maru_2ch_tp marup)
491 nt_2ch_selected_item_tp selectp;
492 nt_write_data_tp writep;
494 wchar_t referer[1024];
495 char post_data[1024*4];
497 char out_buf[1024*4];
500 wchar_t *server_name, *board_name;
502 nt_thread_tp threadp;
504 char s_src[S_SIZE*sizeof(wchar_t)];
505 char s_dst[S_SIZE*sizeof(wchar_t)];
510 assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
511 assert(h_write_data);
512 assert(h_write_data->chk_sum == NT_2CH_WRITE_DATA_CHK_SUM);
514 selectp = (nt_2ch_selected_item_tp)h_select;
515 writep = (nt_write_data_tp)h_write_data;
517 memset(s_src, '\0', sizeof(s_src));
518 memset(s_dst, '\0', sizeof(s_dst));
519 memset(post_data, '\0', sizeof(post_data));
521 if(!selectp->selected_categoryp)
523 if(!selectp->selected_boardp)
525 if(!selectp->selected_threadp)
528 boardp = selectp->selected_boardp;
529 threadp = selectp->selected_threadp;
530 file_name = threadp->file_name;
532 if(!nt_parse_server_name_and_board_name(boardp->address,
533 buf, sizeof(buf), &server_name, &board_name)){
537 if(is_machibbs_address(server_name)){
538 return nt_write_msg_machibbs(selectp, writep, cookiep);
541 wcscpy(url, L"http://");
542 wcscat(url, server_name);
543 wcscat(url, L"/test/bbs.cgi");
545 wcscpy(referer, L"http://");
546 wcscat(referer, server_name);
547 wcscat(referer, L"/test/read.cgi/");
548 wcscat(referer, board_name);
549 wcscat(referer, L"/");
550 dat_name = nt_rid_sufix(file_name);
553 wcscat(referer, dat_name);
554 wcscat(referer, L"/");
556 len = wcstombs(s_src, url, sizeof(s_src)-1);
559 len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
562 if(!set_post_data(post_data, sizeof(post_data),
563 board_name, dat_name, writep->name,
564 writep->mail, writep->msg)){
567 strcat(post_data, "&yuki=akari");
569 if(marup && marup->sid){
570 strcat(post_data, "&sid=");
571 strcat(post_data, marup->sid);
573 if(!nt_http_post(s_src, post_data, out_buf, sizeof(out_buf),
574 s_dst, NULL, NULL, cookiep)){
577 icd = iconv_open("wchar_t", "cp932");
578 if(((iconv_t)-1) == icd){
582 if(writep->result_html)
583 free(writep->result_html);
584 writep->result_html = malloc(1024*sizeof(wchar_t)*4);
585 if(!writep->result_html)
588 if(!nt_conv_sjis2wc(icd, out_buf, writep->result_html,
589 1024*sizeof(wchar_t)*4)){
601 static BOOL nt_write_msg_machibbs(nt_2ch_selected_item_tp selectp,
602 nt_write_data_tp writep, nt_cookie_tp cookiep)
605 wchar_t referer[1024];
606 char post_data[1024*4];
608 char out_buf[1024*4];
611 wchar_t *server_name, *board_name;
613 nt_thread_tp threadp;
615 char s_src[S_SIZE*sizeof(wchar_t)];
616 char s_dst[S_SIZE*sizeof(wchar_t)];
620 memset(s_src, '\0', sizeof(s_src));
621 memset(s_dst, '\0', sizeof(s_dst));
622 memset(post_data, '\0', sizeof(post_data));
624 if(!selectp->selected_categoryp)
626 if(!selectp->selected_boardp)
628 if(!selectp->selected_threadp)
631 boardp = selectp->selected_boardp;
632 threadp = selectp->selected_threadp;
633 file_name = threadp->file_name;
635 if(!nt_parse_server_name_and_board_name(boardp->address,
636 buf, sizeof(buf), &server_name, &board_name)){
641 wcscpy(url, L"http://");
642 wcscat(url, server_name);
643 wcscat(url, L"/bbs/write.cgi");
644 dat_name = nt_rid_sufix(file_name);
648 wcscpy(referer, boardp->address);
650 len = wcstombs(s_src, url, sizeof(s_src)-1);
653 len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
656 if(!set_post_data_machibbs(post_data, sizeof(post_data),
657 board_name, dat_name, writep->name,
658 writep->mail, writep->msg)){
661 len = wcstombs(s_src, url, sizeof(s_src)-1);
664 strcat(post_data, "&CC=%82%A0");
666 if(!nt_http_post(s_src, post_data, out_buf, sizeof(out_buf),
667 s_dst, NULL, NULL, cookiep)){
670 icd = iconv_open("wchar_t", "cp932");
671 if(((iconv_t)-1) == icd){
675 if(writep->result_html)
676 free(writep->result_html);
677 writep->result_html = malloc(1024*sizeof(wchar_t)*4);
678 if(!writep->result_html)
681 if(!nt_conv_sjis2wc(icd, out_buf, writep->result_html,
682 1024*sizeof(wchar_t)*4)){
695 static BOOL set_post_data(char *data, size_t data_len,
696 const wchar_t *bbs, const wchar_t *id,
697 const char *name, const char *mail,
705 assert(bbs && id && name && mail && msg);
707 memset(buf, 0, sizeof(buf));
708 memset(buf2, 0, sizeof(buf2));
710 icd = iconv_open("cp932", "wchar_t");
711 if(((iconv_t)-1) == icd){
718 strcpy(cptr, "bbs=");
719 cptr += strlen(data);
720 if(!nt_conv_wc2sjis(icd, bbs, buf, sizeof(buf)))
724 strcpy(cptr, "&key=");
725 cptr += strlen(cptr);
726 if(!nt_conv_wc2sjis(icd, id, buf, sizeof(buf)))
730 strcpy(cptr, "&time=");
731 cptr += strlen(cptr);
732 sprintf(buf, "%ld&FROM=", t);
738 icd = iconv_open("cp932", "UTF-8");
739 if(icd == (iconv_t)-1){
744 if(name && 0 < strlen(name)){
745 if(!nt_conv_local2sjis(icd, name, buf, sizeof(buf)))
747 if(!url_encode(buf, buf2, sizeof(buf2)))
750 cptr += strlen(buf2);
752 strcpy(cptr, "&mail=");
753 cptr += strlen(cptr);
754 if(mail && 0 < strlen(mail)){
755 if(!nt_conv_local2sjis(icd, mail, buf, sizeof(buf)))
757 if(!url_encode(buf, buf2, sizeof(buf2)))
760 cptr += strlen(buf2);
762 strcpy(cptr, "&MESSAGE=");
763 cptr += strlen(cptr);
764 if(msg && 0 < strlen(msg)){
765 if(!nt_conv_local2sjis(icd, msg, buf, sizeof(buf)))
767 if(!url_encode(buf, buf2, sizeof(buf2)))
770 cptr += strlen(buf2);
772 strcpy(cptr, "&submit=%8F%91%82%AB%8D%9E%82%DE");
779 static BOOL set_post_data_machibbs(char *data, size_t data_len,
780 const wchar_t *bbs, const wchar_t *id,
781 const char *name, const char *mail,
789 assert(bbs && id && name && mail && msg);
791 memset(buf, 0, sizeof(buf));
792 memset(buf2, 0, sizeof(buf2));
794 icd = iconv_open("cp932", "wchar_t");
795 if(((iconv_t)-1) == icd){
802 strcpy(cptr, "BBS=");
803 cptr += strlen(data);
804 if(!nt_conv_wc2sjis(icd, bbs, buf, sizeof(buf)))
808 strcpy(cptr, "&KEY=");
809 cptr += strlen(cptr);
810 if(!nt_conv_wc2sjis(icd, id, buf, sizeof(buf)))
814 strcpy(cptr, "&TIME=");
815 cptr += strlen(cptr);
816 sprintf(buf, "%ld&NAME=", t);
822 icd = iconv_open("cp932", "UTF-8");
823 if(icd == (iconv_t)-1){
828 if(name && 0 < strlen(name)){
829 if(!nt_conv_local2sjis(icd, name, buf, sizeof(buf)))
831 if(!url_encode(buf, buf2, sizeof(buf2)))
834 cptr += strlen(buf2);
836 strcpy(cptr, "&MAIL=");
837 cptr += strlen(cptr);
838 if(mail && 0 < strlen(mail)){
839 if(!nt_conv_local2sjis(icd, mail, buf, sizeof(buf)))
841 if(!url_encode(buf, buf2, sizeof(buf2)))
844 cptr += strlen(buf2);
846 strcpy(cptr, "&MESSAGE=");
847 cptr += strlen(cptr);
848 if(msg && 0 < strlen(msg)){
849 if(!nt_conv_local2sjis(icd, msg, buf, sizeof(buf)))
851 if(!url_encode(buf, buf2, sizeof(buf2)))
854 cptr += strlen(buf2);
856 strcpy(cptr, "&submit=%8F%91%82%AB%8D%9E%82%DE");
863 static BOOL set_offlaw_address(char *buf, size_t buf_len,
864 wchar_t *server_name,
865 wchar_t * board_name, wchar_t *dat_name)
871 cptr = wcsstr(server_name, L".2ch.net");
874 cptr = wcsstr(dat_name, L".dat");
877 cptr = nt_rid_sufix(dat_name);
880 wcscpy(url, L"http://");
881 wcscat(url, server_name);
882 wcscat(url, L"/test/offlaw2.so?shiro=kuma&sid=ERROR&bbs=");
883 wcscat(url, board_name);
884 wcscat(url, L"&key=");
887 len = wcstombs(buf, url, buf_len-1);
893 int nt_read_board_list(nt_link_tp selitem_list)
895 nt_2ch_selected_item_handle h_select;
898 nt_pthread_handle h_pthread;
900 assert(selitem_list);
902 linkp = selitem_list;
904 h_select = (nt_2ch_selected_item_handle)linkp->data;
905 #ifdef NT_DISABLE_PTHREAD
906 if(nt_read_board(h_select))
909 nt_2ch_selected_item_add_ref(h_select);
910 h_pthread = nt_pthread_alloc(
913 nt_read_board_async_result);
915 nt_2ch_selected_item_release_ref(h_select);
916 }else if(!nt_pthread_put_que(h_pthread)){
917 nt_pthread_release_ref(h_pthread);
918 nt_2ch_selected_item_release_ref(h_select);
920 nt_pthread_release_ref(h_pthread);
925 }while(linkp != selitem_list);
929 static nt_pthread_result_t nt_read_board_async(void* data)
931 nt_2ch_selected_item_handle h_select;
932 nt_pthread_result_t result;
934 result.code = NT_PTHREAD_RESULT_NONE;
937 h_select = (nt_2ch_selected_item_handle)data;
938 nt_2ch_selected_item_add_ref(h_select);
939 nt_2ch_selected_item_release_ref(h_select);
941 if(nt_read_board(h_select)){
942 result.code = NT_PTHREAD_RESULT_UPDATE_BOARD;
944 nt_2ch_selected_item_release_ref(h_select);
948 static nt_pthread_result_t nt_read_board_async_result(
949 nt_pthread_result_t result)
954 BOOL nt_set_sel_item(nt_2ch_model_handle h_model,
955 nt_2ch_selected_item_handle *h_sel_itemp,
956 nt_searched_thread_handle h_searched_thread, const wchar_t** errorpp)
958 const wchar_t *board_name, *dat_name, *title;
959 nt_category_handle h_category;
960 nt_board_handle h_board;
961 nt_thread_handle h_thread;
962 nt_2ch_selected_item_handle h_sel_item;
963 nt_enum_handle h_enum;
967 h_sel_item = nt_2ch_selected_item_alloc();
971 board_name = nt_searched_thread_get_board_name(h_searched_thread);
974 dat_name = nt_searched_thread_get_dat_name(h_searched_thread);
975 title = nt_searched_thread_get_title(h_searched_thread);
977 h_board = nt_get_board_by_name(
978 h_model, board_name, &h_category);
979 if(!h_board || !h_category){
980 *errorpp = L"板情報が見つかりませんでした";
981 nt_2ch_selected_item_release_ref(h_sel_item);
984 nt_set_selected_board(h_sel_item, h_category, h_board);
987 h_enum = nt_board_get_thread_enum(h_board);
989 if(!nt_read_board(h_sel_item)){
990 *errorpp = L"板が開けませんでした";
993 h_enum = nt_board_get_thread_enum(h_board);
995 *errorpp = L"板が開けませんでした";
1000 nt_enum_unset(h_enum);
1003 nt_board_release_ref(h_board);
1004 nt_category_release_ref(h_category);
1005 *h_sel_itemp = h_sel_item;
1008 h_thread = nt_get_thread_by_dat_name(h_board, dat_name);
1012 h_thread = nt_thread_dummy_alloc(title, dat_name, 0);
1014 *errorpp = L"スレッド情報が見つかりませんでした";
1019 nt_set_selected_thread(h_sel_item, h_thread);
1020 nt_thread_release_ref(h_thread);
1022 if(!nt_read_thread(h_sel_item)){
1023 *errorpp = L"スレッドが開けませんでした";
1027 nt_board_release_ref(h_board);
1028 nt_category_release_ref(h_category);
1029 *h_sel_itemp = h_sel_item;
1032 nt_board_release_ref(h_board);
1033 nt_category_release_ref(h_category);
1034 nt_2ch_selected_item_release_ref(h_sel_item);