/******************************************************************************
 * mod_uploader / UploadItemCreator.cpp
 ******************************************************************************
 * Copyright (C) 2005 Tetsuya Kimata <kimata@acapulco.dyndns.org>
 *
 * All rights reserved.
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any
 * damages arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any
 * purpose, including commercial applications, and to alter it and
 * redistribute it freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must
 *    not claim that you wrote the original software. If you use this
 *    software in a product, an acknowledgment in the product
 *    documentation would be appreciated but is not bcktuired.
 *
 * 2. Altered source versions must be plainly marked as such, and must
 *    not be misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source
 *    distribution.
 *
 * $Id: UploadItemCreator.cpp 682 2005-09-15 06:41:06Z svn $
 *****************************************************************************/

#include "UploadItemCreator.h"
#include "CharCodeConverter.h"
#include "Misc.h"


/******************************************************************************
 * public メソッド
 *****************************************************************************/
UploadItem::header *UploadItemCreator::create_header(apr_pool_t *pool,
                                                     UploadParser::query_map *qmap,
                                                     const char **tmp_path)
{
    UploadItem::header *data;

    validate_query(pool, qmap);

    APR_PCALLOC(data, UploadItem::header *, pool, sizeof(UploadItem::header));

    strncpy(data->identifier, PACKAGE_NAME, sizeof(PACKAGE_NAME));
    strncpy(data->version, PACKAGE_VERSION, sizeof(PACKAGE_VERSION));

    data->time = apr_time_now();
    strncpy(data->comment, (*qmap)[UploadItem::COMMENT_PARAM].text.c_str(),
            UploadItem::MAX_COMMENT_LENGTH-1);

    strncpy(data->download_pass, (*qmap)[UploadItem::DOWNLOAD_PASS_PARAM].text.c_str(),
            UploadItem::MAX_DOWNLOAD_PASS_LENGTH-1);

    strncpy(data->remove_pass, (*qmap)[UploadItem::REMOVE_PASS_PARAM].text.c_str(),
            UploadItem::MAX_REMOVE_PASS_LENGTH-1);

    set_file_data(pool, data, (*qmap)[UploadItem::FILE_PARAM].file, qmap);

    *tmp_path = (*qmap)[UploadItem::FILE_PARAM].file.tmp_path.c_str();

    return data;
}


/******************************************************************************
 * private メソッド
 *****************************************************************************/
void UploadItemCreator::validate_query(apr_pool_t *pool,
                                       UploadParser::query_map *qmap)
{
    const unsigned char *code_pat;
    const char *file_name;

    // MEMO:
    // - ファイルサイズが 0 の場合は，エラーを出す．
    // - コメントやパスワードについては，中身が空でもエラーを出さない．
    // - ファイル名，MIME タイプ，コメントは HTML エスケープする．

    if (qmap->count(UploadItem::CODE_PAT_PARAM) != 1) {
        throw "文字コード判定パターンの指定が不正です．";
    }

    code_pat = reinterpret_cast<const unsigned char *>((*qmap)[UploadItem::CODE_PAT_PARAM].text.c_str());

    if (qmap->count(UploadItem::FILE_PARAM) != 1) {
        throw "ファイルの指定が不正です．";
    }
    if (((*qmap)[UploadItem::FILE_PARAM].type != UploadParser::FILE) ||
               ((*qmap)[UploadItem::FILE_PARAM].file.size == 0)) {
        throw "ファイルが空です．";
    }

    convert_code(pool, (*qmap)[UploadItem::FILE_PARAM].text, code_pat);
    escape_html(pool, (*qmap)[UploadItem::FILE_PARAM].text);

    file_name = (*qmap)[UploadItem::FILE_PARAM].file.name.c_str();

    if (strlen(file_name) >= UploadItem::MAX_FILE_NAME_LENGTH) {
        throw "ファイル名が長すぎます．";
    }
    do {
        if ((*file_name == '"') || (*file_name == '\'') ||
            (*file_name == '\r') || (*file_name == '\n') ||
            (*file_name == '\\')) {
            throw "ファイル名が不正です．";
        }
    } while (*(++file_name) != '\0');


    if ((*qmap)[UploadItem::FILE_PARAM].file.mime.length() >= UploadItem::MAX_FILE_MIME_LENGTH) {
        throw "ファイルの MIME Type が長すぎます．";
    }
    escape_html(pool, (*qmap)[UploadItem::FILE_PARAM].file.mime);

    if (qmap->count(UploadItem::COMMENT_PARAM) != 1) {
        throw "コメントの指定が不正です．";
    }

    convert_code(pool, (*qmap)[UploadItem::COMMENT_PARAM].text, code_pat);
    escape_html(pool, (*qmap)[UploadItem::COMMENT_PARAM].text);

    if (((*qmap)[UploadItem::COMMENT_PARAM].type != UploadParser::TEXT) ||
               ((*qmap)[UploadItem::COMMENT_PARAM].text.length() >= UploadItem::MAX_COMMENT_LENGTH)) {
        throw "コメントが長すぎます．";
    }

    if (qmap->count(UploadItem::DOWNLOAD_PASS_PARAM) != 1) {
        throw "ダウンロードパスワードの指定が不正です．";
    } else if (((*qmap)[UploadItem::DOWNLOAD_PASS_PARAM].type != UploadParser::TEXT) ||
               ((*qmap)[UploadItem::DOWNLOAD_PASS_PARAM].text.length() >= UploadItem::MAX_DOWNLOAD_PASS_LENGTH)) {
        throw "ダウンロードパスワードが長すぎます．";
    }

    if (qmap->count(UploadItem::REMOVE_PASS_PARAM) != 1) {
        throw "削除パスワードの指定が不正です．";
    } else if (((*qmap)[UploadItem::REMOVE_PASS_PARAM].type != UploadParser::TEXT) ||
               ((*qmap)[UploadItem::REMOVE_PASS_PARAM].text.length() >= UploadItem::MAX_REMOVE_PASS_LENGTH)) {
        throw "削除パスワードが長すぎます．";
    }
}

void UploadItemCreator::escape_html(apr_pool_t *pool, string &str)
{
    str.assign(ap_escape_html(pool, str.c_str()));
}

void UploadItemCreator::convert_code(apr_pool_t *pool, string &str,
                                     const unsigned char *code_pat)
{
    str.assign(CharCodeConverter::convert(pool, str.c_str(), code_pat));
}

void UploadItemCreator::set_file_data(apr_pool_t *pool,
                                      UploadItem::header *data,
                                      UploadParser::file_content& file,
                                      UploadParser::query_map *qmap)
{
    strncpy(data->file_name, file.name.c_str(), UploadItem::MAX_FILE_NAME_LENGTH-1);
    strncpy(data->file_mime, file.mime.c_str(), UploadItem::MAX_FILE_MIME_LENGTH-1);
    strncpy(data->file_digest, file.digest.c_str(), UploadItem::MAX_FILE_DIGEST_LENGTH-1);

    data->file_size = file.size;
}

// Local Variables:
// mode: c++
// buffer-file-coding-system: euc-japan-dos
// End:
