/* 
 * $Id: URLTool_Nano.cpp,v 1.1 2005/10/19 14:05:44 ozawa Exp $
 *
 * Copyright 2005- ONGS Inc. All rights reserved.
 * 
 * author: Masanori OZAWA (ozawa@ongs.co.jp)
 * version: $Revision: 1.1 $
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY ONGS INC ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL ONGS INC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of the ONGS Inc.
 * 
 */

#include "xdtp.h"
#include "URLTool_Nano.h"
#include "URI.h"

#include "sys/types.h"
#include "sys/stat.h"

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
namespace XDTP {
static void ftp_list_callback_for_stat
    (void * userData, 
     const char * filename, 
     const char * attrib, 
     const char * owner, 
     const char * group, 
     unsigned long size, 
     int links, 
     int year, 
     const char * month, 
     int day, 
     int hour, 
     int minute)
{
    FILE_INFO *info = (FILE_INFO*)userData;
    
    info->size = size;
    /*
     * 日付情報については FTPサーバによって応答がまちまちであるため、
     * 現時点では実装しない。将来的には一般的な応答に準拠した方法で
     * 日付情報を処理したい。 by ozawa 2005/10/18
     */
    //info.atime = 0;
    //info.mtime = 0;
}

};

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
using namespace XDTP;

URLTool_Nano::URLTool_Nano()
{
    static bool init = false;
    
    if (!init) {
        xmlNanoHTTPInit();
        xmlNanoFTPInit();
        init = true;
    }
    
    m_ctx = NULL;
    m_type = URL_UNKNOWN;
}

URLTool_Nano::~URLTool_Nano()
{
    closeResource(true);
}

bool URLTool_Nano::openResource(const Glib::ustring& url, URLTYPE type)
{
    char* contentType = NULL;
    
    closeResource();
    
    switch (type) {
    case URL_HTTP:
        m_ctx = xmlNanoHTTPOpen(url.c_str(), &contentType);
        free(contentType);
        break;
    case URL_FTP:
        m_ctx = xmlNanoFTPOpen(url.c_str());
        break;
    case URL_FILE:
        {
            RefPtr<URI> uri = URI::parse(url);
            m_ctx = (FILE*)fopen(uri->getPath().c_str(), "r");
        }
        break;
    default:
        return false;
    }
    
    if (m_ctx) {
        m_type = type;
    }
    
    return (m_ctx ? true : false);
}

void URLTool_Nano::closeResource(bool force)
{
    if (m_ctx) {
        switch (m_type) {
        case URL_HTTP:
            xmlNanoHTTPClose(m_ctx);
            break;
        case URL_FTP:
            xmlNanoFTPClose(m_ctx);
            break;
        case URL_FILE:
            fclose((FILE*)m_ctx);
            break;
        default:
            if (force) {
                fprintf(stderr, "%s: URLTool: Unknown resource type. "
                                "Unable to close the resource.", APP_NAME);
            }
            else {
                THROW("Unknown resource type. Unable to close the resource.");
            }
            break;
        }
        
        m_ctx = NULL;
        m_type = URL_UNKNOWN;
    }
}

int URLTool_Nano::readResource(char* buf, int len)
{
    int result = -1;
    
    if (m_ctx) {
        switch (m_type) {
        case URL_HTTP:
            result = xmlNanoHTTPRead(m_ctx, buf, len);
            break;
        case URL_FTP:
            result = xmlNanoFTPRead(m_ctx, buf, len);
            break;
        case URL_FILE:
            result = fread(buf, 1, len, (FILE*)m_ctx);
            break;
        default:
            THROW("unable to read resource. (type = unknown)");
        }
    }
    
    return result;
}

bool URLTool_Nano::statResourceCore(const Glib::ustring& url, FILE_INFO& info)
{
    bool result = false;
    URLTYPE type = URLTool::parseURLType(url);
    
    switch (type) {
    case URL_HTTP:
        if (openResource(url, type)) {
            info.size = xmlNanoHTTPContentLength(m_ctx);
            info.atime = 0;
            info.mtime = 0;
            closeResource();
            result = (-1 == info.size ? false : true);
        }
        break;
    case URL_FTP:
        if (openResource(url, type)) {
            info.size = -1;
            info.atime = 0;
            info.mtime = 0;
            if (!xmlNanoFTPList(m_ctx, ftp_list_callback_for_stat, &info, NULL)) {
                result = true;
            }
            closeResource();
        }
        break;
    case URL_FILE:
        {
            struct stat sb;
            RefPtr<URI> uri = URI::parse(url);
            
            if (!stat(uri->getPath().c_str(), &sb)) {
                info.size = sb.st_size;
                info.atime = sb.st_atime;
                info.mtime = sb.st_mtime;
                result = true;
            }
        }
        break;
    default:
        break;
    }
    
    return result;
}


syntax highlighted by Code2HTML, v. 0.9.1