/* Copyright 2013 Akira Ohta (akohta001@gmail.com)
    This file is part of ntch.

    The ntch is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    The ntch is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ntch.  If not, see <http://www.gnu.org/licenses/>.
    
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <assert.h>
#include <wchar.h>
#include <iconv.h>
#include <errno.h>
#include <time.h>

#define MODEL_2CH_PRIVATE_DATA

#include "env.h"
#include "utils/nt_std_t.h"
#include "utils/nt_conv_char.h"
#include "utils/file.h"
#include "utils/base64.h"
#include "utils/nt_pthread.h"
#include "net/nt_http.h"
#include "net/nt_cookie.h"
#include "_2ch/model_2ch.h"
#include "_2ch/_2ch.h"

char *URL_2CH_BOARDMENU = "http://menu.2ch.net/bbsmenu.html";
nt_2ch_model_handle app_2ch_model;


#define S_SIZE  (1024*2)

static BOOL set_post_data(char *data, size_t data_len,
		const wchar_t *bbs, const wchar_t *id, 
		const char *name, const char *mail, 
		const char *msg);
static BOOL set_post_data_machibbs(char *data, size_t data_len,
		const wchar_t *bbs, const wchar_t *id, 
		const char *name, const char *mail, 
		const char *msg);
static BOOL set_offlaw_address(char *buf, size_t buf_len,
			wchar_t *server_name, 
			wchar_t * board_name, wchar_t *dat_name);
static BOOL nt_write_msg_machibbs(nt_2ch_selected_item_tp selectp,
			 nt_write_data_tp writep, nt_cookie_tp cookiep);

static nt_pthread_result_t nt_read_board_async(void* data);
static nt_pthread_result_t nt_read_board_async_result(
			nt_pthread_result_t result);

		    
BOOL nt_2ch_model_init(){
	app_2ch_model = nt_2ch_model_alloc();
	return (NULL != app_2ch_model);
}

BOOL nt_init_board_menu()
{
	char	*outp;
	char	*url = URL_2CH_BOARDMENU;
	iconv_t	icd;
	FILE	*fp_src;
	char	s_src[S_SIZE],	s_dst[S_SIZE*sizeof(wchar_t)];
	char	*p_src,	*p_dst;
	size_t	n_src,	n_dst;

	memset(s_src, '\0', S_SIZE);
	memset(s_dst, '\0', S_SIZE*sizeof(wchar_t));

	if(!nt_make_sha1_path(LOG_PATH, url, &outp)){
		return	FALSE;
	}


	if(!nt_http_get(url, outp, NULL, NULL, NULL, FALSE, FALSE)){
		free(outp);
		return FALSE;
	}

	fp_src	=	fopen(outp, "r");
	if(!fp_src){
		free(outp);
		return FALSE;
	}
	icd	=	iconv_open("wchar_t", "cp932");
	if(((iconv_t)-1) == icd){
		free(outp);
		return FALSE;
	}
	while(1){
		if(feof(fp_src))
			break;
		s_src[0] = '\0';
		if(!fgets(s_src, S_SIZE, fp_src))
			break;
		p_src = s_src;
		p_dst = s_dst;

		n_src	=	strlen(s_src);
		n_dst	=	S_SIZE-1;
		while(0	<	n_src){
			size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
			if(sz == -1){
				//fprintf(stderr, "errno: %d %s\n", errno, s_src);
				break;
			}
		}
		//*p_dst	=	'\0';
		*((wchar_t*)p_dst) = L'\0';
		parse_board_menu(app_2ch_model, (const wchar_t*)s_dst);
	}

	if(fp_src)
		fclose(fp_src);
	iconv_close(icd);

	free(outp);
	
	return TRUE;
}

static BOOL is_machibbs_address(const wchar_t *host_name)
{
	wchar_t *cptr;
	cptr = wcsstr(host_name, L".machi.to");
	return (cptr != NULL) ? TRUE : FALSE;
}

BOOL nt_read_thread(nt_2ch_selected_item_handle h_select)
{
	nt_2ch_selected_item_tp selectp;
	wchar_t url[1024];
	wchar_t referer[1024];
	wchar_t buf[1024];
	char	*outp;
	wchar_t *file_name, *cptr;
	wchar_t *server_name, *board_name;
	nt_board_tp boardp;
	nt_thread_tp threadp;
	int len;
	iconv_t icd;
	FILE	*fp_src;
	char	s_src[S_SIZE*sizeof(wchar_t)];
	char	s_dst[S_SIZE*sizeof(wchar_t)];
	char	*p_src,	*p_dst;
	size_t	n_src,	n_dst;
	BOOL is_matchi_bbs;
	
	assert(h_select);
	assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
	
	selectp = (nt_2ch_selected_item_tp)h_select;

	memset(s_src, '\0', sizeof(s_src));
	memset(s_dst, '\0', sizeof(s_dst));


	if(!selectp->selected_categoryp)
		return FALSE;
	if(!selectp->selected_boardp)
		return FALSE;
	if(!selectp->selected_threadp)
		return FALSE;

	boardp = selectp->selected_boardp;
	threadp = selectp->selected_threadp;
	file_name = threadp->file_name;


	if(!nt_parse_server_name_and_board_name(boardp->address,
		buf, sizeof(buf), &server_name, &board_name)){
		return FALSE;
	}
	if(is_machibbs_address(server_name)){
		is_matchi_bbs = TRUE;
		wcscpy(url, L"http://");
		wcscat(url, server_name);
		wcscat(url, L"/bbs/offlaw.cgi/");
		wcscat(url, board_name);
		wcscat(url, L"/");
		cptr = nt_rid_sufix(file_name);
		if(!cptr)
			return FALSE;
		wcscat(url, cptr);
		free(cptr);
		wcscat(url, L"/");
		
		wcscpy(referer, boardp->address);
		wcscat(referer, L"/");
	}else{
		is_matchi_bbs = FALSE;
		wcscpy(url, boardp->address);
		len = wcslen(url);
		if(len <= 0)
			return FALSE;
		if(url[len-1] != L'/'){
			url[len] = L'/';
			len++;
			url[len] = L'\0';
		}
		wcscat(url, L"dat/");
		wcscat(url, file_name);
		wcscpy(referer, L"http://");
		wcscat(referer, server_name);
		wcscat(referer, L"/test/read.cgi/");
		wcscat(referer, board_name);
		wcscat(referer, L"/");
		cptr = nt_rid_sufix(file_name);
		if(!cptr)
			return FALSE;
		wcscat(referer, cptr);
		free(cptr);
		wcscat(referer, L"/");
	}
	len = wcstombs(s_src, url, sizeof(s_src)-1);
	if(len <= 0)
		return FALSE;
	len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
	if(len <= 0)
		return FALSE;
	if(!nt_make_sha1_path(LOG_PATH, s_src, &outp)){
		return	FALSE;
	}

	if(!nt_http_get(s_src, outp, s_dst, NULL, NULL, TRUE, FALSE)){
		if(!set_offlaw_address(s_src, sizeof(s_src),
				server_name, board_name, file_name)){
			free(outp);
			return FALSE;
		}
		if(!nt_http_get(s_src, outp, s_dst, NULL, NULL, FALSE, FALSE)){
			free(outp);
			return FALSE;
		}
	}
	fp_src = fopen(outp, "r");
	if(!fp_src){
		free(outp);
		return FALSE;
	}
	icd	=	iconv_open("wchar_t", "cp932");
	if(((iconv_t)-1) == icd){
		fclose(fp_src);
		free(outp);
		return FALSE;
	}
	nt_thread_clear_children(&threadp->handle);
	threadp->num_res = 0;
	while(1){
		if(feof(fp_src))
			break;
		s_src[0] = '\0';
		if(!fgets(s_src, S_SIZE, fp_src))
			break;
		p_src = s_src;
		p_dst = s_dst;

		n_src	=	strlen(s_src);
		n_dst	=	sizeof(s_dst)-1;
		while(0	< n_src){
			size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
			if(sz == -1){
				//fprintf(stderr, "errno: %d %s\n", errno, s_src);
				break;
			}
		}
		*((wchar_t*)p_dst) = L'\0';
		if(!is_matchi_bbs)
			parse_thread(&threadp->handle, (const wchar_t*)s_dst);
		else
			parse_thread_machi_bbs(&threadp->handle, (const wchar_t*)s_dst);
	}

	fclose(fp_src);
	iconv_close(icd);
	free(outp);
	return (threadp->num_res > 0);
}

wchar_t* nt_read_thread_title(nt_board_handle h_board,
		const wchar_t *dat_name)
{
	nt_board_tp boardp;
	wchar_t url[1024];
	char	*outp;
	wchar_t *title;
	int len;
	iconv_t icd;
	FILE	*fp_src;
	char	s_src[S_SIZE*sizeof(wchar_t)];
	char	s_dst[S_SIZE*sizeof(wchar_t)];
	char	*p_src,	*p_dst;
	size_t	n_src,	n_dst;
	
	assert(h_board);
	assert(h_board->chk_sum == NT_2CH_BOARD_CHK_SUM);
	boardp = (nt_board_tp)h_board;

	memset(s_src, '\0', sizeof(s_src));
	memset(s_dst, '\0', sizeof(s_dst));
	title = NULL;

	wcscpy(url, boardp->address);
	len = wcslen(url);
	if(len <= 0)
		return NULL;
	if(url[len-1] != L'/'){
		url[len] = L'/';
		len++;
		url[len] = L'\0';
	}
	wcscat(url, L"dat/");
	wcscat(url, dat_name);


	len = wcstombs(s_src, url, sizeof(s_src)-1);
	if(len <= 0)
		return NULL;
	if(!nt_make_sha1_path(LOG_PATH, s_src, &outp)){
		return	NULL;
	}

	fp_src = fopen(outp, "r");
	if(!fp_src){
		free(outp);
		return NULL;
	}
	icd	=	iconv_open("wchar_t", "cp932");
	if(((iconv_t)-1) == icd){
		fclose(fp_src);
		free(outp);
		return NULL;
	}
	if(!feof(fp_src)){
		s_src[0] = '\0';
		if(!fgets(s_src, S_SIZE, fp_src)){
			iconv_close(icd);
			fclose(fp_src);
			free(outp);
			return NULL;
		}
		p_src = s_src;
		p_dst = s_dst;

		n_src	=	strlen(s_src);
		n_dst	=	sizeof(s_dst)-1;
		while(0	< n_src){
			size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
			if(sz == -1){
				//fprintf(stderr, "errno: %d %s\n", errno, s_src);
				break;
			}
		}
		*((wchar_t*)p_dst) = L'\0';
		title = parse_thread_title((const wchar_t*)s_dst);
	}
	fclose(fp_src);
	iconv_close(icd);
	free(outp);
	return title;
}

BOOL nt_read_board(nt_2ch_selected_item_handle h_select)
{
	nt_2ch_selected_item_tp selectp;
	wchar_t *address;
	char data[256+1];
	iconv_t icd;
	char *outp;
	int len;
	FILE	*fp_src;
	char	s_src[S_SIZE],	s_dst[S_SIZE*sizeof(wchar_t)];
	char	*p_src,	*p_dst;
	size_t	n_src,	n_dst;
	nt_board_tp boardp;
	nt_mutex_handle h_mutex;

	assert(h_select);
	assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
	
	selectp = (nt_2ch_selected_item_tp)h_select;
	
	memset(data, 0, sizeof(data));
	memset(s_src, '\0', S_SIZE);
	memset(s_dst, '\0', S_SIZE*sizeof(wchar_t));
	//fputs("enter nt_read_board\n",stderr);
	if(!selectp->selected_categoryp)
		return FALSE;
	if(!selectp->selected_boardp)
		return FALSE;
	
	boardp = selectp->selected_boardp;
	//fwprintf(stderr, L"%ls\n", boardp->name);
	h_mutex = nt_board_get_mutex(&boardp->handle);
	if(!h_mutex)
		return FALSE;
	if(!nt_mutex_lock(h_mutex))
		return FALSE;
	//fputs(" -- lock nt_read_board\n",stderr);

	nt_board_clear_children(&boardp->handle);
	address = boardp->address;
	assert(address);

	len = wcstombs(data, address, sizeof(data)-1);
	if(len <= 0){
		nt_mutex_unlock(h_mutex);
		return FALSE;
	}

	if(data[len-1] != '/')
		strcat(data, "/");
	strcat(data, "subject.txt");


	if(!nt_make_sha1_path(LOG_PATH, data, &outp)){
		nt_mutex_unlock(h_mutex);
		return	FALSE;
	}

	if(!nt_http_get(data, outp, URL_2CH_BOARDMENU, NULL, NULL, FALSE, FALSE)){
		free(outp);
		nt_mutex_unlock(h_mutex);
		return FALSE;
	}

	fp_src = fopen(outp, "r");
	if(!fp_src){
		free(outp);
		nt_mutex_unlock(h_mutex);
		return FALSE;
	}
	icd	=	iconv_open("wchar_t", "cp932");
	if(((iconv_t)-1) == icd){
		fclose(fp_src);
		free(outp);
		nt_mutex_unlock(h_mutex);
		return FALSE;
	}
	while(1){
		if(feof(fp_src))
			break;
		s_src[0] = '\0';
		if(!fgets(s_src, S_SIZE, fp_src))
			break;
		p_src = s_src;
		p_dst = s_dst;

		n_src	=	strlen(s_src);
		n_dst	=	(S_SIZE-1)*sizeof(wchar_t);
		while(0	<	n_src){
			size_t sz = iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
			if(sz == -1){
				//fprintf(stderr, "errno: %d %s\n", errno, s_src);
				break;
			}
		}
		*((wchar_t*)p_dst) = L'\0';
		if(!parse_board(&boardp->handle, (const wchar_t*)s_dst)){
		}
	}
	fclose(fp_src);
	iconv_close(icd);
	
	//fputs(" -- unlock nt_read_board\n",stderr);
	nt_mutex_unlock(h_mutex);
	//fputs("exit nt_read_board\n",stderr);
	free(outp);
	if(!boardp->threadlistp)
		return FALSE;
	return TRUE;
}

BOOL nt_write_msg(nt_2ch_selected_item_handle h_select, nt_write_data_handle h_write_data,
			nt_cookie_tp cookiep, nt_maru_2ch_tp marup)
{
	nt_2ch_selected_item_tp selectp;
	nt_write_data_tp writep;
	wchar_t	url[1024];	
	wchar_t	referer[1024];
	char	post_data[1024*4];
	wchar_t	buf[512];
	char	out_buf[1024*4];
	wchar_t	*dat_name;
	wchar_t	*file_name;
	wchar_t	*server_name,	*board_name;
	nt_board_tp	boardp;
	nt_thread_tp	threadp;
	int	len;
	char	s_src[S_SIZE*sizeof(wchar_t)];
	char	s_dst[S_SIZE*sizeof(wchar_t)];
	BOOL result = FALSE;
	iconv_t icd = 0;

	assert(h_select);
	assert(h_select->chk_sum == NT_2CH_SELECTED_ITEM_CHK_SUM);
	assert(h_write_data);
	assert(h_write_data->chk_sum == NT_2CH_WRITE_DATA_CHK_SUM);
	
	selectp = (nt_2ch_selected_item_tp)h_select;
	writep = (nt_write_data_tp)h_write_data;
	
	memset(s_src,	'\0',	sizeof(s_src));
	memset(s_dst,	'\0',	sizeof(s_dst));
	memset(post_data,	'\0',	sizeof(post_data));

	if(!selectp->selected_categoryp)
		return	FALSE;
	if(!selectp->selected_boardp)
		return	FALSE;
	if(!selectp->selected_threadp)
		return	FALSE;

	boardp = selectp->selected_boardp;
	threadp = selectp->selected_threadp;
	file_name = threadp->file_name;

	if(!nt_parse_server_name_and_board_name(boardp->address,
		buf, sizeof(buf), &server_name, &board_name)){
		return FALSE;
	}

	if(is_machibbs_address(server_name)){
		return nt_write_msg_machibbs(selectp, writep, cookiep);
	}
	
	wcscpy(url, L"http://");
	wcscat(url, server_name);
	wcscat(url, L"/test/bbs.cgi");
	
	wcscpy(referer, L"http://");
	wcscat(referer, server_name);
	wcscat(referer, L"/test/read.cgi/");
	wcscat(referer, board_name);
	wcscat(referer, L"/");
	dat_name = nt_rid_sufix(file_name);
	if(!dat_name)
		return FALSE;
	wcscat(referer, dat_name);
	wcscat(referer, L"/");

	len = wcstombs(s_src, url, sizeof(s_src)-1);
	if(len <= 0)
		goto ERROR_TRAP;
	len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
	if(len <= 0)
		goto ERROR_TRAP;
	if(!set_post_data(post_data, sizeof(post_data),
			board_name, dat_name, writep->name,
			writep->mail, writep->msg)){
		goto ERROR_TRAP;
	}
	strcat(post_data, "&yuki=akari");

	if(marup && marup->sid){
		strcat(post_data, "&sid=");
		strcat(post_data, marup->sid);
	}
	if(!nt_http_post(s_src, post_data, out_buf, sizeof(out_buf),
	            s_dst, NULL, NULL, cookiep)){
		goto ERROR_TRAP;
	}
	icd =   iconv_open("wchar_t", "cp932");
	if(((iconv_t)-1) == icd){
		icd = 0;
		goto ERROR_TRAP;
	}
	if(writep->result_html)
		free(writep->result_html);
	writep->result_html = malloc(1024*sizeof(wchar_t)*4);
	if(!writep->result_html)
		goto ERROR_TRAP;

	if(!nt_conv_sjis2wc(icd, out_buf, writep->result_html, 
				1024*sizeof(wchar_t)*4)){
		goto ERROR_TRAP;
	}
	result = TRUE;
ERROR_TRAP:
	if(icd)
		iconv_close(icd);
	free(dat_name);
	return (result);
}


static BOOL nt_write_msg_machibbs(nt_2ch_selected_item_tp selectp, 
			nt_write_data_tp writep, nt_cookie_tp cookiep)
{
	wchar_t	url[1024];	
	wchar_t	referer[1024];
	char	post_data[1024*4];
	wchar_t	buf[512];
	char	out_buf[1024*4];
	wchar_t	*dat_name;
	wchar_t	*file_name;
	wchar_t	*server_name,	*board_name;
	nt_board_tp	boardp;
	nt_thread_tp	threadp;
	int	len;
	char	s_src[S_SIZE*sizeof(wchar_t)];
	char	s_dst[S_SIZE*sizeof(wchar_t)];
	BOOL result = FALSE;
	iconv_t icd = 0;

	memset(s_src,	'\0',	sizeof(s_src));
	memset(s_dst,	'\0',	sizeof(s_dst));
	memset(post_data,	'\0',	sizeof(post_data));

	if(!selectp->selected_categoryp)
		return	FALSE;
	if(!selectp->selected_boardp)
		return	FALSE;
	if(!selectp->selected_threadp)
		return	FALSE;

	boardp = selectp->selected_boardp;
	threadp = selectp->selected_threadp;
	file_name = threadp->file_name;

	if(!nt_parse_server_name_and_board_name(boardp->address,
		buf, sizeof(buf), &server_name, &board_name)){
		return FALSE;
	}

	
	wcscpy(url, L"http://");
	wcscat(url, server_name);
	wcscat(url, L"/bbs/write.cgi");
	dat_name = nt_rid_sufix(file_name);
	if(!dat_name)
		return FALSE;
	
	wcscpy(referer, boardp->address);

	len = wcstombs(s_src, url, sizeof(s_src)-1);
	if(len <= 0)
		goto ERROR_TRAP;
	len = wcstombs(s_dst, referer, sizeof(s_dst)-1);
	if(len <= 0)
		goto ERROR_TRAP;
	if(!set_post_data_machibbs(post_data, sizeof(post_data),
			board_name, dat_name, writep->name,
			writep->mail, writep->msg)){
		goto ERROR_TRAP;
	}
	len = wcstombs(s_src, url, sizeof(s_src)-1);
	if(len <= 0)
		goto ERROR_TRAP;
	strcat(post_data, "&CC=%82%A0");
	
	if(!nt_http_post(s_src, post_data, out_buf, sizeof(out_buf),
	            s_dst, NULL, NULL, cookiep)){
		goto ERROR_TRAP;
	}
	icd =   iconv_open("wchar_t", "cp932");
	if(((iconv_t)-1) == icd){
		icd = 0;
		goto ERROR_TRAP;
	}
	if(writep->result_html)
		free(writep->result_html);
	writep->result_html = malloc(1024*sizeof(wchar_t)*4);
	if(!writep->result_html)
		goto ERROR_TRAP;

	if(!nt_conv_sjis2wc(icd, out_buf, writep->result_html, 
				1024*sizeof(wchar_t)*4)){
		goto ERROR_TRAP;
	}
	result = TRUE;
ERROR_TRAP:
	if(icd)
		iconv_close(icd);
	free(dat_name);
	return (result);
}



static BOOL set_post_data(char *data, size_t data_len,
		const wchar_t *bbs, const wchar_t *id, 
		const char *name, const char *mail, 
		const char *msg)
{
	iconv_t icd;
	time_t t;
	char buf[1024*4];
	char buf2[1024*4];
	char *cptr;
	assert(bbs && id && name && mail && msg);

	memset(buf, 0, sizeof(buf));
	memset(buf2, 0, sizeof(buf2));

	icd =   iconv_open("cp932", "wchar_t");
	if(((iconv_t)-1) == icd){
	    return FALSE;
	}
	t =  time(NULL);
	t -= 600;

	cptr = data;
	strcpy(cptr, "bbs=");
	cptr += strlen(data);
	if(!nt_conv_wc2sjis(icd, bbs, buf, sizeof(buf)))
		return FALSE;
	strcpy(cptr, buf);
	cptr+= strlen(cptr);
	strcpy(cptr, "&key=");
	cptr += strlen(cptr);
	if(!nt_conv_wc2sjis(icd, id, buf, sizeof(buf)))
		return FALSE;
	strcpy(cptr, buf);
	cptr+= strlen(cptr);
	strcpy(cptr, "&time=");
	cptr += strlen(cptr);
	sprintf(buf, "%ld&FROM=", t);
	strcpy(cptr, buf);
	cptr+= strlen(cptr);

	iconv_close(icd);

	icd =   iconv_open("cp932", "UTF-8");
	if(icd == (iconv_t)-1){
		perror("e");
		return FALSE;
	}

	if(name && 0 < strlen(name)){
		if(!nt_conv_local2sjis(icd, name, buf, sizeof(buf)))
			return FALSE;
		if(!url_encode(buf, buf2, sizeof(buf2)))
			return FALSE;
		strcpy(cptr, buf2);
		cptr += strlen(buf2);
	}
	strcpy(cptr, "&mail=");
	cptr += strlen(cptr);
	if(mail && 0 < strlen(mail)){
		if(!nt_conv_local2sjis(icd, mail, buf, sizeof(buf)))
			return FALSE;
		if(!url_encode(buf, buf2, sizeof(buf2)))
			return FALSE;
		strcpy(cptr, buf2);
		cptr += strlen(buf2);
	}
	strcpy(cptr, "&MESSAGE=");
	cptr += strlen(cptr);
	if(msg && 0 < strlen(msg)){
		if(!nt_conv_local2sjis(icd, msg, buf, sizeof(buf)))
			return FALSE;
		if(!url_encode(buf, buf2, sizeof(buf2)))
			return FALSE;
		strcpy(cptr, buf2);
		cptr += strlen(buf2);
	}
	strcpy(cptr, "&submit=%8F%91%82%AB%8D%9E%82%DE");

	iconv_close(icd);
	
	return TRUE;
}

static BOOL set_post_data_machibbs(char *data, size_t data_len,
		const wchar_t *bbs, const wchar_t *id, 
		const char *name, const char *mail, 
		const char *msg)
{
	iconv_t icd;
	time_t t;
	char buf[1024*4];
	char buf2[1024*4];
	char *cptr;
	assert(bbs && id && name && mail && msg);

	memset(buf, 0, sizeof(buf));
	memset(buf2, 0, sizeof(buf2));

	icd =   iconv_open("cp932", "wchar_t");
	if(((iconv_t)-1) == icd){
	    return FALSE;
	}
	t =  time(NULL);
	t -= 600;

	cptr = data;
	strcpy(cptr, "BBS=");
	cptr += strlen(data);
	if(!nt_conv_wc2sjis(icd, bbs, buf, sizeof(buf)))
		return FALSE;
	strcpy(cptr, buf);
	cptr+= strlen(cptr);
	strcpy(cptr, "&KEY=");
	cptr += strlen(cptr);
	if(!nt_conv_wc2sjis(icd, id, buf, sizeof(buf)))
		return FALSE;
	strcpy(cptr, buf);
	cptr+= strlen(cptr);
	strcpy(cptr, "&TIME=");
	cptr += strlen(cptr);
	sprintf(buf, "%ld&NAME=", t);
	strcpy(cptr, buf);
	cptr+= strlen(cptr);

	iconv_close(icd);

	icd =   iconv_open("cp932", "UTF-8");
	if(icd == (iconv_t)-1){
		perror("e");
		return FALSE;
	}

	if(name && 0 < strlen(name)){
		if(!nt_conv_local2sjis(icd, name, buf, sizeof(buf)))
			return FALSE;
		if(!url_encode(buf, buf2, sizeof(buf2)))
			return FALSE;
		strcpy(cptr, buf2);
		cptr += strlen(buf2);
	}
	strcpy(cptr, "&MAIL=");
	cptr += strlen(cptr);
	if(mail && 0 < strlen(mail)){
		if(!nt_conv_local2sjis(icd, mail, buf, sizeof(buf)))
			return FALSE;
		if(!url_encode(buf, buf2, sizeof(buf2)))
			return FALSE;
		strcpy(cptr, buf2);
		cptr += strlen(buf2);
	}
	strcpy(cptr, "&MESSAGE=");
	cptr += strlen(cptr);
	if(msg && 0 < strlen(msg)){
		if(!nt_conv_local2sjis(icd, msg, buf, sizeof(buf)))
			return FALSE;
		if(!url_encode(buf, buf2, sizeof(buf2)))
			return FALSE;
		strcpy(cptr, buf2);
		cptr += strlen(buf2);
	}
	strcpy(cptr, "&submit=%8F%91%82%AB%8D%9E%82%DE");

	iconv_close(icd);
	
	return TRUE;
}

static BOOL set_offlaw_address(char *buf, size_t buf_len,
			wchar_t *server_name, 
			wchar_t * board_name, wchar_t *dat_name)
{
	wchar_t *cptr;
	int len;
	wchar_t url[512];

	cptr = wcsstr(server_name, L".2ch.net");
	if(!cptr)
		return FALSE;
	cptr = wcsstr(dat_name, L".dat");
	if(!cptr)
		return FALSE;
	cptr = nt_rid_sufix(dat_name);
	if(!cptr)
		return FALSE;
	wcscpy(url, L"http://");
	wcscat(url, server_name);
	wcscat(url, L"/test/offlaw2.so?shiro=kuma&sid=ERROR&bbs=");
	wcscat(url, board_name);
	wcscat(url, L"&key=");
	wcscat(url, cptr);
	free(cptr);
	len = wcstombs(buf, url, buf_len-1);
	if(len <= 0)
		return FALSE;
	return TRUE;
}

int nt_read_board_list(nt_link_tp selitem_list)
{
	nt_2ch_selected_item_handle h_select;
	nt_link_tp linkp;
	int num_success;
	nt_pthread_handle h_pthread;
	
	assert(selitem_list);
	num_success = 0;
	linkp = selitem_list;
	do{
		h_select = (nt_2ch_selected_item_handle)linkp->data;
#ifdef NT_DISABLE_PTHREAD
		if(nt_read_board(h_select))
			num_success++;
#else
		nt_2ch_selected_item_add_ref(h_select);
		h_pthread = nt_pthread_alloc(
				nt_read_board_async,
				h_select,
				nt_read_board_async_result);
		if(!h_pthread){
			nt_2ch_selected_item_release_ref(h_select);
		}else if(!nt_pthread_put_que(h_pthread)){
			nt_pthread_release_ref(h_pthread);
			nt_2ch_selected_item_release_ref(h_select);
		}else{
			nt_pthread_release_ref(h_pthread);
			num_success++;
		}
#endif
		linkp = linkp->next;
	}while(linkp != selitem_list);
	return num_success;
}

static nt_pthread_result_t nt_read_board_async(void* data)
{
	nt_2ch_selected_item_handle h_select;
	nt_pthread_result_t result;
	
	result.code = NT_PTHREAD_RESULT_NONE;
	result.data = NULL;
	
	h_select = (nt_2ch_selected_item_handle)data;
	nt_2ch_selected_item_add_ref(h_select);
	nt_2ch_selected_item_release_ref(h_select);
	
	if(nt_read_board(h_select)){
		result.code = NT_PTHREAD_RESULT_UPDATE_BOARD;
	}
	nt_2ch_selected_item_release_ref(h_select);
	return result;
}

static nt_pthread_result_t nt_read_board_async_result(
			nt_pthread_result_t result)
{
	return result;
}

BOOL nt_set_sel_item(nt_2ch_model_handle h_model,
			nt_2ch_selected_item_handle *h_sel_itemp, 
			nt_searched_thread_handle h_searched_thread, const wchar_t** errorpp)
{
	const wchar_t *board_name, *dat_name, *title;
	nt_category_handle h_category;
	nt_board_handle h_board;
	nt_thread_handle h_thread;
	nt_2ch_selected_item_handle h_sel_item;
	nt_enum_handle h_enum;
	
	assert(h_sel_itemp);
	
	h_sel_item = nt_2ch_selected_item_alloc();
	if(!h_sel_item){
		return FALSE;
	}
	board_name = nt_searched_thread_get_board_name(h_searched_thread);
	assert(board_name);
	
	dat_name = nt_searched_thread_get_dat_name(h_searched_thread);
	title = nt_searched_thread_get_title(h_searched_thread);
	
	h_board = nt_get_board_by_name(
			h_model, board_name, &h_category);
	if(!h_board || !h_category){
		*errorpp = L"板情報が見つかりませんでした";
		nt_2ch_selected_item_release_ref(h_sel_item);
		return FALSE;
	}
	nt_set_selected_board(h_sel_item, h_category, h_board);
	
	
	h_enum = nt_board_get_thread_enum(h_board);
	if(!h_enum){
		if(!nt_read_board(h_sel_item)){
			*errorpp = L"板が開けませんでした";
			goto ERROR_TRAP;
		}
		h_enum = nt_board_get_thread_enum(h_board);
		if(!h_enum){
			*errorpp = L"板が開けませんでした";
			goto ERROR_TRAP;
		}
	}
	
	nt_enum_unset(h_enum);
	
	if(!dat_name){
		nt_board_release_ref(h_board);
		nt_category_release_ref(h_category);
		*h_sel_itemp = h_sel_item;
		return TRUE;
	}
	h_thread = nt_get_thread_by_dat_name(h_board, dat_name);
	if(!h_thread){
		if(!title)
			title = L"Dummy";
		h_thread = nt_thread_dummy_alloc(title, dat_name, 0);
		if(!h_thread){
			*errorpp = L"スレッド情報が見つかりませんでした";
			goto ERROR_TRAP;
		}
	}
	
	nt_set_selected_thread(h_sel_item, h_thread);
	nt_thread_release_ref(h_thread);
	
	if(!nt_read_thread(h_sel_item)){
		*errorpp = L"スレッドが開けませんでした";
		goto ERROR_TRAP;
	}
	
	nt_board_release_ref(h_board);
	nt_category_release_ref(h_category);
	*h_sel_itemp = h_sel_item;
	return TRUE;
ERROR_TRAP:
	nt_board_release_ref(h_board);
	nt_category_release_ref(h_category);
	nt_2ch_selected_item_release_ref(h_sel_item);
	return FALSE;
}

