/******************************************************************************
 * mod_uploader / UploadItem.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: UploadItem.cpp 684 2005-09-15 07:12:00Z svn $
 *****************************************************************************/

#include "UploadItem.h"
#include "Auxiliary.h"
#include "Misc.h"

#include "apr_strings.h"
#include "apr_time.h"

#include <string>

#ifdef DEBUG
#include <iostream>
#include <iomanip>
#endif

const char UploadItem::FILE_PARAM[]             = "file";
const char UploadItem::COMMENT_PARAM[]          = "comment";
const char UploadItem::REMOVE_PASS_PARAM[]      = "remove_pass";
const char UploadItem::DOWNLOAD_PASS_PARAM[]    = "download_pass";
const char UploadItem::CODE_PAT_PARAM[]         = "code_pat";

const char UploadItem::FILE_NAME_KEY[]          = "name";
const char UploadItem::FILE_PATH_KEY[]          = "path";
const char UploadItem::COMMENT_KEY[]            = "comment";
const char UploadItem::REMOVE_PASS_KEY[]        = "remove_pass";
const char UploadItem::DOWNLOAD_PASS_KEY[]      = "download_pass";
const char UploadItem::FILE_SIZE_KEY[]          = "size";
const char UploadItem::FILE_MIME_KEY[]          = "mime";
const char UploadItem::FILE_DIGEST_KEY[]        = "digest";
const char UploadItem::TIME_KEY[]               = "time";

const char UploadItem::TIME_FORMAT[]            = UITEM_TIME_FORMAT;
const apr_size_t UploadItem::MAX_TIME_LENGTH    = UITEM_MAX_TIME_LENGTH;
const apr_size_t UploadItem::TIME_ZONE_OFFSET   = UITEM_TIME_ZONE_OFFSET;

#ifdef DEBUG_TEMPLATE
#define ap_escape_html(pool, str) str
#endif


/******************************************************************************
 * public メソッド
 *****************************************************************************/
UploadItem::UploadItem(apr_pool_t *pool, const char *file_path, header *header)
    : pool_(pool)
{
    set_data(file_path, header);
}

UploadItem::UploadItem(apr_pool_t *pool)
    : pool_(pool)
{

}

UploadItem::header *UploadItem::set_data(const char *file_path, header *new_header)
{
    header *old_header = header_;

    if ((new_header == NULL) || (file_path == NULL)) {
        throw "アイテムの情報が不正です．";
    }

    file_path_ = file_path;
    header_ = new_header;

    return old_header;
}

UploadItem::header *UploadItem::get_header() const
{
    return header_;
}

const char *UploadItem::get_file_path() const
{
    return file_path_;
}

const char *UploadItem::get_file_name() const
{
    return header_->file_name;
}

const char *UploadItem::get_file_digest() const
{
    return header_->file_digest;
}

const char *UploadItem::get_comment() const
{
    return header_->comment;
}

const char *UploadItem::get_remove_pass() const
{
    return header_->remove_pass;
}

const char *UploadItem::get_download_pass() const
{
    return header_->download_pass;
}

const char *UploadItem::get_file_size() const
{
    return size_str(pool_, header_->file_size);
}

const char *UploadItem::get_file_mime() const
{
    return header_->file_mime;
}

const char *UploadItem::get_time() const
{
    apr_time_exp_t time_exp;
    char *time_str;
    apr_size_t size;

    APR_PALLOC(time_str, char *, pool_, sizeof(char)*MAX_TIME_LENGTH);

    if (time_str == NULL) {
        throw "時間表記のためのメモリ確保に失敗しました．";
    }
    apr_time_exp_tz(&time_exp, header_->time, TIME_ZONE_OFFSET);
    apr_strftime(time_str, &size, MAX_TIME_LENGTH, TIME_FORMAT, &time_exp);

    return time_str;
}

