///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
//
// See accompanying file COPYING.TXT file for licensing details.
//
///////////////////////////////////////////////////////////////////////////////
#define CPPCMS_SOURCE
#include <cppcms/http_file.h>
#include <cppcms/urandom.h>
#include <cppcms/cppcms_error.h>
#include <booster/nowide/cstdio.h>
#include <booster/nowide/fstream.h>
#include <stdlib.h>
#include <iostream>
#include "http_file_buffer.h"
namespace cppcms {
namespace http {
struct file::impl_data {
impl::file_buffer fb;
std::istream in;
std::ostream out;
impl_data() :
in(&fb),
out(&fb)
{
}
};
std::string file::name() const
{
return name_;
}
std::string file::mime() const
{
return mime_;
}
bool file::has_mime() const
{
return !mime_.empty();
}
std::string file::filename() const
{
return filename_;
}
long long file::size()
{
return d->fb.size();
}
std::istream &file::data()
{
return d->in;
}
std::ostream &file::write_data()
{
return d->out;
}
void file::make_permanent()
{
file_temporary_ = 0;
}
void file::output_file(std::string const &name,bool is_temporary)
{
d->fb.name(name);
if(!is_temporary) {
if(d->fb.to_file()!=0) {
throw cppcms_error("Failed to write to file " + name);
}
}
file_specified_ = 1;
file_temporary_ = is_temporary ? 1:0;
}
void file::copy_stream(std::istream &in,std::ostream &out)
{
out << in.rdbuf();
}
void file::save_to(std::string const &filename)
{
d->in.clear();
d->in.seekg(0);
d->fb.pubsync();
if(d->fb.in_memory()) {
save_by_copy(filename,d->in);
return;
}
#ifdef CPPCMS_WIN32
d->fb.close();
/// we can't move opened file on windows as it would be locked
if(booster::nowide::rename(d->fb.name().c_str(),filename.c_str())!=0) {
booster::nowide::ifstream tmp(d->fb.name().c_str(),std::ios_base::binary | std::ios_base::in);
if(!tmp) {
throw cppcms_error("Failed to reopen file");
}
save_by_copy(filename,tmp);
tmp.close();
booster::nowide::remove(d->fb.name().c_str());
}
#else
if(booster::nowide::rename(d->fb.name().c_str(),filename.c_str())!=0) {
save_by_copy(filename,d->in);
booster::nowide::remove(d->fb.name().c_str());
}
d->fb.close();
#endif
removed_ = 1;
}
void file::save_by_copy(std::string const &file_name,std::istream &in)
{
booster::nowide::ofstream f(file_name.c_str(),std::ios_base::binary | std::ios_base::out);
if(!f) {
throw cppcms_error("Failed to save open file:"+file_name);
}
copy_stream(in,f);
f << std::flush;
f.close();
}
void file::set_memory_limit(size_t size)
{
d->fb.set_limit(size);
}
void file::set_temporary_directory(std::string const &dir)
{
d->fb.temp_dir(dir);
}
file::file() :
removed_(0),
file_specified_(0),
file_temporary_(1),
d(new impl_data())
{
}
file::~file()
{
if(!d->fb.in_memory() && !removed_) {
d->fb.close();
if(file_temporary_ && !d->fb.name().empty()) {
booster::nowide::remove(d->fb.name().c_str());
}
}
}
void file::filename(std::string const &v)
{
filename_=v;
}
void file::name(std::string const &v)
{
name_=v;
}
void file::mime(std::string const &v)
{
mime_=v;
}
} // http
} // cppcms