/*
    mod_bbs Multi Thread BBS Engine
    Copyright (C)2003 1000GEX Project 1000gex@1000gex.net
*/

/* メインルーチン */
int bbs_post(bbs_t *bbs, request_rec *r)
{
    post_init(bbs, r);
    //post_auth(&bbs);
    post_dat(bbs, r);
    post_subject(bbs, r);
    post_back(bbs,r);
    return 0;
}

/* 投稿処理 */
int post_init(bbs_t *bbs,request_rec *r)
{
    int i;
    char *out;
    table *param;
    time_t t;
    struct tm *times;
    char *d_str;

    /* bbs_t構造体の初期化 */
    bbs->method = (char *)r->method;
    //bbs->content_length = r->content_length;
    bbs->user_agent = (char *)ap_table_get(r->headers_in, "User-Agent");
    bbs->referer = (char *)ap_table_get(r->headers_in, "Referer");
    bbs->remote_addr = r->connection->remote_ip;
    bbs->remote_host = r->connection->remote_host;
    bbs->new_flag = 0;
    
    /* 時刻まわり */
    time(&t);
    times = localtime(&t);
    if((times->tm_mon + 1) < 10){
        d_str = "0";
    }
    else{
       d_str = "";
    }
    bbs->date = ap_psprintf(r->pool,
                            "%d/%s%d/%d %d:%d ID:???",
                            1900 + times->tm_year,
                            d_str,
                            times->tm_mon + 1,
                            times->tm_mday,
                            times->tm_hour,
                            times->tm_min
                            );
	bbs->date += 2;

#if DEBUG
    ap_rprintf(r,
                            "<b>bbs->date:</b>%d/%d/%d %d:%d ID:???<br>\n",
                            1900 + times->tm_year,
                            times->tm_mon + 1,
                            times->tm_mday,
                            times->tm_hour,
                            times->tm_min
                            );
#endif

    param = get_request_body(r);
    
    bbs->from = (char *)ap_table_get(param, "FROM");
    bbs->mail = (char *)ap_table_get(param, "mail");
    bbs->message = (char *)ap_table_get(param, "MESSAGE");
    bbs->subject = (char *)ap_table_get(param, "subject");
    bbs->bbs = (char *)ap_table_get(param, "bbs");
    bbs->key = (char *)ap_table_get(param, "key");
    
    /* FROMフィールドが空の場合はNONAMEを代入 */
    if(strlen(bbs->from) == 0){
        bbs->from = ap_pstrdup(r->pool, bbs->noname);
    }
    
    /* mailフィールドがNULLの場合は空文を入れる */
    if(bbs->mail == NULL){
        bbs->mail = "";
    }

	/* mailフィールドがNULLの場合は空文を入れる */
    if(bbs->subject == NULL){
        bbs->subject = "";
    }

    /* サニタイジングは丸投げ */
    bbs_html_escape(r->pool, bbs);

    return TRUE;
}