#ifdef DEBUG
void UploadItem::dump_header(header *header)
{
    cerr << setw(70) << setfill('-') << '-' << endl;
    cerr << "identifier: "      << header->identifier       << endl;
    cerr << "version: "         << header->version          << endl;
    cerr << "time: "            << header->time             << endl;
    cerr << "file_size: "       << static_cast<unsigned int>(header->file_size) << endl;
    cerr << "file_name: "       << header->file_name        << endl;
    cerr << "file_mime: "       << header->file_mime        << endl;
    cerr << "file_digest: "     << header->file_digest      << endl;
    cerr << "remove_pass: "     << header->remove_pass      << endl;
    cerr << "download_pass: "   << header->download_pass    << endl;
    cerr << "comment: "         << header->comment          << endl;
    cerr << setw(70) << setfill('-') << '-' << endl;
}
#endif


/******************************************************************************
 * テスト
 *****************************************************************************/
#ifdef DEBUG_UploadItem
#include "apr_general.h"

#include <iomanip>

void usage(const char *prog_name)
{
    cerr << "Usage: " << prog_name << " <INPUT>" << endl;
}

void print_offset(const char *name, unsigned int offset, unsigned int expected) {
    cout << "    ";
    cout.width(27);
    cout.setf(ios::left, ios::adjustfield);
    cout << name << ": \033[1;37m";
    cout.width(3);
    cout.setf(ios::right, ios::adjustfield);
    cout << offset << "\033[0m" << endl;

    if (offset != expected) {
        cerr << "\033[1;31mError: expected " << expected << ", but actual " << offset << "\033[0m" << endl;
        exit(EXIT_FAILURE);
    }
}

int main(int argc, const char * const *argv)
{
    apr_pool_t *pool;
    unsigned int offset;

    apr_app_initialize(&argc, &argv, NULL);
    apr_pool_create(&pool, NULL);

    cout << "\033[1;36m* \033[0;36mCheack the struct size\033[0m" << endl;
    cout << "    sizeof(UploadItem::header) : \033[1;37m";
    cout.width(3);
    cout.setf(ios::right, ios::adjustfield);
    cout << sizeof(UploadItem::header) << "\033[0m" << endl;
    cout << "    ITEM_HEADER_SIZE           : \033[1;37m";
    cout.width(3);
    cout.setf(ios::right, ios::adjustfield);
    cout << UploadItem::ITEM_HEADER_SIZE << "\033[0m" << endl;
    if (sizeof(UploadItem::header) != UploadItem::ITEM_HEADER_SIZE) {
        cerr << "\033[1;31mError: sizeof(UploadItem::header) != ITEM_HEADER_SIZE\033[0m" << endl;
        exit(EXIT_FAILURE);
    }
    cout << endl;

    cout << "\033[1;36m* \033[0;36mCheck the member offset\033[0m" << endl;

    offset = 0;

    print_offset("identifier",
                 offsetof(UploadItem::header, identifier),
                 offset);
    offset += UploadItem::MAX_IDENTIFIER_LENGTH;

    print_offset("version",
                 offsetof(UploadItem::header, version),
                 offset);
    offset += UploadItem::MAX_VERSION_LENGTH;

    print_offset("file_size",
                 offsetof(UploadItem::header, file_size),
                 offset);
    offset += 16;

    print_offset("time",
                 offsetof(UploadItem::header, time),
                 offset);
    offset += 16;

    print_offset("file_mime",
                 offsetof(UploadItem::header, file_mime),
                 offset);
    offset += UploadItem::MAX_FILE_MIME_LENGTH;

    print_offset("file_name",
                 offsetof(UploadItem::header, file_name),
                 offset);
    offset += UploadItem::MAX_FILE_NAME_LENGTH;

    print_offset("file_digest",
                 offsetof(UploadItem::header, file_digest),
                 offset);
    offset += UploadItem::MAX_FILE_DIGEST_LENGTH;

    print_offset("remove_pass",
                 offsetof(UploadItem::header, remove_pass),
                 offset);
    offset += UploadItem::MAX_REMOVE_PASS_LENGTH;

    print_offset("download_pass",
                 offsetof(UploadItem::header, download_pass),
                 offset);
    offset += UploadItem::MAX_DOWNLOAD_PASS_LENGTH;

    print_offset("comment",
                 offsetof(UploadItem::header, comment),
                 offset);

    cout << endl;
    cout << "\033[1;34mOK. Passed All Checks!\033[0m" << endl;

    apr_terminate();

    return EXIT_SUCCESS;
}
#endif

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