OSDN Git Service

avoid having multiple connections to a single host.
[ntch/develop.git] / src / _2ch / _2ch.c
1 /* Copyright 2013 Akira Ohta (akohta001@gmail.com)
2     This file is part of ntch.
3
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.
8
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.
13
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/>.
16     
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <locale.h>
22 #include <assert.h>
23 #include <wchar.h>
24 #include <iconv.h>
25 #include <errno.h>
26 #include <time.h>
27
28 #define MODEL_2CH_PRIVATE_DATA
29
30 #include "env.h"
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"
40
41 char *URL_2CH_BOARDMENU = "http://menu.2ch.net/bbsmenu.html";
42 nt_2ch_model_handle app_2ch_model;
43
44
45 #define S_SIZE  (1024*2)
46
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, 
50                 const char *msg);
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, 
54                 const char *msg);
55 static BOOL set_offlaw_address(char *buf, size_t buf_len,
56                         wchar_t *server_name, 
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);
60
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);
64
65                     
66 BOOL nt_2ch_model_init(){
67         app_2ch_model = nt_2ch_model_alloc();
68         return (NULL != app_2ch_model);
69 }
70
71 BOOL nt_init_board_menu()
72 {
73         char    *outp;
74         char    *url = URL_2CH_BOARDMENU;
75         iconv_t icd;
76         FILE    *fp_src;
77         char    s_src[S_SIZE],  s_dst[S_SIZE*sizeof(wchar_t)];
78         char    *p_src, *p_dst;
79         size_t  n_src,  n_dst;
80
81         memset(s_src, '\0', S_SIZE);
82         memset(s_dst, '\0', S_SIZE*sizeof(wchar_t));
83
84         if(!nt_make_sha1_path(LOG_PATH, url, &outp)){
85                 return  FALSE;
86         }
87
88
89         if(!nt_http_get(url, outp, NULL, NULL, NULL, FALSE, FALSE)){
90                 free(outp);
91                 return FALSE;
92         }
93
94         fp_src  =       fopen(outp, "r");
95         if(!fp_src){
96                 free(outp);
97                 return FALSE;
98         }
99         icd     =       iconv_open("wchar_t", "cp932");
100         if(((iconv_t)-1) == icd){
101                 free(outp);
102                 return FALSE;
103         }
104         while(1){
105                 if(feof(fp_src))
106                         break;
107                 s_src[0] = '\0';
108                 if(!fgets(s_src, S_SIZE, fp_src))
109                         break;
110                 p_src = s_src;
111                 p_dst = s_dst;
112
113                 n_src   =       strlen(s_src);
114                 n_dst   =       S_SIZE-1;
115                 while(0 <       n_src){
116                         size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
117                         if(sz == -1){
118                                 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
119                                 break;
120                         }
121                 }
122                 //*p_dst        =       '\0';
123                 *((wchar_t*)p_dst) = L'\0';
124                 parse_board_menu(app_2ch_model, (const wchar_t*)s_dst);
125         }
126
127         if(fp_src)
128                 fclose(fp_src);
129         iconv_close(icd);
130
131         free(outp);
132         
133         return TRUE;
134 }
135
136 static BOOL is_machibbs_address(const wchar_t *host_name)
137 {
138         wchar_t *cptr;
139         cptr = wcsstr(host_name, L".machi.to");
140         return (cptr != NULL) ? TRUE : FALSE;
141 }
142
143 BOOL nt_read_thread(nt_2ch_selected_item_handle h_select)
144 {
145         nt_2ch_selected_item_tp selectp;
146         wchar_t url[1024];
147         wchar_t referer[1024];
148         wchar_t buf[1024];
149         char    *outp;
150         wchar_t *file_name, *cptr;
151         wchar_t *server_name, *board_name;
152         nt_board_tp boardp;
153         nt_thread_tp threadp;
154         int len;
155         iconv_t icd;
156         FILE    *fp_src;
157         char    s_src[S_SIZE*sizeof(wchar_t)];
158         char    s_dst[S_SIZE*sizeof(wchar_t)];
159         char    *p_src, *p_dst;
160         size_t  n_src,  n_dst;
161         BOOL is_matchi_bbs;
162         
163         assert(h_select);
164         assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
165         
166         selectp = (nt_2ch_selected_item_tp)h_select;
167
168         memset(s_src, '\0', sizeof(s_src));
169         memset(s_dst, '\0', sizeof(s_dst));
170
171
172         if(!selectp->selected_categoryp)
173                 return FALSE;
174         if(!selectp->selected_boardp)
175                 return FALSE;
176         if(!selectp->selected_threadp)
177                 return FALSE;
178
179         boardp = selectp->selected_boardp;
180         threadp = selectp->selected_threadp;
181         file_name = threadp->file_name;
182
183
184         if(!nt_parse_server_name_and_board_name(boardp->address,
185                 buf, sizeof(buf), &server_name, &board_name)){
186                 return FALSE;
187         }
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);
194                 wcscat(url, L"/");
195                 cptr = nt_rid_sufix(file_name);
196                 if(!cptr)
197                         return FALSE;
198                 wcscat(url, cptr);
199                 free(cptr);
200                 wcscat(url, L"/");
201                 
202                 wcscpy(referer, boardp->address);
203                 wcscat(referer, L"/");
204         }else{
205                 is_matchi_bbs = FALSE;
206                 wcscpy(url, boardp->address);
207                 len = wcslen(url);
208                 if(len <= 0)
209                         return FALSE;
210                 if(url[len-1] != L'/'){
211                         url[len] = L'/';
212                         len++;
213                         url[len] = L'\0';
214                 }
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);
223                 if(!cptr)
224                         return FALSE;
225                 wcscat(referer, cptr);
226                 free(cptr);
227                 wcscat(referer, L"/");
228         }
229         len = wcstombs(s_src, url, sizeof(s_src)-1);
230         if(len <= 0)
231                 return FALSE;
232         len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
233         if(len <= 0)
234                 return FALSE;
235         if(!nt_make_sha1_path(LOG_PATH, s_src, &outp)){
236                 return  FALSE;
237         }
238
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)){
242                         free(outp);
243                         return FALSE;
244                 }
245                 if(!nt_http_get(s_src, outp, s_dst, NULL, NULL, FALSE, FALSE)){
246                         free(outp);
247                         return FALSE;
248                 }
249         }
250         fp_src = fopen(outp, "r");
251         if(!fp_src){
252                 free(outp);
253                 return FALSE;
254         }
255         icd     =       iconv_open("wchar_t", "cp932");
256         if(((iconv_t)-1) == icd){
257                 fclose(fp_src);
258                 free(outp);
259                 return FALSE;
260         }
261         nt_thread_clear_children(&threadp->handle);
262         threadp->num_res = 0;
263         while(1){
264                 if(feof(fp_src))
265                         break;
266                 s_src[0] = '\0';
267                 if(!fgets(s_src, S_SIZE, fp_src))
268                         break;
269                 p_src = s_src;
270                 p_dst = s_dst;
271
272                 n_src   =       strlen(s_src);
273                 n_dst   =       sizeof(s_dst)-1;
274                 while(0 < n_src){
275                         size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
276                         if(sz == -1){
277                                 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
278                                 break;
279                         }
280                 }
281                 *((wchar_t*)p_dst) = L'\0';
282                 if(!is_matchi_bbs)
283                         parse_thread(&threadp->handle, (const wchar_t*)s_dst);
284                 else
285                         parse_thread_machi_bbs(&threadp->handle, (const wchar_t*)s_dst);
286         }
287
288         fclose(fp_src);
289         iconv_close(icd);
290         free(outp);
291         return (threadp->num_res > 0);
292 }
293
294 wchar_t* nt_read_thread_title(nt_board_handle h_board,
295                 const wchar_t *dat_name)
296 {
297         nt_board_tp boardp;
298         wchar_t url[1024];
299         char    *outp;
300         wchar_t *title;
301         int len;
302         iconv_t icd;
303         FILE    *fp_src;
304         char    s_src[S_SIZE*sizeof(wchar_t)];
305         char    s_dst[S_SIZE*sizeof(wchar_t)];
306         char    *p_src, *p_dst;
307         size_t  n_src,  n_dst;
308         
309         assert(h_board);
310         assert(h_board->chk_sum == NT_2CH_BOARD_CHK_SUM);
311         boardp = (nt_board_tp)h_board;
312
313         memset(s_src, '\0', sizeof(s_src));
314         memset(s_dst, '\0', sizeof(s_dst));
315         title = NULL;
316
317         wcscpy(url, boardp->address);
318         len = wcslen(url);
319         if(len <= 0)
320                 return NULL;
321         if(url[len-1] != L'/'){
322                 url[len] = L'/';
323                 len++;
324                 url[len] = L'\0';
325         }
326         wcscat(url, L"dat/");
327         wcscat(url, dat_name);
328
329
330         len = wcstombs(s_src, url, sizeof(s_src)-1);
331         if(len <= 0)
332                 return NULL;
333         if(!nt_make_sha1_path(LOG_PATH, s_src, &outp)){
334                 return  NULL;
335         }
336
337         fp_src = fopen(outp, "r");
338         if(!fp_src){
339                 free(outp);
340                 return NULL;
341         }
342         icd     =       iconv_open("wchar_t", "cp932");
343         if(((iconv_t)-1) == icd){
344                 fclose(fp_src);
345                 free(outp);
346                 return NULL;
347         }
348         if(!feof(fp_src)){
349                 s_src[0] = '\0';
350                 if(!fgets(s_src, S_SIZE, fp_src)){
351                         iconv_close(icd);
352                         fclose(fp_src);
353                         free(outp);
354                         return NULL;
355                 }
356                 p_src = s_src;
357                 p_dst = s_dst;
358
359                 n_src   =       strlen(s_src);
360                 n_dst   =       sizeof(s_dst)-1;
361                 while(0 < n_src){
362                         size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
363                         if(sz == -1){
364                                 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
365                                 break;
366                         }
367                 }
368                 *((wchar_t*)p_dst) = L'\0';
369                 title = parse_thread_title((const wchar_t*)s_dst);
370         }
371         fclose(fp_src);
372         iconv_close(icd);
373         free(outp);
374         return title;
375 }
376
377 BOOL nt_read_board(nt_2ch_selected_item_handle h_select)
378 {
379         nt_2ch_selected_item_tp selectp;
380         wchar_t *address;
381         char data[256+1];
382         iconv_t icd;
383         char *outp;
384         int len;
385         FILE    *fp_src;
386         char    s_src[S_SIZE],  s_dst[S_SIZE*sizeof(wchar_t)];
387         char    *p_src, *p_dst;
388         size_t  n_src,  n_dst;
389         nt_board_tp boardp;
390         nt_mutex_handle h_mutex;
391
392         assert(h_select);
393         assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
394         
395         selectp = (nt_2ch_selected_item_tp)h_select;
396         
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)
402                 return FALSE;
403         if(!selectp->selected_boardp)
404                 return FALSE;
405         
406         boardp = selectp->selected_boardp;
407         //fwprintf(stderr, L"%ls\n", boardp->name);
408         h_mutex = nt_board_get_mutex(&boardp->handle);
409         if(!h_mutex)
410                 return FALSE;
411         if(!nt_mutex_lock(h_mutex))
412                 return FALSE;
413         //fputs(" -- lock nt_read_board\n",stderr);
414
415         nt_board_clear_children(&boardp->handle);
416         address = boardp->address;
417         assert(address);
418
419         len = wcstombs(data, address, sizeof(data)-1);
420         if(len <= 0){
421                 nt_mutex_unlock(h_mutex);
422                 return FALSE;
423         }
424
425         if(data[len-1] != '/')
426                 strcat(data, "/");
427         strcat(data, "subject.txt");
428
429
430         if(!nt_make_sha1_path(LOG_PATH, data, &outp)){
431                 nt_mutex_unlock(h_mutex);
432                 return  FALSE;
433         }
434
435         if(!nt_http_get(data, outp, URL_2CH_BOARDMENU, NULL, NULL, FALSE, FALSE)){
436                 free(outp);
437                 nt_mutex_unlock(h_mutex);
438                 return FALSE;
439         }
440
441         fp_src = fopen(outp, "r");
442         if(!fp_src){
443                 free(outp);
444                 nt_mutex_unlock(h_mutex);
445                 return FALSE;
446         }
447         icd     =       iconv_open("wchar_t", "cp932");
448         if(((iconv_t)-1) == icd){
449                 fclose(fp_src);
450                 free(outp);
451                 nt_mutex_unlock(h_mutex);
452                 return FALSE;
453         }
454         while(1){
455                 if(feof(fp_src))
456                         break;
457                 s_src[0] = '\0';
458                 if(!fgets(s_src, S_SIZE, fp_src))
459                         break;
460                 p_src = s_src;
461                 p_dst = s_dst;
462
463                 n_src   =       strlen(s_src);
464                 n_dst   =       (S_SIZE-1)*sizeof(wchar_t);
465                 while(0 <       n_src){
466                         size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
467                         if(sz == -1){
468                                 //fprintf(stderr, "errno: %d %s\n", errno, s_src);
469                                 break;
470                         }
471                 }
472                 *((wchar_t*)p_dst) = L'\0';
473                 if(!parse_board(&boardp->handle, (const wchar_t*)s_dst)){
474                 }
475         }
476         fclose(fp_src);
477         iconv_close(icd);
478         
479         //fputs(" -- unlock nt_read_board\n",stderr);
480         nt_mutex_unlock(h_mutex);
481         //fputs("exit nt_read_board\n",stderr);
482         free(outp);
483         if(!boardp->threadlistp)
484                 return FALSE;
485         return TRUE;
486 }
487
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)
490 {
491         nt_2ch_selected_item_tp selectp;
492         nt_write_data_tp writep;
493         wchar_t url[1024];      
494         wchar_t referer[1024];
495         char    post_data[1024*4];
496         wchar_t buf[512];
497         char    out_buf[1024*4];
498         wchar_t *dat_name;
499         wchar_t *file_name;
500         wchar_t *server_name,   *board_name;
501         nt_board_tp     boardp;
502         nt_thread_tp    threadp;
503         int     len;
504         char    s_src[S_SIZE*sizeof(wchar_t)];
505         char    s_dst[S_SIZE*sizeof(wchar_t)];
506         BOOL result = FALSE;
507         iconv_t icd = 0;
508
509         assert(h_select);
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);
513         
514         selectp = (nt_2ch_selected_item_tp)h_select;
515         writep = (nt_write_data_tp)h_write_data;
516         
517         memset(s_src,   '\0',   sizeof(s_src));
518         memset(s_dst,   '\0',   sizeof(s_dst));
519         memset(post_data,       '\0',   sizeof(post_data));
520
521         if(!selectp->selected_categoryp)
522                 return  FALSE;
523         if(!selectp->selected_boardp)
524                 return  FALSE;
525         if(!selectp->selected_threadp)
526                 return  FALSE;
527
528         boardp = selectp->selected_boardp;
529         threadp = selectp->selected_threadp;
530         file_name = threadp->file_name;
531
532         if(!nt_parse_server_name_and_board_name(boardp->address,
533                 buf, sizeof(buf), &server_name, &board_name)){
534                 return FALSE;
535         }
536
537         if(is_machibbs_address(server_name)){
538                 return nt_write_msg_machibbs(selectp, writep, cookiep);
539         }
540         
541         wcscpy(url, L"http://");
542         wcscat(url, server_name);
543         wcscat(url, L"/test/bbs.cgi");
544         
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);
551         if(!dat_name)
552                 return FALSE;
553         wcscat(referer, dat_name);
554         wcscat(referer, L"/");
555
556         len = wcstombs(s_src, url, sizeof(s_src)-1);
557         if(len <= 0)
558                 goto ERROR_TRAP;
559         len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
560         if(len <= 0)
561                 goto ERROR_TRAP;
562         if(!set_post_data(post_data, sizeof(post_data),
563                         board_name, dat_name, writep->name,
564                         writep->mail, writep->msg)){
565                 goto ERROR_TRAP;
566         }
567         strcat(post_data, "&yuki=akari");
568
569         if(marup && marup->sid){
570                 strcat(post_data, "&sid=");
571                 strcat(post_data, marup->sid);
572         }
573         if(!nt_http_post(s_src, post_data, out_buf, sizeof(out_buf),
574                     s_dst, NULL, NULL, cookiep)){
575                 goto ERROR_TRAP;
576         }
577         icd =   iconv_open("wchar_t", "cp932");
578         if(((iconv_t)-1) == icd){
579                 icd = 0;
580                 goto ERROR_TRAP;
581         }
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)
586                 goto ERROR_TRAP;
587
588         if(!nt_conv_sjis2wc(icd, out_buf, writep->result_html, 
589                                 1024*sizeof(wchar_t)*4)){
590                 goto ERROR_TRAP;
591         }
592         result = TRUE;
593 ERROR_TRAP:
594         if(icd)
595                 iconv_close(icd);
596         free(dat_name);
597         return (result);
598 }
599
600
601 static BOOL nt_write_msg_machibbs(nt_2ch_selected_item_tp selectp, 
602                         nt_write_data_tp writep, nt_cookie_tp cookiep)
603 {
604         wchar_t url[1024];      
605         wchar_t referer[1024];
606         char    post_data[1024*4];
607         wchar_t buf[512];
608         char    out_buf[1024*4];
609         wchar_t *dat_name;
610         wchar_t *file_name;
611         wchar_t *server_name,   *board_name;
612         nt_board_tp     boardp;
613         nt_thread_tp    threadp;
614         int     len;
615         char    s_src[S_SIZE*sizeof(wchar_t)];
616         char    s_dst[S_SIZE*sizeof(wchar_t)];
617         BOOL result = FALSE;
618         iconv_t icd = 0;
619
620         memset(s_src,   '\0',   sizeof(s_src));
621         memset(s_dst,   '\0',   sizeof(s_dst));
622         memset(post_data,       '\0',   sizeof(post_data));
623
624         if(!selectp->selected_categoryp)
625                 return  FALSE;
626         if(!selectp->selected_boardp)
627                 return  FALSE;
628         if(!selectp->selected_threadp)
629                 return  FALSE;
630
631         boardp = selectp->selected_boardp;
632         threadp = selectp->selected_threadp;
633         file_name = threadp->file_name;
634
635         if(!nt_parse_server_name_and_board_name(boardp->address,
636                 buf, sizeof(buf), &server_name, &board_name)){
637                 return FALSE;
638         }
639
640         
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);
645         if(!dat_name)
646                 return FALSE;
647         
648         wcscpy(referer, boardp->address);
649
650         len = wcstombs(s_src, url, sizeof(s_src)-1);
651         if(len <= 0)
652                 goto ERROR_TRAP;
653         len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
654         if(len <= 0)
655                 goto ERROR_TRAP;
656         if(!set_post_data_machibbs(post_data, sizeof(post_data),
657                         board_name, dat_name, writep->name,
658                         writep->mail, writep->msg)){
659                 goto ERROR_TRAP;
660         }
661         len = wcstombs(s_src, url, sizeof(s_src)-1);
662         if(len <= 0)
663                 goto ERROR_TRAP;
664         strcat(post_data, "&CC=%82%A0");
665         
666         if(!nt_http_post(s_src, post_data, out_buf, sizeof(out_buf),
667                     s_dst, NULL, NULL, cookiep)){
668                 goto ERROR_TRAP;
669         }
670         icd =   iconv_open("wchar_t", "cp932");
671         if(((iconv_t)-1) == icd){
672                 icd = 0;
673                 goto ERROR_TRAP;
674         }
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)
679                 goto ERROR_TRAP;
680
681         if(!nt_conv_sjis2wc(icd, out_buf, writep->result_html, 
682                                 1024*sizeof(wchar_t)*4)){
683                 goto ERROR_TRAP;
684         }
685         result = TRUE;
686 ERROR_TRAP:
687         if(icd)
688                 iconv_close(icd);
689         free(dat_name);
690         return (result);
691 }
692
693
694
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, 
698                 const char *msg)
699 {
700         iconv_t icd;
701         time_t t;
702         char buf[1024*4];
703         char buf2[1024*4];
704         char *cptr;
705         assert(bbs && id && name && mail && msg);
706
707         memset(buf, 0, sizeof(buf));
708         memset(buf2, 0, sizeof(buf2));
709
710         icd =   iconv_open("cp932", "wchar_t");
711         if(((iconv_t)-1) == icd){
712             return FALSE;
713         }
714         t =  time(NULL);
715         t -= 600;
716
717         cptr = data;
718         strcpy(cptr, "bbs=");
719         cptr += strlen(data);
720         if(!nt_conv_wc2sjis(icd, bbs, buf, sizeof(buf)))
721                 return FALSE;
722         strcpy(cptr, buf);
723         cptr+= strlen(cptr);
724         strcpy(cptr, "&key=");
725         cptr += strlen(cptr);
726         if(!nt_conv_wc2sjis(icd, id, buf, sizeof(buf)))
727                 return FALSE;
728         strcpy(cptr, buf);
729         cptr+= strlen(cptr);
730         strcpy(cptr, "&time=");
731         cptr += strlen(cptr);
732         sprintf(buf, "%ld&FROM=", t);
733         strcpy(cptr, buf);
734         cptr+= strlen(cptr);
735
736         iconv_close(icd);
737
738         icd =   iconv_open("cp932", "UTF-8");
739         if(icd == (iconv_t)-1){
740                 perror("e");
741                 return FALSE;
742         }
743
744         if(name && 0 < strlen(name)){
745                 if(!nt_conv_local2sjis(icd, name, buf, sizeof(buf)))
746                         return FALSE;
747                 if(!url_encode(buf, buf2, sizeof(buf2)))
748                         return FALSE;
749                 strcpy(cptr, buf2);
750                 cptr += strlen(buf2);
751         }
752         strcpy(cptr, "&mail=");
753         cptr += strlen(cptr);
754         if(mail && 0 < strlen(mail)){
755                 if(!nt_conv_local2sjis(icd, mail, buf, sizeof(buf)))
756                         return FALSE;
757                 if(!url_encode(buf, buf2, sizeof(buf2)))
758                         return FALSE;
759                 strcpy(cptr, buf2);
760                 cptr += strlen(buf2);
761         }
762         strcpy(cptr, "&MESSAGE=");
763         cptr += strlen(cptr);
764         if(msg && 0 < strlen(msg)){
765                 if(!nt_conv_local2sjis(icd, msg, buf, sizeof(buf)))
766                         return FALSE;
767                 if(!url_encode(buf, buf2, sizeof(buf2)))
768                         return FALSE;
769                 strcpy(cptr, buf2);
770                 cptr += strlen(buf2);
771         }
772         strcpy(cptr, "&submit=%8F%91%82%AB%8D%9E%82%DE");
773
774         iconv_close(icd);
775         
776         return TRUE;
777 }
778
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, 
782                 const char *msg)
783 {
784         iconv_t icd;
785         time_t t;
786         char buf[1024*4];
787         char buf2[1024*4];
788         char *cptr;
789         assert(bbs && id && name && mail && msg);
790
791         memset(buf, 0, sizeof(buf));
792         memset(buf2, 0, sizeof(buf2));
793
794         icd =   iconv_open("cp932", "wchar_t");
795         if(((iconv_t)-1) == icd){
796             return FALSE;
797         }
798         t =  time(NULL);
799         t -= 600;
800
801         cptr = data;
802         strcpy(cptr, "BBS=");
803         cptr += strlen(data);
804         if(!nt_conv_wc2sjis(icd, bbs, buf, sizeof(buf)))
805                 return FALSE;
806         strcpy(cptr, buf);
807         cptr+= strlen(cptr);
808         strcpy(cptr, "&KEY=");
809         cptr += strlen(cptr);
810         if(!nt_conv_wc2sjis(icd, id, buf, sizeof(buf)))
811                 return FALSE;
812         strcpy(cptr, buf);
813         cptr+= strlen(cptr);
814         strcpy(cptr, "&TIME=");
815         cptr += strlen(cptr);
816         sprintf(buf, "%ld&NAME=", t);
817         strcpy(cptr, buf);
818         cptr+= strlen(cptr);
819
820         iconv_close(icd);
821
822         icd =   iconv_open("cp932", "UTF-8");
823         if(icd == (iconv_t)-1){
824                 perror("e");
825                 return FALSE;
826         }
827
828         if(name && 0 < strlen(name)){
829                 if(!nt_conv_local2sjis(icd, name, buf, sizeof(buf)))
830                         return FALSE;
831                 if(!url_encode(buf, buf2, sizeof(buf2)))
832                         return FALSE;
833                 strcpy(cptr, buf2);
834                 cptr += strlen(buf2);
835         }
836         strcpy(cptr, "&MAIL=");
837         cptr += strlen(cptr);
838         if(mail && 0 < strlen(mail)){
839                 if(!nt_conv_local2sjis(icd, mail, buf, sizeof(buf)))
840                         return FALSE;
841                 if(!url_encode(buf, buf2, sizeof(buf2)))
842                         return FALSE;
843                 strcpy(cptr, buf2);
844                 cptr += strlen(buf2);
845         }
846         strcpy(cptr, "&MESSAGE=");
847         cptr += strlen(cptr);
848         if(msg && 0 < strlen(msg)){
849                 if(!nt_conv_local2sjis(icd, msg, buf, sizeof(buf)))
850                         return FALSE;
851                 if(!url_encode(buf, buf2, sizeof(buf2)))
852                         return FALSE;
853                 strcpy(cptr, buf2);
854                 cptr += strlen(buf2);
855         }
856         strcpy(cptr, "&submit=%8F%91%82%AB%8D%9E%82%DE");
857
858         iconv_close(icd);
859         
860         return TRUE;
861 }
862
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)
866 {
867         wchar_t *cptr;
868         int len;
869         wchar_t url[512];
870
871         cptr = wcsstr(server_name, L".2ch.net");
872         if(!cptr)
873                 return FALSE;
874         cptr = wcsstr(dat_name, L".dat");
875         if(!cptr)
876                 return FALSE;
877         cptr = nt_rid_sufix(dat_name);
878         if(!cptr)
879                 return FALSE;
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=");
885         wcscat(url, cptr);
886         free(cptr);
887         len = wcstombs(buf, url, buf_len-1);
888         if(len <= 0)
889                 return FALSE;
890         return TRUE;
891 }
892
893 int nt_read_board_list(nt_link_tp selitem_list)
894 {
895         nt_2ch_selected_item_handle h_select;
896         nt_link_tp linkp;
897         int num_success;
898         nt_pthread_handle h_pthread;
899         
900         assert(selitem_list);
901         num_success = 0;
902         linkp = selitem_list;
903         do{
904                 h_select = (nt_2ch_selected_item_handle)linkp->data;
905 #ifdef NT_DISABLE_PTHREAD
906                 if(nt_read_board(h_select))
907                         num_success++;
908 #else
909                 nt_2ch_selected_item_add_ref(h_select);
910                 h_pthread = nt_pthread_alloc(
911                                 nt_read_board_async,
912                                 h_select,
913                                 nt_read_board_async_result);
914                 if(!h_pthread){
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);
919                 }else{
920                         nt_pthread_release_ref(h_pthread);
921                         num_success++;
922                 }
923 #endif
924                 linkp = linkp->next;
925         }while(linkp != selitem_list);
926         return num_success;
927 }
928
929 static nt_pthread_result_t nt_read_board_async(void* data)
930 {
931         nt_2ch_selected_item_handle h_select;
932         nt_pthread_result_t result;
933         
934         result.code = NT_PTHREAD_RESULT_NONE;
935         result.data = NULL;
936         
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);
940         
941         if(nt_read_board(h_select)){
942                 result.code = NT_PTHREAD_RESULT_UPDATE_BOARD;
943         }
944         nt_2ch_selected_item_release_ref(h_select);
945         return result;
946 }
947
948 static nt_pthread_result_t nt_read_board_async_result(
949                         nt_pthread_result_t result)
950 {
951         return result;
952 }
953
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)
957 {
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;
964         
965         assert(h_sel_itemp);
966         
967         h_sel_item = nt_2ch_selected_item_alloc();
968         if(!h_sel_item){
969                 return FALSE;
970         }
971         board_name = nt_searched_thread_get_board_name(h_searched_thread);
972         assert(board_name);
973         
974         dat_name = nt_searched_thread_get_dat_name(h_searched_thread);
975         title = nt_searched_thread_get_title(h_searched_thread);
976         
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);
982                 return FALSE;
983         }
984         nt_set_selected_board(h_sel_item, h_category, h_board);
985         
986         
987         h_enum = nt_board_get_thread_enum(h_board);
988         if(!h_enum){
989                 if(!nt_read_board(h_sel_item)){
990                         *errorpp = L"板が開けませんでした";
991                         goto ERROR_TRAP;
992                 }
993                 h_enum = nt_board_get_thread_enum(h_board);
994                 if(!h_enum){
995                         *errorpp = L"板が開けませんでした";
996                         goto ERROR_TRAP;
997                 }
998         }
999         
1000         nt_enum_unset(h_enum);
1001         
1002         if(!dat_name){
1003                 nt_board_release_ref(h_board);
1004                 nt_category_release_ref(h_category);
1005                 *h_sel_itemp = h_sel_item;
1006                 return TRUE;
1007         }
1008         h_thread = nt_get_thread_by_dat_name(h_board, dat_name);
1009         if(!h_thread){
1010                 if(!title)
1011                         title = L"Dummy";
1012                 h_thread = nt_thread_dummy_alloc(title, dat_name, 0);
1013                 if(!h_thread){
1014                         *errorpp = L"スレッド情報が見つかりませんでした";
1015                         goto ERROR_TRAP;
1016                 }
1017         }
1018         
1019         nt_set_selected_thread(h_sel_item, h_thread);
1020         nt_thread_release_ref(h_thread);
1021         
1022         if(!nt_read_thread(h_sel_item)){
1023                 *errorpp = L"スレッドが開けませんでした";
1024                 goto ERROR_TRAP;
1025         }
1026         
1027         nt_board_release_ref(h_board);
1028         nt_category_release_ref(h_category);
1029         *h_sel_itemp = h_sel_item;
1030         return TRUE;
1031 ERROR_TRAP:
1032         nt_board_release_ref(h_board);
1033         nt_category_release_ref(h_category);
1034         nt_2ch_selected_item_release_ref(h_sel_item);
1035         return FALSE;
1036 }
1037