int post_dat(bbs_t *bbs, request_rec *r)
{
    FILE *fp;
    int lines = 0;
    int size = 0;
    char *buffer;
    char *dat_file;
    char *path;
    const char *mode;

    /* ファイル用バッファに動的メモリ確保 */
    buffer = ap_pcalloc(r->pool,BBS_BUFFER_SIZE);
    
    /* testファイルの存在するディレクトリまでのパスを生成 */
    r->filename[safe_strlen(r->filename) - 5] = '\0';
    path = ap_pstrdup(r->pool, r->filename);

    /* datファイルへのパスを生成 */
    dat_file = ap_psprintf(r->pool,"%s/%s/dat/%s.dat", path, bbs->bbs, bbs->key);

#if DEBUG
    ap_rprintf(r,"<b>post_dat:</b>filename=%s<br>\n", r->filename);
    ap_rprintf(r,"<b>post_dat:</b>path=%s<br>\n", path);
    ap_rprintf(r,"<b>post_dat:</b>dat_file=%s<br>\n", dat_file);
#endif

    /* 新規書き込みチェックにdatファイルをrモードでオープン */
    if((fp = ap_pfopen(r->pool, dat_file, "r")) == NULL){
        bbs->new_flag = 1;
    }
    else{
            /* 一行ずつ読み出して行数とサイズを調べる(効率悪いんだがなぁ。。) */
            while(fgets(buffer,BBS_BUFFER_SIZE,fp) != NULL){
                size += safe_strlen(buffer);
                lines++;
            }
        ap_pfclose(r->pool, fp);
    }

    /* レス追加の場合はスレッドの状態を判定 */
    if((bbs->new_flag == 0) && (lines > 1000)){
        error_html(r, RES_OVER);
        return -1;
    }
    if((bbs->new_flag == 0) && (size > 524288)){
        error_html(r, THREAD_SIZE_OVER);
        return -1;
    }

    /* ファイルを開く時のモードを決定 */
    if(bbs->new_flag == 1){
        mode = "w";
    }
    else{
        mode = "a";
    }

#if DEBUG
	ap_rprintf(r, "<b>dat_open_mode:</b>%s<br>\n", mode);
#endif

    if((fp = ap_pfopen(r->pool, dat_file, mode)) == NULL){
        error_html(r, DAT_OPEN_FAILED);
        return -1;
    }
        fprintf(fp,
                "%s<>%s<>%s<>%s<>%s\n",
                bbs->from,
                bbs->mail,
                bbs->date,
                bbs->message,
                bbs->subject
            );
    ap_pfclose(r->pool, fp);

#if DEBUG
    ap_rprintf(r, "<b>new_flag:</b>%d<br>",bbs->new_flag);
    ap_rprintf(r,
                "<b>submit_data:</b>%s<>%s<>%s<>%s<>%s<br>\n",
                bbs->from,
                bbs->mail,
                bbs->date,
                bbs->message,
                bbs->subject
            );
#endif

    return OK;
}

int post_subject(bbs_t *bbs, request_rec *r)
{

    FILE *fp;
    char *buffer;
    char *subject_file;
    char *data[1002];
    char *key;
    int subject_position = 0;
    int value_num = 0;
    int lines = 0;
    int size = 0;
    int sep_num = 0;
    char *res[3];
    char *key_target;
    char *sub_target;
    char *new_data;
    int res_num = 0;
    char *new_line;
    char *sub_buffer;
    char *new_subject;
    int i = 0;
    int j = 0;
    char *path;
    subject_t *sub;
    
    /* バッファに動的メモリ確保 */
    buffer = ap_pcalloc(r->pool, BBS_BUFFER_SIZE);
    sub_target = ap_pcalloc(r->pool, BBS_BUFFER_SIZE);
    sub_buffer = ap_pcalloc(r->pool, 3);

    /* 掲示板ディレクトリへのパス */
    path = ap_pstrdup(r->pool, r->filename);

    
    /* 投稿スレのdatファイル名 */
    key_target = ap_psprintf(r->pool, "%s.dat", bbs->key);

    /* subject.txtへのパス */
    subject_file = ap_psprintf(r->pool, "%s/%s/subject.txt", path, bbs->bbs);

#if DEBUG
    ap_rprintf(r,"<b>path:</b>%s<br>\n",path);
    ap_rprintf(r,"<b>key_target:</b>%s<br>\n",key_target);
    ap_rprintf(r,"<b>subject_file:</b>%s<br><br>\n",subject_file);
#endif

    /* subject.txtをオープン */
    if((fp = ap_pfopen(r->pool, subject_file, "r")) == NULL){
        error_html(r, SUBJECT_OPEN_FAILED);
        return FALSE;
    }
    else{
        while(fgets(buffer,BBS_BUFFER_SIZE,fp) != NULL){
            if(lines > 1001){
                ap_pfclose(r->pool, fp);
                error_html(r, SUBJECT_OVER);
                return FALSE;
            }
            if(buffer != NULL){
                data[lines] = ap_pstrdup(r->pool, buffer);
            }
            else{
                ap_pfclose(r->pool, fp);
                error_html(r, SUBJECT_BUFFER_NONE);
                return FALSE;
            }

            sub = ap_psubtoken(r->pool, buffer);
            sub->title[safe_strlen(sub->title) - 2] = '\0';

            if(!strcmp(key_target,sub->dat)){
                subject_position = lines;
                sub_target = ap_pstrdup(r->pool, sub->title);
                /* まとめて新レス分の1を足す */
                res_num = get_res_num(r, sub_target) + 1; 
            }

#if DEBUG
    ap_rprintf(r,"<b>sep_num:</b>%d<br>\n",sep_num);
    ap_rprintf(r,"<b>res_num:</b>%d<br>\n",res_num);
    ap_rprintf(r,"<b>sub->dat:</b>%s<br>\n",sub->dat);
    ap_rprintf(r,"<b>sub->title:</b>%s<br>\n",sub->title);
    ap_rprintf(r,"<b>subject_position:</b>%d<br><br>\n",subject_position);
    ap_rprintf(r, "<b>sub_target:</b>%s<br>\n", sub_target);
    ap_rputs("----------------------------------------------<br>",r);
#endif

            size = safe_strlen(buffer);
            lines++;

            if(lines > THREAD_MAX){
                error_html(r, SUBJECT_OVER);
                return FALSE;
            }
            if(size > 512){
                error_html(r, THREAD_SIZE_OVER);
                return FALSE;
            }
        }
        ap_pfclose(r->pool, fp);
    }
    
    /* 前のレス数表示はバイバイ (ちょっとキモイ処理だが) */
    for(i=0;i<safe_strlen(sub_target);i++){
        sub_buffer[0] = sub_target[i];
        sub_buffer[1] = '\0';
        if(!strcmp(sub_buffer,"(")){
            sub_target[i] = '\0';
        }
    }

    if((fp = ap_pfopen(r->pool, subject_file, "w")) == NULL){
        error_html(r, SUBJECT_OPEN_FAILED);
        return FALSE;
    }

    if((!strcmp(bbs->mail,"sage")) && (bbs->new_flag == 0)){
        /* sageモードでファイル書き込み */
        data[subject_position] = ap_psprintf(r->pool, "%s<>%s(%d)\n", key_target, sub_target, res_num);
        for(i=0;i<lines;i++){
            fputs(data[i],fp);
        }
    }

    if((strcmp(bbs->mail,"sage")) && (bbs->new_flag == 0)){
        /* ageモードでふぁいる書き込み */
        new_data = ap_psprintf(r->pool, "%s<>%s(%d)\n", key_target, sub_target, res_num);
        fputs(new_data,fp);
        for(i=0;i<lines;i++){
            if(i != subject_position){
                fputs(data[i],fp);
            }
        }
    }

    if(bbs->new_flag == 1){
        sub_target = bbs->subject;
        /* ageモードでふぁいる書き込み */
        new_data = ap_psprintf(r->pool, "%s<>%s(%d)\n", key_target, sub_target, res_num);
        fputs(new_data,fp);
        for(i=0;i<lines;i++){
                fputs(data[i],fp);
        }
    }

    ap_pfclose(r->pool, fp);
    return TRUE;
}


int post_back(bbs_t *bbs, request_rec *r)
{
    ap_rprintf(r,
                "<html><head>"
                "<title>書きこみました。</title>"
                "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">"
               // "<META content=5;URL=../%s/index.html http-equiv=refresh>"
                "</head>"
                "<body>書きこみが終わりました。<br><br>"
                "画面を切り替えるまでしばらくお待ち下さい。<br><br>"
                "</body>"
                "</html>"
                ,bbs->bbs
                );
                return TRUE;
}

